pthread_mutex_unlock(&mesh->mutex);
}
-bool meshlink_send(meshlink_handle_t *mesh, meshlink_node_t *destination, const void *data, size_t len) {
+static vpn_packet_t *prepare_packet(meshlink_handle_t *mesh, meshlink_node_t *destination, const void *data, size_t len) {
meshlink_packethdr_t *hdr;
- // Validate arguments
- if(!mesh || !destination || len >= MAXSIZE - sizeof(*hdr)) {
+ if(len >= MAXSIZE - sizeof(*hdr)) {
meshlink_errno = MESHLINK_EINVAL;
- return false;
- }
-
- if(!len) {
- return true;
- }
-
- if(!data) {
- meshlink_errno = MESHLINK_EINVAL;
- return false;
+ return NULL;
}
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 false;
+ return NULL;
}
// Prepare the packet
if(!packet) {
meshlink_errno = MESHLINK_ENOMEM;
- return false;
+ return NULL;
}
packet->probe = false;
memcpy(packet->data + sizeof(*hdr), data, len);
+ return packet;
+}
+
+static bool meshlink_send_immediate(meshlink_handle_t *mesh, meshlink_node_t *destination, const void *data, size_t len) {
+ assert(mesh);
+ assert(destination);
+ assert(data);
+ assert(len);
+
+ // Prepare the packet
+ vpn_packet_t *packet = prepare_packet(mesh, destination, data, len);
+
+ if(!packet) {
+ return false;
+ }
+
+ // Send it immediately
+ route(mesh, mesh->self, packet);
+ free(packet);
+
+ return true;
+}
+
+bool meshlink_send(meshlink_handle_t *mesh, meshlink_node_t *destination, const void *data, size_t len) {
+ // Validate arguments
+ if(!mesh || !destination) {
+ meshlink_errno = MESHLINK_EINVAL;
+ return false;
+ }
+
+ if(!len) {
+ return true;
+ }
+
+ if(!data) {
+ meshlink_errno = MESHLINK_EINVAL;
+ return false;
+ }
+
+ // Prepare the packet
+ vpn_packet_t *packet = prepare_packet(mesh, destination, data, len);
+
+ if(!packet) {
+ return false;
+ }
+
// Queue it
if(!meshlink_queue_push(&mesh->outpacketqueue, packet)) {
free(packet);
}
meshlink_handle_t *mesh = n->mesh;
- return meshlink_send(mesh, (meshlink_node_t *)n, data, len) ? (ssize_t)len : -1;
+ return meshlink_send_immediate(mesh, (meshlink_node_t *)n, data, len) ? (ssize_t)len : -1;
}
void meshlink_set_channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, meshlink_channel_receive_cb_t cb) {