2 * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 /* standard library header */
24 #include <sys/socket.h>
25 #ifdef USE_UNIX_DOMAIN
28 #else /* USE_UNIX_DOMAIN */
29 #include <netinet/in.h>
30 #endif /* USE_UNIX_DOMAIN */
33 #include <sys/epoll.h>
36 /* SLP library header */
40 #include "IPCHelper.h"
42 #ifdef USE_UNIX_DOMAIN
43 #define SCARD_SERVER_DOMAIN "/tmp/omapi-server-domain"
44 #endif /* USE_UNIX_DOMAIN */
46 static void setNonBlockSocket(int socket)
50 flags = fcntl(socket, F_GETFL);
54 if (fcntl(socket, F_SETFL, flags) < 0)
56 /* SCARD_DEBUG_ERR("fcntl, executing nonblock error"); */
60 namespace smartcard_service_api
62 IPCHelper::IPCHelper() : fdPoll(-1)
67 memset(&ipcLock, 0, sizeof(ipcLock));
73 IPCHelper::~IPCHelper()
77 gboolean IPCHelper::channelCallbackFunc(GIOChannel* channel, GIOCondition condition, gpointer data)
79 IPCHelper *helper = (IPCHelper *)data;
80 gboolean result = FALSE;
82 SCARD_DEBUG("channel [%p], condition [%d], data [%p]", channel, condition, data);
86 SCARD_DEBUG_ERR("ipchelper is null");
90 if ((G_IO_ERR & condition) || (G_IO_HUP & condition))
92 result = helper->handleIOErrorCondition(channel, condition);
94 else if (G_IO_NVAL & condition)
96 result = helper->handleInvalidSocketCondition(channel, condition);
98 else if (G_IO_IN & condition)
100 result = helper->handleIncomingCondition(channel, condition);
106 bool IPCHelper::createListenSocket()
108 GIOCondition condition = (GIOCondition)(G_IO_ERR | G_IO_HUP | G_IO_IN);
109 struct sockaddr_un saddrun_rv;
114 memset(&saddrun_rv, 0, sizeof(struct sockaddr_un));
116 unlink(SCARD_SERVER_DOMAIN);
118 ipcSocket = socket(AF_UNIX, SOCK_STREAM, 0);
121 SCARD_DEBUG_ERR("get socket is failed");
125 ::setNonBlockSocket(ipcSocket);
127 saddrun_rv.sun_family = AF_UNIX;
128 strncpy(saddrun_rv.sun_path, SCARD_SERVER_DOMAIN, sizeof(saddrun_rv.sun_path) - 1);
130 if (bind(ipcSocket, (struct sockaddr *)&saddrun_rv, sizeof(saddrun_rv)) < 0)
132 SCARD_DEBUG_ERR("bind is failed \n");
136 if (chmod(SCARD_SERVER_DOMAIN, 0777) < 0)
138 SCARD_DEBUG_ERR("can not change permission of UNIX DOMAIN file");
142 if (listen(ipcSocket, IPC_SERVER_MAX_CLIENT) < 0)
144 SCARD_DEBUG_ERR("listen is failed \n");
148 if ((ioChannel = g_io_channel_unix_new(ipcSocket)) != NULL)
150 if ((watchId = g_io_add_watch(ioChannel, condition, &IPCHelper::channelCallbackFunc, this)) < 1)
152 SCARD_DEBUG_ERR(" g_io_add_watch is failed \n");
158 SCARD_DEBUG_ERR(" g_io_channel_unix_new is failed \n");
162 #ifdef SECURITY_SERVER
163 gid = security_server_get_gid(NET_NFC_MANAGER_OBJECT);
166 SCARD_DEBUG("get gid from security server is failed. this object is not allowed by security server");
170 if((cookies_size = security_server_get_cookie_size()) != 0)
172 if((cookies = (char *)calloc(1, cookies_size)) == NULL)
179 SCARD_DEBUG("server ipc is initialized");
183 SCARD_DEBUG_ERR("error while initializing server ipc");
185 destroyListenSocket();
190 #ifdef CLIENT_IPC_THREAD
191 int IPCHelper::eventPoll()
198 if ((events = epoll_wait(fdPoll, pollEvents, EPOLL_SIZE, -1)) > 0)
202 for (i = 0; i < events; i++)
204 SCARD_DEBUG("pollEvents[%d].events [%X]", i, pollEvents[i].events);
206 if ((pollEvents[i].events & EPOLLHUP) || (pollEvents[i].events & EPOLLERR))
208 SCARD_DEBUG_ERR("connection is closed");
212 else if (pollEvents[i].events & EPOLLIN)
220 if (select(ipcSocket + 1, &fdSetRead, NULL, NULL, NULL) > 0)
222 if (FD_ISSET(ipcSocket, &fdSetRead) == true)
225 unsigned int size = sizeof(val);
227 if (getsockopt(ipcSocket, SOL_SOCKET, SO_ERROR, (void *)&val, &size) == 0)
231 SCARD_DEBUG("socket is readable");
236 SCARD_DEBUG("socket is not available. maybe disconnected");
242 SCARD_DEBUG_ERR("getsockopt failed, errno [%d]", errno);
248 SCARD_DEBUG_ERR("FD_ISSET false!!! what's wrong");
254 SCARD_DEBUG_ERR("select failed [%d]", errno);
261 void *IPCHelper::threadRead(void *data)
263 #ifdef IPC_USE_SIGTERM
265 struct sigaction act;
266 act.sa_handler = thread_sig_handler;
267 sigaction(SIGTERM, &act, NULL);
270 sigemptyset(&newmask);
271 sigaddset(&newmask, SIGTERM);
272 pthread_sigmask(SIG_UNBLOCK, &newmask, NULL);
273 SCARD_DEBUG("sighandler is registered");
275 pthread_mutex_lock(&g_client_lock);
276 pthread_cond_signal ((pthread_cond_t *) data);
277 pthread_mutex_unlock(&g_client_lock);
279 IPCHelper *helper = (IPCHelper *)data;
281 bool condition = true;
284 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
286 while (condition == true)
288 if ((result = helper->eventPoll()) > 0)
290 condition = (helper->handleIncomingCondition(NULL, G_IO_IN) == 0);
292 else if (result == 0)
294 helper->handleIOErrorCondition(NULL, G_IO_ERR);
299 helper->handleInvalidSocketCondition(NULL, G_IO_NVAL);
304 SCARD_DEBUG("threadRead is terminated");
310 bool IPCHelper::createConnectSocket()
312 #ifndef CLIENT_IPC_THREAD
313 GIOCondition condition = (GIOCondition)(G_IO_ERR | G_IO_HUP | G_IO_IN);
322 pthread_mutex_lock(&ipcLock);
324 struct sockaddr_un saddrun_rv;
325 socklen_t len_saddr = 0;
327 memset(&saddrun_rv, 0, sizeof(struct sockaddr_un));
329 ipcSocket = socket(AF_UNIX, SOCK_STREAM, 0);
332 SCARD_DEBUG_ERR("get socket is failed");
336 SCARD_DEBUG("socket is created");
338 ::setNonBlockSocket(ipcSocket);
340 saddrun_rv.sun_family = AF_UNIX;
341 strncpy(saddrun_rv.sun_path, SCARD_SERVER_DOMAIN, sizeof(saddrun_rv.sun_path) - 1);
343 len_saddr = sizeof(saddrun_rv.sun_family) + strlen(SCARD_SERVER_DOMAIN);
345 if ((result = connect(ipcSocket, (struct sockaddr *)&saddrun_rv, len_saddr)) < 0)
347 SCARD_DEBUG_ERR("connect failed [%d]", result);
351 #ifdef CLIENT_IPC_THREAD
353 if((fdPoll = epoll_create1(EPOLL_CLOEXEC)) == -1)
355 SCARD_DEBUG_ERR("epoll_create1 failed");
359 pollEvents = (struct epoll_event *)calloc(EPOLL_SIZE, sizeof(struct epoll_event));
360 if (pollEvents == NULL)
362 SCARD_DEBUG_ERR("alloc failed");
366 struct epoll_event ev;
368 ev.events = EPOLLIN | EPOLLHUP | EPOLLERR;
369 ev.data.fd = ipcSocket;
371 epoll_ctl(fdPoll, EPOLL_CTL_ADD, ipcSocket, &ev);
374 FD_SET(ipcSocket, &fdSetRead);
376 #ifdef IPC_USE_SIGTERM
377 pthread_cond_t pcond = PTHREAD_COND_INITIALIZER;
379 if (pthread_create(&readThread, NULL, &IPCHelper::threadRead, &pcond) != 0)
381 if (pthread_create(&readThread, NULL, &IPCHelper::threadRead, this) != 0)
384 SCARD_DEBUG_ERR("pthread_create is failed");
388 #ifdef IPC_USE_SIGTERM
389 pthread_cond_wait (&pcond, &g_client_lock);
393 if ((ioChannel = g_io_channel_unix_new(ipcSocket)) != NULL)
395 if ((watchId = g_io_add_watch(ioChannel, condition, &IPCHelper::channelCallbackFunc, this)) < 1)
397 SCARD_DEBUG_ERR(" g_io_add_watch is failed");
403 SCARD_DEBUG_ERR(" g_io_channel_unix_new is failed");
407 pthread_mutex_unlock(&ipcLock);
409 SCARD_DEBUG("connecting success");
416 SCARD_DEBUG_ERR("error while initializing client ipc");
418 destroyConnectSocket();
420 pthread_mutex_unlock(&ipcLock);
427 void IPCHelper::destroyListenSocket()
429 if (watchId != (uint32_t)-1)
431 g_source_remove(watchId);
435 if (ioChannel != NULL)
437 g_io_channel_unref(ioChannel);
443 shutdown(ipcSocket, SHUT_RDWR);
450 void IPCHelper::destroyConnectSocket()
452 #ifdef CLIENT_IPC_THREAD
456 pthread_cancel(readThread);
462 struct epoll_event ev;
464 ev.events = EPOLLIN | EPOLLHUP | EPOLLERR;
465 ev.data.fd = ipcSocket;
466 epoll_ctl(fdPoll, EPOLL_CTL_DEL, ipcSocket, &ev);
471 if (pollEvents != NULL)
479 FD_CLR(ipcSocket, &fdSetRead);
485 g_source_remove(watchId);
489 if(ioChannel != NULL)
491 g_io_channel_unref(ioChannel);
498 shutdown(ipcSocket, SHUT_RDWR);
504 bool IPCHelper::sendMessage(int socket, Message *msg)
507 unsigned int length = 0;
509 stream = msg->serialize();
510 length = stream.getLength();
512 SCARD_DEBUG(">>>[SEND]>>> socket [%d], msg [%d], length [%d]", socket, msg->message, stream.getLength());
514 return sendMessage(socket, stream);
517 bool IPCHelper::sendMessage(int socket, ByteArray &buffer)
520 unsigned int length = 0;
522 length = buffer.getLength();
528 /* send 4 bytes (length) */
529 pthread_mutex_lock(&ipcLock);
530 sentBytes = send(socket, &length, sizeof(length), 0);
531 pthread_mutex_unlock(&ipcLock);
532 if (sentBytes == sizeof(length))
534 unsigned int current = 0;
537 pthread_mutex_lock(&ipcLock);
540 sentBytes = send(socket, buffer.getBuffer(current), length - current, 0);
542 current += sentBytes;
544 while (current < length);
545 pthread_mutex_unlock(&ipcLock);
551 SCARD_DEBUG_ERR("send failed, sentBytes [%d]", sentBytes);
556 SCARD_DEBUG_ERR("stream length is zero");
562 Message *IPCHelper::retrieveMessage()
564 return retrieveMessage(ipcSocket);
567 Message *IPCHelper::retrieveMessage(int socket)
574 buffer = retrieveBuffer(socket);
575 if (buffer.getLength() > 0)
580 msg->deserialize(buffer);
584 SCARD_DEBUG_ERR("alloc failed");
589 SCARD_DEBUG_ERR("retrieveBuffer failed ");
597 ByteArray IPCHelper::retrieveBuffer(int socket)
600 unsigned int length = 0;
605 /* read 4 bytes (length) */
606 pthread_mutex_lock(&ipcLock);
607 readBytes = recv(socket, &length, sizeof(length), 0);
608 pthread_mutex_unlock(&ipcLock);
609 if (readBytes == sizeof(length))
613 uint8_t *temp = NULL;
616 temp = new uint8_t[length];
620 unsigned int current = 0;
623 pthread_mutex_lock(&ipcLock);
626 readBytes = recv(socket, temp + current, length - current, 0);
628 current += readBytes;
631 while (current < length);
632 pthread_mutex_unlock(&ipcLock);
634 SCARD_DEBUG("<<<[RETRIEVE]<<< socket [%d], msg_length [%d]", socket, length);
636 buffer.setBuffer(temp, length);
642 SCARD_DEBUG_ERR("allocation failed");
647 SCARD_DEBUG_ERR("invalid length, socket = [%d], msg_length = [%d]", socket, length);
652 SCARD_DEBUG_ERR("failed to recv length, socket = [%d], readBytes [%d]", socket, readBytes);
660 void IPCHelper::setDispatcher(DispatcherHelper *dispatcher)
662 this->dispatcher = dispatcher;
665 } /* namespace smartcard_service_api */