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