Add NOTICE, AUTHOR file and modify boilerplate
[platform/core/connectivity/smartcard-service.git] / client / SEService.cpp
1 /*
2 * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
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 <unistd.h>
20 #include <string.h>
21 #include <glib.h>
22
23 /* SLP library header */
24
25 /* local header */
26 #include "Debug.h"
27 #include "ClientIPC.h"
28 #include "ClientDispatcher.h"
29 #include "SEService.h"
30 #include "Reader.h"
31 #include "Message.h"
32
33 #ifndef EXTERN_API
34 #define EXTERN_API __attribute__((visibility("default")))
35 #endif
36
37 namespace smartcard_service_api
38 {
39         SEService::SEService():SEServiceHelper()
40         {
41                 pid = -1;
42                 this->context = NULL;
43                 this->handler = NULL;
44                 this->listener = NULL;
45                 connected = false;
46
47                 pid = getpid();
48         }
49
50         SEService::SEService(void *user_data, serviceConnected handler):SEServiceHelper()
51         {
52                 pid = -1;
53                 this->context = NULL;
54                 this->handler = NULL;
55                 this->listener = NULL;
56                 connected = false;
57
58                 pid = getpid();
59
60                 initialize(user_data, handler);
61         }
62
63         SEService::SEService(void *user_data, SEServiceListener *listener):SEServiceHelper()
64         {
65                 pid = -1;
66                 this->context = NULL;
67                 this->handler = NULL;
68                 this->listener = NULL;
69                 connected = false;
70
71                 pid = getpid();
72
73                 initialize(user_data, listener);
74         }
75
76         SEService::~SEService()
77         {
78                 uint32_t i;
79
80                 shutdownSync();
81
82                 for (i = 0; i < readers.size(); i++)
83                 {
84                         delete (Reader *)readers[i];
85                 }
86                 readers.clear();
87         }
88
89         void SEService::shutdown()
90         {
91                 if (connected == true)
92                 {
93                         uint32_t i;
94
95                         for (i = 0; i < readers.size(); i++)
96                         {
97                                 readers[i]->closeSessions();
98                         }
99
100                         Message msg;
101
102                         msg.message = Message::MSG_REQUEST_SHUTDOWN;
103                         msg.error = (unsigned int)this; /* using error to context */
104                         msg.caller = (void *)this;
105                         msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
106
107                         if (ClientIPC::getInstance().sendMessage(&msg) == false)
108                         {
109                                 SCARD_DEBUG_ERR("time over");
110                         }
111                 }
112         }
113
114         void SEService::shutdownSync()
115         {
116 #ifdef CLIENT_IPC_THREAD
117                 if (connected == true)
118                 {
119                         uint32_t i;
120
121                         for (i = 0; i < readers.size(); i++)
122                         {
123                                 readers[i]->closeSessions();
124                         }
125
126                         /* send message to load se */
127                         int rv;
128                         Message msg;
129
130                         msg.message = Message::MSG_REQUEST_SHUTDOWN;
131                         msg.error = (unsigned int)this; /* using error to context */
132                         msg.caller = (void *)this;
133                         msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
134
135                         syncLock();
136                         if (ClientIPC::getInstance().sendMessage(&msg) == true)
137                         {
138                                 rv = waitTimedCondition(0);
139
140                                 if (rv == 0)
141                                 {
142                                         ClientDispatcher::getInstance().removeSEService(context);
143
144                                         connected = false;
145                                 }
146                                 else
147                                 {
148                                         SCARD_DEBUG_ERR("time over");
149                                 }
150                         }
151                         else
152                         {
153                                 SCARD_DEBUG_ERR("sendMessage failed");
154                         }
155                         syncUnlock();
156                 }
157 #endif
158         }
159
160         bool SEService::_initialize()
161         {
162                 bool result = false;
163                 ClientIPC *clientIPC = NULL;
164                 ClientDispatcher *clientDispatcher = NULL;
165
166                 SCARD_BEGIN();
167
168                 /* initialize client */
169                 if (!g_thread_supported())
170                 {
171                         g_thread_init(NULL);
172                 }
173
174                 clientDispatcher = &ClientDispatcher::getInstance();
175                 clientIPC = &ClientIPC::getInstance();
176
177                 clientIPC->setDispatcher(clientDispatcher);
178
179 #ifndef CLIENT_IPC_THREAD
180                 if (clientDispatcher->runDispatcherThread() == false)
181                 {
182                         SCARD_DEBUG_ERR("clientDispatcher->runDispatcherThread() failed");
183
184                         return result;
185                 }
186 #endif
187
188                 if (clientIPC->createConnectSocket() == false)
189                 {
190                         SCARD_DEBUG_ERR("clientIPC->createConnectSocket() failed");
191
192                         return result;
193                 }
194
195                 clientDispatcher->addSEService(context, this);
196
197                 {
198                         /* send message to load se */
199                         Message msg;
200
201                         msg.message = Message::MSG_REQUEST_READERS;
202                         msg.error = pid; /* using error to pid */
203                         msg.caller = (void *)this;
204                         msg.userParam = context;
205
206                         result = clientIPC->sendMessage(&msg);
207                 }
208
209                 SCARD_END();
210
211                 return result;
212         }
213
214         bool SEService::initialize(void *context, serviceConnected handler)
215         {
216                 if (context == NULL)
217                 {
218                         SCARD_DEBUG_ERR("invalid param");
219                         return false;
220                 }
221
222                 this->context = context;
223                 this->handler = handler;
224
225                 return _initialize();
226         }
227
228         bool SEService::initialize(void *context, SEServiceListener *listener)
229         {
230                 if (context == NULL)
231                 {
232                         SCARD_DEBUG_ERR("invalid param");
233                         return false;
234                 }
235
236                 this->context = context;
237                 this->listener = listener;
238
239                 return _initialize();
240         }
241
242         bool SEService::parseReaderInformation(unsigned int count, ByteArray data)
243         {
244                 size_t i;
245                 unsigned int offset = 0;
246                 unsigned int len = 0;
247                 void *handle = NULL;
248                 Reader *reader = NULL;
249                 char name[100];
250
251                 for (i = 0; i < count && offset < data.getLength(); i++)
252                 {
253                         memset(name, 0, sizeof(name));
254
255                         memcpy(&len, data.getBuffer(offset), sizeof(len));
256                         offset += sizeof(len);
257
258                         memcpy(name, data.getBuffer(offset), len);
259                         offset += len;
260
261                         memcpy(&handle, data.getBuffer(offset), sizeof(handle));
262                         offset += sizeof(handle);
263
264                         SCARD_DEBUG("Reader [%d] : name [%s], handle [%p]", i, name, handle);
265
266                         /* add readers */
267                         reader = new Reader(context, name, handle);
268                         if (reader == NULL)
269                         {
270                                 SCARD_DEBUG_ERR("alloc failed");
271                                 continue;
272                         }
273
274                         readers.push_back(reader);
275                 }
276
277                 return true;
278         }
279
280         bool SEService::dispatcherCallback(void *message)
281         {
282                 Message *msg = (Message *)message;
283                 SEService *service = NULL;
284                 bool result = false;
285
286                 SCARD_BEGIN();
287
288                 if (msg == NULL)
289                 {
290                         SCARD_DEBUG_ERR("message is null");
291                         return result;
292                 }
293
294                 service = (SEService *)msg->caller;
295
296                 switch (msg->message)
297                 {
298                 case Message::MSG_REQUEST_READERS :
299                         SCARD_DEBUG("[MSG_REQUEST_READERS]");
300
301                         service->connected = true;
302
303                         /* parse message data */
304                         service->parseReaderInformation(msg->param1, msg->data);
305
306                         /* call callback function */
307                         if (service->listener != NULL)
308                         {
309                                 service->listener->serviceConnected(service, service->context);
310                         }
311                         else if (service->handler != NULL)
312                         {
313                                 service->handler(service, service->context);
314                         }
315                         break;
316
317                 case Message::MSG_REQUEST_SHUTDOWN :
318                         SCARD_DEBUG("[MSG_REQUEST_SHUTDOWN]");
319
320                         if (msg->isSynchronousCall() == true) /* synchronized call */
321                         {
322                                 /* sync call */
323                                 service->syncLock();
324
325                                 /* copy result */
326 //                              service->error = msg->error;
327
328                                 service->signalCondition();
329                                 service->syncUnlock();
330                         }
331                         else
332                         {
333 //                              openSessionCallback cb = (openSessionCallback)msg->callback;
334 //
335 //                              /* async call */
336 //                              cb(session, msg->error, msg->userParam);
337                         }
338                         break;
339
340                 case Message::MSG_NOTIFY_SE_INSERTED :
341                         {
342                                 Reader *reader = NULL;
343
344                                 SCARD_DEBUG("[MSG_NOTIFY_SE_INSERTED]");
345
346                                 /* add readers */
347                                 reader = new Reader(service->context, (char *)msg->data.getBuffer(), (void *)msg->param1);
348                                 if (reader != NULL)
349                                 {
350                                         service->readers.push_back(reader);
351                                 }
352                                 else
353                                 {
354                                         SCARD_DEBUG_ERR("alloc failed");
355                                 }
356
357                                 if (service->listener != NULL)
358                                 {
359                                         service->listener->eventHandler(service, (char *)msg->data.getBuffer(), 1, service->context);
360                                 }
361                                 else
362                                 {
363                                         SCARD_DEBUG("listener is null");
364                                 }
365                         }
366                         break;
367
368                 case Message::MSG_NOTIFY_SE_REMOVED :
369                         {
370                                 size_t i;
371
372                                 SCARD_DEBUG("[MSG_NOTIFY_SE_REMOVED]");
373
374                                 for (i = 0; i < service->readers.size(); i++)
375                                 {
376                                         if (((Reader *)service->readers[i])->handle == (void *)msg->param1)
377                                         {
378                                                 ((Reader *)service->readers[i])->present = false;
379                                                 break;
380                                         }
381                                 }
382
383                                 if (service->listener != NULL)
384                                 {
385                                         service->listener->eventHandler(service, (char *)msg->data.getBuffer(), 2, service->context);
386                                 }
387                                 else
388                                 {
389                                         SCARD_DEBUG("listener is null");
390                                 }
391                         }
392                         break;
393
394                 case Message::MSG_OPERATION_RELEASE_CLIENT :
395                         SCARD_DEBUG("[MSG_OPERATION_RELEASE_CLIENT]");
396
397                         if (service->listener != NULL)
398                         {
399                                 service->listener->errorHandler(service, msg->error, service->context);
400
401                                 ClientDispatcher::getInstance().removeSEService(service->context);
402                                 service->connected = false;
403                         }
404                         else
405                         {
406                                 SCARD_DEBUG_ERR("service->listener is null");
407                         }
408                         break;
409
410                 default:
411                         SCARD_DEBUG("unknown message [%s]", msg->toString());
412                         break;
413                 }
414
415                 SCARD_END();
416
417                 return result;
418         }
419
420 } /* namespace smartcard_service_api */
421
422 /* export C API */
423 #define SE_SERVICE_EXTERN_BEGIN \
424         if (handle != NULL) \
425         { \
426                 SEService *service = (SEService *)handle;
427
428 #define SE_SERVICE_EXTERN_END \
429         } \
430         else \
431         { \
432                 SCARD_DEBUG_ERR("Invalid param"); \
433         }
434
435 using namespace smartcard_service_api;
436
437 EXTERN_API se_service_h se_service_create_instance(void *user_data, se_service_connected_cb callback)
438 {
439         SEService *service = new SEService(user_data, (serviceConnected)callback);
440
441         return (se_service_h)service;
442 }
443
444 EXTERN_API se_service_h se_service_create_instance_with_event_callback(void *user_data, se_service_connected_cb connected, se_service_event_cb event, se_sesrvice_error_cb error)
445 {
446         SEService *service = new SEService(user_data, (serviceConnected)connected);
447
448         return (se_service_h)service;
449 }
450
451 EXTERN_API int se_service_get_readers_count(se_service_h handle)
452 {
453         int count = 0;
454
455         SE_SERVICE_EXTERN_BEGIN;
456         vector<ReaderHelper *> temp_readers;
457
458         temp_readers = service->getReaders();
459         count = temp_readers.size();
460         SE_SERVICE_EXTERN_END;
461
462         return count;
463 }
464
465 EXTERN_API bool se_service_get_readers(se_service_h handle, reader_h *readers, int *count)
466 {
467         bool result = false;
468
469         SE_SERVICE_EXTERN_BEGIN;
470         vector<ReaderHelper *> temp_readers;
471         size_t i;
472         int temp = 0;
473
474         temp_readers = service->getReaders();
475
476         for (i = 0; i < temp_readers.size() && i < (size_t)*count; i++)
477         {
478                 if (temp_readers[i]->isSecureElementPresent())
479                 {
480                         readers[i] = (reader_h)temp_readers[i];
481                         temp++;
482                 }
483         }
484         *count = temp;
485         SE_SERVICE_EXTERN_END;
486
487         return result;
488 }
489
490 EXTERN_API bool se_service_is_connected(se_service_h handle)
491 {
492         bool result = false;
493
494         SE_SERVICE_EXTERN_BEGIN;
495         result = service->isConnected();
496         SE_SERVICE_EXTERN_END;
497
498         return result;
499 }
500
501 EXTERN_API void se_service_shutdown(se_service_h handle)
502 {
503         SE_SERVICE_EXTERN_BEGIN;
504         service->shutdown();
505         SE_SERVICE_EXTERN_END;
506 }
507
508 EXTERN_API void se_service_destroy_instance(se_service_h handle)
509 {
510         SE_SERVICE_EXTERN_BEGIN;
511         delete service;
512         SE_SERVICE_EXTERN_END;
513 }