Prevent fix
[platform/framework/native/appfw.git] / src / server / io / FIo_IpcServer.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file  FIo_IpcServer.cpp
20  * @brief This is the implementation file for the _IpcServer class.
21  *
22  */
23
24 #include <cstdio>
25 #include <cstdlib>
26 #include <cstring>
27 #include <cerrno>
28 #include <iostream>
29 #include <new>
30
31 #include <unistd.h>
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <sys/stat.h>
35 #include <sys/un.h>
36
37 #include <ipc/ipc_message.h>
38
39 #include <app_manager.h>
40
41 #include <FBaseRtMutex.h>
42 #include <FBaseSysLog.h>
43 #include <FBase_StringConverter.h>
44 #include <FBaseRt_EventDispatcher.h>
45
46 #include "FIo_IIpcServerEventListener.h"
47 #include "FIo_IpcServer.h"
48
49 using namespace std;
50 using namespace IPC;
51 using namespace Tizen::Base;
52 using namespace Tizen::Base::Runtime;
53 using namespace Tizen::App;
54
55 namespace Tizen { namespace Io
56 {
57
58 _IpcServer::_ChannelInfo::_ChannelInfo(void)
59         : pClientInfo(null)
60         , pGIOChannel(null)
61         , pGSource(null)
62         , destroySource(true)
63 {
64
65 }
66
67 _IpcServer::_ChannelInfo::~_ChannelInfo(void)
68 {
69         if (pGIOChannel != null)
70         {
71                 g_io_channel_unref(pGIOChannel);
72         }
73
74         if (pGSource != null)
75         {
76                 if (destroySource)
77                 {
78                         g_source_destroy(pGSource);
79                 }
80
81                 g_source_unref(pGSource);
82         }
83 }
84
85 _IpcServer::_ClientInfo::_ClientInfo(void)
86         : clientId(-1)
87         , pIpcServer(null)
88         , pReverseChannel(null)
89 {
90
91 }
92
93 _IpcServer::_ClientInfo::~_ClientInfo(void)
94 {
95         if (pReverseChannel != null)
96         {
97                 g_io_channel_unref(pReverseChannel);
98         }
99
100         channels.clear();
101 }
102
103 _IpcServer::_IpcServer(void)
104         : __runOnCallerThread(false)
105         , __pEventDispatcher(null)
106         , __pListener(null)
107         , __handlerThread(0)
108         , __pHandlerGMainContext(null)
109         , __pHandlerGMainLoop(null)
110         , __pConnectGSource(null)
111         , __pCurrentChannel(null)
112         , __pCurrentClientInfo(null)
113 {
114         __messageBuffer[0] = '\0';
115 }
116
117
118 _IpcServer::~_IpcServer(void)
119 {
120         if (__pConnectGSource != null)
121         {
122                 g_source_destroy(__pConnectGSource);
123                 g_source_unref(__pConnectGSource);
124                 __pConnectGSource = null;
125         }
126
127         if (!__runOnCallerThread)
128         {
129                 if (__pEventDispatcher)
130                 {
131                         delete __pEventDispatcher;
132                         __pEventDispatcher = null;
133                 }
134
135                 if (__pHandlerGMainLoop)
136                 {
137                         g_main_loop_unref(__pHandlerGMainLoop);
138                         __pHandlerGMainLoop = null;
139                 }
140
141                 if (__pHandlerGMainContext)
142                 {
143                         g_main_context_unref(__pHandlerGMainContext);
144                         __pHandlerGMainContext = null;
145                 }
146         }
147
148         // clean-up clients
149         __clients.clear();
150 }
151
152 result
153 _IpcServer::Construct(const String& name, const _IIpcServerEventListener& listener, bool runOnCallerThread)
154 {
155         result r = E_SUCCESS;
156
157         GIOChannel* pGIOChannel = null;
158         GSource* pGSource = null;
159
160         struct sockaddr_un serverAddress;
161         int serverSocket = -1;
162         int serverLen = 0;
163         int ret = 0;
164         std::string socketName;
165         char* pName = null;
166         size_t socketNameLength = 0;
167
168         __name = name;
169         __pListener = const_cast <_IIpcServerEventListener*>(&listener);
170         __runOnCallerThread = runOnCallerThread;
171
172         pName = _StringConverter::CopyToCharArrayN(name);
173         SysTryReturnResult(NID_IO, pName != null, E_OUT_OF_MEMORY, "Not enough memory");
174
175         socketName.append("/tmp/");
176         socketName.append(pName);
177
178         delete[] pName;
179
180         socketNameLength = socketName.size() + 1;
181         SysTryReturnResult(NID_IO, socketNameLength < 108, E_INVALID_ARG, "Server name is too long");
182
183         if (!__runOnCallerThread)
184         {
185                 __pHandlerGMainContext = g_main_context_new();
186                 __pHandlerGMainLoop = g_main_loop_new(__pHandlerGMainContext, FALSE);
187
188         }
189         else
190         {
191                 __pHandlerGMainContext = g_main_context_get_thread_default();
192                 if (__pHandlerGMainContext == null) // is global?
193                 {
194                         __pHandlerGMainContext = g_main_context_default();
195                         if (__pHandlerGMainContext == null)
196                         {
197                                 return E_SYSTEM;
198                         }
199                 }
200         }
201
202         ret = unlink(socketName.c_str());
203         SysTryLog(NID_IO, ret == 0, "Unlink a socket has failed.. but it is not a problem.");
204
205         serverSocket = socket(AF_UNIX, SOCK_STREAM, 0);
206         SysTryReturnResult(NID_IO, serverSocket != -1, E_SYSTEM, "Failed to create a socket.");
207
208         bzero(&serverAddress, sizeof(serverAddress));
209         serverAddress.sun_family = AF_UNIX;
210         strncpy(serverAddress.sun_path, socketName.c_str(), socketNameLength);
211         serverLen = sizeof(serverAddress);
212
213         ret = bind(serverSocket, (const struct sockaddr*) &serverAddress, serverLen);
214         SysTryCatch(NID_IO, ret != -1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to bind a socket(%d, %s): %s", serverSocket,
215                            socketName.c_str(), strerror(errno));
216
217         ret = chmod(socketName.c_str(), 0666);
218         SysTryCatch(NID_IO, ret == 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to change permission of a socket(%d, %s): %s", serverSocket,
219                            socketName.c_str(), strerror(errno));
220
221         ret = listen(serverSocket, 15);
222         SysTryCatch(NID_IO, ret == 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to listen the socket(%d, %s): %s", serverSocket,
223                            socketName.c_str(), strerror(errno));
224
225         pGIOChannel = g_io_channel_unix_new(serverSocket);
226         SysTryCatch(NID_IO, pGIOChannel != null, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Not enough memory.");
227
228         // socket will be closed when pGIOChannel is deleted.
229         g_io_channel_set_close_on_unref(pGIOChannel, TRUE);
230         serverSocket = -1;
231
232         pGSource = g_io_create_watch(pGIOChannel, (GIOCondition) (G_IO_IN | G_IO_ERR | G_IO_NVAL | G_IO_HUP));
233         SysTryCatch(NID_IO, pGSource != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
234                            "[E_OUT_OF_MEMORY] Failed to create watch for socket.");
235
236         // channel will be delete when pGSource is deleted.
237         g_io_channel_unref(pGIOChannel);
238         pGIOChannel = null;
239
240         g_source_set_callback(pGSource, (GSourceFunc) OnConnectionRequest, this, NULL);
241         g_source_attach(pGSource, __pHandlerGMainContext);
242
243         if (__runOnCallerThread)
244         {
245                 __pListener->OnIpcServerStarted(*this);
246         }
247         else
248         {
249                 ret = pthread_create(&__handlerThread, null, &ThreadProc, (void*) this);
250                 SysTryCatch(NID_IO, ret == 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to an IPC thread");
251         }
252
253         __pConnectGSource = pGSource;
254
255         return E_SUCCESS;
256
257 CATCH:
258         __name.Clear();
259
260         if (pGIOChannel != null)
261         {
262                 g_io_channel_unref(pGIOChannel);
263         }
264
265         if (serverSocket != -1)
266         {
267                 close(serverSocket);
268         }
269
270         if (runOnCallerThread && __pHandlerGMainContext)
271         {
272                 g_main_context_unref(__pHandlerGMainContext);
273                 __pHandlerGMainContext = null;
274         }
275
276         return r;
277 }
278
279 struct HelloMessage
280 {
281         int pid;
282         bool reverse;  // true if the connection is for reverse message
283 };
284
285 gboolean
286 _IpcServer::OnConnectionRequest(GIOChannel* source, GIOCondition condition, gpointer data)
287 {
288         _IpcServer* pIpcServer = (_IpcServer*) data;
289         GError* pGError = null;
290         HelloMessage helloMessage;
291         _ClientInfo* pClientInfo = null;
292         _ChannelInfo* pChannelInfo = null;
293         GSource* pGSource = null;
294         GIOChannel* pChannel = null;
295
296         int server = -1;
297         int client = -1;
298         struct sockaddr_un clientAddress;
299         socklen_t clientLen = sizeof(clientAddress);
300
301         SysAssertf(pIpcServer != null, "Not yet constructed. Construct() should be called before use.\n");
302         SysAssertf(pIpcServer->__pListener != null, "Listener is null.\n");
303
304         server = g_io_channel_unix_get_fd(source);
305
306         client = accept(server, (struct sockaddr*) &clientAddress, &clientLen);
307         SysTryCatch(NID_IO, client != -1, ,E_SYSTEM, "[E_SYSTEM] Accept failed.");
308
309         read(client, &helloMessage, sizeof(helloMessage));
310
311         pChannel = g_io_channel_unix_new(client);
312         SysTryCatch(NID_IO, pChannel != null, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Not enough memory.");
313
314         g_io_channel_set_encoding(pChannel, NULL, &pGError);
315         g_io_channel_set_flags(pChannel, G_IO_FLAG_NONBLOCK, &pGError);
316
317         g_io_channel_set_close_on_unref(pChannel, TRUE);
318         client = -1;
319
320         pClientInfo = pIpcServer->__clients[helloMessage.pid];
321         if (pClientInfo == null) // first connection request from this client
322         {
323                 pClientInfo = new (std::nothrow) _ClientInfo;
324                 SysTryCatch(NID_IO, pClientInfo != null, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Not enough memory.");
325
326                 pClientInfo->pIpcServer = pIpcServer;
327                 pClientInfo->clientId = helloMessage.pid;
328
329                 char* pAppId = NULL;
330                 int ret = app_manager_get_app_id(helloMessage.pid, &pAppId);
331                 SysTryCatch(NID_IO, ret >= 0, delete pClientInfo, E_SYSTEM, "[E_SYSTEM] Failed to get_app_id: %d", ret);
332
333                 pClientInfo->appId = pAppId;
334                 free(pAppId);
335
336                 pClientInfo->pReverseChannel = null;
337
338                 pIpcServer->__clients[helloMessage.pid] = pClientInfo;
339                 pIpcServer->__pCurrentClientInfo = pClientInfo;
340                 pIpcServer->__pListener->OnIpcClientConnected(*pIpcServer, helloMessage.pid);
341                 pIpcServer->__pCurrentClientInfo = null;
342         }
343
344         if (helloMessage.reverse)
345         {
346                 pClientInfo->pReverseChannel = pChannel;
347         }
348         else
349         {
350                 pChannelInfo = new (std::nothrow) _ChannelInfo;
351                 SysTryCatch(NID_IO, pChannelInfo != null, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Not enough memory.");
352
353                 pGSource = g_io_create_watch(pChannel, (GIOCondition) (G_IO_IN | G_IO_ERR | G_IO_NVAL | G_IO_HUP));
354                 g_source_set_callback(pGSource, (GSourceFunc) OnReadMessage, pChannelInfo, NULL);
355                 g_source_attach(pGSource, pIpcServer->__pHandlerGMainContext);
356
357                 pChannelInfo->pClientInfo = pClientInfo;
358                 pChannelInfo->pGIOChannel = pChannel;
359                 pChannelInfo->pGSource = pGSource;
360
361                 pClientInfo->channels.push_back(pChannelInfo);
362         }
363
364         return true;
365
366 CATCH:
367         if (pChannel != null)
368         {
369                 g_io_channel_unref(pChannel);
370         }
371
372         if (client != -1)
373         {
374                 close(client);
375         }
376
377         return true;
378 }
379
380 int
381 _IpcServer::GetClientId(void) const
382 {
383         if (__pCurrentClientInfo)
384         {
385                 return __pCurrentClientInfo->clientId;
386         }
387
388         return -1;
389 }
390
391 int
392 _IpcServer::GetClientProcessId(void) const
393 {
394         if (__pCurrentClientInfo)
395         {
396                 return __pCurrentClientInfo->clientId;
397         }
398
399         return -1;
400 }
401
402 String
403 _IpcServer::GetClientAppId(void) const
404 {
405         static String nullString;
406
407         if (__pCurrentClientInfo)
408         {
409                 String pkgId;
410                 __pCurrentClientInfo->appId.SubString(0, 10, pkgId);
411
412                 return pkgId;
413         }
414
415         return nullString;
416 }
417
418 String
419 _IpcServer::GetClientAppExecutableName(void) const
420 {
421         static String nullString;
422
423         if (__pCurrentClientInfo)
424         {
425                 String appName;
426                 __pCurrentClientInfo->appId.SubString(11, appName);
427
428                 return appName;
429         }
430
431         return nullString;
432 }
433
434 PackageId
435 _IpcServer::GetClientPackageId(void) const
436 {
437         static String nullString;
438
439         if (__pCurrentClientInfo)
440         {
441                 String pkgId;
442                 __pCurrentClientInfo->appId.SubString(0, 10, pkgId);
443
444                 return pkgId;
445         }
446
447         return nullString;
448 }
449
450 AppId
451 _IpcServer::GetClientApplicationId(void) const
452 {
453         static String nullString;
454
455         if (__pCurrentClientInfo)
456         {
457                 return __pCurrentClientInfo->appId;
458         }
459
460         return nullString;
461 }
462
463 gboolean
464 _IpcServer::HandleReceivedMessage(GIOChannel* source, GIOCondition condition, gpointer data)
465 {
466         GError* pGError = NULL;
467         GIOStatus status;
468         IPC::Message* pMessage = NULL;
469         _ChannelInfo* pChannelInfo = (_ChannelInfo*) data;
470         _ClientInfo* pClientInfo = pChannelInfo->pClientInfo;
471
472         if (condition & G_IO_HUP)
473         {
474                 SysLog(NID_IO, "G_IO_HUP, the connection is closed.");
475
476                 int clientId = pClientInfo->clientId;
477
478                 g_io_channel_shutdown(source, FALSE, &pGError);
479
480                 for (unsigned int i = 0; i < pClientInfo->channels.size(); i++)
481                 {
482                         if (pChannelInfo == pClientInfo->channels[i])
483                         {
484                                 pClientInfo->channels.erase(pClientInfo->channels.begin() + i);
485
486                                 // Do not destroy a source in a dispatch callback
487                                 // because main loop will do it if the callback return FALSE.
488                                 pChannelInfo->destroySource = false;
489                                 delete pChannelInfo;
490
491                                 break;
492                         }
493                 }
494
495                 if (pClientInfo->channels.size() == 0)
496                 {
497                         SysLog(NID_IO, "All connections of client(%d) are closed. delete client info", clientId);
498
499                         __pListener->OnIpcClientDisconnected(*this, clientId);
500
501                         __clients[clientId] = null;
502
503                         delete pClientInfo;
504                 }
505
506                 return FALSE;
507         }
508         else if (condition & G_IO_IN)
509         {
510                 gsize readSize = 0;
511                 const char* pStart = NULL;
512                 const char* pEnd = NULL;
513                 const char* pEndOfMessage = NULL;
514
515                 while (true)
516                 {
517                         pGError = null;
518                         status = g_io_channel_read_chars(source, (char*) __messageBuffer, __MAX_MESSAGE_BUFFER_SIZE, &readSize, &pGError);
519                         if (status != G_IO_STATUS_NORMAL)
520                         {
521                                 if (status == G_IO_STATUS_EOF || status == G_IO_STATUS_ERROR)
522                                 {
523                                         if (status == G_IO_STATUS_EOF)
524                                         {
525                                                 SysLog(NID_IO, "G_IO_STATUS_EOF, the connection is closed.");
526                                         }
527                                         else
528                                         {
529                                                 SysLog(NID_IO, "G_IO_STATUS_ERROR, the connection is closed. ");
530                                         }
531
532                                         pGError = null;
533                                         g_io_channel_shutdown(source, FALSE, &pGError);
534
535                                         int clientId = pClientInfo->clientId;
536
537                                         for (unsigned int i = 0; i < pClientInfo->channels.size(); i++)
538                                         {
539                                                 if (pChannelInfo == pClientInfo->channels[i])
540                                                 {
541                                                         pClientInfo->channels.erase(pClientInfo->channels.begin() + i);
542
543                                                         pChannelInfo->destroySource = false;
544                                                         delete pChannelInfo;
545                                                         break;
546                                                 }
547                                         }
548
549                                         if (pClientInfo->channels.size() == 0)
550                                         {
551                                                 SysLog(NID_IO, "All connections of client(%d) are closed normally by the client.", clientId);
552
553                                                 if (__pListener)
554                                                 {
555                                                         __pListener->OnIpcClientDisconnected(*this, clientId);
556                                                 }
557
558                                                 __clients[clientId] = null;
559
560                                                 delete pClientInfo;
561                                         }
562
563                                         return FALSE;
564                                 }
565                         }
566
567                         if (readSize == 0)
568                         {
569                                 break;
570                         }
571
572                         if (__pending.empty())
573                         {
574                                 pStart = __messageBuffer;
575                                 pEnd = pStart + readSize;
576                         }
577                         else
578                         {
579                                 __pending.append(__messageBuffer, readSize);
580                                 pStart = __pending.data();
581                                 pEnd = pStart + __pending.size();
582                         }
583
584                         while (true)
585                         {
586                                 pEndOfMessage = IPC::Message::FindNext(pStart, pEnd);
587                                 if (pEndOfMessage == NULL)
588                                 {
589                                         __pending.assign(pStart, pEnd - pStart);
590                                         break;
591                                 }
592
593                                 pMessage = new (std::nothrow) IPC::Message(pStart, pEndOfMessage - pStart);
594                                 SysTryReturn(NID_IO, pMessage != null, FALSE, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
595
596                                 __pCurrentChannel = source;
597
598                                 if (__pListener)
599                                 {
600                                         __pListener->OnIpcRequestReceived(*this, *pMessage);
601                                 }
602
603                                 delete pMessage;
604
605                                 __pCurrentChannel = NULL;
606
607                                 pStart = pEndOfMessage;
608                         }
609                 }
610         }
611         else
612         {
613                 // empty statement
614         }
615
616         return TRUE;
617 }
618
619 gboolean
620 _IpcServer::OnReadMessage(GIOChannel* source, GIOCondition condition, gpointer data)
621 {
622         gboolean ret = FALSE;
623         _ChannelInfo* pChannelInfo = (_ChannelInfo*) data;
624         _ClientInfo* pClientInfo = pChannelInfo->pClientInfo;
625         _IpcServer* pIpcServer = (_IpcServer*) pClientInfo->pIpcServer;
626
627         pIpcServer->__pCurrentClientInfo = pClientInfo;
628         ret = pIpcServer->HandleReceivedMessage(source, condition, data);
629         pIpcServer->__pCurrentClientInfo = null;
630
631         return ret;
632 }
633
634 void*
635 _IpcServer::ThreadProc(void* pParam)
636 {
637         _IpcServer* pIpcServer = (_IpcServer*) pParam;
638         if (pIpcServer != NULL)
639         {
640                 pIpcServer->Run(NULL);
641         }
642
643         return NULL;
644 }
645
646 void
647 _IpcServer::Run(void* pParam)
648 {
649         result r = E_SUCCESS;
650
651         if (__pListener == null)
652         {
653                 return;
654         }
655
656         __pEventDispatcher = new (std::nothrow) _EventDispatcher;
657         SysTryReturnVoidResult(NID_IO, __pEventDispatcher != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
658
659         r = __pEventDispatcher->Construct(__pHandlerGMainContext);
660         if (IsFailed(r))
661         {
662                 delete __pEventDispatcher;
663                 __pEventDispatcher = null;
664         }
665
666         __pListener->OnIpcServerStarted(*this);
667
668         g_main_loop_run(__pHandlerGMainLoop);
669
670         __pListener->OnIpcServerStopped(*this);
671 }
672
673 result
674 _IpcServer::Start(void)
675 {
676         return E_SUCCESS;
677 }
678
679 String
680 _IpcServer::GetName(void) const
681 {
682         return __name;
683 }
684
685 result
686 _IpcServer::Stop(void)
687 {
688         result r = E_SUCCESS;
689         int ret = 0;
690
691         SysTryReturnResult(NID_IO, __pListener != null, E_SYSTEM, "Listener is null.");
692
693         if (!__runOnCallerThread)
694         {
695                 pthread_t self = pthread_self();
696
697                 if (__pHandlerGMainLoop)
698                 {
699                         g_main_loop_quit(__pHandlerGMainLoop);
700                 }
701
702                 if (__handlerThread != self)
703                 {
704                         ret = pthread_join(__handlerThread, null);
705                         SysTryLog(NID_IO, ret == 0, "Join an IPC thread returns an error");
706                 }
707         }
708         else
709         {
710                 __pListener->OnIpcServerStopped(*this);
711         }
712
713         return r;
714 }
715
716 bool
717 _IpcServer::Send(IPC::Message* msg)
718 {
719         gsize remain = 0;
720         gsize written = 0;
721         char* pData = NULL;
722         GError* pGError = NULL;
723
724
725         pData = (char*) msg->data();
726         remain = msg->size();
727
728         if (msg->is_reply())
729         {
730                 while (remain > 0)
731                 {
732                         pGError = NULL;
733                         g_io_channel_write_chars(__pCurrentChannel, (char*) pData, remain, &written, &pGError);
734
735                         remain -= written;
736                         pData += written;
737                 }
738
739                 g_io_channel_flush(__pCurrentChannel, &pGError);
740         }
741         else
742         {
743                 // empty statement;
744         }
745
746         return true;
747 }
748
749 result
750 _IpcServer::SendResponse(int client, IPC::Message* pMessage)
751 {
752         result r = E_SUCCESS;
753         gsize remain = 0;
754         gsize written = 0;
755         char* pData = null;
756         GError* pGError = null;
757         _ClientInfo* pClientInfo = null;
758
759         SysTryReturn(NID_IO, client >= 0 && pMessage != null, false, E_INVALID_ARG,
760                                 "[E_INVALID_ARG] pMessage(0x%x) is null or clinet(%d) < 0", pMessage,
761                                 client);
762         SysTryCatch(NID_IO, !pMessage->is_sync(), r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Can't send sync. messagee.");
763
764         pClientInfo = __clients[client];
765         SysTryCatch(NID_IO, pClientInfo != null, r = E_INVALID_ARG, E_INVALID_ARG,
766                            "[E_INVALID_ARG] client(%d) has not been registered.",
767                            client);
768
769         pData = (char*) pMessage->data();
770         remain = pMessage->size();
771
772         while (remain > 0)
773         {
774                 pGError = NULL;
775                 g_io_channel_write_chars(pClientInfo->pReverseChannel, (char*) pData, remain, &written, &pGError);
776                 SysTryCatch(NID_IO, pGError == null, , E_SYSTEM, "[E_SYSTEM] Error occurred during writing message to socket.");
777
778                 remain -= written;
779                 pData += written;
780         }
781
782         g_io_channel_flush(pClientInfo->pReverseChannel, &pGError);
783
784         delete pMessage;
785
786         return E_SUCCESS;
787
788 CATCH:
789         delete pMessage;
790         return r;
791 }
792
793 result
794 _IpcServer::SendResponse(int client, const IPC::Message& message)
795 {
796         result r = E_SUCCESS;
797         gsize remain = 0;
798         gsize written = 0;
799         char* pData = null;
800         GError* pGError = null;
801         _ClientInfo* pClientInfo = null;
802
803         SysTryReturn(NID_IO, client >= 0, false, E_INVALID_ARG, "[E_INVALID_ARG] clinet(%d) < 0", client);
804         SysTryCatch(NID_IO, !message.is_sync(), r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Can't send sync. messagee.");
805
806         pClientInfo = __clients[client];
807         SysTryCatch(NID_IO, pClientInfo != null, r = E_INVALID_ARG, E_INVALID_ARG,
808                            "[E_INVALID_ARG] client(%d) has not been registered.",
809                            client);
810
811         pData = (char*) message.data();
812         remain = message.size();
813
814         while (remain > 0)
815         {
816                 pGError = NULL;
817                 g_io_channel_write_chars(pClientInfo->pReverseChannel, (char*) pData, remain, &written, &pGError);
818                 SysTryCatch(NID_IO, pGError == null, , E_SYSTEM, "[E_SYSTEM] Error occurred during writing message to socket.");
819
820                 remain -= written;
821                 pData += written;
822         }
823
824         g_io_channel_flush(pClientInfo->pReverseChannel, &pGError);
825
826         return E_SUCCESS;
827
828 CATCH:
829         return r;
830 }
831
832 } } // Tizen::Io