From be83b0af60449c7b35d17d97f2e6dc12f611e831 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Mon, 20 Jan 2020 00:45:09 +0100 Subject: [PATCH] Add meshlink_get_node_reachability(). This function returns the current state of a node's reachability, as well as the last time the node became reachable and the last time it became unreachable. --- src/meshlink++.h | 14 ++++++++++++++ src/meshlink.c | 25 +++++++++++++++++++++++++ src/meshlink.h | 16 ++++++++++++++++ src/meshlink.sym | 1 + test/basic.c | 8 ++++++++ test/import-export.c | 28 ++++++++++++++++++++++++++++ 6 files changed, 92 insertions(+) diff --git a/src/meshlink++.h b/src/meshlink++.h index 3599cc55..6374a86d 100644 --- a/src/meshlink++.h +++ b/src/meshlink++.h @@ -388,6 +388,20 @@ public: return (node *)meshlink_get_node(handle, name); } + /// Get a node's reachability status. + /** This function returns the current reachability of a given node, and the times of the last state changes. + * If a given state change never happened, the time returned will be 0. + * + * @param node A pointer to a meshlink::node describing the node. + * @param last_reachable A pointer to a time_t variable that will be filled in with the last time the node became reachable. + * @param last_unreachable A pointer to a time_t variable that will be filled in with the last time the node became unreachable. + * + * @return This function returns true if the node is currently reachable, false otherwise. + */ + bool get_node_reachability(node *node, time_t *last_reachable = NULL, time_t *last_unreachable = NULL) { + return meshlink_get_node_reachability(handle, node, last_reachable, last_unreachable); + } + /// Get a handle for a specific submesh. /** This function returns a handle for the submesh with the given name. * diff --git a/src/meshlink.c b/src/meshlink.c index 30b38684..2d4c2e1f 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -2143,6 +2143,31 @@ meshlink_submesh_t *meshlink_get_node_submesh(meshlink_handle_t *mesh, meshlink_ return s; } +bool meshlink_get_node_reachability(struct meshlink_handle *mesh, struct meshlink_node *node, time_t *last_reachable, time_t *last_unreachable) { + if(!mesh || !node) { + meshlink_errno = MESHLINK_EINVAL; + return NULL; + } + + node_t *n = (node_t *)node; + bool reachable; + + pthread_mutex_lock(&mesh->mutex); + reachable = n->status.reachable; + + if(last_reachable) { + *last_reachable = n->last_reachable; + } + + if(last_unreachable) { + *last_unreachable = n->last_unreachable; + } + + pthread_mutex_unlock(&mesh->mutex); + + return reachable; +} + bool meshlink_sign(meshlink_handle_t *mesh, const void *data, size_t len, void *signature, size_t *siglen) { if(!mesh || !data || !len || !signature || !siglen) { meshlink_errno = MESHLINK_EINVAL; diff --git a/src/meshlink.h b/src/meshlink.h index e3a7ca94..e0f1bae7 100644 --- a/src/meshlink.h +++ b/src/meshlink.h @@ -758,6 +758,22 @@ extern dev_class_t meshlink_get_node_dev_class(struct meshlink_handle *mesh, str */ extern struct meshlink_submesh *meshlink_get_node_submesh(struct meshlink_handle *mesh, struct meshlink_node *node) __attribute__((__warn_unused_result__)); +/// Get a node's reachability status. +/** This function returns the current reachability of a given node, and the times of the last state changes. + * If a given state change never happened, the time returned will be 0. + * + * \memberof meshlink_node + * @param mesh A handle which represents an instance of MeshLink. + * @param node A pointer to a struct meshlink_node describing the node. + * @param last_reachable A pointer to a time_t variable that will be filled in with the last time the node became reachable. + * Pass NULL to not have anything written. + * @param last_unreachable A pointer to a time_t variable that will be filled in with the last time the node became unreachable. + * Pass NULL to not have anything written. + * + * @return This function returns true if the node is currently reachable, false otherwise. + */ +extern bool meshlink_get_node_reachability(struct meshlink_handle *mesh, struct meshlink_node *node, time_t *last_reachable, time_t *last_unreachable); + /// Verify the signature generated by another node of a piece of data. /** This function verifies the signature that another node generated for a piece of data. * diff --git a/src/meshlink.sym b/src/meshlink.sym index b0ad2e52..9c3d9065 100644 --- a/src/meshlink.sym +++ b/src/meshlink.sym @@ -39,6 +39,7 @@ meshlink_get_fingerprint meshlink_get_local_address_for_family meshlink_get_node meshlink_get_node_dev_class +meshlink_get_node_reachability meshlink_get_node_submesh meshlink_get_pmtu meshlink_get_port diff --git a/test/basic.c b/test/basic.c index e0f77c57..46f86960 100644 --- a/test/basic.c +++ b/test/basic.c @@ -37,11 +37,19 @@ int main() { assert(self); assert(!strcmp(self->name, "foo")); + // Check that we are reachable. + + assert(meshlink_get_node_reachability(mesh, self, NULL, NULL)); + // Start and stop the mesh. assert(meshlink_start(mesh)); meshlink_stop(mesh); + // Check that we are still reachable. + + assert(meshlink_get_node_reachability(mesh, self, NULL, NULL)); + // Make sure we can start and stop the mesh again. assert(meshlink_start(mesh)); diff --git a/test/import-export.c b/test/import-export.c index 8bc41c1b..bffe0fc4 100644 --- a/test/import-export.c +++ b/test/import-export.c @@ -58,6 +58,16 @@ int main() { assert(meshlink_import(mesh1, data)); free(data); + // Check that foo knows bar, but that it is not reachable. + + time_t last_reachable; + time_t last_unreachable; + meshlink_node_t *bar = meshlink_get_node(mesh1, "bar"); + assert(bar); + assert(!meshlink_get_node_reachability(mesh1, bar, &last_reachable, &last_unreachable)); + assert(!last_reachable); + assert(!last_unreachable); + // Start both instances meshlink_set_node_status_cb(mesh1, status_cb); @@ -80,6 +90,24 @@ int main() { assert(pmtu); + // Check that we now have reachability information + + assert(meshlink_get_node_reachability(mesh1, bar, &last_reachable, &last_unreachable)); + assert(last_reachable); + assert(!last_unreachable); + + // Stop the meshes. + + meshlink_stop(mesh1); + meshlink_stop(mesh2); + + // Check that bar is no longer reachable + + assert(!meshlink_get_node_reachability(mesh1, bar, &last_reachable, &last_unreachable)); + assert(last_reachable); + assert(last_unreachable); + assert(last_reachable <= last_unreachable); + // Clean up. meshlink_close(mesh2); -- 2.39.2