- Fix the prevent problems.
[platform/core/connectivity/smartcard-service.git] / client / Session.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 <stdlib.h>
21 #include <unistd.h>
22 #include <string.h>
23
24 /* SLP library header */
25
26 /* local header */
27 #include "Debug.h"
28 #include "Session.h"
29 #include "Reader.h"
30 #include "ClientChannel.h"
31 #include "ClientIPC.h"
32
33 #ifndef EXTERN_API
34 #define EXTERN_API __attribute__((visibility("default")))
35 #endif
36
37 namespace smartcard_service_api
38 {
39         Session::Session(void *context, Reader *reader, void *handle):SessionHelper(reader)
40         {
41                 this->context = NULL;
42
43                 if (context == NULL || handle == NULL)
44                 {
45                         SCARD_DEBUG_ERR("handle is null");
46
47                         return;
48                 }
49
50                 this->context = context;
51                 this->handle = handle;
52                 closed = false;
53         }
54
55         Session::~Session()
56         {
57                 close(NULL, this);
58         }
59
60         void Session::closeChannels()
61         {
62                 size_t i;
63
64                 for (i = 0; i < channels.size(); i++)
65                 {
66                         channels[i]->closeSync();
67                         delete (ClientChannel *)channels[i];
68                 }
69
70                 channels.clear();
71         }
72
73         ByteArray Session::getATRSync()
74         {
75                 atr.releaseBuffer();
76
77                 if (getReader()->isSecureElementPresent() == true)
78                 {
79                         Message msg;
80                         int rv;
81
82 #ifdef CLIENT_IPC_THREAD
83                         /* request channel handle from server */
84                         msg.message = Message::MSG_REQUEST_GET_ATR;
85                         msg.param1 = (unsigned int)handle;
86                         msg.error = (unsigned int)context; /* using error to context */
87                         msg.caller = (void *)this;
88                         msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
89
90                         ClientIPC::getInstance().sendMessage(&msg);
91
92                         syncLock();
93                         rv = waitTimedCondition(0);
94                         syncUnlock();
95
96                         if (rv != 0)
97                         {
98                                 SCARD_DEBUG_ERR("time over");
99                         }
100 #endif
101                 }
102                 else
103                 {
104                         SCARD_DEBUG_ERR("unavailable session");
105                 }
106
107                 return atr;
108         }
109
110         int Session::getATR(getATRCallback callback, void *userData)
111         {
112                 int result = -1;
113
114                 if (getReader()->isSecureElementPresent() == true)
115                 {
116                         Message msg;
117
118                         /* request channel handle from server */
119                         msg.message = Message::MSG_REQUEST_GET_ATR;
120                         msg.param1 = (unsigned int)handle;
121                         msg.error = (unsigned int)context; /* using error to context */
122                         msg.caller = (void *)this;
123                         msg.callback = (void *)callback;
124                         msg.userParam = userData;
125
126                         ClientIPC::getInstance().sendMessage(&msg);
127
128                         result = 0;
129                 }
130                 else
131                 {
132                         SCARD_DEBUG_ERR("unavailable session");
133                 }
134
135                 return result;
136         }
137
138         void Session::closeSync()
139         {
140                 Message msg;
141                 int rv;
142
143 #ifdef CLIENT_IPC_THREAD
144                 if (isClosed() == false)
145                 {
146                         closed = true;
147                         closeChannels();
148
149                         /* request channel handle from server */
150                         msg.message = Message::MSG_REQUEST_CLOSE_SESSION;
151                         msg.param1 = (unsigned int)handle;
152                         msg.error = (unsigned int)context; /* using error to context */
153                         msg.caller = (void *)this;
154                         msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
155
156                         ClientIPC::getInstance().sendMessage(&msg);
157
158                         syncLock();
159                         rv = waitTimedCondition(0);
160                         syncUnlock();
161
162                         if (rv != 0)
163                         {
164                                 SCARD_DEBUG_ERR("time over");
165                         }
166                 }
167 #endif
168         }
169
170         int Session::close(closeSessionCallback callback, void *userData)
171         {
172                 Message msg;
173
174                 if (isClosed() == false)
175                 {
176                         closed = true;
177                         closeChannels();
178
179                         /* request channel handle from server */
180                         msg.message = Message::MSG_REQUEST_CLOSE_SESSION;
181                         msg.param1 = (unsigned int)handle;
182                         msg.error = (unsigned int)context; /* using error to context */
183                         msg.caller = (void *)this;
184                         msg.callback = (void *)callback;
185                         msg.userParam = userData;
186
187                         ClientIPC::getInstance().sendMessage(&msg);
188                 }
189
190                 return 0;
191         }
192
193         unsigned int Session::getChannelCountSync()
194         {
195                 channelCount = -1;
196
197                 if (getReader()->isSecureElementPresent() == true)
198                 {
199                         Message msg;
200                         int rv;
201
202 #ifdef CLIENT_IPC_THREAD
203                         /* request channel handle from server */
204                         msg.message = Message::MSG_REQUEST_GET_CHANNEL_COUNT;
205                         msg.param1 = (unsigned int)handle;
206                         msg.error = (unsigned int)context; /* using error to context */
207                         msg.caller = (void *)this;
208                         msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
209
210                         ClientIPC::getInstance().sendMessage(&msg);
211
212                         syncLock();
213                         rv = waitTimedCondition(0);
214                         syncUnlock();
215
216                         if (rv != 0)
217                         {
218                                 SCARD_DEBUG_ERR("time over");
219
220                                 channelCount = -1;
221                         }
222 #endif
223                 }
224                 else
225                 {
226                         SCARD_DEBUG_ERR("unavailable session");
227                 }
228
229                 return channelCount;
230         }
231
232         int Session::getChannelCount(getChannelCountCallback callback, void *userData)
233         {
234                 int result = -1;
235
236                 if (getReader()->isSecureElementPresent() == true)
237                 {
238                         Message msg;
239
240                         msg.message = Message::MSG_REQUEST_GET_CHANNEL_COUNT;
241                         msg.param1 = (unsigned int)handle;
242                         msg.error = (unsigned int)context; /* using error to context */
243                         msg.caller = (void *)this;
244                         msg.callback = (void *)callback;
245                         msg.userParam = userData;
246
247                         ClientIPC::getInstance().sendMessage(&msg);
248
249                         result = 0;
250                 }
251                 else
252                 {
253                         SCARD_DEBUG_ERR("unavailable session");
254                 }
255
256                 return result;
257         }
258
259         Channel *Session::openChannelSync(int id, ByteArray aid)
260         {
261                 openedChannel = NULL;
262
263                 if (getReader()->isSecureElementPresent() == true)
264                 {
265                         Message msg;
266                         int rv;
267
268 #ifdef CLIENT_IPC_THREAD
269                         /* request channel handle from server */
270                         msg.message = Message::MSG_REQUEST_OPEN_CHANNEL;
271                         msg.param1 = id;
272                         msg.param2 = (unsigned int)handle;
273                         msg.data = aid;
274                         msg.error = (unsigned int)context; /* using error to context */
275                         msg.caller = (void *)this;
276                         msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
277
278                         ClientIPC::getInstance().sendMessage(&msg);
279
280                         syncLock();
281                         rv = waitTimedCondition(0);
282                         syncUnlock();
283
284                         if (rv != 0)
285                         {
286                                 SCARD_DEBUG_ERR("time over");
287                         }
288 #endif
289                 }
290                 else
291                 {
292                         SCARD_DEBUG_ERR("unavailable session");
293                 }
294
295                 return (Channel *)openedChannel;
296         }
297
298         int Session::openChannel(int id, ByteArray aid, openChannelCallback callback, void *userData)
299         {
300                 int result = -1;
301
302                 if (getReader()->isSecureElementPresent() == true)
303                 {
304                         Message msg;
305
306                         /* request channel handle from server */
307                         msg.message = Message::MSG_REQUEST_OPEN_CHANNEL;
308                         msg.param1 = id;
309                         msg.param2 = (unsigned int)handle;
310                         msg.data = aid;
311                         msg.error = (unsigned int)context; /* using error to context */
312                         msg.caller = (void *)this;
313                         msg.callback = (void *)callback;
314                         msg.userParam = userData;
315
316                         ClientIPC::getInstance().sendMessage(&msg);
317
318                         result = 0;
319                 }
320                 else
321                 {
322                         SCARD_DEBUG_ERR("unavailable session");
323                 }
324
325                 return result;
326         }
327
328         Channel *Session::openBasicChannelSync(ByteArray aid)
329         {
330                 return openChannelSync(0, aid);
331         }
332
333         Channel *Session::openBasicChannelSync(unsigned char *aid, unsigned int length)
334         {
335                 return openBasicChannelSync(ByteArray(aid, length));
336         }
337
338         int Session::openBasicChannel(ByteArray aid, openChannelCallback callback, void *userData)
339         {
340                 return openChannel(0, aid, callback, userData);
341         }
342
343         int Session::openBasicChannel(unsigned char *aid, unsigned int length, openChannelCallback callback, void *userData)
344         {
345                 return openBasicChannel(ByteArray(aid, length), callback, userData);
346         }
347
348         Channel *Session::openLogicalChannelSync(ByteArray aid)
349         {
350                 return openChannelSync(1, aid);
351         }
352
353         Channel *Session::openLogicalChannelSync(unsigned char *aid, unsigned int length)
354         {
355                 return openLogicalChannelSync(ByteArray(aid, length));
356         }
357
358         int Session::openLogicalChannel(ByteArray aid, openChannelCallback callback, void *userData)
359         {
360                 return openChannel(1, aid, callback, userData);
361         }
362
363         int Session::openLogicalChannel(unsigned char *aid, unsigned int length, openChannelCallback callback, void *userData)
364         {
365                 return openLogicalChannel(ByteArray(aid, length), callback, userData);
366         }
367
368         bool Session::dispatcherCallback(void *message)
369         {
370                 Message *msg = (Message *)message;
371                 Session *session = NULL;
372                 bool result = false;
373
374                 if (msg == NULL)
375                 {
376                         SCARD_DEBUG_ERR("message is null");
377                         return result;
378                 }
379
380                 session = (Session *)msg->caller;
381
382                 switch (msg->message)
383                 {
384                 case Message::MSG_REQUEST_OPEN_CHANNEL :
385                         {
386                                 Channel *channel = NULL;
387
388                                 SCARD_DEBUG("MSG_REQUEST_OPEN_CHANNEL");
389
390                                 if (msg->param1 != 0)
391                                 {
392                                         /* create new instance of channel */
393                                         channel = new ClientChannel(session->context, session, msg->param2, msg->data, (void *)msg->param1);
394                                         if (channel != NULL)
395                                         {
396                                                 session->channels.push_back(channel);
397                                         }
398                                         else
399                                         {
400                                                 SCARD_DEBUG_ERR("alloc failed");
401
402                                                 msg->error = -1;
403                                         }
404                                 }
405
406                                 if (msg->isSynchronousCall() == true) /* synchronized call */
407                                 {
408                                         /* sync call */
409                                         session->syncLock();
410
411                                         /* copy result */
412                                         session->error = msg->error;
413                                         session->openedChannel = channel;
414
415                                         session->signalCondition();
416                                         session->syncUnlock();
417                                 }
418                                 else if (msg->callback != NULL)
419                                 {
420                                         openChannelCallback cb = (openChannelCallback)msg->callback;
421
422                                         /* async call */
423                                         cb(channel, msg->error, msg->userParam);
424                                 }
425                         }
426                         break;
427
428                 case Message::MSG_REQUEST_GET_ATR :
429                         {
430                                 SCARD_DEBUG("MSG_REQUEST_GET_ATR");
431
432                                 if (msg->isSynchronousCall() == true) /* synchronized call */
433                                 {
434                                         /* sync call */
435                                         session->syncLock();
436
437                                         session->error = msg->error;
438                                         session->atr = msg->data;
439
440                                         session->signalCondition();
441                                         session->syncUnlock();
442                                 }
443                                 else if (msg->callback != NULL)
444                                 {
445                                         getATRCallback cb = (getATRCallback)msg->callback;
446
447                                         /* async call */
448                                         cb(msg->data.getBuffer(), msg->data.getLength(), msg->error, msg->userParam);
449                                 }
450                         }
451                         break;
452
453                 case Message::MSG_REQUEST_CLOSE_SESSION :
454                         {
455                                 SCARD_DEBUG("MSG_REQUEST_CLOSE_SESSION");
456
457                                 if (msg->isSynchronousCall() == true) /* synchronized call */
458                                 {
459                                         /* sync call */
460                                         session->syncLock();
461
462                                         session->error = msg->error;
463
464                                         session->signalCondition();
465                                         session->syncUnlock();
466                                 }
467                                 else if (msg->callback != NULL)
468                                 {
469                                         closeSessionCallback cb = (closeSessionCallback)msg->callback;
470
471                                         /* async call */
472                                         cb(msg->error, msg->userParam);
473                                 }
474                         }
475                         break;
476
477                 case Message::MSG_REQUEST_GET_CHANNEL_COUNT :
478                         {
479                                 SCARD_DEBUG("MSG_REQUEST_GET_CHANNEL_COUNT");
480
481                                 if (msg->isSynchronousCall() == true) /* synchronized call */
482                                 {
483                                         /* sync call */
484                                         session->syncLock();
485
486                                         session->error = msg->error;
487                                         session->channelCount = msg->param1;
488
489                                         session->signalCondition();
490                                         session->syncUnlock();
491                                 }
492                                 else if (msg->callback != NULL)
493                                 {
494                                         getChannelCountCallback cb = (getChannelCountCallback)msg->callback;
495
496                                         /* async call */
497                                         cb(msg->param1, msg->error, msg->userParam);
498                                 }
499                         }
500                         break;
501
502                 default:
503                         SCARD_DEBUG("unknown message : %s", msg->toString());
504                         break;
505                 }
506
507                 delete msg;
508
509                 return result;
510         }
511 } /* namespace smartcard_service_api */
512
513 /* export C API */
514 #define SESSION_EXTERN_BEGIN \
515         if (handle != NULL) \
516         { \
517                 Session *session = (Session *)handle;
518
519 #define SESSION_EXTERN_END \
520         } \
521         else \
522         { \
523                 SCARD_DEBUG_ERR("Invalid param"); \
524         }
525
526 using namespace smartcard_service_api;
527
528 EXTERN_API reader_h session_get_reader(session_h handle)
529 {
530         reader_h reader = NULL;
531
532         SESSION_EXTERN_BEGIN;
533         reader = session->getReader();
534         SESSION_EXTERN_END;
535
536         return reader;
537 }
538
539 EXTERN_API int session_get_atr(session_h handle, session_get_atr_cb callback, void *userData)
540 {
541         int result = -1;
542
543         SESSION_EXTERN_BEGIN;
544         result = session->getATR((getATRCallback)callback, userData);
545         SESSION_EXTERN_END;
546
547         return result;
548 }
549
550 EXTERN_API int session_close(session_h handle, session_close_session_cb callback, void *userData)
551 {
552         int result = -1;
553
554         SESSION_EXTERN_BEGIN;
555         result = session->close((closeSessionCallback)callback, userData);
556         SESSION_EXTERN_END;
557
558         return result;
559 }
560
561 EXTERN_API bool session_is_closed(session_h handle)
562 {
563         bool result = false;
564
565         SESSION_EXTERN_BEGIN;
566         result = session->isClosed();
567         SESSION_EXTERN_END;
568
569         return result;
570 }
571
572 EXTERN_API void session_close_channels(session_h handle)
573 {
574         SESSION_EXTERN_BEGIN;
575         session->closeChannels();
576         SESSION_EXTERN_END;
577 }
578
579 EXTERN_API int session_open_basic_channel(session_h handle, unsigned char *aid, unsigned int length, session_open_channel_cb callback, void *userData)
580 {
581         int result = -1;
582
583         SESSION_EXTERN_BEGIN;
584         result = session->openBasicChannel(aid, length, (openChannelCallback)callback, userData);
585         SESSION_EXTERN_END;
586
587         return result;
588 }
589
590 EXTERN_API int session_open_logical_channel(session_h handle, unsigned char *aid, unsigned int length, session_open_channel_cb callback, void *userData)
591 {
592         int result = -1;
593
594         SESSION_EXTERN_BEGIN;
595         result = session->openLogicalChannel(aid, length, (openChannelCallback)callback, userData);
596         SESSION_EXTERN_END;
597
598         return result;
599 }
600
601 EXTERN_API int session_get_channel_count(session_h handle, session_get_channel_count_cb callback, void * userData)
602 {
603         int result = -1;
604
605         SESSION_EXTERN_BEGIN;
606         result = session->getChannelCount((getChannelCountCallback)callback, userData);
607         SESSION_EXTERN_END;
608
609         return result;
610 }
611
612 EXTERN_API void session_destroy_instance(session_h handle)
613 {
614         SESSION_EXTERN_BEGIN;
615         delete session;
616         SESSION_EXTERN_END;
617 }
618
619 EXTERN_API int session_get_atr_sync(session_h handle, unsigned char **buffer, unsigned int *length)
620 {
621         ByteArray temp;
622         int result = -1;
623
624 #ifdef CLIENT_IPC_THREAD
625         if (buffer == NULL || length == NULL)
626                 return result;
627
628         SESSION_EXTERN_BEGIN;
629         temp = session->getATRSync();
630         if (temp.getLength() > 0)
631         {
632                 *length = temp.getLength();
633                 *buffer = (unsigned char *)calloc(1, *length);
634                 memcpy(*buffer, temp.getBuffer(), *length);
635
636                 result = 0;
637         }
638         SESSION_EXTERN_END;
639 #endif
640
641         return result;
642 }
643
644 EXTERN_API void session_close_sync(session_h handle)
645 {
646 #ifdef CLIENT_IPC_THREAD
647         SESSION_EXTERN_BEGIN;
648         session->closeSync();
649         SESSION_EXTERN_END;
650 #endif
651 }
652
653 EXTERN_API channel_h session_open_basic_channel_sync(session_h handle, unsigned char *aid, unsigned int length)
654 {
655         channel_h result = NULL;
656
657 #ifdef CLIENT_IPC_THREAD
658         SESSION_EXTERN_BEGIN;
659         result = session->openBasicChannelSync(aid, length);
660         SESSION_EXTERN_END;
661 #endif
662
663         return result;
664 }
665
666 EXTERN_API channel_h session_open_logical_channel_sync(session_h handle, unsigned char *aid, unsigned int length)
667 {
668         channel_h result = NULL;
669
670 #ifdef CLIENT_IPC_THREAD
671         SESSION_EXTERN_BEGIN;
672         result = session->openBasicChannelSync(aid, length);
673         SESSION_EXTERN_END;
674 #endif
675
676         return result;
677 }
678
679 EXTERN_API unsigned int session_get_channel_count_sync(session_h handle)
680 {
681         unsigned int result = 0;
682
683 #ifdef CLIENT_IPC_THREAD
684         SESSION_EXTERN_BEGIN;
685         result = session->getChannelCountSync();
686         SESSION_EXTERN_END;
687 #endif
688
689         return result;
690 }