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