]> git.meshlink.io Git - meshlink/commitdiff
Add condition check in auto connect for blacklisted nodes
authorLakshminarayana Gurram <38289425+lakshminarayanagurram@users.noreply.github.com>
Tue, 16 Apr 2019 06:39:35 +0000 (12:09 +0530)
committerGuus Sliepen <guus@meshlink.io>
Sat, 25 May 2019 22:11:13 +0000 (00:11 +0200)
* Add condition check in auto connect for blacklisted nodes

* Add test vector to test autoconnect

src/net.c
test/blackbox/run_blackbox_tests/Makefile.am
test/blackbox/run_blackbox_tests/run_blackbox_tests.c
test/blackbox/run_blackbox_tests/test_cases_autoconnect.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_autoconnect.h [new file with mode: 0644]
test/trio.c
test/utils.c
test/utils.h

index 9d5e81719392d7027a970f9238fea35a1adfe229..2a27350b3ed99e3ccec40c81103a69c4abe2c9fc 100644 (file)
--- a/src/net.c
+++ b/src/net.c
@@ -404,7 +404,7 @@ static void periodic_handler(event_loop_t *loop, void *data) {
                        for splay_each(node_t, n, mesh->nodes) {
                                logger(mesh, MESHLINK_DEBUG, "* n->devclass = %d", n->devclass);
 
-                               if(n != mesh->self && n->devclass <= mesh->devclass && !n->connection && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) {
+                               if(n != mesh->self && n->devclass <= mesh->devclass && !n->connection && !n->status.blacklisted && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) {
                                        splay_insert(nodes, n);
                                }
                        }
@@ -438,7 +438,7 @@ static void periodic_handler(event_loop_t *loop, void *data) {
                                        splay_tree_t *nodes = splay_alloc_tree(node_compare_lsc_desc, NULL);
 
                                        for splay_each(node_t, n, mesh->nodes) {
-                                               if(n != mesh->self && n->devclass == devclass && !n->connection && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) {
+                                               if(n != mesh->self && n->devclass == devclass && !n->connection && !n->status.blacklisted && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) {
                                                        splay_insert(nodes, n);
                                                }
                                        }
@@ -469,7 +469,7 @@ static void periodic_handler(event_loop_t *loop, void *data) {
                        splay_tree_t *nodes = splay_alloc_tree(node_compare_devclass_asc_lsc_desc, NULL);
 
                        for splay_each(node_t, n, mesh->nodes) {
-                               if(n != mesh->self && n->devclass <= mesh->devclass && !n->status.reachable && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) {
+                               if(n != mesh->self && n->devclass <= mesh->devclass && !n->status.reachable && !n->status.blacklisted && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) {
                                        splay_insert(nodes, n);
                                }
                        }
@@ -489,6 +489,7 @@ static void periodic_handler(event_loop_t *loop, void *data) {
 
                if(connect_to && !connect_to->connection) {
                        connect_to->last_connect_try = time(NULL);
+                       logger(mesh, MESHLINK_DEBUG, "Autoconnect trying to connect to %s", connect_to->name);
 
                        /* check if there is already a connection attempt to this node */
                        bool found = false;
index 00aa9b896140bb4d7bdf9ca8659090f1668fe0d7..0fa653b120911874da15e8252b0817c6840c0ae2 100644 (file)
@@ -60,7 +60,8 @@ run_blackbox_tests_SOURCES = \
        test_cases_submesh01.c \
        test_cases_submesh02.c \
        test_cases_submesh03.c \
-       test_cases_submesh04.c
+       test_cases_submesh04.c \
+       test_cases_autoconnect.c
 
 run_blackbox_tests_LDADD = ../../../src/libmeshlink.la $(LXC_LIBS) $(CMOCKA_LIBS)
 run_blackbox_tests_CFLAGS = -D_GNU_SOURCE $(LXC_CFLAGS) $(CMOCKA_CFLAGS)
index df23d5ae30d452460fcacc6932fa8b2684d8eac5..edf0f95dc977d28278ce6108ecdaf3d2c429465b 100644 (file)
@@ -71,6 +71,8 @@
 #include "test_cases_submesh03.h"
 #include "test_cases_submesh04.h"
 
+#include "test_cases_autoconnect.h"
+
 #include "../common/containers.h"
 #include "../common/common_handlers.h"
 
@@ -133,11 +135,13 @@ int main(int argc, char *argv[]) {
 
        failed_tests += test_meshlink_channel_conn();
        failed_tests += test_optimal_pmtu();
-       */
+
        failed_tests += test_cases_submesh01();
        failed_tests += test_cases_submesh02();
        failed_tests += test_cases_submesh03();
        failed_tests += test_cases_submesh04();
+       */
+       failed_tests += test_meshlink_autoconnect();
 
        failed_tests += test_optimal_pmtu();
 
diff --git a/test/blackbox/run_blackbox_tests/test_cases_autoconnect.c b/test/blackbox/run_blackbox_tests/test_cases_autoconnect.c
new file mode 100644 (file)
index 0000000..1899127
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+    test_cases_blacklist.c -- Execution of specific meshlink black box test cases
+    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.
+*/
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+
+#include "execute_tests.h"
+#include "test_cases_autoconnect.h"
+#include <pthread.h>
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include "../../utils.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <assert.h>
+#include <string.h>
+
+static void test_case_autoconnect(void **state);
+static bool test_steps_mesh_autoconnect(void);
+static meshlink_handle_t *mesh1, *mesh2;
+
+/* State structure for meshlink_blacklist Test Case #1 */
+static black_box_state_t test_mesh_autoconnect_state = {
+       .test_case_name = "test_case_mesh_autoconnect",
+};
+struct sync_flag test_autoconnect_m1n1_reachable = {.mutex  = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false};
+struct sync_flag test_autoconnect_blacklisted = {.mutex  = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false};
+struct sync_flag test_autoconnect_successful = {.mutex  = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false};
+
+/* Execute meshlink_blacklist Test Case # 1*/
+void test_case_autoconnect(void **state) {
+       execute_test(test_steps_mesh_autoconnect, state);
+}
+
+void callback_logger(meshlink_handle_t *mesh, meshlink_log_level_t level,
+                     const char *text) {
+       (void)level;
+
+       fprintf(stderr, "%s: {%s}\n", mesh->name, text);
+
+       if((check_sync_flag(&test_autoconnect_blacklisted) == true) && (strcmp("m1n2", mesh->name) == 0) && (strcmp("* could not find node for initial connect", text) == 0)) {
+               fprintf(stderr, "Test case successful\n");
+               set_sync_flag(&test_autoconnect_successful, true);
+       } else if((check_sync_flag(&test_autoconnect_blacklisted) == true) && (strcmp("m1n2", mesh->name) == 0)) {
+               assert(strcmp(text, "Autoconnect trying to connect to m1n1") != 0);
+       }
+
+}
+
+static void receive(meshlink_handle_t *mesh, meshlink_node_t *src, const void *data, size_t len) {
+       (void)mesh;
+       (void)src;
+       (void)data;
+       assert(len);
+}
+
+static bool bar_reachable;
+
+static void status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
+       (void)mesh;
+       fprintf(stderr, "Status of node {%s} is %d\n", node->name, reachable);
+
+       if(!strcmp(node->name, "m1n1") && reachable) {
+               set_sync_flag(&test_autoconnect_m1n1_reachable, true);
+       }
+}
+
+
+/* Test Steps for meshlink_blacklist Test Case # 1
+
+    Test Steps:
+    1. Open both the node instances
+    2. Join bar node with foo and Send & Receive data
+    3. Blacklist bar and Send & Receive data
+
+    Expected Result:
+    When default blacklist is disabled, foo node should receive data from bar
+    but when enabled foo node should not receive data
+*/
+bool test_steps_mesh_autoconnect(void) {
+       char *invite = NULL;
+       meshlink_node_t *node = NULL;
+
+       meshlink_destroy("m1n1");
+       meshlink_destroy("m1n2");
+
+       // Open two new meshlink instance.
+       mesh1 = meshlink_open("m1n1", "m1n1", "autoconnect", DEV_CLASS_BACKBONE);
+       assert(mesh1 != NULL);
+       meshlink_set_log_cb(mesh1, TEST_MESHLINK_LOG_LEVEL, callback_logger);
+
+       mesh2 = meshlink_open("m1n2", "m1n2", "autoconnect", DEV_CLASS_STATIONARY);
+       assert(mesh2 != NULL);
+       meshlink_set_log_cb(mesh2, TEST_MESHLINK_LOG_LEVEL, callback_logger);
+       meshlink_set_receive_cb(mesh1, receive);
+
+       // Start both instances
+       meshlink_set_node_status_cb(mesh1, status_cb);
+       assert(meshlink_start(mesh1));
+
+       invite = meshlink_invite(mesh1, NULL, "m1n2");
+       assert(invite);
+
+       assert(meshlink_join(mesh2, invite));
+
+       meshlink_set_node_status_cb(mesh2, status_cb);
+       assert(meshlink_start(mesh2));
+
+       assert(wait_sync_flag(&test_autoconnect_m1n1_reachable, 30));
+
+       node = meshlink_get_node(mesh2, "m1n1");
+       meshlink_blacklist(mesh2, node);
+       set_sync_flag(&test_autoconnect_blacklisted, true);
+
+       assert(wait_sync_flag(&test_autoconnect_successful, 60));
+
+       // Clean up.
+       meshlink_close(mesh1);
+       fprintf(stderr, "Meshlink node1 closed\n");
+       meshlink_close(mesh2);
+       fprintf(stderr, "Meshlink node2 closed\n");
+
+       meshlink_destroy("m1n1");
+       meshlink_destroy("m1n2");
+       fprintf(stderr, "Meshlink nodes destroyed\n");
+
+       return true;
+}
+
+int test_meshlink_autoconnect(void) {
+       const struct CMUnitTest blackbox_blacklist_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_autoconnect, NULL, NULL,
+                               (void *)&test_mesh_autoconnect_state)
+       };
+
+       total_tests += sizeof(blackbox_blacklist_tests) / sizeof(blackbox_blacklist_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_blacklist_tests, NULL, NULL);
+}
+
diff --git a/test/blackbox/run_blackbox_tests/test_cases_autoconnect.h b/test/blackbox/run_blackbox_tests/test_cases_autoconnect.h
new file mode 100644 (file)
index 0000000..10b4911
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_AUTOCONNECT_H
+#define TEST_CASES_AUTOCONNECT_H
+
+/*
+    test_cases_autoconnect.h -- Declarations for Individual Test Case implementation functions
+    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 <stdbool.h>
+
+extern int test_meshlink_autoconnect(void);
+extern int total_tests;
+
+#endif
index 522020fe1d07bbe61d3811095d6fdf7278871ad1..79013a6f5e3ed016a144fad68bb2c52b249ecb5e 100644 (file)
@@ -53,8 +53,8 @@ int main() {
 
        for(int i = 0; i < 3; i++) {
                char *path;
-    int ret_val;
-    (void)ret_val;
+               int ret_val;
+               (void)ret_val;
                ret_val = asprintf(&path, "trio_conf.%d", i);
                assert(path);
 
index a2b7b143972991d824ad23b9922860172f279921..9a9bd211fcef7b85a5ee7904062e30f305009134 100644 (file)
@@ -15,6 +15,14 @@ void set_sync_flag(struct sync_flag *s, bool value) {
        pthread_mutex_unlock(&s->mutex);
 }
 
+bool check_sync_flag(struct sync_flag *s) {
+       bool flag;
+       pthread_mutex_lock(&s->mutex);
+       flag = s->flag;
+       pthread_mutex_unlock(&s->mutex);
+       return flag;
+}
+
 bool wait_sync_flag(struct sync_flag *s, int seconds) {
        struct timespec timeout;
        clock_gettime(CLOCK_REALTIME, &timeout);
@@ -22,10 +30,11 @@ bool wait_sync_flag(struct sync_flag *s, int seconds) {
 
        pthread_mutex_lock(&s->mutex);
 
-       while(!s->flag)
+       while(!s->flag) {
                if(!pthread_cond_timedwait(&s->cond, &s->mutex, &timeout) || errno != EINTR) {
                        break;
                }
+       }
 
        pthread_mutex_unlock(&s->mutex);
 
index 27bb38c3fe9e20a8abae834c1d802d941daee2a2..a657dffad6df98305d17eb092a80584497eee8b8 100644 (file)
@@ -11,6 +11,7 @@ struct sync_flag {
 };
 
 extern void set_sync_flag(struct sync_flag *s, bool value);
+extern bool check_sync_flag(struct sync_flag *s);
 extern bool wait_sync_flag(struct sync_flag *s, int seconds);
 
 /// Create a pair of meshlink instances that are already joined together.