update the latest source
[framework/system/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 <unistd.h>
21
22 /* SLP library header */
23
24 /* local header */
25 #include "Debug.h"
26 #include "Session.h"
27 #include "Reader.h"
28 #include "ClientChannel.h"
29 #include "ClientIPC.h"
30
31 #ifndef EXTERN_API
32 #define EXTERN_API __attribute__((visibility("default")))
33 #endif
34
35 namespace smartcard_service_api
36 {
37         Session::Session(void *context, Reader *reader, void *handle):SessionHelper(reader)
38         {
39                 this->context = NULL;
40
41                 if (context == NULL || handle == NULL)
42                 {
43                         SCARD_DEBUG_ERR("handle is null");
44
45                         return;
46                 }
47
48                 this->context = context;
49                 this->handle = handle;
50                 closed = false;
51         }
52
53         Session::~Session()
54         {
55                 close(NULL, this);
56         }
57
58         void Session::closeChannels()
59         {
60                 size_t i;
61
62                 for (i = 0; i < channels.size(); i++)
63                 {
64                         channels[i]->close(NULL, this);
65                 }
66
67                 channels.clear();
68         }
69
70         ByteArray Session::getATRSync()
71         {
72                 Message msg;
73                 int rv;
74
75                 /* request channel handle from server */
76                 msg.message = Message::MSG_REQUEST_GET_ATR;
77                 msg.param1 = (unsigned int)handle;
78                 msg.error = (unsigned int)context; /* using error to context */
79                 msg.caller = (void *)this;
80                 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
81
82                 ClientIPC::getInstance().sendMessage(&msg);
83
84                 syncLock();
85                 rv = waitTimedCondition(0);
86                 syncUnlock();
87
88                 if (rv != 0)
89                 {
90                         SCARD_DEBUG_ERR("time over");
91
92                         atr.releaseBuffer();
93                 }
94
95                 return atr;
96         }
97
98         int Session::getATR(getATRCallback callback, void *userData)
99         {
100                 Message msg;
101
102                 /* request channel handle from server */
103                 msg.message = Message::MSG_REQUEST_GET_ATR;
104                 msg.param1 = (unsigned int)handle;
105                 msg.error = (unsigned int)context; /* using error to context */
106                 msg.caller = (void *)this;
107                 msg.callback = (void *)callback;
108                 msg.userParam = userData;
109
110                 ClientIPC::getInstance().sendMessage(&msg);
111
112                 return 0;
113         }
114
115         void Session::closeSync()
116         {
117                 Message msg;
118                 int rv;
119
120                 if (isClosed() == false)
121                 {
122                         closed = true;
123                         closeChannels();
124
125                         /* request channel handle from server */
126                         msg.message = Message::MSG_REQUEST_CLOSE_SESSION;
127                         msg.param1 = (unsigned int)handle;
128                         msg.error = (unsigned int)context; /* using error to context */
129                         msg.caller = (void *)this;
130                         msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
131
132                         ClientIPC::getInstance().sendMessage(&msg);
133
134                         syncLock();
135                         rv = waitTimedCondition(0);
136                         syncUnlock();
137
138                         if (rv != 0)
139                         {
140                                 SCARD_DEBUG_ERR("time over");
141                         }
142                 }
143         }
144
145         int Session::close(closeSessionCallback callback, void *userData)
146         {
147                 Message msg;
148
149                 if (isClosed() == false)
150                 {
151                         closed = true;
152                         closeChannels();
153
154                         /* request channel handle from server */
155                         msg.message = Message::MSG_REQUEST_CLOSE_SESSION;
156                         msg.param1 = (unsigned int)handle;
157                         msg.error = (unsigned int)context; /* using error to context */
158                         msg.caller = (void *)this;
159                         msg.callback = (void *)callback;
160                         msg.userParam = userData;
161
162                         ClientIPC::getInstance().sendMessage(&msg);
163                 }
164
165                 return 0;
166         }
167
168         unsigned int Session::getChannelCount(getChannelCountCallback callback, void *userData)
169         {
170                 Message msg;
171
172                 msg.message = Message::MSG_REQUEST_GET_CHANNEL_COUNT;
173                 msg.param1 = (unsigned int)handle;
174                 msg.error = (unsigned int)context; /* using error to context */
175                 msg.caller = (void *)this;
176                 msg.callback = (void *)callback;
177                 msg.userParam = userData;
178
179                 ClientIPC::getInstance().sendMessage(&msg);
180
181                 return 0;
182         }
183
184         unsigned int Session::getChannelCountSync()
185         {
186                 Message msg;
187                 int rv;
188
189                 /* request channel handle from server */
190                 msg.message = Message::MSG_REQUEST_GET_CHANNEL_COUNT;
191                 msg.param1 = (unsigned int)handle;
192                 msg.error = (unsigned int)context; /* using error to context */
193                 msg.caller = (void *)this;
194                 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
195
196                 ClientIPC::getInstance().sendMessage(&msg);
197
198                 syncLock();
199                 rv = waitTimedCondition(0);
200                 syncUnlock();
201
202                 if (rv != 0)
203                 {
204                         SCARD_DEBUG_ERR("time over");
205
206                         return -1;
207                 }
208
209                 return channelCount;
210         }
211
212         Channel *Session::openChannelSync(int id, ByteArray aid)
213         {
214                 Message msg;
215                 int rv;
216
217                 /* request channel handle from server */
218                 msg.message = Message::MSG_REQUEST_OPEN_CHANNEL;
219                 msg.param1 = id;
220                 msg.param2 = (unsigned int)handle;
221                 msg.data = aid;
222                 msg.error = (unsigned int)context; /* using error to context */
223                 msg.caller = (void *)this;
224                 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
225
226                 ClientIPC::getInstance().sendMessage(&msg);
227
228                 syncLock();
229                 rv = waitTimedCondition(0);
230                 syncUnlock();
231
232                 if (rv != 0)
233                 {
234                         SCARD_DEBUG_ERR("time over");
235
236                         return NULL;
237                 }
238
239                 return (Channel *)openedChannel;
240         }
241
242         int Session::openChannel(int id, ByteArray aid, openChannelCallback callback, void *userData)
243         {
244                 Message msg;
245
246                 /* request channel handle from server */
247                 msg.message = Message::MSG_REQUEST_OPEN_CHANNEL;
248                 msg.param1 = id;
249                 msg.param2 = (unsigned int)handle;
250                 msg.data = aid;
251                 msg.error = (unsigned int)context; /* using error to context */
252                 msg.caller = (void *)this;
253                 msg.callback = (void *)callback;
254                 msg.userParam = userData;
255
256                 ClientIPC::getInstance().sendMessage(&msg);
257
258                 return 0;
259         }
260
261         Channel *Session::openBasicChannelSync(ByteArray aid)
262         {
263                 return openChannelSync(0, aid);
264         }
265
266         Channel *Session::openBasicChannelSync(unsigned char *aid, unsigned int length)
267         {
268                 return openBasicChannelSync(ByteArray(aid, length));
269         }
270
271         int Session::openBasicChannel(ByteArray aid, openChannelCallback callback, void *userData)
272         {
273                 return openChannel(0, aid, callback, userData);
274         }
275
276         int Session::openBasicChannel(unsigned char *aid, unsigned int length, openChannelCallback callback, void *userData)
277         {
278                 return openBasicChannel(ByteArray(aid, length), callback, userData);
279         }
280
281         Channel *Session::openLogicalChannelSync(ByteArray aid)
282         {
283                 return openChannelSync(1, aid);
284         }
285
286         Channel *Session::openLogicalChannelSync(unsigned char *aid, unsigned int length)
287         {
288                 return openLogicalChannelSync(ByteArray(aid, length));
289         }
290
291         int Session::openLogicalChannel(ByteArray aid, openChannelCallback callback, void *userData)
292         {
293                 return openChannel(1, aid, callback, userData);
294         }
295
296         int Session::openLogicalChannel(unsigned char *aid, unsigned int length, openChannelCallback callback, void *userData)
297         {
298                 return openLogicalChannel(ByteArray(aid, length), callback, userData);
299         }
300
301         bool Session::dispatcherCallback(void *message)
302         {
303                 Message *msg = (Message *)message;
304                 Session *session = NULL;
305                 bool result = false;
306
307                 if (msg == NULL)
308                 {
309                         SCARD_DEBUG_ERR("message is null");
310                         return result;
311                 }
312
313                 session = (Session *)msg->caller;
314
315                 switch (msg->message)
316                 {
317                 case Message::MSG_REQUEST_OPEN_CHANNEL :
318                         {
319                                 Channel *channel = NULL;
320
321                                 SCARD_DEBUG("MSG_REQUEST_OPEN_CHANNEL");
322
323                                 if (msg->param1 != 0)
324                                 {
325                                         /* create new instance of channel */
326                                         channel = new ClientChannel(session->context, session, msg->param2, msg->data, (void *)msg->param1);
327                                         if (channel != NULL)
328                                         {
329                                                 session->channels.push_back(channel);
330                                         }
331                                         else
332                                         {
333                                                 SCARD_DEBUG_ERR("alloc failed");
334
335                                                 msg->error = -1;
336                                         }
337                                 }
338
339                                 if (msg->callback == (void *)session) /* synchronized call */
340                                 {
341                                         /* sync call */
342                                         session->syncLock();
343
344                                         /* copy result */
345                                         session->error = msg->error;
346                                         session->openedChannel = channel;
347
348                                         session->signalCondition();
349                                         session->syncUnlock();
350                                 }
351                                 else if (msg->callback != NULL)
352                                 {
353                                         openChannelCallback cb = (openChannelCallback)msg->callback;
354
355                                         /* async call */
356                                         cb(channel, msg->error, msg->userParam);
357                                 }
358                         }
359                         break;
360
361                 case Message::MSG_REQUEST_GET_ATR :
362                         {
363                                 SCARD_DEBUG("MSG_REQUEST_GET_ATR");
364
365                                 if (msg->callback == (void *)session) /* synchronized call */
366                                 {
367                                         /* sync call */
368                                         session->syncLock();
369
370                                         session->error = msg->error;
371                                         session->atr = msg->data;
372
373                                         session->signalCondition();
374                                         session->syncUnlock();
375                                 }
376                                 else if (msg->callback != NULL)
377                                 {
378                                         getATRCallback cb = (getATRCallback)msg->callback;
379
380                                         /* async call */
381                                         cb(msg->data.getBuffer(), msg->data.getLength(), msg->error, msg->userParam);
382                                 }
383                         }
384                         break;
385
386                 case Message::MSG_REQUEST_CLOSE_SESSION :
387                         {
388                                 SCARD_DEBUG("MSG_REQUEST_CLOSE_SESSION");
389
390                                 if (msg->callback == (void *)session) /* synchronized call */
391                                 {
392                                         /* sync call */
393                                         session->syncLock();
394
395                                         session->error = msg->error;
396
397                                         session->signalCondition();
398                                         session->syncUnlock();
399                                 }
400                                 else if (msg->callback != NULL)
401                                 {
402                                         closeSessionCallback cb = (closeSessionCallback)msg->callback;
403
404                                         /* async call */
405                                         cb(msg->error, msg->userParam);
406                                 }
407                         }
408                         break;
409
410                 case Message::MSG_REQUEST_GET_CHANNEL_COUNT :
411                         {
412                                 SCARD_DEBUG("MSG_REQUEST_GET_CHANNEL_COUNT");
413
414                                 if (msg->callback == (void *)session) /* synchronized call */
415                                 {
416                                         /* sync call */
417                                         session->syncLock();
418
419                                         session->error = msg->error;
420                                         session->channelCount = msg->param1;
421
422                                         session->signalCondition();
423                                         session->syncUnlock();
424                                 }
425                                 else if (msg->callback != NULL)
426                                 {
427                                         getChannelCountCallback cb = (getChannelCountCallback)msg->callback;
428
429                                         /* async call */
430                                         cb(msg->param1, msg->error, msg->userParam);
431                                 }
432                         }
433                         break;
434
435                 default:
436                         SCARD_DEBUG("unknown message : %s", msg->toString());
437                         break;
438                 }
439
440                 delete msg;
441
442                 return result;
443         }
444 } /* namespace smartcard_service_api */
445
446 /* export C API */
447 #define SESSION_EXTERN_BEGIN \
448         if (handle != NULL) \
449         { \
450                 Session *session = (Session *)handle;
451
452 #define SESSION_EXTERN_END \
453         } \
454         else \
455         { \
456                 SCARD_DEBUG_ERR("Invalid param"); \
457         }
458
459 using namespace smartcard_service_api;
460
461 EXTERN_API reader_h session_get_reader(session_h handle)
462 {
463         reader_h reader = NULL;
464
465         SESSION_EXTERN_BEGIN;
466         reader = session->getReader();
467         SESSION_EXTERN_END;
468
469         return reader;
470 }
471
472 EXTERN_API int session_get_atr(session_h handle, session_get_atr_cb callback, void *userData)
473 {
474         int result = -1;
475
476         SESSION_EXTERN_BEGIN;
477         result = session->getATR((getATRCallback)callback, userData);
478         SESSION_EXTERN_END;
479
480         return result;
481 }
482
483 EXTERN_API int session_close(session_h handle, session_close_session_cb callback, void *userData)
484 {
485         int result = -1;
486
487         SESSION_EXTERN_BEGIN;
488         result = session->close((closeSessionCallback)callback, userData);
489         SESSION_EXTERN_END;
490
491         return result;
492 }
493
494 EXTERN_API bool session_is_closed(session_h handle)
495 {
496         bool result = false;
497
498         SESSION_EXTERN_BEGIN;
499         result = session->isClosed();
500         SESSION_EXTERN_END;
501
502         return result;
503 }
504
505 EXTERN_API void session_close_channels(session_h handle)
506 {
507         SESSION_EXTERN_BEGIN;
508         session->closeChannels();
509         SESSION_EXTERN_END;
510 }
511
512 EXTERN_API int session_open_basic_channel(session_h handle, unsigned char *aid, unsigned int length, session_open_channel_cb callback, void *userData)
513 {
514         int result = -1;
515
516         SESSION_EXTERN_BEGIN;
517         result = session->openBasicChannel(aid, length, (openChannelCallback)callback, userData);
518         SESSION_EXTERN_END;
519
520         return result;
521 }
522
523 EXTERN_API int session_open_logical_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->openLogicalChannel(aid, length, (openChannelCallback)callback, userData);
529         SESSION_EXTERN_END;
530
531         return result;
532 }
533
534 EXTERN_API unsigned int session_get_channel_count(session_h handle, session_get_channel_count_cb callback, void * userData)
535 {
536         unsigned int result = 0;
537
538         SESSION_EXTERN_BEGIN;
539         result = session->getChannelCount((getChannelCountCallback)callback, userData);
540         SESSION_EXTERN_END;
541
542         return result;
543 }
544
545 EXTERN_API void session_destroy_instance(session_h handle)
546 {
547         SESSION_EXTERN_BEGIN;
548         delete session;
549         SESSION_EXTERN_END;
550 }