Add NOTICE, AUTHOR file and modify boilerplate
[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
22 /* SLP library header */
23
24 /* local header */
25 #include "Debug.h"
26 #include "Message.h"
27 #include "ClientIPC.h"
28 #include "ClientChannel.h"
29 #include "ReaderHelper.h"
30
31 #ifndef EXTERN_API
32 #define EXTERN_API __attribute__((visibility("default")))
33 #endif
34
35 namespace smartcard_service_api
36 {
37         ClientChannel::ClientChannel(void *context, Session *session, int channelNum, ByteArray selectResponse, void *handle):Channel(session)
38         {
39                 this->channelNum = -1;
40                 this->handle = NULL;
41                 this->context = NULL;
42
43                 if (handle == NULL)
44                 {
45                         SCARD_DEBUG_ERR("ClientIPC::getInstance() failed");
46
47                         return;
48                 }
49
50                 this->channelNum = channelNum;
51                 this->handle = handle;
52                 this->selectResponse = selectResponse;
53                 this->context = context;
54         }
55
56         ClientChannel::~ClientChannel()
57         {
58                 closeSync();
59         }
60
61         void ClientChannel::closeSync()
62         {
63 #ifdef CLIENT_IPC_THREAD
64                 if (isClosed() == false)
65                 {
66                         if (getSession()->getReader()->isSecureElementPresent() == true)
67                         {
68                                 Message msg;
69                                 int rv;
70
71                                 /* send message to server */
72                                 msg.message = Message::MSG_REQUEST_CLOSE_CHANNEL;
73                                 msg.param1 = (int)handle;
74                                 msg.error = (unsigned int)context; /* using error to context */
75                                 msg.caller = (void *)this;
76                                 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
77
78                                 syncLock();
79                                 if (ClientIPC::getInstance().sendMessage(&msg) == true)
80                                 {
81                                         rv = waitTimedCondition(0);
82                                         if (rv < 0)
83                                         {
84                                                 SCARD_DEBUG_ERR("closeSync failed [%d]", rv);
85                                         }
86                                 }
87                                 else
88                                 {
89                                         SCARD_DEBUG_ERR("sendMessage failed");
90                                 }
91                                 syncUnlock();
92
93                                 channelNum = -1;
94                         }
95                         else
96                         {
97                                 SCARD_DEBUG_ERR("unavailable channel");
98                         }
99                 }
100 #endif
101         }
102
103         int ClientChannel::close(closeCallback callback, void *userParam)
104         {
105                 int result = 0;
106
107                 if (isClosed() == false)
108                 {
109                         if (getSession()->getReader()->isSecureElementPresent() == true)
110                         {
111                                 Message msg;
112
113                                 channelNum = -1;
114
115                                 /* send message to server */
116                                 msg.message = Message::MSG_REQUEST_CLOSE_CHANNEL;
117                                 msg.param1 = (int)handle;
118                                 msg.error = (unsigned int)context; /* using error to context */
119                                 msg.caller = (void *)this;
120                                 msg.callback = (void *)callback;
121                                 msg.userParam = userParam;
122
123                                 if (ClientIPC::getInstance().sendMessage(&msg) == true)
124                                 {
125                                         result = 0;
126                                 }
127                                 else
128                                 {
129                                         result = -1;
130                                 }
131                         }
132                         else
133                         {
134                                 SCARD_DEBUG_ERR("unavailable channel");
135                                 result = -1;
136                         }
137                 }
138
139                 return result;
140         }
141
142         int ClientChannel::transmitSync(ByteArray command, ByteArray &result)
143         {
144                 int rv = -1;
145
146                 if (getSession()->getReader()->isSecureElementPresent() == true)
147                 {
148                         Message msg;
149
150 #ifdef CLIENT_IPC_THREAD
151                         /* send message to server */
152                         msg.message = Message::MSG_REQUEST_TRANSMIT;
153                         msg.param1 = (int)handle;
154                         msg.param2 = 0;
155                         msg.data = command;
156                         msg.error = (unsigned int)context; /* using error to context */
157                         msg.caller = (void *)this;
158                         msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
159
160                         syncLock();
161                         if (ClientIPC::getInstance().sendMessage(&msg) == true)
162                         {
163                                 rv = waitTimedCondition(0);
164                                 if (rv >= 0)
165                                 {
166                                         result = response;
167
168                                         rv = 0;
169                                 }
170                                 else
171                                 {
172                                         SCARD_DEBUG_ERR("clientIPC is null");
173
174                                         rv = -1;
175                                 }
176                         }
177                         else
178                         {
179                                 SCARD_DEBUG_ERR("sendMessage failed");
180                         }
181                         syncUnlock();
182 #endif
183                 }
184                 else
185                 {
186                         SCARD_DEBUG_ERR("unavailable channel");
187                 }
188
189                 return rv;
190         }
191
192         int ClientChannel::transmit(ByteArray command, transmitCallback callback, void *userParam)
193         {
194                 int result = -1;
195
196                 if (getSession()->getReader()->isSecureElementPresent() == true)
197                 {
198                         Message msg;
199
200                         /* send message to server */
201                         msg.message = Message::MSG_REQUEST_TRANSMIT;
202                         msg.param1 = (int)handle;
203                         msg.param2 = 0;
204                         msg.data = command;
205                         msg.error = (unsigned int)context; /* using error to context */
206                         msg.caller = (void *)this;
207                         msg.callback = (void *)callback;
208                         msg.userParam = userParam;
209
210                         if (ClientIPC::getInstance().sendMessage(&msg) == true)
211                         {
212                                 result = 0;
213                         }
214                         else
215                         {
216                                 result = -1;
217                         }
218                 }
219                 else
220                 {
221                         SCARD_DEBUG_ERR("unavailable channel");
222                 }
223
224                 return result;
225         }
226
227         bool ClientChannel::dispatcherCallback(void *message)
228         {
229                 Message *msg = (Message *)message;
230                 ClientChannel *channel = NULL;
231                 bool result = false;
232
233                 if (msg == NULL)
234                 {
235                         SCARD_DEBUG_ERR("message is null");
236                         return result;
237                 }
238
239                 channel = (ClientChannel *)msg->caller;
240
241                 switch (msg->message)
242                 {
243                 case Message::MSG_REQUEST_TRANSMIT :
244                         {
245                                 /* transmit result */
246                                 SCARD_DEBUG("MSG_REQUEST_TRANSMIT");
247
248                                 if (msg->isSynchronousCall() == true) /* synchronized call */
249                                 {
250                                         /* sync call */
251                                         channel->syncLock();
252
253                                         /* copy result */
254                                         channel->error = msg->error;
255                                         channel->response = msg->data;
256
257                                         channel->signalCondition();
258                                         channel->syncUnlock();
259                                 }
260                                 else if (msg->callback != NULL)
261                                 {
262                                         transmitCallback cb = (transmitCallback)msg->callback;
263
264                                         /* async call */
265                                         cb(msg->data.getBuffer(), msg->data.getLength(), msg->error, msg->userParam);
266                                 }
267                         }
268                         break;
269
270                 case Message::MSG_REQUEST_CLOSE_CHANNEL :
271                         {
272                                 SCARD_DEBUG("MSG_REQUEST_CLOSE_CHANNEL");
273
274                                 if (msg->isSynchronousCall() == true) /* synchronized call */
275                                 {
276                                         /* sync call */
277                                         channel->syncLock();
278
279                                         channel->error = msg->error;
280
281                                         channel->signalCondition();
282                                         channel->syncUnlock();
283                                 }
284                                 else if (msg->callback != NULL)
285                                 {
286                                         closeCallback cb = (closeCallback)msg->callback;
287
288                                         /* async call */
289                                         cb(msg->error, msg->userParam);
290                                 }
291                         }
292                         break;
293
294                 default:
295                         SCARD_DEBUG("unknwon message : %s", msg->toString());
296                         break;
297                 }
298
299                 return result;
300         }
301 } /* namespace smartcard_service_api */
302
303 /* export C API */
304 #define CHANNEL_EXTERN_BEGIN \
305         if (handle != NULL) \
306         { \
307                 ClientChannel *channel = (ClientChannel *)handle;
308
309 #define CHANNEL_EXTERN_END \
310         } \
311         else \
312         { \
313                 SCARD_DEBUG_ERR("Invalid param"); \
314         }
315
316 using namespace smartcard_service_api;
317
318 EXTERN_API int channel_close(channel_h handle, channel_close_cb callback, void *userParam)
319 {
320         int result = -1;
321
322         CHANNEL_EXTERN_BEGIN;
323         result = channel->close((closeCallback)callback, userParam);
324         CHANNEL_EXTERN_END;
325
326         return result;
327 }
328
329 EXTERN_API int channel_transmit(channel_h handle, unsigned char *command, unsigned int length, channel_transmit_cb callback, void *userParam)
330 {
331         int result = -1;
332
333         CHANNEL_EXTERN_BEGIN;
334         ByteArray temp;
335
336         temp.setBuffer(command, length);
337         result = channel->transmit(temp, (transmitCallback)callback, userParam);
338         CHANNEL_EXTERN_END;
339
340         return result;
341 }
342
343 EXTERN_API void channel_close_sync(channel_h handle)
344 {
345 #ifdef CLIENT_IPC_THREAD
346         CHANNEL_EXTERN_BEGIN;
347         channel->closeSync();
348         CHANNEL_EXTERN_END;
349 #endif
350 }
351
352 EXTERN_API int channel_transmit_sync(channel_h handle, unsigned char *command, unsigned int cmd_len, unsigned char **response, unsigned int *resp_len)
353 {
354         int result = -1;
355
356 #ifdef CLIENT_IPC_THREAD
357         if (command == NULL || cmd_len == 0 || response == NULL || resp_len == NULL)
358                 return result;
359
360         CHANNEL_EXTERN_BEGIN;
361         ByteArray temp, resp;
362
363         temp.setBuffer(command, cmd_len);
364         result = channel->transmitSync(temp, resp);
365         if (resp.getLength() > 0)
366         {
367                 *resp_len = resp.getLength();
368                 *response = (unsigned char *)calloc(1, *resp_len);
369                 memcpy(*response, resp.getBuffer(), *resp_len);
370         }
371         CHANNEL_EXTERN_END;
372 #endif
373
374         return result;
375 }
376
377 EXTERN_API bool channel_is_basic_channel(channel_h handle)
378 {
379         bool result = false;
380
381         CHANNEL_EXTERN_BEGIN;
382         result = channel->isBasicChannel();
383         CHANNEL_EXTERN_END;
384
385         return result;
386 }
387
388 EXTERN_API bool channel_is_closed(channel_h handle)
389 {
390         bool result = false;
391
392         CHANNEL_EXTERN_BEGIN;
393         result = channel->isClosed();
394         CHANNEL_EXTERN_END;
395
396         return result;
397 }
398
399 EXTERN_API unsigned int channel_get_select_response_length(channel_h handle)
400 {
401         unsigned int result = 0;
402
403         CHANNEL_EXTERN_BEGIN;
404         result = channel->getSelectResponse().getLength();
405         CHANNEL_EXTERN_END;
406
407         return result;
408 }
409
410 EXTERN_API bool channel_get_select_response(channel_h handle, unsigned char *buffer, unsigned int length)
411 {
412         bool result = false;
413
414         if (buffer == NULL || length == 0)
415         {
416                 return result;
417         }
418
419         CHANNEL_EXTERN_BEGIN;
420         ByteArray response;
421
422         response = channel->getSelectResponse();
423         if (response.getLength() > 0)
424         {
425                 memcpy(buffer, response.getBuffer(), MIN(length, response.getLength()));
426                 result = true;
427         }
428         CHANNEL_EXTERN_END;
429
430         return result;
431 }
432
433 EXTERN_API session_h channel_get_session(channel_h handle)
434 {
435         session_h session = NULL;
436
437         CHANNEL_EXTERN_BEGIN;
438         session = channel->getSession();
439         CHANNEL_EXTERN_END;
440
441         return session;
442 }
443
444 EXTERN_API void channel_destroy_instance(channel_h handle)
445 {
446         CHANNEL_EXTERN_BEGIN;
447         delete channel;
448         CHANNEL_EXTERN_END;
449 }