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