2 mesh_event_handler.c -- handling of mesh events API
3 Copyright (C) 2018 Guus Sliepen <guus@meshlink.io>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
24 #include <sys/types.h>
26 #include <sys/ioctl.h>
27 #include <sys/socket.h>
33 #include "mesh_event_handler.h"
35 #define SERVER_LISTEN_PORT "9000" /* Port number that is binded with mesh event server socket */
37 // TODO: Implement mesh event handling with reentrant functions(if required).
38 static struct sockaddr_in server_addr;
39 static int client_fd = -1;
40 static int server_fd = -1;
42 char *mesh_event_sock_create(const char *if_name) {
43 struct sockaddr_in server;
46 struct sockaddr_in *resp_if_addr;
52 server_fd = socket(AF_INET, SOCK_DGRAM, 0);
58 assert(server_fd >= 0);
61 assert(setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) != -1);
63 memset(&req_if, 0, sizeof(req_if));
64 req_if.ifr_addr.sa_family = AF_INET;
65 strncpy(req_if.ifr_name, if_name, IFNAMSIZ - 1);
66 assert(ioctl(server_fd, SIOCGIFADDR, &req_if) != -1);
67 resp_if_addr = (struct sockaddr_in *) & (req_if.ifr_addr);
69 memset(&server, 0, sizeof(server));
70 server.sin_family = AF_INET;
71 server.sin_addr = resp_if_addr->sin_addr;
72 server.sin_port = htons(atoi(SERVER_LISTEN_PORT));
73 assert(bind(server_fd, (struct sockaddr *) &server, sizeof(struct sockaddr)) != -1);
75 assert(ip = malloc(30));
76 strncpy(ip, inet_ntoa(resp_if_addr->sin_addr), 20);
78 strcat(ip, SERVER_LISTEN_PORT);
83 void mesh_event_sock_connect(const char *import) {
88 char *ip = strdup(import);
89 assert((port = strchr(ip, ':')) != NULL);
93 memset(&server_addr, 0, sizeof(server_addr));
94 server_addr.sin_family = AF_INET;
95 server_addr.sin_addr.s_addr = inet_addr(ip);
96 server_addr.sin_port = htons(atoi(port));
97 client_fd = socket(AF_INET, SOCK_DGRAM, 0);
99 assert(client_fd >= 0);
102 bool mesh_event_sock_send(int client_id, mesh_event_t event, void *payload, size_t payload_length) {
103 mesh_event_payload_t mesh_event_send_packet;
106 // Packing the mesh event
107 assert(client_id >= 0);
108 assert(client_fd >= 0);
109 assert(event >= 0 && event < MAX_EVENT);
110 mesh_event_send_packet.client_id = client_id;
111 mesh_event_send_packet.mesh_event = event;
113 if((payload == NULL) || (payload_length == 0)) {
114 mesh_event_send_packet.payload_length = 0;
116 mesh_event_send_packet.payload_length = payload_length;
117 memmove(mesh_event_send_packet.payload, payload, payload_length);
120 send_ret = sendto(client_fd, &mesh_event_send_packet, sizeof(mesh_event_send_packet), 0, (const struct sockaddr *) &server_addr, sizeof(server_addr));
123 perror("sendto status");
130 bool wait_for_event(mesh_event_callback_t callback, int t) {
131 struct timeval timeout;
132 struct sockaddr client;
136 mesh_event_payload_t mesh_event_rec_packet;
139 assert(server_fd >= -1);
145 FD_SET(server_fd, &read_fds);
148 activity = select(server_fd + 1, &read_fds, NULL, NULL, &timeout);
149 assert(activity != -1);
152 // If no activity happened for the timeout given
154 } else if(FD_ISSET(server_fd, &read_fds)) {
155 // Unpacking the mesh event
156 ssize_t recv_ret = recvfrom(server_fd, &mesh_event_rec_packet, sizeof(mesh_event_rec_packet), 0, &client, &soc_len);
157 assert(recv_ret == sizeof(mesh_event_rec_packet));
158 callback(mesh_event_rec_packet);