/*
-* Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
+ * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
/* standard library header */
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
+#include <glib.h>
/* SLP library header */
/* local header */
#include "Debug.h"
-#include "Message.h"
-#include "ClientIPC.h"
#include "ClientChannel.h"
#include "ReaderHelper.h"
+#include "APDUHelper.h"
+#include "ClientGDBus.h"
#ifndef EXTERN_API
#define EXTERN_API __attribute__((visibility("default")))
namespace smartcard_service_api
{
- ClientChannel::ClientChannel(void *context, Session *session, int channelNum, ByteArray selectResponse, void *handle):Channel(session)
+ ClientChannel::ClientChannel(void *context, Session *session,
+ int channelNum, const ByteArray &selectResponse, void *handle)
+ : Channel(session)
{
this->channelNum = -1;
this->handle = NULL;
if (handle == NULL)
{
- SCARD_DEBUG_ERR("ClientIPC::getInstance() failed");
+ _ERR("ClientIPC::getInstance() failed");
return;
}
this->handle = handle;
this->selectResponse = selectResponse;
this->context = context;
+
+ /* init default context */
+ GError *error = NULL;
+
+ proxy = smartcard_service_channel_proxy_new_for_bus_sync(
+ G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
+ "org.tizen.SmartcardService",
+ "/org/tizen/SmartcardService/Channel",
+ NULL, &error);
+ if (proxy == NULL)
+ {
+ _ERR("Can not create proxy : %s", error->message);
+ g_error_free(error);
+ return;
+ }
}
ClientChannel::~ClientChannel()
closeSync();
}
- void ClientChannel::closeSync()
+ void ClientChannel::channel_transmit_cb(GObject *source_object,
+ GAsyncResult *res, gpointer user_data)
{
-#ifdef CLIENT_IPC_THREAD
- if (isClosed() == false)
- {
- if (getSession()->getReader()->isSecureElementPresent() == true)
- {
- Message msg;
- int rv;
-
- /* send message to server */
- msg.message = Message::MSG_REQUEST_CLOSE_CHANNEL;
- msg.param1 = (int)handle;
- msg.error = (unsigned int)context; /* using error to context */
- msg.caller = (void *)this;
- msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
-
- syncLock();
- if (ClientIPC::getInstance().sendMessage(&msg) == true)
- {
- rv = waitTimedCondition(0);
- if (rv < 0)
- {
- SCARD_DEBUG_ERR("closeSync failed [%d]", rv);
- }
- }
- else
- {
- SCARD_DEBUG_ERR("sendMessage failed");
- }
- syncUnlock();
+ CallbackParam *param = (CallbackParam *)user_data;
+ transmitCallback callback;
+ gint result;
+ GVariant *var_response;
+ GError *error = NULL;
+ ByteArray response;
- channelNum = -1;
- }
- else
- {
- SCARD_DEBUG_ERR("unavailable channel");
+ _INFO("MSG_REQUEST_TRANSMIT");
+
+ if (param == NULL) {
+ _ERR("null parameter!!!");
+ return;
+ }
+
+ callback = (transmitCallback)param->callback;
+
+ if (smartcard_service_channel_call_transmit_finish(
+ SMARTCARD_SERVICE_CHANNEL(source_object),
+ &result, &var_response, res, &error) == true) {
+ if (result == SCARD_ERROR_OK) {
+ GDBusHelper::convertVariantToByteArray(var_response, response);
+ } else {
+ _ERR("smartcard_service_channel_call_transmit failed, [%d]", result);
}
+ } else {
+ _ERR("smartcard_service_channel_call_transmit failed, [%s]", error->message);
+ g_error_free(error);
+
+ result = SCARD_ERROR_IPC_FAILED;
}
-#endif
+
+ if (callback != NULL) {
+ callback(response.getBuffer(),
+ response.size(),
+ result, param->user_param);
+ }
+
+ delete param;
}
- int ClientChannel::close(closeCallback callback, void *userParam)
+ void ClientChannel::channel_close_cb(GObject *source_object,
+ GAsyncResult *res, gpointer user_data)
{
- int result = 0;
+ CallbackParam *param = (CallbackParam *)user_data;
+ ClientChannel *channel;
+ closeChannelCallback callback;
+ gint result;
+ GError *error = NULL;
+
+ _INFO("MSG_REQUEST_CLOSE_CHANNEL");
+ if (param == NULL) {
+ _ERR("null parameter!!!");
+ return;
+ }
+
+ channel = (ClientChannel *)param->instance;
+ callback = (closeChannelCallback)param->callback;
+
+ if (smartcard_service_channel_call_close_channel_finish(
+ SMARTCARD_SERVICE_CHANNEL(source_object),
+ &result, res, &error) == true) {
+ if (result == SCARD_ERROR_OK) {
+ channel->channelNum = -1;
+ } else {
+ _ERR("smartcard_service_channel_call_close_channel failed, [%d]", result);
+ }
+ } else {
+ _ERR("smartcard_service_channel_call_close_channel failed, [%s]", error->message);
+ g_error_free(error);
+
+ result = SCARD_ERROR_IPC_FAILED;
+ }
+
+ if (callback != NULL) {
+ callback(result, param->user_param);
+ }
+
+ delete param;
+ }
+
+ void ClientChannel::closeSync()
+ throw(ExceptionBase &, ErrorIO &, ErrorSecurity &,
+ ErrorIllegalState &, ErrorIllegalParameter &)
+ {
if (isClosed() == false)
{
if (getSession()->getReader()->isSecureElementPresent() == true)
{
- Message msg;
+ gint ret;
+ GError *error = NULL;
- channelNum = -1;
+ if (proxy == NULL) {
+ _ERR("dbus proxy is not initialized yet");
+ throw ErrorIllegalState(SCARD_ERROR_NOT_INITIALIZED);
+ }
- /* send message to server */
- msg.message = Message::MSG_REQUEST_CLOSE_CHANNEL;
- msg.param1 = (int)handle;
- msg.error = (unsigned int)context; /* using error to context */
- msg.caller = (void *)this;
- msg.callback = (void *)callback;
- msg.userParam = userParam;
+ if (smartcard_service_channel_call_close_channel_sync(
+ (SmartcardServiceChannel *)proxy,
+ GPOINTER_TO_UINT(context),
+ GPOINTER_TO_UINT(handle),
+ &ret, NULL, &error) == true) {
+ if (ret != SCARD_ERROR_OK) {
+ _ERR("smartcard_service_channel_call_close_channel_sync failed, [%d]", ret);
+ THROW_ERROR(ret);
+ }
+ } else {
+ _ERR("smartcard_service_channel_call_close_channel_sync failed, [%s]", error->message);
+ g_error_free(error);
- if (ClientIPC::getInstance().sendMessage(&msg) == true)
- {
- result = 0;
- }
- else
- {
- result = -1;
+ throw ErrorIO(SCARD_ERROR_IPC_FAILED);
}
}
else
{
- SCARD_DEBUG_ERR("unavailable channel");
- result = -1;
+ _INFO("unavailable channel");
}
}
-
- return result;
}
- int ClientChannel::transmitSync(ByteArray command, ByteArray &result)
+ int ClientChannel::close(closeChannelCallback callback, void *userParam)
{
- int rv = -1;
+ int result = SCARD_ERROR_OK;
- if (getSession()->getReader()->isSecureElementPresent() == true)
+ if (isClosed() == false)
{
- Message msg;
-
-#ifdef CLIENT_IPC_THREAD
- /* send message to server */
- msg.message = Message::MSG_REQUEST_TRANSMIT;
- msg.param1 = (int)handle;
- msg.param2 = 0;
- msg.data = command;
- msg.error = (unsigned int)context; /* using error to context */
- msg.caller = (void *)this;
- msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
-
- syncLock();
- if (ClientIPC::getInstance().sendMessage(&msg) == true)
+ if (getSession()->getReader()->isSecureElementPresent() == true)
{
- rv = waitTimedCondition(0);
- if (rv >= 0)
- {
- result = response;
+ CallbackParam *param = new CallbackParam();
- rv = 0;
- }
- else
- {
- SCARD_DEBUG_ERR("clientIPC is null");
+ param->instance = this;
+ param->callback = (void *)callback;
+ param->user_param = userParam;
- rv = -1;
- }
+ smartcard_service_channel_call_close_channel(
+ (SmartcardServiceChannel *)proxy,
+ GPOINTER_TO_UINT(context),
+ GPOINTER_TO_UINT(handle), NULL,
+ &ClientChannel::channel_close_cb, param);
}
else
{
- SCARD_DEBUG_ERR("sendMessage failed");
+ _ERR("unavailable channel");
+ result = SCARD_ERROR_ILLEGAL_STATE;
}
- syncUnlock();
-#endif
- }
- else
- {
- SCARD_DEBUG_ERR("unavailable channel");
}
- return rv;
+ return result;
}
- int ClientChannel::transmit(ByteArray command, transmitCallback callback, void *userParam)
+ int ClientChannel::transmitSync(const ByteArray &command, ByteArray &result)
+ throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &,
+ ErrorIllegalParameter &, ErrorSecurity &)
{
- int result = -1;
+ int rv = SCARD_ERROR_OK;
if (getSession()->getReader()->isSecureElementPresent() == true)
{
- Message msg;
-
- /* send message to server */
- msg.message = Message::MSG_REQUEST_TRANSMIT;
- msg.param1 = (int)handle;
- msg.param2 = 0;
- msg.data = command;
- msg.error = (unsigned int)context; /* using error to context */
- msg.caller = (void *)this;
- msg.callback = (void *)callback;
- msg.userParam = userParam;
-
- if (ClientIPC::getInstance().sendMessage(&msg) == true)
- {
- result = 0;
- }
- else
- {
- result = -1;
+ GVariant *var_command = NULL, *var_response = NULL;
+ GError *error = NULL;
+
+ var_command = GDBusHelper::convertByteArrayToVariant(command);
+
+ if (smartcard_service_channel_call_transmit_sync(
+ (SmartcardServiceChannel *)proxy,
+ GPOINTER_TO_UINT(context),
+ GPOINTER_TO_UINT(handle),
+ var_command, &rv, &var_response,
+ NULL, &error) == true) {
+
+ if (rv == SCARD_ERROR_OK) {
+ GDBusHelper::convertVariantToByteArray(var_response, result);
+ } else {
+ _ERR("smartcard_service_session_call_get_atr_sync failed, [%d]", rv);
+ THROW_ERROR(rv);
+ }
+ } else {
+ _ERR("smartcard_service_session_call_get_atr_sync failed, [%s]", error->message);
+ g_error_free(error);
+
+ throw ErrorIO(SCARD_ERROR_IPC_FAILED);
}
}
else
{
- SCARD_DEBUG_ERR("unavailable channel");
+ _ERR("unavailable channel");
+ throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
}
- return result;
+ return rv;
}
- bool ClientChannel::dispatcherCallback(void *message)
+ int ClientChannel::transmit(const ByteArray &command, transmitCallback callback, void *userParam)
{
- Message *msg = (Message *)message;
- ClientChannel *channel = NULL;
- bool result = false;
-
- if (msg == NULL)
- {
- SCARD_DEBUG_ERR("message is null");
- return result;
- }
-
- channel = (ClientChannel *)msg->caller;
+ int result;
- switch (msg->message)
+ if (getSession()->getReader()->isSecureElementPresent() == true)
{
- case Message::MSG_REQUEST_TRANSMIT :
- {
- /* transmit result */
- SCARD_DEBUG("MSG_REQUEST_TRANSMIT");
-
- if (msg->isSynchronousCall() == true) /* synchronized call */
- {
- /* sync call */
- channel->syncLock();
-
- /* copy result */
- channel->error = msg->error;
- channel->response = msg->data;
-
- channel->signalCondition();
- channel->syncUnlock();
- }
- else if (msg->callback != NULL)
- {
- transmitCallback cb = (transmitCallback)msg->callback;
+ GVariant *var_command;
+ CallbackParam *param = new CallbackParam();
- /* async call */
- cb(msg->data.getBuffer(), msg->data.getLength(), msg->error, msg->userParam);
- }
- }
- break;
-
- case Message::MSG_REQUEST_CLOSE_CHANNEL :
- {
- SCARD_DEBUG("MSG_REQUEST_CLOSE_CHANNEL");
+ param->instance = this;
+ param->callback = (void *)callback;
+ param->user_param = userParam;
- if (msg->isSynchronousCall() == true) /* synchronized call */
- {
- /* sync call */
- channel->syncLock();
+ var_command = GDBusHelper::convertByteArrayToVariant(command);
- channel->error = msg->error;
+ smartcard_service_channel_call_transmit(
+ (SmartcardServiceChannel *)proxy,
+ GPOINTER_TO_UINT(context),
+ GPOINTER_TO_UINT(handle),
+ var_command, NULL,
+ &ClientChannel::channel_transmit_cb, param);
- channel->signalCondition();
- channel->syncUnlock();
- }
- else if (msg->callback != NULL)
- {
- closeCallback cb = (closeCallback)msg->callback;
-
- /* async call */
- cb(msg->error, msg->userParam);
- }
- }
- break;
-
- default:
- SCARD_DEBUG("unknwon message : %s", msg->toString());
- break;
+ result = SCARD_ERROR_OK;
+ }
+ else
+ {
+ _ERR("unavailable channel");
+ result = SCARD_ERROR_ILLEGAL_STATE;
}
return result;
} \
else \
{ \
- SCARD_DEBUG_ERR("Invalid param"); \
+ _ERR("Invalid param"); \
}
using namespace smartcard_service_api;
int result = -1;
CHANNEL_EXTERN_BEGIN;
- result = channel->close((closeCallback)callback, userParam);
+ result = channel->close((closeChannelCallback)callback, userParam);
CHANNEL_EXTERN_END;
return result;
}
-EXTERN_API int channel_transmit(channel_h handle, unsigned char *command, unsigned int length, channel_transmit_cb callback, void *userParam)
+EXTERN_API int channel_transmit(channel_h handle, unsigned char *command,
+ unsigned int length, channel_transmit_cb callback, void *userParam)
{
int result = -1;
CHANNEL_EXTERN_BEGIN;
ByteArray temp;
- temp.setBuffer(command, length);
+ temp.assign(command, length);
result = channel->transmit(temp, (transmitCallback)callback, userParam);
CHANNEL_EXTERN_END;
EXTERN_API void channel_close_sync(channel_h handle)
{
-#ifdef CLIENT_IPC_THREAD
CHANNEL_EXTERN_BEGIN;
- channel->closeSync();
+ try
+ {
+ channel->closeSync();
+ }
+ catch (...)
+ {
+ }
CHANNEL_EXTERN_END;
-#endif
}
-EXTERN_API int channel_transmit_sync(channel_h handle, unsigned char *command, unsigned int cmd_len, unsigned char **response, unsigned int *resp_len)
+EXTERN_API int channel_transmit_sync(channel_h handle, unsigned char *command,
+ unsigned int cmd_len, unsigned char **response, unsigned int *resp_len)
{
int result = -1;
-#ifdef CLIENT_IPC_THREAD
if (command == NULL || cmd_len == 0 || response == NULL || resp_len == NULL)
return result;
CHANNEL_EXTERN_BEGIN;
ByteArray temp, resp;
- temp.setBuffer(command, cmd_len);
- result = channel->transmitSync(temp, resp);
- if (resp.getLength() > 0)
+ temp.assign(command, cmd_len);
+
+ try
+ {
+ result = channel->transmitSync(temp, resp);
+ if (resp.size() > 0)
+ {
+ *resp_len = resp.size();
+ *response = (unsigned char *)calloc(1, *resp_len);
+ memcpy(*response, resp.getBuffer(), *resp_len);
+ }
+ }
+ catch (...)
{
- *resp_len = resp.getLength();
- *response = (unsigned char *)calloc(1, *resp_len);
- memcpy(*response, resp.getBuffer(), *resp_len);
+ result = -1;
}
CHANNEL_EXTERN_END;
-#endif
return result;
}
unsigned int result = 0;
CHANNEL_EXTERN_BEGIN;
- result = channel->getSelectResponse().getLength();
+ result = channel->getSelectResponse().size();
CHANNEL_EXTERN_END;
return result;
}
-EXTERN_API bool channel_get_select_response(channel_h handle, unsigned char *buffer, unsigned int length)
+EXTERN_API bool channel_get_select_response(channel_h handle,
+ unsigned char *buffer, unsigned int length)
{
bool result = false;
ByteArray response;
response = channel->getSelectResponse();
- if (response.getLength() > 0)
+ if (response.size() > 0)
{
- memcpy(buffer, response.getBuffer(), MIN(length, response.getLength()));
+ memcpy(buffer, response.getBuffer(), MIN(length, response.size()));
result = true;
}
CHANNEL_EXTERN_END;
EXTERN_API void channel_destroy_instance(channel_h handle)
{
- CHANNEL_EXTERN_BEGIN;
- delete channel;
- CHANNEL_EXTERN_END;
+ /* do nothing */
}