2 * Copyright (c) 2018 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.
17 #include "udp_connection.h"
21 #define MESSAGE_IN_BUF_SIZE 512
23 struct udp_connection {
25 udp_receive_cb receive_cb;
31 static gboolean _channel_ready_cb(GIOChannel *source, GIOCondition cond, gpointer data);
32 static void _connection_release_resources(udp_connection_t *connection);
34 udp_connection_t *udp_connection_create(int port)
36 udp_connection_t *connection = (udp_connection_t*) calloc(sizeof(udp_connection_t), 1);
37 if(connection == NULL) {
38 _E("Failed to calloc allocate memory");
42 connection->socket = g_socket_new(G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &(connection->error));
43 if(!connection->socket) {
44 _E("Failed to create socket");
45 _connection_release_resources(connection);
50 GInetAddress *inet_addr = g_inet_address_new_any(G_SOCKET_FAMILY_IPV4);
52 _E("Failed to obtain inet any address");
53 _connection_release_resources(connection);
56 gchar *address_str = g_inet_address_to_string(inet_addr);
57 _D("Obtained address: %s", address_str);
59 GInetSocketAddress *socket_addr = (GInetSocketAddress*) g_inet_socket_address_new(inet_addr, port);
60 g_object_unref(inet_addr);
62 _E("Failed to get socket address");
64 _connection_release_resources(connection);
68 gboolean res = g_socket_bind(connection->socket, (GSocketAddress*) socket_addr, TRUE, &(connection->error));
69 g_object_unref(socket_addr);
71 _E("Failed to bind socket: %s", connection->error->message);
73 _connection_release_resources(connection);
76 _D("Bound socket to %s:%d", address_str, port);
77 g_socket_set_blocking(connection->socket, FALSE);
79 int socket_fd = g_socket_get_fd(connection->socket);
80 connection->channel = g_io_channel_unix_new(socket_fd);
81 connection->watch_id = g_io_add_watch(connection->channel, G_IO_IN, _channel_ready_cb, connection);
82 g_io_channel_unref(connection->channel);
88 int udp_connection_send(udp_connection_t *connection, const char *data, unsigned short int size, const char *address, int port)
90 GIOCondition cond = g_socket_condition_check(connection->socket, G_IO_OUT);
91 if(cond != G_IO_OUT) {
92 _E("Failed to send data - socket is not G_IO_OUT");
96 GInetSocketAddress *receiver_address = (GInetSocketAddress*) g_inet_socket_address_new_from_string(address, port);
97 if(!receiver_address) {
98 _E("Failed to obtain socket address from %s:%d", address, port);
102 GError *error = NULL;
103 gssize wr_size = g_socket_send_to(connection->socket, (GSocketAddress*) receiver_address, data, size, NULL, &error);
104 if(wr_size != size) {
105 _E("Error sending data to %s:%d - sent only %d", address, port, wr_size);
106 g_object_unref(receiver_address);
110 g_object_unref(receiver_address);
111 _D("Sent %d bytes", size);
115 void udp_connection_set_receive_cb(udp_connection_t *connection, udp_receive_cb callback)
117 connection->receive_cb = callback;
120 void udp_connection_destroy(udp_connection_t *connection)
122 _connection_release_resources(connection);
125 static gboolean _channel_ready_cb(GIOChannel *source, GIOCondition cond, gpointer data)
127 udp_connection_t *connection = (udp_connection_t*) data;
128 GError *error = NULL;
129 GInetSocketAddress *socket_address = NULL;
130 gchar buffer[MESSAGE_IN_BUF_SIZE];
132 gssize size = g_socket_receive_from(connection->socket, (GSocketAddress**) &socket_address, buffer, MESSAGE_IN_BUF_SIZE, NULL, &error);
134 _E("Cannot read data from socket");
139 if(size == MESSAGE_IN_BUF_SIZE) {
140 _W("Packet dropped due to its size");
146 _W("No data to read");
150 GInetAddress *address= g_inet_socket_address_get_address(socket_address);
152 _E("Failed to obtain the address of received message");
156 gchar *address_str = g_inet_address_to_string(address);
158 _E("Failed to obtain the address in text of received message");
159 g_object_unref(address);
163 int port = g_inet_socket_address_get_port(socket_address);
164 if(connection->receive_cb) {
165 connection->receive_cb(buffer, size, address_str, port);
169 g_object_unref(socket_address);
174 static void _connection_release_resources(udp_connection_t *connection)
180 if(connection->error) {
181 g_error_free(connection->error);
184 if(connection->socket) {
185 g_socket_close(connection->socket, NULL);