2 * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
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 int gid, cookies_size;
166 gid = security_server_get_gid("smartcard-service");
169 SCARD_DEBUG("get gid from security server is failed. this object is not allowed by security server");
173 if((cookies_size = security_server_get_cookie_size()) != 0)
175 if((cookies = (char *)calloc(1, cookies_size)) == NULL)
182 SCARD_DEBUG("server ipc is initialized");
186 SCARD_DEBUG_ERR("error while initializing server ipc");
188 destroyListenSocket();
193 #ifdef CLIENT_IPC_THREAD
194 int IPCHelper::eventPoll()
201 if ((events = epoll_wait(fdPoll, pollEvents, EPOLL_SIZE, -1)) > 0)
205 for (i = 0; i < events; i++)
207 SCARD_DEBUG("pollEvents[%d].events [%X]", i, pollEvents[i].events);
209 if ((pollEvents[i].events & EPOLLHUP) || (pollEvents[i].events & EPOLLERR))
211 SCARD_DEBUG_ERR("connection is closed");
215 else if (pollEvents[i].events & EPOLLIN)
223 if (select(ipcSocket + 1, &fdSetRead, NULL, NULL, NULL) > 0)
225 if (FD_ISSET(ipcSocket, &fdSetRead) == true)
228 unsigned int size = sizeof(val);
230 if (getsockopt(ipcSocket, SOL_SOCKET, SO_ERROR, (void *)&val, &size) == 0)
234 SCARD_DEBUG("socket is readable");
239 SCARD_DEBUG("socket is not available. maybe disconnected");
245 SCARD_DEBUG_ERR("getsockopt failed, errno [%d]", errno);
251 SCARD_DEBUG_ERR("FD_ISSET false!!! what's wrong");
257 SCARD_DEBUG_ERR("select failed [%d]", errno);
264 void *IPCHelper::threadRead(void *data)
266 #ifdef IPC_USE_SIGTERM
268 struct sigaction act;
269 act.sa_handler = thread_sig_handler;
270 sigaction(SIGTERM, &act, NULL);
273 sigemptyset(&newmask);
274 sigaddset(&newmask, SIGTERM);
275 pthread_sigmask(SIG_UNBLOCK, &newmask, NULL);
276 SCARD_DEBUG("sighandler is registered");
278 pthread_mutex_lock(&g_client_lock);
279 pthread_cond_signal ((pthread_cond_t *) data);
280 pthread_mutex_unlock(&g_client_lock);
282 IPCHelper *helper = (IPCHelper *)data;
284 bool condition = true;
287 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
289 while (condition == true)
291 if ((result = helper->eventPoll()) > 0)
293 condition = (helper->handleIncomingCondition(NULL, G_IO_IN) == 0);
295 else if (result == 0)
297 helper->handleIOErrorCondition(NULL, G_IO_ERR);
302 helper->handleInvalidSocketCondition(NULL, G_IO_NVAL);
307 SCARD_DEBUG("threadRead is terminated");
313 bool IPCHelper::createConnectSocket()
315 #ifndef CLIENT_IPC_THREAD
316 GIOCondition condition = (GIOCondition)(G_IO_ERR | G_IO_HUP | G_IO_IN);
319 char err[200] = { 0, };
326 pthread_mutex_lock(&ipcLock);
328 struct sockaddr_un saddrun_rv;
329 socklen_t len_saddr = 0;
331 memset(&saddrun_rv, 0, sizeof(struct sockaddr_un));
333 ipcSocket = socket(AF_UNIX, SOCK_STREAM, 0);
336 SCARD_DEBUG_ERR("get socket is failed [%d, %s]",
337 errno, strerror_r(errno, err, sizeof(err)));
341 SCARD_DEBUG("socket is created");
343 ::setNonBlockSocket(ipcSocket);
345 saddrun_rv.sun_family = AF_UNIX;
346 strncpy(saddrun_rv.sun_path, SCARD_SERVER_DOMAIN, sizeof(saddrun_rv.sun_path) - 1);
348 len_saddr = sizeof(saddrun_rv.sun_family) + strlen(SCARD_SERVER_DOMAIN);
350 if ((result = connect(ipcSocket, (struct sockaddr *)&saddrun_rv, len_saddr)) < 0)
352 SCARD_DEBUG_ERR("connect failed [%d, %s]",
353 errno, strerror_r(errno, err, sizeof(err)));
357 #ifdef CLIENT_IPC_THREAD
359 if((fdPoll = epoll_create1(EPOLL_CLOEXEC)) == -1)
361 SCARD_DEBUG_ERR("epoll_create1 failed [%d, %s]",
362 errno, strerror_r(errno, err, sizeof(err)));
366 pollEvents = (struct epoll_event *)calloc(EPOLL_SIZE, sizeof(struct epoll_event));
367 if (pollEvents == NULL)
369 SCARD_DEBUG_ERR("alloc failed");
373 struct epoll_event ev;
375 ev.events = EPOLLIN | EPOLLHUP | EPOLLERR;
376 ev.data.fd = ipcSocket;
378 epoll_ctl(fdPoll, EPOLL_CTL_ADD, ipcSocket, &ev);
381 FD_SET(ipcSocket, &fdSetRead);
383 #ifdef IPC_USE_SIGTERM
384 pthread_cond_t pcond = PTHREAD_COND_INITIALIZER;
386 if (pthread_create(&readThread, NULL, &IPCHelper::threadRead, &pcond) != 0)
388 if (pthread_create(&readThread, NULL, &IPCHelper::threadRead, this) != 0)
391 SCARD_DEBUG_ERR("pthread_create is failed");
395 #ifdef IPC_USE_SIGTERM
396 pthread_cond_wait (&pcond, &g_client_lock);
400 if ((ioChannel = g_io_channel_unix_new(ipcSocket)) != NULL)
402 if ((watchId = g_io_add_watch(ioChannel, condition, &IPCHelper::channelCallbackFunc, this)) < 1)
404 SCARD_DEBUG_ERR(" g_io_add_watch is failed");
410 SCARD_DEBUG_ERR(" g_io_channel_unix_new is failed");
414 pthread_mutex_unlock(&ipcLock);
416 SCARD_DEBUG("connecting success");
423 SCARD_DEBUG_ERR("error while initializing client ipc");
425 destroyConnectSocket();
427 pthread_mutex_unlock(&ipcLock);
434 void IPCHelper::destroyListenSocket()
436 if (watchId != (uint32_t)-1)
438 g_source_remove(watchId);
442 if (ioChannel != NULL)
444 g_io_channel_unref(ioChannel);
450 shutdown(ipcSocket, SHUT_RDWR);
457 void IPCHelper::destroyConnectSocket()
459 #ifdef CLIENT_IPC_THREAD
463 pthread_cancel(readThread);
469 struct epoll_event ev;
471 ev.events = EPOLLIN | EPOLLHUP | EPOLLERR;
472 ev.data.fd = ipcSocket;
473 epoll_ctl(fdPoll, EPOLL_CTL_DEL, ipcSocket, &ev);
478 if (pollEvents != NULL)
486 FD_CLR(ipcSocket, &fdSetRead);
492 g_source_remove(watchId);
496 if(ioChannel != NULL)
498 g_io_channel_unref(ioChannel);
505 shutdown(ipcSocket, SHUT_RDWR);
511 bool IPCHelper::sendMessage(int socket, Message *msg)
514 unsigned int length = 0;
516 stream = msg->serialize();
517 length = stream.getLength();
519 SCARD_DEBUG(">>>[SEND]>>> socket [%d], msg [%d], length [%d]",
520 socket, msg->message, stream.getLength());
522 return sendMessage(socket, stream);
525 bool IPCHelper::sendMessage(int socket, ByteArray &buffer)
528 unsigned int length = 0;
530 length = buffer.getLength();
536 /* send 4 bytes (length) */
537 pthread_mutex_lock(&ipcLock);
538 sentBytes = send(socket, &length, sizeof(length), 0);
539 pthread_mutex_unlock(&ipcLock);
540 if (sentBytes == sizeof(length))
542 unsigned int current = 0;
545 pthread_mutex_lock(&ipcLock);
548 sentBytes = send(socket, buffer.getBuffer(current), length - current, 0);
550 current += sentBytes;
552 while (current < length);
553 pthread_mutex_unlock(&ipcLock);
559 SCARD_DEBUG_ERR("send failed, sentBytes [%d]", sentBytes);
564 SCARD_DEBUG_ERR("stream length is zero");
570 Message *IPCHelper::retrieveMessage()
572 return retrieveMessage(ipcSocket);
575 Message *IPCHelper::retrieveMessage(int socket)
582 buffer = retrieveBuffer(socket);
583 if (buffer.getLength() > 0)
588 msg->deserialize(buffer);
592 SCARD_DEBUG_ERR("alloc failed");
597 SCARD_DEBUG_ERR("retrieveBuffer failed ");
605 ByteArray IPCHelper::retrieveBuffer(int socket)
608 unsigned int length = 0;
613 /* read 4 bytes (length) */
614 pthread_mutex_lock(&ipcLock);
615 readBytes = recv(socket, &length, sizeof(length), 0);
616 pthread_mutex_unlock(&ipcLock);
617 if (readBytes == sizeof(length))
621 uint8_t *temp = NULL;
624 temp = new uint8_t[length];
628 unsigned int current = 0;
631 pthread_mutex_lock(&ipcLock);
634 readBytes = recv(socket, temp + current, length - current, 0);
636 current += readBytes;
639 while (current < length);
640 pthread_mutex_unlock(&ipcLock);
642 SCARD_DEBUG("<<<[RETRIEVE]<<< socket [%d], msg_length [%d]", socket, length);
644 buffer.setBuffer(temp, length);
650 SCARD_DEBUG_ERR("allocation failed");
655 SCARD_DEBUG_ERR("invalid length, socket = [%d], msg_length = [%d]", socket, length);
660 SCARD_DEBUG_ERR("failed to recv length, socket = [%d], readBytes [%d]", socket, readBytes);
668 void IPCHelper::setDispatcher(DispatcherHelper *dispatcher)
670 this->dispatcher = dispatcher;
673 } /* namespace smartcard_service_api */