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