Change file path of domain socket
[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 <aul/aul.h>
40
41 #include <ipc/ipc_message.h>
42
43 #include <FBaseRtMutex.h>
44 #include <FBaseSysLog.h>
45 #include <FBase_StringConverter.h>
46 #include <FBaseRt_EventDispatcher.h>
47
48 #include "IIpcServerEventListener.h"
49 #include "IpcServer.h"
50
51 using namespace std;
52 using namespace IPC;
53
54 using namespace Tizen::Base;
55 using namespace Tizen::Base::Runtime;
56 using namespace Tizen::App;
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("/var/run/osp/");
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         // SMACK (Add a * label to socket)
209         if(smack_fsetlabel(serverSocket, "@", SMACK_LABEL_IPOUT) != 0)
210         {
211                 SysTryCatch(NID_IO, errno == EOPNOTSUPP, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] SMACK labeling failed");
212                 SysLog(NID_IO, "Kernel doesn't have Smack.");
213         }
214
215         if(smack_fsetlabel(serverSocket, "*", SMACK_LABEL_IPIN) != 0)
216         {
217                 SysTryCatch(NID_IO, errno == EOPNOTSUPP, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] SMACK labeling failed");
218                 SysLog(NID_IO, "Kernel doesn't have Smack.");
219         }
220
221         bzero(&serverAddress, sizeof(serverAddress));
222         serverAddress.sun_family = AF_UNIX;
223         strncpy(serverAddress.sun_path, socketName.c_str(), socketNameLength);
224         serverLen = sizeof(serverAddress);
225
226         ret = bind(serverSocket, (const struct sockaddr*) &serverAddress, serverLen);
227         SysTryCatch(NID_IO, ret != -1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to bind a socket(%d, %s): %s", serverSocket,
228                            socketName.c_str(), strerror(errno));
229
230         ret = chmod(socketName.c_str(), 0666);
231         SysTryCatch(NID_IO, ret == 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to change permission of a socket(%d, %s): %s", serverSocket,
232                            socketName.c_str(), strerror(errno));
233
234         ret = listen(serverSocket, 128);
235         SysTryCatch(NID_IO, ret == 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to listen a socket(%d, %s): %s", serverSocket,
236                            socketName.c_str(), strerror(errno));
237
238         pGIOChannel = g_io_channel_unix_new(serverSocket);
239         SysTryCatch(NID_IO, pGIOChannel != null, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Not enough memory.");
240
241         // socket will be closed when pGIOChannel is deleted.
242         g_io_channel_set_close_on_unref(pGIOChannel, TRUE);
243         serverSocket = -1;
244
245         pGSource = g_io_create_watch(pGIOChannel, (GIOCondition) (G_IO_IN | G_IO_ERR | G_IO_NVAL | G_IO_HUP));
246         SysTryCatch(NID_IO, pGSource != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
247                            "[E_OUT_OF_MEMORY] Failed to create watch for socket.");
248
249         // channel will be delete when pGSource is deleted.
250         g_io_channel_unref(pGIOChannel);
251         pGIOChannel = null;
252
253         g_source_set_callback(pGSource, (GSourceFunc) OnConnectionRequest, this, NULL);
254         g_source_attach(pGSource, __pHandlerGMainContext);
255
256         if (__runOnCallerThread)
257         {
258                 __pListener->OnIpcServerStarted(*this);
259         }
260         else
261         {
262                 ret = pthread_create(&__handlerThread, null, &ThreadProc, (void*) this);
263                 SysTryCatch(NID_IO, ret == 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to an IPC thread");
264         }
265
266         __pConnectGSource = pGSource;
267
268         return E_SUCCESS;
269
270 CATCH:
271         if (pGIOChannel != null)
272         {
273                 g_io_channel_unref(pGIOChannel);
274         }
275
276         if (serverSocket != -1)
277         {
278                 close(serverSocket);
279         }
280
281         if (runOnCallerThread && __pHandlerGMainContext)
282         {
283                 g_main_context_unref(__pHandlerGMainContext);
284                 __pHandlerGMainContext = null;
285         }
286
287         return r;
288 }
289
290 struct HelloMessage
291 {
292         int reverse;  // if the connection is for reverse message
293 };
294
295 gboolean
296 IpcServer::OnConnectionRequest(GIOChannel* source, GIOCondition condition, gpointer data)
297 {
298         IpcServer* pIpcServer = (IpcServer*) data;
299         GError* pGError = null;
300         HelloMessage helloMessage;
301         _ClientInfo* pClientInfo = null;
302         _ChannelInfo* pChannelInfo = null;
303         GSource* pGSource = null;
304         GIOChannel* pChannel = null;
305         ssize_t readBytes = 0;
306         int ret = 0;
307
308         int server = -1;
309         int client = -1;
310         struct sockaddr_un clientAddress;
311         socklen_t clientLen = sizeof(clientAddress);
312
313         struct ucred cr;
314         socklen_t ucredLen = sizeof(cr);
315
316         SysAssertf(pIpcServer != null, "Not yet constructed. Construct() should be called before use.\n");
317         SysAssertf(pIpcServer->__pListener != null, "Listener is null.\n");
318
319         server = g_io_channel_unix_get_fd(source);
320
321         client = accept(server, (struct sockaddr*) &clientAddress, &clientLen);
322         SysTryCatch(NID_IO, client != -1, , E_SYSTEM, "[E_SYSTEM] Accept failed.");
323
324         readBytes = read(client, &helloMessage, sizeof(helloMessage));
325         SysTryCatch(NID_IO, readBytes >= 0, , E_SYSTEM, "[E_SYSTEM] Failed to receive hello message (%d, %s).",
326                         errno, strerror(errno));
327
328         pChannel = g_io_channel_unix_new(client);
329         SysTryCatch(NID_IO, pChannel != null, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Not enough memory.");
330
331         g_io_channel_set_encoding(pChannel, NULL, &pGError);
332         g_io_channel_set_flags(pChannel, G_IO_FLAG_NONBLOCK, &pGError);
333
334         g_io_channel_set_close_on_unref(pChannel, TRUE);
335
336         ret = getsockopt(client, SOL_SOCKET, SO_PEERCRED, &cr, &ucredLen);
337         SysTryCatch(NID_IO, ret >= 0, , E_SYSTEM, "[E_SYSTEM] Failed to get peercred information: %s", strerror(errno));
338
339         client = -1;
340
341         pClientInfo = pIpcServer->__clients[cr.pid];
342         if (pClientInfo == null) // first connection request from this client
343         {
344                 pClientInfo = new (std::nothrow) _ClientInfo;
345                 SysTryCatch(NID_IO, pClientInfo != null, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Not enough memory.");
346
347                 pClientInfo->pIpcServer = pIpcServer;
348                 pClientInfo->clientId = cr.pid;
349
350                 char buffer[256] = {0, };
351                 ret = aul_app_get_appid_bypid(cr.pid, buffer, sizeof(buffer));
352                 SysTryCatch(NID_IO, ret == AUL_R_OK, delete pClientInfo, E_SYSTEM, "[E_SYSTEM] Failed to get the application ID of pid: %d", ret);
353
354                 pClientInfo->appId = buffer;
355
356                 pClientInfo->pReverseChannel = null;
357
358                 pIpcServer->__clients[cr.pid] = pClientInfo;
359                 pIpcServer->__pCurrentClientInfo = pClientInfo;
360                 pIpcServer->__pListener->OnIpcClientConnected(*pIpcServer, cr.pid);
361                 pIpcServer->__pCurrentClientInfo = null;
362         }
363
364         if (helloMessage.reverse != 0)
365         {
366                 pClientInfo->pReverseChannel = pChannel;
367         }
368         else
369         {
370                 pChannelInfo = new (std::nothrow) _ChannelInfo;
371                 SysTryCatch(NID_IO, pChannelInfo != null, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Not enough memory.");
372
373                 pGSource = g_io_create_watch(pChannel, (GIOCondition) (G_IO_IN | G_IO_ERR | G_IO_NVAL | G_IO_HUP));
374                 g_source_set_callback(pGSource, (GSourceFunc) OnReadMessage, pChannelInfo, NULL);
375                 g_source_attach(pGSource, pIpcServer->__pHandlerGMainContext);
376
377                 pChannelInfo->pClientInfo = pClientInfo;
378                 pChannelInfo->pGIOChannel = pChannel;
379                 pChannelInfo->pGSource = pGSource;
380
381                 pClientInfo->channels.push_back(pChannelInfo);
382         }
383
384         return true;
385
386 CATCH:
387         if (pChannel != null)
388         {
389                 g_io_channel_unref(pChannel);
390         }
391
392         if (client != -1)
393         {
394                 close(client);
395         }
396
397         return true;
398 }
399
400 int
401 IpcServer::GetClientId(void) const
402 {
403         if (__pCurrentClientInfo)
404         {
405                 return __pCurrentClientInfo->clientId;
406         }
407
408         return -1;
409 }
410
411 AppId
412 IpcServer::GetClientApplicationId(void) const
413 {
414         static String nullString;
415
416         if (__pCurrentClientInfo)
417         {
418                 return __pCurrentClientInfo->appId;
419         }
420
421         return nullString;
422 }
423
424 gboolean
425 IpcServer::HandleReceivedMessage(GIOChannel* source, GIOCondition condition, gpointer data)
426 {
427         GError* pGError = NULL;
428         GIOStatus status;
429         IPC::Message* pMessage = NULL;
430         _ChannelInfo* pChannelInfo = (_ChannelInfo*) data;
431         _ClientInfo* pClientInfo = pChannelInfo->pClientInfo;
432
433         if (condition & G_IO_HUP)
434         {
435                 SysLog(NID_IO, "Connection closed");
436                 int clientId = pClientInfo->clientId;
437
438                 g_io_channel_shutdown(source, FALSE, &pGError);
439
440                 for (unsigned int i = 0; i < pClientInfo->channels.size(); i++)
441                 {
442                         if (pChannelInfo == pClientInfo->channels[i])
443                         {
444                                 pClientInfo->channels.erase(pClientInfo->channels.begin() + i);
445
446                                 // Do not destroy a source in a dispatch callback
447                                 // because main loop will do it if the callback return FALSE.
448                                 pChannelInfo->destroySource = false;
449                                 delete pChannelInfo;
450
451                                 break;
452                         }
453                 }
454
455                 if (pClientInfo->channels.size() == 0)
456                 {
457                         SysLog(NID_IO, "All connections of client(%d) are closed. delete client info", clientId);
458
459                         __pListener->OnIpcClientDisconnected(*this, clientId);
460
461                         __clients[clientId] = null;
462
463                         delete pClientInfo;
464                 }
465
466                 return FALSE;
467         }
468         else if (condition & G_IO_IN)
469         {
470                 gsize readSize = 0;
471                 const char* pStart = NULL;
472                 const char* pEnd = NULL;
473                 const char* pEndOfMessage = NULL;
474
475                 while (true)
476                 {
477                         pGError = null;
478                         status = g_io_channel_read_chars(source, (char*) __messageBuffer, __MAX_MESSAGE_BUFFER_SIZE, &readSize, &pGError);
479                         if (status != G_IO_STATUS_NORMAL)
480                         {
481                                 if (status == G_IO_STATUS_EOF || status == G_IO_STATUS_ERROR)
482                                 {
483                                         if (status == G_IO_STATUS_EOF)
484                                         {
485                                                 SysLog(NID_IO, "G_IO_STATUS_EOF, the connection is closed.");
486                                         }
487                                         else
488                                         {
489                                                 SysLog(NID_IO, "G_IO_STATUS_ERROR, the connection is closed. ");
490                                         }
491
492                                         pGError = null;
493                                         g_io_channel_shutdown(source, FALSE, &pGError);
494
495                                         int clientId = pClientInfo->clientId;
496
497                                         for (unsigned int i = 0; i < pClientInfo->channels.size(); i++)
498                                         {
499                                                 if (pChannelInfo == pClientInfo->channels[i])
500                                                 {
501                                                         pClientInfo->channels.erase(pClientInfo->channels.begin() + i);
502
503                                                         pChannelInfo->destroySource = false;
504                                                         delete pChannelInfo;
505                                                         break;
506                                                 }
507                                         }
508
509                                         if (pClientInfo->channels.size() == 0)
510                                         {
511                                                 SysLog(NID_IO, "All connections of client(%d) are closed normally by the client.", clientId);
512
513                                                 if (__pListener)
514                                                 {
515                                                         __pListener->OnIpcClientDisconnected(*this, clientId);
516                                                 }
517
518                                                 __clients[clientId] = null;
519
520                                                 delete pClientInfo;
521                                         }
522
523                                         return FALSE;
524                                 }
525                         }
526
527                         if (readSize == 0)
528                         {
529                                 break;
530                         }
531
532                         if (__pending.empty())
533                         {
534                                 pStart = __messageBuffer;
535                                 pEnd = pStart + readSize;
536                         }
537                         else
538                         {
539                                 __pending.append(__messageBuffer, readSize);
540                                 pStart = __pending.data();
541                                 pEnd = pStart + __pending.size();
542                         }
543
544                         while (true)
545                         {
546                                 pEndOfMessage = IPC::Message::FindNext(pStart, pEnd);
547                                 if (pEndOfMessage == NULL)
548                                 {
549                                         __pending.assign(pStart, pEnd - pStart);
550                                         break;
551                                 }
552
553                                 pMessage = new (std::nothrow) IPC::Message(pStart, pEndOfMessage - pStart);
554                                 SysTryReturn(NID_IO, pMessage != null, FALSE, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
555
556                                 __pCurrentChannel = source;
557
558                                 if (__pListener)
559                                 {
560                                         __pListener->OnIpcRequestReceived(*this, *pMessage);
561                                 }
562
563                                 delete pMessage;
564
565                                 __pCurrentChannel = NULL;
566
567                                 pStart = pEndOfMessage;
568                         }
569                 }
570         }
571         else
572         {
573                 // empty statement
574         }
575
576         return TRUE;
577 }
578
579 gboolean
580 IpcServer::OnReadMessage(GIOChannel* source, GIOCondition condition, gpointer data)
581 {
582         gboolean ret = FALSE;
583         _ChannelInfo* pChannelInfo = (_ChannelInfo*) data;
584         _ClientInfo* pClientInfo = pChannelInfo->pClientInfo;
585         IpcServer* pIpcServer = (IpcServer*) pClientInfo->pIpcServer;
586
587         pIpcServer->__pCurrentClientInfo = pClientInfo;
588         ret = pIpcServer->HandleReceivedMessage(source, condition, data);
589         pIpcServer->__pCurrentClientInfo = null;
590
591         return ret;
592 }
593
594 void*
595 IpcServer::ThreadProc(void* pParam)
596 {
597         IpcServer* pIpcServer = (IpcServer*) pParam;
598         if (pIpcServer != NULL)
599         {
600                 pIpcServer->Run(NULL);
601         }
602
603         return NULL;
604 }
605
606 void
607 IpcServer::Run(void* pParam)
608 {
609         result r = E_SUCCESS;
610
611         if (__pListener == null)
612         {
613                 return;
614         }
615
616         __pEventDispatcher = new (std::nothrow) _EventDispatcher;
617         SysTryReturnVoidResult(NID_IO, __pEventDispatcher != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
618
619         r = __pEventDispatcher->Construct(__pHandlerGMainContext);
620         if (IsFailed(r))
621         {
622                 delete __pEventDispatcher;
623                 __pEventDispatcher = null;
624         }
625
626         __pListener->OnIpcServerStarted(*this);
627
628         g_main_loop_run(__pHandlerGMainLoop);
629
630         __pListener->OnIpcServerStopped(*this);
631 }
632
633 result
634 IpcServer::Start(void)
635 {
636         return E_SUCCESS;
637 }
638
639 String
640 IpcServer::GetName(void) const
641 {
642         return __name;
643 }
644
645 result
646 IpcServer::Stop(void)
647 {
648         result r = E_SUCCESS;
649         int ret = 0;
650
651         SysTryReturnResult(NID_IO, __pListener != null, E_SYSTEM, "Listener is null.");
652
653         if (!__runOnCallerThread)
654         {
655                 pthread_t self = pthread_self();
656
657                 if (__pHandlerGMainLoop)
658                 {
659                         g_main_loop_quit(__pHandlerGMainLoop);
660                 }
661
662                 if (__handlerThread != self)
663                 {
664                         ret = pthread_join(__handlerThread, null);
665                         SysTryLog(NID_IO, ret == 0, "Join an IPC thread returns an error");
666                 }
667         }
668         else
669         {
670                 __pListener->OnIpcServerStopped(*this);
671         }
672
673         return r;
674 }
675
676 bool
677 IpcServer::Send(IPC::Message* msg)
678 {
679         gsize remain = 0;
680         gsize written = 0;
681         char* pData = NULL;
682         GError* pGError = NULL;
683
684
685         pData = (char*) msg->data();
686         remain = msg->size();
687
688         if (msg->is_reply())
689         {
690                 while (remain > 0)
691                 {
692                         pGError = NULL;
693                         g_io_channel_write_chars(__pCurrentChannel, (char*) pData, remain, &written, &pGError);
694
695                         remain -= written;
696                         pData += written;
697                 }
698
699                 g_io_channel_flush(__pCurrentChannel, &pGError);
700         }
701         else
702         {
703                 // empty statement;
704         }
705
706         delete msg;
707
708         return true;
709 }
710
711 result
712 IpcServer::SendResponse(int client, IPC::Message* pMessage)
713 {
714         result r = E_SUCCESS;
715         gsize remain = 0;
716         gsize written = 0;
717         char* pData = null;
718         GError* pGError = null;
719         _ClientInfo* pClientInfo = null;
720         int ret = 0;
721
722         SysTryReturn(NID_IO, client >= 0 && pMessage != null, false, E_INVALID_ARG,
723                                 "[E_INVALID_ARG] pMessage(0x%x) is null or clinet(%d) < 0", pMessage,
724                                 client);
725         SysTryCatch(NID_IO, !pMessage->is_sync(), r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Can't send sync. messagee.");
726
727         pClientInfo = __clients[client];
728         SysTryCatch(NID_IO, pClientInfo != null, r = E_INVALID_ARG, E_INVALID_ARG,
729                            "[E_INVALID_ARG] client(%d) has not been registered.",
730                            client);
731
732         pData = (char*) pMessage->data();
733         remain = pMessage->size();
734
735         while (remain > 0)
736         {
737                 pGError = NULL;
738                 ret = g_io_channel_write_chars(pClientInfo->pReverseChannel, (char*) pData, remain, &written, &pGError);
739                 if (ret != G_IO_STATUS_NORMAL)
740                 {
741                         SysLog(NID_IO, "Failed to send a response: %d", ret);
742                         SysTryCatch(NID_IO, ret != G_IO_STATUS_ERROR, , E_SYSTEM, "[E_SYSTEM] Error occurred during writing message to socket.");
743                 }
744
745                 remain -= written;
746                 pData += written;
747         }
748
749         g_io_channel_flush(pClientInfo->pReverseChannel, &pGError);
750
751         delete pMessage;
752
753         return E_SUCCESS;
754
755 CATCH:
756         delete pMessage;
757         return r;
758 }
759
760 result
761 IpcServer::SendResponse(int client, const IPC::Message& message)
762 {
763         result r = E_SUCCESS;
764         gsize remain = 0;
765         gsize written = 0;
766         char* pData = null;
767         GError* pGError = null;
768         _ClientInfo* pClientInfo = null;
769         int ret = 0;
770
771         SysTryReturn(NID_IO, client >= 0, false, E_INVALID_ARG, "[E_INVALID_ARG] clinet(%d) < 0", client);
772         SysTryCatch(NID_IO, !message.is_sync(), r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Can't send sync. messagee.");
773
774         pClientInfo = __clients[client];
775         SysTryCatch(NID_IO, pClientInfo != null, r = E_INVALID_ARG, E_INVALID_ARG,
776                            "[E_INVALID_ARG] client(%d) has not been registered.",
777                            client);
778
779         pData = (char*) message.data();
780         remain = message.size();
781
782         while (remain > 0)
783         {
784                 pGError = NULL;
785                 ret = g_io_channel_write_chars(pClientInfo->pReverseChannel, (char*) pData, remain, &written, &pGError);
786                 if (ret != G_IO_STATUS_NORMAL)
787                 {
788                         SysLog(NID_IO, "Failed to send a response: %d", ret);
789                         SysTryCatch(NID_IO, ret != G_IO_STATUS_ERROR, , E_SYSTEM, "[E_SYSTEM] Error occurred during writing message to socket.");
790                 }
791
792                 remain -= written;
793                 pData += written;
794         }
795
796         g_io_channel_flush(pClientInfo->pReverseChannel, &pGError);
797
798         return E_SUCCESS;
799
800 CATCH:
801         return r;
802 }