use gdbus
[platform/core/connectivity/smartcard-service.git] / client / Session.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 <stdio.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <string.h>
22
23 /* SLP library header */
24
25 /* local header */
26 #include "Debug.h"
27 #include "Session.h"
28 #include "Reader.h"
29 #include "ClientChannel.h"
30 #ifdef USE_GDBUS
31 #include "smartcard-service-gdbus.h"
32 #include "GDBusHelper.h"
33 #else
34 #include "ClientIPC.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         Session::Session(void *context, Reader *reader, void *handle) :
44                 SessionHelper(reader)
45         {
46                 this->context = NULL;
47
48                 if (context == NULL || handle == NULL)
49                 {
50                         _ERR("handle is null");
51
52                         return;
53                 }
54
55                 this->context = context;
56                 this->handle = handle;
57
58 #ifdef USE_GDBUS
59                 /* initialize client */
60                 if (!g_thread_supported())
61                 {
62                         g_thread_init(NULL);
63                 }
64
65                 g_type_init();
66
67                 /* init default context */
68                 GError *error = NULL;
69
70                 proxy = smartcard_service_session_proxy_new_for_bus_sync(
71                         G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
72                         "org.tizen.SmartcardService",
73                         "/org/tizen/SmartcardService/Session",
74                         NULL, &error);
75                 if (proxy == NULL)
76                 {
77                         _ERR("Can not create proxy : %s", error->message);
78                         g_error_free(error);
79                         return;
80                 }
81 #endif
82                 closed = false;
83         }
84
85         Session::~Session()
86         {
87                 size_t i;
88
89                 closeSync();
90
91                 for (i = 0; i < channels.size(); i++)
92                 {
93                         delete (ClientChannel *)channels[i];
94                 }
95
96                 channels.clear();
97         }
98
99         void Session::closeChannels() throw (ErrorIO &, ErrorIllegalState &)
100         {
101                 size_t i;
102
103                 for (i = 0; i < channels.size(); i++)
104                 {
105                         channels[i]->closeSync();
106                 }
107         }
108 #ifdef USE_GDBUS
109         void Session::session_get_atr_cb(GObject *source_object,
110                 GAsyncResult *res, gpointer user_data)
111         {
112                 CallbackParam *param = (CallbackParam *)user_data;
113                 Session *session;
114                 getATRCallback callback;
115                 gint result;
116                 GVariant *var_atr;
117                 GError *error = NULL;
118                 ByteArray atr;
119
120                 _INFO("MSG_REQUEST_GET_ATR");
121
122                 if (param == NULL) {
123                         _ERR("null parameter!!!");
124                         return;
125                 }
126
127                 session = (Session *)param->instance;
128                 callback = (getATRCallback)param->callback;
129
130                 if (smartcard_service_session_call_get_atr_finish(
131                         SMARTCARD_SERVICE_SESSION(source_object),
132                         &result, &var_atr, res, &error) == true) {
133                         if (result == SCARD_ERROR_OK) {
134                                 GDBusHelper::convertVariantToByteArray(var_atr, atr);
135
136                                 session->atr = atr;
137                         } else {
138                                 _ERR("smartcard_service_session_call_get_atr failed, [%d]", result);
139                         }
140                 } else {
141                         _ERR("smartcard_service_session_call_get_atr failed, [%s]", error->message);
142                         g_error_free(error);
143
144                         result = SCARD_ERROR_IPC_FAILED;
145                 }
146
147                 if (callback != NULL) {
148                         callback(atr.getBuffer(), atr.getLength(), result, param->user_param);
149                 }
150
151                 delete param;
152         }
153
154         void Session::session_open_channel_cb(GObject *source_object,
155                 GAsyncResult *res, gpointer user_data)
156         {
157                 CallbackParam *param = (CallbackParam *)user_data;
158                 Session *session;
159                 openChannelCallback callback;
160                 gint result;
161                 guint channel_id;
162                 GVariant *var_response;
163                 GError *error = NULL;
164                 Channel *channel;
165
166                 _INFO("MSG_REQUEST_OPEN_CHANNEL");
167
168                 if (param == NULL) {
169                         _ERR("null parameter!!!");
170                         return;
171                 }
172
173                 session = (Session *)param->instance;
174                 callback = (openChannelCallback)param->callback;
175
176                 if (smartcard_service_session_call_open_channel_finish(
177                         SMARTCARD_SERVICE_SESSION(source_object),
178                         &result, &channel_id, &var_response,
179                         res, &error) == true) {
180                         if (result == SCARD_ERROR_OK) {
181                                 ByteArray response;
182
183                                 GDBusHelper::convertVariantToByteArray(
184                                         var_response, response);
185
186                                 /* create new instance of channel */
187                                 channel = new ClientChannel(session->context,
188                                         session, channel_id,
189                                         response, (void *)channel_id);
190                                 if (channel != NULL) {
191                                         session->channels.push_back(channel);
192                                 } else {
193                                         _ERR("alloc failed");
194
195                                         result = SCARD_ERROR_OUT_OF_MEMORY;
196                                 }
197                         } else {
198                                 _ERR("smartcard_service_session_call_open_channel failed, [%d]", result);
199                         }
200                 } else {
201                         _ERR("smartcard_service_session_call_open_channel failed, [%s]", error->message);
202                         g_error_free(error);
203
204                         result = SCARD_ERROR_IPC_FAILED;
205                 }
206
207                 if (callback != NULL) {
208                         callback(channel, result, param->user_param);
209                 }
210
211                 delete param;
212         }
213
214         void Session::session_close_cb(GObject *source_object,
215                 GAsyncResult *res, gpointer user_data)
216         {
217                 CallbackParam *param = (CallbackParam *)user_data;
218                 Session *session;
219                 closeSessionCallback callback;
220                 gint result;
221                 GError *error = NULL;
222
223                 _INFO("MSG_REQUEST_CLOSE_SESSION");
224
225                 if (param == NULL) {
226                         _ERR("null parameter!!!");
227                         return;
228                 }
229
230                 session = (Session *)param->instance;
231                 callback = (closeSessionCallback)param->callback;
232
233                 if (smartcard_service_session_call_close_session_finish(
234                         SMARTCARD_SERVICE_SESSION(source_object),
235                         &result, res, &error) == true) {
236                         if (result == SCARD_ERROR_OK) {
237                                 session->closed = true;
238                         } else {
239                                 _ERR("smartcard_service_session_call_close_session failed, [%d]", result);
240                         }
241                 } else {
242                         _ERR("smartcard_service_session_call_close_session failed, [%s]", error->message);
243                         g_error_free(error);
244
245                         result = SCARD_ERROR_IPC_FAILED;
246                 }
247
248                 if (callback != NULL) {
249                         callback(result, param->user_param);
250                 }
251
252                 delete param;
253         }
254 #endif
255         ByteArray Session::getATRSync()
256                 throw (ExceptionBase &, ErrorIO &, ErrorSecurity &,
257                         ErrorIllegalState &, ErrorIllegalParameter &)
258         {
259                 ByteArray result;
260
261                 if (getReader()->isSecureElementPresent() == true)
262                 {
263                         if (atr.isEmpty() == true)
264                         {
265 #ifdef USE_GDBUS
266                                 gint ret;
267                                 GVariant *var_atr = NULL;
268                                 GError *error = NULL;
269
270                                 if (smartcard_service_session_call_get_atr_sync(
271                                         (SmartcardServiceSession *)proxy,
272                                         GPOINTER_TO_UINT(context),
273                                         GPOINTER_TO_UINT(handle),
274                                         &ret, &var_atr, NULL, &error) == true) {
275                                         if (ret == SCARD_ERROR_OK) {
276                                                 GDBusHelper::convertVariantToByteArray(var_atr, result);
277
278                                                 atr = result;
279                                         } else {
280                                                 _ERR("smartcard_service_session_call_get_atr_sync failed, [%d]", ret);
281
282                                                 THROW_ERROR(ret);
283                                         }
284                                 } else {
285                                         _ERR("smartcard_service_session_call_get_atr_sync failed, [%s]", error->message);
286                                         g_error_free(error);
287
288                                         THROW_ERROR(SCARD_ERROR_IPC_FAILED);
289                                 }
290 #else
291                                 Message msg;
292                                 int rv;
293 #ifdef CLIENT_IPC_THREAD
294                                 /* request channel handle from server */
295                                 msg.message = Message::MSG_REQUEST_GET_ATR;
296                                 msg.param1 = (unsigned long)handle;
297                                 msg.error = (unsigned long)context; /* using error to context */
298                                 msg.caller = (void *)this;
299                                 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
300
301                                 syncLock();
302                                 if (ClientIPC::getInstance().sendMessage(&msg) == true)
303                                 {
304                                         rv = waitTimedCondition(0);
305                                         if (rv != 0)
306                                         {
307                                                 _ERR("time over");
308                                                 this->error = SCARD_ERROR_OPERATION_TIMEOUT;
309                                         }
310                                 }
311                                 else
312                                 {
313                                         _ERR("sendMessage failed");
314                                         this->error = SCARD_ERROR_IPC_FAILED;
315                                 }
316                                 syncUnlock();
317
318                                 if (this->error != SCARD_ERROR_OK)
319                                 {
320                                         ThrowError::throwError(this->error);
321                                 }
322 #endif
323 #endif
324                         }
325
326                         result = atr;
327                 }
328                 else
329                 {
330                         _ERR("unavailable session");
331                         throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
332                 }
333
334                 return result;
335         }
336
337         int Session::getATR(getATRCallback callback, void *userData)
338         {
339                 int result;
340
341                 if (getReader()->isSecureElementPresent() == true)
342                 {
343                         if (atr.isEmpty() == true)
344                         {
345 #ifdef USE_GDBUS
346                                 CallbackParam *param = new CallbackParam();
347
348                                 param->instance = this;
349                                 param->callback = (void *)callback;
350                                 param->user_param = userData;
351
352                                 smartcard_service_session_call_get_atr(
353                                         (SmartcardServiceSession *)proxy,
354                                         GPOINTER_TO_UINT(context),
355                                         GPOINTER_TO_UINT(handle), NULL,
356                                         &Session::session_get_atr_cb, param);
357
358                                 result = SCARD_ERROR_OK;
359 #else
360                                 Message msg;
361
362                                 /* request channel handle from server */
363                                 msg.message = Message::MSG_REQUEST_GET_ATR;
364                                 msg.param1 = (unsigned long)handle;
365                                 msg.error = (unsigned long)context; /* using error to context */
366                                 msg.caller = (void *)this;
367                                 msg.callback = (void *)callback;
368                                 msg.userParam = userData;
369
370                                 if (ClientIPC::getInstance().sendMessage(&msg) == true)
371                                 {
372                                         result = SCARD_ERROR_OK;
373                                 }
374                                 else
375                                 {
376                                         _ERR("sendMessage failed");
377                                         result = SCARD_ERROR_IPC_FAILED;
378                                 }
379 #endif
380                         }
381                         else
382                         {
383                                 result = SCARD_ERROR_OK;
384
385                                 /* TODO : invoke callback directly */
386                                 callback(atr.getBuffer(), atr.getLength(), 0, userData);
387                         }
388                 }
389                 else
390                 {
391                         _ERR("unavailable session");
392                         result = SCARD_ERROR_ILLEGAL_STATE;
393                 }
394
395                 return result;
396         }
397
398         void Session::closeSync()
399                 throw (ExceptionBase &, ErrorIO &, ErrorSecurity &,
400                         ErrorIllegalState &, ErrorIllegalParameter &)
401         {
402                 if (isClosed() == false)
403                 {
404                         closed = true;
405                         closeChannels();
406 #ifdef USE_GDBUS
407                         gint ret;
408                         GError *error = NULL;
409
410                         if (smartcard_service_session_call_close_session_sync(
411                                 (SmartcardServiceSession *)proxy,
412                                 GPOINTER_TO_UINT(context),
413                                 GPOINTER_TO_UINT(handle),
414                                 &ret, NULL, &error) == true) {
415                                 if (ret == SCARD_ERROR_OK) {
416                                         closed = true;
417                                 } else {
418                                         _ERR("smartcard_service_session_call_close_session_sync failed, [%d]", ret);
419
420                                         THROW_ERROR(ret);
421                                 }
422                         } else {
423                                 _ERR("smartcard_service_session_call_get_atr_sync failed, [%s]", error->message);
424                                 g_error_free(error);
425
426                                 THROW_ERROR(SCARD_ERROR_IPC_FAILED);
427                         }
428 #else
429                         int rv;
430                         Message msg;
431
432 #ifdef CLIENT_IPC_THREAD
433                         /* request channel handle from server */
434                         msg.message = Message::MSG_REQUEST_CLOSE_SESSION;
435                         msg.param1 = (unsigned long)handle;
436                         msg.error = (unsigned long)context; /* using error to context */
437                         msg.caller = (void *)this;
438                         msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
439
440                         syncLock();
441                         if (ClientIPC::getInstance().sendMessage(&msg) == true)
442                         {
443                                 rv = waitTimedCondition(0);
444
445                                 if (rv != 0)
446                                 {
447                                         _ERR("time over");
448                                         this->error = SCARD_ERROR_OPERATION_TIMEOUT;
449                                 }
450                         }
451                         else
452                         {
453                                 _ERR("sendMessage failed");
454                                 this->error = SCARD_ERROR_IPC_FAILED;
455                         }
456                         syncUnlock();
457
458                         if (this->error != SCARD_ERROR_OK)
459                         {
460                                 ThrowError::throwError(this->error);
461                         }
462 #endif
463 #endif
464                 }
465         }
466
467         int Session::close(closeSessionCallback callback, void *userData)
468         {
469                 int result = SCARD_ERROR_OK;
470
471                 if (isClosed() == false)
472                 {
473                         closed = true;
474                         closeChannels();
475 #ifdef USE_GDBUS
476                         CallbackParam *param = new CallbackParam();
477
478                         param->instance = this;
479                         param->callback = (void *)callback;
480                         param->user_param = userData;
481
482                         smartcard_service_session_call_close_session(
483                                 (SmartcardServiceSession *)proxy,
484                                 GPOINTER_TO_UINT(context),
485                                 GPOINTER_TO_UINT(handle), NULL,
486                                 &Session::session_close_cb, param);
487 #else
488                         Message msg;
489                         /* request channel handle from server */
490                         msg.message = Message::MSG_REQUEST_CLOSE_SESSION;
491                         msg.param1 = (unsigned long)handle;
492                         msg.error = (unsigned long)context; /* using error to context */
493                         msg.caller = (void *)this;
494                         msg.callback = (void *)callback;
495                         msg.userParam = userData;
496
497                         if (ClientIPC::getInstance().sendMessage(&msg) == false)
498                         {
499                                 _ERR("sendMessage failed");
500                                 result = SCARD_ERROR_IPC_FAILED;
501                         }
502 #endif
503                 }
504
505                 return result;
506         }
507
508         unsigned int Session::getChannelCountSync()
509         {
510                 unsigned int count = 0;
511
512                 if (getReader()->isSecureElementPresent() == true)
513                 {
514 #ifdef USE_GDBUS
515                         count = channels.size();
516 #else
517                         Message msg;
518                         int rv;
519
520                         channelCount = -1;
521 #ifdef CLIENT_IPC_THREAD
522                         /* request channel handle from server */
523                         msg.message = Message::MSG_REQUEST_GET_CHANNEL_COUNT;
524                         msg.param1 = (unsigned long)handle;
525                         msg.error = (unsigned long)context; /* using error to context */
526                         msg.caller = (void *)this;
527                         msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
528
529                         syncLock();
530                         if (ClientIPC::getInstance().sendMessage(&msg) == true)
531                         {
532                                 rv = waitTimedCondition(0);
533                                 if (rv != 0)
534                                 {
535                                         _ERR("time over");
536                                         this->error = SCARD_ERROR_OPERATION_TIMEOUT;
537                                 }
538
539                                 count = channelCount;
540                         }
541                         else
542                         {
543                                 _ERR("sendMessage failed");
544                                 this->error = SCARD_ERROR_IPC_FAILED;
545                         }
546                         syncUnlock();
547
548                         if (this->error != SCARD_ERROR_OK)
549                         {
550                                 ThrowError::throwError(this->error);
551                         }
552 #endif
553 #endif
554                 }
555                 else
556                 {
557                         _ERR("unavailable session");
558                         throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
559                 }
560
561                 return count;
562         }
563
564         int Session::getChannelCount(getChannelCountCallback callback, void *userData)
565         {
566                 int result;
567
568                 if (getReader()->isSecureElementPresent() == true)
569                 {
570 #ifdef USE_GDBUS
571 #else
572                         Message msg;
573
574                         msg.message = Message::MSG_REQUEST_GET_CHANNEL_COUNT;
575                         msg.param1 = (unsigned long)handle;
576                         msg.error = (unsigned long)context; /* using error to context */
577                         msg.caller = (void *)this;
578                         msg.callback = (void *)callback;
579                         msg.userParam = userData;
580
581                         if (ClientIPC::getInstance().sendMessage(&msg) == true)
582                         {
583                                 result = SCARD_ERROR_OK;
584                         }
585                         else
586                         {
587                                 _ERR("sendMessage failed");
588                                 result = SCARD_ERROR_IPC_FAILED;
589                         }
590 #endif
591                 }
592                 else
593                 {
594                         _ERR("unavailable session");
595                         result = SCARD_ERROR_ILLEGAL_STATE;
596                 }
597
598                 return result;
599         }
600
601         Channel *Session::openChannelSync(int id, ByteArray &aid)
602                 throw (ExceptionBase &, ErrorIO &, ErrorIllegalState &,
603                         ErrorIllegalParameter &, ErrorSecurity &)
604         {
605                 Channel *channel = NULL;
606
607                 if (getReader()->isSecureElementPresent() == true)
608                 {
609 #ifdef USE_GDBUS
610                         gint ret;
611                         GVariant *var_aid = NULL, *var_response = NULL;
612                         guint channel_id;
613                         GError *error = NULL;
614
615                         var_aid = GDBusHelper::convertByteArrayToVariant(aid);
616
617                         if (smartcard_service_session_call_open_channel_sync(
618                                 (SmartcardServiceSession *)proxy,
619                                 GPOINTER_TO_UINT(context),
620                                 GPOINTER_TO_UINT(handle),
621                                 (guint)id, var_aid, &ret, &channel_id,
622                                 &var_response, NULL, &error) == true) {
623                                 if (ret == SCARD_ERROR_OK && channel_id != 0) {
624                                         ByteArray response;
625
626                                         GDBusHelper::convertVariantToByteArray(
627                                                 var_response, response);
628
629                                         /* create new instance of channel */
630                                         channel = new ClientChannel(context,
631                                                 this, channel_id,
632                                                 response, (void *)channel_id);
633                                         if (channel != NULL)
634                                         {
635                                                 channels.push_back(channel);
636                                         }
637                                         else
638                                         {
639                                                 _ERR("alloc failed");
640
641                                                 THROW_ERROR(SCARD_ERROR_OUT_OF_MEMORY);
642                                         }
643                                 } else {
644                                         _ERR("smartcard_service_session_call_open_channel_sync failed, [%d]", ret);
645
646                                         THROW_ERROR(ret);
647                                 }
648                         } else {
649                                 _ERR("smartcard_service_session_call_open_channel_sync failed, [%s]", error->message);
650                                 g_error_free(error);
651
652                                 THROW_ERROR(SCARD_ERROR_IPC_FAILED);
653                         }
654 #else
655                         Message msg;
656                         int rv;
657
658 #ifdef CLIENT_IPC_THREAD
659                         /* request channel handle from server */
660                         msg.message = Message::MSG_REQUEST_OPEN_CHANNEL;
661                         msg.param1 = id;
662                         msg.param2 = (unsigned long)handle;
663                         msg.data = aid;
664                         msg.error = (unsigned long)context; /* using error to context */
665                         msg.caller = (void *)this;
666                         msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
667
668                         syncLock();
669                         if (ClientIPC::getInstance().sendMessage(&msg) == true)
670                         {
671                                 rv = waitTimedCondition(0);
672                                 if (rv != 0)
673                                 {
674                                         _ERR("time over");
675                                         this->error = SCARD_ERROR_OPERATION_TIMEOUT;
676                                 }
677
678                                 channel = openedChannel;
679                         }
680                         else
681                         {
682                                 _ERR("sendMessage failed");
683                                 this->error = SCARD_ERROR_IPC_FAILED;
684                         }
685                         syncUnlock();
686 #endif
687                         if (this->error != SCARD_ERROR_OK)
688                         {
689                                 ThrowError::throwError(this->error);
690                         }
691 #endif
692                 }
693                 else
694                 {
695                         _ERR("unavailable session");
696
697                         throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
698                 }
699
700                 return (Channel *)channel;
701         }
702
703         int Session::openChannel(int id, ByteArray &aid, openChannelCallback callback, void *userData)
704         {
705                 int result;
706
707                 if (getReader()->isSecureElementPresent() == true)
708                 {
709 #ifdef USE_GDBUS
710                         GVariant *var_aid;
711
712                         CallbackParam *param = new CallbackParam();
713
714                         param->instance = this;
715                         param->callback = (void *)callback;
716                         param->user_param = userData;
717
718                         var_aid = GDBusHelper::convertByteArrayToVariant(aid);
719
720                         smartcard_service_session_call_open_channel(
721                                 (SmartcardServiceSession *)proxy,
722                                 GPOINTER_TO_UINT(context),
723                                 GPOINTER_TO_UINT(handle),
724                                 (guint)id, var_aid, NULL,
725                                 &Session::session_open_channel_cb, param);
726 #else
727                         Message msg;
728
729                         /* request channel handle from server */
730                         msg.message = Message::MSG_REQUEST_OPEN_CHANNEL;
731                         msg.param1 = id;
732                         msg.param2 = (unsigned long)handle;
733                         msg.data = aid;
734                         msg.error = (unsigned long)context; /* using error to context */
735                         msg.caller = (void *)this;
736                         msg.callback = (void *)callback;
737                         msg.userParam = userData;
738
739                         if (ClientIPC::getInstance().sendMessage(&msg) == true)
740                         {
741                                 result = SCARD_ERROR_OK;
742                         }
743                         else
744                         {
745                                 _ERR("sendMessage failed");
746                                 result = SCARD_ERROR_IPC_FAILED;
747                         }
748 #endif
749                 }
750                 else
751                 {
752                         _ERR("unavailable session");
753                         result = SCARD_ERROR_ILLEGAL_STATE;
754                 }
755
756                 return result;
757         }
758
759         Channel *Session::openBasicChannelSync(ByteArray &aid)
760                 throw (ErrorIO &, ErrorIllegalState &, ErrorIllegalParameter &, ErrorSecurity &)
761         {
762                 return openChannelSync(0, aid);
763         }
764
765         Channel *Session::openBasicChannelSync(unsigned char *aid, unsigned int length)
766                 throw (ErrorIO &, ErrorIllegalState &, ErrorIllegalParameter &, ErrorSecurity &)
767         {
768                 ByteArray temp(aid, length);
769
770                 return openBasicChannelSync(temp);
771         }
772
773         int Session::openBasicChannel(ByteArray &aid, openChannelCallback callback, void *userData)
774         {
775                 return openChannel(0, aid, callback, userData);
776         }
777
778         int Session::openBasicChannel(unsigned char *aid, unsigned int length,
779                 openChannelCallback callback, void *userData)
780         {
781                 ByteArray temp(aid, length);
782
783                 return openBasicChannel(temp, callback, userData);
784         }
785
786         Channel *Session::openLogicalChannelSync(ByteArray &aid)
787                 throw (ErrorIO &, ErrorIllegalState &, ErrorIllegalParameter &, ErrorSecurity &)
788         {
789                 return openChannelSync(1, aid);
790         }
791
792         Channel *Session::openLogicalChannelSync(unsigned char *aid, unsigned int length)
793                 throw (ErrorIO &, ErrorIllegalState &, ErrorIllegalParameter &, ErrorSecurity &)
794         {
795                 ByteArray temp(aid, length);
796
797                 return openLogicalChannelSync(temp);
798         }
799
800         int Session::openLogicalChannel(ByteArray &aid, openChannelCallback callback, void *userData)
801         {
802                 return openChannel(1, aid, callback, userData);
803         }
804
805         int Session::openLogicalChannel(unsigned char *aid, unsigned int length,
806                 openChannelCallback callback, void *userData)
807         {
808                 ByteArray temp(aid, length);
809
810                 return openLogicalChannel(temp, callback, userData);
811         }
812
813 #ifndef USE_GDBUS
814         bool Session::dispatcherCallback(void *message)
815         {
816                 Message *msg = (Message *)message;
817                 Session *session;
818                 bool result = false;
819
820                 if (msg == NULL)
821                 {
822                         _ERR("message is null");
823                         return result;
824                 }
825
826                 session = (Session *)msg->caller;
827
828                 switch (msg->message)
829                 {
830                 case Message::MSG_REQUEST_OPEN_CHANNEL :
831                         {
832                                 Channel *channel = NULL;
833
834                                 _INFO("MSG_REQUEST_OPEN_CHANNEL");
835
836                                 if (msg->param1 != 0)
837                                 {
838                                         /* create new instance of channel */
839                                         channel = new ClientChannel(session->context,
840                                                 session, msg->param2, msg->data, (void *)msg->param1);
841                                         if (channel != NULL)
842                                         {
843                                                 session->channels.push_back(channel);
844                                         }
845                                         else
846                                         {
847                                                 _ERR("alloc failed");
848
849                                                 msg->error = SCARD_ERROR_OUT_OF_MEMORY;
850                                         }
851                                 }
852
853                                 if (msg->isSynchronousCall() == true) /* synchronized call */
854                                 {
855                                         /* sync call */
856                                         session->syncLock();
857
858                                         /* copy result */
859                                         session->error = msg->error;
860                                         session->openedChannel = channel;
861
862                                         session->signalCondition();
863                                         session->syncUnlock();
864                                 }
865                                 else if (msg->callback != NULL)
866                                 {
867                                         openChannelCallback cb = (openChannelCallback)msg->callback;
868
869                                         /* async call */
870                                         cb(channel, msg->error, msg->userParam);
871                                 }
872                         }
873                         break;
874
875                 case Message::MSG_REQUEST_GET_ATR :
876                         {
877                                 _INFO("MSG_REQUEST_GET_ATR");
878
879                                 if (msg->isSynchronousCall() == true) /* synchronized call */
880                                 {
881                                         /* sync call */
882                                         session->syncLock();
883
884                                         session->error = msg->error;
885                                         session->atr = msg->data;
886
887                                         session->signalCondition();
888                                         session->syncUnlock();
889                                 }
890                                 else if (msg->callback != NULL)
891                                 {
892                                         getATRCallback cb = (getATRCallback)msg->callback;
893
894                                         /* async call */
895                                         cb(msg->data.getBuffer(), msg->data.getLength(), msg->error, msg->userParam);
896                                 }
897                         }
898                         break;
899
900                 case Message::MSG_REQUEST_CLOSE_SESSION :
901                         {
902                                 _INFO("MSG_REQUEST_CLOSE_SESSION");
903
904                                 if (msg->isSynchronousCall() == true) /* synchronized call */
905                                 {
906                                         /* sync call */
907                                         session->syncLock();
908
909                                         session->error = msg->error;
910
911                                         session->signalCondition();
912                                         session->syncUnlock();
913                                 }
914                                 else if (msg->callback != NULL)
915                                 {
916                                         closeSessionCallback cb = (closeSessionCallback)msg->callback;
917
918                                         /* async call */
919                                         cb(msg->error, msg->userParam);
920                                 }
921                         }
922                         break;
923
924                 case Message::MSG_REQUEST_GET_CHANNEL_COUNT :
925                         {
926                                 _INFO("MSG_REQUEST_GET_CHANNEL_COUNT");
927
928                                 if (msg->isSynchronousCall() == true) /* synchronized call */
929                                 {
930                                         /* sync call */
931                                         session->syncLock();
932
933                                         session->error = msg->error;
934                                         session->channelCount = msg->param1;
935
936                                         session->signalCondition();
937                                         session->syncUnlock();
938                                 }
939                                 else if (msg->callback != NULL)
940                                 {
941                                         getChannelCountCallback cb = (getChannelCountCallback)msg->callback;
942
943                                         /* async call */
944                                         cb(msg->param1, msg->error, msg->userParam);
945                                 }
946                         }
947                         break;
948
949                 default :
950                         _DBG("unknown message : %s", msg->toString());
951                         break;
952                 }
953
954                 delete msg;
955
956                 return result;
957         }
958 #endif
959 } /* namespace smartcard_service_api */
960
961 /* export C API */
962 #define SESSION_EXTERN_BEGIN \
963         if (handle != NULL) \
964         { \
965                 Session *session = (Session *)handle;
966
967 #define SESSION_EXTERN_END \
968         } \
969         else \
970         { \
971                 _ERR("Invalid param"); \
972         }
973
974 using namespace smartcard_service_api;
975
976 EXTERN_API reader_h session_get_reader(session_h handle)
977 {
978         reader_h reader = NULL;
979
980         SESSION_EXTERN_BEGIN;
981                 reader = session->getReader();
982         SESSION_EXTERN_END;
983
984         return reader;
985 }
986
987 EXTERN_API int session_get_atr(session_h handle, session_get_atr_cb callback, void *userData)
988 {
989         int result = -1;
990
991         SESSION_EXTERN_BEGIN;
992                 result = session->getATR((getATRCallback)callback, userData);
993         SESSION_EXTERN_END;
994
995         return result;
996 }
997
998 EXTERN_API int session_close(session_h handle, session_close_session_cb callback, void *userData)
999 {
1000         int result = -1;
1001
1002         SESSION_EXTERN_BEGIN;
1003                 result = session->close((closeSessionCallback)callback, userData);
1004         SESSION_EXTERN_END;
1005
1006         return result;
1007 }
1008
1009 EXTERN_API bool session_is_closed(session_h handle)
1010 {
1011         bool result = false;
1012
1013         SESSION_EXTERN_BEGIN;
1014                 result = session->isClosed();
1015         SESSION_EXTERN_END;
1016
1017         return result;
1018 }
1019
1020 EXTERN_API void session_close_channels(session_h handle)
1021 {
1022         SESSION_EXTERN_BEGIN;
1023                 session->closeChannels();
1024         SESSION_EXTERN_END;
1025 }
1026
1027 EXTERN_API int session_open_basic_channel(session_h handle, unsigned char *aid,
1028         unsigned int length, session_open_channel_cb callback, void *userData)
1029 {
1030         int result = -1;
1031
1032         SESSION_EXTERN_BEGIN;
1033                 result = session->openBasicChannel(aid, length, (openChannelCallback)callback, userData);
1034         SESSION_EXTERN_END;
1035
1036         return result;
1037 }
1038
1039 EXTERN_API int session_open_logical_channel(session_h handle, unsigned char *aid,
1040         unsigned int length, session_open_channel_cb callback, void *userData)
1041 {
1042         int result = -1;
1043
1044         SESSION_EXTERN_BEGIN;
1045                 result = session->openLogicalChannel(aid, length, (openChannelCallback)callback, userData);
1046         SESSION_EXTERN_END;
1047
1048         return result;
1049 }
1050
1051 EXTERN_API int session_get_channel_count(session_h handle, session_get_channel_count_cb callback, void * userData)
1052 {
1053         int result = -1;
1054
1055         SESSION_EXTERN_BEGIN;
1056                 result = session->getChannelCount((getChannelCountCallback)callback, userData);
1057         SESSION_EXTERN_END;
1058
1059         return result;
1060 }
1061
1062 EXTERN_API void session_destroy_instance(session_h handle)
1063 {
1064 }
1065
1066 EXTERN_API int session_get_atr_sync(session_h handle, unsigned char **buffer, unsigned int *length)
1067 {
1068         ByteArray temp;
1069         int result = -1;
1070
1071 #ifdef CLIENT_IPC_THREAD
1072         if (buffer == NULL || length == NULL)
1073                 return result;
1074
1075         SESSION_EXTERN_BEGIN;
1076                 temp = session->getATRSync();
1077                 if (temp.getLength() > 0)
1078                 {
1079                         *length = temp.getLength();
1080                         *buffer = (unsigned char *)calloc(1, *length);
1081                         memcpy(*buffer, temp.getBuffer(), *length);
1082
1083                         result = 0;
1084                 }
1085                 SESSION_EXTERN_END;
1086 #endif
1087
1088         return result;
1089 }
1090
1091 EXTERN_API void session_close_sync(session_h handle)
1092 {
1093 #ifdef CLIENT_IPC_THREAD
1094         SESSION_EXTERN_BEGIN;
1095                 session->closeSync();
1096         SESSION_EXTERN_END;
1097 #endif
1098 }
1099
1100 EXTERN_API channel_h session_open_basic_channel_sync(session_h handle, unsigned char *aid, unsigned int length)
1101 {
1102         channel_h result = NULL;
1103
1104 #ifdef CLIENT_IPC_THREAD
1105         SESSION_EXTERN_BEGIN;
1106                 result = session->openBasicChannelSync(aid, length);
1107         SESSION_EXTERN_END;
1108 #endif
1109
1110         return result;
1111 }
1112
1113 EXTERN_API channel_h session_open_logical_channel_sync(session_h handle, unsigned char *aid, unsigned int length)
1114 {
1115         channel_h result = NULL;
1116
1117 #ifdef CLIENT_IPC_THREAD
1118         SESSION_EXTERN_BEGIN;
1119                 result = session->openLogicalChannelSync(aid, length);
1120         SESSION_EXTERN_END;
1121 #endif
1122
1123         return result;
1124 }
1125
1126 EXTERN_API unsigned int session_get_channel_count_sync(session_h handle)
1127 {
1128         unsigned int result = 0;
1129
1130 #ifdef CLIENT_IPC_THREAD
1131         SESSION_EXTERN_BEGIN;
1132                 result = session->getChannelCountSync();
1133         SESSION_EXTERN_END;
1134 #endif
1135
1136         return result;
1137 }