2cb27e8ba474418f081d24cdcdbe3f77ee0514fe
[platform/core/connectivity/smartcard-service.git] / client / SEService.cpp
1 /*
2  * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
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 <unistd.h>
19 #include <string.h>
20 #include <glib.h>
21
22 /* SLP library header */
23
24 /* local header */
25 #include "Debug.h"
26 #include "ClientIPC.h"
27 #include "ClientDispatcher.h"
28 #include "SEService.h"
29 #include "Reader.h"
30 #include "Message.h"
31
32 #ifndef EXTERN_API
33 #define EXTERN_API __attribute__((visibility("default")))
34 #endif
35
36 namespace smartcard_service_api
37 {
38         SEService::SEService() :
39                 SEServiceHelper()
40         {
41                 this->context = NULL;
42                 this->handler = NULL;
43                 this->listener = NULL;
44                 connected = false;
45         }
46
47         SEService::SEService(void *user_data, serviceConnected handler)
48                 throw(ErrorIO &, ErrorIllegalParameter &) :
49                 SEServiceHelper()
50         {
51                 this->listener = NULL;
52                 connected = false;
53
54                 initialize(user_data, handler);
55         }
56
57         SEService::SEService(void *user_data, SEServiceListener *listener)
58                 throw(ErrorIO &, ErrorIllegalParameter &) :
59                 SEServiceHelper()
60         {
61                 this->handler = NULL;
62                 connected = false;
63
64                 initialize(user_data, listener);
65         }
66
67         SEService::~SEService()
68         {
69                 uint32_t i;
70
71                 try
72                 {
73                         shutdownSync();
74                 }
75                 catch(ExceptionBase &e)
76                 {
77                         SCARD_DEBUG_ERR("EXCEPTION : %s", e.what());
78                 }
79                 catch(...)
80                 {
81                         SCARD_DEBUG_ERR("EXCEPTION!!!");
82                 }
83
84                 for (i = 0; i < readers.size(); i++)
85                 {
86                         delete (Reader *)readers[i];
87                 }
88                 readers.clear();
89         }
90
91         SEService *SEService::createInstance(void *user_data, SEServiceListener *listener)
92                 throw(ErrorIO &, ErrorIllegalParameter &)
93         {
94                 return new SEService(user_data, listener);
95         }
96
97         SEService *SEService::createInstance(void *user_data, serviceConnected handler)
98                 throw(ErrorIO &, ErrorIllegalParameter &)
99         {
100                 return new SEService(user_data, handler);
101         }
102
103         void SEService::shutdown()
104         {
105                 if (connected == true)
106                 {
107                         uint32_t i;
108
109                         for (i = 0; i < readers.size(); i++)
110                         {
111                                 readers[i]->closeSessions();
112                         }
113
114                         Message msg;
115
116                         msg.message = Message::MSG_REQUEST_SHUTDOWN;
117                         msg.error = (unsigned int)this; /* using error to context */
118                         msg.caller = (void *)this;
119                         msg.callback = (void *)NULL;
120
121                         if (ClientIPC::getInstance().sendMessage(&msg) == false)
122                         {
123                                 SCARD_DEBUG_ERR("time over");
124                         }
125                 }
126         }
127
128         void SEService::shutdownSync()
129         {
130 #ifdef CLIENT_IPC_THREAD
131                 if (connected == true)
132                 {
133                         uint32_t i;
134
135                         for (i = 0; i < readers.size(); i++)
136                         {
137                                 readers[i]->closeSessions();
138                         }
139
140                         /* send message to load se */
141                         Message msg;
142
143                         msg.message = Message::MSG_REQUEST_SHUTDOWN;
144                         msg.error = (unsigned int)this; /* using error to context */
145                         msg.caller = (void *)this;
146                         msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
147
148                         syncLock();
149                         if (ClientIPC::getInstance().sendMessage(&msg) == true)
150                         {
151                                 int rv;
152
153                                 rv = waitTimedCondition(0);
154
155                                 if (rv == 0)
156                                 {
157                                         ClientDispatcher::getInstance().removeSEService(context);
158
159                                         connected = false;
160                                 }
161                                 else
162                                 {
163                                         SCARD_DEBUG_ERR("time over");
164                                 }
165                         }
166                         else
167                         {
168                                 SCARD_DEBUG_ERR("sendMessage failed");
169                         }
170                         syncUnlock();
171                 }
172 #endif
173         }
174
175         bool SEService::_initialize() throw(ErrorIO &)
176         {
177                 bool result = false;
178                 ClientIPC *clientIPC;
179                 ClientDispatcher *clientDispatcher;
180
181                 SCARD_BEGIN();
182
183                 /* initialize client */
184                 if (!g_thread_supported())
185                 {
186                         g_thread_init(NULL);
187                 }
188
189                 clientDispatcher = &ClientDispatcher::getInstance();
190                 clientIPC = &ClientIPC::getInstance();
191
192                 clientIPC->setDispatcher(clientDispatcher);
193
194 #ifndef CLIENT_IPC_THREAD
195                 if (clientDispatcher->runDispatcherThread() == false)
196                 {
197                         SCARD_DEBUG_ERR("clientDispatcher->runDispatcherThread() failed");
198
199                         return result;
200                 }
201 #endif
202
203                 if (clientIPC->createConnectSocket() == false)
204                 {
205                         SCARD_DEBUG_ERR("clientIPC->createConnectSocket() failed");
206
207                         return result;
208                 }
209
210                 clientDispatcher->addSEService(context, this);
211
212                 {
213                         /* send message to load se */
214                         Message msg;
215
216                         msg.message = Message::MSG_REQUEST_READERS;
217                         msg.error = getpid(); /* using error to pid */
218                         msg.caller = (void *)this;
219                         msg.userParam = context;
220
221                         result = clientIPC->sendMessage(&msg);
222                 }
223
224                 SCARD_END();
225
226                 return result;
227         }
228
229         bool SEService::initialize(void *context, serviceConnected handler)
230                 throw(ErrorIO &, ErrorIllegalParameter &)
231         {
232                 if (context == NULL)
233                 {
234                         ErrorIllegalParameter e(0);
235
236                         throw e;
237                 }
238
239                 this->context = context;
240                 this->handler = handler;
241
242                 return _initialize();
243         }
244
245         bool SEService::initialize(void *context, SEServiceListener *listener)
246                 throw(ErrorIO &, ErrorIllegalParameter &)
247         {
248                 if (context == NULL)
249                 {
250                         ErrorIllegalParameter e(0);
251
252                         throw e;
253                 }
254
255                 this->context = context;
256                 this->listener = listener;
257
258                 return _initialize();
259         }
260
261         bool SEService::parseReaderInformation(unsigned int count, ByteArray data)
262         {
263                 size_t i;
264                 unsigned int offset = 0;
265                 unsigned int len = 0;
266                 void *handle = NULL;
267                 Reader *reader = NULL;
268                 char name[100];
269
270                 for (i = 0; i < count && offset < data.getLength(); i++)
271                 {
272                         memset(name, 0, sizeof(name));
273
274                         memcpy(&len, data.getBuffer(offset), sizeof(len));
275                         offset += sizeof(len);
276
277                         memcpy(name, data.getBuffer(offset), len);
278                         offset += len;
279
280                         memcpy(&handle, data.getBuffer(offset), sizeof(handle));
281                         offset += sizeof(handle);
282
283                         SCARD_DEBUG("Reader [%d] : name [%s], handle [%p]", i, name, handle);
284
285                         /* add readers */
286                         reader = new Reader(context, name, handle);
287                         if (reader == NULL)
288                         {
289                                 SCARD_DEBUG_ERR("alloc failed");
290                                 continue;
291                         }
292
293                         readers.push_back(reader);
294                 }
295
296                 return true;
297         }
298
299         bool SEService::dispatcherCallback(void *message)
300         {
301                 Message *msg = (Message *)message;
302                 SEService *service = NULL;
303                 bool result = false;
304
305                 SCARD_BEGIN();
306
307                 if (msg == NULL)
308                 {
309                         SCARD_DEBUG_ERR("message is null");
310                         return result;
311                 }
312
313                 service = (SEService *)msg->caller;
314
315                 switch (msg->message)
316                 {
317                 case Message::MSG_REQUEST_READERS :
318                         SCARD_DEBUG("[MSG_REQUEST_READERS]");
319
320                         service->connected = true;
321
322                         /* parse message data */
323                         service->parseReaderInformation(msg->param1, msg->data);
324
325                         /* call callback function */
326                         if (service->listener != NULL)
327                         {
328                                 service->listener->serviceConnected(service, service->context);
329                         }
330                         else if (service->handler != NULL)
331                         {
332                                 service->handler(service, service->context);
333                         }
334                         break;
335
336                 case Message::MSG_REQUEST_SHUTDOWN :
337                         SCARD_DEBUG("[MSG_REQUEST_SHUTDOWN]");
338
339                         if (msg->isSynchronousCall() == true) /* synchronized call */
340                         {
341                                 /* sync call */
342                                 service->syncLock();
343
344                                 /* copy result */
345 //                              service->error = msg->error;
346                                 service->signalCondition();
347                                 service->syncUnlock();
348                         }
349                         else
350                         {
351                                 /* Do nothing... */
352                         }
353                         break;
354
355                 case Message::MSG_NOTIFY_SE_INSERTED :
356                         {
357                                 Reader *reader = NULL;
358
359                                 SCARD_DEBUG("[MSG_NOTIFY_SE_INSERTED]");
360
361                                 /* add readers */
362                                 reader = new Reader(service->context,
363                                         (char *)msg->data.getBuffer(), (void *)msg->param1);
364                                 if (reader != NULL)
365                                 {
366                                         service->readers.push_back(reader);
367                                 }
368                                 else
369                                 {
370                                         SCARD_DEBUG_ERR("alloc failed");
371                                 }
372
373                                 if (service->listener != NULL)
374                                 {
375                                         service->listener->eventHandler(service,
376                                                 (char *)msg->data.getBuffer(), 1, service->context);
377                                 }
378                                 else
379                                 {
380                                         SCARD_DEBUG("listener is null");
381                                 }
382                         }
383                         break;
384
385                 case Message::MSG_NOTIFY_SE_REMOVED :
386                         {
387                                 size_t i;
388
389                                 SCARD_DEBUG("[MSG_NOTIFY_SE_REMOVED]");
390
391                                 for (i = 0; i < service->readers.size(); i++)
392                                 {
393                                         if (((Reader *)service->readers[i])->handle == (void *)msg->param1)
394                                         {
395                                                 ((Reader *)service->readers[i])->present = false;
396                                                 break;
397                                         }
398                                 }
399
400                                 if (service->listener != NULL)
401                                 {
402                                         service->listener->eventHandler(service,
403                                                 (char *)msg->data.getBuffer(), 2, service->context);
404                                 }
405                                 else
406                                 {
407                                         SCARD_DEBUG("listener is null");
408                                 }
409                         }
410                         break;
411
412                 case Message::MSG_OPERATION_RELEASE_CLIENT :
413                         SCARD_DEBUG("[MSG_OPERATION_RELEASE_CLIENT]");
414
415                         if (service->listener != NULL)
416                         {
417                                 service->listener->errorHandler(service, msg->error, service->context);
418
419                                 ClientDispatcher::getInstance().removeSEService(service->context);
420                                 service->connected = false;
421                         }
422                         else
423                         {
424                                 SCARD_DEBUG_ERR("service->listener is null");
425                         }
426                         break;
427
428                 default :
429                         SCARD_DEBUG("unknown message [%s]", msg->toString());
430                         break;
431                 }
432
433                 SCARD_END();
434
435                 return result;
436         }
437
438 } /* namespace smartcard_service_api */
439
440 /* export C API */
441 #define SE_SERVICE_EXTERN_BEGIN \
442         if (handle != NULL) \
443         { \
444                 SEService *service = (SEService *)handle;
445
446 #define SE_SERVICE_EXTERN_END \
447         } \
448         else \
449         { \
450                 SCARD_DEBUG_ERR("Invalid param"); \
451         }
452
453 using namespace smartcard_service_api;
454
455 EXTERN_API se_service_h se_service_create_instance(void *user_data, se_service_connected_cb callback)
456 {
457         SEService *service;
458
459         try
460         {
461                 service = new SEService(user_data, (serviceConnected)callback);
462         }
463         catch (...)
464         {
465                 service = NULL;
466         }
467
468         return (se_service_h)service;
469 }
470
471 EXTERN_API se_service_h se_service_create_instance_with_event_callback(void *user_data,
472         se_service_connected_cb connected, se_service_event_cb event, se_sesrvice_error_cb error)
473 {
474         SEService *service;
475
476         try
477         {
478                 service = new SEService(user_data, (serviceConnected)connected);
479         }
480         catch (...)
481         {
482                 service = NULL;
483         }
484
485         return (se_service_h)service;
486 }
487
488 EXTERN_API int se_service_get_readers_count(se_service_h handle)
489 {
490         int count = 0;
491
492         SE_SERVICE_EXTERN_BEGIN;
493
494         vector<ReaderHelper *> temp_readers;
495
496         temp_readers = service->getReaders();
497         count = temp_readers.size();
498
499         SE_SERVICE_EXTERN_END;
500
501         return count;
502 }
503
504 EXTERN_API bool se_service_get_readers(se_service_h handle, reader_h *readers, int *count)
505 {
506         bool result = false;
507
508         SE_SERVICE_EXTERN_BEGIN;
509
510         vector<ReaderHelper *> temp_readers;
511         size_t i;
512         int temp = 0;
513
514         temp_readers = service->getReaders();
515
516         for (i = 0; i < temp_readers.size() && i < (size_t)*count; i++)
517         {
518                 if (temp_readers[i]->isSecureElementPresent())
519                 {
520                         readers[i] = (reader_h)temp_readers[i];
521                         temp++;
522                 }
523         }
524         *count = temp;
525
526         SE_SERVICE_EXTERN_END;
527
528         return result;
529 }
530
531 EXTERN_API bool se_service_is_connected(se_service_h handle)
532 {
533         bool result = false;
534
535         SE_SERVICE_EXTERN_BEGIN;
536
537         result = service->isConnected();
538
539         SE_SERVICE_EXTERN_END;
540
541         return result;
542 }
543
544 EXTERN_API void se_service_shutdown(se_service_h handle)
545 {
546         SE_SERVICE_EXTERN_BEGIN;
547
548         service->shutdown();
549
550         SE_SERVICE_EXTERN_END;
551 }
552
553 EXTERN_API void se_service_destroy_instance(se_service_h handle)
554 {
555         SE_SERVICE_EXTERN_BEGIN;
556
557         delete service;
558
559         SE_SERVICE_EXTERN_END;
560 }