]> git.meshlink.io Git - meshlink-tiny/blob - src/meshlink.c
Remove support for submeshes.
[meshlink-tiny] / src / meshlink.c
1 /*
2     meshlink.c -- Implementation of the MeshLink API.
3     Copyright (C) 2014-2021 Guus Sliepen <guus@meshlink.io>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License along
16     with this program; if not, write to the Free Software Foundation, Inc.,
17     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "system.h"
21 #include <pthread.h>
22
23 #include "crypto.h"
24 #include "ecdsagen.h"
25 #include "logger.h"
26 #include "meshlink_internal.h"
27 #include "net.h"
28 #include "netutl.h"
29 #include "node.h"
30 #include "packmsg.h"
31 #include "prf.h"
32 #include "protocol.h"
33 #include "route.h"
34 #include "sockaddr.h"
35 #include "utils.h"
36 #include "xalloc.h"
37 #include "ed25519/sha512.h"
38 #include "devtools.h"
39
40 #ifndef MSG_NOSIGNAL
41 #define MSG_NOSIGNAL 0
42 #endif
43 __thread meshlink_errno_t meshlink_errno;
44 meshlink_log_cb_t global_log_cb;
45 meshlink_log_level_t global_log_level;
46
47 typedef bool (*search_node_by_condition_t)(const node_t *, const void *);
48
49 static int rstrip(char *value) {
50         int len = strlen(value);
51
52         while(len && strchr("\t\r\n ", value[len - 1])) {
53                 value[--len] = 0;
54         }
55
56         return len;
57 }
58
59 static bool is_valid_hostname(const char *hostname) {
60         if(!*hostname) {
61                 return false;
62         }
63
64         for(const char *p = hostname; *p; p++) {
65                 if(!(isalnum(*p) || *p == '-' || *p == '.' || *p == ':')) {
66                         return false;
67                 }
68         }
69
70         return true;
71 }
72
73 static bool is_valid_port(const char *port) {
74         if(!*port) {
75                 return false;
76         }
77
78         if(isdigit(*port)) {
79                 char *end;
80                 unsigned long int result = strtoul(port, &end, 10);
81                 return result && result < 65536 && !*end;
82         }
83
84         for(const char *p = port; *p; p++) {
85                 if(!(isalnum(*p) || *p == '-')) {
86                         return false;
87                 }
88         }
89
90         return true;
91 }
92
93 static void set_timeout(int sock, int timeout) {
94 #ifdef _WIN32
95         DWORD tv = timeout;
96 #else
97         struct timeval tv;
98         tv.tv_sec = timeout / 1000;
99         tv.tv_usec = (timeout - tv.tv_sec * 1000) * 1000;
100 #endif
101         setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
102         setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
103 }
104
105 struct socket_in_netns_params {
106         int domain;
107         int type;
108         int protocol;
109         int netns;
110         int fd;
111 };
112
113 #ifdef HAVE_SETNS
114 static void *socket_in_netns_thread(void *arg) {
115         struct socket_in_netns_params *params = arg;
116
117         if(setns(params->netns, CLONE_NEWNET) == -1) {
118                 meshlink_errno = MESHLINK_EINVAL;
119                 return NULL;
120         }
121
122         params->fd = socket(params->domain, params->type, params->protocol);
123
124         return NULL;
125 }
126 #endif // HAVE_SETNS
127
128 static int socket_in_netns(int domain, int type, int protocol, int netns) {
129         if(netns == -1) {
130                 return socket(domain, type, protocol);
131         }
132
133 #ifdef HAVE_SETNS
134         struct socket_in_netns_params params = {domain, type, protocol, netns, -1};
135
136         pthread_t thr;
137
138         if(pthread_create(&thr, NULL, socket_in_netns_thread, &params) == 0) {
139                 if(pthread_join(thr, NULL) != 0) {
140                         abort();
141                 }
142         }
143
144         return params.fd;
145 #else
146         return -1;
147 #endif // HAVE_SETNS
148
149 }
150
151 static bool write_main_config_files(meshlink_handle_t *mesh) {
152         if(!mesh->confbase) {
153                 return true;
154         }
155
156         uint8_t buf[4096];
157
158         /* Write the main config file */
159         packmsg_output_t out = {buf, sizeof buf};
160
161         packmsg_add_uint32(&out, MESHLINK_CONFIG_VERSION);
162         packmsg_add_str(&out, mesh->name);
163         packmsg_add_bin(&out, ecdsa_get_private_key(mesh->private_key), 96);
164         packmsg_add_nil(&out); // Invitation keys are not supported
165         packmsg_add_uint16(&out, atoi(mesh->myport));
166
167         if(!packmsg_output_ok(&out)) {
168                 return false;
169         }
170
171         config_t config = {buf, packmsg_output_size(&out, buf)};
172
173         if(!main_config_write(mesh, "current", &config, mesh->config_key)) {
174                 return false;
175         }
176
177         /* Write our own host config file */
178         if(!node_write_config(mesh, mesh->self, true)) {
179                 return false;
180         }
181
182         return true;
183 }
184
185 typedef struct {
186         meshlink_handle_t *mesh;
187         int sock;
188         char cookie[18 + 32];
189         char hash[18];
190         bool success;
191         sptps_t sptps;
192         char *data;
193         size_t thedatalen;
194         size_t blen;
195         char line[4096];
196         char buffer[4096];
197 } join_state_t;
198
199 static bool finalize_join(join_state_t *state, const void *buf, uint16_t len) {
200         meshlink_handle_t *mesh = state->mesh;
201         packmsg_input_t in = {buf, len};
202         uint32_t version = packmsg_get_uint32(&in);
203
204         if(version != MESHLINK_INVITATION_VERSION) {
205                 logger(mesh, MESHLINK_ERROR, "Invalid invitation version!\n");
206                 return false;
207         }
208
209         char *name = packmsg_get_str_dup(&in);
210         packmsg_skip_element(&in); // submesh_name
211         dev_class_t devclass = packmsg_get_int32(&in);
212         uint32_t count = packmsg_get_array(&in);
213
214         if(!name || !check_id(name)) {
215                 logger(mesh, MESHLINK_DEBUG, "No valid Name found in invitation!\n");
216                 free(name);
217                 return false;
218         }
219
220         if(!count) {
221                 logger(mesh, MESHLINK_ERROR, "Incomplete invitation file!\n");
222                 free(name);
223                 return false;
224         }
225
226         free(mesh->name);
227         free(mesh->self->name);
228         mesh->name = name;
229         mesh->self->name = xstrdup(name);
230         mesh->self->devclass = devclass == DEV_CLASS_UNKNOWN ? mesh->devclass : devclass;
231
232         // Initialize configuration directory
233         if(!config_init(mesh, "current")) {
234                 return false;
235         }
236
237         if(!write_main_config_files(mesh)) {
238                 return false;
239         }
240
241         // Write host config files
242         for(uint32_t i = 0; i < count; i++) {
243                 const void *data;
244                 uint32_t data_len = packmsg_get_bin_raw(&in, &data);
245
246                 if(!data_len) {
247                         logger(mesh, MESHLINK_ERROR, "Incomplete invitation file!\n");
248                         return false;
249                 }
250
251                 packmsg_input_t in2 = {data, data_len};
252                 uint32_t version2 = packmsg_get_uint32(&in2);
253                 char *name2 = packmsg_get_str_dup(&in2);
254
255                 if(!packmsg_input_ok(&in2) || version2 != MESHLINK_CONFIG_VERSION || !check_id(name2)) {
256                         free(name2);
257                         packmsg_input_invalidate(&in);
258                         break;
259                 }
260
261                 if(!check_id(name2)) {
262                         free(name2);
263                         break;
264                 }
265
266                 if(!strcmp(name2, mesh->name)) {
267                         logger(mesh, MESHLINK_ERROR, "Secondary chunk would overwrite our own host config file.\n");
268                         free(name2);
269                         meshlink_errno = MESHLINK_EPEER;
270                         return false;
271                 }
272
273                 node_t *n = new_node();
274                 n->name = name2;
275
276                 config_t config = {data, data_len};
277
278                 if(!node_read_from_config(mesh, n, &config)) {
279                         free_node(n);
280                         logger(mesh, MESHLINK_ERROR, "Invalid host config file in invitation file!\n");
281                         meshlink_errno = MESHLINK_EPEER;
282                         return false;
283                 }
284
285                 if(i == 0) {
286                         /* The first host config file is of the inviter itself;
287                          * remember the address we are currently using for the invitation connection.
288                          */
289                         sockaddr_t sa;
290                         socklen_t salen = sizeof(sa);
291
292                         if(getpeername(state->sock, &sa.sa, &salen) == 0) {
293                                 node_add_recent_address(mesh, n, &sa);
294                         }
295                 }
296
297                 if(!node_write_config(mesh, n, true)) {
298                         free_node(n);
299                         return false;
300                 }
301
302                 node_add(mesh, n);
303         }
304
305         /* Ensure the configuration directory metadata is on disk */
306         if(!config_sync(mesh, "current") || (mesh->confbase && !sync_path(mesh->confbase))) {
307                 return false;
308         }
309
310         if(!mesh->inviter_commits_first) {
311                 devtool_set_inviter_commits_first(false);
312         }
313
314         sptps_send_record(&state->sptps, 1, ecdsa_get_public_key(mesh->private_key), 32);
315
316         logger(mesh, MESHLINK_DEBUG, "Configuration stored in: %s\n", mesh->confbase);
317
318         return true;
319 }
320
321 static bool invitation_send(void *handle, uint8_t type, const void *data, size_t len) {
322         (void)type;
323         join_state_t *state = handle;
324         const char *ptr = data;
325
326         while(len) {
327                 int result = send(state->sock, ptr, len, 0);
328
329                 if(result == -1 && errno == EINTR) {
330                         continue;
331                 } else if(result <= 0) {
332                         return false;
333                 }
334
335                 ptr += result;
336                 len -= result;
337         }
338
339         return true;
340 }
341
342 static bool invitation_receive(void *handle, uint8_t type, const void *msg, uint16_t len) {
343         join_state_t *state = handle;
344         meshlink_handle_t *mesh = state->mesh;
345
346         if(mesh->inviter_commits_first) {
347                 switch(type) {
348                 case SPTPS_HANDSHAKE:
349                         return sptps_send_record(&state->sptps, 2, state->cookie, 18 + 32);
350
351                 case 1:
352                         break;
353
354                 case 0:
355                         if(!finalize_join(state, msg, len)) {
356                                 return false;
357                         }
358
359                         logger(mesh, MESHLINK_DEBUG, "Invitation successfully accepted.\n");
360                         shutdown(state->sock, SHUT_RDWR);
361                         state->success = true;
362                         break;
363
364                 default:
365                         return false;
366                 }
367         } else {
368                 switch(type) {
369                 case SPTPS_HANDSHAKE:
370                         return sptps_send_record(&state->sptps, 0, state->cookie, 18);
371
372                 case 0:
373                         return finalize_join(state, msg, len);
374
375                 case 1:
376                         logger(mesh, MESHLINK_DEBUG, "Invitation successfully accepted.\n");
377                         shutdown(state->sock, SHUT_RDWR);
378                         state->success = true;
379                         break;
380
381                 default:
382                         return false;
383                 }
384         }
385
386         return true;
387 }
388
389 static bool recvline(join_state_t *state) {
390         char *newline = NULL;
391
392         while(!(newline = memchr(state->buffer, '\n', state->blen))) {
393                 int result = recv(state->sock, state->buffer + state->blen, sizeof(state)->buffer - state->blen, 0);
394
395                 if(result == -1 && errno == EINTR) {
396                         continue;
397                 } else if(result <= 0) {
398                         return false;
399                 }
400
401                 state->blen += result;
402         }
403
404         if((size_t)(newline - state->buffer) >= sizeof(state->line)) {
405                 return false;
406         }
407
408         size_t len = newline - state->buffer;
409
410         memcpy(state->line, state->buffer, len);
411         state->line[len] = 0;
412         memmove(state->buffer, newline + 1, state->blen - len - 1);
413         state->blen -= len + 1;
414
415         return true;
416 }
417
418 static bool sendline(int fd, const char *format, ...) {
419         char buffer[4096];
420         char *p = buffer;
421         int blen = 0;
422         va_list ap;
423
424         va_start(ap, format);
425         blen = vsnprintf(buffer, sizeof(buffer), format, ap);
426         va_end(ap);
427
428         if(blen < 1 || (size_t)blen >= sizeof(buffer)) {
429                 return false;
430         }
431
432         buffer[blen] = '\n';
433         blen++;
434
435         while(blen) {
436                 int result = send(fd, p, blen, MSG_NOSIGNAL);
437
438                 if(result == -1 && errno == EINTR) {
439                         continue;
440                 } else if(result <= 0) {
441                         return false;
442                 }
443
444                 p += result;
445                 blen -= result;
446         }
447
448         return true;
449 }
450
451 static const char *errstr[] = {
452         [MESHLINK_OK] = "No error",
453         [MESHLINK_EINVAL] = "Invalid argument",
454         [MESHLINK_ENOMEM] = "Out of memory",
455         [MESHLINK_ENOENT] = "No such node",
456         [MESHLINK_EEXIST] = "Node already exists",
457         [MESHLINK_EINTERNAL] = "Internal error",
458         [MESHLINK_ERESOLV] = "Could not resolve hostname",
459         [MESHLINK_ESTORAGE] = "Storage error",
460         [MESHLINK_ENETWORK] = "Network error",
461         [MESHLINK_EPEER] = "Error communicating with peer",
462         [MESHLINK_ENOTSUP] = "Operation not supported",
463         [MESHLINK_EBUSY] = "MeshLink instance already in use",
464         [MESHLINK_EBLACKLISTED] = "Node is blacklisted",
465 };
466
467 const char *meshlink_strerror(meshlink_errno_t err) {
468         if((int)err < 0 || err >= sizeof(errstr) / sizeof(*errstr)) {
469                 return "Invalid error code";
470         }
471
472         return errstr[err];
473 }
474
475 static bool ecdsa_keygen(meshlink_handle_t *mesh) {
476         logger(mesh, MESHLINK_DEBUG, "Generating ECDSA keypair:\n");
477
478         mesh->private_key = ecdsa_generate();
479
480         if(!mesh->private_key) {
481                 logger(mesh, MESHLINK_ERROR, "Error during key generation!\n");
482                 meshlink_errno = MESHLINK_EINTERNAL;
483                 return false;
484         }
485
486         logger(mesh, MESHLINK_DEBUG, "Done.\n");
487
488         return true;
489 }
490
491 static bool timespec_lt(const struct timespec *a, const struct timespec *b) {
492         if(a->tv_sec == b->tv_sec) {
493                 return a->tv_nsec < b->tv_nsec;
494         } else {
495                 return a->tv_sec < b->tv_sec;
496         }
497 }
498
499 static struct timespec idle(event_loop_t *loop, void *data) {
500         (void)loop;
501         meshlink_handle_t *mesh = data;
502         struct timespec t, tmin = {3600, 0};
503
504         for splay_each(node_t, n, mesh->nodes) {
505                 if(!n->utcp) {
506                         continue;
507                 }
508
509                 t = utcp_timeout(n->utcp);
510
511                 if(timespec_lt(&t, &tmin)) {
512                         tmin = t;
513                 }
514         }
515
516         return tmin;
517 }
518
519 static bool meshlink_setup(meshlink_handle_t *mesh) {
520         if(!config_destroy(mesh->confbase, "new")) {
521                 logger(mesh, MESHLINK_ERROR, "Could not delete configuration in %s/new: %s\n", mesh->confbase, strerror(errno));
522                 meshlink_errno = MESHLINK_ESTORAGE;
523                 return false;
524         }
525
526         if(!config_destroy(mesh->confbase, "old")) {
527                 logger(mesh, MESHLINK_ERROR, "Could not delete configuration in %s/old: %s\n", mesh->confbase, strerror(errno));
528                 meshlink_errno = MESHLINK_ESTORAGE;
529                 return false;
530         }
531
532         if(!config_init(mesh, "current")) {
533                 logger(mesh, MESHLINK_ERROR, "Could not set up configuration in %s/current: %s\n", mesh->confbase, strerror(errno));
534                 meshlink_errno = MESHLINK_ESTORAGE;
535                 return false;
536         }
537
538         if(!ecdsa_keygen(mesh)) {
539                 meshlink_errno = MESHLINK_EINTERNAL;
540                 return false;
541         }
542
543         mesh->myport = xstrdup("0");
544
545         /* Create a node for ourself */
546
547         mesh->self = new_node();
548         mesh->self->name = xstrdup(mesh->name);
549         mesh->self->devclass = mesh->devclass;
550         mesh->self->ecdsa = ecdsa_set_public_key(ecdsa_get_public_key(mesh->private_key));
551         mesh->self->session_id = mesh->session_id;
552
553         if(!write_main_config_files(mesh)) {
554                 logger(mesh, MESHLINK_ERROR, "Could not write main config files into %s/current: %s\n", mesh->confbase, strerror(errno));
555                 meshlink_errno = MESHLINK_ESTORAGE;
556                 return false;
557         }
558
559         /* Ensure the configuration directory metadata is on disk */
560         if(!config_sync(mesh, "current")) {
561                 return false;
562         }
563
564         return true;
565 }
566
567 static bool meshlink_read_config(meshlink_handle_t *mesh) {
568         config_t config;
569
570         if(!main_config_read(mesh, "current", &config, mesh->config_key)) {
571                 logger(NULL, MESHLINK_ERROR, "Could not read main configuration file!");
572                 return false;
573         }
574
575         packmsg_input_t in = {config.buf, config.len};
576         const void *private_key;
577
578         uint32_t version = packmsg_get_uint32(&in);
579         char *name = packmsg_get_str_dup(&in);
580         uint32_t private_key_len = packmsg_get_bin_raw(&in, &private_key);
581         packmsg_skip_element(&in); // Invitation key is not supported
582         uint16_t myport = packmsg_get_uint16(&in);
583
584         if(!packmsg_done(&in) || version != MESHLINK_CONFIG_VERSION || private_key_len != 96) {
585                 logger(NULL, MESHLINK_ERROR, "Error parsing main configuration file!");
586                 free(name);
587                 config_free(&config);
588                 return false;
589         }
590
591         if(mesh->name && strcmp(mesh->name, name)) {
592                 logger(NULL, MESHLINK_ERROR, "Configuration is for a different name (%s)!", name);
593                 meshlink_errno = MESHLINK_ESTORAGE;
594                 free(name);
595                 config_free(&config);
596                 return false;
597         }
598
599         free(mesh->name);
600         mesh->name = name;
601         xasprintf(&mesh->myport, "%u", myport);
602         mesh->private_key = ecdsa_set_private_key(private_key);
603         config_free(&config);
604
605         /* Create a node for ourself and read our host configuration file */
606
607         mesh->self = new_node();
608         mesh->self->name = xstrdup(name);
609         mesh->self->devclass = mesh->devclass;
610         mesh->self->session_id = mesh->session_id;
611
612         if(!node_read_public_key(mesh, mesh->self)) {
613                 logger(NULL, MESHLINK_ERROR, "Could not read our host configuration file!");
614                 meshlink_errno = MESHLINK_ESTORAGE;
615                 free_node(mesh->self);
616                 mesh->self = NULL;
617                 return false;
618         }
619
620         return true;
621 }
622
623 #ifdef HAVE_SETNS
624 static void *setup_network_in_netns_thread(void *arg) {
625         meshlink_handle_t *mesh = arg;
626
627         if(setns(mesh->netns, CLONE_NEWNET) != 0) {
628                 return NULL;
629         }
630
631         bool success = setup_network(mesh);
632         return success ? arg : NULL;
633 }
634 #endif // HAVE_SETNS
635
636 meshlink_open_params_t *meshlink_open_params_init(const char *confbase, const char *name, const char *appname, dev_class_t devclass) {
637         logger(NULL, MESHLINK_DEBUG, "meshlink_open_params_init(%s, %s, %s, %d)", confbase, name, appname, devclass);
638
639         if(!confbase || !*confbase) {
640                 logger(NULL, MESHLINK_ERROR, "No confbase given!\n");
641                 meshlink_errno = MESHLINK_EINVAL;
642                 return NULL;
643         }
644
645         if(!appname || !*appname) {
646                 logger(NULL, MESHLINK_ERROR, "No appname given!\n");
647                 meshlink_errno = MESHLINK_EINVAL;
648                 return NULL;
649         }
650
651         if(strchr(appname, ' ')) {
652                 logger(NULL, MESHLINK_ERROR, "Invalid appname given!\n");
653                 meshlink_errno = MESHLINK_EINVAL;
654                 return NULL;
655         }
656
657         if(name && !check_id(name)) {
658                 logger(NULL, MESHLINK_ERROR, "Invalid name given!\n");
659                 meshlink_errno = MESHLINK_EINVAL;
660                 return NULL;
661         }
662
663         if(devclass < 0 || devclass >= DEV_CLASS_COUNT) {
664                 logger(NULL, MESHLINK_ERROR, "Invalid devclass given!\n");
665                 meshlink_errno = MESHLINK_EINVAL;
666                 return NULL;
667         }
668
669         meshlink_open_params_t *params = xzalloc(sizeof * params);
670
671         params->confbase = xstrdup(confbase);
672         params->name = name ? xstrdup(name) : NULL;
673         params->appname = xstrdup(appname);
674         params->devclass = devclass;
675         params->netns = -1;
676
677         xasprintf(&params->lock_filename, "%s" SLASH "meshlink.lock", confbase);
678
679         return params;
680 }
681
682 bool meshlink_open_params_set_netns(meshlink_open_params_t *params, int netns) {
683         logger(NULL, MESHLINK_DEBUG, "meshlink_open_params_set_netnst(%d)", netns);
684
685         if(!params) {
686                 meshlink_errno = MESHLINK_EINVAL;
687                 return false;
688         }
689
690         params->netns = netns;
691
692         return true;
693 }
694
695 bool meshlink_open_params_set_storage_key(meshlink_open_params_t *params, const void *key, size_t keylen) {
696         logger(NULL, MESHLINK_DEBUG, "meshlink_open_params_set_storage_key(%p, %zu)", key, keylen);
697
698         if(!params) {
699                 meshlink_errno = MESHLINK_EINVAL;
700                 return false;
701         }
702
703         if((!key && keylen) || (key && !keylen)) {
704                 logger(NULL, MESHLINK_ERROR, "Invalid key length!\n");
705                 meshlink_errno = MESHLINK_EINVAL;
706                 return false;
707         }
708
709         params->key = key;
710         params->keylen = keylen;
711
712         return true;
713 }
714
715 bool meshlink_open_params_set_storage_policy(meshlink_open_params_t *params, meshlink_storage_policy_t policy) {
716         logger(NULL, MESHLINK_DEBUG, "meshlink_open_params_set_storage_policy(%d)", policy);
717
718         if(!params) {
719                 meshlink_errno = MESHLINK_EINVAL;
720                 return false;
721         }
722
723         params->storage_policy = policy;
724
725         return true;
726 }
727
728 bool meshlink_open_params_set_lock_filename(meshlink_open_params_t *params, const char *filename) {
729         logger(NULL, MESHLINK_DEBUG, "meshlink_open_params_set_lock_filename(%s)", filename);
730
731         if(!params || !filename) {
732                 meshlink_errno = MESHLINK_EINVAL;
733                 return false;
734         }
735
736         free(params->lock_filename);
737         params->lock_filename = xstrdup(filename);
738
739         return true;
740 }
741
742 bool meshlink_encrypted_key_rotate(meshlink_handle_t *mesh, const void *new_key, size_t new_keylen) {
743         logger(NULL, MESHLINK_DEBUG, "meshlink_encrypted_key_rotate(%p, %zu)", new_key, new_keylen);
744
745         if(!mesh || !new_key || !new_keylen) {
746                 logger(mesh, MESHLINK_ERROR, "Invalid arguments given!\n");
747                 meshlink_errno = MESHLINK_EINVAL;
748                 return false;
749         }
750
751         if(pthread_mutex_lock(&mesh->mutex) != 0) {
752                 abort();
753         }
754
755         // Create hash for the new key
756         void *new_config_key;
757         new_config_key = xmalloc(CHACHA_POLY1305_KEYLEN);
758
759         if(!prf(new_key, new_keylen, "MeshLink configuration key", 26, new_config_key, CHACHA_POLY1305_KEYLEN)) {
760                 logger(mesh, MESHLINK_ERROR, "Error creating new configuration key!\n");
761                 meshlink_errno = MESHLINK_EINTERNAL;
762                 pthread_mutex_unlock(&mesh->mutex);
763                 return false;
764         }
765
766         // Copy contents of the "current" confbase sub-directory to "new" confbase sub-directory with the new key
767
768         if(!config_copy(mesh, "current", mesh->config_key, "new", new_config_key)) {
769                 logger(mesh, MESHLINK_ERROR, "Could not set up configuration in %s/old: %s\n", mesh->confbase, strerror(errno));
770                 meshlink_errno = MESHLINK_ESTORAGE;
771                 pthread_mutex_unlock(&mesh->mutex);
772                 return false;
773         }
774
775         devtool_keyrotate_probe(1);
776
777         // Rename confbase/current/ to confbase/old
778
779         if(!config_rename(mesh, "current", "old")) {
780                 logger(mesh, MESHLINK_ERROR, "Cannot rename %s/current to %s/old\n", mesh->confbase, mesh->confbase);
781                 meshlink_errno = MESHLINK_ESTORAGE;
782                 pthread_mutex_unlock(&mesh->mutex);
783                 return false;
784         }
785
786         devtool_keyrotate_probe(2);
787
788         // Rename confbase/new/ to confbase/current
789
790         if(!config_rename(mesh, "new", "current")) {
791                 logger(mesh, MESHLINK_ERROR, "Cannot rename %s/new to %s/current\n", mesh->confbase, mesh->confbase);
792                 meshlink_errno = MESHLINK_ESTORAGE;
793                 pthread_mutex_unlock(&mesh->mutex);
794                 return false;
795         }
796
797         devtool_keyrotate_probe(3);
798
799         // Cleanup the "old" confbase sub-directory
800
801         if(!config_destroy(mesh->confbase, "old")) {
802                 pthread_mutex_unlock(&mesh->mutex);
803                 return false;
804         }
805
806         // Change the mesh handle key with new key
807
808         free(mesh->config_key);
809         mesh->config_key = new_config_key;
810
811         pthread_mutex_unlock(&mesh->mutex);
812
813         return true;
814 }
815
816 void meshlink_open_params_free(meshlink_open_params_t *params) {
817         logger(NULL, MESHLINK_DEBUG, "meshlink_open_params_free()");
818
819         if(!params) {
820                 meshlink_errno = MESHLINK_EINVAL;
821                 return;
822         }
823
824         free(params->confbase);
825         free(params->name);
826         free(params->appname);
827         free(params->lock_filename);
828
829         free(params);
830 }
831
832 /// Device class traits
833 static const dev_class_traits_t default_class_traits[DEV_CLASS_COUNT] = {
834         { .pingtimeout = 5, .pinginterval = 60, .maxtimeout = 900, .min_connects = 3, .max_connects = 10000, .edge_weight = 1 }, // DEV_CLASS_BACKBONE
835         { .pingtimeout = 5, .pinginterval = 60, .maxtimeout = 900, .min_connects = 3, .max_connects = 100, .edge_weight = 3 },   // DEV_CLASS_STATIONARY
836         { .pingtimeout = 5, .pinginterval = 60, .maxtimeout = 900, .min_connects = 3, .max_connects = 3, .edge_weight = 6 },     // DEV_CLASS_PORTABLE
837         { .pingtimeout = 5, .pinginterval = 60, .maxtimeout = 900, .min_connects = 1, .max_connects = 1, .edge_weight = 9 },     // DEV_CLASS_UNKNOWN
838 };
839
840 meshlink_handle_t *meshlink_open(const char *confbase, const char *name, const char *appname, dev_class_t devclass) {
841         logger(NULL, MESHLINK_DEBUG, "meshlink_open(%s, %s, %s, %d)", confbase, name, appname, devclass);
842
843         if(!confbase || !*confbase) {
844                 logger(NULL, MESHLINK_ERROR, "No confbase given!\n");
845                 meshlink_errno = MESHLINK_EINVAL;
846                 return NULL;
847         }
848
849         char lock_filename[PATH_MAX];
850         snprintf(lock_filename, sizeof(lock_filename), "%s" SLASH "meshlink.lock", confbase);
851
852         /* Create a temporary struct on the stack, to avoid allocating and freeing one. */
853         meshlink_open_params_t params = {
854                 .confbase = (char *)confbase,
855                 .lock_filename = lock_filename,
856                 .name = (char *)name,
857                 .appname = (char *)appname,
858                 .devclass = devclass,
859                 .netns = -1,
860         };
861
862         return meshlink_open_ex(&params);
863 }
864
865 meshlink_handle_t *meshlink_open_encrypted(const char *confbase, const char *name, const char *appname, dev_class_t devclass, const void *key, size_t keylen) {
866         logger(NULL, MESHLINK_DEBUG, "meshlink_open_encrypted(%s, %s, %s, %d, %p, %zu)", confbase, name, appname, devclass, key, keylen);
867
868         if(!confbase || !*confbase) {
869                 logger(NULL, MESHLINK_ERROR, "No confbase given!\n");
870                 meshlink_errno = MESHLINK_EINVAL;
871                 return NULL;
872         }
873
874         char lock_filename[PATH_MAX];
875         snprintf(lock_filename, sizeof(lock_filename), "%s" SLASH "meshlink.lock", confbase);
876
877         /* Create a temporary struct on the stack, to avoid allocating and freeing one. */
878         meshlink_open_params_t params = {
879                 .confbase = (char *)confbase,
880                 .lock_filename = lock_filename,
881                 .name = (char *)name,
882                 .appname = (char *)appname,
883                 .devclass = devclass,
884                 .netns = -1,
885         };
886
887         if(!meshlink_open_params_set_storage_key(&params, key, keylen)) {
888                 return false;
889         }
890
891         return meshlink_open_ex(&params);
892 }
893
894 meshlink_handle_t *meshlink_open_ephemeral(const char *name, const char *appname, dev_class_t devclass) {
895         logger(NULL, MESHLINK_DEBUG, "meshlink_open_ephemeral(%s, %s, %d)", name, appname, devclass);
896
897         if(!name) {
898                 logger(NULL, MESHLINK_ERROR, "No name given!\n");
899                 meshlink_errno = MESHLINK_EINVAL;
900                 return NULL;
901         }
902
903         if(!check_id(name)) {
904                 logger(NULL, MESHLINK_ERROR, "Invalid name given!\n");
905                 meshlink_errno = MESHLINK_EINVAL;
906                 return NULL;
907         }
908
909         if(!appname || !*appname) {
910                 logger(NULL, MESHLINK_ERROR, "No appname given!\n");
911                 meshlink_errno = MESHLINK_EINVAL;
912                 return NULL;
913         }
914
915         if(strchr(appname, ' ')) {
916                 logger(NULL, MESHLINK_ERROR, "Invalid appname given!\n");
917                 meshlink_errno = MESHLINK_EINVAL;
918                 return NULL;
919         }
920
921         if(devclass < 0 || devclass >= DEV_CLASS_COUNT) {
922                 logger(NULL, MESHLINK_ERROR, "Invalid devclass given!\n");
923                 meshlink_errno = MESHLINK_EINVAL;
924                 return NULL;
925         }
926
927         /* Create a temporary struct on the stack, to avoid allocating and freeing one. */
928         meshlink_open_params_t params = {
929                 .name = (char *)name,
930                 .appname = (char *)appname,
931                 .devclass = devclass,
932                 .netns = -1,
933         };
934
935         return meshlink_open_ex(&params);
936 }
937
938 meshlink_handle_t *meshlink_open_ex(const meshlink_open_params_t *params) {
939         logger(NULL, MESHLINK_DEBUG, "meshlink_open_ex()");
940
941         // Validate arguments provided by the application
942         if(!params->appname || !*params->appname) {
943                 logger(NULL, MESHLINK_ERROR, "No appname given!\n");
944                 meshlink_errno = MESHLINK_EINVAL;
945                 return NULL;
946         }
947
948         if(strchr(params->appname, ' ')) {
949                 logger(NULL, MESHLINK_ERROR, "Invalid appname given!\n");
950                 meshlink_errno = MESHLINK_EINVAL;
951                 return NULL;
952         }
953
954         if(params->name && !check_id(params->name)) {
955                 logger(NULL, MESHLINK_ERROR, "Invalid name given!\n");
956                 meshlink_errno = MESHLINK_EINVAL;
957                 return NULL;
958         }
959
960         if(params->devclass < 0 || params->devclass >= DEV_CLASS_COUNT) {
961                 logger(NULL, MESHLINK_ERROR, "Invalid devclass given!\n");
962                 meshlink_errno = MESHLINK_EINVAL;
963                 return NULL;
964         }
965
966         if((params->key && !params->keylen) || (!params->key && params->keylen)) {
967                 logger(NULL, MESHLINK_ERROR, "Invalid key length!\n");
968                 meshlink_errno = MESHLINK_EINVAL;
969                 return NULL;
970         }
971
972         meshlink_handle_t *mesh = xzalloc(sizeof(meshlink_handle_t));
973
974         if(params->confbase) {
975                 mesh->confbase = xstrdup(params->confbase);
976         }
977
978         mesh->appname = xstrdup(params->appname);
979         mesh->devclass = params->devclass;
980         mesh->netns = params->netns;
981         mesh->log_cb = global_log_cb;
982         mesh->log_level = global_log_level;
983         mesh->packet = xmalloc(sizeof(vpn_packet_t));
984
985         randomize(&mesh->prng_state, sizeof(mesh->prng_state));
986
987         do {
988                 randomize(&mesh->session_id, sizeof(mesh->session_id));
989         } while(mesh->session_id == 0);
990
991         memcpy(mesh->dev_class_traits, default_class_traits, sizeof(default_class_traits));
992
993         mesh->name = params->name ? xstrdup(params->name) : NULL;
994
995         // Hash the key
996         if(params->key) {
997                 mesh->config_key = xmalloc(CHACHA_POLY1305_KEYLEN);
998
999                 if(!prf(params->key, params->keylen, "MeshLink configuration key", 26, mesh->config_key, CHACHA_POLY1305_KEYLEN)) {
1000                         logger(NULL, MESHLINK_ERROR, "Error creating configuration key!\n");
1001                         meshlink_close(mesh);
1002                         meshlink_errno = MESHLINK_EINTERNAL;
1003                         return NULL;
1004                 }
1005         }
1006
1007         // initialize mutexes and conds
1008         pthread_mutexattr_t attr;
1009         pthread_mutexattr_init(&attr);
1010
1011         if(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0) {
1012                 abort();
1013         }
1014
1015         pthread_mutex_init(&mesh->mutex, &attr);
1016         pthread_cond_init(&mesh->cond, NULL);
1017
1018         mesh->threadstarted = false;
1019         event_loop_init(&mesh->loop);
1020         mesh->loop.data = mesh;
1021
1022         meshlink_queue_init(&mesh->outpacketqueue);
1023
1024         // Atomically lock the configuration directory.
1025         if(!main_config_lock(mesh, params->lock_filename)) {
1026                 meshlink_close(mesh);
1027                 return NULL;
1028         }
1029
1030         // If no configuration exists yet, create it.
1031
1032         bool new_configuration = false;
1033
1034         if(!meshlink_confbase_exists(mesh)) {
1035                 if(!mesh->name) {
1036                         logger(NULL, MESHLINK_ERROR, "No configuration files found!\n");
1037                         meshlink_close(mesh);
1038                         meshlink_errno = MESHLINK_ESTORAGE;
1039                         return NULL;
1040                 }
1041
1042                 if(!meshlink_setup(mesh)) {
1043                         logger(NULL, MESHLINK_ERROR, "Cannot create initial configuration\n");
1044                         meshlink_close(mesh);
1045                         return NULL;
1046                 }
1047
1048                 new_configuration = true;
1049         } else {
1050                 if(!meshlink_read_config(mesh)) {
1051                         logger(NULL, MESHLINK_ERROR, "Cannot read main configuration\n");
1052                         meshlink_close(mesh);
1053                         return NULL;
1054                 }
1055         }
1056
1057         mesh->storage_policy = params->storage_policy;
1058
1059 #ifdef HAVE_MINGW
1060         struct WSAData wsa_state;
1061         WSAStartup(MAKEWORD(2, 2), &wsa_state);
1062 #endif
1063
1064         // Setup up everything
1065         // TODO: we should not open listening sockets yet
1066
1067         bool success = false;
1068
1069         if(mesh->netns != -1) {
1070 #ifdef HAVE_SETNS
1071                 pthread_t thr;
1072
1073                 if(pthread_create(&thr, NULL, setup_network_in_netns_thread, mesh) == 0) {
1074                         void *retval = NULL;
1075                         success = pthread_join(thr, &retval) == 0 && retval;
1076                 }
1077
1078 #else
1079                 meshlink_errno = MESHLINK_EINTERNAL;
1080                 return NULL;
1081
1082 #endif // HAVE_SETNS
1083         } else {
1084                 success = setup_network(mesh);
1085         }
1086
1087         if(!success) {
1088                 meshlink_close(mesh);
1089                 meshlink_errno = MESHLINK_ENETWORK;
1090                 return NULL;
1091         }
1092
1093         if(!node_write_config(mesh, mesh->self, new_configuration)) {
1094                 logger(NULL, MESHLINK_ERROR, "Cannot update configuration\n");
1095                 return NULL;
1096         }
1097
1098         idle_set(&mesh->loop, idle, mesh);
1099
1100         logger(NULL, MESHLINK_DEBUG, "meshlink_open returning\n");
1101         return mesh;
1102 }
1103
1104 static void *meshlink_main_loop(void *arg) {
1105         meshlink_handle_t *mesh = arg;
1106
1107         if(mesh->netns != -1) {
1108 #ifdef HAVE_SETNS
1109
1110                 if(setns(mesh->netns, CLONE_NEWNET) != 0) {
1111                         pthread_cond_signal(&mesh->cond);
1112                         return NULL;
1113                 }
1114
1115 #else
1116                 pthread_cond_signal(&mesh->cond);
1117                 return NULL;
1118 #endif // HAVE_SETNS
1119         }
1120
1121         if(pthread_mutex_lock(&mesh->mutex) != 0) {
1122                 abort();
1123         }
1124
1125         logger(mesh, MESHLINK_DEBUG, "Starting main_loop...\n");
1126         pthread_cond_broadcast(&mesh->cond);
1127         main_loop(mesh);
1128         logger(mesh, MESHLINK_DEBUG, "main_loop returned.\n");
1129
1130         pthread_mutex_unlock(&mesh->mutex);
1131
1132         return NULL;
1133 }
1134
1135 bool meshlink_start(meshlink_handle_t *mesh) {
1136         if(!mesh) {
1137                 meshlink_errno = MESHLINK_EINVAL;
1138                 return false;
1139         }
1140
1141         logger(mesh, MESHLINK_DEBUG, "meshlink_start called\n");
1142
1143         if(pthread_mutex_lock(&mesh->mutex) != 0) {
1144                 abort();
1145         }
1146
1147         assert(mesh->self);
1148         assert(mesh->private_key);
1149         assert(mesh->self->ecdsa);
1150         assert(!memcmp((uint8_t *)mesh->self->ecdsa + 64, (uint8_t *)mesh->private_key + 64, 32));
1151
1152         if(mesh->threadstarted) {
1153                 logger(mesh, MESHLINK_DEBUG, "thread was already running\n");
1154                 pthread_mutex_unlock(&mesh->mutex);
1155                 return true;
1156         }
1157
1158         // Reset node connection timers
1159         for splay_each(node_t, n, mesh->nodes) {
1160                 n->last_connect_try = 0;
1161         }
1162
1163
1164         //Check that a valid name is set
1165         if(!mesh->name) {
1166                 logger(mesh, MESHLINK_ERROR, "No name given!\n");
1167                 meshlink_errno = MESHLINK_EINVAL;
1168                 pthread_mutex_unlock(&mesh->mutex);
1169                 return false;
1170         }
1171
1172         init_outgoings(mesh);
1173
1174         // Start the main thread
1175
1176         event_loop_start(&mesh->loop);
1177
1178         // Ensure we have a decent amount of stack space. Musl's default of 80 kB is too small.
1179         pthread_attr_t attr;
1180         pthread_attr_init(&attr);
1181         pthread_attr_setstacksize(&attr, 1024 * 1024);
1182
1183         if(pthread_create(&mesh->thread, &attr, meshlink_main_loop, mesh) != 0) {
1184                 logger(mesh, MESHLINK_ERROR, "Could not start thread: %s\n", strerror(errno));
1185                 memset(&mesh->thread, 0, sizeof(mesh)->thread);
1186                 meshlink_errno = MESHLINK_EINTERNAL;
1187                 event_loop_stop(&mesh->loop);
1188                 pthread_mutex_unlock(&mesh->mutex);
1189                 return false;
1190         }
1191
1192         pthread_cond_wait(&mesh->cond, &mesh->mutex);
1193         mesh->threadstarted = true;
1194
1195         pthread_mutex_unlock(&mesh->mutex);
1196         return true;
1197 }
1198
1199 void meshlink_stop(meshlink_handle_t *mesh) {
1200         logger(mesh, MESHLINK_DEBUG, "meshlink_stop()\n");
1201
1202         if(!mesh) {
1203                 meshlink_errno = MESHLINK_EINVAL;
1204                 return;
1205         }
1206
1207         if(pthread_mutex_lock(&mesh->mutex) != 0) {
1208                 abort();
1209         }
1210
1211         // Shut down the main thread
1212         event_loop_stop(&mesh->loop);
1213
1214         // TODO: send something to a local socket to kick the event loop
1215
1216         if(mesh->threadstarted) {
1217                 // Wait for the main thread to finish
1218                 pthread_mutex_unlock(&mesh->mutex);
1219
1220                 if(pthread_join(mesh->thread, NULL) != 0) {
1221                         abort();
1222                 }
1223
1224                 if(pthread_mutex_lock(&mesh->mutex) != 0) {
1225                         abort();
1226                 }
1227
1228                 mesh->threadstarted = false;
1229         }
1230
1231         // Close all metaconnections
1232         if(mesh->connections) {
1233                 for(list_node_t *node = mesh->connections->head, *next; node; node = next) {
1234                         next = node->next;
1235                         connection_t *c = node->data;
1236                         c->outgoing = NULL;
1237                         terminate_connection(mesh, c, false);
1238                 }
1239         }
1240
1241         exit_outgoings(mesh);
1242
1243         // Try to write out any changed node config files, ignore errors at this point.
1244         if(mesh->nodes) {
1245                 for splay_each(node_t, n, mesh->nodes) {
1246                         if(n->status.dirty) {
1247                                 if(!node_write_config(mesh, n, false)) {
1248                                         // ignore
1249                                 }
1250                         }
1251                 }
1252         }
1253
1254         pthread_mutex_unlock(&mesh->mutex);
1255 }
1256
1257 void meshlink_close(meshlink_handle_t *mesh) {
1258         logger(mesh, MESHLINK_DEBUG, "meshlink_close()\n");
1259
1260         if(!mesh) {
1261                 meshlink_errno = MESHLINK_EINVAL;
1262                 return;
1263         }
1264
1265         // stop can be called even if mesh has not been started
1266         meshlink_stop(mesh);
1267
1268         // lock is not released after this
1269         if(pthread_mutex_lock(&mesh->mutex) != 0) {
1270                 abort();
1271         }
1272
1273         // Close and free all resources used.
1274
1275         close_network_connections(mesh);
1276
1277         logger(mesh, MESHLINK_INFO, "Terminating");
1278
1279         event_loop_exit(&mesh->loop);
1280
1281 #ifdef HAVE_MINGW
1282
1283         if(mesh->confbase) {
1284                 WSACleanup();
1285         }
1286
1287 #endif
1288
1289         if(mesh->netns != -1) {
1290                 close(mesh->netns);
1291         }
1292
1293         for(vpn_packet_t *packet; (packet = meshlink_queue_pop(&mesh->outpacketqueue));) {
1294                 free(packet);
1295         }
1296
1297         meshlink_queue_exit(&mesh->outpacketqueue);
1298
1299         free(mesh->name);
1300         free(mesh->appname);
1301         free(mesh->confbase);
1302         free(mesh->config_key);
1303         free(mesh->external_address_url);
1304         free(mesh->packet);
1305         ecdsa_free(mesh->private_key);
1306
1307         main_config_unlock(mesh);
1308
1309         pthread_mutex_unlock(&mesh->mutex);
1310         pthread_mutex_destroy(&mesh->mutex);
1311
1312         memset(mesh, 0, sizeof(*mesh));
1313
1314         free(mesh);
1315 }
1316
1317 bool meshlink_destroy_ex(const meshlink_open_params_t *params) {
1318         logger(NULL, MESHLINK_DEBUG, "meshlink_destroy_ex()\n");
1319
1320         if(!params) {
1321                 meshlink_errno = MESHLINK_EINVAL;
1322                 return false;
1323         }
1324
1325         if(!params->confbase) {
1326                 /* Ephemeral instances */
1327                 return true;
1328         }
1329
1330         /* Exit early if the confbase directory itself doesn't exist */
1331         if(access(params->confbase, F_OK) && errno == ENOENT) {
1332                 return true;
1333         }
1334
1335         /* Take the lock the same way meshlink_open() would. */
1336         FILE *lockfile = fopen(params->lock_filename, "w+");
1337
1338         if(!lockfile) {
1339                 logger(NULL, MESHLINK_ERROR, "Could not open lock file %s: %s", params->lock_filename, strerror(errno));
1340                 meshlink_errno = MESHLINK_ESTORAGE;
1341                 return false;
1342         }
1343
1344 #ifdef FD_CLOEXEC
1345         fcntl(fileno(lockfile), F_SETFD, FD_CLOEXEC);
1346 #endif
1347
1348 #ifdef HAVE_MINGW
1349         // TODO: use _locking()?
1350 #else
1351
1352         if(flock(fileno(lockfile), LOCK_EX | LOCK_NB) != 0) {
1353                 logger(NULL, MESHLINK_ERROR, "Configuration directory %s still in use\n", params->lock_filename);
1354                 fclose(lockfile);
1355                 meshlink_errno = MESHLINK_EBUSY;
1356                 return false;
1357         }
1358
1359 #endif
1360
1361         if(!config_destroy(params->confbase, "current") || !config_destroy(params->confbase, "new") || !config_destroy(params->confbase, "old")) {
1362                 logger(NULL, MESHLINK_ERROR, "Cannot remove sub-directories in %s: %s\n", params->confbase, strerror(errno));
1363                 return false;
1364         }
1365
1366         if(unlink(params->lock_filename)) {
1367                 logger(NULL, MESHLINK_ERROR, "Cannot remove lock file %s: %s\n", params->lock_filename, strerror(errno));
1368                 fclose(lockfile);
1369                 meshlink_errno = MESHLINK_ESTORAGE;
1370                 return false;
1371         }
1372
1373         fclose(lockfile);
1374
1375         if(!sync_path(params->confbase)) {
1376                 logger(NULL, MESHLINK_ERROR, "Cannot sync directory %s: %s\n", params->confbase, strerror(errno));
1377                 meshlink_errno = MESHLINK_ESTORAGE;
1378                 return false;
1379         }
1380
1381         return true;
1382 }
1383
1384 bool meshlink_destroy(const char *confbase) {
1385         logger(NULL, MESHLINK_DEBUG, "meshlink_destroy(%s)", confbase);
1386
1387         char lock_filename[PATH_MAX];
1388         snprintf(lock_filename, sizeof(lock_filename), "%s" SLASH "meshlink.lock", confbase);
1389
1390         meshlink_open_params_t params = {
1391                 .confbase = (char *)confbase,
1392                 .lock_filename = lock_filename,
1393         };
1394
1395         return meshlink_destroy_ex(&params);
1396 }
1397
1398 void meshlink_set_receive_cb(meshlink_handle_t *mesh, meshlink_receive_cb_t cb) {
1399         logger(mesh, MESHLINK_DEBUG, "meshlink_set_receive_cb(%p)", (void *)(intptr_t)cb);
1400
1401         if(!mesh) {
1402                 meshlink_errno = MESHLINK_EINVAL;
1403                 return;
1404         }
1405
1406         if(pthread_mutex_lock(&mesh->mutex) != 0) {
1407                 abort();
1408         }
1409
1410         mesh->receive_cb = cb;
1411         pthread_mutex_unlock(&mesh->mutex);
1412 }
1413
1414 void meshlink_set_connection_try_cb(meshlink_handle_t *mesh, meshlink_connection_try_cb_t cb) {
1415         logger(mesh, MESHLINK_DEBUG, "meshlink_set_connection_try_cb(%p)", (void *)(intptr_t)cb);
1416
1417         if(!mesh) {
1418                 meshlink_errno = MESHLINK_EINVAL;
1419                 return;
1420         }
1421
1422         if(pthread_mutex_lock(&mesh->mutex) != 0) {
1423                 abort();
1424         }
1425
1426         mesh->connection_try_cb = cb;
1427         pthread_mutex_unlock(&mesh->mutex);
1428 }
1429
1430 void meshlink_set_node_status_cb(meshlink_handle_t *mesh, meshlink_node_status_cb_t cb) {
1431         logger(mesh, MESHLINK_DEBUG, "meshlink_set_node_status_cb(%p)", (void *)(intptr_t)cb);
1432
1433         if(!mesh) {
1434                 meshlink_errno = MESHLINK_EINVAL;
1435                 return;
1436         }
1437
1438         if(pthread_mutex_lock(&mesh->mutex) != 0) {
1439                 abort();
1440         }
1441
1442         mesh->node_status_cb = cb;
1443         pthread_mutex_unlock(&mesh->mutex);
1444 }
1445
1446 void meshlink_set_node_pmtu_cb(meshlink_handle_t *mesh, meshlink_node_pmtu_cb_t cb) {
1447         logger(mesh, MESHLINK_DEBUG, "meshlink_set_node_pmtu_cb(%p)", (void *)(intptr_t)cb);
1448
1449         if(!mesh) {
1450                 meshlink_errno = MESHLINK_EINVAL;
1451                 return;
1452         }
1453
1454         if(pthread_mutex_lock(&mesh->mutex) != 0) {
1455                 abort();
1456         }
1457
1458         mesh->node_pmtu_cb = cb;
1459         pthread_mutex_unlock(&mesh->mutex);
1460 }
1461
1462 void meshlink_set_node_duplicate_cb(meshlink_handle_t *mesh, meshlink_node_duplicate_cb_t cb) {
1463         logger(mesh, MESHLINK_DEBUG, "meshlink_set_node_duplicate_cb(%p)", (void *)(intptr_t)cb);
1464
1465         if(!mesh) {
1466                 meshlink_errno = MESHLINK_EINVAL;
1467                 return;
1468         }
1469
1470         if(pthread_mutex_lock(&mesh->mutex) != 0) {
1471                 abort();
1472         }
1473
1474         mesh->node_duplicate_cb = cb;
1475         pthread_mutex_unlock(&mesh->mutex);
1476 }
1477
1478 void meshlink_set_log_cb(meshlink_handle_t *mesh, meshlink_log_level_t level, meshlink_log_cb_t cb) {
1479         logger(mesh, MESHLINK_DEBUG, "meshlink_set_log_cb(%p)", (void *)(intptr_t)cb);
1480
1481         if(mesh) {
1482                 if(pthread_mutex_lock(&mesh->mutex) != 0) {
1483                         abort();
1484                 }
1485
1486                 mesh->log_cb = cb;
1487                 mesh->log_level = cb ? level : 0;
1488                 pthread_mutex_unlock(&mesh->mutex);
1489         } else {
1490                 global_log_cb = cb;
1491                 global_log_level = cb ? level : 0;
1492         }
1493 }
1494
1495 void meshlink_set_error_cb(struct meshlink_handle *mesh, meshlink_error_cb_t cb) {
1496         logger(mesh, MESHLINK_DEBUG, "meshlink_set_error_cb(%p)", (void *)(intptr_t)cb);
1497
1498         if(!mesh) {
1499                 meshlink_errno = MESHLINK_EINVAL;
1500                 return;
1501         }
1502
1503         if(pthread_mutex_lock(&mesh->mutex) != 0) {
1504                 abort();
1505         }
1506
1507         mesh->error_cb = cb;
1508         pthread_mutex_unlock(&mesh->mutex);
1509 }
1510
1511 static bool prepare_packet(meshlink_handle_t *mesh, meshlink_node_t *destination, const void *data, size_t len, vpn_packet_t *packet) {
1512         meshlink_packethdr_t *hdr;
1513
1514         if(len > MAXSIZE - sizeof(*hdr)) {
1515                 meshlink_errno = MESHLINK_EINVAL;
1516                 return false;
1517         }
1518
1519         node_t *n = (node_t *)destination;
1520
1521         if(n->status.blacklisted) {
1522                 logger(mesh, MESHLINK_ERROR, "Node %s blacklisted, dropping packet\n", n->name);
1523                 meshlink_errno = MESHLINK_EBLACKLISTED;
1524                 return false;
1525         }
1526
1527         // Prepare the packet
1528         packet->probe = false;
1529         packet->tcp = false;
1530         packet->len = len + sizeof(*hdr);
1531
1532         hdr = (meshlink_packethdr_t *)packet->data;
1533         memset(hdr, 0, sizeof(*hdr));
1534         // leave the last byte as 0 to make sure strings are always
1535         // null-terminated if they are longer than the buffer
1536         strncpy((char *)hdr->destination, destination->name, sizeof(hdr->destination) - 1);
1537         strncpy((char *)hdr->source, mesh->self->name, sizeof(hdr->source) - 1);
1538
1539         memcpy(packet->data + sizeof(*hdr), data, len);
1540
1541         return true;
1542 }
1543
1544 static bool meshlink_send_immediate(meshlink_handle_t *mesh, meshlink_node_t *destination, const void *data, size_t len) {
1545         assert(mesh);
1546         assert(destination);
1547         assert(data);
1548         assert(len);
1549
1550         // Prepare the packet
1551         if(!prepare_packet(mesh, destination, data, len, mesh->packet)) {
1552                 return false;
1553         }
1554
1555         // Send it immediately
1556         route(mesh, mesh->self, mesh->packet);
1557
1558         return true;
1559 }
1560
1561 bool meshlink_send(meshlink_handle_t *mesh, meshlink_node_t *destination, const void *data, size_t len) {
1562         logger(mesh, MESHLINK_DEBUG, "meshlink_send(%s, %p, %zu)", destination ? destination->name : "(null)", data, len);
1563
1564         // Validate arguments
1565         if(!mesh || !destination) {
1566                 meshlink_errno = MESHLINK_EINVAL;
1567                 return false;
1568         }
1569
1570         if(!len) {
1571                 return true;
1572         }
1573
1574         if(!data) {
1575                 meshlink_errno = MESHLINK_EINVAL;
1576                 return false;
1577         }
1578
1579         // Prepare the packet
1580         vpn_packet_t *packet = malloc(sizeof(*packet));
1581
1582         if(!packet) {
1583                 meshlink_errno = MESHLINK_ENOMEM;
1584                 return false;
1585         }
1586
1587         if(!prepare_packet(mesh, destination, data, len, packet)) {
1588                 free(packet);
1589                 return false;
1590         }
1591
1592         // Queue it
1593         if(!meshlink_queue_push(&mesh->outpacketqueue, packet)) {
1594                 free(packet);
1595                 meshlink_errno = MESHLINK_ENOMEM;
1596                 return false;
1597         }
1598
1599         logger(mesh, MESHLINK_DEBUG, "Adding packet of %zu bytes to packet queue", len);
1600
1601         // Notify event loop
1602         signal_trigger(&mesh->loop, &mesh->datafromapp);
1603
1604         return true;
1605 }
1606
1607 void meshlink_send_from_queue(event_loop_t *loop, void *data) {
1608         (void)loop;
1609         meshlink_handle_t *mesh = data;
1610
1611         logger(mesh, MESHLINK_DEBUG, "Flushing the packet queue");
1612
1613         for(vpn_packet_t *packet; (packet = meshlink_queue_pop(&mesh->outpacketqueue));) {
1614                 logger(mesh, MESHLINK_DEBUG, "Removing packet of %d bytes from packet queue", packet->len);
1615                 mesh->self->in_packets++;
1616                 mesh->self->in_bytes += packet->len;
1617                 route(mesh, mesh->self, packet);
1618                 free(packet);
1619         }
1620 }
1621
1622 ssize_t meshlink_get_pmtu(meshlink_handle_t *mesh, meshlink_node_t *destination) {
1623         if(!mesh || !destination) {
1624                 meshlink_errno = MESHLINK_EINVAL;
1625                 return -1;
1626         }
1627
1628         if(pthread_mutex_lock(&mesh->mutex) != 0) {
1629                 abort();
1630         }
1631
1632         node_t *n = (node_t *)destination;
1633
1634         if(!n->status.reachable) {
1635                 pthread_mutex_unlock(&mesh->mutex);
1636                 return 0;
1637
1638         } else if(n->mtuprobes > 30 && n->minmtu) {
1639                 pthread_mutex_unlock(&mesh->mutex);
1640                 return n->minmtu;
1641         } else {
1642                 pthread_mutex_unlock(&mesh->mutex);
1643                 return MTU;
1644         }
1645 }
1646
1647 char *meshlink_get_fingerprint(meshlink_handle_t *mesh, meshlink_node_t *node) {
1648         if(!mesh || !node) {
1649                 meshlink_errno = MESHLINK_EINVAL;
1650                 return NULL;
1651         }
1652
1653         if(pthread_mutex_lock(&mesh->mutex) != 0) {
1654                 abort();
1655         }
1656
1657         node_t *n = (node_t *)node;
1658
1659         if(!node_read_public_key(mesh, n) || !n->ecdsa) {
1660                 meshlink_errno = MESHLINK_EINTERNAL;
1661                 pthread_mutex_unlock(&mesh->mutex);
1662                 return false;
1663         }
1664
1665         char *fingerprint = ecdsa_get_base64_public_key(n->ecdsa);
1666
1667         if(!fingerprint) {
1668                 meshlink_errno = MESHLINK_EINTERNAL;
1669         }
1670
1671         pthread_mutex_unlock(&mesh->mutex);
1672         return fingerprint;
1673 }
1674
1675 meshlink_node_t *meshlink_get_self(meshlink_handle_t *mesh) {
1676         if(!mesh) {
1677                 meshlink_errno = MESHLINK_EINVAL;
1678                 return NULL;
1679         }
1680
1681         return (meshlink_node_t *)mesh->self;
1682 }
1683
1684 meshlink_node_t *meshlink_get_node(meshlink_handle_t *mesh, const char *name) {
1685         if(!mesh || !name) {
1686                 meshlink_errno = MESHLINK_EINVAL;
1687                 return NULL;
1688         }
1689
1690         node_t *n = NULL;
1691
1692         if(pthread_mutex_lock(&mesh->mutex) != 0) {
1693                 abort();
1694         }
1695
1696         n = lookup_node(mesh, (char *)name); // TODO: make lookup_node() use const
1697         pthread_mutex_unlock(&mesh->mutex);
1698
1699         if(!n) {
1700                 meshlink_errno = MESHLINK_ENOENT;
1701         }
1702
1703         return (meshlink_node_t *)n;
1704 }
1705
1706 meshlink_node_t **meshlink_get_all_nodes(meshlink_handle_t *mesh, meshlink_node_t **nodes, size_t *nmemb) {
1707         if(!mesh || !nmemb || (*nmemb && !nodes)) {
1708                 meshlink_errno = MESHLINK_EINVAL;
1709                 return NULL;
1710         }
1711
1712         meshlink_node_t **result;
1713
1714         //lock mesh->nodes
1715         if(pthread_mutex_lock(&mesh->mutex) != 0) {
1716                 abort();
1717         }
1718
1719         *nmemb = mesh->nodes->count;
1720         result = realloc(nodes, *nmemb * sizeof(*nodes));
1721
1722         if(result) {
1723                 meshlink_node_t **p = result;
1724
1725                 for splay_each(node_t, n, mesh->nodes) {
1726                         *p++ = (meshlink_node_t *)n;
1727                 }
1728         } else {
1729                 *nmemb = 0;
1730                 free(nodes);
1731                 meshlink_errno = MESHLINK_ENOMEM;
1732         }
1733
1734         pthread_mutex_unlock(&mesh->mutex);
1735
1736         return result;
1737 }
1738
1739 static meshlink_node_t **meshlink_get_all_nodes_by_condition(meshlink_handle_t *mesh, const void *condition, meshlink_node_t **nodes, size_t *nmemb, search_node_by_condition_t search_node) {
1740         meshlink_node_t **result;
1741
1742         if(pthread_mutex_lock(&mesh->mutex) != 0) {
1743                 abort();
1744         }
1745
1746         *nmemb = 0;
1747
1748         for splay_each(node_t, n, mesh->nodes) {
1749                 if(search_node(n, condition)) {
1750                         ++*nmemb;
1751                 }
1752         }
1753
1754         if(*nmemb == 0) {
1755                 free(nodes);
1756                 pthread_mutex_unlock(&mesh->mutex);
1757                 return NULL;
1758         }
1759
1760         result = realloc(nodes, *nmemb * sizeof(*nodes));
1761
1762         if(result) {
1763                 meshlink_node_t **p = result;
1764
1765                 for splay_each(node_t, n, mesh->nodes) {
1766                         if(search_node(n, condition)) {
1767                                 *p++ = (meshlink_node_t *)n;
1768                         }
1769                 }
1770         } else {
1771                 *nmemb = 0;
1772                 free(nodes);
1773                 meshlink_errno = MESHLINK_ENOMEM;
1774         }
1775
1776         pthread_mutex_unlock(&mesh->mutex);
1777
1778         return result;
1779 }
1780
1781 static bool search_node_by_dev_class(const node_t *node, const void *condition) {
1782         dev_class_t *devclass = (dev_class_t *)condition;
1783
1784         if(*devclass == (dev_class_t)node->devclass) {
1785                 return true;
1786         }
1787
1788         return false;
1789 }
1790
1791
1792 struct time_range {
1793         time_t start;
1794         time_t end;
1795 };
1796
1797 meshlink_node_t **meshlink_get_all_nodes_by_dev_class(meshlink_handle_t *mesh, dev_class_t devclass, meshlink_node_t **nodes, size_t *nmemb) {
1798         if(!mesh || devclass < 0 || devclass >= DEV_CLASS_COUNT || !nmemb) {
1799                 meshlink_errno = MESHLINK_EINVAL;
1800                 return NULL;
1801         }
1802
1803         return meshlink_get_all_nodes_by_condition(mesh, &devclass, nodes, nmemb, search_node_by_dev_class);
1804 }
1805
1806 dev_class_t meshlink_get_node_dev_class(meshlink_handle_t *mesh, meshlink_node_t *node) {
1807         if(!mesh || !node) {
1808                 meshlink_errno = MESHLINK_EINVAL;
1809                 return -1;
1810         }
1811
1812         dev_class_t devclass;
1813
1814         if(pthread_mutex_lock(&mesh->mutex) != 0) {
1815                 abort();
1816         }
1817
1818         devclass = ((node_t *)node)->devclass;
1819
1820         pthread_mutex_unlock(&mesh->mutex);
1821
1822         return devclass;
1823 }
1824
1825 bool meshlink_get_node_reachability(struct meshlink_handle *mesh, struct meshlink_node *node, time_t *last_reachable, time_t *last_unreachable) {
1826         if(!mesh || !node) {
1827                 meshlink_errno = MESHLINK_EINVAL;
1828                 return NULL;
1829         }
1830
1831         node_t *n = (node_t *)node;
1832         bool reachable;
1833
1834         if(pthread_mutex_lock(&mesh->mutex) != 0) {
1835                 abort();
1836         }
1837
1838         reachable = n->status.reachable && !n->status.blacklisted;
1839
1840         // TODO: handle reachable times?
1841         (void)last_reachable;
1842         (void)last_unreachable;
1843
1844         pthread_mutex_unlock(&mesh->mutex);
1845
1846         return reachable;
1847 }
1848
1849 bool meshlink_sign(meshlink_handle_t *mesh, const void *data, size_t len, void *signature, size_t *siglen) {
1850         logger(mesh, MESHLINK_DEBUG, "meshlink_sign(%p, %zu, %p, %p)", data, len, signature, (void *)siglen);
1851
1852         if(!mesh || !data || !len || !signature || !siglen) {
1853                 meshlink_errno = MESHLINK_EINVAL;
1854                 return false;
1855         }
1856
1857         if(*siglen < MESHLINK_SIGLEN) {
1858                 meshlink_errno = MESHLINK_EINVAL;
1859                 return false;
1860         }
1861
1862         if(pthread_mutex_lock(&mesh->mutex) != 0) {
1863                 abort();
1864         }
1865
1866         if(!ecdsa_sign(mesh->private_key, data, len, signature)) {
1867                 meshlink_errno = MESHLINK_EINTERNAL;
1868                 pthread_mutex_unlock(&mesh->mutex);
1869                 return false;
1870         }
1871
1872         *siglen = MESHLINK_SIGLEN;
1873         pthread_mutex_unlock(&mesh->mutex);
1874         return true;
1875 }
1876
1877 bool meshlink_verify(meshlink_handle_t *mesh, meshlink_node_t *source, const void *data, size_t len, const void *signature, size_t siglen) {
1878         logger(mesh, MESHLINK_DEBUG, "meshlink_verify(%p, %zu, %p, %zu)", data, len, signature, siglen);
1879
1880         if(!mesh || !source || !data || !len || !signature) {
1881                 meshlink_errno = MESHLINK_EINVAL;
1882                 return false;
1883         }
1884
1885         if(siglen != MESHLINK_SIGLEN) {
1886                 meshlink_errno = MESHLINK_EINVAL;
1887                 return false;
1888         }
1889
1890         if(pthread_mutex_lock(&mesh->mutex) != 0) {
1891                 abort();
1892         }
1893
1894         bool rval = false;
1895
1896         struct node_t *n = (struct node_t *)source;
1897
1898         if(!node_read_public_key(mesh, n)) {
1899                 meshlink_errno = MESHLINK_EINTERNAL;
1900                 rval = false;
1901         } else {
1902                 rval = ecdsa_verify(((struct node_t *)source)->ecdsa, data, len, signature);
1903         }
1904
1905         pthread_mutex_unlock(&mesh->mutex);
1906         return rval;
1907 }
1908
1909 bool meshlink_set_canonical_address(meshlink_handle_t *mesh, meshlink_node_t *node, const char *address, const char *port) {
1910         logger(mesh, MESHLINK_DEBUG, "meshlink_set_canonical_address(%s, %s, %s)", node ? node->name : "(null)", address ? address : "(null)", port ? port : "(null)");
1911
1912         if(!mesh || !node || !address) {
1913                 meshlink_errno = MESHLINK_EINVAL;
1914                 return false;
1915         }
1916
1917         if(!is_valid_hostname(address)) {
1918                 logger(mesh, MESHLINK_ERROR, "Invalid character in address: %s", address);
1919                 meshlink_errno = MESHLINK_EINVAL;
1920                 return false;
1921         }
1922
1923         if((node_t *)node != mesh->self && !port) {
1924                 logger(mesh, MESHLINK_ERROR, "Missing port number!");
1925                 meshlink_errno = MESHLINK_EINVAL;
1926                 return false;
1927
1928         }
1929
1930         if(port && !is_valid_port(port)) {
1931                 logger(mesh, MESHLINK_ERROR, "Invalid character in port: %s", address);
1932                 meshlink_errno = MESHLINK_EINVAL;
1933                 return false;
1934         }
1935
1936         char *canonical_address;
1937
1938         xasprintf(&canonical_address, "%s %s", address, port ? port : mesh->myport);
1939
1940         if(pthread_mutex_lock(&mesh->mutex) != 0) {
1941                 abort();
1942         }
1943
1944         node_t *n = (node_t *)node;
1945         free(n->canonical_address);
1946         n->canonical_address = canonical_address;
1947
1948         if(!node_write_config(mesh, n, false)) {
1949                 pthread_mutex_unlock(&mesh->mutex);
1950                 return false;
1951         }
1952
1953         pthread_mutex_unlock(&mesh->mutex);
1954
1955         return config_sync(mesh, "current");
1956 }
1957
1958 bool meshlink_clear_canonical_address(meshlink_handle_t *mesh, meshlink_node_t *node) {
1959         logger(mesh, MESHLINK_DEBUG, "meshlink_clear_canonical_address(%s)", node ? node->name : "(null)");
1960
1961         if(!mesh || !node) {
1962                 meshlink_errno = MESHLINK_EINVAL;
1963                 return false;
1964         }
1965
1966         if(pthread_mutex_lock(&mesh->mutex) != 0) {
1967                 abort();
1968         }
1969
1970         node_t *n = (node_t *)node;
1971         free(n->canonical_address);
1972         n->canonical_address = NULL;
1973
1974         if(!node_write_config(mesh, n, false)) {
1975                 pthread_mutex_unlock(&mesh->mutex);
1976                 return false;
1977         }
1978
1979         pthread_mutex_unlock(&mesh->mutex);
1980
1981         return config_sync(mesh, "current");
1982 }
1983
1984 bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) {
1985         logger(mesh, MESHLINK_DEBUG, "meshlink_join(%s)", invitation ? invitation : "(null)");
1986
1987         if(!mesh || !invitation) {
1988                 meshlink_errno = MESHLINK_EINVAL;
1989                 return false;
1990         }
1991
1992         if(mesh->storage_policy == MESHLINK_STORAGE_DISABLED) {
1993                 meshlink_errno = MESHLINK_EINVAL;
1994                 return false;
1995         }
1996
1997         join_state_t state = {
1998                 .mesh = mesh,
1999                 .sock = -1,
2000         };
2001
2002         ecdsa_t *key = NULL;
2003         ecdsa_t *hiskey = NULL;
2004
2005         //TODO: think of a better name for this variable, or of a different way to tokenize the invitation URL.
2006         char copy[strlen(invitation) + 1];
2007
2008         if(pthread_mutex_lock(&mesh->mutex) != 0) {
2009                 abort();
2010         }
2011
2012         //Before doing meshlink_join make sure we are not connected to another mesh
2013         if(mesh->threadstarted) {
2014                 logger(mesh, MESHLINK_ERROR, "Cannot join while started\n");
2015                 meshlink_errno = MESHLINK_EINVAL;
2016                 goto exit;
2017         }
2018
2019         // Refuse to join a mesh if we are already part of one. We are part of one if we know at least one other node.
2020         if(mesh->nodes->count > 1) {
2021                 logger(mesh, MESHLINK_ERROR, "Already part of an existing mesh\n");
2022                 meshlink_errno = MESHLINK_EINVAL;
2023                 goto exit;
2024         }
2025
2026         strcpy(copy, invitation);
2027
2028         // Split the invitation URL into a list of hostname/port tuples, a key hash and a cookie.
2029
2030         char *slash = strchr(copy, '/');
2031
2032         if(!slash) {
2033                 goto invalid;
2034         }
2035
2036         *slash++ = 0;
2037
2038         if(strlen(slash) != 48) {
2039                 goto invalid;
2040         }
2041
2042         char *address = copy;
2043         char *port = NULL;
2044
2045         if(!b64decode(slash, state.hash, 18) || !b64decode(slash + 24, state.cookie, 18)) {
2046                 goto invalid;
2047         }
2048
2049         if(mesh->inviter_commits_first) {
2050                 memcpy(state.cookie + 18, ecdsa_get_public_key(mesh->private_key), 32);
2051         }
2052
2053         // Generate a throw-away key for the invitation.
2054         key = ecdsa_generate();
2055
2056         if(!key) {
2057                 meshlink_errno = MESHLINK_EINTERNAL;
2058                 goto exit;
2059         }
2060
2061         char *b64key = ecdsa_get_base64_public_key(key);
2062         char *comma;
2063
2064         while(address && *address) {
2065                 // We allow commas in the address part to support multiple addresses in one invitation URL.
2066                 comma = strchr(address, ',');
2067
2068                 if(comma) {
2069                         *comma++ = 0;
2070                 }
2071
2072                 // Split of the port
2073                 port = strrchr(address, ':');
2074
2075                 if(!port) {
2076                         goto invalid;
2077                 }
2078
2079                 *port++ = 0;
2080
2081                 // IPv6 address are enclosed in brackets, per RFC 3986
2082                 if(*address == '[') {
2083                         address++;
2084                         char *bracket = strchr(address, ']');
2085
2086                         if(!bracket) {
2087                                 goto invalid;
2088                         }
2089
2090                         *bracket++ = 0;
2091
2092                         if(*bracket) {
2093                                 goto invalid;
2094                         }
2095                 }
2096
2097                 // Connect to the meshlink daemon mentioned in the URL.
2098                 struct addrinfo *ai = str2addrinfo(address, port, SOCK_STREAM);
2099
2100                 if(ai) {
2101                         for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) {
2102                                 state.sock = socket_in_netns(aip->ai_family, SOCK_STREAM, IPPROTO_TCP, mesh->netns);
2103
2104                                 if(state.sock == -1) {
2105                                         logger(mesh, MESHLINK_DEBUG, "Could not open socket: %s\n", strerror(errno));
2106                                         meshlink_errno = MESHLINK_ENETWORK;
2107                                         continue;
2108                                 }
2109
2110 #ifdef SO_NOSIGPIPE
2111                                 int nosigpipe = 1;
2112                                 setsockopt(state.sock, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(nosigpipe));
2113 #endif
2114
2115                                 set_timeout(state.sock, 5000);
2116
2117                                 if(connect(state.sock, aip->ai_addr, aip->ai_addrlen)) {
2118                                         logger(mesh, MESHLINK_DEBUG, "Could not connect to %s port %s: %s\n", address, port, strerror(errno));
2119                                         meshlink_errno = MESHLINK_ENETWORK;
2120                                         closesocket(state.sock);
2121                                         state.sock = -1;
2122                                         continue;
2123                                 }
2124
2125                                 break;
2126                         }
2127
2128                         freeaddrinfo(ai);
2129                 } else {
2130                         meshlink_errno = MESHLINK_ERESOLV;
2131                 }
2132
2133                 if(state.sock != -1 || !comma) {
2134                         break;
2135                 }
2136
2137                 address = comma;
2138         }
2139
2140         if(state.sock == -1) {
2141                 goto exit;
2142         }
2143
2144         logger(mesh, MESHLINK_DEBUG, "Connected to %s port %s...\n", address, port);
2145
2146         // Tell him we have an invitation, and give him our throw-away key.
2147
2148         state.blen = 0;
2149
2150         if(!sendline(state.sock, "0 ?%s %d.%d %s", b64key, PROT_MAJOR, PROT_MINOR, mesh->appname)) {
2151                 logger(mesh, MESHLINK_ERROR, "Error sending request to %s port %s: %s\n", address, port, strerror(errno));
2152                 meshlink_errno = MESHLINK_ENETWORK;
2153                 goto exit;
2154         }
2155
2156         free(b64key);
2157
2158         char hisname[4096] = "";
2159         int code, hismajor, hisminor = 0;
2160
2161         if(!recvline(&state) || sscanf(state.line, "%d %s %d.%d", &code, hisname, &hismajor, &hisminor) < 3 || code != 0 || hismajor != PROT_MAJOR || !check_id(hisname) || !recvline(&state) || !rstrip(state.line) || sscanf(state.line, "%d ", &code) != 1 || code != ACK || strlen(state.line) < 3) {
2162                 logger(mesh, MESHLINK_ERROR, "Cannot read greeting from peer\n");
2163                 meshlink_errno = MESHLINK_ENETWORK;
2164                 goto exit;
2165         }
2166
2167         // Check if the hash of the key he gave us matches the hash in the URL.
2168         char *fingerprint = state.line + 2;
2169         char hishash[64];
2170
2171         if(sha512(fingerprint, strlen(fingerprint), hishash)) {
2172                 logger(mesh, MESHLINK_ERROR, "Could not create hash\n%s\n", state.line + 2);
2173                 meshlink_errno = MESHLINK_EINTERNAL;
2174                 goto exit;
2175         }
2176
2177         if(memcmp(hishash, state.hash, 18)) {
2178                 logger(mesh, MESHLINK_ERROR, "Peer has an invalid key!\n%s\n", state.line + 2);
2179                 meshlink_errno = MESHLINK_EPEER;
2180                 goto exit;
2181         }
2182
2183         hiskey = ecdsa_set_base64_public_key(fingerprint);
2184
2185         if(!hiskey) {
2186                 meshlink_errno = MESHLINK_EINTERNAL;
2187                 goto exit;
2188         }
2189
2190         // Start an SPTPS session
2191         if(!sptps_start(&state.sptps, &state, true, false, key, hiskey, meshlink_invitation_label, sizeof(meshlink_invitation_label), invitation_send, invitation_receive)) {
2192                 meshlink_errno = MESHLINK_EINTERNAL;
2193                 goto exit;
2194         }
2195
2196         // Feed rest of input buffer to SPTPS
2197         if(!sptps_receive_data(&state.sptps, state.buffer, state.blen)) {
2198                 meshlink_errno = MESHLINK_EPEER;
2199                 goto exit;
2200         }
2201
2202         ssize_t len;
2203         logger(mesh, MESHLINK_DEBUG, "Starting invitation recv loop: %d %zu\n", state.sock, sizeof(state.line));
2204
2205         while((len = recv(state.sock, state.line, sizeof(state.line), 0))) {
2206                 if(len < 0) {
2207                         if(errno == EINTR) {
2208                                 continue;
2209                         }
2210
2211                         logger(mesh, MESHLINK_ERROR, "Error reading data from %s port %s: %s\n", address, port, strerror(errno));
2212                         meshlink_errno = MESHLINK_ENETWORK;
2213                         goto exit;
2214                 }
2215
2216                 if(!sptps_receive_data(&state.sptps, state.line, len)) {
2217                         meshlink_errno = MESHLINK_EPEER;
2218                         goto exit;
2219                 }
2220         }
2221
2222         if(!state.success) {
2223                 logger(mesh, MESHLINK_ERROR, "Connection closed by peer, invitation cancelled.\n");
2224                 meshlink_errno = MESHLINK_EPEER;
2225                 goto exit;
2226         }
2227
2228         sptps_stop(&state.sptps);
2229         ecdsa_free(hiskey);
2230         ecdsa_free(key);
2231         closesocket(state.sock);
2232
2233         pthread_mutex_unlock(&mesh->mutex);
2234         return true;
2235
2236 invalid:
2237         logger(mesh, MESHLINK_ERROR, "Invalid invitation URL\n");
2238         meshlink_errno = MESHLINK_EINVAL;
2239 exit:
2240         sptps_stop(&state.sptps);
2241         ecdsa_free(hiskey);
2242         ecdsa_free(key);
2243
2244         if(state.sock != -1) {
2245                 closesocket(state.sock);
2246         }
2247
2248         pthread_mutex_unlock(&mesh->mutex);
2249         return false;
2250 }
2251
2252 char *meshlink_export(meshlink_handle_t *mesh) {
2253         if(!mesh) {
2254                 meshlink_errno = MESHLINK_EINVAL;
2255                 return NULL;
2256         }
2257
2258         // Create a config file on the fly.
2259
2260         uint8_t buf[4096];
2261         packmsg_output_t out = {buf, sizeof(buf)};
2262         packmsg_add_uint32(&out, MESHLINK_CONFIG_VERSION);
2263         packmsg_add_str(&out, mesh->name);
2264         packmsg_add_str(&out, CORE_MESH);
2265
2266         if(pthread_mutex_lock(&mesh->mutex) != 0) {
2267                 abort();
2268         }
2269
2270         packmsg_add_int32(&out, mesh->self->devclass);
2271         packmsg_add_bool(&out, mesh->self->status.blacklisted);
2272         packmsg_add_bin(&out, ecdsa_get_public_key(mesh->private_key), 32);
2273
2274         if(mesh->self->canonical_address && !strchr(mesh->self->canonical_address, ' ')) {
2275                 char *canonical_address = NULL;
2276                 xasprintf(&canonical_address, "%s %s", mesh->self->canonical_address, mesh->myport);
2277                 packmsg_add_str(&out, canonical_address);
2278                 free(canonical_address);
2279         } else {
2280                 packmsg_add_str(&out, mesh->self->canonical_address ? mesh->self->canonical_address : "");
2281         }
2282
2283         uint32_t count = 0;
2284
2285         for(uint32_t i = 0; i < MAX_RECENT; i++) {
2286                 if(mesh->self->recent[i].sa.sa_family) {
2287                         count++;
2288                 } else {
2289                         break;
2290                 }
2291         }
2292
2293         packmsg_add_array(&out, count);
2294
2295         for(uint32_t i = 0; i < count; i++) {
2296                 packmsg_add_sockaddr(&out, &mesh->self->recent[i]);
2297         }
2298
2299         packmsg_add_int64(&out, 0);
2300         packmsg_add_int64(&out, 0);
2301
2302         pthread_mutex_unlock(&mesh->mutex);
2303
2304         if(!packmsg_output_ok(&out)) {
2305                 logger(mesh, MESHLINK_ERROR, "Error creating export data\n");
2306                 meshlink_errno = MESHLINK_EINTERNAL;
2307                 return NULL;
2308         }
2309
2310         // Prepare a base64-encoded packmsg array containing our config file
2311
2312         uint32_t len = packmsg_output_size(&out, buf);
2313         uint32_t len2 = ((len + 4) * 4) / 3 + 4;
2314         uint8_t *buf2 = xmalloc(len2);
2315         packmsg_output_t out2 = {buf2, len2};
2316         packmsg_add_array(&out2, 1);
2317         packmsg_add_bin(&out2, buf, packmsg_output_size(&out, buf));
2318
2319         if(!packmsg_output_ok(&out2)) {
2320                 logger(mesh, MESHLINK_ERROR, "Error creating export data\n");
2321                 meshlink_errno = MESHLINK_EINTERNAL;
2322                 free(buf2);
2323                 return NULL;
2324         }
2325
2326         b64encode_urlsafe(buf2, (char *)buf2, packmsg_output_size(&out2, buf2));
2327
2328         return (char *)buf2;
2329 }
2330
2331 bool meshlink_import(meshlink_handle_t *mesh, const char *data) {
2332         logger(mesh, MESHLINK_DEBUG, "meshlink_import(%p)", (const void *)data);
2333
2334         if(!mesh || !data) {
2335                 meshlink_errno = MESHLINK_EINVAL;
2336                 return false;
2337         }
2338
2339         size_t datalen = strlen(data);
2340         uint8_t *buf = xmalloc(datalen);
2341         int buflen = b64decode(data, buf, datalen);
2342
2343         if(!buflen) {
2344                 logger(mesh, MESHLINK_ERROR, "Invalid data\n");
2345                 free(buf);
2346                 meshlink_errno = MESHLINK_EPEER;
2347                 return false;
2348         }
2349
2350         packmsg_input_t in = {buf, buflen};
2351         uint32_t count = packmsg_get_array(&in);
2352
2353         if(!count) {
2354                 logger(mesh, MESHLINK_ERROR, "Invalid data\n");
2355                 free(buf);
2356                 meshlink_errno = MESHLINK_EPEER;
2357                 return false;
2358         }
2359
2360         if(pthread_mutex_lock(&mesh->mutex) != 0) {
2361                 abort();
2362         }
2363
2364         while(count--) {
2365                 const void *data2;
2366                 uint32_t len2 = packmsg_get_bin_raw(&in, &data2);
2367
2368                 if(!len2) {
2369                         break;
2370                 }
2371
2372                 packmsg_input_t in2 = {data2, len2};
2373                 uint32_t version = packmsg_get_uint32(&in2);
2374                 char *name = packmsg_get_str_dup(&in2);
2375
2376                 if(!packmsg_input_ok(&in2) || version != MESHLINK_CONFIG_VERSION || !check_id(name)) {
2377                         free(name);
2378                         packmsg_input_invalidate(&in);
2379                         break;
2380                 }
2381
2382                 if(!check_id(name)) {
2383                         free(name);
2384                         break;
2385                 }
2386
2387                 node_t *n = lookup_node(mesh, name);
2388
2389                 if(n) {
2390                         logger(mesh, MESHLINK_DEBUG, "Node %s already exists, not importing\n", name);
2391                         free(name);
2392                         continue;
2393                 }
2394
2395                 n = new_node();
2396                 n->name = name;
2397
2398                 config_t config = {data2, len2};
2399
2400                 if(!node_read_from_config(mesh, n, &config)) {
2401                         free_node(n);
2402                         packmsg_input_invalidate(&in);
2403                         break;
2404                 }
2405
2406                 if(!node_write_config(mesh, n, true)) {
2407                         free_node(n);
2408                         free(buf);
2409                         return false;
2410                 }
2411
2412                 node_add(mesh, n);
2413         }
2414
2415         pthread_mutex_unlock(&mesh->mutex);
2416
2417         free(buf);
2418
2419         if(!packmsg_done(&in)) {
2420                 logger(mesh, MESHLINK_ERROR, "Invalid data\n");
2421                 meshlink_errno = MESHLINK_EPEER;
2422                 return false;
2423         }
2424
2425         if(!config_sync(mesh, "current")) {
2426                 return false;
2427         }
2428
2429         return true;
2430 }
2431
2432 bool meshlink_forget_node(meshlink_handle_t *mesh, meshlink_node_t *node) {
2433         logger(mesh, MESHLINK_DEBUG, "meshlink_forget_node(%s)", node ? node->name : "(null)");
2434
2435         if(!mesh || !node) {
2436                 meshlink_errno = MESHLINK_EINVAL;
2437                 return false;
2438         }
2439
2440         node_t *n = (node_t *)node;
2441
2442         if(pthread_mutex_lock(&mesh->mutex) != 0) {
2443                 abort();
2444         }
2445
2446         /* Check that the node is not reachable */
2447         if(n->status.reachable || n->connection) {
2448                 pthread_mutex_unlock(&mesh->mutex);
2449                 logger(mesh, MESHLINK_WARNING, "Could not forget %s: still reachable", n->name);
2450                 return false;
2451         }
2452
2453         /* Check that we don't have any active UTCP connections */
2454         if(n->utcp && utcp_is_active(n->utcp)) {
2455                 pthread_mutex_unlock(&mesh->mutex);
2456                 logger(mesh, MESHLINK_WARNING, "Could not forget %s: active UTCP connections", n->name);
2457                 return false;
2458         }
2459
2460         /* Check that we have no active connections to this node */
2461         for list_each(connection_t, c, mesh->connections) {
2462                 if(c->node == n) {
2463                         pthread_mutex_unlock(&mesh->mutex);
2464                         logger(mesh, MESHLINK_WARNING, "Could not forget %s: active connection", n->name);
2465                         return false;
2466                 }
2467         }
2468
2469         /* Remove any pending outgoings to this node */
2470         if(mesh->outgoings) {
2471                 for list_each(outgoing_t, outgoing, mesh->outgoings) {
2472                         if(outgoing->node == n) {
2473                                 list_delete_node(mesh->outgoings, list_node);
2474                         }
2475                 }
2476         }
2477
2478         /* Delete the config file for this node */
2479         if(!config_delete(mesh, "current", n->name)) {
2480                 pthread_mutex_unlock(&mesh->mutex);
2481                 return false;
2482         }
2483
2484         /* Delete the node struct and any remaining edges referencing this node */
2485         node_del(mesh, n);
2486
2487         pthread_mutex_unlock(&mesh->mutex);
2488
2489         return config_sync(mesh, "current");
2490 }
2491
2492 /* Hint that a hostname may be found at an address
2493  * See header file for detailed comment.
2494  */
2495 void meshlink_hint_address(meshlink_handle_t *mesh, meshlink_node_t *node, const struct sockaddr *addr) {
2496         logger(mesh, MESHLINK_DEBUG, "meshlink_hint_address(%s, %p)", node ? node->name : "(null)", (const void *)addr);
2497
2498         if(!mesh || !node || !addr) {
2499                 meshlink_errno = EINVAL;
2500                 return;
2501         }
2502
2503         if(pthread_mutex_lock(&mesh->mutex) != 0) {
2504                 abort();
2505         }
2506
2507         node_t *n = (node_t *)node;
2508
2509         if(node_add_recent_address(mesh, n, (sockaddr_t *)addr)) {
2510                 if(!node_write_config(mesh, n, false)) {
2511                         logger(mesh, MESHLINK_DEBUG, "Could not update %s\n", n->name);
2512                 }
2513         }
2514
2515         pthread_mutex_unlock(&mesh->mutex);
2516         // @TODO do we want to fire off a connection attempt right away?
2517 }
2518
2519 static bool channel_pre_accept(struct utcp *utcp, uint16_t port) {
2520         (void)port;
2521         node_t *n = utcp->priv;
2522         meshlink_handle_t *mesh = n->mesh;
2523
2524         if(mesh->channel_accept_cb && mesh->channel_listen_cb) {
2525                 return mesh->channel_listen_cb(mesh, (meshlink_node_t *)n, port);
2526         } else {
2527                 return mesh->channel_accept_cb;
2528         }
2529 }
2530
2531 /* Finish one AIO buffer, return true if the channel is still open. */
2532 static bool aio_finish_one(meshlink_handle_t *mesh, meshlink_channel_t *channel, meshlink_aio_buffer_t **head) {
2533         meshlink_aio_buffer_t *aio = *head;
2534         *head = aio->next;
2535
2536         if(channel->c) {
2537                 channel->in_callback = true;
2538
2539                 if(aio->data) {
2540                         if(aio->cb.buffer) {
2541                                 aio->cb.buffer(mesh, channel, aio->data, aio->done, aio->priv);
2542                         }
2543                 } else {
2544                         if(aio->cb.fd) {
2545                                 aio->cb.fd(mesh, channel, aio->fd, aio->done, aio->priv);
2546                         }
2547                 }
2548
2549                 channel->in_callback = false;
2550
2551                 if(!channel->c) {
2552                         free(aio);
2553                         free(channel);
2554                         return false;
2555                 }
2556         }
2557
2558         free(aio);
2559         return true;
2560 }
2561
2562 /* Finish all AIO buffers, return true if the channel is still open. */
2563 static bool aio_abort(meshlink_handle_t *mesh, meshlink_channel_t *channel, meshlink_aio_buffer_t **head) {
2564         while(*head) {
2565                 if(!aio_finish_one(mesh, channel, head)) {
2566                         return false;
2567                 }
2568         }
2569
2570         return true;
2571 }
2572
2573 static ssize_t channel_recv(struct utcp_connection *connection, const void *data, size_t len) {
2574         meshlink_channel_t *channel = connection->priv;
2575
2576         if(!channel) {
2577                 abort();
2578         }
2579
2580         node_t *n = channel->node;
2581         meshlink_handle_t *mesh = n->mesh;
2582
2583         if(n->status.destroyed) {
2584                 meshlink_channel_close(mesh, channel);
2585                 return len;
2586         }
2587
2588         const char *p = data;
2589         size_t left = len;
2590
2591         while(channel->aio_receive) {
2592                 if(!len) {
2593                         /* This receive callback signalled an error, abort all outstanding AIO buffers. */
2594                         if(!aio_abort(mesh, channel, &channel->aio_receive)) {
2595                                 return len;
2596                         }
2597
2598                         break;
2599                 }
2600
2601                 meshlink_aio_buffer_t *aio = channel->aio_receive;
2602                 size_t todo = aio->len - aio->done;
2603
2604                 if(todo > left) {
2605                         todo = left;
2606                 }
2607
2608                 if(aio->data) {
2609                         memcpy((char *)aio->data + aio->done, p, todo);
2610                 } else {
2611                         ssize_t result = write(aio->fd, p, todo);
2612
2613                         if(result <= 0) {
2614                                 if(result < 0 && errno == EINTR) {
2615                                         continue;
2616                                 }
2617
2618                                 /* Writing to fd failed, cancel just this AIO buffer. */
2619                                 logger(mesh, MESHLINK_ERROR, "Writing to AIO fd %d failed: %s", aio->fd, strerror(errno));
2620
2621                                 if(!aio_finish_one(mesh, channel, &channel->aio_receive)) {
2622                                         return len;
2623                                 }
2624
2625                                 continue;
2626                         }
2627
2628                         todo = result;
2629                 }
2630
2631                 aio->done += todo;
2632                 p += todo;
2633                 left -= todo;
2634
2635                 if(aio->done == aio->len) {
2636                         if(!aio_finish_one(mesh, channel, &channel->aio_receive)) {
2637                                 return len;
2638                         }
2639                 }
2640
2641                 if(!left) {
2642                         return len;
2643                 }
2644         }
2645
2646         if(channel->receive_cb) {
2647                 channel->receive_cb(mesh, channel, p, left);
2648         }
2649
2650         return len;
2651 }
2652
2653 static void channel_accept(struct utcp_connection *utcp_connection, uint16_t port) {
2654         node_t *n = utcp_connection->utcp->priv;
2655
2656         if(!n) {
2657                 abort();
2658         }
2659
2660         meshlink_handle_t *mesh = n->mesh;
2661
2662         if(!mesh->channel_accept_cb) {
2663                 return;
2664         }
2665
2666         meshlink_channel_t *channel = xzalloc(sizeof(*channel));
2667         channel->node = n;
2668         channel->c = utcp_connection;
2669
2670         if(mesh->channel_accept_cb(mesh, channel, port, NULL, 0)) {
2671                 utcp_accept(utcp_connection, channel_recv, channel);
2672         } else {
2673                 free(channel);
2674         }
2675 }
2676
2677 static void channel_retransmit(struct utcp_connection *utcp_connection) {
2678         node_t *n = utcp_connection->utcp->priv;
2679         meshlink_handle_t *mesh = n->mesh;
2680
2681         if(n->mtuprobes == 31 && n->mtutimeout.cb) {
2682                 timeout_set(&mesh->loop, &n->mtutimeout, &(struct timespec) {
2683                         0, 0
2684                 });
2685         }
2686 }
2687
2688 static ssize_t channel_send(struct utcp *utcp, const void *data, size_t len) {
2689         node_t *n = utcp->priv;
2690
2691         if(n->status.destroyed) {
2692                 return -1;
2693         }
2694
2695         meshlink_handle_t *mesh = n->mesh;
2696         return meshlink_send_immediate(mesh, (meshlink_node_t *)n, data, len) ? (ssize_t)len : -1;
2697 }
2698
2699 void meshlink_set_channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, meshlink_channel_receive_cb_t cb) {
2700         logger(mesh, MESHLINK_DEBUG, "meshlink_set_channel_receive_cb(%p, %p)", (void *)channel, (void *)(intptr_t)cb);
2701
2702         if(!mesh || !channel) {
2703                 meshlink_errno = MESHLINK_EINVAL;
2704                 return;
2705         }
2706
2707         channel->receive_cb = cb;
2708 }
2709
2710 static void channel_receive(meshlink_handle_t *mesh, meshlink_node_t *source, const void *data, size_t len) {
2711         (void)mesh;
2712         node_t *n = (node_t *)source;
2713
2714         if(!n->utcp) {
2715                 abort();
2716         }
2717
2718         utcp_recv(n->utcp, data, len);
2719 }
2720
2721 static void channel_poll(struct utcp_connection *connection, size_t len) {
2722         meshlink_channel_t *channel = connection->priv;
2723
2724         if(!channel) {
2725                 abort();
2726         }
2727
2728         node_t *n = channel->node;
2729         meshlink_handle_t *mesh = n->mesh;
2730
2731         while(channel->aio_send) {
2732                 if(!len) {
2733                         /* This poll callback signalled an error, abort all outstanding AIO buffers. */
2734                         if(!aio_abort(mesh, channel, &channel->aio_send)) {
2735                                 return;
2736                         }
2737
2738                         break;
2739                 }
2740
2741                 /* We have at least one AIO buffer. Send as much as possible from the buffers. */
2742                 meshlink_aio_buffer_t *aio = channel->aio_send;
2743                 size_t todo = aio->len - aio->done;
2744                 ssize_t sent;
2745
2746                 if(todo > len) {
2747                         todo = len;
2748                 }
2749
2750                 if(aio->data) {
2751                         sent = utcp_send(connection, (char *)aio->data + aio->done, todo);
2752                 } else {
2753                         /* Limit the amount we read at once to avoid stack overflows */
2754                         if(todo > 65536) {
2755                                 todo = 65536;
2756                         }
2757
2758                         char buf[todo];
2759                         ssize_t result = read(aio->fd, buf, todo);
2760
2761                         if(result > 0) {
2762                                 todo = result;
2763                                 sent = utcp_send(connection, buf, todo);
2764                         } else {
2765                                 if(result < 0 && errno == EINTR) {
2766                                         continue;
2767                                 }
2768
2769                                 /* Reading from fd failed, cancel just this AIO buffer. */
2770                                 if(result != 0) {
2771                                         logger(mesh, MESHLINK_ERROR, "Reading from AIO fd %d failed: %s", aio->fd, strerror(errno));
2772                                 }
2773
2774                                 if(!aio_finish_one(mesh, channel, &channel->aio_send)) {
2775                                         return;
2776                                 }
2777
2778                                 continue;
2779                         }
2780                 }
2781
2782                 if(sent != (ssize_t)todo) {
2783                         /* Sending failed, abort all outstanding AIO buffers and send a poll callback. */
2784                         if(!aio_abort(mesh, channel, &channel->aio_send)) {
2785                                 return;
2786                         }
2787
2788                         len = 0;
2789                         break;
2790                 }
2791
2792                 aio->done += sent;
2793                 len -= sent;
2794
2795                 /* If we didn't finish this buffer, exit early. */
2796                 if(aio->done < aio->len) {
2797                         return;
2798                 }
2799
2800                 /* Signal completion of this buffer, and go to the next one. */
2801                 if(!aio_finish_one(mesh, channel, &channel->aio_send)) {
2802                         return;
2803                 }
2804
2805                 if(!len) {
2806                         return;
2807                 }
2808         }
2809
2810         if(channel->poll_cb) {
2811                 channel->poll_cb(mesh, channel, len);
2812         } else {
2813                 utcp_set_poll_cb(connection, NULL);
2814         }
2815 }
2816
2817 void meshlink_set_channel_poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, meshlink_channel_poll_cb_t cb) {
2818         logger(mesh, MESHLINK_DEBUG, "meshlink_set_channel_poll_cb(%p, %p)", (void *)channel, (void *)(intptr_t)cb);
2819
2820         if(!mesh || !channel) {
2821                 meshlink_errno = MESHLINK_EINVAL;
2822                 return;
2823         }
2824
2825         if(pthread_mutex_lock(&mesh->mutex) != 0) {
2826                 abort();
2827         }
2828
2829         channel->poll_cb = cb;
2830         utcp_set_poll_cb(channel->c, (cb || channel->aio_send) ? channel_poll : NULL);
2831         pthread_mutex_unlock(&mesh->mutex);
2832 }
2833
2834 void meshlink_set_channel_listen_cb(meshlink_handle_t *mesh, meshlink_channel_listen_cb_t cb) {
2835         logger(mesh, MESHLINK_DEBUG, "meshlink_set_channel_listen_cb(%p)", (void *)(intptr_t)cb);
2836
2837         if(!mesh) {
2838                 meshlink_errno = MESHLINK_EINVAL;
2839                 return;
2840         }
2841
2842         if(pthread_mutex_lock(&mesh->mutex) != 0) {
2843                 abort();
2844         }
2845
2846         mesh->channel_listen_cb = cb;
2847
2848         pthread_mutex_unlock(&mesh->mutex);
2849 }
2850
2851 void meshlink_set_channel_accept_cb(meshlink_handle_t *mesh, meshlink_channel_accept_cb_t cb) {
2852         logger(mesh, MESHLINK_DEBUG, "meshlink_set_channel_accept_cb(%p)", (void *)(intptr_t)cb);
2853
2854         if(!mesh) {
2855                 meshlink_errno = MESHLINK_EINVAL;
2856                 return;
2857         }
2858
2859         if(pthread_mutex_lock(&mesh->mutex) != 0) {
2860                 abort();
2861         }
2862
2863         mesh->channel_accept_cb = cb;
2864         mesh->receive_cb = channel_receive;
2865
2866         for splay_each(node_t, n, mesh->nodes) {
2867                 if(!n->utcp && n != mesh->self) {
2868                         n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n);
2869                         utcp_set_mtu(n->utcp, n->mtu - sizeof(meshlink_packethdr_t));
2870                         utcp_set_retransmit_cb(n->utcp, channel_retransmit);
2871                 }
2872         }
2873
2874         pthread_mutex_unlock(&mesh->mutex);
2875 }
2876
2877 void meshlink_set_channel_sndbuf(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t size) {
2878         logger(mesh, MESHLINK_DEBUG, "meshlink_set_channel_sndbuf(%p, %zu)", (void *)channel, size);
2879
2880         meshlink_set_channel_sndbuf_storage(mesh, channel, NULL, size);
2881 }
2882
2883 void meshlink_set_channel_rcvbuf(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t size) {
2884         logger(mesh, MESHLINK_DEBUG, "meshlink_set_channel_rcvbuf(%p, %zu)", (void *)channel, size);
2885
2886         meshlink_set_channel_rcvbuf_storage(mesh, channel, NULL, size);
2887 }
2888
2889 void meshlink_set_channel_sndbuf_storage(meshlink_handle_t *mesh, meshlink_channel_t *channel, void *buf, size_t size) {
2890         logger(mesh, MESHLINK_DEBUG, "meshlink_set_channel_sndbuf_storage(%p, %p, %zu)", (void *)channel, buf, size);
2891
2892         if(!mesh || !channel) {
2893                 meshlink_errno = MESHLINK_EINVAL;
2894                 return;
2895         }
2896
2897         if(pthread_mutex_lock(&mesh->mutex) != 0) {
2898                 abort();
2899         }
2900
2901         utcp_set_sndbuf(channel->c, buf, size);
2902         pthread_mutex_unlock(&mesh->mutex);
2903 }
2904
2905 void meshlink_set_channel_rcvbuf_storage(meshlink_handle_t *mesh, meshlink_channel_t *channel, void *buf, size_t size) {
2906         logger(mesh, MESHLINK_DEBUG, "meshlink_set_channel_rcvbuf_storage(%p, %p, %zu)", (void *)channel, buf, size);
2907
2908         if(!mesh || !channel) {
2909                 meshlink_errno = MESHLINK_EINVAL;
2910                 return;
2911         }
2912
2913         if(pthread_mutex_lock(&mesh->mutex) != 0) {
2914                 abort();
2915         }
2916
2917         utcp_set_rcvbuf(channel->c, buf, size);
2918         pthread_mutex_unlock(&mesh->mutex);
2919 }
2920
2921 void meshlink_set_channel_flags(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint32_t flags) {
2922         logger(mesh, MESHLINK_DEBUG, "meshlink_set_channel_flags(%p, %u)", (void *)channel, flags);
2923
2924         if(!mesh || !channel) {
2925                 meshlink_errno = MESHLINK_EINVAL;
2926                 return;
2927         }
2928
2929         if(pthread_mutex_lock(&mesh->mutex) != 0) {
2930                 abort();
2931         }
2932
2933         utcp_set_flags(channel->c, flags);
2934         pthread_mutex_unlock(&mesh->mutex);
2935 }
2936
2937 meshlink_channel_t *meshlink_channel_open_ex(meshlink_handle_t *mesh, meshlink_node_t *node, uint16_t port, meshlink_channel_receive_cb_t cb, const void *data, size_t len, uint32_t flags) {
2938         logger(mesh, MESHLINK_DEBUG, "meshlink_channel_open_ex(%s, %u, %p, %p, %zu, %u)", node ? node->name : "(null)", port, (void *)(intptr_t)cb, data, len, flags);
2939
2940         if(data && len) {
2941                 abort();        // TODO: handle non-NULL data
2942         }
2943
2944         if(!mesh || !node) {
2945                 meshlink_errno = MESHLINK_EINVAL;
2946                 return NULL;
2947         }
2948
2949         if(pthread_mutex_lock(&mesh->mutex) != 0) {
2950                 abort();
2951         }
2952
2953         node_t *n = (node_t *)node;
2954
2955         if(!n->utcp) {
2956                 n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n);
2957                 utcp_set_mtu(n->utcp, n->mtu - sizeof(meshlink_packethdr_t));
2958                 utcp_set_retransmit_cb(n->utcp, channel_retransmit);
2959                 mesh->receive_cb = channel_receive;
2960
2961                 if(!n->utcp) {
2962                         meshlink_errno = errno == ENOMEM ? MESHLINK_ENOMEM : MESHLINK_EINTERNAL;
2963                         pthread_mutex_unlock(&mesh->mutex);
2964                         return NULL;
2965                 }
2966         }
2967
2968         if(n->status.blacklisted) {
2969                 logger(mesh, MESHLINK_ERROR, "Cannot open a channel with blacklisted node\n");
2970                 meshlink_errno = MESHLINK_EBLACKLISTED;
2971                 pthread_mutex_unlock(&mesh->mutex);
2972                 return NULL;
2973         }
2974
2975         meshlink_channel_t *channel = xzalloc(sizeof(*channel));
2976         channel->node = n;
2977         channel->receive_cb = cb;
2978
2979         if(data && !len) {
2980                 channel->priv = (void *)data;
2981         }
2982
2983         channel->c = utcp_connect_ex(n->utcp, port, channel_recv, channel, flags);
2984
2985         pthread_mutex_unlock(&mesh->mutex);
2986
2987         if(!channel->c) {
2988                 meshlink_errno = errno == ENOMEM ? MESHLINK_ENOMEM : MESHLINK_EINTERNAL;
2989                 free(channel);
2990                 return NULL;
2991         }
2992
2993         return channel;
2994 }
2995
2996 meshlink_channel_t *meshlink_channel_open(meshlink_handle_t *mesh, meshlink_node_t *node, uint16_t port, meshlink_channel_receive_cb_t cb, const void *data, size_t len) {
2997         logger(mesh, MESHLINK_DEBUG, "meshlink_channel_open_ex(%s, %u, %p, %p, %zu)", node ? node->name : "(null)", port, (void *)(intptr_t)cb, data, len);
2998
2999         return meshlink_channel_open_ex(mesh, node, port, cb, data, len, MESHLINK_CHANNEL_TCP);
3000 }
3001
3002 void meshlink_channel_shutdown(meshlink_handle_t *mesh, meshlink_channel_t *channel, int direction) {
3003         logger(mesh, MESHLINK_DEBUG, "meshlink_channel_shutdown(%p, %d)", (void *)channel, direction);
3004
3005         if(!mesh || !channel) {
3006                 meshlink_errno = MESHLINK_EINVAL;
3007                 return;
3008         }
3009
3010         if(pthread_mutex_lock(&mesh->mutex) != 0) {
3011                 abort();
3012         }
3013
3014         utcp_shutdown(channel->c, direction);
3015         pthread_mutex_unlock(&mesh->mutex);
3016 }
3017
3018 void meshlink_channel_close(meshlink_handle_t *mesh, meshlink_channel_t *channel) {
3019         logger(mesh, MESHLINK_DEBUG, "meshlink_channel_close(%p)", (void *)channel);
3020
3021         if(!mesh || !channel) {
3022                 meshlink_errno = MESHLINK_EINVAL;
3023                 return;
3024         }
3025
3026         if(pthread_mutex_lock(&mesh->mutex) != 0) {
3027                 abort();
3028         }
3029
3030         if(channel->c) {
3031                 utcp_close(channel->c);
3032                 channel->c = NULL;
3033
3034                 /* Clean up any outstanding AIO buffers. */
3035                 aio_abort(mesh, channel, &channel->aio_send);
3036                 aio_abort(mesh, channel, &channel->aio_receive);
3037         }
3038
3039         if(!channel->in_callback) {
3040                 free(channel);
3041         }
3042
3043         pthread_mutex_unlock(&mesh->mutex);
3044 }
3045
3046 void meshlink_channel_abort(meshlink_handle_t *mesh, meshlink_channel_t *channel) {
3047         logger(mesh, MESHLINK_DEBUG, "meshlink_channel_abort(%p)", (void *)channel);
3048
3049         if(!mesh || !channel) {
3050                 meshlink_errno = MESHLINK_EINVAL;
3051                 return;
3052         }
3053
3054         if(pthread_mutex_lock(&mesh->mutex) != 0) {
3055                 abort();
3056         }
3057
3058         if(channel->c) {
3059                 utcp_abort(channel->c);
3060                 channel->c = NULL;
3061
3062                 /* Clean up any outstanding AIO buffers. */
3063                 aio_abort(mesh, channel, &channel->aio_send);
3064                 aio_abort(mesh, channel, &channel->aio_receive);
3065         }
3066
3067         if(!channel->in_callback) {
3068                 free(channel);
3069         }
3070
3071         pthread_mutex_unlock(&mesh->mutex);
3072 }
3073
3074 ssize_t meshlink_channel_send(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
3075         logger(mesh, MESHLINK_DEBUG, "meshlink_channel_send(%p, %p, %zu)", (void *)channel, data, len);
3076
3077         if(!mesh || !channel) {
3078                 meshlink_errno = MESHLINK_EINVAL;
3079                 return -1;
3080         }
3081
3082         if(!len) {
3083                 return 0;
3084         }
3085
3086         if(!data) {
3087                 meshlink_errno = MESHLINK_EINVAL;
3088                 return -1;
3089         }
3090
3091         // TODO: more finegrained locking.
3092         // Ideally we want to put the data into the UTCP connection's send buffer.
3093         // Then, preferably only if there is room in the receiver window,
3094         // kick the meshlink thread to go send packets.
3095
3096         ssize_t retval;
3097
3098         if(pthread_mutex_lock(&mesh->mutex) != 0) {
3099                 abort();
3100         }
3101
3102         /* Disallow direct calls to utcp_send() while we still have AIO active. */
3103         if(channel->aio_send) {
3104                 retval = 0;
3105         } else {
3106                 retval = utcp_send(channel->c, data, len);
3107         }
3108
3109         pthread_mutex_unlock(&mesh->mutex);
3110
3111         if(retval < 0) {
3112                 meshlink_errno = MESHLINK_ENETWORK;
3113         }
3114
3115         return retval;
3116 }
3117
3118 bool meshlink_channel_aio_send(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len, meshlink_aio_cb_t cb, void *priv) {
3119         logger(mesh, MESHLINK_DEBUG, "meshlink_channel_aio_send(%p, %p, %zu, %p, %p)", (void *)channel, data, len, (void *)(intptr_t)cb, priv);
3120
3121         if(!mesh || !channel) {
3122                 meshlink_errno = MESHLINK_EINVAL;
3123                 return false;
3124         }
3125
3126         if(!len || !data) {
3127                 meshlink_errno = MESHLINK_EINVAL;
3128                 return false;
3129         }
3130
3131         meshlink_aio_buffer_t *aio = xzalloc(sizeof(*aio));
3132         aio->data = data;
3133         aio->len = len;
3134         aio->cb.buffer = cb;
3135         aio->priv = priv;
3136
3137         if(pthread_mutex_lock(&mesh->mutex) != 0) {
3138                 abort();
3139         }
3140
3141         /* Append the AIO buffer descriptor to the end of the chain */
3142         meshlink_aio_buffer_t **p = &channel->aio_send;
3143
3144         while(*p) {
3145                 p = &(*p)->next;
3146         }
3147
3148         *p = aio;
3149
3150         /* Ensure the poll callback is set, and call it right now to push data if possible */
3151         utcp_set_poll_cb(channel->c, channel_poll);
3152         size_t todo = MIN(len, utcp_get_rcvbuf_free(channel->c));
3153
3154         if(todo) {
3155                 channel_poll(channel->c, todo);
3156         }
3157
3158         pthread_mutex_unlock(&mesh->mutex);
3159
3160         return true;
3161 }
3162
3163 bool meshlink_channel_aio_fd_send(meshlink_handle_t *mesh, meshlink_channel_t *channel, int fd, size_t len, meshlink_aio_fd_cb_t cb, void *priv) {
3164         logger(mesh, MESHLINK_DEBUG, "meshlink_channel_aio_fd_send(%p, %d, %zu, %p, %p)", (void *)channel, fd, len, (void *)(intptr_t)cb, priv);
3165
3166         if(!mesh || !channel) {
3167                 meshlink_errno = MESHLINK_EINVAL;
3168                 return false;
3169         }
3170
3171         if(!len || fd == -1) {
3172                 meshlink_errno = MESHLINK_EINVAL;
3173                 return false;
3174         }
3175
3176         meshlink_aio_buffer_t *aio = xzalloc(sizeof(*aio));
3177         aio->fd = fd;
3178         aio->len = len;
3179         aio->cb.fd = cb;
3180         aio->priv = priv;
3181
3182         if(pthread_mutex_lock(&mesh->mutex) != 0) {
3183                 abort();
3184         }
3185
3186         /* Append the AIO buffer descriptor to the end of the chain */
3187         meshlink_aio_buffer_t **p = &channel->aio_send;
3188
3189         while(*p) {
3190                 p = &(*p)->next;
3191         }
3192
3193         *p = aio;
3194
3195         /* Ensure the poll callback is set, and call it right now to push data if possible */
3196         utcp_set_poll_cb(channel->c, channel_poll);
3197         size_t left = utcp_get_rcvbuf_free(channel->c);
3198
3199         if(left) {
3200                 channel_poll(channel->c, left);
3201         }
3202
3203         pthread_mutex_unlock(&mesh->mutex);
3204
3205         return true;
3206 }
3207
3208 bool meshlink_channel_aio_receive(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len, meshlink_aio_cb_t cb, void *priv) {
3209         logger(mesh, MESHLINK_DEBUG, "meshlink_channel_aio_receive(%p, %p, %zu, %p, %p)", (void *)channel, data, len, (void *)(intptr_t)cb, priv);
3210
3211         if(!mesh || !channel) {
3212                 meshlink_errno = MESHLINK_EINVAL;
3213                 return false;
3214         }
3215
3216         if(!len || !data) {
3217                 meshlink_errno = MESHLINK_EINVAL;
3218                 return false;
3219         }
3220
3221         meshlink_aio_buffer_t *aio = xzalloc(sizeof(*aio));
3222         aio->data = data;
3223         aio->len = len;
3224         aio->cb.buffer = cb;
3225         aio->priv = priv;
3226
3227         if(pthread_mutex_lock(&mesh->mutex) != 0) {
3228                 abort();
3229         }
3230
3231         /* Append the AIO buffer descriptor to the end of the chain */
3232         meshlink_aio_buffer_t **p = &channel->aio_receive;
3233
3234         while(*p) {
3235                 p = &(*p)->next;
3236         }
3237
3238         *p = aio;
3239
3240         pthread_mutex_unlock(&mesh->mutex);
3241
3242         return true;
3243 }
3244
3245 bool meshlink_channel_aio_fd_receive(meshlink_handle_t *mesh, meshlink_channel_t *channel, int fd, size_t len, meshlink_aio_fd_cb_t cb, void *priv) {
3246         logger(mesh, MESHLINK_DEBUG, "meshlink_channel_aio_fd_receive(%p, %d, %zu, %p, %p)", (void *)channel, fd, len, (void *)(intptr_t)cb, priv);
3247
3248         if(!mesh || !channel) {
3249                 meshlink_errno = MESHLINK_EINVAL;
3250                 return false;
3251         }
3252
3253         if(!len || fd == -1) {
3254                 meshlink_errno = MESHLINK_EINVAL;
3255                 return false;
3256         }
3257
3258         meshlink_aio_buffer_t *aio = xzalloc(sizeof(*aio));
3259         aio->fd = fd;
3260         aio->len = len;
3261         aio->cb.fd = cb;
3262         aio->priv = priv;
3263
3264         if(pthread_mutex_lock(&mesh->mutex) != 0) {
3265                 abort();
3266         }
3267
3268         /* Append the AIO buffer descriptor to the end of the chain */
3269         meshlink_aio_buffer_t **p = &channel->aio_receive;
3270
3271         while(*p) {
3272                 p = &(*p)->next;
3273         }
3274
3275         *p = aio;
3276
3277         pthread_mutex_unlock(&mesh->mutex);
3278
3279         return true;
3280 }
3281
3282 uint32_t meshlink_channel_get_flags(meshlink_handle_t *mesh, meshlink_channel_t *channel) {
3283         if(!mesh || !channel) {
3284                 meshlink_errno = MESHLINK_EINVAL;
3285                 return -1;
3286         }
3287
3288         return channel->c->flags;
3289 }
3290
3291 size_t meshlink_channel_get_sendq(meshlink_handle_t *mesh, meshlink_channel_t *channel) {
3292         if(!mesh || !channel) {
3293                 meshlink_errno = MESHLINK_EINVAL;
3294                 return -1;
3295         }
3296
3297         return utcp_get_sendq(channel->c);
3298 }
3299
3300 size_t meshlink_channel_get_recvq(meshlink_handle_t *mesh, meshlink_channel_t *channel) {
3301         if(!mesh || !channel) {
3302                 meshlink_errno = MESHLINK_EINVAL;
3303                 return -1;
3304         }
3305
3306         return utcp_get_recvq(channel->c);
3307 }
3308
3309 size_t meshlink_channel_get_mss(meshlink_handle_t *mesh, meshlink_channel_t *channel) {
3310         if(!mesh || !channel) {
3311                 meshlink_errno = MESHLINK_EINVAL;
3312                 return -1;
3313         }
3314
3315         return utcp_get_mss(channel->node->utcp);
3316 }
3317
3318 void meshlink_set_node_channel_timeout(meshlink_handle_t *mesh, meshlink_node_t *node, int timeout) {
3319         logger(mesh, MESHLINK_DEBUG, "meshlink_set_node_channel_timeout(%s, %d)", node ? node->name : "(null)", timeout);
3320
3321         if(!mesh || !node) {
3322                 meshlink_errno = MESHLINK_EINVAL;
3323                 return;
3324         }
3325
3326         node_t *n = (node_t *)node;
3327
3328         if(pthread_mutex_lock(&mesh->mutex) != 0) {
3329                 abort();
3330         }
3331
3332         if(!n->utcp) {
3333                 n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n);
3334                 utcp_set_mtu(n->utcp, n->mtu - sizeof(meshlink_packethdr_t));
3335                 utcp_set_retransmit_cb(n->utcp, channel_retransmit);
3336         }
3337
3338         utcp_set_user_timeout(n->utcp, timeout);
3339
3340         pthread_mutex_unlock(&mesh->mutex);
3341 }
3342
3343 void update_node_status(meshlink_handle_t *mesh, node_t *n) {
3344         if(n->status.reachable && mesh->channel_accept_cb && !n->utcp) {
3345                 n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n);
3346                 utcp_set_mtu(n->utcp, n->mtu - sizeof(meshlink_packethdr_t));
3347                 utcp_set_retransmit_cb(n->utcp, channel_retransmit);
3348         }
3349
3350         if(mesh->node_status_cb) {
3351                 mesh->node_status_cb(mesh, (meshlink_node_t *)n, n->status.reachable && !n->status.blacklisted);
3352         }
3353
3354         if(mesh->node_pmtu_cb) {
3355                 mesh->node_pmtu_cb(mesh, (meshlink_node_t *)n, n->minmtu);
3356         }
3357 }
3358
3359 void update_node_pmtu(meshlink_handle_t *mesh, node_t *n) {
3360         utcp_set_mtu(n->utcp, (n->minmtu > MINMTU ? n->minmtu : MINMTU) - sizeof(meshlink_packethdr_t));
3361
3362         if(mesh->node_pmtu_cb && !n->status.blacklisted) {
3363                 mesh->node_pmtu_cb(mesh, (meshlink_node_t *)n, n->minmtu);
3364         }
3365 }
3366
3367 void handle_duplicate_node(meshlink_handle_t *mesh, node_t *n) {
3368         if(!mesh->node_duplicate_cb || n->status.duplicate) {
3369                 return;
3370         }
3371
3372         n->status.duplicate = true;
3373         mesh->node_duplicate_cb(mesh, (meshlink_node_t *)n);
3374 }
3375
3376 void meshlink_hint_network_change(struct meshlink_handle *mesh) {
3377         logger(mesh, MESHLINK_DEBUG, "meshlink_hint_network_change()");
3378
3379         if(!mesh) {
3380                 meshlink_errno = MESHLINK_EINVAL;
3381                 return;
3382         }
3383
3384         if(pthread_mutex_lock(&mesh->mutex) != 0) {
3385                 abort();
3386         }
3387
3388         pthread_mutex_unlock(&mesh->mutex);
3389 }
3390
3391 void meshlink_set_dev_class_timeouts(meshlink_handle_t *mesh, dev_class_t devclass, int pinginterval, int pingtimeout) {
3392         logger(mesh, MESHLINK_DEBUG, "meshlink_set_dev_class_timeouts(%d, %d, %d)", devclass, pinginterval, pingtimeout);
3393
3394         if(!mesh || devclass < 0 || devclass >= DEV_CLASS_COUNT) {
3395                 meshlink_errno = EINVAL;
3396                 return;
3397         }
3398
3399         if(pinginterval < 1 || pingtimeout < 1 || pingtimeout > pinginterval) {
3400                 meshlink_errno = EINVAL;
3401                 return;
3402         }
3403
3404         if(pthread_mutex_lock(&mesh->mutex) != 0) {
3405                 abort();
3406         }
3407
3408         mesh->dev_class_traits[devclass].pinginterval = pinginterval;
3409         mesh->dev_class_traits[devclass].pingtimeout = pingtimeout;
3410         pthread_mutex_unlock(&mesh->mutex);
3411 }
3412
3413 void meshlink_set_dev_class_fast_retry_period(meshlink_handle_t *mesh, dev_class_t devclass, int fast_retry_period) {
3414         logger(mesh, MESHLINK_DEBUG, "meshlink_set_dev_class_fast_retry_period(%d, %d)", devclass, fast_retry_period);
3415
3416         if(!mesh || devclass < 0 || devclass >= DEV_CLASS_COUNT) {
3417                 meshlink_errno = EINVAL;
3418                 return;
3419         }
3420
3421         if(fast_retry_period < 0) {
3422                 meshlink_errno = EINVAL;
3423                 return;
3424         }
3425
3426         if(pthread_mutex_lock(&mesh->mutex) != 0) {
3427                 abort();
3428         }
3429
3430         mesh->dev_class_traits[devclass].fast_retry_period = fast_retry_period;
3431         pthread_mutex_unlock(&mesh->mutex);
3432 }
3433
3434 void meshlink_set_dev_class_maxtimeout(struct meshlink_handle *mesh, dev_class_t devclass, int maxtimeout) {
3435         logger(mesh, MESHLINK_DEBUG, "meshlink_set_dev_class_fast_maxtimeout(%d, %d)", devclass, maxtimeout);
3436
3437         if(!mesh || devclass < 0 || devclass >= DEV_CLASS_COUNT) {
3438                 meshlink_errno = EINVAL;
3439                 return;
3440         }
3441
3442         if(maxtimeout < 0) {
3443                 meshlink_errno = EINVAL;
3444                 return;
3445         }
3446
3447         if(pthread_mutex_lock(&mesh->mutex) != 0) {
3448                 abort();
3449         }
3450
3451         mesh->dev_class_traits[devclass].maxtimeout = maxtimeout;
3452         pthread_mutex_unlock(&mesh->mutex);
3453 }
3454
3455 void meshlink_reset_timers(struct meshlink_handle *mesh) {
3456         logger(mesh, MESHLINK_DEBUG, "meshlink_reset_timers()");
3457
3458         if(!mesh) {
3459                 return;
3460         }
3461
3462         if(pthread_mutex_lock(&mesh->mutex) != 0) {
3463                 abort();
3464         }
3465
3466         handle_network_change(mesh, true);
3467
3468         pthread_mutex_unlock(&mesh->mutex);
3469 }
3470
3471 void meshlink_set_inviter_commits_first(struct meshlink_handle *mesh, bool inviter_commits_first) {
3472         logger(mesh, MESHLINK_DEBUG, "meshlink_set_inviter_commits_first(%d)", inviter_commits_first);
3473
3474         if(!mesh) {
3475                 meshlink_errno = EINVAL;
3476                 return;
3477         }
3478
3479         if(pthread_mutex_lock(&mesh->mutex) != 0) {
3480                 abort();
3481         }
3482
3483         mesh->inviter_commits_first = inviter_commits_first;
3484         pthread_mutex_unlock(&mesh->mutex);
3485 }
3486
3487 void meshlink_set_scheduling_granularity(struct meshlink_handle *mesh, long granularity) {
3488         logger(mesh, MESHLINK_DEBUG, "meshlink_set_scheduling_granularity(%ld)", granularity);
3489
3490         if(!mesh || granularity < 0) {
3491                 meshlink_errno = EINVAL;
3492                 return;
3493         }
3494
3495         utcp_set_clock_granularity(granularity);
3496 }
3497
3498 void meshlink_set_storage_policy(struct meshlink_handle *mesh, meshlink_storage_policy_t policy) {
3499         logger(mesh, MESHLINK_DEBUG, "meshlink_set_storage_policy(%d)", policy);
3500
3501         if(!mesh) {
3502                 meshlink_errno = EINVAL;
3503                 return;
3504         }
3505
3506         if(pthread_mutex_lock(&mesh->mutex) != 0) {
3507                 abort();
3508         }
3509
3510         mesh->storage_policy = policy;
3511         pthread_mutex_unlock(&mesh->mutex);
3512 }
3513
3514 void handle_network_change(meshlink_handle_t *mesh, bool online) {
3515         (void)online;
3516
3517         if(!mesh->connections || !mesh->loop.running) {
3518                 return;
3519         }
3520
3521         retry(mesh);
3522         signal_trigger(&mesh->loop, &mesh->datafromapp);
3523 }
3524
3525 void call_error_cb(meshlink_handle_t *mesh, meshlink_errno_t cb_errno) {
3526         // We should only call the callback function if we are in the background thread.
3527         if(!mesh->error_cb) {
3528                 return;
3529         }
3530
3531         if(!mesh->threadstarted) {
3532                 return;
3533         }
3534
3535         if(mesh->thread == pthread_self()) {
3536                 mesh->error_cb(mesh, cb_errno);
3537         }
3538 }
3539
3540 static void __attribute__((constructor)) meshlink_init(void) {
3541         crypto_init();
3542         utcp_set_clock_granularity(10000);
3543 }
3544
3545 static void __attribute__((destructor)) meshlink_exit(void) {
3546         crypto_exit();
3547 }