#include "system.h"
#include <pthread.h>
+#include "adns.h"
#include "crypto.h"
#include "ecdsagen.h"
#include "logger.h"
#include "meshlink_internal.h"
+#include "net.h"
#include "netutl.h"
#include "node.h"
#include "submesh.h"
mesh->submeshes = NULL;
mesh->log_cb = global_log_cb;
mesh->log_level = global_log_level;
+ mesh->packet = xmalloc(sizeof(vpn_packet_t));
randomize(&mesh->prng_state, sizeof(mesh->prng_state));
}
init_outgoings(mesh);
+ init_adns(mesh);
// Start the main thread
}
}
+ exit_adns(mesh);
exit_outgoings(mesh);
// Ensure we are considered unreachable
free(mesh->confbase);
free(mesh->config_key);
free(mesh->external_address_url);
+ free(mesh->packet);
ecdsa_free(mesh->private_key);
if(mesh->invitation_addresses) {
pthread_mutex_unlock(&mesh->mutex);
}
-static vpn_packet_t *prepare_packet(meshlink_handle_t *mesh, meshlink_node_t *destination, const void *data, size_t len) {
+static bool prepare_packet(meshlink_handle_t *mesh, meshlink_node_t *destination, const void *data, size_t len, vpn_packet_t *packet) {
meshlink_packethdr_t *hdr;
if(len >= MAXSIZE - sizeof(*hdr)) {
meshlink_errno = MESHLINK_EINVAL;
- return NULL;
+ return false;
}
node_t *n = (node_t *)destination;
if(n->status.blacklisted) {
logger(mesh, MESHLINK_ERROR, "Node %s blacklisted, dropping packet\n", n->name);
meshlink_errno = MESHLINK_EBLACKLISTED;
- return NULL;
+ return false;
}
// Prepare the packet
- vpn_packet_t *packet = malloc(sizeof(*packet));
-
- if(!packet) {
- meshlink_errno = MESHLINK_ENOMEM;
- return NULL;
- }
-
packet->probe = false;
packet->tcp = false;
packet->len = len + sizeof(*hdr);
memcpy(packet->data + sizeof(*hdr), data, len);
- return packet;
+ return true;
}
static bool meshlink_send_immediate(meshlink_handle_t *mesh, meshlink_node_t *destination, const void *data, size_t len) {
assert(len);
// Prepare the packet
- vpn_packet_t *packet = prepare_packet(mesh, destination, data, len);
-
- if(!packet) {
+ if(!prepare_packet(mesh, destination, data, len, mesh->packet)) {
return false;
}
// Send it immediately
- route(mesh, mesh->self, packet);
- free(packet);
+ route(mesh, mesh->self, mesh->packet);
return true;
}
}
// Prepare the packet
- vpn_packet_t *packet = prepare_packet(mesh, destination, data, len);
+ vpn_packet_t *packet = malloc(sizeof(*packet));
if(!packet) {
+ meshlink_errno = MESHLINK_ENOMEM;
return false;
}
+ if(!prepare_packet(mesh, destination, data, len, packet)) {
+ free(packet);
+ }
+
// Queue it
if(!meshlink_queue_push(&mesh->outpacketqueue, packet)) {
free(packet);
for splay_each(node_t, n, mesh->nodes) {
if(!n->utcp && n != mesh->self) {
n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n);
+ utcp_set_mtu(n->utcp, n->mtu - sizeof(meshlink_packethdr_t));
}
}
if(!n->utcp) {
n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n);
+ utcp_set_mtu(n->utcp, n->mtu - sizeof(meshlink_packethdr_t));
mesh->receive_cb = channel_receive;
if(!n->utcp) {
return utcp_get_recvq(channel->c);
}
+size_t meshlink_channel_get_mss(meshlink_handle_t *mesh, meshlink_channel_t *channel) {
+ if(!mesh || !channel) {
+ meshlink_errno = MESHLINK_EINVAL;
+ return -1;
+ }
+
+ return utcp_get_mss(channel->node->utcp);
+}
+
void meshlink_set_node_channel_timeout(meshlink_handle_t *mesh, meshlink_node_t *node, int timeout) {
if(!mesh || !node) {
meshlink_errno = MESHLINK_EINVAL;
if(!n->utcp) {
n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n);
+ utcp_set_mtu(n->utcp, n->mtu - sizeof(meshlink_packethdr_t));
}
utcp_set_user_timeout(n->utcp, timeout);
void update_node_status(meshlink_handle_t *mesh, node_t *n) {
if(n->status.reachable && mesh->channel_accept_cb && !n->utcp) {
n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n);
+ utcp_set_mtu(n->utcp, n->mtu - sizeof(meshlink_packethdr_t));
}
if(mesh->node_status_cb) {
}
void update_node_pmtu(meshlink_handle_t *mesh, node_t *n) {
+ utcp_set_mtu(n->utcp, (n->minmtu > MINMTU ? n->minmtu : MINMTU) - sizeof(meshlink_packethdr_t));
+
if(mesh->node_pmtu_cb && !n->status.blacklisted) {
mesh->node_pmtu_cb(mesh, (meshlink_node_t *)n, n->minmtu);
}
pthread_mutex_unlock(&mesh->mutex);
}
+void meshlink_set_scheduling_granularity(struct meshlink_handle *mesh, long granularity) {
+ if(!mesh || granularity < 0) {
+ meshlink_errno = EINVAL;
+ return;
+ }
+
+ utcp_set_clock_granularity(granularity);
+}
+
void handle_network_change(meshlink_handle_t *mesh, bool online) {
(void)online;
static void __attribute__((constructor)) meshlink_init(void) {
crypto_init();
+ utcp_set_clock_granularity(10000);
}
static void __attribute__((destructor)) meshlink_exit(void) {