Fix problems
[platform/core/connectivity/smartcard-service.git] / client / Reader.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 <stdio.h>
19 #include <string.h>
20 #include <unistd.h>
21
22 /* SLP library header */
23
24 /* local header */
25 #include "Debug.h"
26 #include "Reader.h"
27 #include "Session.h"
28 #ifdef USE_GDBUS
29 #include "ClientGDBus.h"
30 #include "smartcard-service-gdbus.h"
31 #else
32 #include "Message.h"
33 #include "ClientIPC.h"
34 #endif
35
36 #ifndef EXTERN_API
37 #define EXTERN_API __attribute__((visibility("default")))
38 #endif
39
40 namespace smartcard_service_api
41 {
42         Reader::Reader(void *context, const char *name, void *handle) :
43                 ReaderHelper(name), context(context), handle(handle)
44         {
45                 _BEGIN();
46
47                 if (context == NULL || name == NULL ||
48                         strlen(name) == 0 || handle == NULL)
49                 {
50                         _ERR("invalid param");
51
52                         return;
53                 }
54 #ifdef USE_GDBUS
55                 /* initialize client */
56                 if (!g_thread_supported())
57                 {
58                         g_thread_init(NULL);
59                 }
60
61                 g_type_init();
62
63                 /* init default context */
64                 GError *error = NULL;
65
66                 proxy = smartcard_service_reader_proxy_new_for_bus_sync(
67                         G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
68                         "org.tizen.SmartcardService",
69                         "/org/tizen/SmartcardService/Reader",
70                         NULL, &error);
71                 if (proxy == NULL)
72                 {
73                         _ERR("Can not create proxy : %s", error->message);
74                         g_error_free(error);
75                         return;
76                 }
77 #endif
78                 present = true;
79
80                 _END();
81         }
82
83         Reader::~Reader()
84         {
85                 size_t i;
86
87                 closeSessions();
88
89                 for (i = 0; i < sessions.size(); i++)
90                 {
91                         delete (Session *)sessions[i];
92                 }
93
94                 sessions.clear();
95         }
96
97         void Reader::closeSessions()
98                 throw(ErrorIO &, ErrorIllegalState &)
99         {
100                 size_t i;
101
102                 for (i = 0; i < sessions.size(); i++)
103                 {
104                         sessions[i]->closeSync();
105                 }
106         }
107
108         SessionHelper *Reader::openSessionSync()
109                 throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &,
110                         ErrorIllegalParameter &, ErrorSecurity &)
111         {
112                 Session *session = NULL;
113
114                 if (isSecureElementPresent() == true)
115                 {
116 #ifdef USE_GDBUS
117                         gint result;
118                         GError *error = NULL;
119                         guint session_id;
120
121                         if (smartcard_service_reader_call_open_session_sync(
122                                 (SmartcardServiceReader *)proxy,
123                                 ClientGDBus::getCookie(),
124                                 GPOINTER_TO_UINT(context),
125                                 GPOINTER_TO_UINT(handle),
126                                 &result, &session_id, NULL, &error) == true) {
127                                 if (result == SCARD_ERROR_OK) {
128                                         /* create new instance of channel */
129                                         session = new Session(context, this,
130                                                 GUINT_TO_POINTER(session_id));
131                                         if (session != NULL) {
132                                                 sessions.push_back(session);
133                                         } else {
134                                                 _ERR("Session creating instance failed");
135
136                                                 THROW_ERROR(SCARD_ERROR_OUT_OF_MEMORY);
137                                         }
138                                 } else {
139                                         _ERR("smartcard_service_reader_call_open_session_sync failed, [%d]", result);
140
141                                         THROW_ERROR(result);
142                                 }
143                         } else {
144                                 _ERR("smartcard_service_reader_call_open_session_sync failed, [%s]", error->message);
145                                 g_error_free(error);
146
147                                 THROW_ERROR(SCARD_ERROR_IPC_FAILED);
148                         }
149 #else
150                         Message msg;
151                         int rv;
152
153                         openedSession = NULL;
154 #ifdef CLIENT_IPC_THREAD
155                         /* request channel handle from server */
156                         msg.message = Message::MSG_REQUEST_OPEN_SESSION;
157                         msg.param1 = (unsigned long)handle;
158                         msg.error = (unsigned long)context; /* using error to context */
159                         msg.caller = (void *)this;
160                         msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
161
162                         syncLock();
163                         if (ClientIPC::getInstance().sendMessage(msg) == true)
164                         {
165                                 rv = waitTimedCondition(0);
166                                 if (rv != 0)
167                                 {
168                                         _ERR("time over");
169                                         this->error = SCARD_ERROR_OPERATION_TIMEOUT;
170                                 }
171
172                                 session = openedSession;
173                         }
174                         else
175                         {
176                                 _ERR("sendMessage failed");
177                                 this->error = SCARD_ERROR_IPC_FAILED;
178                         }
179                         syncUnlock();
180
181                         if (this->error != SCARD_ERROR_OK)
182                         {
183                                 ThrowError::throwError(this->error);
184                         }
185 #endif
186 #endif
187                 }
188                 else
189                 {
190                         _ERR("unavailable reader");
191                         throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
192                 }
193
194                 return session;
195         }
196
197 #ifdef USE_GDBUS
198         void Reader::reader_open_session_cb(GObject *source_object,
199                 GAsyncResult *res, gpointer user_data)
200         {
201                 CallbackParam *param = (CallbackParam *)user_data;
202                 Reader *reader;
203                 openSessionCallback callback;
204                 Session *session = NULL;
205                 gint result;
206                 guint handle;
207                 GError *error = NULL;
208
209                 _INFO("MSG_REQUEST_OPEN_SESSION");
210
211                 if (param == NULL) {
212                         _ERR("null parameter!!!");
213                         return;
214                 }
215
216                 reader = (Reader *)param->instance;
217                 callback = (openSessionCallback)param->callback;
218
219                 if (smartcard_service_reader_call_open_session_finish(
220                         SMARTCARD_SERVICE_READER(source_object),
221                         &result, &handle, res, &error) == true) {
222                         if (result == SCARD_ERROR_OK) {
223                                 /* create new instance of channel */
224                                 session = new Session(reader->context, reader,
225                                         GUINT_TO_POINTER(handle));
226                                 if (session != NULL) {
227                                         reader->sessions.push_back(session);
228                                 } else {
229                                         _ERR("Session creating instance failed");
230
231                                         result = SCARD_ERROR_OUT_OF_MEMORY;
232                                 }
233                         } else {
234                                 _ERR("smartcard_service_reader_call_open_session failed, [%d]", result);
235                         }
236                 } else {
237                         _ERR("smartcard_service_reader_call_open_session failed, [%s]", error->message);
238                         g_error_free(error);
239
240                         result = SCARD_ERROR_IPC_FAILED;
241                 }
242
243                 if (callback != NULL) {
244                         callback(session, result, param->user_param);
245                 }
246
247                 delete param;
248         }
249 #endif
250         int Reader::openSession(openSessionCallback callback, void *userData)
251         {
252                 int result;
253
254                 _BEGIN();
255
256                 if (isSecureElementPresent() == true)
257                 {
258 #ifdef USE_GDBUS
259                         CallbackParam *param = new CallbackParam();
260
261                         param->instance = this;
262                         param->callback = (void *)callback;
263                         param->user_param = userData;
264
265                         smartcard_service_reader_call_open_session(
266                                 (SmartcardServiceReader *)proxy,
267                                 ClientGDBus::getCookie(),
268                                 GPOINTER_TO_UINT(context),
269                                 GPOINTER_TO_UINT(handle),
270                                 NULL, &Reader::reader_open_session_cb, param);
271
272                         result = SCARD_ERROR_OK;
273 #else
274                         Message msg;
275
276                         /* request channel handle from server */
277                         msg.message = Message::MSG_REQUEST_OPEN_SESSION;
278                         msg.param1 = (unsigned long)handle;
279                         msg.error = (unsigned long)context; /* using error to context */
280                         msg.caller = (void *)this;
281                         msg.callback = (void *)callback;
282                         msg.userParam = userData;
283
284                         if (ClientIPC::getInstance().sendMessage(msg) == true)
285                         {
286                                 result = SCARD_ERROR_OK;
287                         }
288                         else
289                         {
290                                 _ERR("sendMessage failed");
291                                 result = SCARD_ERROR_IPC_FAILED;
292                         }
293 #endif
294                 }
295                 else
296                 {
297                         _ERR("unavailable reader");
298                         result = SCARD_ERROR_ILLEGAL_STATE;
299                 }
300
301                 _END();
302
303                 return result;
304         }
305
306 #ifndef USE_GDBUS
307         bool Reader::dispatcherCallback(void *message)
308         {
309                 Message *msg = (Message *)message;
310                 Reader *reader;
311                 bool result = false;
312
313                 _BEGIN();
314
315                 if (msg == NULL)
316                 {
317                         _ERR("message is null");
318                         return result;
319                 }
320
321                 reader = (Reader *)msg->caller;
322
323                 switch (msg->message)
324                 {
325                 case Message::MSG_REQUEST_OPEN_SESSION :
326                         {
327                                 Session *session = NULL;
328
329                                 _INFO("MSG_REQUEST_OPEN_SESSION");
330
331                                 if (msg->param1 != 0)
332                                 {
333                                         /* create new instance of channel */
334                                         session = new Session(reader->context, reader, (void *)msg->param1);
335                                         if (session == NULL)
336                                         {
337                                                 _ERR("Session creating instance failed");
338
339                                                 return session;
340                                         }
341
342                                         reader->sessions.push_back(session);
343                                 }
344
345                                 if (msg->isSynchronousCall() == true) /* synchronized call */
346                                 {
347                                         /* sync call */
348                                         reader->syncLock();
349
350                                         /* copy result */
351                                         reader->error = msg->error;
352                                         reader->openedSession = session;
353                                         reader->signalCondition();
354
355                                         reader->syncUnlock();
356                                 }
357                                 else if (msg->callback != NULL)
358                                 {
359                                         openSessionCallback cb = (openSessionCallback)msg->callback;
360
361                                         /* async call */
362                                         cb(session, msg->error, msg->userParam);
363                                 }
364                         }
365                         break;
366
367                 default:
368                         _DBG("unknown [%s]", msg->toString().c_str());
369                         break;
370                 }
371
372                 delete msg;
373
374                 _END();
375
376                 return result;
377         }
378 #endif
379 } /* namespace smartcard_service_api */
380
381 /* export C API */
382 #define READER_EXTERN_BEGIN \
383         if (handle != NULL) \
384         { \
385                 Reader *reader = (Reader *)handle;
386
387 #define READER_EXTERN_END \
388         } \
389         else \
390         { \
391                 _ERR("Invalid param"); \
392         }
393
394 using namespace smartcard_service_api;
395
396 EXTERN_API const char *reader_get_name(reader_h handle)
397 {
398         const char *name = NULL;
399
400         READER_EXTERN_BEGIN;
401         name = reader->getName();
402         READER_EXTERN_END;
403
404         return name;
405 }
406
407 EXTERN_API se_service_h reader_get_se_service(reader_h handle)
408 {
409         se_service_h service = NULL;
410
411         READER_EXTERN_BEGIN;
412         service = (se_service_h)reader->getSEService();
413         READER_EXTERN_END;
414
415         return service;
416 }
417
418 EXTERN_API bool reader_is_secure_element_present(reader_h handle)
419 {
420         bool result = false;
421
422         READER_EXTERN_BEGIN;
423         result = reader->isSecureElementPresent();
424         READER_EXTERN_END;
425
426         return result;
427 }
428
429 EXTERN_API int reader_open_session(reader_h handle, reader_open_session_cb callback, void *userData)
430 {
431         int result = -1;
432
433         READER_EXTERN_BEGIN;
434         result = reader->openSession((openSessionCallback)callback, userData);
435         READER_EXTERN_END;
436
437         return result;
438 }
439
440 EXTERN_API session_h reader_open_session_sync(reader_h handle)
441 {
442         session_h result = NULL;
443
444 #ifdef CLIENT_IPC_THREAD
445         READER_EXTERN_BEGIN;
446         result = (session_h)reader->openSessionSync();
447         READER_EXTERN_END;
448 #endif
449
450         return result;
451 }
452
453 EXTERN_API void reader_close_sessions(reader_h handle)
454 {
455         READER_EXTERN_BEGIN;
456         reader->closeSessions();
457         READER_EXTERN_END;
458 }
459
460 EXTERN_API void reader_destroy_instance(reader_h handle)
461 {
462 }