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