Give delay when client request shutting down
[platform/core/connectivity/smartcard-service.git] / server / ServerDispatcher.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 #ifndef USE_GDBUS
18 /* standard library header */
19 #include <stdio.h>
20 #include <string.h>
21
22 /* SLP library header */
23
24 /* local header */
25 #include "Debug.h"
26 #include "Exception.h"
27 #include "ServerDispatcher.h"
28 #include "ServerIPC.h"
29 #include "ServerResource.h"
30 #include "ServerSEService.h"
31 #include "ServerChannel.h"
32 #include "ServerSession.h"
33 #include "ServerReader.h"
34
35 namespace smartcard_service_api
36 {
37         ServerDispatcher::ServerDispatcher():DispatcherHelper()
38         {
39                 _BEGIN();
40
41                 runDispatcherThread();
42
43                 _END();
44         }
45
46         ServerDispatcher::~ServerDispatcher()
47         {
48         }
49
50         ServerDispatcher *ServerDispatcher::getInstance()
51         {
52                 static ServerDispatcher instance;
53
54                 return &instance;
55         }
56
57         void *ServerDispatcher::dispatcherThreadFunc(DispatcherMsg *msg, void *data)
58         {
59                 int socket = -1;
60                 ServerResource *resource = NULL;
61
62                 if (data == NULL)
63                 {
64                         _ERR("dispatcher instance is null");
65                         return NULL;
66                 }
67
68                 if (msg == NULL)
69                 {
70                         _ERR("message is null");
71                         return NULL;
72                 }
73
74                 resource = &ServerResource::getInstance();
75                 socket = msg->getPeerSocket();
76
77                 switch (msg->message)
78                 {
79                 /* handle message */
80                 case Message::MSG_REQUEST_READERS :
81                         {
82                                 _INFO("[MSG_REQUEST_READERS]");
83
84                                 int count = 0;
85                                 Message response(*msg);
86                                 ByteArray info;
87                                 ClientInstance *instance = NULL;
88                                 ServiceInstance *service = NULL;
89
90                                 response.param1 = 0;
91                                 response.param2 = 0;
92
93                                 /* load secure elements */
94                                 resource->loadSecureElements();
95
96                                 if ((instance = resource->getClient(socket)) != NULL)
97                                 {
98                                         /* update client PID */
99                                         if (instance->getPID() == -1)
100                                         {
101                                                 instance->setPID(msg->error);
102                                                 _INFO("update PID [%d]", msg->error);
103
104                                                 /* generate certification hashes */
105                                                 instance->generateCertificationHashes();
106                                         }
107
108                                         /* create service */
109                                         if ((service = resource->createService(socket)) != NULL)
110                                         {
111                                                 response.error = SCARD_ERROR_OK;
112                                                 response.param2 = service->getHandle();
113
114                                                 if ((count = resource->getReadersInformation(info)) > 0)
115                                                 {
116                                                         response.param1 = count;
117                                                         response.data = info;
118                                                 }
119                                                 else
120                                                 {
121                                                         _INFO("no secure elements");
122                                                 }
123                                         }
124                                         else
125                                         {
126                                                 _ERR("createClient failed");
127
128                                                 response.error = SCARD_ERROR_UNAVAILABLE;
129                                         }
130                                 }
131                                 else
132                                 {
133                                         _ERR("client doesn't exist, socket [%d]", socket);
134
135                                         response.error = SCARD_ERROR_UNAVAILABLE;
136                                 }
137
138                                 /* response to client */
139                                 ServerIPC::getInstance()->sendMessage(socket, response);
140                         }
141                         break;
142
143                 case Message::MSG_REQUEST_SHUTDOWN :
144                         {
145                                 Message response(*msg);
146
147                                 _INFO("[MSG_REQUEST_SHUTDOWN]");
148
149                                 response.error = SCARD_ERROR_OK;
150
151                                 resource->removeService(socket, msg->param1);
152
153                                 /* response to client */
154                                 ServerIPC::getInstance()->sendMessage(socket, response);
155                         }
156                         break;
157
158                 case Message::MSG_REQUEST_OPEN_SESSION :
159                         {
160                                 Message response(*msg);
161                                 unsigned int handle = IntegerHandle::INVALID_HANDLE;
162
163                                 _INFO("[MSG_REQUEST_OPEN_SESSION]");
164
165                                 if (resource->isValidReaderHandle(msg->param1))
166                                 {
167                                         vector<ByteArray> temp;
168
169                                         handle = resource->createSession(socket, msg->error/* service context */, msg->param1, temp, msg->caller);
170                                         if (handle != IntegerHandle::INVALID_HANDLE)
171                                         {
172                                                 response.error = SCARD_ERROR_OK;
173                                         }
174                                         else
175                                         {
176                                                 _ERR("createSession failed [%d]", handle);
177                                                 response.error = SCARD_ERROR_OUT_OF_MEMORY;
178                                         }
179                                 }
180                                 else
181                                 {
182                                         _ERR("request invalid reader handle [%d]", msg->param1);
183                                         response.error = SCARD_ERROR_ILLEGAL_PARAM;
184                                 }
185
186                                 response.param1 = handle;
187
188                                 /* response to client */
189                                 ServerIPC::getInstance()->sendMessage(socket, response);
190                         }
191                         break;
192
193                 case Message::MSG_REQUEST_CLOSE_SESSION :
194                         {
195                                 Message response(*msg);
196
197                                 _INFO("[MSG_REQUEST_CLOSE_SESSION]");
198
199                                 response.param1 = 0;
200                                 response.error = SCARD_ERROR_OK;
201
202                                 if (resource->isValidSessionHandle(socket, msg->error/* service context */, msg->param1))
203                                 {
204                                         resource->removeSession(socket, msg->error/* service context */, msg->param1);
205                                 }
206
207                                 /* response to client */
208                                 ServerIPC::getInstance()->sendMessage(socket, response);
209                         }
210                         break;
211
212                 case Message::MSG_REQUEST_OPEN_CHANNEL :
213                         {
214                                 Message response(*msg);
215
216                                 _INFO("[MSG_REQUEST_OPEN_CHANNEL]");
217
218                                 response.param1 = IntegerHandle::INVALID_HANDLE;
219                                 response.param2 = 0;
220                                 response.data.clear();
221
222                                 try
223                                 {
224                                         unsigned int channelID = IntegerHandle::INVALID_HANDLE;
225
226                                         channelID = resource->createChannel(socket, msg->error/* service context */, msg->param2, msg->param1, msg->data);
227                                         if (channelID != IntegerHandle::INVALID_HANDLE)
228                                         {
229                                                 ServerChannel *temp;
230
231                                                 temp = (ServerChannel *)resource->getChannel(socket, msg->error/* service context */, channelID);
232                                                 if (temp != NULL)
233                                                 {
234                                                         response.param1 = channelID;
235                                                         response.param2 = temp->getChannelNumber();
236                                                         response.error = SCARD_ERROR_OK;
237                                                         response.data = temp->getSelectResponse();
238                                                 }
239                                                 else
240                                                 {
241                                                         _ERR("IS IT POSSIBLE??????????????????");
242                                                         response.error = SCARD_ERROR_UNKNOWN;
243                                                 }
244                                         }
245                                         else
246                                         {
247                                                 _ERR("channel is null.");
248
249                                                 /* set error value */
250                                                 response.error = SCARD_ERROR_UNAVAILABLE;
251                                         }
252                                 }
253                                 catch (ExceptionBase &e)
254                                 {
255                                         response.error = e.getErrorCode();
256                                 }
257
258                                 /* response to client */
259                                 ServerIPC::getInstance()->sendMessage(socket, response);
260                         }
261                         break;
262
263                 case Message::MSG_REQUEST_GET_CHANNEL_COUNT :
264                         {
265                                 Message response(*msg);
266
267                                 _INFO("[MSG_REQUEST_GET_CHANNEL_COUNT]");
268
269                                 response.error = SCARD_ERROR_OK;
270                                 response.param1 = resource->getChannelCount(socket, msg->error/* service context */, msg->param1);
271
272                                 /* response to client */
273                                 ServerIPC::getInstance()->sendMessage(socket, response);
274                         }
275                         break;
276
277                 case Message::MSG_REQUEST_CLOSE_CHANNEL :
278                         {
279                                 Message response(*msg);
280
281                                 _INFO("[MSG_REQUEST_CLOSE_CHANNEL]");
282
283                                 response.error = SCARD_ERROR_OK;
284
285                                 if (resource->getChannel(socket, msg->error/* service context */, msg->param1) != NULL)
286                                 {
287                                         resource->removeChannel(socket, msg->error/* service context */, msg->param1);
288                                 }
289
290                                 /* response to client */
291                                 ServerIPC::getInstance()->sendMessage(socket, response);
292                         }
293                         break;
294
295                 case Message::MSG_REQUEST_GET_ATR :
296                         {
297                                 int rv;
298                                 Message response(*msg);
299                                 ByteArray result;
300                                 ServiceInstance *client = NULL;
301
302                                 _INFO("[MSG_REQUEST_GET_ATR]");
303
304                                 if ((client = resource->getService(socket, msg->error/* service context */)) != NULL)
305                                 {
306                                         Terminal *terminal = NULL;
307
308                                         if ((terminal = client->getTerminal(msg->param1)) != NULL)
309                                         {
310                                                 if ((rv = terminal->getATRSync(result)) == 0)
311                                                 {
312                                                         response.data = result;
313                                                         response.error = SCARD_ERROR_OK;
314                                                 }
315                                                 else
316                                                 {
317                                                         _ERR("transmit failed [%d]", rv);
318
319                                                         response.error = rv;
320                                                 }
321                                         }
322                                         else
323                                         {
324                                                 _ERR("getTerminal failed : socket [%d], context [%d], session [%d]", socket, msg->error/* service context */, msg->param1);
325                                                 response.error = SCARD_ERROR_UNAVAILABLE;
326                                         }
327                                 }
328                                 else
329                                 {
330                                         _ERR("getClient failed : socket [%d], context [%d], session [%d]", socket, msg->error/* service context */, msg->param1);
331                                         response.error = SCARD_ERROR_UNAVAILABLE;
332                                 }
333
334                                 /* response to client */
335                                 ServerIPC::getInstance()->sendMessage(socket, response);
336                         }
337                         break;
338
339                 case Message::MSG_REQUEST_TRANSMIT :
340                         {
341                                 int rv;
342                                 Message response(*msg);
343                                 ByteArray result;
344                                 Channel *channel = NULL;
345
346                                 _INFO("[MSG_REQUEST_TRANSMIT]");
347
348                                 if ((channel = resource->getChannel(socket, msg->error/* service context */, msg->param1)) != NULL)
349                                 {
350                                         if ((rv = channel->transmitSync(msg->data, result)) == 0)
351                                         {
352                                                 response.data = result;
353                                                 response.error = SCARD_ERROR_OK;
354                                         }
355                                         else
356                                         {
357                                                 _ERR("transmit failed [%d]", rv);
358
359                                                 response.error = rv;
360                                         }
361                                 }
362                                 else
363                                 {
364                                         _ERR("invalid handle : socket [%d], context [%d], channel [%d]", socket, msg->error/* service context */, msg->param1);
365                                         response.error = SCARD_ERROR_UNAVAILABLE;
366                                 }
367
368                                 /* response to client */
369                                 ServerIPC::getInstance()->sendMessage(socket, response);
370                         }
371                         break;
372
373                 case Message::MSG_OPERATION_RELEASE_CLIENT :
374                         {
375                                 _INFO("[MSG_OPERATION_RELEASE_CLIENT]");
376
377                                 resource->removeClient(msg->param1);
378                                 _DBG("remain client [%d]", resource->getClientCount());
379                         }
380 #ifdef USE_AUTOSTART
381                         if (resource->getClientCount() == 0)
382                         {
383                                 _INFO("There is no client. shutting down service");
384                                 g_main_loop_quit((GMainLoop *)resource->getMainLoopInstance());
385                         }
386 #endif
387                         break;
388
389                 default :
390                         _DBG("unknown message [%s], socket [%d]", msg->toString().c_str(), socket);
391                         break;
392                 }
393
394                 return NULL;
395         }
396
397 } /* namespace smartcard_service_api */
398 #endif