Remove storing select response every select command
[platform/core/connectivity/smartcard-service.git] / client / ClientChannel.cpp
index 2a035c2..b4d84da 100644 (file)
@@ -1,18 +1,18 @@
 /*
-* Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
-*
-* 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>
@@ -26,6 +26,8 @@
 #include "Message.h"
 #include "ClientIPC.h"
 #include "ClientChannel.h"
+#include "ReaderHelper.h"
+#include "APDUHelper.h"
 
 #ifndef EXTERN_API
 #define EXTERN_API __attribute__((visibility("default")))
@@ -33,7 +35,9 @@
 
 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, ByteArray selectResponse, void *handle)
+               : Channel(session)
        {
                this->channelNum = -1;
                this->handle = NULL;
@@ -41,7 +45,7 @@ namespace smartcard_service_api
 
                if (handle == NULL)
                {
-                       SCARD_DEBUG_ERR("ClientIPC::getInstance() failed");
+                       _ERR("ClientIPC::getInstance() failed");
 
                        return;
                }
@@ -58,108 +62,181 @@ namespace smartcard_service_api
        }
 
        void ClientChannel::closeSync()
+               throw(ExceptionBase &, ErrorIO &, ErrorSecurity &,
+                       ErrorIllegalState &, ErrorIllegalParameter &)
        {
-               Message msg;
-               int rv;
-
 #ifdef CLIENT_IPC_THREAD
                if (isClosed() == false)
                {
-                       /* 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 */
+                       if (getSession()->getReader()->isSecureElementPresent() == true)
+                       {
+                               Message msg;
+                               int rv;
+
+                               /* send message to server */
+                               msg.message = Message::MSG_REQUEST_CLOSE_CHANNEL;
+                               msg.param1 = (unsigned long)handle;
+                               msg.error = (unsigned long)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)
+                                       {
+                                               _ERR("timeout [%d]", rv);
+                                               this->error = SCARD_ERROR_OPERATION_TIMEOUT;
+                                       }
+                               }
+                               else
+                               {
+                                       _ERR("sendMessage failed");
+                                       this->error = SCARD_ERROR_IPC_FAILED;
+                               }
+                               syncUnlock();
 
-                       ClientIPC::getInstance().sendMessage(&msg);
+                               channelNum = -1;
 
-                       syncLock();
-                       rv = waitTimedCondition(0);
-                       syncUnlock();
-
-                       if (rv < 0)
+                               if (this->error != SCARD_ERROR_OK)
+                               {
+                                       ThrowError::throwError(this->error);
+                               }
+                       }
+                       else
                        {
-                               SCARD_DEBUG_ERR("closeSync failed [%d]", rv);
+                               _INFO("unavailable channel");
                        }
-
-                       channelNum = -1;
                }
 #endif
        }
 
        int ClientChannel::close(closeCallback callback, void *userParam)
        {
-               Message msg;
+               int result = SCARD_ERROR_OK;
 
                if (isClosed() == false)
                {
-                       channelNum = -1;
-
-                       /* 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;
-
-                       ClientIPC::getInstance().sendMessage(&msg);
+                       if (getSession()->getReader()->isSecureElementPresent() == true)
+                       {
+                               Message msg;
+                               channelNum = -1;
+
+                               /* send message to server */
+                               msg.message = Message::MSG_REQUEST_CLOSE_CHANNEL;
+                               msg.param1 = (unsigned long)handle;
+                               msg.error = (unsigned long)context; /* using error to context */
+                               msg.caller = (void *)this;
+                               msg.callback = (void *)callback;
+                               msg.userParam = userParam;
+
+                               if (ClientIPC::getInstance().sendMessage(&msg) == false)
+                               {
+                                       _ERR("sendMessage failed");
+                                       result = SCARD_ERROR_IPC_FAILED;
+                               }
+                       }
+                       else
+                       {
+                               _ERR("unavailable channel");
+                               result = SCARD_ERROR_ILLEGAL_STATE;
+                       }
                }
 
-               return 0;
+               return result;
        }
 
        int ClientChannel::transmitSync(ByteArray command, ByteArray &result)
