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