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