code cleanup and fix build problems
[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                 /* 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                         {
171                                 gint ret;
172                                 GError *error = NULL;
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                                                 _ERR("smartcard_service_channel_call_close_channel_sync failed, [%d]", ret);
186                                                 THROW_ERROR(ret);
187                                         }
188                                 } else {
189                                         _ERR("smartcard_service_channel_call_close_channel_sync failed, [%s]", error->message);
190                                         g_error_free(error);
191
192                                         throw ErrorIO(SCARD_ERROR_IPC_FAILED);
193                                 }
194                         }
195                         else
196                         {
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                 {
208                         if (getSession()->getReader()->isSecureElementPresent() == true)
209                         {
210                                 CallbackParam *param = new CallbackParam();
211
212                                 param->instance = this;
213                                 param->callback = (void *)callback;
214                                 param->user_param = userParam;
215
216                                 smartcard_service_channel_call_close_channel(
217                                         (SmartcardServiceChannel *)proxy,
218                                         GPOINTER_TO_UINT(context),
219                                         GPOINTER_TO_UINT(handle), NULL,
220                                         &ClientChannel::channel_close_cb, param);
221                         }
222                         else
223                         {
224                                 _ERR("unavailable channel");
225                                 result = SCARD_ERROR_ILLEGAL_STATE;
226                         }
227                 }
228
229                 return result;
230         }
231
232         int ClientChannel::transmitSync(const ByteArray &command, ByteArray &result)
233                 throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &,
234                         ErrorIllegalParameter &, ErrorSecurity &)
235         {
236                 int rv = SCARD_ERROR_OK;
237
238                 if (getSession()->getReader()->isSecureElementPresent() == true)
239                 {
240                         GVariant *var_command = NULL, *var_response = NULL;
241                         GError *error = NULL;
242
243                         var_command = GDBusHelper::convertByteArrayToVariant(command);
244
245                         if (smartcard_service_channel_call_transmit_sync(
246                                 (SmartcardServiceChannel *)proxy,
247                                 GPOINTER_TO_UINT(context),
248                                 GPOINTER_TO_UINT(handle),
249                                 var_command, &rv, &var_response,
250                                 NULL, &error) == true) {
251
252                                 if (rv == SCARD_ERROR_OK) {
253                                         GDBusHelper::convertVariantToByteArray(var_response, result);
254                                 } else {
255                                         _ERR("smartcard_service_session_call_get_atr_sync failed, [%d]", rv);
256                                         THROW_ERROR(rv);
257                                 }
258                         } else {
259                                 _ERR("smartcard_service_session_call_get_atr_sync failed, [%s]", error->message);
260                                 g_error_free(error);
261
262                                 throw ErrorIO(SCARD_ERROR_IPC_FAILED);
263                         }
264                 }
265                 else
266                 {
267                         _ERR("unavailable channel");
268                         throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
269                 }
270
271                 return rv;
272         }
273
274         int ClientChannel::transmit(const ByteArray &command, transmitCallback callback, void *userParam)
275         {
276                 int result;
277
278                 if (getSession()->getReader()->isSecureElementPresent() == true)
279                 {
280                         GVariant *var_command;
281                         CallbackParam *param = new CallbackParam();
282
283                         param->instance = this;
284                         param->callback = (void *)callback;
285                         param->user_param = userParam;
286
287                         var_command = GDBusHelper::convertByteArrayToVariant(command);
288
289                         smartcard_service_channel_call_transmit(
290                                 (SmartcardServiceChannel *)proxy,
291                                 GPOINTER_TO_UINT(context),
292                                 GPOINTER_TO_UINT(handle),
293                                 var_command, NULL,
294                                 &ClientChannel::channel_transmit_cb, param);
295
296                         result = SCARD_ERROR_OK;
297                 }
298                 else
299                 {
300                         _ERR("unavailable channel");
301                         result = SCARD_ERROR_ILLEGAL_STATE;
302                 }
303
304                 return result;
305         }
306 } /* namespace smartcard_service_api */
307
308 /* export C API */
309 #define CHANNEL_EXTERN_BEGIN \
310         if (handle != NULL) \
311         { \
312                 ClientChannel *channel = (ClientChannel *)handle;
313
314 #define CHANNEL_EXTERN_END \
315         } \
316         else \
317         { \
318                 _ERR("Invalid param"); \
319         }
320
321 using namespace smartcard_service_api;
322
323 EXTERN_API int channel_close(channel_h handle, channel_close_cb callback, void *userParam)
324 {
325         int result = -1;
326
327         CHANNEL_EXTERN_BEGIN;
328         result = channel->close((closeChannelCallback)callback, userParam);
329         CHANNEL_EXTERN_END;
330
331         return result;
332 }
333
334 EXTERN_API int channel_transmit(channel_h handle, unsigned char *command,
335         unsigned int length, channel_transmit_cb callback, void *userParam)
336 {
337         int result = -1;
338
339         CHANNEL_EXTERN_BEGIN;
340         ByteArray temp;
341
342         temp.assign(command, length);
343         result = channel->transmit(temp, (transmitCallback)callback, userParam);
344         CHANNEL_EXTERN_END;
345
346         return result;
347 }
348
349 EXTERN_API void channel_close_sync(channel_h handle)
350 {
351         CHANNEL_EXTERN_BEGIN;
352         try
353         {
354                 channel->closeSync();
355         }
356         catch (...)
357         {
358         }
359         CHANNEL_EXTERN_END;
360 }
361
362 EXTERN_API int channel_transmit_sync(channel_h handle, unsigned char *command,
363         unsigned int cmd_len, unsigned char **response, unsigned int *resp_len)
364 {
365         int result = -1;
366
367         if (command == NULL || cmd_len == 0 || response == NULL || resp_len == NULL)
368                 return result;
369
370         CHANNEL_EXTERN_BEGIN;
371         ByteArray temp, resp;
372
373         temp.assign(command, cmd_len);
374
375         try
376         {
377                 result = channel->transmitSync(temp, resp);
378                 if (resp.size() > 0)
379                 {
380                         *resp_len = resp.size();
381                         *response = (unsigned char *)calloc(1, *resp_len);
382                         memcpy(*response, resp.getBuffer(), *resp_len);
383                 }
384         }
385         catch (...)
386         {
387                 result = -1;
388         }
389         CHANNEL_EXTERN_END;
390
391         return result;
392 }
393
394 EXTERN_API bool channel_is_basic_channel(channel_h handle)
395 {
396         bool result = false;
397
398         CHANNEL_EXTERN_BEGIN;
399         result = channel->isBasicChannel();
400         CHANNEL_EXTERN_END;
401
402         return result;
403 }
404
405 EXTERN_API bool channel_is_closed(channel_h handle)
406 {
407         bool result = false;
408
409         CHANNEL_EXTERN_BEGIN;
410         result = channel->isClosed();
411         CHANNEL_EXTERN_END;
412
413         return result;
414 }
415
416 EXTERN_API unsigned int channel_get_select_response_length(channel_h handle)
417 {
418         unsigned int result = 0;
419
420         CHANNEL_EXTERN_BEGIN;
421         result = channel->getSelectResponse().size();
422         CHANNEL_EXTERN_END;
423
424         return result;
425 }
426
427 EXTERN_API bool channel_get_select_response(channel_h handle,
428         unsigned char *buffer, unsigned int length)
429 {
430         bool result = false;
431
432         if (buffer == NULL || length == 0)
433         {
434                 return result;
435         }
436
437         CHANNEL_EXTERN_BEGIN;
438         ByteArray response;
439
440         response = channel->getSelectResponse();
441         if (response.size() > 0)
442         {
443                 memcpy(buffer, response.getBuffer(), MIN(length, response.size()));
444                 result = true;
445         }
446         CHANNEL_EXTERN_END;
447
448         return result;
449 }
450
451 EXTERN_API session_h channel_get_session(channel_h handle)
452 {
453         session_h session = NULL;
454
455         CHANNEL_EXTERN_BEGIN;
456         session = channel->getSession();
457         CHANNEL_EXTERN_END;
458
459         return session;
460 }
461
462 EXTERN_API void channel_destroy_instance(channel_h handle)
463 {
464         /* do nothing */
465 }