This reverses the mutex use; instead of locking when modifying nodes,
we unlock when not modifying the mesh. Any API functions that wish
to use the mesh must aquire the lock first.
TODO: Currently there is a deadlock problem, and the discovery thread is not
cleanly handled yet.
-bool event_loop_run(event_loop_t *loop) {
+bool event_loop_run(event_loop_t *loop, pthread_mutex_t *mutex) {
loop->running = true;
fd_set readable;
loop->running = true;
fd_set readable;
+ // release mesh mutex during select
+ if(mutex)
+ pthread_mutex_unlock(mutex);
int n = select(fds, &readable, &writable, NULL, tv);
int n = select(fds, &readable, &writable, NULL, tv);
+ if(mutex)
+ pthread_mutex_lock(mutex);
if(n < 0) {
if(sockwouldblock(errno))
if(n < 0) {
if(sockwouldblock(errno))
extern void event_loop_init(event_loop_t *loop);
extern void event_loop_exit(event_loop_t *loop);
extern void event_loop_init(event_loop_t *loop);
extern void event_loop_exit(event_loop_t *loop);
-extern bool event_loop_run(event_loop_t *loop);
+extern bool event_loop_run(event_loop_t *loop, pthread_mutex_t *mutex);
extern void event_loop_flush_output(event_loop_t *loop);
extern void event_loop_stop(event_loop_t *loop);
extern void event_loop_flush_output(event_loop_t *loop);
extern void event_loop_stop(event_loop_t *loop);
// Validate arguments provided by the application
bool usingname = false;
// Validate arguments provided by the application
bool usingname = false;
+
+ logger(NULL, MESHLINK_DEBUG, "meshlink_open called\n");
if(!confbase || !*confbase) {
logger(NULL, MESHLINK_ERROR, "No confbase given!\n");
if(!confbase || !*confbase) {
logger(NULL, MESHLINK_ERROR, "No confbase given!\n");
mesh->appname = xstrdup(appname);
mesh->dclass = dclass;
if (usingname) mesh->name = xstrdup(name);
mesh->appname = xstrdup(appname);
mesh->dclass = dclass;
if (usingname) mesh->name = xstrdup(name);
- pthread_mutex_init ( &(mesh->nodes_mutex), NULL);
+
+ // initialize mutex
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&(mesh->mesh_mutex), &attr);
+
mesh->threadstarted = false;
event_loop_init(&mesh->loop);
mesh->loop.data = mesh;
mesh->threadstarted = false;
event_loop_init(&mesh->loop);
mesh->loop.data = mesh;
+ logger(NULL, MESHLINK_DEBUG, "meshlink_open returning\n");
return mesh;
}
static void *meshlink_main_loop(void *arg) {
meshlink_handle_t *mesh = arg;
return mesh;
}
static void *meshlink_main_loop(void *arg) {
meshlink_handle_t *mesh = arg;
+ pthread_mutex_lock(&(mesh->mesh_mutex));
+
try_outgoing_connections(mesh);
logger(mesh, MESHLINK_DEBUG, "Starting main_loop...\n");
main_loop(mesh);
logger(mesh, MESHLINK_DEBUG, "main_loop returned.\n");
try_outgoing_connections(mesh);
logger(mesh, MESHLINK_DEBUG, "Starting main_loop...\n");
main_loop(mesh);
logger(mesh, MESHLINK_DEBUG, "main_loop returned.\n");
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
return NULL;
}
bool meshlink_start(meshlink_handle_t *mesh) {
return NULL;
}
bool meshlink_start(meshlink_handle_t *mesh) {
-
- logger(mesh, MESHLINK_DEBUG, "meshlink_start called\n");
-
if(!mesh) {
meshlink_errno = MESHLINK_EINVAL;
return false;
}
if(!mesh) {
meshlink_errno = MESHLINK_EINVAL;
return false;
}
+ pthread_mutex_lock(&(mesh->mesh_mutex));
+
+ logger(mesh, MESHLINK_DEBUG, "meshlink_start called\n");
// TODO: open listening sockets first
// TODO: open listening sockets first
if(!mesh->name ) {
logger(mesh, MESHLINK_DEBUG, "No name given!\n");
meshlink_errno = MESHLINK_EINVAL;
if(!mesh->name ) {
logger(mesh, MESHLINK_DEBUG, "No name given!\n");
meshlink_errno = MESHLINK_EINVAL;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
logger(mesh, MESHLINK_DEBUG, "Could not start thread: %s\n", strerror(errno));
memset(&mesh->thread, 0, sizeof mesh->thread);
meshlink_errno = MESHLINK_EINTERNAL;
logger(mesh, MESHLINK_DEBUG, "Could not start thread: %s\n", strerror(errno));
memset(&mesh->thread, 0, sizeof mesh->thread);
meshlink_errno = MESHLINK_EINTERNAL;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
return true;
}
void meshlink_stop(meshlink_handle_t *mesh) {
return true;
}
void meshlink_stop(meshlink_handle_t *mesh) {
-
- logger(mesh, MESHLINK_DEBUG, "meshlink_stop called\n");
-
if(!mesh) {
meshlink_errno = MESHLINK_EINVAL;
return;
}
if(!mesh) {
meshlink_errno = MESHLINK_EINVAL;
return;
}
+ pthread_mutex_lock(&(mesh->mesh_mutex));
+ logger(mesh, MESHLINK_DEBUG, "meshlink_stop called\n");
+
// Stop discovery
discovery_stop(mesh);
// Stop discovery
discovery_stop(mesh);
shutdown(s->tcp.fd, SHUT_RDWR);
// Wait for the main thread to finish
shutdown(s->tcp.fd, SHUT_RDWR);
// Wait for the main thread to finish
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
pthread_join(mesh->thread, NULL);
pthread_join(mesh->thread, NULL);
+ pthread_mutex_lock(&(mesh->mesh_mutex));
+
mesh->threadstarted = false;
// Fix the socket
mesh->threadstarted = false;
// Fix the socket
logger(mesh, MESHLINK_ERROR, "Could not repair listenen socket!");
else
io_add(&mesh->loop, &s->tcp, handle_new_meta_connection, s, s->tcp.fd, IO_READ);
logger(mesh, MESHLINK_ERROR, "Could not repair listenen socket!");
else
io_add(&mesh->loop, &s->tcp, handle_new_meta_connection, s, s->tcp.fd, IO_READ);
+
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
}
void meshlink_close(meshlink_handle_t *mesh) {
}
void meshlink_close(meshlink_handle_t *mesh) {
+ // lock is not released after this
+ pthread_mutex_lock(&(mesh->mesh_mutex));
+
// Close and free all resources used.
close_network_connections(mesh);
// Close and free all resources used.
close_network_connections(mesh);
free(mesh->name);
free(mesh->appname);
free(mesh->confbase);
free(mesh->name);
free(mesh->appname);
free(mesh->confbase);
+ pthread_mutex_destroy(&(mesh->mesh_mutex));
memset(mesh, 0, sizeof *mesh);
memset(mesh, 0, sizeof *mesh);
+ pthread_mutex_lock(&(mesh->mesh_mutex));
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
}
void meshlink_set_node_status_cb(meshlink_handle_t *mesh, meshlink_node_status_cb_t cb) {
}
void meshlink_set_node_status_cb(meshlink_handle_t *mesh, meshlink_node_status_cb_t cb) {
+ pthread_mutex_lock(&(mesh->mesh_mutex));
mesh->node_status_cb = cb;
mesh->node_status_cb = cb;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
}
void meshlink_set_log_cb(meshlink_handle_t *mesh, meshlink_log_level_t level, meshlink_log_cb_t cb) {
if(mesh) {
}
void meshlink_set_log_cb(meshlink_handle_t *mesh, meshlink_log_level_t level, meshlink_log_cb_t cb) {
if(mesh) {
+ pthread_mutex_lock(&(mesh->mesh_mutex));
mesh->log_cb = cb;
mesh->log_level = cb ? level : 0;
mesh->log_cb = cb;
mesh->log_level = cb ? level : 0;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
} else {
global_log_cb = cb;
global_log_level = cb ? level : 0;
} else {
global_log_cb = cb;
global_log_level = cb ? level : 0;
+ pthread_mutex_lock(&(mesh->mesh_mutex));
+
//add packet to the queue
outpacketqueue_t *packet_in_queue = xzalloc(sizeof *packet_in_queue);
packet_in_queue->destination=destination;
//add packet to the queue
outpacketqueue_t *packet_in_queue = xzalloc(sizeof *packet_in_queue);
packet_in_queue->destination=destination;
packet_in_queue->len=len;
if(!meshlink_queue_push(&mesh->outpacketqueue, packet_in_queue)) {
free(packet_in_queue);
packet_in_queue->len=len;
if(!meshlink_queue_push(&mesh->outpacketqueue, packet_in_queue)) {
free(packet_in_queue);
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
return false;
}
//notify event loop
signal_trigger(&(mesh->loop),&(mesh->datafromapp));
return false;
}
//notify event loop
signal_trigger(&(mesh->loop),&(mesh->datafromapp));
+
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
return true;
}
void meshlink_send_from_queue(event_loop_t* el,meshlink_handle_t *mesh) {
return true;
}
void meshlink_send_from_queue(event_loop_t* el,meshlink_handle_t *mesh) {
+ pthread_mutex_lock(&(mesh->mesh_mutex));
+
vpn_packet_t packet;
meshlink_packethdr_t *hdr = (meshlink_packethdr_t *)packet.data;
outpacketqueue_t* p = meshlink_queue_pop(&mesh->outpacketqueue);
if(!p)
vpn_packet_t packet;
meshlink_packethdr_t *hdr = (meshlink_packethdr_t *)packet.data;
outpacketqueue_t* p = meshlink_queue_pop(&mesh->outpacketqueue);
if(!p)
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
return;
if (sizeof(meshlink_packethdr_t) + p->len > MAXSIZE) {
return;
if (sizeof(meshlink_packethdr_t) + p->len > MAXSIZE) {
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
mesh->self->in_packets++;
mesh->self->in_bytes += packet.len;
route(mesh, mesh->self, &packet);
mesh->self->in_packets++;
mesh->self->in_bytes += packet.len;
route(mesh, mesh->self, &packet);
+
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
meshlink_errno = MESHLINK_EINVAL;
return -1;
}
meshlink_errno = MESHLINK_EINVAL;
return -1;
}
+ pthread_mutex_lock(&(mesh->mesh_mutex));
node_t *n = (node_t *)destination;
node_t *n = (node_t *)destination;
- if(!n->status.reachable)
+ if(!n->status.reachable) {
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
- else if(n->mtuprobes > 30 && n->minmtu)
+
+ }
+ else if(n->mtuprobes > 30 && n->minmtu) {
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+ }
+ else {
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
}
char *meshlink_get_fingerprint(meshlink_handle_t *mesh, meshlink_node_t *node) {
}
char *meshlink_get_fingerprint(meshlink_handle_t *mesh, meshlink_node_t *node) {
meshlink_errno = MESHLINK_EINVAL;
return NULL;
}
meshlink_errno = MESHLINK_EINVAL;
return NULL;
}
+ pthread_mutex_lock(&(mesh->mesh_mutex));
node_t *n = (node_t *)node;
if(!node_read_ecdsa_public_key(mesh, n) || !n->ecdsa) {
meshlink_errno = MESHLINK_EINTERNAL;
node_t *n = (node_t *)node;
if(!node_read_ecdsa_public_key(mesh, n) || !n->ecdsa) {
meshlink_errno = MESHLINK_EINTERNAL;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
if(!fingerprint)
meshlink_errno = MESHLINK_EINTERNAL;
if(!fingerprint)
meshlink_errno = MESHLINK_EINTERNAL;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
- return (meshlink_node_t *)lookup_node(mesh, (char *)name); // TODO: make lookup_node() use const
+ meshlink_node_t *node = NULL;
+
+ pthread_mutex_lock(&(mesh->mesh_mutex));
+ node = (meshlink_node_t *)lookup_node(mesh, (char *)name); // TODO: make lookup_node() use const
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+ return node;
}
meshlink_node_t **meshlink_get_all_nodes(meshlink_handle_t *mesh, meshlink_node_t **nodes, size_t *nmemb) {
}
meshlink_node_t **meshlink_get_all_nodes(meshlink_handle_t *mesh, meshlink_node_t **nodes, size_t *nmemb) {
meshlink_node_t **result;
//lock mesh->nodes
meshlink_node_t **result;
//lock mesh->nodes
- pthread_mutex_lock(&(mesh->nodes_mutex));
+ pthread_mutex_lock(&(mesh->mesh_mutex));
*nmemb = mesh->nodes->count;
result = realloc(nodes, *nmemb * sizeof *nodes);
*nmemb = mesh->nodes->count;
result = realloc(nodes, *nmemb * sizeof *nodes);
meshlink_errno = MESHLINK_ENOMEM;
}
meshlink_errno = MESHLINK_ENOMEM;
}
- pthread_mutex_unlock(&(mesh->nodes_mutex));
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+ pthread_mutex_lock(&(mesh->mesh_mutex));
+
if(!ecdsa_sign(mesh->self->connection->ecdsa, data, len, signature)) {
meshlink_errno = MESHLINK_EINTERNAL;
if(!ecdsa_sign(mesh->self->connection->ecdsa, data, len, signature)) {
meshlink_errno = MESHLINK_EINTERNAL;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
return false;
}
*siglen = MESHLINK_SIGLEN;
return false;
}
*siglen = MESHLINK_SIGLEN;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+ pthread_mutex_lock(&(mesh->mesh_mutex));
+
+ bool rval = false;
+
struct node_t *n = (struct node_t *)source;
node_read_ecdsa_public_key(mesh, n);
if(!n->ecdsa) {
meshlink_errno = MESHLINK_EINTERNAL;
struct node_t *n = (struct node_t *)source;
node_read_ecdsa_public_key(mesh, n);
if(!n->ecdsa) {
meshlink_errno = MESHLINK_EINTERNAL;
+ rval = false;
+ } else {
+ rval = ecdsa_verify(((struct node_t *)source)->ecdsa, data, len, signature);
-
- return ecdsa_verify(((struct node_t *)source)->ecdsa, data, len, signature);
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+ return rval;
}
static bool refresh_invitation_key(meshlink_handle_t *mesh) {
char filename[PATH_MAX];
}
static bool refresh_invitation_key(meshlink_handle_t *mesh) {
char filename[PATH_MAX];
+
+ pthread_mutex_lock(&(mesh->mesh_mutex));
snprintf(filename, sizeof filename, "%s" SLASH "invitations", mesh->confbase);
if(mkdir(filename, 0700) && errno != EEXIST) {
logger(mesh, MESHLINK_DEBUG, "Could not create directory %s: %s\n", filename, strerror(errno));
meshlink_errno = MESHLINK_ESTORAGE;
snprintf(filename, sizeof filename, "%s" SLASH "invitations", mesh->confbase);
if(mkdir(filename, 0700) && errno != EEXIST) {
logger(mesh, MESHLINK_DEBUG, "Could not create directory %s: %s\n", filename, strerror(errno));
meshlink_errno = MESHLINK_ESTORAGE;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
if(!dir) {
logger(mesh, MESHLINK_DEBUG, "Could not read directory %s: %s\n", filename, strerror(errno));
meshlink_errno = MESHLINK_ESTORAGE;
if(!dir) {
logger(mesh, MESHLINK_DEBUG, "Could not read directory %s: %s\n", filename, strerror(errno));
meshlink_errno = MESHLINK_ESTORAGE;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
logger(mesh, MESHLINK_DEBUG, "Error while reading directory %s: %s\n", filename, strerror(errno));
closedir(dir);
meshlink_errno = MESHLINK_ESTORAGE;
logger(mesh, MESHLINK_DEBUG, "Error while reading directory %s: %s\n", filename, strerror(errno));
closedir(dir);
meshlink_errno = MESHLINK_ESTORAGE;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
- if(mesh->invitation_key)
+ if(mesh->invitation_key) {
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
// Create a new key if necessary.
FILE *f = fopen(filename, "r");
// Create a new key if necessary.
FILE *f = fopen(filename, "r");
if(errno != ENOENT) {
logger(mesh, MESHLINK_DEBUG, "Could not read %s: %s\n", filename, strerror(errno));
meshlink_errno = MESHLINK_ESTORAGE;
if(errno != ENOENT) {
logger(mesh, MESHLINK_DEBUG, "Could not read %s: %s\n", filename, strerror(errno));
meshlink_errno = MESHLINK_ESTORAGE;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
if(!mesh->invitation_key) {
logger(mesh, MESHLINK_DEBUG, "Could not generate a new key!\n");
meshlink_errno = MESHLINK_EINTERNAL;
if(!mesh->invitation_key) {
logger(mesh, MESHLINK_DEBUG, "Could not generate a new key!\n");
meshlink_errno = MESHLINK_EINTERNAL;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
return false;
}
f = fopen(filename, "w");
if(!f) {
logger(mesh, MESHLINK_DEBUG, "Could not write %s: %s\n", filename, strerror(errno));
meshlink_errno = MESHLINK_ESTORAGE;
return false;
}
f = fopen(filename, "w");
if(!f) {
logger(mesh, MESHLINK_DEBUG, "Could not write %s: %s\n", filename, strerror(errno));
meshlink_errno = MESHLINK_ESTORAGE;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
return false;
}
chmod(filename, 0600);
return false;
}
chmod(filename, 0600);
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
return mesh->invitation_key;
}
return mesh->invitation_key;
}
meshlink_errno = MESHLINK_EINVAL;
return false;
}
meshlink_errno = MESHLINK_EINVAL;
return false;
}
+
+ bool rval = false;
+
+ pthread_mutex_lock(&(mesh->mesh_mutex));
for(const char *p = address; *p; p++) {
if(isalnum(*p) || *p == '-' || *p == '.' || *p == ':')
continue;
logger(mesh, MESHLINK_DEBUG, "Invalid character in address: %s\n", address);
meshlink_errno = MESHLINK_EINVAL;
for(const char *p = address; *p; p++) {
if(isalnum(*p) || *p == '-' || *p == '.' || *p == ':')
continue;
logger(mesh, MESHLINK_DEBUG, "Invalid character in address: %s\n", address);
meshlink_errno = MESHLINK_EINVAL;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
- return append_config_file(mesh, mesh->self->name, "Address", address);
+ rval = append_config_file(mesh, mesh->self->name, "Address", address);
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+ return rval;
}
char *meshlink_invite(meshlink_handle_t *mesh, const char *name) {
}
char *meshlink_invite(meshlink_handle_t *mesh, const char *name) {
meshlink_errno = MESHLINK_EINVAL;
return NULL;
}
meshlink_errno = MESHLINK_EINVAL;
return NULL;
}
+
+ pthread_mutex_lock(&(mesh->mesh_mutex));
// Check validity of the new node's name
if(!check_id(name)) {
logger(mesh, MESHLINK_DEBUG, "Invalid name for node.\n");
meshlink_errno = MESHLINK_EINVAL;
// Check validity of the new node's name
if(!check_id(name)) {
logger(mesh, MESHLINK_DEBUG, "Invalid name for node.\n");
meshlink_errno = MESHLINK_EINVAL;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
if(!access(filename, F_OK)) {
logger(mesh, MESHLINK_DEBUG, "A host config file for %s already exists!\n", name);
meshlink_errno = MESHLINK_EEXIST;
if(!access(filename, F_OK)) {
logger(mesh, MESHLINK_DEBUG, "A host config file for %s already exists!\n", name);
meshlink_errno = MESHLINK_EEXIST;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
if(meshlink_get_node(mesh, name)) {
logger(mesh, MESHLINK_DEBUG, "A node with name %s is already known!\n", name);
meshlink_errno = MESHLINK_EEXIST;
if(meshlink_get_node(mesh, name)) {
logger(mesh, MESHLINK_DEBUG, "A node with name %s is already known!\n", name);
meshlink_errno = MESHLINK_EEXIST;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
if(!address) {
logger(mesh, MESHLINK_DEBUG, "No Address known for ourselves!\n");
meshlink_errno = MESHLINK_ERESOLV;
if(!address) {
logger(mesh, MESHLINK_DEBUG, "No Address known for ourselves!\n");
meshlink_errno = MESHLINK_ERESOLV;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
return NULL;
}
if(!refresh_invitation_key(mesh)) {
meshlink_errno = MESHLINK_EINTERNAL;
return NULL;
}
if(!refresh_invitation_key(mesh)) {
meshlink_errno = MESHLINK_EINTERNAL;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
if(!ifd) {
logger(mesh, MESHLINK_DEBUG, "Could not create invitation file %s: %s\n", filename, strerror(errno));
meshlink_errno = MESHLINK_ESTORAGE;
if(!ifd) {
logger(mesh, MESHLINK_DEBUG, "Could not create invitation file %s: %s\n", filename, strerror(errno));
meshlink_errno = MESHLINK_ESTORAGE;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
return NULL;
}
FILE *f = fdopen(ifd, "w");
return NULL;
}
FILE *f = fdopen(ifd, "w");
} else {
logger(mesh, MESHLINK_DEBUG, "Could not create %s: %s\n", filename, strerror(errno));
meshlink_errno = MESHLINK_ESTORAGE;
} else {
logger(mesh, MESHLINK_DEBUG, "Could not create %s: %s\n", filename, strerror(errno));
meshlink_errno = MESHLINK_ESTORAGE;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
xasprintf(&url, "%s/%s%s", address, hash, cookie);
free(address);
xasprintf(&url, "%s/%s%s", address, hash, cookie);
free(address);
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
meshlink_errno = MESHLINK_EINVAL;
return false;
}
meshlink_errno = MESHLINK_EINVAL;
return false;
}
+
+ pthread_mutex_lock(&(mesh->mesh_mutex));
//TODO: think of a better name for this variable, or of a different way to tokenize the invitation URL.
char copy[strlen(invitation) + 1];
//TODO: think of a better name for this variable, or of a different way to tokenize the invitation URL.
char copy[strlen(invitation) + 1];
ecdsa_t *key = ecdsa_generate();
if(!key) {
meshlink_errno = MESHLINK_EINTERNAL;
ecdsa_t *key = ecdsa_generate();
if(!key) {
meshlink_errno = MESHLINK_EINTERNAL;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
struct addrinfo *ai = str2addrinfo(address, port, SOCK_STREAM);
if(!ai) {
meshlink_errno = MESHLINK_ERESOLV;
struct addrinfo *ai = str2addrinfo(address, port, SOCK_STREAM);
if(!ai) {
meshlink_errno = MESHLINK_ERESOLV;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
logger(mesh, MESHLINK_DEBUG, "Could not open socket: %s\n", strerror(errno));
freeaddrinfo(ai);
meshlink_errno = MESHLINK_ENETWORK;
logger(mesh, MESHLINK_DEBUG, "Could not open socket: %s\n", strerror(errno));
freeaddrinfo(ai);
meshlink_errno = MESHLINK_ENETWORK;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
closesocket(mesh->sock);
freeaddrinfo(ai);
meshlink_errno = MESHLINK_ENETWORK;
closesocket(mesh->sock);
freeaddrinfo(ai);
meshlink_errno = MESHLINK_ENETWORK;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
logger(mesh, MESHLINK_DEBUG, "Error sending request to %s port %s: %s\n", address, port, strerror(errno));
closesocket(mesh->sock);
meshlink_errno = MESHLINK_ENETWORK;
logger(mesh, MESHLINK_DEBUG, "Error sending request to %s port %s: %s\n", address, port, strerror(errno));
closesocket(mesh->sock);
meshlink_errno = MESHLINK_ENETWORK;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
logger(mesh, MESHLINK_DEBUG, "Cannot read greeting from peer\n");
closesocket(mesh->sock);
meshlink_errno = MESHLINK_ENETWORK;
logger(mesh, MESHLINK_DEBUG, "Cannot read greeting from peer\n");
closesocket(mesh->sock);
meshlink_errno = MESHLINK_ENETWORK;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
if(sha512(fingerprint, strlen(fingerprint), hishash)) {
logger(mesh, MESHLINK_DEBUG, "Could not create hash\n%s\n", mesh->line + 2);
meshlink_errno = MESHLINK_EINTERNAL;
if(sha512(fingerprint, strlen(fingerprint), hishash)) {
logger(mesh, MESHLINK_DEBUG, "Could not create hash\n%s\n", mesh->line + 2);
meshlink_errno = MESHLINK_EINTERNAL;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
return false;
}
if(memcmp(hishash, mesh->hash, 18)) {
logger(mesh, MESHLINK_DEBUG, "Peer has an invalid key!\n%s\n", mesh->line + 2);
meshlink_errno = MESHLINK_EPEER;
return false;
}
if(memcmp(hishash, mesh->hash, 18)) {
logger(mesh, MESHLINK_DEBUG, "Peer has an invalid key!\n%s\n", mesh->line + 2);
meshlink_errno = MESHLINK_EPEER;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
ecdsa_t *hiskey = ecdsa_set_base64_public_key(fingerprint);
if(!hiskey) {
meshlink_errno = MESHLINK_EINTERNAL;
ecdsa_t *hiskey = ecdsa_set_base64_public_key(fingerprint);
if(!hiskey) {
meshlink_errno = MESHLINK_EINTERNAL;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
return false;
}
// Start an SPTPS session
if(!sptps_start(&mesh->sptps, mesh, true, false, key, hiskey, "meshlink invitation", 15, invitation_send, invitation_receive)) {
meshlink_errno = MESHLINK_EINTERNAL;
return false;
}
// Start an SPTPS session
if(!sptps_start(&mesh->sptps, mesh, true, false, key, hiskey, "meshlink invitation", 15, invitation_send, invitation_receive)) {
meshlink_errno = MESHLINK_EINTERNAL;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
return false;
}
// Feed rest of input buffer to SPTPS
if(!sptps_receive_data(&mesh->sptps, mesh->buffer, mesh->blen)) {
meshlink_errno = MESHLINK_EPEER;
return false;
}
// Feed rest of input buffer to SPTPS
if(!sptps_receive_data(&mesh->sptps, mesh->buffer, mesh->blen)) {
meshlink_errno = MESHLINK_EPEER;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
continue;
logger(mesh, MESHLINK_DEBUG, "Error reading data from %s port %s: %s\n", address, port, strerror(errno));
meshlink_errno = MESHLINK_ENETWORK;
continue;
logger(mesh, MESHLINK_DEBUG, "Error reading data from %s port %s: %s\n", address, port, strerror(errno));
meshlink_errno = MESHLINK_ENETWORK;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
return false;
}
if(!sptps_receive_data(&mesh->sptps, mesh->line, len)) {
meshlink_errno = MESHLINK_EPEER;
return false;
}
if(!sptps_receive_data(&mesh->sptps, mesh->line, len)) {
meshlink_errno = MESHLINK_EPEER;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
if(!mesh->success) {
logger(mesh, MESHLINK_DEBUG, "Connection closed by peer, invitation cancelled.\n");
meshlink_errno = MESHLINK_EPEER;
if(!mesh->success) {
logger(mesh, MESHLINK_DEBUG, "Connection closed by peer, invitation cancelled.\n");
meshlink_errno = MESHLINK_EPEER;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
return true;
invalid:
logger(mesh, MESHLINK_DEBUG, "Invalid invitation URL or you are already connected to a Mesh ?\n");
meshlink_errno = MESHLINK_EINVAL;
return true;
invalid:
logger(mesh, MESHLINK_DEBUG, "Invalid invitation URL or you are already connected to a Mesh ?\n");
meshlink_errno = MESHLINK_EINVAL;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+ pthread_mutex_lock(&(mesh->mesh_mutex));
+
char filename[PATH_MAX];
snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, mesh->self->name);
FILE *f = fopen(filename, "r");
if(!f) {
logger(mesh, MESHLINK_DEBUG, "Could not open %s: %s\n", filename, strerror(errno));
meshlink_errno = MESHLINK_ESTORAGE;
char filename[PATH_MAX];
snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, mesh->self->name);
FILE *f = fopen(filename, "r");
if(!f) {
logger(mesh, MESHLINK_DEBUG, "Could not open %s: %s\n", filename, strerror(errno));
meshlink_errno = MESHLINK_ESTORAGE;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
logger(mesh, MESHLINK_DEBUG, "Error reading from %s: %s\n", filename, strerror(errno));
fclose(f);
meshlink_errno = MESHLINK_ESTORAGE;
logger(mesh, MESHLINK_DEBUG, "Error reading from %s: %s\n", filename, strerror(errno));
fclose(f);
meshlink_errno = MESHLINK_ESTORAGE;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
return NULL;
}
fclose(f);
buf[len - 1] = 0;
return NULL;
}
fclose(f);
buf[len - 1] = 0;
+
+ pthread_mutex_lock(&(mesh->mesh_mutex));
meshlink_errno = MESHLINK_EINVAL;
return false;
}
meshlink_errno = MESHLINK_EINVAL;
return false;
}
+
+ pthread_mutex_lock(&(mesh->mesh_mutex));
if(strncmp(data, "Name = ", 7)) {
logger(mesh, MESHLINK_DEBUG, "Invalid data\n");
meshlink_errno = MESHLINK_EPEER;
if(strncmp(data, "Name = ", 7)) {
logger(mesh, MESHLINK_DEBUG, "Invalid data\n");
meshlink_errno = MESHLINK_EPEER;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
if(!end) {
logger(mesh, MESHLINK_DEBUG, "Invalid data\n");
meshlink_errno = MESHLINK_EPEER;
if(!end) {
logger(mesh, MESHLINK_DEBUG, "Invalid data\n");
meshlink_errno = MESHLINK_EPEER;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
if(!check_id(name)) {
logger(mesh, MESHLINK_DEBUG, "Invalid Name\n");
meshlink_errno = MESHLINK_EPEER;
if(!check_id(name)) {
logger(mesh, MESHLINK_DEBUG, "Invalid Name\n");
meshlink_errno = MESHLINK_EPEER;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
if(!access(filename, F_OK)) {
logger(mesh, MESHLINK_DEBUG, "File %s already exists, not importing\n", filename);
meshlink_errno = MESHLINK_EEXIST;
if(!access(filename, F_OK)) {
logger(mesh, MESHLINK_DEBUG, "File %s already exists, not importing\n", filename);
meshlink_errno = MESHLINK_EEXIST;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
return false;
}
if(errno != ENOENT) {
logger(mesh, MESHLINK_DEBUG, "Error accessing %s: %s\n", filename, strerror(errno));
meshlink_errno = MESHLINK_ESTORAGE;
return false;
}
if(errno != ENOENT) {
logger(mesh, MESHLINK_DEBUG, "Error accessing %s: %s\n", filename, strerror(errno));
meshlink_errno = MESHLINK_ESTORAGE;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
if(!f) {
logger(mesh, MESHLINK_DEBUG, "Could not create %s: %s\n", filename, strerror(errno));
meshlink_errno = MESHLINK_ESTORAGE;
if(!f) {
logger(mesh, MESHLINK_DEBUG, "Could not create %s: %s\n", filename, strerror(errno));
meshlink_errno = MESHLINK_ESTORAGE;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+ pthread_mutex_lock(&(mesh->mesh_mutex));
+
node_t *n;
n = (node_t*)node;
n->status.blacklisted=true;
node_t *n;
n = (node_t*)node;
n->status.blacklisted=true;
//Make blacklisting persistent in the config file
append_config_file(mesh, n->name, "blacklisted", "yes");
//Make blacklisting persistent in the config file
append_config_file(mesh, n->name, "blacklisted", "yes");
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+ pthread_mutex_lock(&(mesh->mesh_mutex));
+
node_t *n = (node_t *)node;
n->status.blacklisted = false;
//TODO: remove blacklisted = yes from the config file
node_t *n = (node_t *)node;
n->status.blacklisted = false;
//TODO: remove blacklisted = yes from the config file
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
if(!mesh || !node || !addr)
return;
if(!mesh || !node || !addr)
return;
+ pthread_mutex_lock(&(mesh->mesh_mutex));
+
char *host = NULL, *port = NULL, *str = NULL;
sockaddr2str((const sockaddr_t *)addr, &host, &port);
char *host = NULL, *port = NULL, *str = NULL;
sockaddr2str((const sockaddr_t *)addr, &host, &port);
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
// @TODO do we want to fire off a connection attempt right away?
}
// @TODO do we want to fire off a connection attempt right away?
}
pthread_t thread;
bool threadstarted;
pthread_mutex_t outpacketqueue_mutex;
pthread_t thread;
bool threadstarted;
pthread_mutex_t outpacketqueue_mutex;
- pthread_mutex_t nodes_mutex;
+ pthread_mutex_t mesh_mutex;
event_loop_t loop;
listen_socket_t listen_socket[MAXSOCKETS];
int listen_sockets;
event_loop_t loop;
listen_socket_t listen_socket[MAXSOCKETS];
int listen_sockets;
mesh->datafromapp.signum = 0;
signal_add(&(mesh->loop),&(mesh->datafromapp), (signal_cb_t)meshlink_send_from_queue,mesh, mesh->datafromapp.signum);
mesh->datafromapp.signum = 0;
signal_add(&(mesh->loop),&(mesh->datafromapp), (signal_cb_t)meshlink_send_from_queue,mesh, mesh->datafromapp.signum);
- if(!event_loop_run(&mesh->loop)) {
+ if(!event_loop_run(&(mesh->loop), &(mesh->mesh_mutex))) {
logger(mesh, MESHLINK_ERROR, "Error while waiting for input: %s", strerror(errno));
return 1;
}
logger(mesh, MESHLINK_ERROR, "Error while waiting for input: %s", strerror(errno));
return 1;
}
}
void init_nodes(meshlink_handle_t *mesh) {
}
void init_nodes(meshlink_handle_t *mesh) {
- pthread_mutex_lock(&(mesh->nodes_mutex));
mesh->nodes = splay_alloc_tree((splay_compare_t) node_compare, (splay_action_t) free_node);
mesh->node_udp_cache = hash_alloc(0x100, sizeof(sockaddr_t));
mesh->nodes = splay_alloc_tree((splay_compare_t) node_compare, (splay_action_t) free_node);
mesh->node_udp_cache = hash_alloc(0x100, sizeof(sockaddr_t));
- pthread_mutex_unlock(&(mesh->nodes_mutex));
}
void exit_nodes(meshlink_handle_t *mesh) {
}
void exit_nodes(meshlink_handle_t *mesh) {
- pthread_mutex_lock(&(mesh->nodes_mutex));
if(mesh->node_udp_cache)
hash_free(mesh->node_udp_cache);
if(mesh->nodes)
splay_delete_tree(mesh->nodes);
mesh->node_udp_cache = NULL;
mesh->nodes = NULL;
if(mesh->node_udp_cache)
hash_free(mesh->node_udp_cache);
if(mesh->nodes)
splay_delete_tree(mesh->nodes);
mesh->node_udp_cache = NULL;
mesh->nodes = NULL;
- pthread_mutex_unlock(&(mesh->nodes_mutex));
}
node_t *new_node(void) {
}
node_t *new_node(void) {
}
void node_add(meshlink_handle_t *mesh, node_t *n) {
}
void node_add(meshlink_handle_t *mesh, node_t *n) {
- pthread_mutex_lock(&(mesh->nodes_mutex));
n->mesh = mesh;
splay_insert(mesh->nodes, n);
n->mesh = mesh;
splay_insert(mesh->nodes, n);
- pthread_mutex_unlock(&(mesh->nodes_mutex));
}
void node_del(meshlink_handle_t *mesh, node_t *n) {
}
void node_del(meshlink_handle_t *mesh, node_t *n) {
- pthread_mutex_lock(&(mesh->nodes_mutex));
timeout_del(&mesh->loop, &n->mtutimeout);
for splay_each(edge_t, e, n->edge_tree)
edge_del(mesh, e);
splay_delete(mesh->nodes, n);
timeout_del(&mesh->loop, &n->mtutimeout);
for splay_each(edge_t, e, n->edge_tree)
edge_del(mesh, e);
splay_delete(mesh->nodes, n);
- pthread_mutex_unlock(&(mesh->nodes_mutex));
}
node_t *lookup_node(meshlink_handle_t *mesh, const char *name) {
const node_t n = {.name = (char *)name};
node_t *result;
}
node_t *lookup_node(meshlink_handle_t *mesh, const char *name) {
const node_t n = {.name = (char *)name};
node_t *result;
- pthread_mutex_lock(&(mesh->nodes_mutex));
result = splay_search(mesh->nodes, &n);
result = splay_search(mesh->nodes, &n);
- pthread_mutex_unlock(&(mesh->nodes_mutex));