]> git.meshlink.io Git - meshlink/blobdiff - test/blackbox/common/mesh_event_handler.c
Add the blackbox container based test suite.
[meshlink] / test / blackbox / common / mesh_event_handler.c
diff --git a/test/blackbox/common/mesh_event_handler.c b/test/blackbox/common/mesh_event_handler.c
new file mode 100644 (file)
index 0000000..0f331d6
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+    mesh_event_handler.c -- handling of mesh events API
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <time.h>
+#include "mesh_event_handler.h"
+
+#define SERVER_LISTEN_PORT "9000" /* Port number that is binded with mesh event server socket */
+
+// TODO: Implement mesh event handling with reentrant functions(if required).
+static struct sockaddr_in server_addr;
+static int client_fd = -1;
+static int server_fd = -1;
+
+char *mesh_event_sock_create(const char *if_name) {
+       struct sockaddr_in server;
+       char *ip;
+       struct ifreq req_if;
+       struct sockaddr_in *resp_if_addr;
+
+       if(if_name == NULL) {
+               return NULL;
+       }
+
+       server_fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+       if(server_fd < 0) {
+               perror("socket");
+       }
+
+       assert(server_fd >= 0);
+
+       int reuse = 1;
+       assert(setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) != -1);
+
+       memset(&req_if, 0, sizeof(req_if));
+       req_if.ifr_addr.sa_family = AF_INET;
+       strncpy(req_if.ifr_name, if_name, IFNAMSIZ - 1);
+       assert(ioctl(server_fd, SIOCGIFADDR, &req_if) != -1);
+       resp_if_addr = (struct sockaddr_in *) & (req_if.ifr_addr);
+
+       memset(&server, 0, sizeof(server));
+       server.sin_family = AF_INET;
+       server.sin_addr   = resp_if_addr->sin_addr;
+       server.sin_port   = htons(atoi(SERVER_LISTEN_PORT));
+       assert(bind(server_fd, (struct sockaddr *) &server, sizeof(struct sockaddr)) != -1);
+
+       assert(ip = malloc(30));
+       strncpy(ip, inet_ntoa(resp_if_addr->sin_addr), 20);
+       strcat(ip, ":");
+       strcat(ip, SERVER_LISTEN_PORT);
+
+       return ip;
+}
+
+void mesh_event_sock_connect(const char *import) {
+       char *port = NULL;
+
+       assert(import);
+
+       char *ip = strdup(import);
+       assert((port = strchr(ip, ':')) != NULL);
+       *port = '\0';
+       port++;
+
+       memset(&server_addr, 0, sizeof(server_addr));
+       server_addr.sin_family      = AF_INET;
+       server_addr.sin_addr.s_addr = inet_addr(ip);
+       server_addr.sin_port        = htons(atoi(port));
+       client_fd = socket(AF_INET, SOCK_DGRAM, 0);
+       free(ip);
+       assert(client_fd >= 0);
+}
+
+bool mesh_event_sock_send(int client_id, mesh_event_t event, void *payload, size_t payload_length) {
+       mesh_event_payload_t mesh_event_send_packet;
+       ssize_t send_ret;
+
+       // Packing the mesh event
+       assert(client_id >= 0);
+       assert(client_fd >= 0);
+       assert(event >= 0 && event < MAX_EVENT);
+       mesh_event_send_packet.client_id   = client_id;
+       mesh_event_send_packet.mesh_event  = event;
+
+       if((payload == NULL) || (payload_length == 0)) {
+               mesh_event_send_packet.payload_length = 0;
+       } else {
+               mesh_event_send_packet.payload_length = payload_length;
+               memmove(mesh_event_send_packet.payload, payload, payload_length);
+       }
+
+       send_ret = sendto(client_fd, &mesh_event_send_packet, sizeof(mesh_event_send_packet), 0, (const struct sockaddr *) &server_addr, sizeof(server_addr));
+
+       if(send_ret < 0) {
+               perror("sendto status");
+               return false;
+       } else {
+               return true;
+       }
+}
+
+bool wait_for_event(mesh_event_callback_t callback, int t) {
+       struct timeval timeout;
+       struct sockaddr client;
+       socklen_t soc_len;
+       fd_set read_fds;
+       int activity;
+       mesh_event_payload_t mesh_event_rec_packet;
+
+       assert(callback);
+       assert(server_fd >= -1);
+       assert(t >= 0);
+
+       timeout.tv_sec  = t;
+       timeout.tv_usec = 0;
+       FD_ZERO(&read_fds);
+       FD_SET(server_fd, &read_fds);
+
+       while(1) {
+               activity = select(server_fd + 1, &read_fds, NULL, NULL, &timeout);
+               assert(activity != -1);
+
+               if(activity == 0) {
+                       // If no activity happened for the timeout given
+                       return false;
+               } else if(FD_ISSET(server_fd, &read_fds)) {
+                       // Unpacking the mesh event
+                       ssize_t recv_ret = recvfrom(server_fd, &mesh_event_rec_packet, sizeof(mesh_event_rec_packet), 0, &client, &soc_len);
+                       assert(recv_ret == sizeof(mesh_event_rec_packet));
+                       callback(mesh_event_rec_packet);
+                       return true;
+               }
+       }// while
+}