Change sequence of loading secure elements
[platform/core/connectivity/smartcard-service.git] / server / ServerIPC.cpp
1 /*
2  * Copyright (c) 2012, 2013 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 /* standard library header */
18 #include <string.h>
19 #include <sys/socket.h>
20 #include <unistd.h>
21
22 /* SLP library header */
23 #ifdef SECURITY_SERVER
24 #include "security-server.h"
25 #endif
26
27 /* local header */
28 #include "Debug.h"
29 #include "ServerIPC.h"
30 #include "ServerResource.h"
31 #include "ServerDispatcher.h"
32
33 #ifndef EXTERN_API
34 #define EXTERN_API __attribute__((visibility("default")))
35 #endif
36
37 namespace smartcard_service_api
38 {
39         ServerIPC::ServerIPC():IPCHelper()
40         {
41                 SCARD_BEGIN();
42
43                 setDispatcher(ServerDispatcher::getInstance());
44
45                 SCARD_END();
46         }
47
48         ServerIPC::~ServerIPC()
49         {
50         }
51
52         ServerIPC *ServerIPC::getInstance()
53         {
54                 static ServerIPC instance;
55
56                 return &instance;
57         }
58
59         Message *ServerIPC::retrieveMessage(int socket)
60         {
61                 ByteArray buffer;
62                 Message *msg = NULL;
63
64                 SCARD_BEGIN();
65
66                 buffer = IPCHelper::retrieveBuffer(socket);
67                 if (buffer.getLength() > 0)
68                 {
69 #ifdef SECURITY_SERVER
70                         ByteArray cookie;
71                         int result, gid;
72
73                         if (buffer.getLength() < 20)
74                                 return msg;
75
76                         cookie.setBuffer(buffer.getBuffer(), 20);
77
78                         gid = security_server_get_gid("smartcard-daemon");
79                         if ((result = security_server_check_privilege(cookie.getBuffer(), gid)) != SECURITY_SERVER_API_SUCCESS)
80                         {
81                                 SCARD_DEBUG_ERR("security_server_check_privilege failed [%d]", result);
82                                 return msg;
83                         }
84 #endif
85                         msg = new Message();
86                         if (msg != NULL)
87                         {
88                                 msg->deserialize(buffer);
89                         }
90                         else
91                         {
92                                 SCARD_DEBUG_ERR("alloc failed");
93                         }
94                 }
95                 else
96                 {
97                         SCARD_DEBUG_ERR("retrieveBuffer failed ");
98                 }
99
100                 SCARD_END();
101
102                 return msg;
103         }
104
105         bool ServerIPC::acceptClient()
106         {
107                 GIOCondition condition = (GIOCondition)(G_IO_ERR | G_IO_HUP | G_IO_IN);
108                 socklen_t addrlen = 0;
109                 int client_sock_fd = 0;
110                 GIOChannel *client_channel = NULL;
111                 int client_src_id;
112
113                 SCARD_DEBUG("client is trying to connect to server");
114
115                 pthread_mutex_lock(&ipcLock);
116                 client_sock_fd = accept(ipcSocket, NULL, &addrlen);
117                 pthread_mutex_unlock(&ipcLock);
118
119                 if (client_sock_fd < 0)
120                 {
121                         SCARD_DEBUG_ERR("can not accept client");
122                         goto ERROR;
123                 }
124
125                 SCARD_DEBUG("client is accepted by server");
126
127                 if ((client_channel = g_io_channel_unix_new(client_sock_fd)) == NULL)
128                 {
129                         SCARD_DEBUG_ERR("create new g io channel is failed");
130                         goto ERROR;
131                 }
132
133                 if ((client_src_id = g_io_add_watch(client_channel, condition, &IPCHelper::channelCallbackFunc, this)) < 1)
134                 {
135                         SCARD_DEBUG_ERR("add io callback is failed");
136                         goto ERROR;
137                 }
138
139                 SCARD_DEBUG("client socket is bond with g_io_channel");
140
141                 if (ServerResource::getInstance().createClient(client_channel, client_sock_fd, client_src_id, 0, -1) == false)
142                 {
143                         SCARD_DEBUG_ERR("failed to add client");
144                 }
145
146                 return true;
147
148 ERROR :
149                 if (client_channel != NULL)
150                 {
151                         g_io_channel_unref(client_channel);
152                 }
153
154                 if (client_sock_fd != -1)
155                 {
156                         shutdown(client_sock_fd, SHUT_RDWR);
157                         close(client_sock_fd);
158                 }
159
160                 return false;
161         }
162
163         void ServerIPC::restartServerIPC()
164         {
165                 destroyListenSocket();
166
167                 createListenSocket();
168         }
169
170         void ServerIPC::releaseClient(void *channel, int socket, int watchID)
171         {
172                 if (watchID != 0)
173                 {
174                         g_source_remove(watchID);
175                 }
176
177                 if (channel != NULL)
178                 {
179                         g_io_channel_unref((GIOChannel *)channel);
180                 }
181
182                 if (socket >= 0)
183                 {
184                         shutdown(socket, SHUT_RDWR);
185                         close(socket);
186                 }
187         }
188
189         int ServerIPC::handleIOErrorCondition(void *channel, GIOCondition condition)
190         {
191                 SCARD_BEGIN();
192
193                 if(channel == ioChannel)
194                 {
195                         SCARD_DEBUG("server socket is closed");
196                         restartServerIPC();
197                 }
198                 else
199                 {
200                         DispatcherMsg dispMsg;
201                         int peerSocket = g_io_channel_unix_get_fd((GIOChannel *)channel);
202
203                         SCARD_DEBUG("client socket is closed, socket [%d]", peerSocket);
204
205                         /* push messsage to dispatcher */
206                         dispMsg.message = Message::MSG_OPERATION_RELEASE_CLIENT;
207                         dispMsg.param1 = peerSocket;
208                         dispMsg.setPeerSocket(peerSocket);
209
210                         /* push to dispatcher */
211                         ServerDispatcher::getInstance()->pushMessage(&dispMsg);
212                 }
213
214                 SCARD_END();
215
216                 return FALSE;
217         }
218
219         int ServerIPC::handleInvalidSocketCondition(void *channel, GIOCondition condition)
220         {
221                 SCARD_BEGIN();
222                 SCARD_END();
223
224                 return FALSE;
225         }
226
227         int ServerIPC::handleIncomingCondition(void *channel, GIOCondition condition)
228         {
229                 int result = FALSE;
230
231                 SCARD_BEGIN();
232
233                 if(channel == ioChannel)
234                 {
235                         /* connect state. should accept */
236                         SCARD_DEBUG("new client connected");
237
238                         result = acceptClient();
239                 }
240                 else
241                 {
242                         int peerSocket = g_io_channel_unix_get_fd((GIOChannel *)channel);
243
244                         SCARD_DEBUG("data incomming from [%d]", peerSocket);
245
246                         if (peerSocket >= 0)
247                         {
248                                 Message *msg;
249
250                                 /* read message */
251                                 if ((msg = retrieveMessage(peerSocket)) != NULL)
252                                 {
253                                         DispatcherMsg dispMsg(msg, peerSocket);
254
255                                         /* push to dispatcher */
256                                         ServerDispatcher::getInstance()->pushMessage(&dispMsg);
257
258                                         result = TRUE;
259
260                                         delete msg;
261                                 }
262                                 else
263                                 {
264                                         /* clear client connection */
265                                         SCARD_DEBUG_ERR("retrieve message failed, socket [%d]", peerSocket);
266                                 }
267                         }
268                         else
269                         {
270                                 SCARD_DEBUG_ERR("client context doesn't exist, socket [%d]", peerSocket);
271                         }
272                 }
273
274                 SCARD_END();
275
276                 return result;
277         }
278
279 } /* namespace smartcard_service_api */
280
281 using namespace smartcard_service_api;
282
283 EXTERN_API void server_ipc_create_listen_socket()
284 {
285         ServerIPC *ipc = ServerIPC::getInstance();
286
287         ipc->createListenSocket();
288 }