// process an incoming handshake link_t link_receive_handshake(link_t link, lob_t inner) { uint32_t out, at, err; uint8_t csid = 0; lob_t outer = lob_linked(inner); if(!link || !inner || !outer) return LOG("bad args"); // inner/link must be validated by caller already, we just load if missing if(!link->key) { util_unhex(lob_get(inner, "csid"), 2, &csid); if(!link_load(link, csid, inner)) { lob_free(inner); return LOG("load key failed for %s %u %s",hashname_short(link->id),csid,util_hex(inner->body,inner->body_len,NULL)); } } if((err = e3x_exchange_verify(link->x,outer))) { lob_free(inner); return LOG("handshake verification fail: %d",err); } out = e3x_exchange_out(link->x,0); at = lob_get_uint(inner,"at"); link_t ready = link_up(link); // if bad at, always send current handshake if(e3x_exchange_in(link->x, at) < out) { LOG("old handshake: %s (%d,%d,%d)",lob_json(inner),at,out); link_sync(link); lob_free(inner); return link; } // try to sync ephemeral key if(!e3x_exchange_sync(link->x,outer)) { lob_free(inner); return LOG("sync failed"); } // we may need to re-sync if(out != e3x_exchange_out(link->x,0)) link_sync(link); // notify of ready state change if(!ready && link_up(link)) { LOG("link ready"); mesh_link(link->mesh, link); } link->handshake = lob_free(link->handshake); link->handshake = inner; return link; }
// process an incoming handshake link_t link_receive_handshake(link_t link, lob_t inner, pipe_t pipe) { link_t ready; uint32_t out, err; seen_t seen; uint8_t csid = 0; char *hexid; lob_t attached, outer = lob_linked(inner); if(!link || !inner || !outer) return LOG("bad args"); hexid = lob_get(inner, "csid"); if(!lob_get(link->mesh->keys, hexid)) return LOG("unsupported csid %s",hexid); util_unhex(hexid, 2, &csid); attached = lob_parse(inner->body, inner->body_len); if(!link->key && link_key(link->mesh, attached, csid) != link) return LOG("invalid/mismatch link handshake"); if((err = e3x_exchange_verify(link->x,outer))) return LOG("handshake verification fail: %d",err); out = e3x_exchange_out(link->x,0); ready = link_up(link); // if bad at, always send current handshake if(e3x_exchange_in(link->x, lob_get_uint(inner,"at")) < out) { LOG("old/bad at: %s (%d,%d,%d)",lob_json(inner),lob_get_int(inner,"at"),e3x_exchange_in(link->x,0),e3x_exchange_out(link->x,0)); // just reset pipe seen and call link_sync to resend handshake for(seen = link->pipes;pipe && seen;seen = seen->next) if(seen->pipe == pipe) seen->at = 0; lob_free(link_sync(link)); return NULL; } // trust/add this pipe if(pipe) link_pipe(link,pipe); // try to sync ephemeral key if(!e3x_exchange_sync(link->x,outer)) return LOG("sync failed"); // we may need to re-sync if(out != e3x_exchange_out(link->x,0)) lob_free(link_sync(link)); // notify of ready state change if(!ready && link_up(link)) { LOG("link ready"); mesh_link(link->mesh, link); } return link; }
int main(int argc, char **argv) { mesh_t meshA = mesh_new(3); fail_unless(meshA); lob_t secretsA = mesh_generate(meshA); fail_unless(secretsA); fail_unless(ext_link_auto(meshA)); mesh_t meshB = mesh_new(3); fail_unless(meshB); lob_t secretsB = mesh_generate(meshB); fail_unless(secretsB); fail_unless(ext_link_auto(meshB)); net_loopback_t pair = net_loopback_new(meshA,meshB); fail_unless(pair); link_t linkAB = link_get(meshA, meshB->id->hashname); link_t linkBA = link_get(meshB, meshA->id->hashname); fail_unless(linkAB); fail_unless(linkBA); fail_unless(link_sync(linkAB)); // lob_t block = lob_new(); // lob_append(block,NULL,1500); // fail_unless(ext_block_send(linkAB,block)); // fail_unless(ext_block_receive(meshB)); return 0; }
// add a pipe to this link if not yet link_t link_pipe(link_t link, pipe_t pipe) { seen_t seen; if(!link || !pipe) return LOG("bad args"); // see if we've seen it already for(seen = link->pipes; seen; seen = seen->next) { if(seen->pipe == pipe) return link; } // add this pipe to this link LOG("adding pipe %s",pipe->id); if(!(seen = malloc(sizeof (struct seen_struct)))) return NULL; memset(seen,0,sizeof (struct seen_struct)); seen->pipe = pipe; seen->next = link->pipes; link->pipes = seen; // make sure it gets sync'd lob_free(link_sync(link)); return link; }
int main(int argc, char **argv) { mesh_t meshA = mesh_new(3); fail_unless(meshA); lob_t secretsA = mesh_generate(meshA); fail_unless(secretsA); mesh_t meshB = mesh_new(3); fail_unless(meshB); lob_t secretsB = mesh_generate(meshB); fail_unless(secretsB); net_loopback_t pair = net_loopback_new(meshA,meshB); fail_unless(pair); link_t linkAB = link_get(meshA, meshB->id->hashname); link_t linkBA = link_get(meshB, meshA->id->hashname); fail_unless(linkAB); fail_unless(linkBA); fail_unless(link_sync(linkAB)); fail_unless(link_ready(linkAB)); fail_unless(link_ready(linkBA)); return 0; }
// trigger a new exchange sync link_t link_resync(link_t link) { if(!link) return LOG("bad args"); if(!link->x) return LOG("no exchange"); // force a higher at, triggers all to sync exchange3_out(link->x,exchange3_out(link->x,0)+1); return link_sync(link); }
// add a delivery pipe to this link link_t link_pipe(link_t link, link_t (*send)(link_t link, lob_t packet, void *arg), void *arg) { if(!link || !send) return NULL; if(send == link->send_cb && arg == link->send_arg) return link; // noop if(link->send_cb) LOG_INFO("replacing existing pipe on link"); link->send_cb = send; link->send_arg = arg; // flush handshake return link_sync(link); }
int main(int argc, char **argv) { mesh_t meshA = mesh_new(); fail_unless(meshA); lob_t secretsA = mesh_generate(meshA); fail_unless(secretsA); mesh_t meshB = mesh_new(); fail_unless(meshB); lob_t secretsB = mesh_generate(meshB); fail_unless(secretsB); net_tcp4_t netA = net_tcp4_new(meshA, NULL); fail_unless(netA); fail_unless(netA->port > 0); fail_unless(netA->path); LOG("netA %.*s",netA->path->head_len,netA->path->head); net_tcp4_t netB = net_tcp4_new(meshB, NULL); fail_unless(netB); fail_unless(netB->port > 0); LOG("netB %.*s",netB->path->head_len,netB->path->head); link_t linkAB = link_keys(meshA, meshB->keys); link_t linkBA = link_keys(meshB, meshA->keys); fail_unless(linkAB); fail_unless(linkBA); fail_unless(link_path(linkAB,netB->path)); fail_unless(link_path(linkBA,netA->path)); link_sync(linkAB); // let tcp go back and forth enough, need a better way to do this int loop; for(loop = 10; loop; loop--) { net_tcp4_loop(netB); net_tcp4_loop(netA); } fail_unless(e3x_exchange_out(linkBA->x,0) >= e3x_exchange_out(linkAB->x,0)); fail_unless(e3x_exchange_out(linkBA->x,0) == e3x_exchange_out(linkAB->x,0)); return 0; }
int main(int argc, char **argv) { mesh_t meshA = mesh_new(3); fail_unless(meshA); lob_t secretsA = mesh_generate(meshA); fail_unless(secretsA); mesh_t meshB = mesh_new(3); fail_unless(meshB); lob_t secretsB = mesh_generate(meshB); fail_unless(secretsB); net_serial_t netA = net_serial_new(meshA, NULL); fail_unless(netA); pipe_t pAB = net_serial_add(netA, "sAB", readerA, writerA, 64); fail_unless(pAB); net_serial_t netB = net_serial_new(meshB, NULL); fail_unless(netB); pipe_t pBA = net_serial_add(netB, "sBA", readerB, writerB, 64); fail_unless(pBA); link_t linkAB = link_pipe(link_keys(meshA, meshB->keys), pAB); link_t linkBA = link_pipe(link_keys(meshB, meshA->keys), pBA); fail_unless(linkAB); fail_unless(linkBA); link_sync(linkAB); // let serial go go go int loop; for(loop = 2000; loop; loop--) { net_serial_loop(netB); net_serial_loop(netA); } LOG("BA %d AB %d",e3x_exchange_out(linkBA->x,0),e3x_exchange_out(linkAB->x,0)); fail_unless(e3x_exchange_out(linkBA->x,0) >= e3x_exchange_out(linkAB->x,0)); fail_unless(e3x_exchange_out(linkBA->x,0) == e3x_exchange_out(linkAB->x,0)); return 0; }
int main(int argc, char **argv) { mesh_t meshA = mesh_new(3); fail_unless(meshA); lob_t secretsA = mesh_generate(meshA); fail_unless(secretsA); mesh_t meshB = mesh_new(3); fail_unless(meshB); lob_t secretsB = mesh_generate(meshB); fail_unless(secretsB); net_udp4_t netA = net_udp4_new(meshA, NULL); fail_unless(netA); fail_unless(netA->port > 0); fail_unless(netA->path); fail_unless(lob_match(meshA->paths,"type","udp4")); LOG("netA %.*s",netA->path->head_len,netA->path->head); net_udp4_t netB = net_udp4_new(meshB, NULL); fail_unless(netB); fail_unless(netB->port > 0); LOG("netB %.*s",netB->path->head_len,netB->path->head); link_t linkAB = link_keys(meshA, meshB->keys); link_t linkBA = link_keys(meshB, meshA->keys); fail_unless(linkAB); fail_unless(linkBA); fail_unless(link_path(linkAB,netB->path)); fail_unless(link_path(linkBA,netA->path)); link_sync(linkAB); net_udp4_receive(netB); fail_unless(e3x_exchange_out(linkBA->x,0) >= e3x_exchange_out(linkAB->x,0)); net_udp4_receive(netA); fail_unless(e3x_exchange_out(linkBA->x,0) == e3x_exchange_out(linkAB->x,0)); return 0; }
// process an incoming handshake link_t link_handshake(link_t link, lob_t inner, lob_t outer, pipe_t pipe) { link_t ready; uint32_t out; if(!link || !inner || !outer) return LOG("bad args"); if(!link->key && link_key(link->mesh,inner) != link) return LOG("invalid/mismatch handshake key"); out = exchange3_out(link->x,0); ready = link_ready(link); // if bad at, always send current handshake if(exchange3_in(link->x, lob_get_int(inner,"at")) < out) { LOG("old/bad at: %s (%d,%d,%d)",lob_json(inner),lob_get_int(inner,"at"),exchange3_in(link->x,0),exchange3_out(link->x,0)); if(pipe) pipe->send(pipe,exchange3_handshake(link->x),link); return NULL; } // trust/add this pipe if(pipe) link_pipe(link,pipe); // try to sync ephemeral key if(!exchange3_sync(link->x,outer)) return LOG("sync failed"); // we may need to re-sync if(out != exchange3_out(link->x,0)) link_sync(link); // notify of ready state change if(!ready && link_ready(link)) { LOG("link ready"); mesh_link(link->mesh, link); } return link; }