/*
meshlink.c -- Implementation of the MeshLink API.
- Copyright (C) 2014-2018 Guus Sliepen <guus@meshlink.io>
+ Copyright (C) 2014-2021 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
mesh->appname = xstrdup(params->appname);
mesh->devclass = params->devclass;
- mesh->discovery = true;
+ mesh->discovery.enabled = true;
mesh->invitation_timeout = 604800; // 1 week
mesh->netns = params->netns;
mesh->submeshes = NULL;
pthread_mutex_init(&mesh->mutex, &attr);
pthread_cond_init(&mesh->cond, NULL);
- pthread_mutex_init(&mesh->discovery_mutex, NULL);
- pthread_cond_init(&mesh->discovery_cond, NULL);
-
pthread_cond_init(&mesh->adns_cond, NULL);
mesh->threadstarted = false;
#endif // HAVE_SETNS
}
- if(mesh->discovery) {
+ if(mesh->discovery.enabled) {
discovery_start(mesh);
}
pthread_mutex_unlock(&mesh->mutex);
// Stop discovery
- if(mesh->discovery) {
+ if(mesh->discovery.enabled) {
discovery_stop(mesh);
}
}
// Connect to the meshlink daemon mentioned in the URL.
- struct addrinfo *ai = adns_blocking_request(mesh, xstrdup(address), xstrdup(port), SOCK_STREAM, 5);
+ struct addrinfo *ai = adns_blocking_request(mesh, xstrdup(address), xstrdup(port), SOCK_STREAM, 30);
if(ai) {
for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) {
pthread_mutex_unlock(&mesh->mutex);
}
+void meshlink_channel_abort(meshlink_handle_t *mesh, meshlink_channel_t *channel) {
+ if(!mesh || !channel) {
+ meshlink_errno = MESHLINK_EINVAL;
+ return;
+ }
+
+ if(pthread_mutex_lock(&mesh->mutex) != 0) {
+ abort();
+ }
+
+ if(channel->c) {
+ utcp_abort(channel->c);
+ channel->c = NULL;
+
+ /* Clean up any outstanding AIO buffers. */
+ aio_abort(mesh, channel, &channel->aio_send);
+ aio_abort(mesh, channel, &channel->aio_receive);
+ }
+
+ if(!channel->in_callback) {
+ free(channel);
+ }
+
+ pthread_mutex_unlock(&mesh->mutex);
+}
+
ssize_t meshlink_channel_send(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
if(!mesh || !channel) {
meshlink_errno = MESHLINK_EINVAL;
abort();
}
- if(mesh->discovery == enable) {
+ if(mesh->discovery.enabled == enable) {
goto end;
}
}
}
- mesh->discovery = enable;
+ mesh->discovery.enabled = enable;
end:
pthread_mutex_unlock(&mesh->mutex);
}
+void meshlink_hint_network_change(struct meshlink_handle *mesh) {
+ if(!mesh) {
+ meshlink_errno = MESHLINK_EINVAL;
+ return;
+ }
+
+ if(pthread_mutex_lock(&mesh->mutex) != 0) {
+ abort();
+ }
+
+ if(mesh->discovery.enabled) {
+ scan_ifaddrs(mesh);
+ }
+
+ if(mesh->loop.now.tv_sec > mesh->discovery.last_update + 5) {
+ mesh->discovery.last_update = mesh->loop.now.tv_sec;
+ handle_network_change(mesh, 1);
+ }
+
+ pthread_mutex_unlock(&mesh->mutex);
+}
+
void meshlink_set_dev_class_timeouts(meshlink_handle_t *mesh, dev_class_t devclass, int pinginterval, int pingtimeout) {
if(!mesh || devclass < 0 || devclass >= DEV_CLASS_COUNT) {
meshlink_errno = EINVAL;
handle_network_change(mesh, true);
- if(mesh->discovery) {
+ if(mesh->discovery.enabled) {
discovery_refresh(mesh);
}