uint16_t invitation: 1; /* 1 if this is an invitation */
uint16_t invitation_used: 1; /* 1 if the invitation has been consumed */
uint16_t initiator: 1; /* 1 if we initiated this connection */
+ uint16_t raw_packet: 1; /* 1 if we are expecting a raw packet next */
} connection_status_t;
#include "ecdsa.h"
channel->receive_cb = cb;
}
-static void channel_receive(meshlink_handle_t *mesh, meshlink_node_t *source, const void *data, size_t len) {
+void channel_receive(meshlink_handle_t *mesh, meshlink_node_t *source, const void *data, size_t len) {
(void)mesh;
node_t *n = (node_t *)source;
}
mesh->channel_accept_cb = cb;
- mesh->receive_cb = channel_receive;
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));
utcp_set_retransmit_cb(n->utcp, channel_retransmit);
- mesh->receive_cb = channel_receive;
if(!n->utcp) {
meshlink_errno = errno == ENOMEM ? MESHLINK_ENOMEM : MESHLINK_EINTERNAL;
void handle_duplicate_node(meshlink_handle_t *mesh, struct node_t *n);
void handle_network_change(meshlink_handle_t *mesh, bool online);
void call_error_cb(meshlink_handle_t *mesh, meshlink_errno_t meshlink_errno);
+void channel_receive(meshlink_handle_t *mesh, meshlink_node_t *node, const void *data, size_t len);
/// Per-instance PRNG
static inline int prng(meshlink_handle_t *mesh, uint64_t max) {
bool send_meta(meshlink_handle_t *mesh, connection_t *c, const char *buffer, int length) {
assert(c);
assert(buffer);
- assert(length);
+ assert(length >= 0);
logger(mesh, MESHLINK_DEBUG, "Sending %d bytes of metadata to %s", length, c->name);
return true;
}
- /* Are we receiving a TCPpacket? */
+ /* Are we receiving a raw packet? */
+
+ if(c->status.raw_packet) {
+ c->status.raw_packet = false;
- if(c->tcplen) {
- abort(); // TODO: get rid of tcplen altogether
+ if(mesh->receive_cb) {
+ mesh->receive_cb(mesh, (meshlink_node_t *)c->node, data, length);
+ }
+
+ return true;
}
/* Change newline to null byte, just like non-SPTPS requests */
}
if(!n->status.validkey) {
+ if(n->connection && (n->connection->flags & PROTOCOL_TINY) & n->connection->status.active) {
+ send_raw_packet(mesh, n->connection, origpkt);
+ return;
+ }
+
logger(mesh, MESHLINK_INFO, "No valid key known yet for %s", n->name);
if(!n->status.waitingforkey) {
[KEY_CHANGED] = key_changed_h,
[REQ_KEY] = req_key_h,
[ANS_KEY] = ans_key_h,
+ [PACKET] = raw_packet_h,
};
/* Request names */
[KEY_CHANGED] = "KEY_CHANGED",
[REQ_KEY] = "REQ_KEY",
[ANS_KEY] = "ANS_KEY",
+ [PACKET] = "PACKET",
};
bool check_id(const char *id) {
bool send_del_edge(struct meshlink_handle *mesh, struct connection_t *, const struct edge_t *, int contradictions);
bool send_req_key(struct meshlink_handle *mesh, struct node_t *);
bool send_canonical_address(struct meshlink_handle *mesh, struct node_t *);
+bool send_raw_packet(struct meshlink_handle *mesh, struct connection_t *, const vpn_packet_t *);
/* Request handlers */
bool req_key_h(struct meshlink_handle *mesh, struct connection_t *, const char *);
bool ans_key_h(struct meshlink_handle *mesh, struct connection_t *, const char *);
bool tcppacket_h(struct meshlink_handle *mesh, struct connection_t *, const char *);
+bool raw_packet_h(struct meshlink_handle *mesh, struct connection_t *, const char *);
#endif
// This should never happen with MeshLink.
return false;
}
+
+bool send_raw_packet(meshlink_handle_t *mesh, connection_t *c, const vpn_packet_t *packet) {
+ size_t hdrsize = sizeof(meshlink_packethdr_t);
+ assert(packet->len >= hdrsize);
+ return send_request(mesh, c, NULL, "%d", PACKET) && send_meta(mesh, c, (const char *)packet->data + hdrsize, packet->len - hdrsize);
+}
+
+bool raw_packet_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
+ (void)mesh;
+ (void)request;
+ c->status.raw_packet = true;
+ return true;
+}
logger(mesh, MESHLINK_DEBUG, "I received a packet for me with payload: %s\n", hex);
- if(mesh->receive_cb) {
+ if(source->utcp) {
+ channel_receive(mesh, (meshlink_node_t *)source, payload, len);
+ } else if(mesh->receive_cb) {
mesh->receive_cb(mesh, (meshlink_node_t *)source, payload, len);
}