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