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