(void)message;
}
+ /// This functions is called whenever MeshLink has encountered a serious error.
+ virtual void error(meshlink_errno_t meshlink_errno) {
+ /* do nothing */
+ (void)meshlink_errno;
+ }
+
/// This functions is called whenever MeshLink a meta-connection attempt is made.
virtual void connection_try(node *peer) {
/* do nothing */
meshlink_set_node_pmtu_cb(handle, &node_pmtu_trampoline);
meshlink_set_node_duplicate_cb(handle, &node_duplicate_trampoline);
meshlink_set_log_cb(handle, MESHLINK_DEBUG, &log_trampoline);
+ meshlink_set_error_cb(handle, &error_trampoline);
meshlink_set_channel_accept_cb(handle, &channel_accept_trampoline);
meshlink_set_connection_try_cb(handle, &connection_try_trampoline);
return meshlink_start(handle);
that->log(level, message);
}
+ static void error_trampoline(meshlink_handle_t *handle, meshlink_errno_t meshlink_errno) {
+ if(!(handle->priv)) {
+ return;
+ }
+
+ meshlink::mesh *that = static_cast<mesh *>(handle->priv);
+ that->error(meshlink_errno);
+ }
+
static void connection_try_trampoline(meshlink_handle_t *handle, meshlink_node_t *peer) {
if(!(handle->priv)) {
return;
}
}
+void meshlink_set_error_cb(struct meshlink_handle *mesh, meshlink_error_cb_t cb) {
+ if(!mesh) {
+ meshlink_errno = MESHLINK_EINVAL;
+ return;
+ }
+
+ pthread_mutex_lock(&(mesh->mesh_mutex));
+ mesh->error_cb = cb;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+}
+
bool meshlink_send(meshlink_handle_t *mesh, meshlink_node_t *destination, const void *data, size_t len) {
meshlink_packethdr_t *hdr;
retry(mesh);
}
+void call_error_cb(meshlink_handle_t *mesh) {
+ // We should only call the callback function if we are in the background thread.
+ if(!mesh->error_cb) {
+ return;
+ }
+
+ if(!mesh->threadstarted) {
+ return;
+ }
+
+ if(mesh->thread == pthread_self()) {
+ mesh->error_cb(mesh, meshlink_errno);
+ }
+}
+
+
static void __attribute__((constructor)) meshlink_init(void) {
crypto_init();
}
*/
extern void meshlink_set_log_cb(struct meshlink_handle *mesh, meshlink_log_level_t level, meshlink_log_cb_t cb);
+/// A callback for receiving error conditions encountered by the MeshLink thread.
+/** @param mesh A handle which represents an instance of MeshLink, or NULL.
+ * @param errno The error code describing what kind of error occured.
+ */
+typedef void (*meshlink_error_cb_t)(struct meshlink_handle *mesh, meshlink_errno_t meshlink_errno);
+
+/// Set the error callback.
+/** This functions sets the callback that is called whenever the MeshLink thread encounters a serious error.
+ *
+ * While most API functions report an error directly to the caller in case something went wrong,
+ * MeshLink also runs a background thread which can encounter error conditions.
+ * Most of them will be dealt with automatically, however there can be errors that will prevent MeshLink from
+ * working correctly. When the callback is called, it means that MeshLink is no longer functioning
+ * as expected. The application should then present an error message and shut down, or perform any other
+ * action it deems appropriate.
+ *
+ * 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.
+ *
+ * Even though the callback signals a serious error inside MeshLink, all open handles are still valid,
+ * and the application should close handles in exactly the same it would have to do if the callback
+ * was not called. This must not be done inside the callback itself.
+ *
+ * \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.
+ */
+extern void meshlink_set_error_cb(struct meshlink_handle *mesh, meshlink_error_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
meshlink_set_connection_try_cb
meshlink_set_default_blacklist
meshlink_set_dev_class_timeouts
+meshlink_set_error_cb
meshlink_set_invitation_timeout
meshlink_set_log_cb
meshlink_set_node_duplicate_cb
meshlink_channel_accept_cb_t channel_accept_cb;
meshlink_node_duplicate_cb_t node_duplicate_cb;
meshlink_connection_try_cb_t connection_try_cb;
+ meshlink_error_cb_t error_cb;
// Mesh parameters
char *appname;
extern meshlink_log_cb_t global_log_cb;
extern void handle_duplicate_node(meshlink_handle_t *mesh, struct node_t *n);
extern void handle_network_change(meshlink_handle_t *mesh, bool online);
+extern void call_error_cb(meshlink_handle_t *mesh);
/// Per-instance PRNG
static inline int prng(meshlink_handle_t *mesh, uint64_t max) {
}
config_t config = {buf, packmsg_output_size(&out, buf)};
- return config_write(mesh, "current", n->name, &config, mesh->config_key);
+
+ if(!config_write(mesh, "current", n->name, &config, mesh->config_key)) {
+ call_error_cb(mesh);
+ return false;
+ }
+
+ return true;
}
static bool load_node(meshlink_handle_t *mesh, const char *name, void *priv) {