2 * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 /* standard library header */
23 /* SLP library header */
29 #include "ClientChannel.h"
31 #include "ClientGDBus.h"
33 #include "ClientIPC.h"
37 #define EXTERN_API __attribute__((visibility("default")))
40 namespace smartcard_service_api
42 Session::Session(void *context, Reader *reader, void *handle) :
47 if (context == NULL || handle == NULL)
49 _ERR("handle is null");
54 this->context = context;
55 this->handle = handle;
58 /* initialize client */
59 if (!g_thread_supported())
66 /* init default context */
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",
76 _ERR("Can not create proxy : %s", error->message);
90 for (i = 0; i < channels.size(); i++)
92 delete (ClientChannel *)channels[i];
98 void Session::closeChannels() throw (ErrorIO &, ErrorIllegalState &)
102 for (i = 0; i < channels.size(); i++)
104 channels[i]->closeSync();
108 void Session::session_get_atr_cb(GObject *source_object,
109 GAsyncResult *res, gpointer user_data)
111 CallbackParam *param = (CallbackParam *)user_data;
113 getATRCallback callback;
116 GError *error = NULL;
119 _INFO("MSG_REQUEST_GET_ATR");
122 _ERR("null parameter!!!");
126 session = (Session *)param->instance;
127 callback = (getATRCallback)param->callback;
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);
137 _ERR("smartcard_service_session_call_get_atr failed, [%d]", result);
140 _ERR("smartcard_service_session_call_get_atr failed, [%s]", error->message);
143 result = SCARD_ERROR_IPC_FAILED;
146 if (callback != NULL) {
147 callback(atr.getBuffer(),
148 atr.size(), result, param->user_param);
154 void Session::session_open_channel_cb(GObject *source_object,
155 GAsyncResult *res, gpointer user_data)
157 CallbackParam *param = (CallbackParam *)user_data;
159 openChannelCallback callback;
162 GVariant *var_response;
163 GError *error = NULL;
166 _INFO("MSG_REQUEST_OPEN_CHANNEL");
169 _ERR("null parameter!!!");
173 session = (Session *)param->instance;
174 callback = (openChannelCallback)param->callback;
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) {
183 GDBusHelper::convertVariantToByteArray(
184 var_response, response);
186 /* create new instance of channel */
187 channel = new ClientChannel(session->context,
189 response, (void *)channel_id);
190 if (channel != NULL) {
191 session->channels.push_back(channel);
193 _ERR("alloc failed");
195 result = SCARD_ERROR_OUT_OF_MEMORY;
198 _ERR("smartcard_service_session_call_open_channel failed, [%d]", result);
201 _ERR("smartcard_service_session_call_open_channel failed, [%s]", error->message);
204 result = SCARD_ERROR_IPC_FAILED;
207 if (callback != NULL) {
208 callback(channel, result, param->user_param);
214 void Session::session_close_cb(GObject *source_object,
215 GAsyncResult *res, gpointer user_data)
217 CallbackParam *param = (CallbackParam *)user_data;
219 closeSessionCallback callback;
221 GError *error = NULL;
223 _INFO("MSG_REQUEST_CLOSE_SESSION");
226 _ERR("null parameter!!!");
230 session = (Session *)param->instance;
231 callback = (closeSessionCallback)param->callback;
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;
239 _ERR("smartcard_service_session_call_close_session failed, [%d]", result);
242 _ERR("smartcard_service_session_call_close_session failed, [%s]", error->message);
245 result = SCARD_ERROR_IPC_FAILED;
248 if (callback != NULL) {
249 callback(result, param->user_param);
255 const ByteArray Session::getATRSync()
256 throw (ExceptionBase &, ErrorIO &, ErrorSecurity &,
257 ErrorIllegalState &, ErrorIllegalParameter &)
261 if (getReader()->isSecureElementPresent() == true)
263 if (atr.isEmpty() == true)
267 GVariant *var_atr = NULL;
268 GError *error = NULL;
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);
281 _ERR("smartcard_service_session_call_get_atr_sync failed, [%d]", ret);
286 _ERR("smartcard_service_session_call_get_atr_sync failed, [%s]", error->message);
289 THROW_ERROR(SCARD_ERROR_IPC_FAILED);
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 */
303 if (ClientIPC::getInstance().sendMessage(msg) == true)
305 rv = waitTimedCondition(0);
309 this->error = SCARD_ERROR_OPERATION_TIMEOUT;
314 _ERR("sendMessage failed");
315 this->error = SCARD_ERROR_IPC_FAILED;
319 if (this->error != SCARD_ERROR_OK)
321 ThrowError::throwError(this->error);
331 _ERR("unavailable session");
332 throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
338 int Session::getATR(getATRCallback callback, void *userData)
342 if (getReader()->isSecureElementPresent() == true)
344 if (atr.isEmpty() == true)
347 CallbackParam *param = new CallbackParam();
349 param->instance = this;
350 param->callback = (void *)callback;
351 param->user_param = userData;
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);
360 result = SCARD_ERROR_OK;
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;
372 if (ClientIPC::getInstance().sendMessage(msg) == true)
374 result = SCARD_ERROR_OK;
378 _ERR("sendMessage failed");
379 result = SCARD_ERROR_IPC_FAILED;
385 result = SCARD_ERROR_OK;
387 /* TODO : invoke callback directly */
388 callback(atr.getBuffer(),
389 atr.size(), 0, userData);
394 _ERR("unavailable session");
395 result = SCARD_ERROR_ILLEGAL_STATE;
401 void Session::closeSync()
402 throw (ExceptionBase &, ErrorIO &, ErrorSecurity &,
403 ErrorIllegalState &, ErrorIllegalParameter &)
405 if (isClosed() == false)
411 GError *error = NULL;
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) {
422 _ERR("smartcard_service_session_call_close_session_sync failed, [%d]", ret);
427 _ERR("smartcard_service_session_call_get_atr_sync failed, [%s]", error->message);
430 THROW_ERROR(SCARD_ERROR_IPC_FAILED);
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 */
445 if (ClientIPC::getInstance().sendMessage(msg) == true)
447 rv = waitTimedCondition(0);
452 this->error = SCARD_ERROR_OPERATION_TIMEOUT;
457 _ERR("sendMessage failed");
458 this->error = SCARD_ERROR_IPC_FAILED;
462 if (this->error != SCARD_ERROR_OK)
464 ThrowError::throwError(this->error);
471 int Session::close(closeSessionCallback callback, void *userData)
473 int result = SCARD_ERROR_OK;
475 if (isClosed() == false)
480 CallbackParam *param = new CallbackParam();
482 param->instance = this;
483 param->callback = (void *)callback;
484 param->user_param = userData;
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);
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;
502 if (ClientIPC::getInstance().sendMessage(msg) == false)
504 _ERR("sendMessage failed");
505 result = SCARD_ERROR_IPC_FAILED;
513 unsigned int Session::getChannelCountSync()
515 unsigned int count = 0;
517 if (getReader()->isSecureElementPresent() == true)
520 count = channels.size();
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 */
535 if (ClientIPC::getInstance().sendMessage(msg) == true)
537 rv = waitTimedCondition(0);
541 this->error = SCARD_ERROR_OPERATION_TIMEOUT;
544 count = channelCount;
548 _ERR("sendMessage failed");
549 this->error = SCARD_ERROR_IPC_FAILED;
553 if (this->error != SCARD_ERROR_OK)
555 ThrowError::throwError(this->error);
562 _ERR("unavailable session");
563 throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
569 int Session::getChannelCount(getChannelCountCallback callback, void *userData)
573 if (getReader()->isSecureElementPresent() == true)
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;
586 if (ClientIPC::getInstance().sendMessage(msg) == true)
588 result = SCARD_ERROR_OK;
592 _ERR("sendMessage failed");
593 result = SCARD_ERROR_IPC_FAILED;
599 _ERR("unavailable session");
600 result = SCARD_ERROR_ILLEGAL_STATE;
606 Channel *Session::openChannelSync(int id, const ByteArray &aid)
607 throw (ExceptionBase &, ErrorIO &, ErrorIllegalState &,
608 ErrorIllegalParameter &, ErrorSecurity &)
610 Channel *channel = NULL;
612 if (getReader()->isSecureElementPresent() == true)
616 GVariant *var_aid = NULL, *var_response = NULL;
618 GError *error = NULL;
620 var_aid = GDBusHelper::convertByteArrayToVariant(aid);
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) {
632 GDBusHelper::convertVariantToByteArray(
633 var_response, response);
635 /* create new instance of channel */
636 channel = new ClientChannel(context,
638 response, (void *)channel_id);
641 channels.push_back(channel);
645 _ERR("alloc failed");
647 THROW_ERROR(SCARD_ERROR_OUT_OF_MEMORY);
650 _ERR("smartcard_service_session_call_open_channel_sync failed, [%d]", ret);
655 _ERR("smartcard_service_session_call_open_channel_sync failed, [%s]", error->message);
658 THROW_ERROR(SCARD_ERROR_IPC_FAILED);
664 #ifdef CLIENT_IPC_THREAD
665 /* request channel handle from server */
666 msg.message = Message::MSG_REQUEST_OPEN_CHANNEL;
668 msg.param2 = (unsigned long)handle;
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 */
675 if (ClientIPC::getInstance().sendMessage(msg) == true)
677 rv = waitTimedCondition(0);
681 this->error = SCARD_ERROR_OPERATION_TIMEOUT;
684 channel = openedChannel;
688 _ERR("sendMessage failed");
689 this->error = SCARD_ERROR_IPC_FAILED;
693 if (this->error != SCARD_ERROR_OK)
695 ThrowError::throwError(this->error);
701 _ERR("unavailable session");
703 throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
706 return (Channel *)channel;
709 int Session::openChannel(int id, const ByteArray &aid, openChannelCallback callback, void *userData)
713 if (getReader()->isSecureElementPresent() == true)
718 CallbackParam *param = new CallbackParam();
720 param->instance = this;
721 param->callback = (void *)callback;
722 param->user_param = userData;
724 var_aid = GDBusHelper::convertByteArrayToVariant(aid);
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);
736 /* request channel handle from server */
737 msg.message = Message::MSG_REQUEST_OPEN_CHANNEL;
739 msg.param2 = (unsigned long)handle;
741 msg.error = (unsigned long)context; /* using error to context */
742 msg.caller = (void *)this;
743 msg.callback = (void *)callback;
744 msg.userParam = userData;
746 if (ClientIPC::getInstance().sendMessage(msg) == true)
748 result = SCARD_ERROR_OK;
752 _ERR("sendMessage failed");
753 result = SCARD_ERROR_IPC_FAILED;
759 _ERR("unavailable session");
760 result = SCARD_ERROR_ILLEGAL_STATE;
766 Channel *Session::openBasicChannelSync(const ByteArray &aid)
767 throw (ErrorIO &, ErrorIllegalState &, ErrorIllegalParameter &, ErrorSecurity &)
769 return openChannelSync(0, aid);
772 Channel *Session::openBasicChannelSync(const unsigned char *aid, unsigned int length)
773 throw (ErrorIO &, ErrorIllegalState &, ErrorIllegalParameter &, ErrorSecurity &)
775 ByteArray temp(aid, length);
777 return openBasicChannelSync(temp);
780 int Session::openBasicChannel(const ByteArray &aid, openChannelCallback callback, void *userData)
782 return openChannel(0, aid, callback, userData);
785 int Session::openBasicChannel(const unsigned char *aid, unsigned int length,
786 openChannelCallback callback, void *userData)
788 ByteArray temp(aid, length);
790 return openBasicChannel(temp, callback, userData);
793 Channel *Session::openLogicalChannelSync(const ByteArray &aid)
794 throw (ErrorIO &, ErrorIllegalState &, ErrorIllegalParameter &, ErrorSecurity &)
796 return openChannelSync(1, aid);
799 Channel *Session::openLogicalChannelSync(const unsigned char *aid, unsigned int length)
800 throw (ErrorIO &, ErrorIllegalState &, ErrorIllegalParameter &, ErrorSecurity &)
802 ByteArray temp(aid, length);
804 return openLogicalChannelSync(temp);
807 int Session::openLogicalChannel(const ByteArray &aid, openChannelCallback callback, void *userData)
809 return openChannel(1, aid, callback, userData);
812 int Session::openLogicalChannel(const unsigned char *aid, unsigned int length,
813 openChannelCallback callback, void *userData)
815 ByteArray temp(aid, length);
817 return openLogicalChannel(temp, callback, userData);
821 bool Session::dispatcherCallback(void *message)
823 Message *msg = (Message *)message;
829 _ERR("message is null");
833 session = (Session *)msg->caller;
835 switch (msg->message)
837 case Message::MSG_REQUEST_OPEN_CHANNEL :
839 Channel *channel = NULL;
841 _INFO("MSG_REQUEST_OPEN_CHANNEL");
843 if (msg->param1 != 0)
845 /* create new instance of channel */
846 channel = new ClientChannel(session->context,
847 session, msg->param2, msg->data, (void *)msg->param1);
850 session->channels.push_back(channel);
854 _ERR("alloc failed");
856 msg->error = SCARD_ERROR_OUT_OF_MEMORY;
860 if (msg->isSynchronousCall() == true) /* synchronized call */
866 session->error = msg->error;
867 session->openedChannel = channel;
869 session->signalCondition();
870 session->syncUnlock();
872 else if (msg->callback != NULL)
874 openChannelCallback cb = (openChannelCallback)msg->callback;
877 cb(channel, msg->error, msg->userParam);
882 case Message::MSG_REQUEST_GET_ATR :
884 _INFO("MSG_REQUEST_GET_ATR");
886 if (msg->isSynchronousCall() == true) /* synchronized call */
891 session->error = msg->error;
892 session->atr = msg->data;
894 session->signalCondition();
895 session->syncUnlock();
897 else if (msg->callback != NULL)
899 getATRCallback cb = (getATRCallback)msg->callback;
902 cb(msg->data.getBuffer(),
910 case Message::MSG_REQUEST_CLOSE_SESSION :
912 _INFO("MSG_REQUEST_CLOSE_SESSION");
914 if (msg->isSynchronousCall() == true) /* synchronized call */
919 session->error = msg->error;
921 session->signalCondition();
922 session->syncUnlock();
924 else if (msg->callback != NULL)
926 closeSessionCallback cb = (closeSessionCallback)msg->callback;
929 cb(msg->error, msg->userParam);
934 case Message::MSG_REQUEST_GET_CHANNEL_COUNT :
936 _INFO("MSG_REQUEST_GET_CHANNEL_COUNT");
938 if (msg->isSynchronousCall() == true) /* synchronized call */
943 session->error = msg->error;
944 session->channelCount = msg->param1;
946 session->signalCondition();
947 session->syncUnlock();
949 else if (msg->callback != NULL)
951 getChannelCountCallback cb = (getChannelCountCallback)msg->callback;
954 cb(msg->param1, msg->error, msg->userParam);
960 _DBG("unknown message : %s", msg->toString().c_str());
969 } /* namespace smartcard_service_api */
972 #define SESSION_EXTERN_BEGIN \
973 if (handle != NULL) \
975 Session *session = (Session *)handle;
977 #define SESSION_EXTERN_END \
981 _ERR("Invalid param"); \
984 using namespace smartcard_service_api;
986 EXTERN_API reader_h session_get_reader(session_h handle)
988 reader_h reader = NULL;
990 SESSION_EXTERN_BEGIN;
991 reader = session->getReader();
997 EXTERN_API int session_get_atr(session_h handle, session_get_atr_cb callback, void *userData)
1001 SESSION_EXTERN_BEGIN;
1002 result = session->getATR((getATRCallback)callback, userData);
1008 EXTERN_API int session_close(session_h handle, session_close_session_cb callback, void *userData)
1012 SESSION_EXTERN_BEGIN;
1013 result = session->close((closeSessionCallback)callback, userData);
1019 EXTERN_API bool session_is_closed(session_h handle)
1021 bool result = false;
1023 SESSION_EXTERN_BEGIN;
1024 result = session->isClosed();
1030 EXTERN_API void session_close_channels(session_h handle)
1032 SESSION_EXTERN_BEGIN;
1033 session->closeChannels();
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)
1042 SESSION_EXTERN_BEGIN;
1043 result = session->openBasicChannel(aid, length, (openChannelCallback)callback, userData);
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)
1054 SESSION_EXTERN_BEGIN;
1055 result = session->openLogicalChannel(aid, length, (openChannelCallback)callback, userData);
1061 EXTERN_API int session_get_channel_count(session_h handle, session_get_channel_count_cb callback, void * userData)
1065 SESSION_EXTERN_BEGIN;
1066 result = session->getChannelCount((getChannelCountCallback)callback, userData);
1072 EXTERN_API void session_destroy_instance(session_h handle)
1076 EXTERN_API int session_get_atr_sync(session_h handle, unsigned char **buffer, unsigned int *length)
1081 #ifdef CLIENT_IPC_THREAD
1082 if (buffer == NULL || length == NULL)
1085 SESSION_EXTERN_BEGIN;
1086 temp = session->getATRSync();
1087 if (temp.size() > 0)
1089 *length = temp.size();
1090 *buffer = (unsigned char *)calloc(1, *length);
1091 memcpy(*buffer, temp.getBuffer(), *length);
1101 EXTERN_API void session_close_sync(session_h handle)
1103 #ifdef CLIENT_IPC_THREAD
1104 SESSION_EXTERN_BEGIN;
1105 session->closeSync();
1110 EXTERN_API channel_h session_open_basic_channel_sync(session_h handle, unsigned char *aid, unsigned int length)
1112 channel_h result = NULL;
1114 #ifdef CLIENT_IPC_THREAD
1115 SESSION_EXTERN_BEGIN;
1116 result = session->openBasicChannelSync(aid, length);
1123 EXTERN_API channel_h session_open_logical_channel_sync(session_h handle, unsigned char *aid, unsigned int length)
1125 channel_h result = NULL;
1127 #ifdef CLIENT_IPC_THREAD
1128 SESSION_EXTERN_BEGIN;
1129 result = session->openLogicalChannelSync(aid, length);
1136 EXTERN_API unsigned int session_get_channel_count_sync(session_h handle)
1138 unsigned int result = 0;
1140 #ifdef CLIENT_IPC_THREAD
1141 SESSION_EXTERN_BEGIN;
1142 result = session->getChannelCountSync();