Adjust comment
[platform/core/connectivity/smartcard-service.git] / server / ServerResource.cpp
index f8ad898..7cc61dc 100644 (file)
@@ -1,19 +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 <stdio.h>
 #include "SignatureHelper.h"
 #include "GPSEACL.h"
 
+#ifndef EXTERN_API
+#define EXTERN_API __attribute__((visibility("default")))
+#endif
+
 namespace smartcard_service_api
 {
        unsigned int IntegerHandle::newHandle = 0;
@@ -75,7 +78,7 @@ namespace smartcard_service_api
 
 #define OMAPI_SE_PATH "/usr/lib/se"
 
-       ServerResource::ServerResource()
+       ServerResource::ServerResource() : mainLoop(NULL)
        {
                SCARD_BEGIN();
 
@@ -148,6 +151,11 @@ namespace smartcard_service_api
                }
        }
 
+       int ServerResource::getClientCount()
+       {
+               return (int)mapClients.size();
+       }
+
        void ServerResource::removeClient(int socket)
        {
                map<int, ClientInstance *>::iterator item;
@@ -161,7 +169,7 @@ namespace smartcard_service_api
                }
                else
                {
-                       SCARD_DEBUG("client exists already [%d]", socket);
+                       SCARD_DEBUG("client removed already [%d]", socket);
                }
        }
 
@@ -278,7 +286,41 @@ namespace smartcard_service_api
                return result;
        }
 
-       unsigned int ServerResource::createSession(int socket, unsigned int context, unsigned int terminalID, ByteArray packageCert, void *caller)
+       Terminal *ServerResource::getTerminalByReaderID(unsigned int readerID)
+       {
+               Terminal *result = NULL;
+               map<unsigned int, unsigned int>::iterator item;
+
+               if ((item = mapReaders.find(readerID)) != mapReaders.end())
+               {
+                       result = getTerminal(item->second);
+               }
+               else
+               {
+                       SCARD_DEBUG_ERR("Terminal doesn't exist, reader ID [%d]", readerID);
+               }
+
+               return result;
+       }
+
+       unsigned int ServerResource::getTerminalID(const char *name)
+       {
+               unsigned int result = IntegerHandle::INVALID_HANDLE;
+               map<unsigned int, Terminal *>::iterator item;
+
+               for (item = mapTerminals.begin(); item != mapTerminals.end(); item++)
+               {
+                       if (strncmp(name, item->second->getName(), strlen(name)) == 0)
+                       {
+                               result = item->first;
+                               break;
+                       }
+               }
+
+               return result;
+       }
+
+       unsigned int ServerResource::createSession(int socket, unsigned int context, unsigned int readerID, vector<ByteArray> &certHashes, void *caller)
        {
                unsigned int result = -1;
                Terminal *temp = NULL;
@@ -286,9 +328,9 @@ namespace smartcard_service_api
 
                if ((instance = getService(socket, context)) != NULL)
                {
-                       if ((temp = getTerminal(terminalID)) != NULL)
+                       if ((temp = getTerminalByReaderID(readerID)) != NULL)
                        {
-                               result = instance->openSession(temp, packageCert, caller);
+                               result = instance->openSession(temp, certHashes, caller);
                        }
                }
                else
@@ -347,126 +389,284 @@ namespace smartcard_service_api
                }
        }
 
