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