Fix for wrong statement
[platform/core/api/nfc.git] / src / net_nfc_client_hce_ipc.c
1 /*
2  * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Flora License, Version 1.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://floralicense.org/license/
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 #include <sys/socket.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
20 #include <sys/un.h>
21 #include <sys/types.h>
22 #include <fcntl.h>
23 #include <sys/epoll.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <pthread.h>
28 #include <errno.h>
29 #include <sys/time.h>
30 #include <stdarg.h>
31 #include <signal.h>
32 #include <glib-object.h>
33
34 /* LCOV_EXCL_START */
35
36 #include "net_nfc_typedef_internal.h"
37 #include "net_nfc_debug_internal.h"
38 #include "net_nfc_util_defines.h"
39 #include "net_nfc_util_internal.h"
40 #include "net_nfc_util_hce.h"
41 #include "net_nfc_client_hce.h"
42 #include "net_nfc_client_hce_ipc.h"
43
44 /* static variable */
45 static pthread_mutex_t g_client_ipc_mutex = PTHREAD_MUTEX_INITIALIZER;
46 static pthread_mutex_t cb_lock = PTHREAD_MUTEX_INITIALIZER;
47
48 static int hce_client_socket = -1;
49 static GIOChannel *hce_client_channel = NULL;
50 static guint hce_client_src_id = 0;
51
52 /* static function */
53 static void __set_non_block_socket(int socket)
54 {
55         int flags;
56
57         flags = fcntl(socket, F_GETFL);
58         flags |= O_NONBLOCK;
59
60         if (fcntl(socket, F_SETFL, flags) < 0)
61                 DEBUG_ERR_MSG("fcntl, executing nonblock error");
62 }
63
64 static bool __receive_data_from_server(int socket, data_s *data)
65 {
66         bool result;
67         ssize_t ret;
68         uint32_t len;
69
70         /* first, receive length */
71         ret = recv(socket, (void *)&len, sizeof(len), 0);
72         if (ret != sizeof(len)) {
73                 DEBUG_ERR_MSG("recv failed, socket [%d], result [%d]", socket, ret);
74
75                 return false;
76         }
77
78         if (len > 1024) {
79                 DEBUG_ERR_MSG("too large message, socket [%d], len [%d]", socket, len);
80
81                 return false;
82         }
83
84         result = net_nfc_util_init_data(data, len);
85         if (result == true) {
86                 ssize_t offset = 0;
87
88                 /* second, receive buffer */
89                 do {
90                         ret = recv(socket, data->buffer + offset, data->length - offset, 0);
91                         if (ret == -1)
92                                 break;
93
94                         offset += ret;
95                 } while (offset < len);
96
97                 if (offset != len) {
98                         DEBUG_ERR_MSG("recv failed, socket [%d], offset [%d], len [%d]", socket, offset, len);
99
100                         net_nfc_util_clear_data(data);
101
102                         result = false;
103                 } else {
104                         DEBUG_CLIENT_MSG("recv success, length [%d]", offset);
105                 }
106         } else {
107                 DEBUG_ERR_MSG("net_nfc_util_init_data failed");
108         }
109
110         return result;
111 }
112
113 static bool __process_server_message()
114 {
115         bool result;
116         data_s data;
117
118         if (__receive_data_from_server(hce_client_socket, &data) == true) {
119                 net_nfc_hce_data_t *header;
120                 data_s temp;
121
122                 header = (net_nfc_hce_data_t *)data.buffer;
123
124                 temp.buffer = header->data;
125                 temp.length = data.length - sizeof(net_nfc_hce_data_t);
126
127                 net_nfc_client_hce_process_received_event(header->type,
128                         (net_nfc_target_handle_h)GUINT_TO_POINTER(header->handle), (data_h)&temp);
129
130                 result = true;
131         } else {
132                 DEBUG_ERR_MSG("__receive_data_from_client failed");
133
134                 result = false;
135         }
136
137         return result;
138 }
139
140 static bool __send_data_to_server(int socket, data_s *data)
141 {
142         ssize_t ret;
143
144         ret = send(socket, data->buffer, data->length, MSG_NOSIGNAL);
145         if (ret == -1) {
146                 DEBUG_ERR_MSG("send failed, socket [%d]", socket);
147
148                 return false;
149         }
150
151         return true;
152 }
153
154 bool net_nfc_server_hce_ipc_send_to_server(int type,
155         net_nfc_target_handle_s *handle, data_s *data)
156 {
157         bool ret;
158         data_s temp;
159         uint32_t len = sizeof(net_nfc_hce_data_t);
160
161         if (data != NULL && data->length > 0)
162                 len += data->length;
163
164         ret = net_nfc_util_init_data(&temp, len + sizeof(len));
165         if (ret == true) {
166                 net_nfc_hce_data_t *header;
167
168                 *(uint32_t *)(temp.buffer) = len;
169                 header = (net_nfc_hce_data_t *)(temp.buffer + sizeof(len));
170
171                 header->type = type;
172                 header->handle = GPOINTER_TO_UINT(handle);
173
174                 if (data != NULL && data->length > 0)
175                         memcpy(header->data, data->buffer, data->length);
176
177                 ret = __send_data_to_server(hce_client_socket, &temp);
178
179                 net_nfc_util_clear_data(&temp);
180         } else {
181                 DEBUG_ERR_MSG("net_nfc_util_init_data failed");
182         }
183
184         return ret;
185 }
186
187 /******************************************************************************/
188
189 static inline void net_nfc_client_ipc_lock()
190 {
191         pthread_mutex_lock(&g_client_ipc_mutex);
192 }
193
194 static inline void net_nfc_client_ipc_unlock()
195 {
196         pthread_mutex_unlock(&g_client_ipc_mutex);
197 }
198
199 bool net_nfc_client_hce_ipc_is_initialized()
200 {
201         return (hce_client_socket != -1 && hce_client_channel != NULL);
202 }
203
204 static net_nfc_error_e _finalize_client_socket()
205 {
206         net_nfc_error_e result = NET_NFC_OK;
207
208         net_nfc_client_ipc_lock();
209
210         if (hce_client_src_id > 0) {
211                 g_source_remove(hce_client_src_id);
212                 hce_client_src_id = 0;
213         }
214
215         if (hce_client_channel != NULL) {
216                 g_io_channel_unref(hce_client_channel);
217                 hce_client_channel = NULL;
218         }
219
220         if (hce_client_socket != -1) {
221                 shutdown(hce_client_socket, SHUT_WR);
222                 close(hce_client_socket);
223                 hce_client_socket = -1;
224
225                 INFO_MSG("client socket closed");
226         }
227
228         net_nfc_client_ipc_unlock();
229
230         return result;
231 }
232
233 static gboolean __on_io_event_cb(GIOChannel *channel, GIOCondition condition,
234         gpointer data)
235 {
236         if ((G_IO_ERR & condition) || (G_IO_HUP & condition)) {
237                 DEBUG_CLIENT_MSG("client socket is closed");
238
239                 /* clean up client context */
240                 net_nfc_client_hce_ipc_deinit();
241
242                 return FALSE;
243         } else if (G_IO_NVAL & condition) {
244                 DEBUG_CLIENT_MSG("INVALID socket");
245
246                 return FALSE;
247         } else if (G_IO_IN & condition) {
248                 if (channel != hce_client_channel) {
249                         DEBUG_CLIENT_MSG("unknown channel");
250
251                         return FALSE;
252                 }
253
254                 DEBUG_CLIENT_MSG("message from server to client socket");
255
256                 if (__process_server_message() == false) {
257                         DEBUG_ERR_MSG("__process_server_message failed");
258
259                         net_nfc_client_hce_ipc_deinit();
260
261                         return FALSE;
262                 }
263         } else {
264                 DEBUG_CLIENT_MSG("IO ERROR. socket is closed ");
265
266                 /* clean up client context */
267                 net_nfc_client_hce_ipc_deinit();
268
269                 return FALSE;
270         }
271
272         return TRUE;
273 }
274
275 net_nfc_error_e net_nfc_client_hce_ipc_init()
276 {
277         net_nfc_error_e result = NET_NFC_OK;
278         struct sockaddr_un saddrun_rv;
279         socklen_t len_saddr = 0;
280         pthread_mutexattr_t attr;
281
282         if (net_nfc_client_hce_ipc_is_initialized() == true) {
283                 DEBUG_CLIENT_MSG("client is already initialized");
284
285                 return NET_NFC_ALREADY_INITIALIZED;
286         }
287
288         pthread_mutexattr_init(&attr);
289         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
290         pthread_mutex_init(&cb_lock, &attr);
291
292         memset(&saddrun_rv, 0, sizeof(struct sockaddr_un));
293
294         net_nfc_client_ipc_lock();
295
296         hce_client_socket = socket(AF_UNIX, SOCK_STREAM, 0);
297         if (hce_client_socket == -1) {
298                 DEBUG_ERR_MSG("get socket is failed");
299
300                 result = NET_NFC_IPC_FAIL;
301                 goto ERROR;
302         }
303
304         __set_non_block_socket(hce_client_socket);
305
306         saddrun_rv.sun_family = AF_UNIX;
307         strncpy(saddrun_rv.sun_path, NET_NFC_HCE_SERVER_DOMAIN, sizeof(saddrun_rv.sun_path) - 1);
308
309         len_saddr = sizeof(saddrun_rv.sun_family) + strlen(NET_NFC_HCE_SERVER_DOMAIN);
310
311         if (connect(hce_client_socket, (struct sockaddr *)&saddrun_rv, len_saddr) < 0) {
312                 DEBUG_ERR_MSG("error is occured");
313                 result = NET_NFC_IPC_FAIL;
314
315                 goto ERROR;
316         }
317
318         GIOCondition condition = (GIOCondition)(G_IO_ERR | G_IO_HUP | G_IO_IN);
319
320         hce_client_channel = g_io_channel_unix_new(hce_client_socket);
321         if (hce_client_channel == NULL) {
322                 DEBUG_ERR_MSG(" g_io_channel_unix_new is failed ");
323                 result = NET_NFC_IPC_FAIL;
324
325                 goto ERROR;
326         }
327
328         hce_client_src_id = g_io_add_watch(hce_client_channel, condition,
329                 __on_io_event_cb, NULL);
330         if (hce_client_src_id < 1) {
331                 DEBUG_ERR_MSG(" g_io_add_watch is failed ");
332                 result = NET_NFC_IPC_FAIL;
333
334                 goto ERROR;
335         }
336
337         DEBUG_CLIENT_MSG("client socket is ready");
338
339         net_nfc_client_ipc_unlock();
340
341         return NET_NFC_OK;
342
343 ERROR:
344         DEBUG_ERR_MSG("error while initializing client ipc");
345
346         net_nfc_client_ipc_unlock();
347
348         _finalize_client_socket();
349
350         return result;
351 }
352
353 void net_nfc_client_hce_ipc_deinit()
354 {
355         if (net_nfc_client_hce_ipc_is_initialized() == true)
356                 _finalize_client_socket();
357 }
358
359 /* LCOV_EXCL_STOP */
360