-       unsigned int ServerResource::createChannel(int socket, unsigned int context, unsigned int sessionID, int channelType, ByteArray aid)
+       bool ServerResource::_isAuthorizedAccess(ServerChannel *channel, int pid, ByteArray aid, vector<ByteArray> &hashes)
        {
-               unsigned int result = -1;
-               ServiceInstance *client = NULL;
+               bool result = true;
+
+#if 1 /* disable for temporary */
+               char filename[1024] = { 0, };
+               AccessControlList *acList = NULL;
 
-               if ((client = getService(socket, context)) != NULL)
+               /* check exceptional case */
+               SignatureHelper::getProcessName(pid, filename, sizeof(filename));
+               if (strncmp(filename, "ozD3Dw1MZruTDKHWGgYaDib2B2LV4/nfT+8b/g1Vsk8=", sizeof(filename)) != 0)
                {
-                       if (client->isVaildSessionHandle(sessionID) == true)
+                       /* request open channel sequence */
+                       if ((acList = getAccessControlList(channel)) != NULL)
                        {
-                               AccessControlList *acList = NULL;
-                               ServerSession *session = NULL;
-                               Terminal *terminal = NULL;
-
-                               terminal = client->getTerminal(sessionID);
-                               session = client->getSession(sessionID);
-                               if (terminal != NULL && session != NULL)
-                               {
-                                       int rv = 0;
-                                       int channelNum = 0;
-                                       ByteArray certHash;
-                                       ByteArray selectResponse;
-                                       ByteArray command;
-                                       char filename[1024] = { 0, };
-
-                                       /* check exceptional case */
-                                       SignatureHelper::getProcessName(client->getParent()->getPID(), filename, sizeof(filename));
-                                       if (strncmp(filename, "ozD3Dw1MZruTDKHWGgYaDib2B2LV4/nfT+8b/g1Vsk8=", sizeof(filename)) != 0)
-                                       {
 #if 1
-                                               certHash = session->packageCert;
+                               PKCS15 pkcs15(channel);
+
+                               acList->loadACL(channel);
+                               result = acList->isAuthorizedAccess(aid, hashes);
 #else
-                                               certHash = client->getParent()->getCertificationHash();
+                               result = acList->isAuthorizedAccess(aid, session->packageCert);
+#endif
+                       }
+                       else
+                       {
+                               SCARD_DEBUG_ERR("acList is null");
+                               result = false;
+                       }
+               }
 #endif
-                                               /* request open channel sequence */
-                                               if ((acList = getAccessControlList(terminal)) == NULL)
-                                               {
-                                                       SCARD_DEBUG_ERR("acList is null");
 
-                                                       return result;
-                                               }
+               return result;
+       }
 
-                                               if (acList->isAuthorizedAccess(aid, certHash) == false)
-                                               {
-                                                       SCARD_DEBUG_ERR("unauthorized access, aid %s, hash %s", aid.toString(), certHash.toString());
+#if 0
+       unsigned int ServerResource::_createChannel(Terminal *terminal, ServiceInstance *service, int channelType, unsigned int sessionID, ByteArray aid)
+       {
+               unsigned int result = IntegerHandle::INVALID_HANDLE;
+               int rv = 0;
+               int channelNum = 0;
+               ByteArray command;
+               ByteArray response;
 
-                                                       return result;
-                                               }
-                                       }
+               if (channelType == 1)
+               {
+                       /* open channel */
+                       command = APDUHelper::generateAPDU(APDUHelper::COMMAND_OPEN_LOGICAL_CHANNEL, 0, ByteArray::EMPTY);
+                       rv = terminal->transmitSync(command, response);
 
-                                       if (channelType == 1)
-                                       {
-                                               ByteArray response;
+                       if (rv == 0 && response.getLength() >= 2)
+                       {
+                               ResponseHelper resp(response);
 
-                                               /* open channel */
-                                               command = APDUHelper::generateAPDU(APDUHelper::COMMAND_OPEN_LOGICAL_CHANNEL, 0, ByteArray::EMPTY);
-                                               rv = terminal->transmitSync(command, response);
+                               if (resp.getStatus() == 0)
+                               {
+                                       channelNum = resp.getDataField()[0];
 
-                                               if (rv == 0 && response.getLength() >= 2)
-                                               {
-                                                       ResponseHelper resp(response);
+                                       SCARD_DEBUG("channelNum [%d]", channelNum);
+                               }
+                               else
+                               {
+                                       SCARD_DEBUG_ERR("status word [%d][ %02X %02X ]", resp.getStatus(), resp.getSW1(), resp.getSW2());
 
-                                                       if (resp.getStatus() == 0)
-                                                       {
-                                                               channelNum = resp.getDataField()[0];
+                                       return result;
+                               }
+                       }
+                       else
+                       {
+                               SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", rv, response.getLength());
 
-                                                               SCARD_DEBUG("channelNum [%d]", channelNum);
-                                                       }
-                                                       else
-                                                       {
-                                                               SCARD_DEBUG_ERR("status word [%d][ 0x%02X 0x%02X ]", resp.getStatus(), response[response.getLength() - 2], response[response.getLength() - 1]);
+                               return result;
+                       }
+               }
 
-                                                               return result;
-                                                       }
-                                               }
-                                               else
-                                               {
-                                                       SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", rv, response.getLength());
+               /* select aid */
+               APDUCommand apdu;
+               apdu.setCommand(0, APDUCommand::INS_SELECT_FILE, APDUCommand::P1_SELECT_BY_DF_NAME, APDUCommand::P2_SELECT_GET_FCP, aid, 0);
+               apdu.setChannel(1, channelNum);
+               apdu.getBuffer(command);
 
-                                                       return result;
-                                               }
-                                       }
+               rv = terminal->transmitSync(command, response);
+               if (rv == 0 && response.getLength() >= 2)
+               {
+                       ResponseHelper resp(response);
 
-                                       /* select aid */
-                                       command = APDUHelper::generateAPDU(APDUHelper::COMMAND_SELECT_BY_DF_NAME, channelNum, aid);
-                                       rv = terminal->transmitSync(command, selectResponse);
-                                       if (rv == 0 && selectResponse.getLength() >= 2)
-                                       {
-                                               ResponseHelper resp(selectResponse);
+                       if (resp.getStatus() == 0)
+                       {
+                               result = service->openChannel(sessionID, channelNum, response);
+                               if (result == IntegerHandle::INVALID_HANDLE)
+                               {
+                                       SCARD_DEBUG_ERR("channel is null.");
+                               }
+                       }
+                       else
+                       {
+                               SCARD_DEBUG_ERR("status word [%d][ %02X %02X ]", resp.getStatus(), resp.getSW1(), resp.getSW2());
+                       }
+               }
+               else
+               {
+                       SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", rv, response.getLength());
+               }
 
-                                               if (resp.getStatus() == 0)
-                                               {
-                                                       result = client->openChannel(sessionID, channelNum);
-                                                       if (result != IntegerHandle::INVALID_HANDLE)
-                                                       {
-                                                               ServerChannel *temp = (ServerChannel *)client->getChannel(result);
-                                                               if (temp != NULL)
-                                                               {
-                                                                       /* set select response */
-                                                                       temp->selectResponse = selectResponse;
-                                                               }
-                                                               else
-                                                               {
-                                                                       SCARD_DEBUG_ERR("IS IT POSSIBLE??????????????????");
-                                                               }
-                                                       }
-                                                       else
-                                                       {
-                                                               SCARD_DEBUG_ERR("channel is null.");
-                                                       }
-                                               }
-                                               else
-                                               {
-                                                       SCARD_DEBUG_ERR("status word [%d][ 0x%02X 0x%02X ]", resp.getStatus(), selectResponse[selectResponse.getLength() - 2], selectResponse[selectResponse.getLength() - 1]);
-                                               }
-                                       }
-                                       else
+               return result;
+       }
+#else
+       int ServerResource::_openLogicalChannel(Terminal *terminal)
+       {
+               int result = -1;
+               int rv = 0;
+               ByteArray command;
+               ByteArray response;
+
+               /* open channel */
+               command = APDUHelper::generateAPDU(APDUHelper::COMMAND_OPEN_LOGICAL_CHANNEL, 0, ByteArray::EMPTY);
+               rv = terminal->transmitSync(command, response);
+               if (rv == 0 && response.getLength() >= 2)
+               {
+                       ResponseHelper resp(response);
+
+                       if (resp.getStatus() == 0)
+                       {
+                               result = resp.getDataField()[0];
+                       }
+                       else
+                       {
+                               SCARD_DEBUG_ERR("status word [%d][ %02X %02X ]", resp.getStatus(), resp.getSW1(), resp.getSW2());
+                               if (0)
+                               {
+                                       /* TODO : if there is no more channel, return error code */
+                                       SCARD_DEBUG_ERR("no more logical channel");
+                                       result = -2;
+                               }
+                       }
+               }
+               else
+               {
+                       SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", rv, response.getLength());
+               }
+
+               return result;
+       }
+
+       int ServerResource::_closeLogicalChannel(Terminal *terminal, int channelNum)
+       {
+               int result = -1;
+               int rv = 0;
+               ByteArray command;
+               ByteArray response;
+
+               /* open channel */
+               command = APDUHelper::generateAPDU(APDUHelper::COMMAND_CLOSE_LOGICAL_CHANNEL, channelNum, ByteArray::EMPTY);
+               rv = terminal->transmitSync(command, response);
+               if (rv == 0 && response.getLength() >= 2)
+               {
+                       ResponseHelper resp(response);
+
+                       if (resp.getStatus() == 0)
+                       {
+                               SCARD_DEBUG("channel closed [%d]", channelNum);
+                               result = 0;
+                       }
+                       else
+                       {
+                               SCARD_DEBUG_ERR("status word [%d][ %02X %02X ]", resp.getStatus(), resp.getSW1(), resp.getSW2());
+                       }
+               }
+               else
+               {
+                       SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", rv, response.getLength());
+               }
+
+               return result;
+       }
+
+       unsigned int ServerResource::_createChannel(Terminal *terminal, ServiceInstance *service, int channelType, unsigned int sessionID, ByteArray aid)
+       {
+               unsigned int result = IntegerHandle::INVALID_HANDLE;
+               int channelNum = 0;
+               ServerChannel *channel = NULL;
+
+               /* open logical channel */
+               if (channelType == 1)
+               {
+                       channelNum = _openLogicalChannel(terminal);
+                       if (channelNum > 0)
+                       {
+                               SCARD_DEBUG("channelNum [%d]", result);
+                       }
+                       else
+                       {
+                               SCARD_DEBUG_ERR("_openLogicalChannel failed [%d]", channelNum);
+                               return result;
+                       }
+               }
+
+               /* create channel instance */
+               result = service->openChannel(sessionID, channelNum, ByteArray::EMPTY);
+               if (result == IntegerHandle::INVALID_HANDLE)
+               {
+                       SCARD_DEBUG_ERR("channel is null.");
+
+                       /* close logical channel */
+                       if (channelNum > 0)
+                       {
+                               _closeLogicalChannel(terminal, channelNum);
+                       }
+                       return result;
+               }
+
+               channel = service->getChannel(result);
+
+               /* check */
+               if (_isAuthorizedAccess(channel, service->getParent()->getPID(),
+                               aid, service->getParent()->getCertificationHashes()) == true)
+               {
+                       int rv = 0;
+                       ByteArray command;
+                       ByteArray response;
+
+                       /* select aid */
+                       command = APDUHelper::generateAPDU(APDUHelper::COMMAND_SELECT_BY_DF_NAME, channelNum, aid);
+                       rv = channel->transmitSync(command, response);
+                       if (rv == 0 && response.getLength() >= 2)
+                       {
+                               ResponseHelper resp(response);
+
+                               if (resp.getStatus() == 0)
+                               {
+                                       channel->selectResponse = response;
+                                       /* remove privilege mode */
+                                       channel->unsetPrivilegeMode();
+                               }
+                               else
+                               {
+                                       SCARD_DEBUG_ERR("status word [%d][ %02X %02X ]", resp.getStatus(), resp.getSW1(), resp.getSW2());
+                               }
+                       }
+                       else
+                       {
+                               SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", rv, response.getLength());
+                       }
+               }
+               else
+               {
+                       SCARD_DEBUG_ERR("unauthorized access");
+
+                       service->closeChannel(result);
+                       result = IntegerHandle::INVALID_HANDLE;
+               }
+
+
+               return result;
+       }
+#endif
+
+       unsigned int ServerResource::createChannel(int socket, unsigned int context, unsigned int sessionID, int channelType, ByteArray aid)
+       {
+               unsigned int result = -1;
+               ServiceInstance *service = NULL;
+
+               if ((service = getService(socket, context)) != NULL)
+               {
+                       if (service->isVaildSessionHandle(sessionID) == true)
+                       {
+                               ServerSession *session = NULL;
+                               Terminal *terminal = NULL;
+
+                               terminal = service->getTerminal(sessionID);
+                               session = service->getSession(sessionID);
+                               if (terminal != NULL && session != NULL)
+                               {
+                                       result = _createChannel(terminal, service, channelType, sessionID, aid);
+                                       if (result == IntegerHandle::INVALID_HANDLE)
                                        {
-                                               SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", rv, selectResponse.getLength());
+                                               SCARD_DEBUG_ERR("create channel failed [%d]", sessionID);
                                        }
-
                                }
                                else
                                {
@@ -480,7 +680,7 @@ namespace smartcard_service_api
                }
                else
                {
-                       SCARD_DEBUG_ERR("getClient is failed [%d] [%d]", socket, context);
+                       SCARD_DEBUG_ERR("getService is failed [%d] [%d]", socket, context);
                }
 
                return result;
@@ -524,21 +724,37 @@ namespace smartcard_service_api
 
                if ((item = mapACL.find(terminal)) == mapACL.end())
                {
-                       ServerChannel *channel = new ServerChannel(NULL, NULL, 0, terminal);
-                       if (channel != NULL)
+                       /* load access control */
+                       result = new GPSEACL();
+                       if (result != NULL)
                        {
-                               /* load access control */
-                               result = new GPSEACL(channel);
-                               if (result != NULL)
-                               {
-                                       result->loadACL();
+                               mapACL.insert(make_pair(terminal, result));
+                       }
+                       else
+                       {
+                               SCARD_DEBUG_ERR("alloc failed");
+                       }
+               }
+               else
+               {
+                       result = item->second;
+               }
 
-                                       mapACL.insert(make_pair(terminal, result));
-                               }
-                               else
-                               {
-                                       SCARD_DEBUG_ERR("alloc failed");
-                               }
+               return result;
+       }
+
+       AccessControlList *ServerResource::getAccessControlList(ServerChannel *channel)
+       {
+               AccessControlList *result = NULL;
+               map<Terminal *, AccessControlList *>::iterator item;
+
+               if ((item = mapACL.find(channel->getTerminal())) == mapACL.end())
+               {
+                       /* load access control */
+                       result = new GPSEACL();
+                       if (result != NULL)
+                       {
+                               mapACL.insert(make_pair(channel->getTerminal(), result));
                        }
                        else
                        {
@@ -602,6 +818,11 @@ namespace smartcard_service_api
 
                                SCARD_DEBUG("register success [%s] [%p] [%s] [%p]", library, libHandle, terminal->getName(), terminal);
 
+                               if (terminal->isSecureElementPresence() == true)
+                               {
+                                       createReader(handle);
+                               }
+
                                result = true;
                        }
                        else
@@ -684,14 +905,14 @@ namespace smartcard_service_api
 
        bool ServerResource::isValidReaderHandle(unsigned int reader)
        {
-               return (getTerminal(reader) != NULL);
+               return (getTerminalByReaderID(reader) != NULL);
        }
 
        bool ServerResource::isValidSessionHandle(int socket, unsigned int context, unsigned int session)
        {
                ServiceInstance *instance = NULL;
 
-               return (((instance = getService(socket, context)) != NULL) && (getService(socket, context)->isVaildSessionHandle(session)));
+               return (((instance = getService(socket, context)) != NULL) && (instance->isVaildSessionHandle(session)));
        }
 
        int ServerResource::getReadersInformation(ByteArray &info)
@@ -702,16 +923,24 @@ namespace smartcard_service_api
                unsigned int offset = 0;
                unsigned int nameLen = 0;
 
-               if (mapTerminals.size() > 0)
+               if (mapReaders.size() > 0)
                {
-                       map<unsigned int, Terminal *>::iterator item;
+                       Terminal *terminal = NULL;
+                       map<unsigned int, unsigned int>::iterator item;
 
-                       for (item = mapTerminals.begin(); item != mapTerminals.end(); item++)
+                       for (item = mapReaders.begin(); item != mapReaders.end(); item++)
                        {
-                               if (item->second->isSecureElementPresence())
+                               if (item->second != IntegerHandle::INVALID_HANDLE)
                                {
-                                       length += sizeof(nameLen) + strlen(item->second->getName()) + sizeof(unsigned int);
-                                       result++;
+                                       terminal = getTerminal(item->second);
+                                       if (terminal != NULL)
+                                       {
+                                               if (terminal->isSecureElementPresence())
+                                               {
+                                                       length += sizeof(nameLen) + strlen(terminal->getName()) + sizeof(unsigned int);
+                                                       result++;
+                                               }
+                                       }
                                }
                        }
 
@@ -720,20 +949,27 @@ namespace smartcard_service_api
                        {
                                memset(buffer, 0, length);
 
-                               for (item = mapTerminals.begin(); item != mapTerminals.end(); item++)
+                               for (item = mapReaders.begin(); item != mapReaders.end(); item++)
                                {
-                                       if (item->second->isSecureElementPresence())
+                                       if (item->second != IntegerHandle::INVALID_HANDLE)
                                        {
-                                               nameLen = strlen(item->second->getName());
+                                               terminal = getTerminal(item->second);
+                                               if (terminal != NULL)
+                                               {
+                                                       if (terminal->isSecureElementPresence())
+                                                       {
+                                                               nameLen = strlen(terminal->getName());
 
-                                               memcpy(buffer + offset, &nameLen, sizeof(nameLen));
-                                               offset += sizeof(nameLen);
+                                                               memcpy(buffer + offset, &nameLen, sizeof(nameLen));
+                                                               offset += sizeof(nameLen);
 
-                                               memcpy(buffer + offset, item->second->getName(), nameLen);
-                                               offset += nameLen;
+                                                               memcpy(buffer + offset, terminal->getName(), nameLen);
+                                                               offset += nameLen;
 
-                                               memcpy(buffer + offset, &item->first, sizeof(unsigned int));
-                                               offset += sizeof(unsigned int);
+                                                               memcpy(buffer + offset, &item->first, sizeof(unsigned int));
+                                                               offset += sizeof(unsigned int);
+                                                       }
+                                               }
                                        }
                                }
 
@@ -770,47 +1006,105 @@ namespace smartcard_service_api
 
        void ServerResource::terminalCallback(void *terminal, int event, int error, void *user_param)
        {
-               SCARD_BEGIN();
+               SCARD_DEBUG("terminal [%s], event [%d], error [%d], user_param [%p]", (char *)terminal, event, error, user_param);
 
                switch (event)
                {
                case Terminal::NOTIFY_SE_AVAILABLE :
                        {
+                               ServerResource &instance = ServerResource::getInstance();
+                               unsigned int terminalID = IntegerHandle::INVALID_HANDLE;
                                Message msg;
 
                                SCARD_DEBUG("[NOTIFY_SE_AVAILABLE]");
 
-                               SCARD_DEBUG("terminal [%s], event [%d], error [%d], user_param [%p]", (char *)terminal, event, error, user_param);
-
-                               /* send all client to refresh reader */
-                               msg.message = msg.MSG_NOTIFY_SE_INSERTED;
-                               msg.data.setBuffer((unsigned char *)terminal, strlen((char *)terminal) + 1);
+                               terminalID = instance.getTerminalID((char *)terminal);
+                               if (terminalID != IntegerHandle::INVALID_HANDLE)
+                               {
+                                       /* send all client to refresh reader */
+                                       msg.message = msg.MSG_NOTIFY_SE_INSERTED;
+                                       msg.param1 = instance.createReader(terminalID);
+                                       msg.data.setBuffer((unsigned char *)terminal, strlen((char *)terminal) + 1);
 
-                               ServerResource::getInstance().sendMessageToAllClients(msg);
+                                       instance.sendMessageToAllClients(msg);
+                               }
                        }
                        break;
 
                case Terminal::NOTIFY_SE_NOT_AVAILABLE :
                        {
+                               ServerResource &instance = ServerResource::getInstance();
+                               unsigned int readerID = IntegerHandle::INVALID_HANDLE;
                                Message msg;
 
                                SCARD_DEBUG("[NOTIFY_SE_NOT_AVAILABLE]");
 
-                               SCARD_DEBUG("terminal [%s], event [%d], error [%d], user_param [%p]", (char *)terminal, event, error, user_param);
+                               readerID = instance.getReaderID((char *)terminal);
 
                                /* send all client to refresh reader */
                                msg.message = msg.MSG_NOTIFY_SE_REMOVED;
+                               msg.param1 = readerID;
                                msg.data.setBuffer((unsigned char *)terminal, strlen((char *)terminal) + 1);
 
-                               ServerResource::getInstance().sendMessageToAllClients(msg);
+                               instance.sendMessageToAllClients(msg);
+                               instance.removeReader(readerID);
                        }
                        break;
 
                default :
+                       SCARD_DEBUG("terminal [%s], event [%d], error [%d], user_param [%p]", (char *)terminal, event, error, user_param);
                        break;
                }
+       }
 
-               SCARD_END();
+       unsigned int ServerResource::createReader(unsigned int terminalID)
+       {
+               unsigned int result = -1;
+
+               result = IntegerHandle::assignHandle();
+
+               mapReaders.insert(make_pair(result, terminalID));
+
+               return result;
+       }
+
+       unsigned int ServerResource::getReaderID(const char *name)
+       {
+               unsigned int result = IntegerHandle::INVALID_HANDLE, terminalID = IntegerHandle::INVALID_HANDLE;
+
+               terminalID = getTerminalID(name);
+               if (terminalID != IntegerHandle::INVALID_HANDLE)
+               {
+                       map<unsigned int, unsigned int>::iterator item;
+
+                       for (item = mapReaders.begin(); item != mapReaders.end(); item++)
+                       {
+                               if (item->second == terminalID)
+                               {
+                                       result = item->first;
+                                       break;
+                               }
+                       }
+               }
+
+               return result;
+       }
+
+       void ServerResource::removeReader(unsigned int readerID)
+       {
+               map<unsigned int, unsigned int>::iterator item;
+
+               if ((item = mapReaders.find(readerID)) != mapReaders.end())
+               {
+                       item->second = IntegerHandle::INVALID_HANDLE;
+               }
        }
 
 } /* namespace smartcard_service_api */
+
+using namespace smartcard_service_api;
+
+EXTERN_API void server_resource_set_main_loop_instance(void *instance)
+{
+       ServerResource::getInstance().setMainLoopInstance(instance);
+}