fixed typos
[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
29 #define RECEIVER_UDP_PORT 57984
30 #define RECEIVER_UDP_WAIT_TIMEOUT 3
31
32 typedef enum __receiver_udp_state_e {
33         RECEIVER_UDP_STATE_NONE,
34         RECEIVER_UDP_STATE_READY,
35         RECEIVER_UDP_STATE_CONNECTED,
36 } receiver_udp_state_e;
37
38 typedef struct __receiver_udp_h {
39         guint io_watch_id;
40         guint wait_timer_id;
41         receiver_udp_state_e state;
42         GSocket *socket;
43 } receiver_udp_h;
44
45 static receiver_udp_h *udp_handle = NULL;
46
47 static gchar *__socket_address_to_string(GSocketAddress *address)
48 {
49         GInetAddress *inet_address = NULL;
50         char *str, *res;
51         int port;
52
53         inet_address =
54                 g_inet_socket_address_get_address(G_INET_SOCKET_ADDRESS(address));
55
56         str = g_inet_address_to_string(inet_address);
57         port = g_inet_socket_address_get_port(G_INET_SOCKET_ADDRESS(address));
58
59         res = g_strdup_printf("%s:%d", str, port);
60         g_free(str);
61
62         return res;
63 }
64
65 static int __receiver_udp_init(void)
66 {
67         if (udp_handle) {
68                 _E("receiver udp is already initialized");
69                 return -1;
70         }
71
72         udp_handle = malloc(sizeof(receiver_udp_h));
73         if (!udp_handle) {
74                 _E("failed to alloc receiver udp handle");
75                 return -1;
76         }
77
78         udp_handle->state = RECEIVER_UDP_STATE_NONE;
79         udp_handle->io_watch_id = 0;
80         udp_handle->wait_timer_id = 0;
81         udp_handle->socket = NULL;
82
83         return 0;
84 }
85
86 static int __receiver_udp_fini(void)
87 {
88         if (udp_handle) {
89                 if (udp_handle->io_watch_id)
90                         g_source_remove(udp_handle->io_watch_id);
91
92                 if (udp_handle->wait_timer_id)
93                         g_source_remove(udp_handle->wait_timer_id);
94
95                 if (udp_handle->socket) {
96                         g_socket_close(udp_handle->socket, NULL);
97                         g_object_unref(udp_handle->socket);
98                 }
99
100                 free(udp_handle);
101                 udp_handle = NULL;
102         }
103
104         return 0;
105 }
106
107 /* Uses system call, because glib socket API doesn't support unset connect
108  * Please carefully use this function, and after use this function,
109  * DO NOT use g_socket_is_connected().
110  */
111 static int __receiver_udp_unset_connection(void)
112 {
113         struct sockaddr addr;
114         int s_fd = 0;
115
116         retvm_if(!udp_handle, -1, "handle is not created");
117         retvm_if(!udp_handle->socket, -1, "socket is not created");
118
119         s_fd = g_socket_get_fd(udp_handle->socket);
120         bzero((char *)&addr, sizeof(addr));
121         addr.sa_family = AF_UNSPEC;
122
123         if (connect(s_fd, &addr, sizeof(addr))) {
124                 _E("failed to unset connect - %s\n", strerror(errno));
125                 /* re-create socket or not ??? */
126                 return -1;
127         }
128         udp_handle->state = RECEIVER_UDP_STATE_READY;
129         _D("unset connection");
130
131         return 0;
132 }
133
134 static int __receiver_udp_set_connection(GSocketAddress *sender_a)
135 {
136         GError *error = NULL;
137
138         retv_if(!sender_a, -1);
139         retvm_if(!udp_handle, -1, "handle is not created");
140         retvm_if(!udp_handle->socket, -1, "socket is not created");
141
142         if (udp_handle->state != RECEIVER_UDP_STATE_READY) {
143                 _E("check state %d", udp_handle->state);
144                 return -1;
145         }
146
147         /* use connect() to specify sender address and reject other sender */
148         if (!g_socket_connect(udp_handle->socket, sender_a, NULL, &error)) {
149                 _E("failed to connect - %s", error->message);
150                 g_error_free(error);
151                 return -1;
152         }
153         udp_handle->state = RECEIVER_UDP_STATE_CONNECTED;
154         _D("set connection");
155
156         return 0;
157 }
158
159 static gboolean __wait_time_out(gpointer user_data)
160 {
161         __receiver_udp_unset_connection();
162
163         return FALSE;
164 }
165
166 static void __receiver_udp_update_wait_timer(void)
167 {
168         if (udp_handle) {
169                 if (udp_handle->wait_timer_id) {
170                         g_source_remove(udp_handle->wait_timer_id);
171                         udp_handle->wait_timer_id = 0;
172                 }
173                 udp_handle->wait_timer_id =
174                         g_timeout_add_seconds(RECEIVER_UDP_WAIT_TIMEOUT,
175                                 (GSourceFunc)__wait_time_out, NULL);
176         }
177         return;
178 }
179
180 static gboolean __read_socket(GIOChannel *channel,
181                 GIOCondition condition,
182                 gpointer data)
183 {
184         gssize size = 0;
185         receiver_udp_h *handle = (receiver_udp_h *)data;
186         GError *error = NULL;
187
188         char buf[1024] = {0, }; /* temp */
189
190         retv_if(!handle, TRUE);
191         retv_if(!handle->socket, TRUE);
192
193         if (handle->state == RECEIVER_UDP_STATE_NONE) {
194                 _E("receiver udp is not ready yet");
195                 return TRUE;
196         }
197
198         if (handle->state == RECEIVER_UDP_STATE_READY) {
199                 char *s_addr = NULL;
200                 GSocketAddress *address = NULL;
201
202                 size = g_socket_receive_from(handle->socket, &address,
203                         buf, sizeof(buf), NULL, &error);
204
205                 if (size < 0) {
206                         _D("Error receiving from socket: %s", error->message);
207                         g_error_free(error);
208                 }
209
210                 s_addr = __socket_address_to_string(address);
211                 _D("received first data from [%s]", s_addr);
212
213
214                 if (!__receiver_udp_set_connection(address))
215                         __receiver_udp_update_wait_timer();
216                 else
217                         _E("failed to set connection with [%s]", s_addr);
218
219                 free(s_addr);
220                 g_object_unref(address);
221         } else { /* state is RECEIVER_UDP_STATE_CONNECTED */
222                 size = g_socket_receive(handle->socket,
223                         buf, sizeof(buf), NULL, &error);
224
225                 if (size < 0) {
226                         _D("Error receiving from socket: %s", error->message);
227                         g_error_free(error);
228                 }
229                 _D("received data");
230                 __receiver_udp_update_wait_timer();
231         }
232
233         /* TODO : what should I do after receiveing some data? */
234
235         return TRUE;
236 }
237
238 int receiver_udp_start(void)
239 {
240         GError *error = NULL;
241         GSocketAddress *address = NULL;
242         GInetAddress *i_addr = NULL;
243         int socket_fd = 0;
244         GIOChannel *ch = NULL;
245         int ret = 0;
246
247         if (!udp_handle) {
248                 ret = __receiver_udp_init();
249                 if (ret)
250                         return -1;
251         }
252
253         if (udp_handle->state >= RECEIVER_UDP_STATE_READY) {
254                 _W("receiver udp is already started");
255                 return 0;
256         }
257
258         udp_handle->socket = g_socket_new(G_SOCKET_FAMILY_IPV4,
259                 G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &error);
260
261         if (udp_handle->socket == NULL) {
262                 _E("failed to get new socket - %s", error->message);
263                 goto ERROR;
264         }
265
266         /* set non-blocking mode */
267         g_socket_set_blocking(udp_handle->socket, FALSE);
268
269         i_addr = g_inet_address_new_any(G_SOCKET_FAMILY_IPV4);
270         if (!i_addr) {
271                 _E("failed to get inet any address");
272                 goto ERROR;
273         }
274         address = g_inet_socket_address_new(i_addr, RECEIVER_UDP_PORT);
275         g_object_unref(i_addr);
276         i_addr = NULL;
277
278         if (!address) {
279                 _E("failed to get socket address");
280                 goto ERROR;
281         }
282
283         if (!g_socket_bind(udp_handle->socket, address, TRUE, &error)) {
284                 _E("Can't bind socket: %s\n", error->message);
285                 goto ERROR;
286         }
287         g_object_unref(address);
288         address = NULL;
289
290         socket_fd = g_socket_get_fd(udp_handle->socket);
291         ch = g_io_channel_unix_new(socket_fd);
292         udp_handle->io_watch_id =
293                 g_io_add_watch(ch, G_IO_IN, __read_socket, udp_handle);
294         g_io_channel_unref(ch);
295         ch = NULL;
296
297         udp_handle->state = RECEIVER_UDP_STATE_READY;
298         _D("receiver udp started");
299
300         return 0;
301
302 ERROR:
303         if (error)
304                 g_error_free(error);
305
306         if (address)
307                 g_object_unref(address);
308
309         if (i_addr)
310                 g_object_unref(i_addr);
311
312         __receiver_udp_fini();
313
314         return -1;
315 }
316
317 int receiver_udp_stop(void)
318 {
319         __receiver_udp_fini();
320         _D("receiver udp stopped");
321
322         return 0;
323 }