Remove legacy codes
[platform/core/connectivity/smartcard-service.git] / client / 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                 /* initialize client */
59                 if (!g_thread_supported())
60                 {
61                         g_thread_init(NULL);
62                 }
63
64                 g_type_init();
65
66                 /* init default context */
67                 GError *error = NULL;
68
69                 proxy = smartcard_service_channel_proxy_new_for_bus_sync(
70                         G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
71                         "org.tizen.SmartcardService",
72                         "/org/tizen/SmartcardService/Channel",
73                         NULL, &error);
74                 if (proxy == NULL)
75                 {
76                         _ERR("Can not create proxy : %s", error->message);
77                         g_error_free(error);
78                         return;
79                 }
80         }
81
82         ClientChannel::~ClientChannel()
83         {
84                 closeSync();
85         }
86
87         void ClientChannel::channel_transmit_cb(GObject *source_object,
88                 GAsyncResult *res, gpointer user_data)
89         {
90                 CallbackParam *param = (CallbackParam *)user_data;
91                 transmitCallback callback;
92                 gint result;
93                 GVariant *var_response;
94                 GError *error = NULL;
95                 ByteArray response;
96
97                 _INFO("MSG_REQUEST_TRANSMIT");
98
99                 if (param == NULL) {
100                         _ERR("null parameter!!!");
101                         return;
102                 }
103
104                 callback = (transmitCallback)param->callback;
105
106                 if (smartcard_service_channel_call_transmit_finish(
107                         SMARTCARD_SERVICE_CHANNEL(source_object),
108                         &result, &var_response, res, &error) == true) {
109                         if (result == SCARD_ERROR_OK) {
110                                 GDBusHelper::convertVariantToByteArray(var_response, response);
111                         } else {
112                                 _ERR("smartcard_service_channel_call_transmit failed, [%d]", result);
113                         }
114                 } else {
115                         _ERR("smartcard_service_channel_call_transmit failed, [%s]", error->message);
116                         g_error_free(error);
117
118                         result = SCARD_ERROR_IPC_FAILED;
119                 }
120
121                 if (callback != NULL) {
122                         callback(response.getBuffer(),
123                                 response.size(),
124                                 result, param->user_param);
125                 }
126
127                 delete param;
128         }
129
130         void ClientChannel::channel_close_cb(GObject *source_object,
131                 GAsyncResult *res, gpointer user_data)
132         {
133                 CallbackParam *param = (CallbackParam *)user_data;
134                 ClientChannel *channel;
135                 closeChannelCallback callback;
136                 gint result;
137                 GError *error = NULL;
138
139                 _INFO("MSG_REQUEST_CLOSE_CHANNEL");
140
141                 if (param == NULL) {
142                         _ERR("null parameter!!!");
143                         return;
144                 }
145
146                 channel = (ClientChannel *)param->instance;
147                 callback = (closeChannelCallback)param->callback;
148
149                 if (smartcard_service_channel_call_close_channel_finish(
150                         SMARTCARD_SERVICE_CHANNEL(source_object),
151                         &result, res, &error) == true) {
152                         if (result == SCARD_ERROR_OK) {
153                                 channel->channelNum = -1;
154                         } else {
155                                 _ERR("smartcard_service_channel_call_close_channel failed, [%d]", result);
156                         }
157                 } else {
158                         _ERR("smartcard_service_channel_call_close_channel failed, [%s]", error->message);
159                         g_error_free(error);
160
161                         result = SCARD_ERROR_IPC_FAILED;
162                 }
163
164                 if (callback != NULL) {
165                         callback(result, param->user_param);
166                 }
167
168                 delete param;
169         }
170
171         void ClientChannel::closeSync()
172                 throw(ExceptionBase &, ErrorIO &, ErrorSecurity &,
173                         ErrorIllegalState &, ErrorIllegalParameter &)
174         {
175                 if (isClosed() == false)
176                 {
177                         if (getSession()->getReader()->isSecureElementPresent() == true)
178                         {
179                                 gint ret;
180                                 GError *error = NULL;
181
182                                 if (proxy == NULL) {
183                                         _ERR("dbus proxy is not initialized yet");
184                                         throw ErrorIllegalState(SCARD_ERROR_NOT_INITIALIZED);
185                                 }
186
187                                 if (smartcard_service_channel_call_close_channel_sync(
188                                         (SmartcardServiceChannel *)proxy,
189                                         GPOINTER_TO_UINT(context),
190                                         GPOINTER_TO_UINT(handle),
191                                         &ret, NULL, &error) == true) {
192                                         if (ret != SCARD_ERROR_OK) {
193                                                 _ERR("smartcard_service_channel_call_close_channel_sync failed, [%d]", ret);
194                                                 THROW_ERROR(ret);
195                                         }
196                                 } else {
197                                         _ERR("smartcard_service_channel_call_close_channel_sync failed, [%s]", error->message);
198                                         g_error_free(error);
199
200                                         throw ErrorIO(SCARD_ERROR_IPC_FAILED);
201                                 }
202                         }
203                         else
204                         {
205                                 _INFO("unavailable channel");
206                         }
207                 }
208         }
209
210         int ClientChannel::close(closeChannelCallback callback, void *userParam)
211         {
212                 int result = SCARD_ERROR_OK;
213
214                 if (isClosed() == false)
215                 {
216                         if (getSession()->getReader()->isSecureElementPresent() == true)
217                         {
218                                 CallbackParam *param = new CallbackParam();
219
220                                 param->instance = this;
221                                 param->callback = (void *)callback;
222                                 param->user_param = userParam;
223
224                                 smartcard_service_channel_call_close_channel(
225                                         (SmartcardServiceChannel *)proxy,
226                                         GPOINTER_TO_UINT(context),
227                                         GPOINTER_TO_UINT(handle), NULL,
228                                         &ClientChannel::channel_close_cb, param);
229                         }
230                         else
231                         {
232                                 _ERR("unavailable channel");
233                                 result = SCARD_ERROR_ILLEGAL_STATE;
234                         }
235                 }
236
237                 return result;
238         }
239
240         int ClientChannel::transmitSync(const ByteArray &command, ByteArray &result)
241                 throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &,
242                         ErrorIllegalParameter &, ErrorSecurity &)
243         {
244                 int rv = SCARD_ERROR_OK;
245
246                 if (getSession()->getReader()->isSecureElementPresent() == true)
247                 {
248                         GVariant *var_command = NULL, *var_response = NULL;
249                         GError *error = NULL;
250
251                         var_command = GDBusHelper::convertByteArrayToVariant(command);
252
253                         if (smartcard_service_channel_call_transmit_sync(
254                                 (SmartcardServiceChannel *)proxy,
255                                 GPOINTER_TO_UINT(context),
256                                 GPOINTER_TO_UINT(handle),
257                                 var_command, &rv, &var_response,
258                                 NULL, &error) == true) {
259
260                                 if (rv == SCARD_ERROR_OK) {
261                                         GDBusHelper::convertVariantToByteArray(var_response, result);
262                                 } else {
263                                         _ERR("smartcard_service_session_call_get_atr_sync failed, [%d]", rv);
264                                         THROW_ERROR(rv);
265                                 }
266                         } else {
267                                 _ERR("smartcard_service_session_call_get_atr_sync failed, [%s]", error->message);
268                                 g_error_free(error);
269
270                                 throw ErrorIO(SCARD_ERROR_IPC_FAILED);
271                         }
272                 }
273                 else
274                 {
275                         _ERR("unavailable channel");
276                         throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
277                 }
278
279                 return rv;
280         }
281
282         int ClientChannel::transmit(const ByteArray &command, transmitCallback callback, void *userParam)
283         {
284                 int result;
285
286                 if (getSession()->getReader()->isSecureElementPresent() == true)
287                 {
288                         GVariant *var_command;
289                         CallbackParam *param = new CallbackParam();
290
291                         param->instance = this;
292                         param->callback = (void *)callback;
293                         param->user_param = userParam;
294
295                         var_command = GDBusHelper::convertByteArrayToVariant(command);
296
297                         smartcard_service_channel_call_transmit(
298                                 (SmartcardServiceChannel *)proxy,
299                                 GPOINTER_TO_UINT(context),
300                                 GPOINTER_TO_UINT(handle),
301                                 var_command, NULL,
302                                 &ClientChannel::channel_transmit_cb, param);
303
304                         result = SCARD_ERROR_OK;
305                 }
306                 else
307                 {
308                         _ERR("unavailable channel");
309                         result = SCARD_ERROR_ILLEGAL_STATE;
310                 }
311
312                 return result;
313         }
314 } /* namespace smartcard_service_api */
315
316 /* export C API */
317 #define CHANNEL_EXTERN_BEGIN \
318         if (handle != NULL) \
319         { \
320                 ClientChannel *channel = (ClientChannel *)handle;
321
322 #define CHANNEL_EXTERN_END \
323         } \
324         else \
325         { \
326                 _ERR("Invalid param"); \
327         }
328
329 using namespace smartcard_service_api;
330
331 EXTERN_API int channel_close(channel_h handle, channel_close_cb callback, void *userParam)
332 {
333         int result = -1;
334
335         CHANNEL_EXTERN_BEGIN;
336         result = channel->close((closeChannelCallback)callback, userParam);
337         CHANNEL_EXTERN_END;
338
339         return result;
340 }
341
342 EXTERN_API int channel_transmit(channel_h handle, unsigned char *command,
343         unsigned int length, channel_transmit_cb callback, void *userParam)
344 {
345         int result = -1;
346
347         CHANNEL_EXTERN_BEGIN;
348         ByteArray temp;
349
350         temp.assign(command, length);
351         result = channel->transmit(temp, (transmitCallback)callback, userParam);
352         CHANNEL_EXTERN_END;
353
354         return result;
355 }
356
357 EXTERN_API void channel_close_sync(channel_h handle)
358 {
359         CHANNEL_EXTERN_BEGIN;
360         try
361         {
362                 channel->closeSync();
363         }
364         catch (...)
365         {
366         }
367         CHANNEL_EXTERN_END;
368 }
369
370 EXTERN_API int channel_transmit_sync(channel_h handle, unsigned char *command,
371         unsigned int cmd_len, unsigned char **response, unsigned int *resp_len)
372 {
373         int result = -1;
374
375         if (command == NULL || cmd_len == 0 || response == NULL || resp_len == NULL)
376                 return result;
377
378         CHANNEL_EXTERN_BEGIN;
379         ByteArray temp, resp;
380
381         temp.assign(command, cmd_len);
382
383         try
384         {
385                 result = channel->transmitSync(temp, resp);
386                 if (resp.size() > 0)
387                 {
388                         *resp_len = resp.size();
389                         *response = (unsigned char *)calloc(1, *resp_len);
390                         memcpy(*response, resp.getBuffer(), *resp_len);
391                 }
392         }
393         catch (...)
394         {
395                 result = -1;
396         }
397         CHANNEL_EXTERN_END;
398
399         return result;
400 }
401
402 EXTERN_API bool channel_is_basic_channel(channel_h handle)
403 {
404         bool result = false;
405
406         CHANNEL_EXTERN_BEGIN;
407         result = channel->isBasicChannel();
408         CHANNEL_EXTERN_END;
409
410         return result;
411 }
412
413 EXTERN_API bool channel_is_closed(channel_h handle)
414 {
415         bool result = false;
416
417         CHANNEL_EXTERN_BEGIN;
418         result = channel->isClosed();
419         CHANNEL_EXTERN_END;
420
421         return result;
422 }
423
424 EXTERN_API unsigned int channel_get_select_response_length(channel_h handle)
425 {
426         unsigned int result = 0;
427
428         CHANNEL_EXTERN_BEGIN;
429         result = channel->getSelectResponse().size();
430         CHANNEL_EXTERN_END;
431
432         return result;
433 }
434
435 EXTERN_API bool channel_get_select_response(channel_h handle,
436         unsigned char *buffer, unsigned int length)
437 {
438         bool result = false;
439
440         if (buffer == NULL || length == 0)
441         {
442                 return result;
443         }
444
445         CHANNEL_EXTERN_BEGIN;
446         ByteArray response;
447
448         response = channel->getSelectResponse();
449         if (response.size() > 0)
450         {
451                 memcpy(buffer, response.getBuffer(), MIN(length, response.size()));
452                 result = true;
453         }
454         CHANNEL_EXTERN_END;
455
456         return result;
457 }
458
459 EXTERN_API session_h channel_get_session(channel_h handle)
460 {
461         session_h session = NULL;
462
463         CHANNEL_EXTERN_BEGIN;
464         session = channel->getSession();
465         CHANNEL_EXTERN_END;
466
467         return session;
468 }
469
470 EXTERN_API void channel_destroy_instance(channel_h handle)
471 {
472         /* do nothing */
473 }