2 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
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
8 * http://floralicense.org/license/
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.
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
27 #include "receiver_internal.h"
30 #define RECEIVER_UDP_PORT 57984
31 #define RECEIVER_UDP_WAIT_TIMEOUT 3
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;
40 typedef struct __receiver_udp_h {
43 receiver_udp_state_e state;
47 // static receiver_udp_h *udp_handle = NULL;
49 static gchar *__socket_address_to_string(GSocketAddress *address)
51 GInetAddress *inet_address = NULL;
56 g_inet_socket_address_get_address(G_INET_SOCKET_ADDRESS(address));
58 str = g_inet_address_to_string(inet_address);
59 port = g_inet_socket_address_get_port(G_INET_SOCKET_ADDRESS(address));
61 res = g_strdup_printf("%s:%d", str, port);
67 static receiver_state_e ___state_convert(receiver_udp_state_e state)
69 receiver_state_e r_state = RECEIVER_STATE_NONE;
72 case RECEIVER_UDP_STATE_NONE:
73 r_state = RECEIVER_STATE_NONE;
75 case RECEIVER_UDP_STATE_INIT:
76 r_state = RECEIVER_STATE_INIT;
78 case RECEIVER_UDP_STATE_READY:
79 r_state = RECEIVER_STATE_READY;
81 case RECEIVER_UDP_STATE_CONNECTED:
82 r_state = RECEIVER_STATE_CONNECTED;
88 static void __receiver_udp_state_set(
89 receiver_module_h *handle, receiver_udp_state_e state)
91 receiver_udp_h *udp_handle = NULL;
95 udp_handle = receiver_get_module_data(handle);
98 udp_handle->state = state;
100 receiver_module_state_changed(handle, ___state_convert(state));
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().
109 static int __receiver_udp_unset_connection(receiver_module_h *handle)
111 receiver_udp_h *udp_handle = NULL;
112 struct sockaddr addr;
115 retv_if(!handle, -1);
117 udp_handle = receiver_get_module_data(handle);
119 retvm_if(!udp_handle, -1, "handle is not created");
120 retvm_if(!udp_handle->socket, -1, "socket is not created");
122 s_fd = g_socket_get_fd(udp_handle->socket);
123 bzero((char *)&addr, sizeof(addr));
124 addr.sa_family = AF_UNSPEC;
126 if (connect(s_fd, &addr, sizeof(addr))) {
127 _E("failed to unset connect - %s\n", strerror(errno));
128 /* re-create socket or not ??? */
132 __receiver_udp_state_set(handle, RECEIVER_UDP_STATE_READY);
137 static int __receiver_udp_set_connection(
138 receiver_module_h *handle, GSocketAddress *sender_a)
140 GError *error = NULL;
141 receiver_udp_h *udp_handle = NULL;
143 retv_if(!handle, -1);
144 retv_if(!sender_a, -1);
146 udp_handle = receiver_get_module_data(handle);
148 retvm_if(!udp_handle, -1, "handle is not created");
149 retvm_if(!udp_handle->socket, -1, "socket is not created");
151 if (udp_handle->state != RECEIVER_UDP_STATE_READY) {
152 _E("check state %d", udp_handle->state);
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);
163 __receiver_udp_state_set(handle, RECEIVER_UDP_STATE_CONNECTED);
168 static gboolean __wait_time_out(gpointer user_data)
170 receiver_module_h *handle = user_data;
172 retv_if(!handle, FALSE);
174 __receiver_udp_unset_connection(handle);
179 static void __receiver_udp_update_wait_timer(receiver_module_h *handle)
181 receiver_udp_h *udp_handle = NULL;
185 udp_handle = receiver_get_module_data(handle);
188 if (udp_handle->wait_timer_id) {
189 g_source_remove(udp_handle->wait_timer_id);
190 udp_handle->wait_timer_id = 0;
192 udp_handle->wait_timer_id =
193 g_timeout_add_seconds(RECEIVER_UDP_WAIT_TIMEOUT,
194 (GSourceFunc)__wait_time_out, handle);
200 static gboolean __read_socket(GIOChannel *channel,
201 GIOCondition condition,
204 receiver_module_h *handle = data;
205 receiver_udp_h *udp_handle = NULL;
206 GError *error = NULL;
207 message_s *r_msg = NULL;
210 retv_if(!handle, TRUE);
212 udp_handle = receiver_get_module_data(handle);
214 retv_if(!udp_handle, TRUE);
215 retv_if(!udp_handle->socket, TRUE);
217 if (udp_handle->state < RECEIVER_UDP_STATE_READY) {
218 _E("receiver udp is not ready yet");
222 r_msg = malloc(sizeof(message_s));
223 retv_if(!r_msg, TRUE);
225 if (udp_handle->state == RECEIVER_UDP_STATE_READY) {
227 GSocketAddress *address = NULL;
229 size = g_socket_receive_from(udp_handle->socket, &address,
230 (gchar *)r_msg, sizeof(message_s), NULL, &error);
233 _D("Error receiving from socket: %s", error->message);
239 s_addr = __socket_address_to_string(address);
240 _D("received first data from [%s]", s_addr);
242 message_push_to_inqueue(r_msg);
244 if (!__receiver_udp_set_connection(handle, address))
245 __receiver_udp_update_wait_timer(handle);
247 _E("failed to set connection with [%s]", 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);
256 _D("Error receiving from socket: %s", error->message);
262 message_push_to_inqueue(r_msg);
264 __receiver_udp_update_wait_timer(handle);
267 /* TODO : what should I do after receiveing some data? */
272 static int _receiver_udp_start(void *data)
274 receiver_module_h *handle = data;
275 receiver_udp_h *udp_handle = NULL;
277 GIOChannel *ch = NULL;
279 retv_if(!handle, -1);
281 udp_handle = receiver_get_module_data(handle);
283 retv_if(!udp_handle, -1);
284 retv_if(!udp_handle->socket, -1);
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");
291 _E("receiver udp is invalid state [%d]", udp_handle->state);
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);
303 __receiver_udp_state_set(handle, RECEIVER_UDP_STATE_READY);
308 static int _receiver_udp_stop(void *data)
310 receiver_module_h *handle = data;
311 receiver_udp_h *udp_handle = NULL;
313 retv_if(!handle, -1);
315 udp_handle = receiver_get_module_data(handle);
317 retv_if(!udp_handle, -1);
318 retv_if(!udp_handle->socket, -1);
320 if (udp_handle->state < RECEIVER_UDP_STATE_READY) {
321 _E("receiver udp is invalid state [%d]", udp_handle->state);
325 if (udp_handle->wait_timer_id) {
326 g_source_remove(udp_handle->wait_timer_id);
327 udp_handle->wait_timer_id = 0;
330 if (udp_handle->io_watch_id) {
331 g_source_remove(udp_handle->io_watch_id);
332 udp_handle->io_watch_id = 0;
335 __receiver_udp_state_set(handle, RECEIVER_UDP_STATE_INIT);
340 static int _receiver_udp_init(void *data)
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;
348 retv_if(!handle, -1);
350 udp_handle = receiver_get_module_data(handle);
351 retv_if(!udp_handle, -1);
353 if (udp_handle->state != RECEIVER_UDP_STATE_NONE) {
354 _E("receiver udp is invalid state [%d]", udp_handle->state);
358 udp_handle->socket = g_socket_new(G_SOCKET_FAMILY_IPV4,
359 G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &error);
361 if (udp_handle->socket == NULL) {
362 _E("failed to get new socket - %s", error->message);
366 /* set non-blocking mode */
367 g_socket_set_blocking(udp_handle->socket, FALSE);
369 i_addr = g_inet_address_new_any(G_SOCKET_FAMILY_IPV4);
371 _E("failed to get inet any address");
374 address = g_inet_socket_address_new(i_addr, RECEIVER_UDP_PORT);
375 g_object_unref(i_addr);
379 _E("failed to get socket address");
383 if (!g_socket_bind(udp_handle->socket, address, TRUE, &error)) {
384 _E("Can't bind socket: %s\n", error->message);
387 g_object_unref(address);
390 __receiver_udp_state_set(handle, RECEIVER_UDP_STATE_INIT);
399 g_object_unref(address);
402 g_object_unref(i_addr);
407 static int _receiver_udp_fini(void *data)
409 receiver_module_h *handle = data;
410 receiver_udp_h *udp_handle = NULL;
412 retv_if(!handle, -1);
414 udp_handle = receiver_get_module_data(handle);
415 retv_if(!udp_handle, -1);
418 if (udp_handle->io_watch_id)
419 g_source_remove(udp_handle->io_watch_id);
421 if (udp_handle->wait_timer_id)
422 g_source_remove(udp_handle->wait_timer_id);
424 if (udp_handle->socket) {
425 g_socket_close(udp_handle->socket, NULL);
426 g_object_unref(udp_handle->socket);
429 __receiver_udp_state_set(handle, RECEIVER_UDP_STATE_NONE);
438 static receiver_state_e _receiver_udp_get_state(void *data)
440 receiver_module_h *handle = data;
441 receiver_udp_h *udp_handle = NULL;
443 retv_if(!handle, RECEIVER_STATE_NONE);
445 udp_handle = receiver_get_module_data(handle);
446 retv_if(!udp_handle, RECEIVER_STATE_NONE);
448 return ___state_convert(udp_handle->state);
451 /* Keep it here??? or move to new file??? */
452 int receiver_udp_module_register(receiver_module_h *handle)
454 receiver_udp_h *udp_handle = NULL;
456 retv_if(!handle, -1);
458 udp_handle = malloc(sizeof(receiver_udp_h));
460 _E("failed to alloc receiver udp handle");
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;
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);