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