}
static bool commit_invitation(meshlink_handle_t *mesh, connection_t *c, const void *data) {
+ // Check if the node is known
+ node_t *n = lookup_node(mesh, c->name);
+
+ if(n) {
+ if(n->status.blacklisted) {
+ logger(mesh, MESHLINK_ERROR, "Invitee %s is blacklisted", c->name);
+ } else {
+ logger(mesh, MESHLINK_ERROR, "Invitee %s already known", c->name);
+ }
+
+ return false;
+ }
+
// Create a new node
- node_t *n = new_node();
+ n = new_node();
n->name = xstrdup(c->name);
n->devclass = DEV_CLASS_UNKNOWN;
n->ecdsa = ecdsa_set_public_key(data);
connection_t *c = handle;
meshlink_handle_t *mesh = c->mesh;
+ // Extend the time for the invitation exchange upon receiving a valid message
+ c->last_ping_time = mesh->loop.now.tv_sec;
+
if(type == SPTPS_HANDSHAKE) {
// The peer should send its cookie first.
return true;
assert(*request);
char name[MAX_STRING_SIZE];
+ char real_address[MAX_STRING_SIZE] = "";
+ char real_port[MAX_STRING_SIZE] = "";
- if(sscanf(request, "%*d " MAX_STRING " %d.%d", name, &c->protocol_major, &c->protocol_minor) < 2) {
+ if(sscanf(request, "%*d " MAX_STRING " %d.%d %*s " MAX_STRING " " MAX_STRING, name, &c->protocol_major, &c->protocol_minor, real_address, real_port) < 2) {
logger(mesh, MESHLINK_ERROR, "Got bad %s from %s", "ID", c->name);
return false;
}
+ /* Parse the real address if present */
+
+ if(!c->outgoing && *real_address && *real_port) {
+ sockaddr_t sa = str2sockaddr(real_address, real_port);
+
+ if(sa.sa.sa_family == AF_UNKNOWN || sa.sa.sa_family == AF_UNSPEC) {
+ logger(mesh, MESHLINK_ERROR, "Could not parse real address from %s", c->name);
+ sockaddrfree(&sa);
+ return false;
+ }
+
+ sockaddrfree(&c->address);
+ c->address = sa;
+ }
+
/* Check if this is an invitation */
if(name[0] == '?') {
c->protocol_minor = 2;
c->allow_request = 1;
+ c->last_ping_time = mesh->loop.now.tv_sec;
return sptps_start(&c->sptps, c, false, false, mesh->invitation_key, c->ecdsa, meshlink_invitation_label, sizeof(meshlink_invitation_label), send_meta_sptps, receive_invitation_sptps);
}
return false;
}
- if(n->status.blacklisted) {
- logger(mesh, MESHLINK_WARNING, "Peer %s is blacklisted", c->name);
- return false;
- }
-
if(!node_read_public_key(mesh, n)) {
logger(mesh, MESHLINK_ERROR, "No key known for peer %s", c->name);
}
c->allow_request = ACK;
+ c->last_ping_time = mesh->loop.now.tv_sec;
char label[sizeof(meshlink_tcp_label) + strlen(mesh->self->name) + strlen(c->name) + 2];
if(c->outgoing) {
}
bool send_ack(meshlink_handle_t *mesh, connection_t *c) {
+ node_t *n = lookup_node(mesh, c->name);
+
+ if(n && n->status.blacklisted) {
+ logger(mesh, MESHLINK_WARNING, "Peer %s is blacklisted", c->name);
+ return send_error(mesh, c, BLACKLISTED, "blacklisted");
+ }
+
+ c->last_ping_time = mesh->loop.now.tv_sec;
return send_request(mesh, c, NULL, "%d %s %d %x", ACK, mesh->myport, mesh->devclass, OPTION_PMTU_DISCOVERY | (PROT_MINOR << 24));
}
n->last_successfull_connection = mesh->loop.now.tv_sec;
n->connection = c;
+ n->nexthop = n;
c->node = n;
/* Activate this connection */
mesh->meta_status_cb(mesh, (meshlink_node_t *)n, true);
}
+ /* Terminate any connections to this node that are not activated yet */
+
+ for list_each(connection_t, other, mesh->connections) {
+ if(!other->status.active && !strcmp(other->name, c->name)) {
+ if(other->outgoing) {
+ if(c->outgoing) {
+ logger(mesh, MESHLINK_WARNING, "Two outgoing connections to the same node!");
+ } else {
+ c->outgoing = other->outgoing;
+ }
+
+ other->outgoing = NULL;
+ }
+
+ logger(mesh, MESHLINK_DEBUG, "Terminating pending second connection with %s", n->name);
+ terminate_connection(mesh, other, false);
+ }
+ }
+
/* Send him everything we know */
send_everything(mesh, c);
c->edge->weight = mesh->dev_class_traits[devclass].edge_weight;
c->edge->connection = c;
+ node_add_recent_address(mesh, n, &c->address);
edge_add(mesh, c->edge);
/* Notify everyone of the new edge */
graph(mesh);
+ /* Request a session key to jump start UDP traffic */
+
+ if(c->status.initiator) {
+ send_req_key(mesh, n);
+ }
+
return true;
}