Update source
[platform/core/connectivity/smartcard-service.git] / server / ServerResource.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
18 /* standard library header */
19 #include <stdio.h>
20 #include <string.h>
21 #include <dlfcn.h>
22 #include <errno.h>
23 #include <dirent.h>
24
25 /* SLP library header */
26
27 /* local header */
28 #include "Debug.h"
29 #include "ServerResource.h"
30 #include "TerminalInterface.h"
31 #include "APDUHelper.h"
32 #include "SignatureHelper.h"
33 #include "GPSEACL.h"
34
35 #ifndef EXTERN_API
36 #define EXTERN_API __attribute__((visibility("default")))
37 #endif
38
39 namespace smartcard_service_api
40 {
41         unsigned int IntegerHandle::newHandle = 0;
42         set<unsigned int> IntegerHandle::setHandles;
43         PMutex IntegerHandle::mutexLock;
44
45         unsigned int IntegerHandle::assignHandle()
46         {
47                 SCOPE_LOCK(mutexLock)
48                 {
49                         pair<set<unsigned int>::iterator, bool> result;
50
51                         do
52                         {
53                                 newHandle++;
54                                 if (newHandle == (unsigned int)-1)
55                                 {
56                                         newHandle = 1;
57                                 }
58
59                                 result = setHandles.insert(newHandle);
60
61                         }
62                         while (!result.second);
63                 }
64
65                 SCARD_DEBUG("assign handle : newHandle [%d]", newHandle);
66
67                 return newHandle;
68         }
69
70         void IntegerHandle::releaseHandle(unsigned int handle)
71         {
72                 SCARD_DEBUG("will be released : Handle [%d]", handle);
73
74                 SCOPE_LOCK(mutexLock)
75                 {
76                         setHandles.erase(handle);
77                 }
78         }
79
80 #define OMAPI_SE_PATH "/usr/lib/se"
81
82         ServerResource::ServerResource() : mainLoop(NULL)
83         {
84                 SCARD_BEGIN();
85
86                 serverIPC = ServerIPC::getInstance();
87                 serverDispatcher = ServerDispatcher::getInstance();
88
89 #if 1
90                 loadSecureElements();
91 #endif
92                 SCARD_END();
93         }
94
95         ServerResource::~ServerResource()
96         {
97         }
98
99         ServerResource &ServerResource::getInstance()
100         {
101                 static ServerResource serverResource;
102
103                 return serverResource;
104         }
105
106         bool ServerResource::createClient(void *ioChannel, int socket, int watchID, int state, int pid)
107         {
108                 bool result = false;
109
110                 if (getClient(socket) == NULL)
111                 {
112                         ClientInstance *instance = new ClientInstance(ioChannel, socket, watchID, state, pid);
113                         if (instance != NULL)
114                         {
115                                 mapClients.insert(make_pair(socket, instance));
116                                 result = true;
117                         }
118                         else
119                         {
120                                 SCARD_DEBUG_ERR("alloc failed");
121                         }
122                 }
123                 else
124                 {
125                         SCARD_DEBUG_ERR("client already exist [%d]", socket);
126                 }
127
128                 return result;
129         }
130
131         ClientInstance *ServerResource::getClient(int socket)
132         {
133                 ClientInstance *result = NULL;
134                 map<int, ClientInstance *>::iterator item;
135
136                 if ((item = mapClients.find(socket)) != mapClients.end())
137                 {
138                         result = item->second;
139                 }
140
141                 return result;
142         }
143
144         void ServerResource::setPID(int socket, int pid)
145         {
146                 map<int, ClientInstance *>::iterator item;
147
148                 if ((item = mapClients.find(socket)) != mapClients.end())
149                 {
150                         if (item->second->getPID() < 0)
151                                 item->second->setPID(pid);
152                 }
153         }
154
155         int ServerResource::getClientCount()
156         {
157                 return (int)mapClients.size();
158         }
159
160         void ServerResource::removeClient(int socket)
161         {
162                 map<int, ClientInstance *>::iterator item;
163
164                 if ((item = mapClients.find(socket)) != mapClients.end())
165                 {
166                         ServerIPC::getInstance()->releaseClient(item->second->getIOChannel(), item->second->getSocket(), item->second->getWatchID());
167
168                         delete item->second;
169                         mapClients.erase(item);
170                 }
171                 else
172                 {
173                         SCARD_DEBUG("client removed already [%d]", socket);
174                 }
175         }
176
177         void ServerResource::removeClients()
178         {
179                 map<int, ClientInstance *>::iterator item;
180
181                 for (item = mapClients.begin(); item != mapClients.end(); item++)
182                 {
183                         ServerIPC::getInstance()->releaseClient(item->second->getIOChannel(), item->second->getSocket(), item->second->getWatchID());
184
185                         delete item->second;
186                 }
187
188                 mapClients.clear();
189         }
190
191         bool ServerResource::createService(int socket, unsigned int context)
192         {
193                 bool result = false;
194                 ClientInstance *instance = NULL;
195
196                 if ((instance = getClient(socket)) != NULL)
197                 {
198                         if ((result = instance->createService(context)) == false)
199                         {
200                                 SCARD_DEBUG_ERR("ClientInstance::createService failed [%d] [%d]", socket, context);
201                         }
202                 }
203                 else
204                 {
205                         SCARD_DEBUG_ERR("client doesn't exist [%d]", socket);
206                 }
207
208                 return result;
209         }
210
211         ServiceInstance *ServerResource::getService(int socket, unsigned int context)
212         {
213                 ServiceInstance *result = NULL;
214                 ClientInstance *instance = NULL;
215
216                 if ((instance = getClient(socket)) != NULL)
217                 {
218                         result = instance->getService(context);
219                 }
220                 else
221                 {
222                         SCARD_DEBUG_ERR("client doesn't exist [%d]", socket);
223                 }
224
225                 return result;
226         }
227
228         void ServerResource::removeService(int socket, unsigned int context)
229         {
230                 ClientInstance *instance = NULL;
231
232                 if ((instance = getClient(socket)) != NULL)
233                 {
234                         instance->removeService(context);
235                 }
236                 else
237                 {
238                         SCARD_DEBUG_ERR("client doesn't exist [%d]", socket);
239                 }
240         }
241
242         void ServerResource::removeServices(int socket)
243         {
244                 ClientInstance *instance = NULL;
245
246                 if ((instance = getClient(socket)) != NULL)
247                 {
248                         instance->removeServices();
249                 }
250                 else
251                 {
252                         SCARD_DEBUG_ERR("client doesn't exist [%d]", socket);
253                 }
254         }
255
256         Terminal *ServerResource::getTerminal(unsigned int terminalID)
257         {
258                 Terminal *result = NULL;
259                 map<unsigned int, Terminal *>::iterator item;
260
261                 if ((item = mapTerminals.find(terminalID)) != mapTerminals.end())
262                 {
263                         result = item->second;
264                 }
265                 else
266                 {
267                         SCARD_DEBUG_ERR("Terminal doesn't exist [%d]", terminalID);
268                 }
269
270                 return result;
271         }
272
273         Terminal *ServerResource::getTerminal(const char *name)
274         {
275                 Terminal *result = NULL;
276                 map<unsigned int, Terminal *>::iterator item;
277
278                 for (item = mapTerminals.begin(); item != mapTerminals.end(); item++)
279                 {
280                         if (strncmp(name, item->second->getName(), strlen(name)) == 0)
281                         {
282                                 result = item->second;
283                                 break;
284                         }
285                 }
286
287                 return result;
288         }
289
290         unsigned int ServerResource::createSession(int socket, unsigned int context, unsigned int terminalID, vector<ByteArray> &certHashes, void *caller)
291         {
292                 unsigned int result = -1;
293                 Terminal *temp = NULL;
294                 ServiceInstance *instance = NULL;
295
296                 if ((instance = getService(socket, context)) != NULL)
297                 {
298                         if ((temp = getTerminal(terminalID)) != NULL)
299                         {
300                                 result = instance->openSession(temp, certHashes, caller);
301                         }
302                 }
303                 else
304                 {
305                         SCARD_DEBUG_ERR("getService doesn't exist : socket [%d], context [%d]", socket, context);
306                 }
307
308                 return result;
309         }
310
311         ServerSession *ServerResource::getSession(int socket, unsigned int context, unsigned int sessionID)
312         {
313                 ServerSession *result = NULL;
314                 ServiceInstance *instance = NULL;
315
316                 if ((instance = getService(socket, context)) != NULL)
317                 {
318                         result = instance->getSession(sessionID);
319                 }
320                 else
321                 {
322                         SCARD_DEBUG_ERR("Session doesn't exist : socket [%d], context [%d], handle [%d]", socket, context, sessionID);
323                 }
324
325                 return result;
326         }
327
328         unsigned int ServerResource::getChannelCount(int socket, unsigned int context, unsigned int sessionID)
329         {
330                 unsigned int result = -1;
331                 ServiceInstance *instance = NULL;
332
333                 if ((instance = getService(socket, context)) != NULL)
334                 {
335                         result = instance->getChannelCountBySession(sessionID);
336                 }
337                 else
338                 {
339                         SCARD_DEBUG_ERR("getService doesn't exist : socket [%d], context [%d]", socket, context);
340                 }
341
342                 return result;
343         }
344
345         void ServerResource::removeSession(int socket, unsigned int context, unsigned int sessionID)
346         {
347                 ServiceInstance *instance = NULL;
348
349                 if ((instance = getService(socket, context)) != NULL)
350                 {
351                         instance->closeSession(sessionID);
352                 }
353                 else
354                 {
355                         SCARD_DEBUG_ERR("getService doesn't exist : socket [%d], context [%d]", socket, context);
356                 }
357         }
358
359         bool ServerResource::_isAuthorizedAccess(Terminal *terminal, int pid, ByteArray aid, vector<ByteArray> &hashes)
360         {
361                 bool result = true;
362
363 #if 1 /* disable for temporary */
364                 char filename[1024] = { 0, };
365                 AccessControlList *acList = NULL;
366
367                 /* check exceptional case */
368                 SignatureHelper::getProcessName(pid, filename, sizeof(filename));
369                 if (strncmp(filename, "ozD3Dw1MZruTDKHWGgYaDib2B2LV4/nfT+8b/g1Vsk8=", sizeof(filename)) != 0)
370                 {
371                         /* request open channel sequence */
372                         if ((acList = getAccessControlList(terminal)) != NULL)
373                         {
374 #if 1
375                                 result = acList->isAuthorizedAccess(aid, hashes);
376 #else
377                                 result = acList->isAuthorizedAccess(aid, session->packageCert);
378 #endif
379                         }
380                         else
381                         {
382                                 SCARD_DEBUG_ERR("acList is null");
383                                 result = false;
384                         }
385                 }
386 #endif
387
388                 return result;
389         }
390
391         unsigned int ServerResource::_createChannel(Terminal *terminal, ServiceInstance *service, int channelType, unsigned int sessionID, ByteArray aid)
392         {
393                 unsigned int result = IntegerHandle::INVALID_HANDLE;
394                 int rv = 0;
395                 int channelNum = 0;
396                 ByteArray command;
397                 ByteArray response;
398
399                 if (channelType == 1)
400                 {
401                         /* open channel */
402                         command = APDUHelper::generateAPDU(APDUHelper::COMMAND_OPEN_LOGICAL_CHANNEL, 0, ByteArray::EMPTY);
403                         rv = terminal->transmitSync(command, response);
404
405                         if (rv == 0 && response.getLength() >= 2)
406                         {
407                                 ResponseHelper resp(response);
408
409                                 if (resp.getStatus() == 0)
410                                 {
411                                         channelNum = resp.getDataField()[0];
412
413                                         SCARD_DEBUG("channelNum [%d]", channelNum);
414                                 }
415                                 else
416                                 {
417                                         SCARD_DEBUG_ERR("status word [%d][ %02X %02X ]", resp.getStatus(), resp.getSW1(), resp.getSW2());
418
419                                         return result;
420                                 }
421                         }
422                         else
423                         {
424                                 SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", rv, response.getLength());
425
426                                 return result;
427                         }
428                 }
429
430                 /* select aid */
431                 APDUCommand apdu;
432                 apdu.setCommand(0, APDUCommand::INS_SELECT_FILE, APDUCommand::P1_SELECT_BY_DF_NAME, APDUCommand::P2_SELECT_GET_FCP, aid, 0);
433                 apdu.setChannel(1, channelNum);
434                 apdu.getBuffer(command);
435
436                 rv = terminal->transmitSync(command, response);
437                 if (rv == 0 && response.getLength() >= 2)
438                 {
439                         ResponseHelper resp(response);
440
441                         if (resp.getStatus() == 0)
442                         {
443                                 result = service->openChannel(sessionID, channelNum, response);
444                                 if (result == IntegerHandle::INVALID_HANDLE)
445                                 {
446                                         SCARD_DEBUG_ERR("channel is null.");
447                                 }
448                         }
449                         else
450                         {
451                                 SCARD_DEBUG_ERR("status word [%d][ %02X %02X ]", resp.getStatus(), resp.getSW1(), resp.getSW2());
452                         }
453                 }
454                 else
455                 {
456                         SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", rv, response.getLength());
457                 }
458
459                 return result;
460         }
461
462         unsigned int ServerResource::createChannel(int socket, unsigned int context, unsigned int sessionID, int channelType, ByteArray aid)
463         {
464                 unsigned int result = -1;
465                 ServiceInstance *service = NULL;
466
467                 if ((service = getService(socket, context)) != NULL)
468                 {
469                         if (service->isVaildSessionHandle(sessionID) == true)
470                         {
471                                 ServerSession *session = NULL;
472                                 Terminal *terminal = NULL;
473
474                                 terminal = service->getTerminal(sessionID);
475                                 session = service->getSession(sessionID);
476                                 if (terminal != NULL && session != NULL)
477                                 {
478                                         if (_isAuthorizedAccess(terminal, service->getParent()->getPID(), aid, service->getParent()->getCertificationHashes()) == true)
479                                         {
480                                                 result = _createChannel(terminal, service, channelType, sessionID, aid);
481                                         }
482                                         else
483                                         {
484                                                 SCARD_DEBUG_ERR("access denied [%d]", sessionID);
485                                         }
486                                 }
487                                 else
488                                 {
489                                         SCARD_DEBUG_ERR("session is invalid [%d]", sessionID);
490                                 }
491                         }
492                         else
493                         {
494                                 SCARD_DEBUG_ERR("session is invalid [%d]", sessionID);
495                         }
496                 }
497                 else
498                 {
499                         SCARD_DEBUG_ERR("getService is failed [%d] [%d]", socket, context);
500                 }
501
502                 return result;
503         }
504
505         Channel *ServerResource::getChannel(int socket, unsigned int context, unsigned int channelID)
506         {
507                 Channel *result = NULL;
508                 ServiceInstance *instance = NULL;
509
510                 if ((instance = getService(socket, context)) != NULL)
511                 {
512                         result = instance->getChannel(channelID);
513                 }
514                 else
515                 {
516                         SCARD_DEBUG_ERR("Channel doesn't exist : socket [%d], context [%d], handle [%d]", socket, context, channelID);
517                 }
518
519                 return result;
520         }
521
522         void ServerResource::removeChannel(int socket, unsigned int context, unsigned int channelID)
523         {
524                 ServiceInstance *instance = NULL;
525
526                 if ((instance = getService(socket, context)) != NULL)
527                 {
528                         instance->closeChannel(channelID);
529                 }
530                 else
531                 {
532                         SCARD_DEBUG_ERR("getService doesn't exist : socket [%d], context [%d]", socket, context);
533                 }
534         }
535
536         AccessControlList *ServerResource::getAccessControlList(Terminal *terminal)
537         {
538                 AccessControlList *result = NULL;
539                 map<Terminal *, AccessControlList *>::iterator item;
540
541                 if ((item = mapACL.find(terminal)) == mapACL.end())
542                 {
543                         ServerChannel *channel = new ServerChannel(NULL, NULL, 0, terminal);
544                         if (channel != NULL)
545                         {
546                                 /* load access control */
547                                 result = new GPSEACL(channel);
548                                 if (result != NULL)
549                                 {
550                                         mapACL.insert(make_pair(terminal, result));
551                                 }
552                                 else
553                                 {
554                                         SCARD_DEBUG_ERR("alloc failed");
555                                 }
556                         }
557                         else
558                         {
559                                 SCARD_DEBUG_ERR("alloc failed");
560                         }
561                 }
562                 else
563                 {
564                         result = item->second;
565                 }
566
567                 return result;
568         }
569
570         Terminal *ServerResource::createInstance(void *library)
571         {
572                 Terminal *terminal = NULL;
573                 terminal_create_instance_fn createInstance = NULL;
574
575                 /* create se instance */
576                 createInstance = (terminal_create_instance_fn)dlsym(library, "create_instance");
577                 if (createInstance != NULL)
578                 {
579                         terminal = (Terminal *)createInstance();
580                         if (terminal != NULL)
581                         {
582                                 SCARD_DEBUG("terminal [%p]", terminal);
583                         }
584                         else
585                         {
586                                 SCARD_DEBUG_ERR("terminal is null");
587                         }
588                 }
589                 else
590                 {
591                         SCARD_DEBUG_ERR("create_instance is null [%d]", errno);
592                 }
593
594                 return terminal;
595         }
596
597         bool ServerResource::appendSELibrary(char *library)
598         {
599                 void *libHandle = NULL;
600                 bool result = false;
601
602                 libHandle = dlopen(library, RTLD_LAZY);
603                 if (libHandle != NULL)
604                 {
605                         Terminal *terminal = NULL;
606
607                         terminal = createInstance(libHandle);
608                         if (terminal != NULL)
609                         {
610                                 unsigned int handle = IntegerHandle::assignHandle();
611
612                                 mapTerminals.insert(make_pair(handle, terminal));
613                                 libraries.push_back(libHandle);
614
615                                 terminal->setStatusCallback(&ServerResource::terminalCallback);
616
617                                 SCARD_DEBUG("register success [%s] [%p] [%s] [%p]", library, libHandle, terminal->getName(), terminal);
618
619                                 result = true;
620                         }
621                         else
622                         {
623                                 SCARD_DEBUG_ERR("terminal is null [%s]", library);
624
625                                 dlclose(libHandle);
626                         }
627                 }
628                 else
629                 {
630                         SCARD_DEBUG_ERR("it is not se file [%s] [%d]", library, errno);
631                 }
632
633                 return result;
634         }
635
636         int ServerResource::loadSecureElements()
637         {
638                 int result;
639                 void *libHandle;
640                 DIR *dir = NULL;
641                 struct dirent *entry = NULL;
642
643                 if ((dir = opendir(OMAPI_SE_PATH)) != NULL)
644                 {
645                         while ((entry = readdir(dir)) != NULL)
646                         {
647                                 if (strncmp(entry->d_name, ".", 1) != 0 && strncmp(entry->d_name, "..", 2) != 0)
648                                 {
649                                         char fullPath[1024] = { 0, };
650
651                                         /* TODO : need additional name rule :) */
652
653                                         /* open each files */
654                                         libHandle = NULL;
655
656                                         snprintf(fullPath, sizeof(fullPath), "%s/%s", OMAPI_SE_PATH, entry->d_name);
657
658                                         SCARD_DEBUG("se name [%s]", fullPath);
659
660                                         result = appendSELibrary(fullPath);
661                                 }
662                         }
663
664                         closedir(dir);
665
666                         result = 0;
667                 }
668                 else
669                 {
670                         result = -1;
671                 }
672
673                 return result;
674         }
675
676         void ServerResource::unloadSecureElements()
677         {
678                 size_t i;
679                 map<unsigned int, Terminal *>::iterator item;
680
681                 for (item = mapTerminals.begin(); item != mapTerminals.end(); item++)
682                 {
683                         item->second->finalize();
684
685                         IntegerHandle::releaseHandle(item->first);
686                 }
687
688                 mapTerminals.clear();
689
690                 for (i = 0; i < libraries.size(); i++)
691                 {
692                         if (libraries[i] != NULL)
693                                 dlclose(libraries[i]);
694                 }
695
696                 libraries.clear();
697         }
698
699         bool ServerResource::isValidReaderHandle(unsigned int reader)
700         {
701                 return (getTerminal(reader) != NULL);
702         }
703
704         bool ServerResource::isValidSessionHandle(int socket, unsigned int context, unsigned int session)
705         {
706                 ServiceInstance *instance = NULL;
707
708                 return (((instance = getService(socket, context)) != NULL) && (getService(socket, context)->isVaildSessionHandle(session)));
709         }
710
711         int ServerResource::getReadersInformation(ByteArray &info)
712         {
713                 int result = 0;
714                 unsigned char *buffer = NULL;
715                 unsigned int length = 0;
716                 unsigned int offset = 0;
717                 unsigned int nameLen = 0;
718
719                 if (mapTerminals.size() > 0)
720                 {
721                         map<unsigned int, Terminal *>::iterator item;
722
723                         for (item = mapTerminals.begin(); item != mapTerminals.end(); item++)
724                         {
725                                 if (item->second->isSecureElementPresence())
726                                 {
727                                         length += sizeof(nameLen) + strlen(item->second->getName()) + sizeof(unsigned int);
728                                         result++;
729                                 }
730                         }
731
732                         buffer = new unsigned char[length];
733                         if (buffer != NULL)
734                         {
735                                 memset(buffer, 0, length);
736
737                                 for (item = mapTerminals.begin(); item != mapTerminals.end(); item++)
738                                 {
739                                         if (item->second->isSecureElementPresence())
740                                         {
741                                                 nameLen = strlen(item->second->getName());
742
743                                                 memcpy(buffer + offset, &nameLen, sizeof(nameLen));
744                                                 offset += sizeof(nameLen);
745
746                                                 memcpy(buffer + offset, item->second->getName(), nameLen);
747                                                 offset += nameLen;
748
749                                                 memcpy(buffer + offset, &item->first, sizeof(unsigned int));
750                                                 offset += sizeof(unsigned int);
751                                         }
752                                 }
753
754                                 info.setBuffer(buffer, length);
755                                 delete []buffer;
756                         }
757                         else
758                         {
759                                 SCARD_DEBUG_ERR("alloc failed");
760                                 result = -1;
761                         }
762                 }
763                 else
764                 {
765                         SCARD_DEBUG("no secure element");
766                 }
767
768                 return result;
769         }
770
771         bool ServerResource::sendMessageToAllClients(Message &msg)
772         {
773                 bool result = true;
774                 map<int, ClientInstance *>::iterator item;
775
776                 for (item = mapClients.begin(); item != mapClients.end(); item++)
777                 {
778                         if (item->second->sendMessageToAllServices(item->second->getSocket(), msg) == false)
779                                 result = false;
780                 }
781
782                 return result;
783         }
784
785         void ServerResource::terminalCallback(void *terminal, int event, int error, void *user_param)
786         {
787                 SCARD_BEGIN();
788
789                 switch (event)
790                 {
791                 case Terminal::NOTIFY_SE_AVAILABLE :
792                         {
793                                 Message msg;
794
795                                 SCARD_DEBUG("[NOTIFY_SE_AVAILABLE]");
796                                 SCARD_DEBUG("terminal [%s], error [%d], user_param [%p]", (char *)terminal, error, user_param);
797
798                                 /* send all client to refresh reader */
799                                 msg.message = msg.MSG_NOTIFY_SE_INSERTED;
800                                 msg.data.setBuffer((unsigned char *)terminal, strlen((char *)terminal) + 1);
801
802                                 ServerResource::getInstance().sendMessageToAllClients(msg);
803                         }
804                         break;
805
806                 case Terminal::NOTIFY_SE_NOT_AVAILABLE :
807                         {
808                                 Message msg;
809
810                                 SCARD_DEBUG("[NOTIFY_SE_NOT_AVAILABLE]");
811                                 SCARD_DEBUG("terminal [%s], error [%d], user_param [%p]", (char *)terminal, error, user_param);
812
813                                 /* send all client to refresh reader */
814                                 msg.message = msg.MSG_NOTIFY_SE_REMOVED;
815                                 msg.data.setBuffer((unsigned char *)terminal, strlen((char *)terminal) + 1);
816
817                                 ServerResource::getInstance().sendMessageToAllClients(msg);
818                         }
819                         break;
820
821                 default :
822                         SCARD_DEBUG("terminal [%s], event [%d], error [%d], user_param [%p]", (char *)terminal, event, error, user_param);
823                         break;
824                 }
825
826                 SCARD_END();
827         }
828
829 } /* namespace smartcard_service_api */
830
831 using namespace smartcard_service_api;
832
833 EXTERN_API void server_resource_set_main_loop_instance(void *instance)
834 {
835         ServerResource::getInstance().setMainLoopInstance(instance);
836 }