From: Guus Sliepen Date: Sun, 3 Oct 2021 13:40:45 +0000 (+0200) Subject: Add a callback that notifies when the MeshLink thread starts and stops. X-Git-Url: https://git.meshlink.io/?a=commitdiff_plain;h=refs%2Fheads%2Ffeature%2Fthread-status-callback;p=meshlink Add a callback that notifies when the MeshLink thread starts and stops. This callback is called from within the MeshLink thread, right after it starts and right before it stops. --- diff --git a/src/meshlink++.h b/src/meshlink++.h index fd663992..9e97fc82 100644 --- a/src/meshlink++.h +++ b/src/meshlink++.h @@ -280,6 +280,12 @@ public: (void)peer; } + /// This functions is called whenever the MeshLink thread status changes. + virtual void thread_status(bool status) { + /* do nothing */ + (void)status; + } + /// This functions is called whenever MeshLink a meta-connection attempt is made. virtual void connection_try(node *peer) { /* do nothing */ @@ -381,6 +387,7 @@ public: meshlink_set_log_cb(handle, MESHLINK_DEBUG, &log_trampoline); meshlink_set_error_cb(handle, &error_trampoline); meshlink_set_blacklisted_cb(handle, &blacklisted_trampoline); + meshlink_set_thread_status_cb(handle, &thread_status_trampoline); meshlink_set_channel_listen_cb(handle, &channel_listen_trampoline); meshlink_set_channel_accept_cb(handle, &channel_accept_trampoline); meshlink_set_connection_try_cb(handle, &connection_try_trampoline); @@ -1313,6 +1320,15 @@ private: that->blacklisted(static_cast(peer)); } + static void thread_status_trampoline(meshlink_handle_t *handle, bool status) { + if(!(handle->priv)) { + return; + } + + meshlink::mesh *that = static_cast(handle->priv); + that->thread_status(status); + } + static void connection_try_trampoline(meshlink_handle_t *handle, meshlink_node_t *peer) { if(!(handle->priv)) { return; diff --git a/src/meshlink.c b/src/meshlink.c index 71263b91..d89aa806 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -1723,11 +1723,19 @@ static void *meshlink_main_loop(void *arg) { abort(); } + if(mesh->thread_status_cb) { + mesh->thread_status_cb(mesh, true); + } + logger(mesh, MESHLINK_DEBUG, "Starting main_loop...\n"); pthread_cond_broadcast(&mesh->cond); main_loop(mesh); logger(mesh, MESHLINK_DEBUG, "main_loop returned.\n"); + if(mesh->thread_status_cb) { + mesh->thread_status_cb(mesh, false); + } + pthread_mutex_unlock(&mesh->mutex); // Stop discovery @@ -2166,6 +2174,22 @@ void meshlink_set_blacklisted_cb(struct meshlink_handle *mesh, meshlink_blacklis pthread_mutex_unlock(&mesh->mutex); } +void meshlink_set_thread_status_cb(struct meshlink_handle *mesh, meshlink_thread_status_cb_t cb) { + logger(mesh, MESHLINK_DEBUG, "meshlink_set_thread_status_cb(%p)", (void *)(intptr_t)cb); + + if(!mesh) { + meshlink_errno = MESHLINK_EINVAL; + return; + } + + if(pthread_mutex_lock(&mesh->mutex) != 0) { + abort(); + } + + mesh->thread_status_cb = cb; + pthread_mutex_unlock(&mesh->mutex); +} + static bool prepare_packet(meshlink_handle_t *mesh, meshlink_node_t *destination, const void *data, size_t len, vpn_packet_t *packet) { meshlink_packethdr_t *hdr; diff --git a/src/meshlink.h b/src/meshlink.h index 9a887168..903bab36 100644 --- a/src/meshlink.h +++ b/src/meshlink.h @@ -611,6 +611,27 @@ typedef void (*meshlink_blacklisted_cb_t)(struct meshlink_handle *mesh, struct m */ void meshlink_set_blacklisted_cb(struct meshlink_handle *mesh, meshlink_blacklisted_cb_t cb); +/// A callback notifying when the MeshLink thread starts and stops. +/* @param mesh A handle which represents an instance of MeshLink, or NULL. + * @param started True if the MeshLink thread has started, false if it is about to stop. + */ +typedef void (*meshlink_thread_status_cb_t)(struct meshlink_handle *mesh, bool started); + +/// Set the thread status callback. +/** This functions sets the callback that is called whenever the MeshLink thread has started or is about to stop. + * + * The callback is run in MeshLink's own thread. + * It is important that the callback uses apprioriate methods (queues, pipes, locking, etc.) + * to hand the data over to the application's thread. + * The callback should also not block itself and return as quickly as possible. + * + * \memberof meshlink_handle + * @param mesh A handle which represents an instance of MeshLink, or NULL. + * @param cb A pointer to the function which will be called when a serious error is encountered. + * If a NULL pointer is given, the callback will be disabled. + */ +void meshlink_set_thread_status_cb(struct meshlink_handle *mesh, meshlink_thread_status_cb_t cb); + /// Send data to another node. /** This functions sends one packet of data to another node in the mesh. * The packet is sent using UDP semantics, which means that diff --git a/src/meshlink.sym b/src/meshlink.sym index f598bcb6..853394d0 100644 --- a/src/meshlink.sym +++ b/src/meshlink.sym @@ -103,6 +103,7 @@ meshlink_set_node_status_cb meshlink_set_port meshlink_set_receive_cb meshlink_set_scheduling_granularity +meshlink_set_thread_status_cb meshlink_sign meshlink_start meshlink_stop diff --git a/src/meshlink_internal.h b/src/meshlink_internal.h index 469a05b1..b57f212c 100644 --- a/src/meshlink_internal.h +++ b/src/meshlink_internal.h @@ -140,6 +140,7 @@ struct meshlink_handle { meshlink_connection_try_cb_t connection_try_cb; meshlink_error_cb_t error_cb; meshlink_blacklisted_cb_t blacklisted_cb; + meshlink_thread_status_cb_t thread_status_cb; // Mesh parameters char *appname;