Return error code
[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 long)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 long)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                         throw ErrorIllegalParameter(SCARD_ERROR_ILLEGAL_PARAM);
235                 }
236
237                 this->context = context;
238                 this->handler = handler;
239
240                 return _initialize();
241         }
242
243         bool SEService::initialize(void *context, SEServiceListener *listener)
244                 throw(ErrorIO &, ErrorIllegalParameter &)
245         {
246                 if (context == NULL)
247                 {
248                         throw ErrorIllegalParameter(SCARD_ERROR_ILLEGAL_PARAM);
249                 }
250
251                 this->context = context;
252                 this->listener = listener;
253
254                 return _initialize();
255         }
256
257         bool SEService::parseReaderInformation(unsigned int count, ByteArray data)
258         {
259                 size_t i;
260                 unsigned int offset = 0;
261                 unsigned int len = 0;
262                 void *handle = NULL;
263                 Reader *reader = NULL;
264                 char name[100];
265
266                 for (i = 0; i < count && offset < data.getLength(); i++)
267                 {
268                         memset(name, 0, sizeof(name));
269
270                         memcpy(&len, data.getBuffer(offset), sizeof(len));
271                         offset += sizeof(len);
272
273                         memcpy(name, data.getBuffer(offset), len);
274                         offset += len;
275
276                         memcpy(&handle, data.getBuffer(offset), sizeof(handle));
277                         offset += sizeof(handle);
278
279                         SCARD_DEBUG("Reader [%d] : name [%s], handle [%p]", i, name, handle);
280
281                         /* add readers */
282                         reader = new Reader(context, name, handle);
283                         if (reader == NULL)
284                         {
285                                 SCARD_DEBUG_ERR("alloc failed");
286                                 continue;
287                         }
288
289                         readers.push_back(reader);
290                 }
291
292                 return true;
293         }
294
295         bool SEService::dispatcherCallback(void *message)
296         {
297                 Message *msg = (Message *)message;
298                 SEService *service = NULL;
299                 bool result = false;
300
301                 SCARD_BEGIN();
302
303                 if (msg == NULL)
304                 {
305                         SCARD_DEBUG_ERR("message is null");
306                         return result;
307                 }
308
309                 service = (SEService *)msg->caller;
310
311                 switch (msg->message)
312                 {
313                 case Message::MSG_REQUEST_READERS :
314                         SCARD_DEBUG("[MSG_REQUEST_READERS]");
315
316                         service->connected = true;
317
318                         /* parse message data */
319                         service->parseReaderInformation(msg->param1, msg->data);
320
321                         /* call callback function */
322                         if (service->listener != NULL)
323                         {
324                                 service->listener->serviceConnected(service, service->context);
325                         }
326                         else if (service->handler != NULL)
327                         {
328                                 service->handler(service, service->context);
329                         }
330                         break;
331
332                 case Message::MSG_REQUEST_SHUTDOWN :
333                         SCARD_DEBUG("[MSG_REQUEST_SHUTDOWN]");
334
335                         if (msg->isSynchronousCall() == true) /* synchronized call */
336                         {
337                                 /* sync call */
338                                 service->syncLock();
339
340                                 /* copy result */
341 //                              service->error = msg->error;
342                                 service->signalCondition();
343                                 service->syncUnlock();
344                         }
345                         else
346                         {
347                                 /* Do nothing... */
348                         }
349                         break;
350
351                 case Message::MSG_NOTIFY_SE_INSERTED :
352                         {
353                                 Reader *reader = NULL;
354
355                                 SCARD_DEBUG("[MSG_NOTIFY_SE_INSERTED]");
356
357                                 /* add readers */
358                                 reader = new Reader(service->context,
359                                         (char *)msg->data.getBuffer(), (void *)msg->param1);
360                                 if (reader != NULL)
361                                 {
362                                         service->readers.push_back(reader);
363                                 }
364                                 else
365                                 {
366                                         SCARD_DEBUG_ERR("alloc failed");
367                                 }
368
369                                 if (service->listener != NULL)
370                                 {
371                                         service->listener->eventHandler(service,
372                                                 (char *)msg->data.getBuffer(), 1, service->context);
373                                 }
374                                 else
375                                 {
376                                         SCARD_DEBUG("listener is null");
377                                 }
378                         }
379                         break;
380
381                 case Message::MSG_NOTIFY_SE_REMOVED :
382                         {
383                                 size_t i;
384
385                                 SCARD_DEBUG("[MSG_NOTIFY_SE_REMOVED]");
386
387                                 for (i = 0; i < service->readers.size(); i++)
388                                 {
389                                         if (((Reader *)service->readers[i])->handle == (void *)msg->param1)
390                                         {
391                                                 ((Reader *)service->readers[i])->present = false;
392                                                 break;
393                                         }
394                                 }
395
396                                 if (service->listener != NULL)
397                                 {
398                                         service->listener->eventHandler(service,
399                                                 (char *)msg->data.getBuffer(), 2, service->context);
400                                 }
401                                 else
402                                 {
403                                         SCARD_DEBUG("listener is null");
404                                 }
405                         }
406                         break;
407
408                 case Message::MSG_OPERATION_RELEASE_CLIENT :
409                         SCARD_DEBUG("[MSG_OPERATION_RELEASE_CLIENT]");
410
411                         if (service->listener != NULL)
412                         {
413                                 service->listener->errorHandler(service, msg->error, service->context);
414
415                                 ClientDispatcher::getInstance().removeSEService(service->context);
416                                 service->connected = false;
417                         }
418                         else
419                         {
420                                 SCARD_DEBUG_ERR("service->listener is null");
421                         }
422                         break;
423
424                 default :
425                         SCARD_DEBUG("unknown message [%s]", msg->toString());
426                         break;
427                 }
428
429                 SCARD_END();
430
431                 return result;
432         }
433
434 } /* namespace smartcard_service_api */
435
436 /* export C API */
437 #define SE_SERVICE_EXTERN_BEGIN \
438         if (handle != NULL) \
439         { \
440                 SEService *service = (SEService *)handle;
441
442 #define SE_SERVICE_EXTERN_END \
443         } \
444         else \
445         { \
446                 SCARD_DEBUG_ERR("Invalid param"); \
447         }
448
449 using namespace smartcard_service_api;
450
451 EXTERN_API se_service_h se_service_create_instance(void *user_data, se_service_connected_cb callback)
452 {
453         SEService *service;
454
455         try
456         {
457                 service = new SEService(user_data, (serviceConnected)callback);
458         }
459         catch (...)
460         {
461                 service = NULL;
462         }
463
464         return (se_service_h)service;
465 }
466
467 EXTERN_API se_service_h se_service_create_instance_with_event_callback(void *user_data,
468         se_service_connected_cb connected, se_service_event_cb event, se_sesrvice_error_cb error)
469 {
470         SEService *service;
471
472         try
473         {
474                 service = new SEService(user_data, (serviceConnected)connected);
475         }
476         catch (...)
477         {
478                 service = NULL;
479         }
480
481         return (se_service_h)service;
482 }
483
484 EXTERN_API int se_service_get_readers_count(se_service_h handle)
485 {
486         int count = 0;
487
488         SE_SERVICE_EXTERN_BEGIN;
489
490         vector<ReaderHelper *> temp_readers;
491
492         temp_readers = service->getReaders();
493         count = temp_readers.size();
494
495         SE_SERVICE_EXTERN_END;
496
497         return count;
498 }
499
500 EXTERN_API bool se_service_get_readers(se_service_h handle, reader_h *readers, int *count)
501 {
502         bool result = false;
503
504         SE_SERVICE_EXTERN_BEGIN;
505
506         vector<ReaderHelper *> temp_readers;
507         size_t i;
508         int temp = 0;
509
510         temp_readers = service->getReaders();
511
512         for (i = 0; i < temp_readers.size() && i < (size_t)*count; i++)
513         {
514                 if (temp_readers[i]->isSecureElementPresent())
515                 {
516                         readers[i] = (reader_h)temp_readers[i];
517                         temp++;
518                 }
519         }
520         *count = temp;
521
522         SE_SERVICE_EXTERN_END;
523
524         return result;
525 }
526
527 EXTERN_API bool se_service_is_connected(se_service_h handle)
528 {
529         bool result = false;
530
531         SE_SERVICE_EXTERN_BEGIN;
532
533         result = service->isConnected();
534
535         SE_SERVICE_EXTERN_END;
536
537         return result;
538 }
539
540 EXTERN_API void se_service_shutdown(se_service_h handle)
541 {
542         SE_SERVICE_EXTERN_BEGIN;
543
544         service->shutdown();
545
546         SE_SERVICE_EXTERN_END;
547 }
548
549 EXTERN_API void se_service_destroy_instance(se_service_h handle)
550 {
551         SE_SERVICE_EXTERN_BEGIN;
552
553         delete service;
554
555         SE_SERVICE_EXTERN_END;
556 }