+               throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &,
+                       ErrorIllegalParameter &, ErrorSecurity &)
        {
-               Message msg;
-               int rv;
+               int rv = SCARD_ERROR_OK;
+               if (getSession()->getReader()->isSecureElementPresent() == true)
+               {
+                       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 */
-
-               ClientIPC::getInstance().sendMessage(&msg);
-
-               syncLock();
-               rv = waitTimedCondition(0);
-               syncUnlock();
-
-               if (rv < 0)
-               {
-                       SCARD_DEBUG_ERR("clientIPC is null");
+                       /* send message to server */
+                       msg.message = Message::MSG_REQUEST_TRANSMIT;
+                       msg.param1 = (unsigned long)handle;
+                       msg.param2 = 0;
+                       msg.data = command;
+                       msg.error = (unsigned long)context; /* using error to context */
+                       msg.caller = (void *)this;
+                       msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
 
-                       return -1;
-               }
+                       syncLock();
+                       if (ClientIPC::getInstance().sendMessage(&msg) == true)
+                       {
+                               rv = waitTimedCondition(0);
+                               if (rv >= 0)
+                               {
+                                       result = response;
+                                       rv = SCARD_ERROR_OK;
+                               }
+                               else
+                               {
+                                       _ERR("timeout [%d]", rv);
+                                       this->error = SCARD_ERROR_OPERATION_TIMEOUT;
+                               }
+                       }
+                       else
+                       {
+                               _ERR("sendMessage failed");
+                       }
+                       syncUnlock();
 
-               result = response;
+                       if (this->error != SCARD_ERROR_OK)
+                       {
+                               ThrowError::throwError(this->error);
+                       }
 #endif
-               return 0;
+               }
+               else
+               {
+                       _ERR("unavailable channel");
+                       throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
+               }
+
+               return rv;
        }
 
        int ClientChannel::transmit(ByteArray command, transmitCallback callback, void *userParam)
        {
-               Message msg;
+               int result;
+
+               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;
+                       /* send message to server */
+                       msg.message = Message::MSG_REQUEST_TRANSMIT;
+                       msg.param1 = (unsigned long)handle;
+                       msg.param2 = 0;
+                       msg.data = command;
+                       msg.error = (unsigned long)context; /* using error to context */
+                       msg.caller = (void *)this;
+                       msg.callback = (void *)callback;
+                       msg.userParam = userParam;
 
-               ClientIPC::getInstance().sendMessage(&msg);
+                       if (ClientIPC::getInstance().sendMessage(&msg) == true)
+                       {
+                               result = SCARD_ERROR_OK;
+                       }
+                       else
+                       {
+                               _ERR("sendMessage failed");
+                               result = SCARD_ERROR_IPC_FAILED;
+                       }
+               }
+               else
+               {
+                       _ERR("unavailable channel");
+                       result = SCARD_ERROR_ILLEGAL_STATE;
+               }
 
-               return 0;
+               return result;
        }
 
        bool ClientChannel::dispatcherCallback(void *message)
@@ -170,7 +247,7 @@ namespace smartcard_service_api
 
                if (msg == NULL)
                {
-                       SCARD_DEBUG_ERR("message is null");
+                       _ERR("message is null");
                        return result;
                }
 
@@ -181,9 +258,9 @@ namespace smartcard_service_api
                case Message::MSG_REQUEST_TRANSMIT :
                        {
                                /* transmit result */
-                               SCARD_DEBUG("MSG_REQUEST_TRANSMIT");
+                               _INFO("MSG_REQUEST_TRANSMIT");
 
-                               if (msg->callback == (void *)channel) /* synchronized call */
+                               if (msg->isSynchronousCall() == true) /* synchronized call */
                                {
                                        /* sync call */
                                        channel->syncLock();
@@ -207,9 +284,9 @@ namespace smartcard_service_api
 
                case Message::MSG_REQUEST_CLOSE_CHANNEL :
                        {
-                               SCARD_DEBUG("MSG_REQUEST_CLOSE_CHANNEL");
+                               _INFO("MSG_REQUEST_CLOSE_CHANNEL");
 
-                               if (msg->callback == (void *)channel) /* synchronized call */
+                               if (msg->isSynchronousCall() == true) /* synchronized call */
                                {
                                        /* sync call */
                                        channel->syncLock();
@@ -230,7 +307,7 @@ namespace smartcard_service_api
                        break;
 
                default:
-                       SCARD_DEBUG("unknwon message : %s", msg->toString());
+                       _DBG("Unknown message : %s", msg->toString());
                        break;
                }
 
@@ -250,7 +327,7 @@ namespace smartcard_service_api
        } \
        else \
        { \
-               SCARD_DEBUG_ERR("Invalid param"); \
+               _ERR("Invalid param"); \
        }
 
 using namespace smartcard_service_api;
@@ -266,7 +343,8 @@ EXTERN_API int channel_close(channel_h handle, channel_close_cb callback, void *
        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;
 
@@ -284,12 +362,19 @@ 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;
 
@@ -301,12 +386,20 @@ EXTERN_API int channel_transmit_sync(channel_h handle, unsigned char *command, u
        ByteArray temp, resp;
 
        temp.setBuffer(command, cmd_len);
-       result = channel->transmitSync(temp, resp);
-       if (resp.getLength() > 0)
+
+       try
        {
-               *resp_len = resp.getLength();
-               *response = (unsigned char *)calloc(1, *resp_len);
-               memcpy(*response, resp.getBuffer(), *resp_len);
+               result = channel->transmitSync(temp, resp);
+               if (resp.getLength() > 0)
+               {
+                       *resp_len = resp.getLength();
+                       *response = (unsigned char *)calloc(1, *resp_len);
+                       memcpy(*response, resp.getBuffer(), *resp_len);
+               }
+       }
+       catch (...)
+       {
+               result = -1;
        }
        CHANNEL_EXTERN_END;
 #endif
@@ -347,7 +440,8 @@ EXTERN_API unsigned int channel_get_select_response_length(channel_h handle)
        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;
 
@@ -383,7 +477,5 @@ EXTERN_API session_h channel_get_session(channel_h handle)
 
 EXTERN_API void channel_destroy_instance(channel_h handle)
 {
-       CHANNEL_EXTERN_BEGIN;
-       delete channel;
-       CHANNEL_EXTERN_END;
+       /* do nothing */
 }