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