예제 #1
0
// must be called after every send or receive, pass pkt to e3x_encrypt before sending
lob_t e3x_channel_sending(e3x_channel_t c)
{
  lob_t ret;
  uint32_t now;
  if(!c) return NULL;
  
  // packets waiting
  if(c->out)
  {
    ret = lob_shift(c->out);
    c->out = ret->next;
    // if it's a content packet and reliable, add to sent list
    if(c->seq && ret->id) c->sent = lob_push(c->sent, lob_copy(ret));
    return ret;
  }
  
  // check sent list for any flagged to resend
  now = util_sys_seconds();
  for(ret = c->sent; ret; ret = ret->next)
  {
    if(!ret->id) continue;
    if(ret->id == now) continue;
    // max once per second throttle resend
    ret->id = now;
    return ret;
  }
  
  LOG("sending ack %d acked %d",c->ack,c->acked);

  // if we need to generate an ack/miss yet, do that
  if(c->ack != c->acked) return e3x_channel_oob(c);
  
  return NULL;
}
예제 #2
0
// this will set the default inactivity timeout using this event timer and our uid
uint32_t e3x_channel_timeout(e3x_channel_t c, e3x_event_t ev, uint32_t timeout)
{
  if(!c) return 0;

  // un-set any
  if(ev != c->ev)
  {
    // cancel and clearn any previous timer state
    c->timeout = 0;
    if(c->ev) e3x_event_set(c->ev,NULL,c->uid,0);
    c->ev = NULL;
    lob_free(c->timer);
    c->timer = NULL;
  }
  
  // no event manager, no timeouts
  if(!ev) return 0;
  
  // no timeout, just return how much time is left
  if(!timeout) return _time_left(c);

  // add/update new timeout
  c->tsince = util_sys_seconds(); // start timer now
  c->timeout = timeout;
  c->ev = ev;
  c->timer = lob_new();
  lob_set_uint(c->timer,"c",c->id);
  lob_set(c->timer, "id", c->uid);
  lob_set(c->timer, "err", "timeout");
  e3x_event_set(c->ev, c->timer, lob_get(c->timer, "id"), timeout*1000); // ms in the future
  return _time_left(c);
}
예제 #3
0
// internally calculate until timeout
uint32_t _time_left(e3x_channel_t c)
{
  uint32_t at = util_sys_seconds();
  if(!c) return 0;
  if(!c->timeout) return 1; // never timeout
  // some seconds left yet
  if((at - c->tsince) < c->timeout) return c->timeout - (at - c->tsince);
  return 0;
}
예제 #4
0
uint64_t util_at(void)
{
  uint64_t at;
  uint32_t *half = (uint32_t*)(&at);

  // store both current seconds and ms since then in one value
  half[0] = util_sys_seconds();
  half[1] = (uint32_t)util_sys_ms(half[0]);

  return at;
}
예제 #5
0
파일: link.c 프로젝트: telehash/telehash-c
// load in the key to existing link
link_t link_load(link_t link, uint8_t csid, lob_t key)
{
  char hex[3];
  lob_t copy;

  if(!link || !csid || !key) return LOG("bad args");
  if(link->x)
  {
    link->csid = link->x->csid; // repair in case mesh_unlink was called, any better place?
    return link;
  }

  LOG("adding %x key to link %s",csid,hashname_short(link->id));

  // key must be bin
  if(key->body_len)
  {
    copy = lob_new();
    lob_body(copy,key->body,key->body_len);
  }else{
    util_hex(&csid,1,hex);
    copy = lob_get_base32(key,hex);
  }
  link->x = e3x_exchange_new(link->mesh->self, csid, copy);
  if(!link->x)
  {
    LOG("invalid %x key %s %s",csid,util_hex(copy->body,copy->body_len,NULL),lob_json(key));
    lob_free(copy);
    return NULL;
  }

  link->csid = csid;
  link->key = copy;

  e3x_exchange_out(link->x, util_sys_seconds());
  LOG("new exchange session to %s",hashname_short(link->id));

  return link;
}
예제 #6
0
// load in the key to existing link
link_t link_load(link_t link, uint8_t csid, lob_t key)
{
  char hex[3];
  lob_t copy;

  if(!link || !csid || !key) return LOG("bad args");
  if(link->x) return link;

  LOG("adding %x key to link %s",csid,link->id->hashname);
  
  // key must be bin
  if(key->body_len)
  {
    copy = lob_copy(key);
  }else{
    util_hex(&csid,1,hex);
    copy = lob_get_base32(key,hex);
  }
  link->x = e3x_exchange_new(link->mesh->self, csid, copy);
  if(!link->x)
  {
    lob_free(copy);
    return LOG("invalid %x key %d %s",csid,key->body_len,lob_json(key));
  }

  link->csid = csid;
  link->key = copy;
  
  // route packets to this token
  util_hex(e3x_exchange_token(link->x),16,link->token);
  xht_set(link->mesh->index,link->token,link);
  e3x_exchange_out(link->x, util_sys_seconds());
  LOG("new session token %s to %s",link->token,link->id->hashname);

  return link;
}
예제 #7
0
// process any unencrypted handshake packet
link_t mesh_receive_handshake(mesh_t mesh, lob_t handshake, pipe_t pipe)
{
  uint32_t now;
  hashname_t from;
  link_t link;

  if(!mesh || !handshake) return LOG("bad args");
  if(!lob_get(handshake,"id"))
  {
    LOG("bad handshake, no id: %s",lob_json(handshake));
    lob_free(handshake);
    return NULL;
  }
  now = util_sys_seconds();
  
  // normalize handshake
  handshake->id = now; // save when we cached it
  if(!lob_get(handshake,"type")) lob_set(handshake,"type","link"); // default to link type
  if(!lob_get_uint(handshake,"at")) lob_set_uint(handshake,"at",now); // require an at
  LOG("handshake at %d id %s",now,lob_get(handshake,"id"));
  
  // validate/extend link handshakes immediately
  if(util_cmp(lob_get(handshake,"type"),"link") == 0)
  {
    // get the csid
    uint8_t csid = 0;
    lob_t outer;
    if((outer = lob_linked(handshake)))
    {
      csid = outer->head[0];
    }else if(lob_get(handshake,"csid")){
      util_unhex(lob_get(handshake,"csid"),2,&csid);
    }
    if(!csid)
    {
      LOG("bad link handshake, no csid: %s",lob_json(handshake));
      lob_free(handshake);
      return NULL;
    }
    char hexid[3] = {0};
    util_hex(&csid, 1, hexid);
      
    // get attached hashname
    lob_t tmp = lob_parse(handshake->body, handshake->body_len);
    from = hashname_vkey(tmp, csid);
    if(!from)
    {
      LOG("bad link handshake, no hashname: %s",lob_json(handshake));
      lob_free(tmp);
      lob_free(handshake);
      return NULL;
    }
    lob_set(handshake,"csid",hexid);
    lob_set(handshake,"hashname",hashname_char(from));
    lob_set_raw(handshake,hexid,2,"true",4); // intermediate format
    lob_body(handshake, tmp->body, tmp->body_len); // re-attach as raw key
    lob_free(tmp);

    // short-cut, if it's a key from an existing link, pass it on
    // TODO: using mesh_linked here is a stack issue during loopback peer test!
    if((link = mesh_linkid(mesh,from))) return link_receive_handshake(link, handshake, pipe);
    LOG("no link found for handshake from %s",hashname_char(from));

    // extend the key json to make it compatible w/ normal patterns
    tmp = lob_new();
    lob_set_base32(tmp,hexid,handshake->body,handshake->body_len);
    lob_set_raw(handshake,"keys",0,(char*)tmp->head,tmp->head_len);
    lob_free(tmp);
    // add the path if one
    if(pipe && pipe->path)
    {
      char *paths = malloc(pipe->path->head_len+3);
      sprintf(paths,"[%.*s]",(int)pipe->path->head_len,(char*)pipe->path->head);
      lob_set_raw(handshake,"paths",0,paths,pipe->path->head_len+2);
      free(paths);
    }
  }

  // always add to the front of the cached list if needed in the future
  mesh->cached = lob_unshift(mesh->cached, handshake);

  // tell anyone listening about the newly discovered handshake
  mesh_discover(mesh, handshake, pipe);
  
  return NULL;
}