refines receiver and receiver udp module
[apps/native/gear-racing-car.git] / src / receiver_udp.c
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Flora License, Version 1.1 (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 <stdlib.h>
18 #include <glib.h>
19 #include <gio/gio.h>
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
24 #include <errno.h>
25
26 #include "log.h"
27 #include "receiver_internal.h"
28 #include "message.h"
29
30 #define RECEIVER_UDP_PORT 57984
31 #define RECEIVER_UDP_WAIT_TIMEOUT 3
32
33 typedef enum __receiver_udp_state_e {
34         RECEIVER_UDP_STATE_NONE,
35         RECEIVER_UDP_STATE_INIT,
36         RECEIVER_UDP_STATE_READY,
37         RECEIVER_UDP_STATE_CONNECTED,
38 } receiver_udp_state_e;
39
40 typedef struct __receiver_udp_h {
41         guint io_watch_id;
42         guint wait_timer_id;
43         receiver_udp_state_e state;
44         GSocket *socket;
45 } receiver_udp_h;
46
47 // static receiver_udp_h *udp_handle = NULL;
48
49 static gchar *__socket_address_to_string(GSocketAddress *address)
50 {
51         GInetAddress *inet_address = NULL;
52         char *str, *res;
53         int port;
54
55         inet_address =
56                 g_inet_socket_address_get_address(G_INET_SOCKET_ADDRESS(address));
57
58         str = g_inet_address_to_string(inet_address);
59         port = g_inet_socket_address_get_port(G_INET_SOCKET_ADDRESS(address));
60
61         res = g_strdup_printf("%s:%d", str, port);
62         g_free(str);
63
64         return res;
65 }
66
67 static receiver_state_e ___state_convert(receiver_udp_state_e state)
68 {
69         receiver_state_e r_state = RECEIVER_STATE_NONE;
70
71         switch (state) {
72         case RECEIVER_UDP_STATE_NONE:
73                 r_state = RECEIVER_STATE_NONE;
74                 break;
75         case RECEIVER_UDP_STATE_INIT:
76                 r_state = RECEIVER_STATE_INIT;
77                 break;
78         case RECEIVER_UDP_STATE_READY:
79                 r_state = RECEIVER_STATE_READY;
80                 break;
81         case RECEIVER_UDP_STATE_CONNECTED:
82                 r_state = RECEIVER_STATE_CONNECTED;
83                 break;
84         }
85         return r_state;
86 }
87
88 static void __receiver_udp_state_set(
89         receiver_module_h *handle, receiver_udp_state_e state)
90 {
91         receiver_udp_h *udp_handle = NULL;
92
93         ret_if(!handle);
94
95         udp_handle = receiver_get_module_data(handle);
96         ret_if(!udp_handle);
97
98         udp_handle->state = state;
99
100         receiver_module_state_changed(handle, ___state_convert(state));
101
102         return;
103 }
104
105 /* Uses system call, because glib socket API doesn't support unset connect
106  * Please carefully use this function, and after use this function,
107  * DO NOT use g_socket_is_connected().
108  */
109 static int __receiver_udp_unset_connection(receiver_module_h *handle)
110 {
111         receiver_udp_h *udp_handle = NULL;
112         struct sockaddr addr;
113         int s_fd = 0;
114
115         retv_if(!handle, -1);
116
117         udp_handle = receiver_get_module_data(handle);
118
119         retvm_if(!udp_handle, -1, "handle is not created");
120         retvm_if(!udp_handle->socket, -1, "socket is not created");
121
122         s_fd = g_socket_get_fd(udp_handle->socket);
123         bzero((char *)&addr, sizeof(addr));
124         addr.sa_family = AF_UNSPEC;
125
126         if (connect(s_fd, &addr, sizeof(addr))) {
127                 _E("failed to unset connect - %s\n", strerror(errno));
128                 /* re-create socket or not ??? */
129                 return -1;
130         }
131
132         __receiver_udp_state_set(handle, RECEIVER_UDP_STATE_READY);
133
134         return 0;
135 }
136
137 static int __receiver_udp_set_connection(
138         receiver_module_h *handle, GSocketAddress *sender_a)
139 {
140         GError *error = NULL;
141         receiver_udp_h *udp_handle = NULL;
142
143         retv_if(!handle, -1);
144         retv_if(!sender_a, -1);
145
146         udp_handle = receiver_get_module_data(handle);
147
148         retvm_if(!udp_handle, -1, "handle is not created");
149         retvm_if(!udp_handle->socket, -1, "socket is not created");
150
151         if (udp_handle->state != RECEIVER_UDP_STATE_READY) {
152                 _E("check state %d", udp_handle->state);
153                 return -1;
154         }
155
156         /* use connect() to specify sender address and reject other sender */
157         if (!g_socket_connect(udp_handle->socket, sender_a, NULL, &error)) {
158                 _E("failed to connect - %s", error->message);
159                 g_error_free(error);
160                 return -1;
161         }
162
163         __receiver_udp_state_set(handle, RECEIVER_UDP_STATE_CONNECTED);
164
165         return 0;
166 }
167
168 static gboolean __wait_time_out(gpointer user_data)
169 {
170         receiver_module_h *handle = user_data;
171
172         retv_if(!handle, FALSE);
173
174         __receiver_udp_unset_connection(handle);
175
176         return FALSE;
177 }
178
179 static void __receiver_udp_update_wait_timer(receiver_module_h *handle)
180 {
181         receiver_udp_h *udp_handle = NULL;
182
183         ret_if(!handle);
184
185         udp_handle = receiver_get_module_data(handle);
186
187         if (udp_handle) {
188                 if (udp_handle->wait_timer_id) {
189                         g_source_remove(udp_handle->wait_timer_id);
190                         udp_handle->wait_timer_id = 0;
191                 }
192                 udp_handle->wait_timer_id =
193                         g_timeout_add_seconds(RECEIVER_UDP_WAIT_TIMEOUT,
194                                 (GSourceFunc)__wait_time_out, handle);
195         }
196
197         return;
198 }
199
200 static gboolean __read_socket(GIOChannel *channel,
201                 GIOCondition condition,
202                 gpointer data)
203 {
204         receiver_module_h *handle = data;
205         receiver_udp_h *udp_handle = NULL;
206         GError *error = NULL;
207         message_s *r_msg = NULL;
208         gssize size = 0;
209
210         retv_if(!handle, TRUE);
211
212         udp_handle = receiver_get_module_data(handle);
213
214         retv_if(!udp_handle, TRUE);
215         retv_if(!udp_handle->socket, TRUE);
216
217         if (udp_handle->state < RECEIVER_UDP_STATE_READY) {
218                 _E("receiver udp is not ready yet");
219                 return TRUE;
220         }
221
222         r_msg = malloc(sizeof(message_s));
223         retv_if(!r_msg, TRUE);
224
225         if (udp_handle->state == RECEIVER_UDP_STATE_READY) {
226                 char *s_addr = NULL;
227                 GSocketAddress *address = NULL;
228
229                 size = g_socket_receive_from(udp_handle->socket, &address,
230                         (gchar *)r_msg, sizeof(message_s), NULL, &error);
231
232                 if (size < 0) {
233                         _D("Error receiving from socket: %s", error->message);
234                         g_error_free(error);
235                         free(r_msg);
236                         r_msg = NULL;
237                 }
238
239                 s_addr = __socket_address_to_string(address);
240                 _D("received first data from [%s]", s_addr);
241
242                 message_push_to_inqueue(r_msg);
243
244                 if (!__receiver_udp_set_connection(handle, address))
245                         __receiver_udp_update_wait_timer(handle);
246                 else
247                         _E("failed to set connection with [%s]", s_addr);
248
249                 free(s_addr);
250                 g_object_unref(address);
251         } else { /* state is RECEIVER_UDP_STATE_CONNECTED */
252                 size = g_socket_receive(udp_handle->socket,
253                         (gchar *)r_msg, sizeof(message_s), NULL, &error);
254
255                 if (size < 0) {
256                         _D("Error receiving from socket: %s", error->message);
257                         g_error_free(error);
258                         free(r_msg);
259                         r_msg = NULL;
260                 }
261                 _D("received data");
262                 message_push_to_inqueue(r_msg);
263
264                 __receiver_udp_update_wait_timer(handle);
265         }
266
267         /* TODO : what should I do after receiveing some data? */
268
269         return TRUE;
270 }
271
272 static int _receiver_udp_start(void *data)
273 {
274         receiver_module_h *handle = data;
275         receiver_udp_h *udp_handle = NULL;
276         int socket_fd = 0;
277         GIOChannel *ch = NULL;
278
279         retv_if(!handle, -1);
280
281         udp_handle = receiver_get_module_data(handle);
282
283         retv_if(!udp_handle, -1);
284         retv_if(!udp_handle->socket, -1);
285
286         if (udp_handle->state != RECEIVER_UDP_STATE_INIT) {
287                 if (udp_handle->state == RECEIVER_UDP_STATE_READY) {
288                         _E("receiver udp is already started");
289                         return 0;
290                 } else {
291                         _E("receiver udp is invalid state [%d]", udp_handle->state);
292                         return -1;
293                 }
294         }
295
296         socket_fd = g_socket_get_fd(udp_handle->socket);
297         ch = g_io_channel_unix_new(socket_fd);
298         udp_handle->io_watch_id =
299                 g_io_add_watch(ch, G_IO_IN, __read_socket, handle);
300         g_io_channel_unref(ch);
301         ch = NULL;
302
303         __receiver_udp_state_set(handle, RECEIVER_UDP_STATE_READY);
304
305         return 0;
306 }
307
308 static int _receiver_udp_stop(void *data)
309 {
310         receiver_module_h *handle = data;
311         receiver_udp_h *udp_handle = NULL;
312
313         retv_if(!handle, -1);
314
315         udp_handle = receiver_get_module_data(handle);
316
317         retv_if(!udp_handle, -1);
318         retv_if(!udp_handle->socket, -1);
319
320         if (udp_handle->state < RECEIVER_UDP_STATE_READY) {
321                 _E("receiver udp is invalid state [%d]", udp_handle->state);
322                 return -1;
323         }
324
325         if (udp_handle->wait_timer_id) {
326                 g_source_remove(udp_handle->wait_timer_id);
327                 udp_handle->wait_timer_id = 0;
328         }
329
330         if (udp_handle->io_watch_id) {
331                 g_source_remove(udp_handle->io_watch_id);
332                 udp_handle->io_watch_id = 0;
333         }
334
335         __receiver_udp_state_set(handle, RECEIVER_UDP_STATE_INIT);
336
337         return 0;
338 }
339
340 static int _receiver_udp_init(void *data)
341 {
342         receiver_module_h *handle = data;
343         receiver_udp_h *udp_handle = NULL;
344         GError *error = NULL;
345         GSocketAddress *address = NULL;
346         GInetAddress *i_addr = NULL;
347
348         retv_if(!handle, -1);
349
350         udp_handle = receiver_get_module_data(handle);
351         retv_if(!udp_handle, -1);
352
353         if (udp_handle->state != RECEIVER_UDP_STATE_NONE) {
354                 _E("receiver udp is invalid state [%d]", udp_handle->state);
355                 return -1;
356         }
357
358         udp_handle->socket = g_socket_new(G_SOCKET_FAMILY_IPV4,
359                 G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &error);
360
361         if (udp_handle->socket == NULL) {
362                 _E("failed to get new socket - %s", error->message);
363                 goto ERROR;
364         }
365
366         /* set non-blocking mode */
367         g_socket_set_blocking(udp_handle->socket, FALSE);
368
369         i_addr = g_inet_address_new_any(G_SOCKET_FAMILY_IPV4);
370         if (!i_addr) {
371                 _E("failed to get inet any address");
372                 goto ERROR;
373         }
374         address = g_inet_socket_address_new(i_addr, RECEIVER_UDP_PORT);
375         g_object_unref(i_addr);
376         i_addr = NULL;
377
378         if (!address) {
379                 _E("failed to get socket address");
380                 goto ERROR;
381         }
382
383         if (!g_socket_bind(udp_handle->socket, address, TRUE, &error)) {
384                 _E("Can't bind socket: %s\n", error->message);
385                 goto ERROR;
386         }
387         g_object_unref(address);
388         address = NULL;
389
390         __receiver_udp_state_set(handle, RECEIVER_UDP_STATE_INIT);
391
392         return 0;
393
394 ERROR:
395         if (error)
396                 g_error_free(error);
397
398         if (address)
399                 g_object_unref(address);
400
401         if (i_addr)
402                 g_object_unref(i_addr);
403
404         return -1;
405 }
406
407 static int _receiver_udp_fini(void *data)
408 {
409         receiver_module_h *handle = data;
410         receiver_udp_h *udp_handle = NULL;
411
412         retv_if(!handle, -1);
413
414         udp_handle = receiver_get_module_data(handle);
415         retv_if(!udp_handle, -1);
416
417         if (udp_handle) {
418                 if (udp_handle->io_watch_id)
419                         g_source_remove(udp_handle->io_watch_id);
420
421                 if (udp_handle->wait_timer_id)
422                         g_source_remove(udp_handle->wait_timer_id);
423
424                 if (udp_handle->socket) {
425                         g_socket_close(udp_handle->socket, NULL);
426                         g_object_unref(udp_handle->socket);
427                 }
428
429                 __receiver_udp_state_set(handle, RECEIVER_UDP_STATE_NONE);
430
431                 free(udp_handle);
432                 udp_handle = NULL;
433         }
434
435         return 0;
436 }
437
438 static receiver_state_e _receiver_udp_get_state(void *data)
439 {
440         receiver_module_h *handle = data;
441         receiver_udp_h *udp_handle = NULL;
442
443         retv_if(!handle, RECEIVER_STATE_NONE);
444
445         udp_handle = receiver_get_module_data(handle);
446         retv_if(!udp_handle, RECEIVER_STATE_NONE);
447
448         return ___state_convert(udp_handle->state);
449 }
450
451 /* Keep it here??? or move to new file??? */
452 int receiver_udp_module_register(receiver_module_h *handle)
453 {
454         receiver_udp_h *udp_handle = NULL;
455
456         retv_if(!handle, -1);
457
458         udp_handle = malloc(sizeof(receiver_udp_h));
459         if (!udp_handle) {
460                 _E("failed to alloc receiver udp handle");
461                 return -1;
462         }
463
464         udp_handle->state = RECEIVER_UDP_STATE_NONE;
465         udp_handle->io_watch_id = 0;
466         udp_handle->wait_timer_id = 0;
467         udp_handle->socket = NULL;
468
469         receiver_set_module_data(handle, udp_handle);
470         receiver_set_module_init_function(handle, _receiver_udp_init);
471         receiver_set_module_fini_function(handle, _receiver_udp_fini);
472         receiver_set_module_start_function(handle, _receiver_udp_start);
473         receiver_set_module_stop_function(handle, _receiver_udp_stop);
474         receiver_set_module_get_state_function(handle, _receiver_udp_get_state);
475
476         return 0;
477 }