Update source
[platform/core/connectivity/smartcard-service.git] / client / Session.cpp
1 /*
2 * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18 /* standard library header */
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <string.h>
23
24 /* SLP library header */
25
26 /* local header */
27 #include "Debug.h"
28 #include "Session.h"
29 #include "Reader.h"
30 #include "ClientChannel.h"
31 #include "ClientIPC.h"
32
33 #ifndef EXTERN_API
34 #define EXTERN_API __attribute__((visibility("default")))
35 #endif
36
37 namespace smartcard_service_api
38 {
39         Session::Session(void *context, Reader *reader, void *handle):SessionHelper(reader)
40         {
41                 this->context = NULL;
42
43                 if (context == NULL || handle == NULL)
44                 {
45                         SCARD_DEBUG_ERR("handle is null");
46
47                         return;
48                 }
49
50                 this->context = context;
51                 this->handle = handle;
52                 closed = false;
53         }
54
55         Session::~Session()
56         {
57                 close(NULL, this);
58         }
59
60         void Session::closeChannels()
61         {
62                 size_t i;
63
64                 for (i = 0; i < channels.size(); i++)
65                 {
66                         channels[i]->closeSync();
67                         delete (ClientChannel *)channels[i];
68                 }
69
70                 channels.clear();
71         }
72
73         ByteArray Session::getATRSync()
74         {
75                 Message msg;
76                 int rv;
77
78 #ifdef CLIENT_IPC_THREAD
79                 /* request channel handle from server */
80                 msg.message = Message::MSG_REQUEST_GET_ATR;
81                 msg.param1 = (unsigned int)handle;
82                 msg.error = (unsigned int)context; /* using error to context */
83                 msg.caller = (void *)this;
84                 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
85
86                 ClientIPC::getInstance().sendMessage(&msg);
87
88                 syncLock();
89                 rv = waitTimedCondition(0);
90                 syncUnlock();
91
92                 if (rv != 0)
93                 {
94                         SCARD_DEBUG_ERR("time over");
95
96                         atr.releaseBuffer();
97                 }
98 #endif
99
100                 return atr;
101         }
102
103         int Session::getATR(getATRCallback callback, void *userData)
104         {
105                 Message msg;
106
107                 /* request channel handle from server */
108                 msg.message = Message::MSG_REQUEST_GET_ATR;
109                 msg.param1 = (unsigned int)handle;
110                 msg.error = (unsigned int)context; /* using error to context */
111                 msg.caller = (void *)this;
112                 msg.callback = (void *)callback;
113                 msg.userParam = userData;
114
115                 ClientIPC::getInstance().sendMessage(&msg);
116
117                 return 0;
118         }
119
120         void Session::closeSync()
121         {
122                 Message msg;
123                 int rv;
124
125 #ifdef CLIENT_IPC_THREAD
126                 if (isClosed() == false)
127                 {
128                         closed = true;
129                         closeChannels();
130
131                         /* request channel handle from server */
132                         msg.message = Message::MSG_REQUEST_CLOSE_SESSION;
133                         msg.param1 = (unsigned int)handle;
134                         msg.error = (unsigned int)context; /* using error to context */
135                         msg.caller = (void *)this;
136                         msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
137
138                         ClientIPC::getInstance().sendMessage(&msg);
139
140                         syncLock();
141                         rv = waitTimedCondition(0);
142                         syncUnlock();
143
144                         if (rv != 0)
145                         {
146                                 SCARD_DEBUG_ERR("time over");
147                         }
148                 }
149 #endif
150         }
151
152         int Session::close(closeSessionCallback callback, void *userData)
153         {
154                 Message msg;
155
156                 if (isClosed() == false)
157                 {
158                         closed = true;
159                         closeChannels();
160
161                         /* request channel handle from server */
162                         msg.message = Message::MSG_REQUEST_CLOSE_SESSION;
163                         msg.param1 = (unsigned int)handle;
164                         msg.error = (unsigned int)context; /* using error to context */
165                         msg.caller = (void *)this;
166                         msg.callback = (void *)callback;
167                         msg.userParam = userData;
168
169                         ClientIPC::getInstance().sendMessage(&msg);
170                 }
171
172                 return 0;
173         }
174
175         unsigned int Session::getChannelCountSync()
176         {
177                 Message msg;
178                 int rv;
179
180 #ifdef CLIENT_IPC_THREAD
181                 /* request channel handle from server */
182                 msg.message = Message::MSG_REQUEST_GET_CHANNEL_COUNT;
183                 msg.param1 = (unsigned int)handle;
184                 msg.error = (unsigned int)context; /* using error to context */
185                 msg.caller = (void *)this;
186                 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
187
188                 ClientIPC::getInstance().sendMessage(&msg);
189
190                 syncLock();
191                 rv = waitTimedCondition(0);
192                 syncUnlock();
193
194                 if (rv != 0)
195                 {
196                         SCARD_DEBUG_ERR("time over");
197
198                         channelCount = -1;
199                 }
200 #endif
201
202                 return channelCount;
203         }
204
205         int Session::getChannelCount(getChannelCountCallback callback, void *userData)
206         {
207                 Message msg;
208
209                 msg.message = Message::MSG_REQUEST_GET_CHANNEL_COUNT;
210                 msg.param1 = (unsigned int)handle;
211                 msg.error = (unsigned int)context; /* using error to context */
212                 msg.caller = (void *)this;
213                 msg.callback = (void *)callback;
214                 msg.userParam = userData;
215
216                 ClientIPC::getInstance().sendMessage(&msg);
217
218                 return 0;
219         }
220
221         Channel *Session::openChannelSync(int id, ByteArray aid)
222         {
223                 Message msg;
224                 int rv;
225
226 #ifdef CLIENT_IPC_THREAD
227                 /* request channel handle from server */
228                 msg.message = Message::MSG_REQUEST_OPEN_CHANNEL;
229                 msg.param1 = id;
230                 msg.param2 = (unsigned int)handle;
231                 msg.data = aid;
232                 msg.error = (unsigned int)context; /* using error to context */
233                 msg.caller = (void *)this;
234                 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
235
236                 ClientIPC::getInstance().sendMessage(&msg);
237
238                 syncLock();
239                 rv = waitTimedCondition(0);
240                 syncUnlock();
241
242                 if (rv != 0)
243                 {
244                         SCARD_DEBUG_ERR("time over");
245
246                         openedChannel = NULL;
247                 }
248 #endif
249
250                 return (Channel *)openedChannel;
251         }
252
253         int Session::openChannel(int id, ByteArray aid, openChannelCallback callback, void *userData)
254         {
255                 Message msg;
256
257                 /* request channel handle from server */
258                 msg.message = Message::MSG_REQUEST_OPEN_CHANNEL;
259                 msg.param1 = id;
260                 msg.param2 = (unsigned int)handle;
261                 msg.data = aid;
262                 msg.error = (unsigned int)context; /* using error to context */
263                 msg.caller = (void *)this;
264                 msg.callback = (void *)callback;
265                 msg.userParam = userData;
266
267                 ClientIPC::getInstance().sendMessage(&msg);
268
269                 return 0;
270         }
271
272         Channel *Session::openBasicChannelSync(ByteArray aid)
273         {
274                 return openChannelSync(0, aid);
275         }
276
277         Channel *Session::openBasicChannelSync(unsigned char *aid, unsigned int length)
278         {
279                 return openBasicChannelSync(ByteArray(aid, length));
280         }
281
282         int Session::openBasicChannel(ByteArray aid, openChannelCallback callback, void *userData)
283         {
284                 return openChannel(0, aid, callback, userData);
285         }
286
287         int Session::openBasicChannel(unsigned char *aid, unsigned int length, openChannelCallback callback, void *userData)
288         {
289                 return openBasicChannel(ByteArray(aid, length), callback, userData);
290         }
291
292         Channel *Session::openLogicalChannelSync(ByteArray aid)
293         {
294                 return openChannelSync(1, aid);
295         }
296
297         Channel *Session::openLogicalChannelSync(unsigned char *aid, unsigned int length)
298         {
299                 return openLogicalChannelSync(ByteArray(aid, length));
300         }
301
302         int Session::openLogicalChannel(ByteArray aid, openChannelCallback callback, void *userData)
303         {
304                 return openChannel(1, aid, callback, userData);
305         }
306
307         int Session::openLogicalChannel(unsigned char *aid, unsigned int length, openChannelCallback callback, void *userData)
308         {
309                 return openLogicalChannel(ByteArray(aid, length), callback, userData);
310         }
311
312         bool Session::dispatcherCallback(void *message)
313         {
314                 Message *msg = (Message *)message;
315                 Session *session = NULL;
316                 bool result = false;
317
318                 if (msg == NULL)
319                 {
320                         SCARD_DEBUG_ERR("message is null");
321                         return result;
322                 }
323
324                 session = (Session *)msg->caller;
325
326                 switch (msg->message)
327                 {
328                 case Message::MSG_REQUEST_OPEN_CHANNEL :
329                         {
330                                 Channel *channel = NULL;
331
332                                 SCARD_DEBUG("MSG_REQUEST_OPEN_CHANNEL");
333
334                                 if (msg->param1 != 0)
335                                 {
336                                         /* create new instance of channel */
337                                         channel = new ClientChannel(session->context, session, msg->param2, msg->data, (void *)msg->param1);
338                                         if (channel != NULL)
339                                         {
340                                                 session->channels.push_back(channel);
341                                         }
342                                         else
343                                         {
344                                                 SCARD_DEBUG_ERR("alloc failed");
345
346                                                 msg->error = -1;
347                                         }
348                                 }
349
350                                 if (msg->callback == (void *)session) /* synchronized call */
351                                 {
352                                         /* sync call */
353                                         session->syncLock();
354
355                                         /* copy result */
356                                         session->error = msg->error;
357                                         session->openedChannel = channel;
358
359                                         session->signalCondition();
360                                         session->syncUnlock();
361                                 }
362                                 else if (msg->callback != NULL)
363                                 {
364                                         openChannelCallback cb = (openChannelCallback)msg->callback;
365
366                                         /* async call */
367                                         cb(channel, msg->error, msg->userParam);
368                                 }
369                         }
370                         break;
371
372                 case Message::MSG_REQUEST_GET_ATR :
373                         {
374                                 SCARD_DEBUG("MSG_REQUEST_GET_ATR");
375
376                                 if (msg->callback == (void *)session) /* synchronized call */
377                                 {
378                                         /* sync call */
379                                         session->syncLock();
380
381                                         session->error = msg->error;
382                                         session->atr = msg->data;
383
384                                         session->signalCondition();
385                                         session->syncUnlock();
386                                 }
387                                 else if (msg->callback != NULL)
388                                 {
389                                         getATRCallback cb = (getATRCallback)msg->callback;
390
391                                         /* async call */
392                                         cb(msg->data.getBuffer(), msg->data.getLength(), msg->error, msg->userParam);
393                                 }
394                         }
395                         break;
396
397                 case Message::MSG_REQUEST_CLOSE_SESSION :
398                         {
399                                 SCARD_DEBUG("MSG_REQUEST_CLOSE_SESSION");
400
401                                 if (msg->callback == (void *)session) /* synchronized call */
402                                 {
403                                         /* sync call */
404                                         session->syncLock();
405
406                                         session->error = msg->error;
407
408                                         session->signalCondition();
409                                         session->syncUnlock();
410                                 }
411                                 else if (msg->callback != NULL)
412                                 {
413                                         closeSessionCallback cb = (closeSessionCallback)msg->callback;
414
415                                         /* async call */
416                                         cb(msg->error, msg->userParam);
417                                 }
418                         }
419                         break;
420
421                 case Message::MSG_REQUEST_GET_CHANNEL_COUNT :
422                         {
423                                 SCARD_DEBUG("MSG_REQUEST_GET_CHANNEL_COUNT");
424
425                                 if (msg->callback == (void *)session) /* synchronized call */
426                                 {
427                                         /* sync call */
428                                         session->syncLock();
429
430                                         session->error = msg->error;
431                                         session->channelCount = msg->param1;
432
433                                         session->signalCondition();
434                                         session->syncUnlock();
435                                 }
436                                 else if (msg->callback != NULL)
437                                 {
438                                         getChannelCountCallback cb = (getChannelCountCallback)msg->callback;
439
440                                         /* async call */
441                                         cb(msg->param1, msg->error, msg->userParam);
442                                 }
443                         }
444                         break;
445
446                 default:
447                         SCARD_DEBUG("unknown message : %s", msg->toString());
448                         break;
449                 }
450
451                 delete msg;
452
453                 return result;
454         }
455 } /* namespace smartcard_service_api */
456
457 /* export C API */
458 #define SESSION_EXTERN_BEGIN \
459         if (handle != NULL) \
460         { \
461                 Session *session = (Session *)handle;
462
463 #define SESSION_EXTERN_END \
464         } \
465         else \
466         { \
467                 SCARD_DEBUG_ERR("Invalid param"); \
468         }
469
470 using namespace smartcard_service_api;
471
472 EXTERN_API reader_h session_get_reader(session_h handle)
473 {
474         reader_h reader = NULL;
475
476         SESSION_EXTERN_BEGIN;
477         reader = session->getReader();
478         SESSION_EXTERN_END;
479
480         return reader;
481 }
482
483 EXTERN_API int session_get_atr(session_h handle, session_get_atr_cb callback, void *userData)
484 {
485         int result = -1;
486
487         SESSION_EXTERN_BEGIN;
488         result = session->getATR((getATRCallback)callback, userData);
489         SESSION_EXTERN_END;
490
491         return result;
492 }
493
494 EXTERN_API int session_close(session_h handle, session_close_session_cb callback, void *userData)
495 {
496         int result = -1;
497
498         SESSION_EXTERN_BEGIN;
499         result = session->close((closeSessionCallback)callback, userData);
500         SESSION_EXTERN_END;
501
502         return result;
503 }
504
505 EXTERN_API bool session_is_closed(session_h handle)
506 {
507         bool result = false;
508
509         SESSION_EXTERN_BEGIN;
510         result = session->isClosed();
511         SESSION_EXTERN_END;
512
513         return result;
514 }
515
516 EXTERN_API void session_close_channels(session_h handle)
517 {
518         SESSION_EXTERN_BEGIN;
519         session->closeChannels();
520         SESSION_EXTERN_END;
521 }
522
523 EXTERN_API int session_open_basic_channel(session_h handle, unsigned char *aid, unsigned int length, session_open_channel_cb callback, void *userData)
524 {
525         int result = -1;
526
527         SESSION_EXTERN_BEGIN;
528         result = session->openBasicChannel(aid, length, (openChannelCallback)callback, userData);
529         SESSION_EXTERN_END;
530
531         return result;
532 }
533
534 EXTERN_API int session_open_logical_channel(session_h handle, unsigned char *aid, unsigned int length, session_open_channel_cb callback, void *userData)
535 {
536         int result = -1;
537
538         SESSION_EXTERN_BEGIN;
539         result = session->openLogicalChannel(aid, length, (openChannelCallback)callback, userData);
540         SESSION_EXTERN_END;
541
542         return result;
543 }
544
545 EXTERN_API int session_get_channel_count(session_h handle, session_get_channel_count_cb callback, void * userData)
546 {
547         int result = -1;
548
549         SESSION_EXTERN_BEGIN;
550         result = session->getChannelCount((getChannelCountCallback)callback, userData);
551         SESSION_EXTERN_END;
552
553         return result;
554 }
555
556 EXTERN_API void session_destroy_instance(session_h handle)
557 {
558         SESSION_EXTERN_BEGIN;
559         delete session;
560         SESSION_EXTERN_END;
561 }
562
563 EXTERN_API int session_get_atr_sync(session_h handle, unsigned char **buffer, unsigned int *length)
564 {
565         ByteArray temp;
566         int result = -1;
567
568 #ifdef CLIENT_IPC_THREAD
569         if (buffer == NULL || length == NULL)
570                 return result;
571
572         SESSION_EXTERN_BEGIN;
573         temp = session->getATRSync();
574         if (temp.getLength() > 0)
575         {
576                 *length = temp.getLength();
577                 *buffer = (unsigned char *)calloc(1, *length);
578                 memcpy(*buffer, temp.getBuffer(), *length);
579
580                 result = 0;
581         }
582         SESSION_EXTERN_END;
583 #endif
584
585         return result;
586 }
587
588 EXTERN_API void session_close_sync(session_h handle)
589 {
590 #ifdef CLIENT_IPC_THREAD
591         SESSION_EXTERN_BEGIN;
592         session->closeSync();
593         SESSION_EXTERN_END;
594 #endif
595 }
596
597 EXTERN_API channel_h session_open_basic_channel_sync(session_h handle, unsigned char *aid, unsigned int length)
598 {
599         channel_h result = NULL;
600
601 #ifdef CLIENT_IPC_THREAD
602         SESSION_EXTERN_BEGIN;
603         result = session->openBasicChannelSync(aid, length);
604         SESSION_EXTERN_END;
605 #endif
606
607         return result;
608 }
609
610 EXTERN_API channel_h session_open_logical_channel_sync(session_h handle, unsigned char *aid, unsigned int length)
611 {
612         channel_h result = NULL;
613
614 #ifdef CLIENT_IPC_THREAD
615         SESSION_EXTERN_BEGIN;
616         result = session->openBasicChannelSync(aid, length);
617         SESSION_EXTERN_END;
618 #endif
619
620         return result;
621 }
622
623 EXTERN_API unsigned int session_get_channel_count_sync(session_h handle)
624 {
625         unsigned int result = 0;
626
627 #ifdef CLIENT_IPC_THREAD
628         SESSION_EXTERN_BEGIN;
629         result = session->getChannelCountSync();
630         SESSION_EXTERN_END;
631 #endif
632
633         return result;
634 }