#include "ed25519/sha512.h"
#include "discovery.h"
#include "devtools.h"
+#include "graph.h"
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
return finalize_join(mesh, msg, len);
case 1:
- logger(mesh, MESHLINK_DEBUG, "Invitation succesfully accepted.\n");
+ logger(mesh, MESHLINK_DEBUG, "Invitation successfully accepted.\n");
shutdown(mesh->sock, SHUT_RDWR);
mesh->success = true;
break;
pthread_cond_wait(&mesh->cond, &mesh->mutex);
mesh->threadstarted = true;
- mesh->self->last_reachable = time(NULL);
- mesh->self->status.dirty = true;
+
+ // Ensure we are considered reachable
+ graph(mesh);
pthread_mutex_unlock(&mesh->mutex);
return true;
pthread_mutex_lock(&mesh->mutex);
logger(mesh, MESHLINK_DEBUG, "meshlink_stop called\n");
- if(mesh->self) {
- mesh->self->last_unreachable = time(NULL);
- mesh->self->status.dirty = true;
- }
-
// Shut down the main thread
event_loop_stop(&mesh->loop);
exit_outgoings(mesh);
+ // Ensure we are considered unreachable
+ if(mesh->nodes) {
+ graph(mesh);
+ }
+
// Try to write out any changed node config files, ignore errors at this point.
if(mesh->nodes) {
for splay_each(node_t, n, mesh->nodes) {
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 && !n->status.blacklisted;
+
+ 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;
}
// Ensure no other nodes know about this name
- if(meshlink_get_node(mesh, name)) {
+ if(lookup_node(mesh, name)) {
logger(mesh, MESHLINK_ERROR, "A node with name %s is already known!\n", name);
meshlink_errno = MESHLINK_EEXIST;
pthread_mutex_unlock(&mesh->mutex);
// If we changed our own host config file, write it out now
if(mesh->self->status.dirty) {
if(!node_write_config(mesh, mesh->self)) {
- logger(mesh, MESHLINK_ERROR, "Could not write our own host conifg file!\n");
+ logger(mesh, MESHLINK_ERROR, "Could not write our own host config file!\n");
pthread_mutex_unlock(&mesh->mutex);
return NULL;
}
n->mtuprobes = 0;
n->status.udp_confirmed = false;
+ if(n->status.reachable) {
+ n->last_unreachable = mesh->loop.now.tv_sec;
+ }
+
/* Graph updates will suppress status updates for blacklisted nodes, so we need to
* manually call the status callback if necessary.
*/
n->status.blacklisted = false;
if(n->status.reachable) {
+ n->last_reachable = mesh->loop.now.tv_sec;
update_node_status(mesh, n);
}
pthread_mutex_unlock(&mesh->mutex);
}
+void meshlink_set_dev_class_fast_retry_period(meshlink_handle_t *mesh, dev_class_t devclass, int fast_retry_period) {
+ if(!mesh || devclass < 0 || devclass >= DEV_CLASS_COUNT) {
+ meshlink_errno = EINVAL;
+ return;
+ }
+
+ if(fast_retry_period < 0) {
+ meshlink_errno = EINVAL;
+ return;
+ }
+
+ pthread_mutex_lock(&mesh->mutex);
+ mesh->dev_class_traits[devclass].fast_retry_period = fast_retry_period;
+ pthread_mutex_unlock(&mesh->mutex);
+}
+
void handle_network_change(meshlink_handle_t *mesh, bool online) {
(void)online;