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