Example #1
0
// 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;
}
Example #2
0
// 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;
}
Example #3
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);
  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;
}
Example #4
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;
}
Example #5
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_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;
}
Example #6
0
File: link.c Project: fd/telehash-c
// 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);
}
Example #7
0
// 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);
}
Example #8
0
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;
}
Example #9
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;
}
Example #10
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;
}
Example #11
0
File: link.c Project: fd/telehash-c
// 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;
}