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