Change some indent for Tizen 3.0 Coding rule
[platform/core/api/smartcard.git] / src / ClientChannel.cpp
1 /*
2  * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
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 <stdlib.h>
19 #include <unistd.h>
20 #include <string.h>
21 #include <glib.h>
22
23 /* SLP library header */
24
25 /* local header */
26 #include "Debug.h"
27 #include "ClientChannel.h"
28 #include "ReaderHelper.h"
29 #include "APDUHelper.h"
30 #include "ClientGDBus.h"
31
32 #ifndef EXTERN_API
33 #define EXTERN_API __attribute__((visibility("default")))
34 #endif
35
36 namespace smartcard_service_api
37 {
38         ClientChannel::ClientChannel(void *context, Session *session,
39                 int channelNum, const ByteArray &selectResponse, void *handle)
40                 : Channel(session)
41         {
42                 this->channelNum = -1;
43                 this->handle = NULL;
44                 this->context = NULL;
45
46                 if (handle == NULL)
47                 {
48                         _ERR("ClientIPC::getInstance() failed");
49
50                         return;
51                 }
52
53                 this->channelNum = channelNum;
54                 this->handle = handle;
55                 this->selectResponse = selectResponse;
56                 this->context = context;
57
58                 /* init default context */
59                 GError *error = NULL;
60
61                 proxy = smartcard_service_channel_proxy_new_for_bus_sync(
62                         G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
63                         "org.tizen.SmartcardService",
64                         "/org/tizen/SmartcardService/Channel",
65                         NULL, &error);
66                 if (proxy == NULL)
67                 {
68                         _ERR("Can not create proxy : %s", error->message);
69                         g_error_free(error);
70                         return;
71                 }
72         }
73
74         ClientChannel::~ClientChannel()
75         {
76                 closeSync();
77         }
78
79         void ClientChannel::channel_transmit_cb(GObject *source_object,
80                 GAsyncResult *res, gpointer user_data)
81         {
82                 CallbackParam *param = (CallbackParam *)user_data;
83                 transmitCallback callback;
84                 gint result;
85                 GVariant *var_response;
86                 GError *error = NULL;
87                 ByteArray response;
88
89                 _INFO("MSG_REQUEST_TRANSMIT");
90
91                 if (param == NULL) {
92                         _ERR("null parameter!!!");
93                         return;
94                 }
95
96                 callback = (transmitCallback)param->callback;
97
98                 if (smartcard_service_channel_call_transmit_finish(
99                         SMARTCARD_SERVICE_CHANNEL(source_object),
100                         &result, &var_response, res, &error) == true) {
101                         if (result == SCARD_ERROR_OK) {
102                                 GDBusHelper::convertVariantToByteArray(var_response, response);
103                         } else {
104                                 _ERR("smartcard_service_channel_call_transmit failed, [%d]", result);
105                         }
106                 } else {
107                         _ERR("smartcard_service_channel_call_transmit failed, [%s]", error->message);
108                         g_error_free(error);
109
110                         result = SCARD_ERROR_IPC_FAILED;
111                 }
112
113                 if (callback != NULL) {
114                         callback(response.getBuffer(),
115                                 response.size(),
116                                 result, param->user_param);
117                 }
118
119                 delete param;
120         }
121
122         void ClientChannel::channel_close_cb(GObject *source_object,
123                 GAsyncResult *res, gpointer user_data)
124         {
125                 CallbackParam *param = (CallbackParam *)user_data;
126                 ClientChannel *channel;
127                 closeChannelCallback callback;
128                 gint result;
129                 GError *error = NULL;
130
131                 _INFO("MSG_REQUEST_CLOSE_CHANNEL");
132
133                 if (param == NULL) {
134                         _ERR("null parameter!!!");
135                         return;
136                 }
137
138                 channel = (ClientChannel *)param->instance;
139                 callback = (closeChannelCallback)param->callback;
140
141                 if (smartcard_service_channel_call_close_channel_finish(
142                         SMARTCARD_SERVICE_CHANNEL(source_object),
143                         &result, res, &error) == true) {
144                         if (result == SCARD_ERROR_OK) {
145                                 channel->channelNum = -1;
146                         } else {
147                                 _ERR("smartcard_service_channel_call_close_channel failed, [%d]", result);
148                         }
149                 } else {
150                         _ERR("smartcard_service_channel_call_close_channel failed, [%s]", error->message);
151                         g_error_free(error);
152
153                         result = SCARD_ERROR_IPC_FAILED;
154                 }
155
156                 if (callback != NULL) {
157                         callback(result, param->user_param);
158                 }
159
160                 delete param;
161         }
162
163         void ClientChannel::closeSync()
164                 throw(ExceptionBase &, ErrorIO &, ErrorSecurity &,
165                         ErrorIllegalState &, ErrorIllegalParameter &)
166         {
167                 if (isClosed() == false)
168                 {
169                         if (getSession()->getReader()->isSecureElementPresent() == true) {
170                                 gint ret;
171                                 GError *error = NULL;
172
173
174                                 if (proxy == NULL) {
175                                         _ERR("dbus proxy is not initialized yet");
176                                         throw ErrorIllegalState(SCARD_ERROR_NOT_INITIALIZED);
177                                 }
178
179                                 if (smartcard_service_channel_call_close_channel_sync(
180                                         (SmartcardServiceChannel *)proxy,
181                                         GPOINTER_TO_UINT(context),
182                                         GPOINTER_TO_UINT(handle),
183                                         &ret, NULL, &error) == true) {
184                                         if (ret == SCARD_ERROR_OK) {
185                                                 channelNum = -1;
186                                         } else {
187                                                 _ERR("smartcard_service_channel_call_close_channel_sync failed, [%d]", ret);
188                                                 THROW_ERROR(ret);
189                                         }
190                                 } else {
191                                         _ERR("smartcard_service_channel_call_close_channel_sync failed, [%s]", error->message);
192                                         g_error_free(error);
193
194                                         throw ErrorIO(SCARD_ERROR_IPC_FAILED);
195                                 }
196                         } else {
197                                 _INFO("unavailable channel");
198                         }
199                 }
200         }
201
202         int ClientChannel::close(closeChannelCallback callback, void *userParam)
203         {
204                 int result = SCARD_ERROR_OK;
205
206                 if (isClosed() == false) {
207                         if (getSession()->getReader()->isSecureElementPresent() == true) {
208                                 CallbackParam *param = new CallbackParam();
209
210                                 param->instance = this;
211                                 param->callback = (void *)callback;
212                                 param->user_param = userParam;
213
214                                 smartcard_service_channel_call_close_channel(
215                                         (SmartcardServiceChannel *)proxy,
216                                         GPOINTER_TO_UINT(context),
217                                         GPOINTER_TO_UINT(handle), NULL,
218                                         &ClientChannel::channel_close_cb, param);
219                         } else {
220                                 _ERR("unavailable channel");
221                                 result = SCARD_ERROR_ILLEGAL_STATE;
222                         }
223                 }
224
225                 return result;
226         }
227
228         int ClientChannel::transmitSync(const ByteArray &command, ByteArray &result)
229                 throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &,
230                         ErrorIllegalParameter &, ErrorSecurity &)
231         {
232                 int rv = SCARD_ERROR_OK;
233
234                 if (getSession()->getReader()->isSecureElementPresent() == true) {
235                         GVariant *var_command = NULL, *var_response = NULL;
236                         GError *error = NULL;
237
238                         var_command = GDBusHelper::convertByteArrayToVariant(command);
239
240                         if (smartcard_service_channel_call_transmit_sync(
241                                 (SmartcardServiceChannel *)proxy,
242                                 GPOINTER_TO_UINT(context),
243                                 GPOINTER_TO_UINT(handle),
244                                 var_command, &rv, &var_response,
245                                 NULL, &error) == true) {
246                                 if (rv == SCARD_ERROR_OK) {
247                                         GDBusHelper::convertVariantToByteArray(var_response, transmitResponse);
248                                         result = transmitResponse;
249                                 } else {
250                                         _ERR("smartcard_service_session_call_transmit failed, [%d]", rv);
251                                         THROW_ERROR(rv);
252                                 }
253                         } else {
254                                 _ERR("smartcard_service_session_call_transmit failed, [%s]", error->message);
255                                 g_error_free(error);
256
257                                 throw ErrorIO(SCARD_ERROR_IPC_FAILED);
258                         }
259                 } else {
260                         _ERR("unavailable channel");
261                         throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
262                 }
263
264                 return rv;
265         }
266
267         int ClientChannel::transmit(const ByteArray &command, transmitCallback callback, void *userParam)
268         {
269                 int result;
270
271                 if (getSession()->getReader()->isSecureElementPresent() == true) {
272                         GVariant *var_command;
273                         CallbackParam *param = new CallbackParam();
274
275                         param->instance = this;
276                         param->callback = (void *)callback;
277                         param->user_param = userParam;
278
279                         var_command = GDBusHelper::convertByteArrayToVariant(command);
280
281                         smartcard_service_channel_call_transmit(
282                                 (SmartcardServiceChannel *)proxy,
283                                 GPOINTER_TO_UINT(context),
284                                 GPOINTER_TO_UINT(handle),
285                                 var_command, NULL,
286                                 &ClientChannel::channel_transmit_cb, param);
287
288                         result = SCARD_ERROR_OK;
289                 } else {
290                         _ERR("unavailable channel");
291                         result = SCARD_ERROR_ILLEGAL_STATE;
292                 }
293
294                 return result;
295         }
296 } /* namespace smartcard_service_api */
297
298 /* export C API */
299 #define CHANNEL_EXTERN_BEGIN \
300         if (handle != NULL) \
301         { \
302                 ClientChannel *channel = (ClientChannel *)handle;
303
304 #define CHANNEL_EXTERN_END \
305         } \
306         else \
307         { \
308                 _ERR("Invalid param"); \
309         }
310
311 using namespace smartcard_service_api;
312
313 EXTERN_API int channel_close_sync(channel_h handle)
314 {
315         int result = SCARD_ERROR_OK;
316
317         CHANNEL_EXTERN_BEGIN;
318
319         try
320         {
321                 channel->closeSync();
322         }
323         catch (ExceptionBase &e)
324         {
325                 _ERR("Error occur : %s\n", e.what());
326                 result = e.getErrorCode();
327         }
328         catch (...)
329         {
330                 _ERR("Error occur : unknown error\n");
331                 result = SCARD_ERROR_UNKNOWN;
332         }
333
334         CHANNEL_EXTERN_END;
335
336         return result;
337 }
338
339 EXTERN_API int channel_transmit_sync(channel_h handle, unsigned char *command,
340         unsigned int cmd_len, unsigned char **response, unsigned int *resp_len)
341 {
342         int result = SCARD_ERROR_OK;
343
344         if (command == NULL || cmd_len == 0 || response == NULL || resp_len == NULL)
345                 return SCARD_ERROR_UNKNOWN;
346
347         CHANNEL_EXTERN_BEGIN;
348
349         try
350         {
351                 ByteArray temp, resp;
352
353                 temp.assign(command, cmd_len);
354                 channel->transmitSync(temp, resp);
355
356                 if (resp.size() > 0)
357                 {
358                         *response = (unsigned char *)calloc(resp.size(), sizeof(unsigned char));
359                         *resp_len = resp.size();
360                         memcpy(*response, resp.getBuffer(), *resp_len);
361                 }
362         }
363         catch (ExceptionBase &e)
364         {
365                 _ERR("Error occur : %s\n", e.what());
366                 result = e.getErrorCode();
367                 *resp_len = 0;
368         }
369         catch (...)
370         {
371                 _ERR("Error occur : unknown error\n");
372                 result = SCARD_ERROR_UNKNOWN;
373                 *resp_len = 0;
374         }
375
376         CHANNEL_EXTERN_END;
377
378         return result;
379 }
380
381 EXTERN_API int channel_is_basic_channel(channel_h handle, bool* is_basic_channel)
382 {
383         int result = SCARD_ERROR_OK;
384
385         CHANNEL_EXTERN_BEGIN;
386
387         try
388         {
389                 *is_basic_channel = channel->isBasicChannel();
390         }
391         catch (ExceptionBase &e)
392         {
393                 _ERR("Error occur : %s\n", e.what());
394                 result = e.getErrorCode();
395         }
396         catch (...)
397         {
398                 _ERR("Error occur : unknown error\n");
399                 result = SCARD_ERROR_UNKNOWN;
400         }
401
402         CHANNEL_EXTERN_END;
403
404         return result;
405 }
406
407 EXTERN_API int channel_is_closed(channel_h handle, bool* is_closed)
408 {
409         int result = SCARD_ERROR_OK;
410
411         CHANNEL_EXTERN_BEGIN;
412
413         try
414         {
415                 *is_closed = channel->isClosed();
416         }
417         catch (ExceptionBase &e)
418         {
419                 _ERR("Error occur : %s\n", e.what());
420                 result = e.getErrorCode();
421         }
422         catch (...)
423         {
424                 _ERR("Error occur : unknown error\n");
425                 result = SCARD_ERROR_UNKNOWN;
426         }
427
428         CHANNEL_EXTERN_END;
429
430         return result;
431 }
432
433 EXTERN_API int channel_get_select_response(channel_h handle,
434         unsigned char **buffer, size_t *length)
435 {
436         int result = SCARD_ERROR_OK;
437
438         CHANNEL_EXTERN_BEGIN;
439
440         try
441         {
442                 ByteArray response = channel->getSelectResponse();
443                 uint8_t* get_buffer = response.getBuffer();
444
445                 *length = response.size();
446
447                 if (*length > 0)
448                 {
449                         *buffer = (unsigned char *)calloc(*length, sizeof(unsigned char));
450                         if(*buffer == NULL || get_buffer == NULL)
451                         {
452                                 *length = 0;
453                                 return SCARD_ERROR_NOT_ENOUGH_RESOURCE;
454                         }
455
456                         memcpy(*buffer, get_buffer, *length);
457                 }
458         }
459         catch (ExceptionBase &e)
460         {
461                 _ERR("Error occur : %s\n", e.what());
462                 result = e.getErrorCode();
463                 *length = 0;
464         }
465         catch (...)
466         {
467                 _ERR("Error occur : unknown error\n");
468                 result = SCARD_ERROR_UNKNOWN;
469                 *length = 0;
470         }
471
472         CHANNEL_EXTERN_END;
473
474         return result;
475 }
476
477 EXTERN_API int channel_get_transmit_response(channel_h handle,
478         unsigned char **buffer, size_t *length)
479 {
480         int result = SCARD_ERROR_OK;
481
482         CHANNEL_EXTERN_BEGIN;
483
484         try
485         {
486                 ByteArray response;
487
488                 response = channel->getTransmitResponse();
489
490                 *length = response.size();
491
492                 if (*length > 0)
493                 {
494                         *buffer = (unsigned char *)calloc(*length, sizeof(unsigned char));
495                         memcpy(*buffer, response.getBuffer(), *length);
496                 }
497         }
498         catch (ExceptionBase &e)
499         {
500                 _ERR("Error occur : %s\n", e.what());
501                 result = e.getErrorCode();
502                 *length = 0;
503         }
504         catch (...)
505         {
506                 _ERR("Error occur : unknown error\n");
507                 result = SCARD_ERROR_UNKNOWN;
508                 *length = 0;
509         }
510
511         CHANNEL_EXTERN_END;
512
513         return result;
514 }
515
516 EXTERN_API int channel_get_session(channel_h handle, int *session_handle)
517 {
518         int result = SCARD_ERROR_OK;
519         session_h session = NULL;
520
521         CHANNEL_EXTERN_BEGIN;
522
523         try
524         {
525                 session = channel->getSession();
526                 *session_handle = (long)session;
527         }
528         catch (ExceptionBase &e)
529         {
530                 _ERR("Error occur : %s\n", e.what());
531                 result = e.getErrorCode();
532         }
533         catch (...)
534         {
535                 _ERR("Error occur : unknown error\n");
536                 result = SCARD_ERROR_UNKNOWN;
537         }
538
539         CHANNEL_EXTERN_END;
540
541         return result;
542 }
543
544 EXTERN_API int channel_select_next(channel_h handle, bool *pSuccess)
545 {
546         int result = SCARD_ERROR_OK;
547
548         CHANNEL_EXTERN_BEGIN;
549
550         try
551         {
552                 *pSuccess = channel->selectNext();
553         }
554         catch (ExceptionBase &e)
555         {
556                 _ERR("Error occur : %s\n", e.what());
557                 result = e.getErrorCode();
558         }
559         catch (...)
560         {
561                 _ERR("Error occur : unknown error\n");
562                 result = SCARD_ERROR_UNKNOWN;
563         }
564
565         CHANNEL_EXTERN_END;
566
567         return result;
568 }
569
570 EXTERN_API unsigned int channel_get_select_response_length(channel_h handle)
571 {
572         unsigned int result = 0;
573
574         CHANNEL_EXTERN_BEGIN;
575         result = channel->getSelectResponse().size();
576         CHANNEL_EXTERN_END;
577
578         return result;
579 }
580
581 EXTERN_API int channel_close(channel_h handle, channel_close_cb callback, void *userParam)
582 {
583         int result = -1;
584
585         CHANNEL_EXTERN_BEGIN;
586         result = channel->close((closeChannelCallback)callback, userParam);
587         CHANNEL_EXTERN_END;
588
589         return result;
590 }
591
592 EXTERN_API int channel_transmit(channel_h handle, unsigned char *command,
593         unsigned int length, channel_transmit_cb callback, void *userParam)
594 {
595         int result = -1;
596
597         CHANNEL_EXTERN_BEGIN;
598         ByteArray temp;
599
600         temp.assign(command, length);
601         result = channel->transmit(temp, (transmitCallback)callback, userParam);
602         CHANNEL_EXTERN_END;
603
604         return result;
605 }
606
607 EXTERN_API void channel_destroy_instance(channel_h handle)
608 {
609         /* do nothing */
610 }