]> git.meshlink.io Git - meshlink/commitdiff
Add a callback that notifies when the MeshLink thread starts and stops. feature/thread-status-callback
authorGuus Sliepen <guus@meshlink.io>
Sun, 3 Oct 2021 13:40:45 +0000 (15:40 +0200)
committerGuus Sliepen <guus@meshlink.io>
Sun, 3 Oct 2021 13:40:45 +0000 (15:40 +0200)
This callback is called from within the MeshLink thread, right after it
starts and right before it stops.

src/meshlink++.h
src/meshlink.c
src/meshlink.h
src/meshlink.sym
src/meshlink_internal.h

index fd66399217596e29ef54f85e1bd83d3c425edfaa..9e97fc820d846b29e9570da08bbc1fb47b65e4bd 100644 (file)
@@ -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<node *>(peer));
        }
 
+       static void thread_status_trampoline(meshlink_handle_t *handle, bool status) {
+               if(!(handle->priv)) {
+                       return;
+               }
+
+               meshlink::mesh *that = static_cast<mesh *>(handle->priv);
+               that->thread_status(status);
+       }
+
        static void connection_try_trampoline(meshlink_handle_t *handle, meshlink_node_t *peer) {
                if(!(handle->priv)) {
                        return;
index 71263b910696a4e9531672afec7c8252c4223b82..d89aa806eed7560be01e3e7b40729b538edc880b 100644 (file)
@@ -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;
 
index 9a887168acd7a56c5c624f88f11e6243201d4d6c..903bab36db1d1481035667b11ac90f046169a104 100644 (file)
@@ -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
index f598bcb61b70364de1a493777b1eb3e463b3b8c1..853394d072c103725e8a1dc74ec82358a0f7e666 100644 (file)
@@ -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
index 469a05b1aec146e81f0bf3482fcf2405f2c41ccd..b57f212c5fdf6569243c2256497f8e11f5514d6f 100644 (file)
@@ -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;