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