update the latest source
[platform/core/connectivity/smartcard-service.git] / common / IPCHelper.cpp
1 /*
2 * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
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 /* standard library header */
19 #include <stdio.h>
20 #include <unistd.h>
21 #include <string.h>
22 #include <sys/socket.h>
23 #ifdef USE_UNIX_DOMAIN
24 #include <sys/un.h>
25 #include <sys/stat.h>
26 #else /* USE_UNIX_DOMAIN */
27 #include <netinet/in.h>
28 #endif /* USE_UNIX_DOMAIN */
29 #include <fcntl.h>
30
31 /* SLP library header */
32
33 /* local header */
34 #include "Debug.h"
35 #include "IPCHelper.h"
36
37 #ifdef USE_UNIX_DOMAIN
38 #define OMAPI_SERVER_DOMAIN "/tmp/omapi-server-domain"
39 #endif /* USE_UNIX_DOMAIN */
40
41 static void setNonBlockSocket(int socket)
42 {
43         int flags;
44
45         flags = fcntl(socket, F_GETFL);
46
47         flags |= O_NONBLOCK;
48
49         if (fcntl(socket, F_SETFL, flags) < 0)
50         {
51                 /* SCARD_DEBUG_ERR("fcntl, executing nonblock error"); */
52         }
53 }
54
55 namespace smartcard_service_api
56 {
57         IPCHelper::IPCHelper()
58         {
59                 ipcSocket = -1;
60                 ioChannel = NULL;
61                 watchId = 0;
62                 memset(&ipcLock, 0, sizeof(ipcLock));
63                 dispatcher = NULL;
64         }
65
66         IPCHelper::~IPCHelper()
67         {
68         }
69
70         gboolean IPCHelper::channelCallbackFunc(GIOChannel* channel, GIOCondition condition, gpointer data)
71         {
72                 IPCHelper *helper = (IPCHelper *)data;
73                 gboolean result = FALSE;
74
75                 SCARD_DEBUG("channel [%p], condition [%d], data [%p]", channel, condition, data);
76
77                 if (helper == NULL)
78                 {
79                         SCARD_DEBUG_ERR("ipchelper is null");
80                         return result;
81                 }
82
83                 if ((G_IO_ERR & condition) || (G_IO_HUP & condition))
84                 {
85                         result = helper->handleIOErrorCondition(channel, condition);
86                 }
87                 else if (G_IO_NVAL & condition)
88                 {
89                         result = helper->handleInvalidSocketCondition(channel, condition);
90                 }
91                 else if (G_IO_IN & condition)
92                 {
93                         result = helper->handleIncomingCondition(channel, condition);
94                 }
95
96                 return result;
97         }
98
99         bool IPCHelper::createListenSocket()
100         {
101                 GIOCondition condition = (GIOCondition)(G_IO_ERR | G_IO_HUP | G_IO_IN);
102                 struct sockaddr_un saddrun_rv;
103
104                 if (ipcSocket >= 0)
105                         return true;
106
107                 memset(&saddrun_rv, 0, sizeof(struct sockaddr_un));
108
109                 unlink(OMAPI_SERVER_DOMAIN);
110
111                 ipcSocket = socket(AF_UNIX, SOCK_STREAM, 0);
112                 if (ipcSocket == -1)
113                 {
114                         SCARD_DEBUG_ERR("get socket is failed");
115                         return false;
116                 }
117
118                 ::setNonBlockSocket(ipcSocket);
119
120                 saddrun_rv.sun_family = AF_UNIX;
121                 strncpy(saddrun_rv.sun_path, OMAPI_SERVER_DOMAIN, sizeof(saddrun_rv.sun_path) - 1);
122
123                 if (bind(ipcSocket, (struct sockaddr *)&saddrun_rv, sizeof(saddrun_rv)) < 0)
124                 {
125                         SCARD_DEBUG_ERR("bind is failed \n");
126                         goto ERROR;
127                 }
128
129                 if (chmod(OMAPI_SERVER_DOMAIN, 0777) < 0)
130                 {
131                         SCARD_DEBUG_ERR("can not change permission of UNIX DOMAIN file");
132                         goto ERROR;
133                 }
134
135                 if (listen(ipcSocket, IPC_SERVER_MAX_CLIENT) < 0)
136                 {
137                         SCARD_DEBUG_ERR("listen is failed \n");
138                         goto ERROR;
139                 }
140
141                 if ((ioChannel = g_io_channel_unix_new(ipcSocket)) != NULL)
142                 {
143                         if ((watchId = g_io_add_watch(ioChannel, condition, &IPCHelper::channelCallbackFunc, this)) < 1)
144                         {
145                                 SCARD_DEBUG_ERR(" g_io_add_watch is failed \n");
146                                 goto ERROR;
147                         }
148                 }
149                 else
150                 {
151                         SCARD_DEBUG_ERR(" g_io_channel_unix_new is failed \n");
152                         goto ERROR;
153                 }
154
155 #ifdef SECURITY_SERVER
156                 gid = security_server_get_gid(NET_NFC_MANAGER_OBJECT);
157                 if(gid == 0)
158                 {
159                         SCARD_DEBUG("get gid from security server is failed. this object is not allowed by security server");
160                         goto ERROR;
161                 }
162
163                 if((cookies_size = security_server_get_cookie_size()) != 0)
164                 {
165                         if((cookies = (char *)calloc(1, cookies_size)) == NULL)
166                         {
167                                 goto ERROR;
168                         }
169                 }
170 #endif
171
172                 SCARD_DEBUG("server ipc is initialized");
173
174                 return true;
175 ERROR :
176                 if (watchId != (uint32_t)-1)
177                 {
178                         g_source_remove(watchId);
179                         watchId = -1;
180                 }
181
182                 if (ioChannel != NULL)
183                 {
184                         g_io_channel_unref(ioChannel);
185                         ioChannel = NULL;
186                 }
187
188                 if (ipcSocket != -1)
189                 {
190                         shutdown(ipcSocket, SHUT_RDWR);
191                         close(ipcSocket);
192
193                         ipcSocket = -1;
194                 }
195
196                 return false;
197         }
198
199         bool IPCHelper::createConnectSocket()
200         {
201                 GIOCondition condition = (GIOCondition) (G_IO_ERR | G_IO_HUP | G_IO_IN);
202
203                 SCARD_BEGIN();
204
205                 if (ipcSocket >= 0)
206                         return true;
207
208                 pthread_mutex_lock(&ipcLock);
209
210                 struct sockaddr_un saddrun_rv;
211                 socklen_t len_saddr = 0;
212
213                 memset(&saddrun_rv, 0, sizeof(struct sockaddr_un));
214
215                 ipcSocket = socket(AF_UNIX, SOCK_STREAM, 0);
216                 if (ipcSocket == -1)
217                 {
218                         SCARD_DEBUG_ERR("get socket is failed \n");
219                         pthread_mutex_unlock(&ipcLock);
220
221                         SCARD_END();
222
223                         return false;
224                 }
225
226                 SCARD_DEBUG("socket is created");
227
228                 ::setNonBlockSocket(ipcSocket);
229
230                 saddrun_rv.sun_family = AF_UNIX;
231                 strncpy(saddrun_rv.sun_path, OMAPI_SERVER_DOMAIN, sizeof(saddrun_rv.sun_path) - 1);
232
233                 len_saddr = sizeof(saddrun_rv.sun_family) + strlen(OMAPI_SERVER_DOMAIN);
234
235                 if ((connect(ipcSocket, (struct sockaddr *)&saddrun_rv, len_saddr)) < 0)
236                 {
237                         SCARD_DEBUG_ERR("error is occured");
238                         pthread_mutex_unlock(&ipcLock);
239                         goto ERROR;
240                 }
241
242                 pthread_mutex_unlock(&ipcLock);
243
244                 if ((ioChannel = g_io_channel_unix_new(ipcSocket)) != NULL)
245                 {
246                         if ((watchId = g_io_add_watch(ioChannel, condition, &IPCHelper::channelCallbackFunc, this)) < 1)
247                         {
248                                 SCARD_DEBUG_ERR(" g_io_add_watch is failed \n");
249                                 goto ERROR;
250                         }
251                 }
252                 else
253                 {
254                         SCARD_DEBUG_ERR(" g_io_channel_unix_new is failed \n");
255                         goto ERROR;
256                 }
257
258                 SCARD_DEBUG("socket and g io channel is binded");
259
260                 SCARD_END();
261
262                 return true;
263
264 ERROR :
265                 SCARD_DEBUG_ERR("error while initializing client ipc");
266
267                 if(watchId != 0)
268                 {
269                         g_source_remove(watchId);
270                         watchId = 0;
271                 }
272
273                 if(ioChannel != NULL)
274                 {
275                         g_io_channel_unref(ioChannel);
276                         ioChannel = NULL;
277                 }
278
279                 if (ipcSocket != -1)
280                 {
281                         shutdown(ipcSocket, SHUT_RDWR);
282                         close(ipcSocket);
283                         ipcSocket = -1;
284                 }
285
286                 SCARD_END();
287
288                 return false;
289         }
290
291         bool IPCHelper::sendMessage(Message *msg)
292         {
293                 if (ipcSocket == -1)
294                         return false;
295
296                 return sendMessage(ipcSocket, msg);
297         }
298
299         bool IPCHelper::sendMessage(int socket, Message *msg)
300         {
301                 bool result = false;
302                 ByteArray stream;
303                 unsigned int length = 0;
304
305                 stream = msg->serialize();
306                 length = stream.getLength();
307
308                 SCARD_DEBUG(">>>[SEND]>>> socket [%d], msg [%d], length [%d]", socket, msg->message, length);
309
310                 if (length > 0)
311                 {
312                         int sentBytes = 0;
313
314                         /* send 4 bytes (length) */
315                         pthread_mutex_lock(&ipcLock);
316                         sentBytes = send(socket, &length, sizeof(length), 0);
317                         pthread_mutex_unlock(&ipcLock);
318                         if (sentBytes == sizeof(length))
319                         {
320                                 unsigned int current = 0;
321
322                                 /* send message */
323                                 pthread_mutex_lock(&ipcLock);
324                                 do
325                                 {
326                                         sentBytes = send(socket, stream.getBuffer(current), length - current, 0);
327                                         if (sentBytes > 0)
328                                                 current += sentBytes;
329                                 }
330                                 while (current < length);
331                                 pthread_mutex_unlock(&ipcLock);
332
333                                 result = true;
334                         }
335                         else
336                         {
337                                 SCARD_DEBUG_ERR("send failed, sentBytes [%d]", sentBytes);
338                         }
339                 }
340                 else
341                 {
342                         SCARD_DEBUG_ERR("stream length is zero");
343                 }
344
345                 return result;
346         }
347
348         Message *IPCHelper::retrieveMessage()
349         {
350                 return retrieveMessage(ipcSocket);
351         }
352
353         Message *IPCHelper::retrieveMessage(int socket)
354         {
355                 Message *msg = NULL;
356                 unsigned int length = 0;
357                 int readBytes = 0;
358
359                 SCARD_BEGIN();
360
361                 /* read 4 bytes (length) */
362                 pthread_mutex_lock(&ipcLock);
363                 readBytes = recv(socket, &length, sizeof(length), 0);
364                 pthread_mutex_unlock(&ipcLock);
365                 if (readBytes == sizeof(length))
366                 {
367                         if (length > 0)
368                         {
369                                 unsigned char *buffer = NULL;
370
371                                 /* prepare buffer */
372                                 buffer = new unsigned char[length];
373                                 if (buffer != NULL)
374                                 {
375                                         int retry = 0;
376                                         unsigned int current = 0;
377
378                                         /* read message */
379                                         pthread_mutex_lock(&ipcLock);
380                                         do
381                                         {
382                                                 readBytes = recv(socket, buffer + current, length - current, 0);
383                                                 if (readBytes > 0)
384                                                         current += readBytes;
385                                                 retry++;
386                                         }
387                                         while (current < length);
388                                         pthread_mutex_unlock(&ipcLock);
389
390                                         msg = new Message();
391                                         if (msg != NULL)
392                                         {
393                                                 msg->deserialize(buffer, length);
394
395                                                 SCARD_DEBUG("<<<[RETRIEVE]<<< socket [%d], msg_length [%d]", socket, length);
396                                         }
397                                         else
398                                         {
399                                                 SCARD_DEBUG_ERR("alloc failed");
400                                         }
401
402                                         delete []buffer;
403                                 }
404                                 else
405                                 {
406                                         SCARD_DEBUG_ERR("allocation failed");
407                                 }
408                         }
409                         else
410                         {
411                                 SCARD_DEBUG_ERR("invalid length, socket = [%d], msg_length = [%d]", socket, length);
412                         }
413                 }
414                 else
415                 {
416                         SCARD_DEBUG_ERR("failed to recv length, socket = [%d], readBytes [%d]", socket, readBytes);
417                 }
418
419
420                 SCARD_END();
421
422                 return msg;
423         }
424
425         void IPCHelper::setDispatcher(DispatcherHelper *dispatcher)
426         {
427                 this->dispatcher = dispatcher;
428         }
429
430 } /* namespace smartcard_service_api */