5a21e2331c1e07a195650f58e65d66cc7a77c271
[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 #include <glib-object.h>
22
23 /* local header */
24 #include "Debug.h"
25 #include "SEService.h"
26 #include "ClientChannel.h"
27 #include "Reader.h"
28 #include "ClientGDBus.h"
29
30 #ifndef EXTERN_API
31 #define EXTERN_API __attribute__((visibility("default")))
32 #endif
33
34 #define SHUTDOWN_DELAY          500000 /* us */
35 #define VERSION "3.0"
36
37 namespace smartcard_service_api
38 {
39         SEService::SEService() : SEServiceHelper(),
40                 handle(-1), context(NULL), handler(NULL), listener(NULL),
41                 version(VERSION)
42         {
43                 proxy = NULL;
44         }
45
46         SEService::SEService(void *user_data, serviceConnected handler)
47                 throw(ErrorIO &, ErrorIllegalParameter &) :
48                 SEServiceHelper(), handle(-1),
49                 listener(NULL), version(VERSION)
50         {
51                 initialize(user_data, handler);
52         }
53
54         SEService::SEService(void *user_data, SEServiceListener *listener)
55                 throw(ErrorIO &, ErrorIllegalParameter &) :
56                 SEServiceHelper(), handle(-1),
57                 handler(NULL), version(VERSION)
58         {
59                 initialize(user_data, listener);
60         }
61
62         SEService::SEService(void *user_data)
63                 throw(ErrorIO &, ErrorIllegalParameter &, ExceptionBase &) :
64                 SEServiceHelper(), handle(-1),
65                 handler(NULL), version(VERSION)
66         {
67                 initializeSync(user_data);
68         }
69
70         SEService::~SEService()
71         {
72                 try
73                 {
74                         size_t i;
75
76                         shutdownSync();
77
78                         for (i = 0; i < readers.size(); i++)
79                         {
80                                 delete (Reader *)readers[i];
81                         }
82
83                         readers.clear();
84                 }
85                 catch (ExceptionBase &e)
86                 {
87                         _ERR("EXCEPTION : %s", e.what());
88                 }
89                 catch (...)
90                 {
91                         _ERR("EXCEPTION!!!");
92                 }
93         }
94
95         SEService *SEService::createInstance(void *user_data,
96                 SEServiceListener *listener)
97                 throw(ErrorIO &, ErrorIllegalParameter &)
98         {
99                 return new SEService(user_data, listener);
100         }
101
102         SEService *SEService::createInstance(void *user_data,
103                 serviceConnected handler)
104                 throw(ErrorIO &, ErrorIllegalParameter &)
105         {
106                 return new SEService(user_data, handler);
107         }
108
109         void SEService::reader_inserted(GObject *source_object,
110                 guint reader_id, gchar *reader_name, gpointer user_data)
111         {
112                 Reader *reader = NULL;
113                 SEService *service = (SEService *)user_data;
114
115                 _INFO("[MSG_NOTIFY_SE_INSERTED]");
116
117                 /* add readers */
118                 reader = new Reader(service->context,
119                         reader_name, GUINT_TO_POINTER(reader_id));
120                 if (reader != NULL)
121                 {
122                         service->readers.push_back(reader);
123                 }
124                 else
125                 {
126                         _ERR("alloc failed");
127                 }
128
129                 if (service->listener != NULL)
130                 {
131                         service->listener->eventHandler(service,
132                                 reader_name, 1, service->context);
133                 }
134                 else
135                 {
136                         _DBG("listener is null");
137                 }
138         }
139
140         void SEService::reader_removed(GObject *source_object,
141                 guint reader_id, gchar *reader_name, gpointer user_data)
142         {
143                 SEService *service = (SEService *)user_data;
144                 size_t i;
145
146                 _INFO("[MSG_NOTIFY_SE_REMOVED]");
147
148                 for (i = 0; i < service->readers.size(); i++)
149                 {
150                         if (((Reader *)service->readers[i])->handle ==
151                                 GUINT_TO_POINTER(reader_id))
152                         {
153                                 ((Reader *)service->readers[i])->unavailable();
154                                 break;
155                         }
156                 }
157
158                 if (service->listener != NULL)
159                 {
160                         service->listener->eventHandler(service,
161                                 reader_name, 2, service->context);
162                 }
163                 else
164                 {
165                         _DBG("listener is null");
166                 }
167         }
168
169         void SEService::se_service_shutdown_cb(GObject *source_object,
170                 GAsyncResult *res, gpointer user_data)
171         {
172                 SEService *service = (SEService *)user_data;
173                 gint result;
174                 GError *error = NULL;
175
176                 if (smartcard_service_se_service_call_shutdown_finish(
177                         SMARTCARD_SERVICE_SE_SERVICE(source_object),
178                         &result, res, &error) == true) {
179                         if (result == SCARD_ERROR_OK) {
180                                 service->connected = false;
181                         } else {
182                                 _ERR("smartcard_service_se_service_call_shutdown failed, [%d]", result);
183                         }
184                 } else {
185                         _ERR("smartcard_service_se_service_call_shutdown failed, [%s]", error->message);
186                         g_error_free(error);
187                 }
188         }
189
190         void SEService::se_service_cb(GObject *source_object,
191                 GAsyncResult *res, gpointer user_data)
192         {
193                 SEService *service = (SEService *)user_data;
194                 gint result;
195                 guint handle;
196                 GVariant *readers = NULL;
197                 GError *error = NULL;
198
199                 if (service == NULL) {
200                         _ERR("null parameter!!!");
201                         return;
202                 }
203
204                 if (smartcard_service_se_service_call_se_service_finish(
205                         SMARTCARD_SERVICE_SE_SERVICE(source_object),
206                         &result, &handle, &readers, res, &error) == true) {
207                         if (result == SCARD_ERROR_OK) {
208                                 service->connected = true;
209                                 service->handle = handle;
210                                 service->parseReaderInformation(readers);
211                         }
212                 } else {
213                         _ERR("smartcard_service_se_service_call_se_service failed, [%s]", error->message);
214                         g_error_free(error);
215
216                         result = SCARD_ERROR_IPC_FAILED;
217                 }
218
219                 if (service->handler != NULL) {
220                         service->handler(service, service->context);
221                 } else if (service->listener != NULL) {
222                         if (result == SCARD_ERROR_OK) {
223                                 service->listener->serviceConnected(service, service->context);
224                         } else {
225                                 service->listener->errorHandler(service, result, service->context);
226                         }
227                 }
228         }
229
230         void SEService::shutdown()
231         {
232                 shutdownSync();
233         }
234
235         void SEService::shutdownSync()
236         {
237                 if (connected == true)
238                 {
239                         uint32_t i;
240
241                         for (i = 0; i < readers.size(); i++)
242                         {
243                                 readers[i]->closeSessions();
244                         }
245
246                         gint result;
247                         GError *error = NULL;
248
249                         if (smartcard_service_se_service_call_shutdown_sync(
250                                 (SmartcardServiceSeService *)proxy,
251                                 handle,
252                                 &result,
253                                 NULL,
254                                 &error) == false) {
255                                 _ERR("smartcard_service_se_service_call_shutdown_sync failed, [%s]", error->message);
256
257                                 g_error_free(error);
258                         }
259
260                         /* wait at least 500ms */
261                         usleep(SHUTDOWN_DELAY);
262
263                         connected = false;
264                 }
265         }
266
267         bool SEService::_initialize() throw(ErrorIO &)
268         {
269                 bool result = false;
270
271                 _BEGIN();
272
273                 /* init default context */
274                 GError *error = NULL;
275
276                 proxy = smartcard_service_se_service_proxy_new_for_bus_sync(
277                         G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
278                         "org.tizen.SmartcardService",
279                         "/org/tizen/SmartcardService/SeService",
280                         NULL, &error);
281                 if (proxy == NULL)
282                 {
283                         _ERR("Can not create proxy : %s", error->message);
284                         g_error_free(error);
285                         return false;
286                 }
287
288                 g_signal_connect(proxy, "reader-inserted",
289                                 G_CALLBACK(&SEService::reader_inserted), this);
290
291                 g_signal_connect(proxy, "reader-removed",
292                                 G_CALLBACK(&SEService::reader_removed), this);
293
294                 /* request reader */
295                 smartcard_service_se_service_call_se_service(
296                         (SmartcardServiceSeService *)proxy,
297                         NULL,
298                         &SEService::se_service_cb,
299                         this);
300
301                 _END();
302
303                 return result;
304         }
305
306         int SEService::_initialize_sync_do_not_throw_exception()
307         {
308                 gint result;
309                 guint handle;
310                 GError *error = NULL;
311                 GVariant *readers = NULL;
312                 SEService *service = (SEService *)this;
313
314                 _BEGIN();
315
316                 /* init default context */
317
318                 proxy = smartcard_service_se_service_proxy_new_for_bus_sync(
319                         G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
320                         "org.tizen.SmartcardService",
321                         "/org/tizen/SmartcardService/SeService",
322                         NULL, &error);
323                 if (proxy == NULL)
324                 {
325                         _ERR("Can not create proxy : %s", error->message);
326                         g_error_free(error);
327                         return false;
328                 }
329
330                 g_signal_connect(proxy, "reader-inserted",
331                                 G_CALLBACK(&SEService::reader_inserted), this);
332
333                 g_signal_connect(proxy, "reader-removed",
334                                 G_CALLBACK(&SEService::reader_removed), this);
335
336                 /* request reader */
337                 if(smartcard_service_se_service_call_se_service_sync(
338                         (SmartcardServiceSeService *)proxy, &result, &handle, &readers, NULL, &error) == true)
339                 {
340                         if (result == SCARD_ERROR_OK)
341                         {
342                                 service->connected = true;
343                                 service->handle = handle;
344                                 service->parseReaderInformation(readers);
345                         }
346                         else
347                         {
348                                 _ERR("Initialize error : %d", result);
349                         }
350                 }
351
352                 if (service->handler != NULL) {
353                         service->handler(service, service->context);
354                 } else if (service->listener != NULL) {
355                         if (result == SCARD_ERROR_OK) {
356                                 service->listener->serviceConnected(service, service->context);
357                         } else {
358                                 service->listener->errorHandler(service, result, service->context);
359                         }
360                 }
361
362                 _END();
363
364                 return result;
365         }
366
367         int SEService::_initialize_sync() throw(ErrorIO &, ExceptionBase &)
368         {
369                 gint result;
370                 guint handle;
371                 GError *error = NULL;
372                 GVariant *readers = NULL;
373                 SEService *service = (SEService *)this;
374
375                 _BEGIN();
376
377                 /* init default context */
378
379                 proxy = smartcard_service_se_service_proxy_new_for_bus_sync(
380                         G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
381                         "org.tizen.SmartcardService",
382                         "/org/tizen/SmartcardService/SeService",
383                         NULL, &error);
384                 if (proxy == NULL)
385                 {
386                         _ERR("Can not create proxy : %s", error->message);
387                         g_error_free(error);
388                         return false;
389                 }
390
391                 g_signal_connect(proxy, "reader-inserted",
392                                 G_CALLBACK(&SEService::reader_inserted), this);
393
394                 g_signal_connect(proxy, "reader-removed",
395                                 G_CALLBACK(&SEService::reader_removed), this);
396
397                 /* request reader */
398                 if(smartcard_service_se_service_call_se_service_sync(
399                         (SmartcardServiceSeService *)proxy, &result, &handle, &readers, NULL, &error) == true)
400                 {
401                         if (result == SCARD_ERROR_OK)
402                         {
403                                 service->connected = true;
404                                 service->handle = handle;
405                                 service->parseReaderInformation(readers);
406                         }
407                         else
408                         {
409                                 throw ExceptionBase(result);
410                         }
411                 }
412                 else
413                 {
414                         _ERR("smartcard_service_se_service_call_se_service failed, [%s]", error->message);
415                         g_error_free(error);
416
417                         result = SCARD_ERROR_IPC_FAILED;
418                 }
419
420                 _END();
421
422                 return result;
423         }
424
425         bool SEService::initialize(void *context, serviceConnected handler)
426                 throw(ErrorIO &, ErrorIllegalParameter &)
427         {
428                 if (context == NULL)
429                 {
430                         throw ErrorIllegalParameter(SCARD_ERROR_ILLEGAL_PARAM);
431                 }
432
433                 this->context = context;
434                 this->handler = handler;
435
436                 return _initialize();
437         }
438
439         bool SEService::initialize(void *context, SEServiceListener *listener)
440                 throw(ErrorIO &, ErrorIllegalParameter &)
441         {
442                 if (context == NULL)
443                 {
444                         throw ErrorIllegalParameter(SCARD_ERROR_ILLEGAL_PARAM);
445                 }
446
447                 this->context = context;
448                 this->listener = listener;
449
450                 return _initialize_sync_do_not_throw_exception();
451         }
452
453         bool SEService::initializeSync(void *context)
454                 throw(ErrorIO &, ErrorIllegalParameter &, ExceptionBase &)
455         {
456                 this->context = context;
457
458                 _initialize_sync();
459                 return true;
460         }
461
462         bool SEService::parseReaderInformation(GVariant *variant)
463         {
464                 Reader *reader = NULL;
465
466                 GVariantIter *iter;
467                 guint handle;
468                 gchar *name;
469
470                 g_variant_get(variant, "a(us)", &iter);
471
472                 while (g_variant_iter_loop(iter, "(us)", &handle, &name) == true)
473                 {
474                         SECURE_LOGD("Reader : name [%s], handle [%08x]", name, handle);
475
476                         /* add readers */
477                         reader = new Reader((void *)this->handle, name, GUINT_TO_POINTER(handle));
478                         if (reader == NULL)
479                         {
480                                 _ERR("alloc failed");
481                                 continue;
482                         }
483
484                         readers.push_back(reader);
485                 }
486
487                 g_variant_iter_free(iter);
488
489                 return true;
490         }
491
492         bool SEService::parseReaderInformation(unsigned int count,
493                 const ByteArray &data)
494         {
495                 size_t i;
496                 unsigned int offset = 0;
497                 unsigned int len = 0;
498                 void *handle = NULL;
499                 Reader *reader = NULL;
500                 char name[100];
501                 const uint8_t *buffer = NULL;
502
503
504                 for (i = 0; i < count && offset < data.size(); i++)
505                 {
506                         memset(name, 0, sizeof(name));
507
508                         buffer = data.getBuffer(offset);
509                         if(buffer == NULL)
510                                 continue;
511
512                         memcpy(&len, buffer, sizeof(len));
513                         offset += sizeof(len);
514
515                         buffer = data.getBuffer(offset);
516                         if(buffer == NULL)
517                                 return false;
518
519                         memcpy(name, buffer, len);
520                         offset += len;
521
522                         buffer = data.getBuffer(offset);
523                         if(buffer == NULL)
524                                 return false;
525
526                         memcpy(&handle, buffer, sizeof(handle));
527                         offset += sizeof(handle);
528
529                         SECURE_LOGD("Reader [%d] : name [%s], handle [%p]", i, name, handle);
530
531                         /* add readers */
532                         reader = new Reader(context, name, handle);
533                         if (reader == NULL)
534                         {
535                                 _ERR("alloc failed");
536                                 continue;
537                         }
538
539                         readers.push_back(reader);
540                 }
541
542                 return true;
543         }
544 } /* namespace smartcard_service_api */
545
546 /* export C API */
547 #define SE_SERVICE_EXTERN_BEGIN \
548         if (handle != NULL) \
549         { \
550                 SEService *service = (SEService *)handle;
551
552 #define SE_SERVICE_EXTERN_END \
553         } \
554         else \
555         { \
556                 _ERR("Invalid param"); \
557         }
558
559 using namespace smartcard_service_api;
560
561 EXTERN_API se_service_h se_service_create_instance(void *user_data,
562         se_service_connected_cb callback)
563 {
564         SEService *service;
565
566         try
567         {
568                 service = new SEService(user_data, (serviceConnected)callback);
569         }
570         catch (...)
571         {
572                 service = NULL;
573         }
574
575         return (se_service_h)service;
576 }
577
578 EXTERN_API se_service_h se_service_create_instance_with_event_callback(
579         void *user_data, se_service_connected_cb connected,
580         se_service_event_cb event, se_sesrvice_error_cb error)
581 {
582         SEService *service;
583
584         try
585         {
586                 service = new SEService(user_data, (serviceConnected)connected);
587         }
588         catch (...)
589         {
590                 service = NULL;
591         }
592
593         return (se_service_h)service;
594 }
595
596 EXTERN_API se_service_h se_service_create_instance_sync(void *user_data,
597         int *result)
598 {
599         SEService *service;
600
601         try
602         {
603                 service = new SEService(user_data);
604         }
605         catch (ExceptionBase &e)
606         {
607                 *result = e.getErrorCode();
608                 service = NULL;
609         }
610         catch (...)
611         {
612                 *result = SCARD_ERROR_UNKNOWN;
613                 service = NULL;
614         }
615
616         return (se_service_h)service;
617 }
618
619 EXTERN_API int se_service_get_version(se_service_h handle, char **version_str)
620 {
621         int ret = 0;
622
623         if (version_str == NULL) {
624                 return SCARD_ERROR_ILLEGAL_PARAM;
625         }
626
627         SE_SERVICE_EXTERN_BEGIN;
628
629         *version_str = g_strdup(service->getVersion());
630
631         SE_SERVICE_EXTERN_END;
632
633         return ret;
634 }
635
636 EXTERN_API int se_service_get_readers_count(se_service_h handle)
637 {
638         int count = 0;
639
640         SE_SERVICE_EXTERN_BEGIN;
641
642         vector<ReaderHelper *> temp_readers;
643
644         temp_readers = service->getReaders();
645         count = temp_readers.size();
646
647         SE_SERVICE_EXTERN_END;
648
649         return count;
650 }
651
652 EXTERN_API int se_service_get_readers(se_service_h handle, int **readers, int *count)
653 {
654         int result = 0;
655
656         SE_SERVICE_EXTERN_BEGIN;
657
658         vector<ReaderHelper *> temp_readers;
659         size_t i;
660         int temp = 0;
661
662         temp_readers = service->getReaders();
663         if(temp_readers.size() > 0)
664         {
665                 *readers = (int *)calloc(temp_readers.size(), sizeof(int));
666
667                 if(*readers == NULL)
668                 {
669                         *count = 0;
670                         return SCARD_ERROR_NOT_ENOUGH_RESOURCE;
671                 }
672
673                 for (i = 0; i < temp_readers.size(); i++)
674                 {
675                         if (temp_readers[i]->isSecureElementPresent())
676                         {
677                                 (*readers)[i] = (long)temp_readers[i];
678                                 temp++;
679                         }
680                 }
681                 *count = temp;
682         }
683
684         SE_SERVICE_EXTERN_END;
685
686         return result;
687 }
688
689 EXTERN_API bool se_service_is_connected(se_service_h handle)
690 {
691         bool result = false;
692
693         SE_SERVICE_EXTERN_BEGIN;
694
695         result = service->isConnected();
696
697         SE_SERVICE_EXTERN_END;
698
699         return result;
700 }
701
702 EXTERN_API void se_service_shutdown(se_service_h handle)
703 {
704         SE_SERVICE_EXTERN_BEGIN;
705
706         service->shutdownSync();
707
708         SE_SERVICE_EXTERN_END;
709 }
710
711 EXTERN_API int se_service_destroy_instance(se_service_h handle)
712 {
713         int result = 0;
714
715         SE_SERVICE_EXTERN_BEGIN;
716
717         delete service;
718
719         SE_SERVICE_EXTERN_END;
720
721         return result;
722 }