Пример #1
0
lob_t ephemeral_encrypt(ephemeral_t ephem, lob_t inner)
{
  lob_t outer;
  uint8_t iv[16], hmac[32];
  size_t inner_len;

  outer = lob_new();
  inner_len = lob_len(inner);
  if(!lob_body(outer,NULL,16+4+inner_len+4)) return lob_free(outer);

  // copy in token and create/copy iv
  memcpy(outer->body,ephem->token,16);
  memset(iv,0,16);
  memcpy(iv,&(ephem->seq),4);
  ephem->seq++;
  memcpy(outer->body+16,iv,4);

  // encrypt full inner into the outer
  aes_128_ctr(ephem->enckey,inner_len,iv,lob_raw(inner),outer->body+16+4);

  // generate mac key and mac the ciphertext
  memcpy(hmac,ephem->enckey,16);
  memcpy(hmac+16,iv,4);
  hmac_256(hmac,16+4,outer->body+16+4,inner_len,hmac);
  fold3(hmac,outer->body+16+4+inner_len);

  return outer;
}
Пример #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
lob_t local_decrypt(local_t local, lob_t outer)
{
  uint8_t secret[crypto_box_BEFORENMBYTES];
  lob_t inner, tmp;

//  * `KEY` - 32 bytes, the sending exchange's ephemeral public key
//  * `NONCE` - 24 bytes, randomly generated
//  * `CIPHERTEXT` - the inner packet bytes encrypted using secretbox() using the `NONCE` as the nonce and the shared secret (derived from the recipients endpoint key and the included ephemeral key) as the key
//  * `AUTH` - 16 bytes, the calculated onetimeauth(`KEY` + `INNER`, SHA256(`NONCE` + secret)) using the shared secret derived from both endpoint keys, the hashing is to minimize the chance that the same key input is ever used twice

  if(outer->body_len <= (32+24+crypto_secretbox_MACBYTES+16)) return NULL;
  tmp = lob_new();
  if(!lob_body(tmp,NULL,outer->body_len-(32+24+crypto_secretbox_MACBYTES+16))) return lob_free(tmp);

  // get the shared secret
  crypto_box_beforenm(secret, outer->body, local->secret);

  // decrypt the inner
  if(crypto_secretbox_open_easy(tmp->body,
    outer->body+32+24,
    tmp->body_len+crypto_secretbox_MACBYTES,
    outer->body+32,
    secret) != 0) return lob_free(tmp);

  // load inner packet
  inner = lob_parse(tmp->body,tmp->body_len);
  lob_free(tmp);

  return inner;
}
Пример #4
0
lob_t remote_encrypt(remote_t remote, local_t local, lob_t inner)
{
  uint8_t shared[uECC_BYTES+4], iv[16], hash[32], csid = 0x1a;
  lob_t outer;
  size_t inner_len;

  outer = lob_new();
  lob_head(outer,&csid,1);
  inner_len = lob_len(inner);
  if(!lob_body(outer,NULL,21+4+inner_len+4)) return lob_free(outer);

  // copy in the ephemeral public key
  memcpy(outer->body, remote->ecomp, uECC_BYTES+1);

  // get the shared secret to create the iv+key for the open aes
  if(!uECC_shared_secret(remote->key, remote->esecret, shared)) return lob_free(outer);
  e3x_hash(shared,uECC_BYTES,hash);
  fold1(hash,hash);
  memset(iv,0,16);
  memcpy(iv,&(remote->seq),4);
  remote->seq++; // increment seq after every use
  memcpy(outer->body+21,iv,4); // send along the used IV

  // encrypt the inner into the outer
  aes_128_ctr(hash,inner_len,iv,lob_raw(inner),outer->body+21+4);

  // generate secret for hmac
  if(!uECC_shared_secret(remote->key, local->secret, shared)) return lob_free(outer);
  memcpy(shared+uECC_BYTES,outer->body+21,4); // use the IV too

  hmac_256(shared,uECC_BYTES+4,outer->body,21+4+inner_len,hash);
  fold3(hash,outer->body+21+4+inner_len); // write into last 4 bytes

  return outer;
}
Пример #5
0
lob_t util_fjson(char *file)
{
  unsigned char *buf;
  size_t len;
  struct stat fs;
  FILE *fd;
  lob_t p;
  
  fd = fopen(file,"rb");
  if(!fd) return LOG("fopen error %s: %s",file,strerror(errno));
  if(fstat(fileno(fd),&fs) < 0)
  {
    fclose(fd);
    return LOG("fstat error %s: %s",file,strerror(errno));
  }
  
  if(!(buf = malloc((size_t)fs.st_size)))
  {
    fclose(fd);
    return LOG("OOM");
  }
  len = fread(buf,1,(size_t)fs.st_size,fd);
  fclose(fd);
  if(len != (size_t)fs.st_size)
  {
    free(buf);
    return LOG("fread %d != %d for %s: %s",len,fs.st_size,file,strerror(errno));
  }
  
  p = lob_new();
  lob_head(p, buf, len);
  if(!p) LOG("json failed %s parsing %.*s",file,len,buf);
  free(buf);
  return p;
}
Пример #6
0
// decode base64 into the pair of lob packets
lob_t jwt_decode(char *encoded, size_t len)
{
  lob_t header, claims;
  char *dot1, *dot2, *end;
  size_t dlen;

  if(!encoded) return NULL;
  if(!len) len = strlen(encoded);
  end = encoded+(len-1);
  
  // make sure the dot separators are there
  dot1 = strchr(encoded,'.');
  if(!dot1 || dot1+1 >= end) return LOG("missing/bad first separator");
  dot1++;
  dot2 = strchr(dot1,'.');
  if(!dot2 || (dot2+1) >= end) return LOG("missing/bad second separator");
  dot2++;

  claims = lob_new();
  header = lob_link(NULL, claims);
  
  // decode claims sig first
  dlen = base64_decoder(dot2, (end-dot2)+1, (uint8_t*)dot2);
  lob_body(claims, (uint8_t*)dot2, dlen);

  // decode claims json
  dlen = base64_decoder(dot1, (dot2-dot1), (uint8_t*)dot1);
  lob_head(claims, (uint8_t*)dot1, dlen);

  // decode header json
  dlen = base64_decoder(encoded, (dot1-encoded), (uint8_t*)encoded);
  lob_head(header, (uint8_t*)encoded, dlen);

  return header;
}
Пример #7
0
lob_t remote_encrypt(remote_t remote, local_t local, lob_t inner)
{
  uint8_t secret[crypto_box_BEFORENMBYTES], nonce[24], shared[24+crypto_box_BEFORENMBYTES], hash[32], csid = 0x3a;
  lob_t outer;
  size_t inner_len;

  outer = lob_new();
  lob_head(outer,&csid,1);
  inner_len = lob_len(inner);
  if(!lob_body(outer,NULL,32+24+inner_len+crypto_secretbox_MACBYTES+16)) return lob_free(outer);

  // copy in the ephemeral public key/nonce
  memcpy(outer->body, remote->ekey, 32);
  randombytes(nonce,24);
  memcpy(outer->body+32, nonce, 24);

  // get the shared secret to create the nonce+key for the open aes
  crypto_box_beforenm(secret, remote->key, remote->esecret);

  // encrypt the inner
  if(crypto_secretbox_easy(outer->body+32+24,
    lob_raw(inner),
    inner_len,
    nonce,
    secret) != 0) return lob_free(outer);

  // generate secret for hmac
  crypto_box_beforenm(secret, remote->key, local->secret);
  memcpy(shared,nonce,24);
  memcpy(shared+24,secret,crypto_box_BEFORENMBYTES);
  e3x_hash(shared,24+crypto_box_BEFORENMBYTES,hash);
  crypto_onetimeauth(outer->body+32+24+inner_len+crypto_secretbox_MACBYTES, outer->body, outer->body_len-16, hash);

  return outer;
}
Пример #8
0
lob_t local_decrypt(local_t local, lob_t outer)
{
  uint8_t key[uECC_BYTES*2], shared[uECC_BYTES], iv[16], hash[32];
  lob_t inner, tmp;

//  * `KEY` - 21 bytes, the sender's ephemeral exchange public key in compressed format
//  * `IV` - 4 bytes, a random but unique value determined by the sender
//  * `INNER` - (minimum 21+2 bytes) the AES-128-CTR encrypted inner packet ciphertext
//  * `HMAC` - 4 bytes, the calculated HMAC of all of the previous KEY+INNER bytes

  if(outer->body_len <= (21+4+0+4)) return NULL;
  tmp = lob_new();
  if(!lob_body(tmp,NULL,outer->body_len-(4+21+4))) return lob_free(tmp);

  // get the shared secret to create the iv+key for the open aes
  uECC_decompress(outer->body,key);
  if(!uECC_shared_secret(key, local->secret, shared)) return lob_free(tmp);
  e3x_hash(shared,uECC_BYTES,hash);
  fold1(hash,hash);
  memset(iv,0,16);
  memcpy(iv,outer->body+21,4);

  // decrypt the inner
  aes_128_ctr(hash,tmp->body_len,iv,outer->body+4+21,tmp->body);

  // load inner packet
  inner = lob_parse(tmp->body,tmp->body_len);
  lob_free(tmp);
  return inner;
}
Пример #9
0
int main(int argc, char **argv)
{
  lob_t opts = lob_new();
  fail_unless(e3x_init(opts) == 0);
  fail_unless(!lob_get(opts,"err"));
  fail_unless(!e3x_err());
  lob_free(opts);
  return 0;
}
Пример #10
0
lob_t util_uri_add_path(lob_t uri, lob_t path)
{
  lob_t keys;
  lob_t query = lob_linked(uri);
  if(!uri || !path) return NULL;
  if(!query)
  {
    if(!(query = lob_new())) return LOG("OOM");
    lob_link(uri, query);
  }
  // encode and add to chain after query
  if(!(keys = lob_new())) return LOG("OOM");
  lob_set_base32(keys,"paths",path->head,path->head_len);
  lob_link(keys, lob_linked(query));
  lob_link(query, keys);
  
  return uri;
}
Пример #11
0
lob_t link_handshakes(link_t link)
{
  uint32_t i;
  uint8_t csid;
  char *key;
  lob_t tmp, hs = NULL, handshakes = NULL;
  if(!link) return NULL;
  
  // no keys means we have to generate a handshake for each key
  if(!link->x)
  {
    for(i=0;(key = lob_get_index(link->mesh->keys,i));i+=2)
    {
      util_unhex(key,2,&csid);
      hs = lob_new();
      tmp = hashname_im(link->mesh->keys, csid);
      lob_body(hs, lob_raw(tmp), lob_len(tmp));
      lob_free(tmp);
      handshakes = lob_link(hs, handshakes);
    }
  }else{ // generate one just for this csid
    handshakes = lob_new();
    tmp = hashname_im(link->mesh->keys, link->csid);
    lob_body(handshakes, lob_raw(tmp), lob_len(tmp));
    lob_free(tmp);
  }

  // add any custom per-link
  for(hs = link->handshakes; hs; hs = lob_linked(hs)) handshakes = lob_link(lob_copy(hs), handshakes);

  // add any mesh-wide handshakes
  for(hs = link->mesh->handshakes; hs; hs = lob_linked(hs)) handshakes = lob_link(lob_copy(hs), handshakes);
  
  // encrypt them if we can
  if(link->x)
  {
    tmp = handshakes;
    handshakes = NULL;
    for(hs = tmp; hs; hs = lob_linked(hs)) handshakes = lob_link(e3x_exchange_handshake(link->x, hs), handshakes);
    lob_free(tmp);
  }

  return handshakes;
}
Пример #12
0
int main(int argc, char **argv)
{
  hashname_t hn;
  
  fail_unless(e3x_init(NULL) == 0);

  hn = hashname_vchar("uvabrvfqacyvgcu8kbrrmk9apjbvgvn2wjechqr3vf9c1zm3hv7g");
  fail_unless(!hn);

  hn = hashname_vchar("jvdoio6kjvf3yqnxfvck43twaibbg4pmb7y3mqnvxafb26rqllwa");
  fail_unless(hn);
  fail_unless(strlen(hashname_char(hn)) == 52);
  hashname_free(hn);

  // create intermediate fixture
  lob_t im = lob_new();
  lob_set(im,"1a","ym7p66flpzyncnwkzxv2qk5dtosgnnstgfhw6xj2wvbvm7oz5oaq");
  lob_set(im,"3a","bmxelsxgecormqjlnati6chxqua7wzipxliw5le35ifwxlge2zva");
  hn = hashname_vkey(im, 0);
  fail_unless(hn);
  fail_unless(util_cmp(hashname_char(hn),"jvdoio6kjvf3yqnxfvck43twaibbg4pmb7y3mqnvxafb26rqllwa") == 0);

  lob_t keys = lob_new();
  lob_set(keys,"1a","vgjz3yjb6cevxjomdleilmzasbj6lcc7");
  lob_set(keys,"3a","hp6yglmmqwcbw5hno37uauh6fn6dx5oj7s5vtapaifrur2jv6zha");
  hn = hashname_vkeys(keys);
  fail_unless(hn);
  fail_unless(util_cmp(hashname_char(hn),"jvdoio6kjvf3yqnxfvck43twaibbg4pmb7y3mqnvxafb26rqllwa") == 0);

  fail_unless(hashname_id(NULL,NULL) == 0);
  fail_unless(hashname_id(im,keys) == 0x3a);
  lob_t test = lob_new();
  lob_set(test,"1a","test");
  lob_set(test,"2a","test");
  fail_unless(hashname_id(keys,test) == 0x1a);
  
  // check short utils
  hn = hashname_schar("uvabrvfq");
  fail_unless(hn);
  fail_unless(hashname_isshort(hn));
  fail_unless(util_cmp(hashname_short(hn),"uvabrvfq") == 0);

  return 0;
}
Пример #13
0
// ack/miss only base packet
lob_t e3x_channel_oob(e3x_channel_t c)
{
  lob_t ret, cur;
  char *miss;
  uint32_t seq, last, delta;
  size_t len;
  if(!c) return NULL;

  ret = lob_new();
  lob_set_uint(ret,"c",c->id);
  
  if(!c->seq) return ret;
  
  // check for ack/miss
  if(c->ack != c->acked)
  {
    lob_set_uint(ret,"ack",c->ack);

    // also check to include misses
    cur = c->in;
    last = c->ack;
    if(cur && (cur->id - last) != 1)
    {
      // I'm so tired of strings in c
      len = 2;
      if(!(miss = malloc(len))) return lob_free(ret);
      len = (size_t)snprintf(miss,len,"[");
      for(seq=c->ack+1; cur; seq++)
      {
//        LOG("ack %d seq %d last %d cur %d",c->ack,seq,last,cur->id);
        // if we have this seq, skip to next packet
        if(cur->id <= seq)
        {
          cur = cur->next;
          continue;
        }
        // insert this missing seq delta
        delta = seq - last;
        last = seq;
        len += (size_t)snprintf(NULL, 0, "%u,", delta) + 1;
        if(!(miss = realloc(miss, len))) return lob_free(ret);
        sprintf(miss+strlen(miss),"%u,", delta);
      }
      // add current window at the end
      delta = 100; // TODO calculate this from actual space avail
      len += (size_t)snprintf(NULL, 0, "%u]", delta) + 1;
      if(!(miss = realloc(miss, len))) return lob_free(ret);
      sprintf(miss+strlen(miss),"%u]", delta);
      lob_set_raw(ret,"miss",4,miss,strlen(miss));
    }

    c->acked = c->ack;
  }
  
  return ret;
}
Пример #14
0
// return >0 if this alg is supported
uint8_t jwt_alg(char *alg)
{
  uint8_t err;
  lob_t test = lob_new();
  lob_set(test,"alg",alg);
  // TODO refactor how this is checked
  err = e3x_exchange_validate(NULL, test, NULL, (uint8_t*)"x", 1);
  lob_free(test);
  return (err == 1) ? 0 : 1;
}
Пример #15
0
// generate json of mesh keys and current paths
lob_t mesh_json(mesh_t mesh)
{
  lob_t json, paths;
  if(!mesh) return LOG_ERROR("bad args");

  json = lob_new();
  lob_set(json,"hashname",hashname_char(mesh->id));
  lob_set_raw(json,"keys",0,(char*)mesh->keys->head,mesh->keys->head_len);
  paths = lob_array(mesh->paths);
  lob_set_raw(json,"paths",0,(char*)paths->head,paths->head_len);
  lob_free(paths);
  return json;
}
Пример #16
0
// get link info json
lob_t link_json(link_t link)
{
  char hex[3];
  lob_t json;
  if(!link) return LOG("bad args");

  json = lob_new();
  lob_set(json,"hashname",hashname_char(link->id));
  lob_set(json,"csid",util_hex(&link->csid, 1, hex));
  lob_set_base32(json,"key",link->key->body,link->key->body_len);
//  paths = lob_array(mesh->paths);
//  lob_set_raw(json,"paths",0,(char*)paths->head,paths->head_len);
//  lob_free(paths);
  return json;
}
Пример #17
0
// get keys from query
lob_t util_uri_keys(lob_t uri)
{
  uint32_t i;
  char *key, *value;
  lob_t keys, query = lob_linked(uri);
  if(!query) return NULL;
  keys = lob_new();

  // loop through all keyval pairs to find cs**
  for(i=0;(key = lob_get_index(query,i));i+=2)
  {
    value = lob_get_index(query,i+1);
    if(strlen(key) != 4 || strncmp(key,"cs",2) != 0 || !value) continue; // skip non-csid keys
    lob_set_len(keys,key+2,2,value,strlen(value));
  }
  
  return keys;
}
Пример #18
0
net_tcp4_t net_tcp4_new(mesh_t mesh, lob_t options)
{
  int port, sock, pipes, opt = 1;
  net_tcp4_t net;
  struct sockaddr_in sa;
  socklen_t size = sizeof(struct sockaddr_in);
  
  port = lob_get_int(options,"port");
  pipes = lob_get_int(options,"pipes");
  if(!pipes) pipes = 11; // hashtable for active pipes

  // create a udp socket
  if((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) ) < 0 ) return LOG("failed to create socket %s",strerror(errno));

  memset(&sa,0,sizeof(sa));
  sa.sin_family = AF_INET;
  sa.sin_port = htons(port);
  sa.sin_addr.s_addr = htonl(INADDR_ANY);
  if(bind(sock, (struct sockaddr*)&sa, size) < 0) return LOG("bind failed %s",strerror(errno));
  getsockname(sock, (struct sockaddr*)&sa, &size);
  if(listen(sock, 10) < 0) return LOG("listen failed %s",strerror(errno));
  setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt , sizeof(int));
  fcntl(sock, F_SETFL, O_NONBLOCK);

  if(!(net = malloc(sizeof (struct net_tcp4_struct)))) return LOG("OOM");
  memset(net,0,sizeof (struct net_tcp4_struct));
  net->server = sock;
  net->port = ntohs(sa.sin_port);
  net->pipes = xht_new(pipes);

  // connect us to this mesh
  net->mesh = mesh;
  xht_set(mesh->index, MUID, net);
  mesh_on_path(mesh, MUID, tcp4_path);
  
  // convenience
  net->path = lob_new();
  lob_set(net->path,"type","tcp4");
  lob_set(net->path,"ip","127.0.0.1");
  lob_set_int(net->path,"port",net->port);

  return net;
}
Пример #19
0
lob_t util_uri_add_keys(lob_t uri, lob_t keys)
{
  uint32_t i;
  char *key, *value, csid[5];
  lob_t query = lob_linked(uri);
  if(!uri || !keys) return NULL;
  if(!query)
  {
    query = lob_new();
    lob_link(uri, query);
  }
  
  for(i=0;(key = lob_get_index(keys,i));i+=2)
  {
    value = lob_get_index(keys,i+1);
    if(strlen(key) != 2 || !value) continue; // paranoid
    snprintf(csid,5,"cs%s",key);
    lob_set(query,csid,value);
  }

  return uri;
}
Пример #20
0
lob_t ephemeral_encrypt(ephemeral_t ephem, lob_t inner)
{
  lob_t outer;
  size_t inner_len;

  outer = lob_new();
  inner_len = lob_len(inner);
  if(!lob_body(outer,NULL,16+24+inner_len+crypto_secretbox_MACBYTES)) return lob_free(outer);

  // copy in token and create nonce
  memcpy(outer->body,ephem->token,16);
  randombytes(outer->body+16,24);

  crypto_secretbox_easy(outer->body+16+24,
    lob_raw(inner),
    lob_len(inner),
    outer->body+16,
    ephem->enckey);

  return outer;

}
Пример #21
0
// decode base64 into the pair of lob packets
lob_t jwt_decode(char *encoded, size_t len)
{
  lob_t header, claims;
  char *dot1, *dot2, *end;

  if(!encoded) return NULL;
  if(!len) len = strlen(encoded);
  end = encoded+len;
  
  // make sure the dot separators are there
  dot1 = memchr(encoded,'.',(end-encoded));
  if(!dot1) return LOG_INFO("missing/bad first separator");
  dot1++;
  dot2 = memchr(dot1,'.',(end-dot1));
  if(!dot2) return LOG_INFO("missing/bad second separator");
  dot2++;

  // quick sanity check of the base64
  if(!base64_decoder(dot2, (end-dot2), NULL)) return LOG_INFO("invalid sig base64: %.*s",(end-dot2),dot2);
  if(!base64_decoder(dot1, (dot2-dot1)-1, NULL)) return LOG_INFO("invalid claims base64: %.*s",(dot2-dot1)-1,dot1);
  if(!base64_decoder(encoded, (dot1-encoded)-1, NULL)) return LOG_INFO("invalid header b64: %.*s",(dot1-encoded)-1,encoded);

  claims = lob_new();
  header = lob_link(NULL, claims);
  
  // decode claims json
  lob_head(claims, NULL, base64_decoder(dot1, (dot2-dot1)-1, NULL));
  base64_decoder(dot1, (dot2-dot1)-1, lob_head_get(claims));

  // decode claims sig 
  lob_body(claims, NULL, base64_decoder(dot2, (end-dot2), NULL));
  base64_decoder(dot2, (end-dot2), lob_body_get(claims));

  // decode header json
  lob_head(header, NULL, base64_decoder(encoded, (dot1-encoded)-1, NULL));
  base64_decoder(encoded, (dot1-encoded)-1, lob_head_get(header));

  return header;
}
Пример #22
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)
  {
    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;
}
Пример #23
0
// intermediate hashes in the json, if id is given it is attached as BODY instead
lob_t hashname_im(lob_t keys, uint8_t id)
{
  uint32_t i;
  size_t len;
  uint8_t *buf, hash[32];
  char *key, *value, hex[3];
  lob_t im;

  if(!keys) return LOG("bad args");

  // loop through all keys and create intermediates
  im = lob_new();
  buf = NULL;
  util_hex(&id,1,hex);
  for(i=0;(key = lob_get_index(keys,i));i+=2)
  {
    value = lob_get_index(keys,i+1);
    if(strlen(key) != 2 || !value) continue; // skip non-csid keys
    len = base32_decode_floor(strlen(value));
    // save to body raw or as a base32 intermediate value
    if(id && util_cmp(hex,key) == 0)
    {
      lob_body(im,NULL,len);
      if(base32_decode(value,strlen(value),im->body,len) != len) continue;
      lob_set_raw(im,key,0,"true",4);
    }else{
      buf = util_reallocf(buf,len);
      if(!buf) return lob_free(im);
      if(base32_decode(value,strlen(value),buf,len) != len) continue;
      // store the hash intermediate value
      e3x_hash(buf,len,hash);
      lob_set_base32(im,key,hash,32);
    }
  }
  if(buf) free(buf);
  return im;
}
Пример #24
0
// just a convenience, generates handshake w/ current e3x_exchange_at value
lob_t e3x_exchange_handshake(e3x_exchange_t x, lob_t inner)
{
  lob_t tmp;
  uint8_t i;
  uint8_t local = 0;
  if(!x) return LOG("invalid args");
  if(!x->out) return LOG("no out set");

  // create deprecated key handshake inner from all supported csets
  if(!inner)
  {
    local = 1;
    inner = lob_new();
    lob_set(inner, "type", "key");
    // loop through all ciphersets for any keys
    for(i=0; i<CS_MAX; i++)
    {
      if(!(tmp = x->self->keys[i])) continue;
      // this csid's key is the body, rest is intermediate in json
      if(e3x_cipher_sets[i] == x->cs)
      {
        lob_body(inner,tmp->body,tmp->body_len);
      }else{
        uint8_t hash[32];
        e3x_hash(tmp->body,tmp->body_len,hash);
        lob_set_base32(inner,e3x_cipher_sets[i]->hex,hash,32);
      }
    }
  }

  // set standard values
  lob_set_uint(inner,"at",x->out);

  tmp = e3x_exchange_message(x, inner);
  if(!local) return tmp;
  return lob_link(tmp, inner);
}
Пример #25
0
int main(int argc, char *argv[])
{
  lob_t id, options, json;
  mesh_t mesh;
  net_udp4_t udp4;
  net_tcp4_t tcp4;
  int port = 0;

  if(argc==2)
  {
    port = atoi(argv[1]);
  }

  id = util_fjson("id.json");
  if(!id) return -1;
  
  mesh = mesh_new(0);
  mesh_load(mesh,lob_get_json(id,"secrets"),lob_get_json(id,"keys"));
  mesh_on_discover(mesh,"auto",mesh_add); // auto-link anyone
  mesh_on_open(mesh,"path",path_on_open); // add path support

  options = lob_new();
  lob_set_int(options,"port",port);

  udp4 = net_udp4_new(mesh, options);
  util_sock_timeout(udp4->server,100);

  tcp4 = net_tcp4_new(mesh, options);

  json = mesh_json(mesh);
  printf("%s\n",lob_json(json));
  printf("%s\n",mesh_uri(mesh, NULL));

  while(net_udp4_receive(udp4) && net_tcp4_loop(tcp4));

  /*
  if(util_loadjson(s) != 0 || (sock = util_server(0,1000)) <= 0)
  {
    printf("failed to startup %s or %s\n", strerror(errno), crypt_err());
    return -1;
  }

  printf("loaded hashname %s\n",s->id->hexname);

  // create/send a ping packet  
  c = chan_new(s, bucket_get(s->seeds, 0), "link", 0);
  p = chan_packet(c);
  chan_send(c, p);
  util_sendall(s,sock);

  in = path_new("ipv4");
  while(util_readone(s, sock, in) == 0)
  {
    switch_loop(s);

    while((c = switch_pop(s)))
    {
      printf("channel active %d %s %s\n",c->ended,c->hexid,c->to->hexname);
      if(util_cmp(c->type,"connect") == 0) ext_connect(c);
      if(util_cmp(c->type,"link") == 0) ext_link(c);
      if(util_cmp(c->type,"path") == 0) ext_path(c);
      while((p = chan_pop(c)))
      {
        printf("unhandled channel packet %.*s\n", p->json_len, p->json);      
        lob_free(p);
      }
    }

    util_sendall(s,sock);
  }
  */
  perror("exiting");
  return 0;
}
Пример #26
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;
}
Пример #27
0
// serialize out from lob format to "uri" key and return it
char *util_uri_format(lob_t uri)
{
  char *part, *key, *value;
  uint32_t i, prev = 0;
  lob_t buf, query;
  if(!uri) return NULL;
  
  // use a lob body as the buffer to build it up
  buf = lob_new();
  
  part = lob_get(uri, "protocol");
  if(part)
  {
    lob_append_str(buf, part);
  }else{
    lob_append_str(buf, "link");
  }
  lob_append_str(buf, "://");

  part = lob_get(uri, "hostname");
  if(part)
  {
    lob_append_str(buf, part);
    part = lob_get(uri, "port");
    if(part)
    {
      lob_append_str(buf, ":");
      lob_append_str(buf, part);
    }
  }else{
    part = lob_get(uri, "host");
    if(part) lob_append_str(buf, part);
  }
  
  part = lob_get(uri, "path");
  if(part)
  {
    lob_append_str(buf, part);
  }else{
    lob_append_str(buf, "/");
  }
  
  // append on any query string
  
  for(query = lob_linked(uri); query; query = lob_linked(query))
  {
    for(i=0;(key = lob_get_index(query,i));i+=2)
    {
      value = lob_get_index(query,i+1);
      if(!strlen(key) || !value) continue; // paranoid
      lob_append_str(buf,(prev++)?"&":"?");
      lob_append_str(buf,key);
      lob_append_str(buf,"=");
      lob_append_str(buf,value);
    }
  }

  if((part = lob_get(uri, "hash")))
  {
    lob_append_str(buf, "#");
    lob_append_str(buf, part);
  }

  lob_set_len(uri,"uri",3,(char*)buf->body,buf->body_len);
  lob_free(buf);

  return lob_get(uri,"uri");
}
Пример #28
0
// this is a very simple single-pass telehash uri parser, no magic
lob_t util_uri_parse(char *encoded)
{
  size_t klen, vlen;
  char *at, *val;
  lob_t uri;
  
  if(!encoded) return LOG("bad args");
  uri = lob_new();
  lob_set(uri,"orig",encoded);

  // check for protocol:// prefix first
  if(!(at = strstr(encoded,"://")))
  {
    lob_set(uri, "protocol", "link");
  }else{
    lob_set_len(uri, "protocol", 0, encoded, (size_t)(at - encoded));
    encoded = at+3;
  }
  
  // check for user@ prefix next
  if((at = strchr(encoded,'@')))
  {
    lob_set_len(uri, "auth", 0, encoded, (size_t)(at - encoded));
    encoded = at+1;
  }
  
  // ensure there's at least a host
  if(!strlen(encoded) || !isalnum((int)encoded[0]))
  {
    lob_free(uri);
    return LOG("invalid host: '%s'",encoded);
  }

  // copy in host and parse hostname/port
  if((at = strchr(encoded,'/')) || (at = strchr(encoded,'?')) || (at = strchr(encoded,'#')))
  {
    lob_set_len(uri, "host", 0, encoded, (size_t)(at - encoded));
  }else{
    lob_set_len(uri, "host", 0, encoded, strlen(encoded));
  }

  // hostname+port
  val = lob_get(uri, "host");
  if(val && (at = strchr(val,':')))
  {
    lob_set_len(uri, "hostname", 0, val, (size_t)(at - val));
    lob_set_uint(uri, "port", (uint16_t)strtoul(at+1,NULL,10));
  }else{
    lob_set(uri, "hostname", val);
  }

  // optional path
  if((at = strchr(encoded,'/')))
  {
    encoded = at;
    if((at = strchr(encoded+1,'?')) || (at = strchr(encoded+1,'#')))
    {
      lob_set_len(uri, "path", 0, encoded, (size_t)(at - encoded));
    }else{
      lob_set_len(uri, "path", 0, encoded, strlen(encoded));
    }
  }

  // optional hash at the end
  if((at = strchr(encoded,'#')))
  {
    lob_set_len(uri, "hash", 0, at+1, strlen(at+1));
  }

  // optional query string
  if((at = strchr(encoded,'?')))
  {
    uri->chain = lob_new();
    encoded = at+1;
    if((at = strchr(encoded,'#')))
    {
      klen = (size_t)(at - encoded);
    }else{
      klen = strlen(encoded);
    }
    while(klen)
    {
      // skip any separator
      if(*encoded == '&')
      {
        encoded++;
        klen--;
      }
      // require the equals
      if(!(val = strchr(encoded,'='))) break;
      val++;
      if((at = strchr(val,'&')))
      {
        vlen = (size_t)(at - val);
      }else{
        vlen = strlen(val);
      }
      lob_set_len(uri->chain, encoded, (size_t)(val-encoded)-1, val, vlen);
      // skip past whole block
      klen -= (size_t)((val+vlen) - encoded);
      encoded = val + vlen;
    }
  }

  return uri;
}
Пример #29
0
int main(int argc, char **argv)
{
  fail_unless(!e3x_init(NULL)); // random seed
  
  mesh_t meshA = mesh_new();
  fail_unless(meshA);
  lob_t keyA = lob_new();
  lob_set(keyA,"1a",A_KEY);
  lob_t secA = lob_new();
  lob_set(secA,"1a",A_SEC);
  fail_unless(!mesh_load(meshA,secA,keyA));
  mesh_on_discover(meshA,"auto",mesh_add);

  lob_t keyB = lob_new();
  lob_set(keyB,"1a",B_KEY);
  hashname_t hnB = hashname_vkeys(keyB);
  fail_unless(hnB);
  link_t linkAB = link_get(meshA,hnB);
  fail_unless(linkAB);
  
  netA = tmesh_new(meshA, "test", NULL);
  fail_unless(netA);
  
  netA->sort = driver_sort;
  netA->schedule = driver_schedule;
  netA->advance = driver_advance;
  netA->medium = driver_medium;
  netA->free = driver_free;
  
  fail_unless(netA->knock);
  fail_unless(strcmp(netA->community,"test") == 0);

  // create outgoing beacon
  fail_unless(tmesh_schedule(netA,1));
  fail_unless(netA->beacon);
  fail_unless(!netA->beacon->frames);
  fail_unless(!netA->beacon->mote);
  fail_unless(netA->beacon->medium == 1);

  // should have schedule a beacon rx
  fail_unless(scheduled == 1);
  fail_unless(netA->knock->is_active);
  fail_unless(netA->knock->tempo == netA->beacon);
  fail_unless(netA->knock->tempo->at == 2);
  fail_unless(netA->knock->tempo->chan == 1);

  mote_t moteB = tmesh_mote(netA, linkAB);
  fail_unless(moteB);
  fail_unless(moteB->link == linkAB);
  fail_unless(moteB->signal);
  fail_unless(moteB->signal->medium == 1);
  fail_unless(moteB->signal->driver == (void*)1);

  /*
  cmnty_t c = tmesh_join(netA,"qzjb5f4t","foo");
  fail_unless(c);
  fail_unless(c->medium->bin[0] == 134);
  fail_unless(c->medium->radio == devA->id);
  fail_unless(c->beacons == NULL);
  fail_unless(c->pipe->path);
  LOG("netA %.*s",c->pipe->path->head_len,c->pipe->path->head);
  fail_unless(tmesh_leave(netA,c));

  char hex[256];
  netA->last = 1;
  fail_unless(!tmesh_join(netA, "azdhpa5r", NULL));
  fail_unless((c = tmesh_join(netA, "azdhpa5n", "Public")));
  fail_unless(c->beacons);
  fail_unless(c->beacons->public);
  mote_t m = c->beacons;
  mote_t mpub = m;
  memset(m->nonce,42,8); // nonce is random, force stable for fixture testing
  LOG("nonce %s",util_hex(m->nonce,8,hex));
  fail_unless(util_cmp(hex,"2a2a2a2a2a2a2a2a") == 0);
  LOG("public at is now %lu",c->beacons->at);

  m = tmesh_link(netA, c, link);
  fail_unless(m);
  fail_unless(m->link == link);
  fail_unless(m == tmesh_link(netA, c, link));
  fail_unless(m->order == 0);
  memset(m->nonce,3,8); // nonce is random, force stable for fixture testing
  LOG("secret %s",util_hex(m->secret,32,hex));
  fail_unless(util_cmp(hex,"b7bc9e4f1f128f49a3bcef321450b996600987b129723cc7ae752d6500883c65") == 0);
  LOG("public at is now %lu",mpub->at);
  
  fail_unless(mote_reset(m));
  memset(m->nonce,0,8); // nonce is random, force stable for fixture testing
  knock_t knock = devA->knock;
  fail_unless(mote_advance(m));
  LOG("next is %lld",m->at);
  fail_unless(m->at == 8369);
  fail_unless(mote_knock(m,knock));
  fail_unless(!knock->tx);
  fail_unless(mote_advance(m));
  fail_unless(mote_advance(m));
  fail_unless(mote_advance(m));
  fail_unless(mote_advance(m));
  fail_unless(mote_knock(m,knock));
  fail_unless(knock->tx);
  LOG("next is %lld",knock->start);
  fail_unless(knock->start == 29905);
  LOG("public at is now %lu",mpub->at);
  fail_unless(mpub->at == 1);
  mpub->at = 5;

  mote_t bm = tmesh_seek(netA,c,link->id);
  memset(bm->nonce,2,8); // nonce is random, force stable for fixture testing
  mote_reset(m);
  memset(m->nonce,2,8); // nonce is random, force stable for fixture testing
  m->at = 10;
  fail_unless(tmesh_process(netA,1,1));
  fail_unless(m->at == 9);
  fail_unless(knock->mote == mpub);

  LOG("tx %d start %lld stop %lld chan %d at %lld",knock->tx,knock->start,knock->stop,knock->chan,m->at);
  fail_unless(!knock->tx);
  fail_unless(knock->start == 4);
  fail_unless(knock->stop == 4+1000);
  fail_unless(knock->chan == 27);
//  fail_unless(tmesh_knocked(netA,knock));
  LOG("public at is now %lu",c->beacons->at);
  
  fail_unless(mote_advance(m));
  LOG("seek %s",util_hex(m->nonce,8,hex));
  fail_unless(util_cmp(hex,"dc09a8ca7f5cb75e") == 0);
  fail_unless(mote_advance(m));
  LOG("at is %lu",m->at);
  fail_unless(m->at >= 6037);

  // public ping now
//  m->at = 0xffffffff;
  memset(knock,0,sizeof(struct knock_struct));
  fail_unless(tmesh_process(netA,8050,0));
  LOG("beacon at is now %lu",bm->at);
  fail_unless(knock->mote == bm);
  LOG("tx %d start %lld stop %lld chan %d",knock->tx,knock->start,knock->stop,knock->chan);
  fail_unless(!knock->tx);
  fail_unless(knock->start == 9040);
  fail_unless(knock->stop == 9040+1000);
  fail_unless(knock->chan == 19);
  
  // TEMP DISABLED
  return 0;

  // public ping tx
  memset(m->nonce,4,8); // fixture for testing
  m->order = 1;
  memset(knock,0,sizeof(struct knock_struct));
  LOG("public at is now %lu",m->at);
  fail_unless(tmesh_process(netA,20000,0));
  fail_unless(knock->mote == bm);
  LOG("tx %d start %lld stop %lld chan %d",knock->tx,knock->start,knock->stop,knock->chan);
  fail_unless(knock->ready);
  fail_unless(knock->tx);
  fail_unless(knock->start == 21128);
  fail_unless(knock->chan == 19);
  // frame would be random ciphered, but we fixed it to test
  LOG("frame %s",util_hex(knock->frame,32+8,hex)); // just the stable part
  fail_unless(util_cmp(hex,"6c265ac8d9a533a1bc7c7f49ed83ae5d32d31b4b9b76c485b182d649c91deb08a160aab63ee8212c") == 0);
  // let's preted it's an rx now
  knock->tx = 0;
  knock->stopped = knock->stop; // fake rx good
  LOG("faking rx in");
  fail_unless(!tmesh_knocked(netA,knock)); // identity crisis
  fail_unless(tmesh_process(netA,42424,0));
  LOG("tx %d start %lld stop %lld chan %d",knock->tx,knock->start,knock->stop,knock->chan);
  fail_unless(knock->stopped);
  fail_unless(knock->start == 43444);

  // leave public community
  fail_unless(tmesh_leave(netA,c));
  
  // two motes meshing
  mesh_t meshB = mesh_new();
  fail_unless(meshB);
  lob_t secB = lob_new();
  lob_set(secB,"1a",B_SEC);
  fail_unless(!mesh_load(meshB,secB,keyB));
  mesh_on_discover(meshB,"auto",mesh_add);

  hashname_t hnA = hashname_vkeys(keyA);
  fail_unless(hnA);
  link_t linkBA = link_get(meshB,hnA);
  fail_unless(linkBA);
  
  netB = tmesh_new(meshB, NULL);
  fail_unless(netB);
  cmnty_t cB = tmesh_join(netB,"qzjb5f4t","test");
  fail_unless(cB);
  fail_unless(cB->pipe->path);
  LOG("netB %s",lob_json(cB->pipe->path));

  cmnty_t cA = tmesh_join(netA,"qzjb5f4t","test");
  fail_unless(cA);
  fail_unless(cA->pipe->path);
  LOG("netA %s",lob_json(cA->pipe->path));
  
  mote_t bmBA = tmesh_seek(netB, cB, linkBA->id);
  fail_unless(bmBA);
  fail_unless(bmBA->order == 1);
  LOG("bmBA %s secret %s",hashname_short(bmBA->beacon),util_hex(bmBA->secret,32,hex));
  fail_unless(util_cmp(hex,"9a972d28dcc211d43eafdca7877bed1bbeaec30fd3740f4b787355d10423ad12") == 0);

  mote_t mBA = tmesh_link(netB, cB, linkBA);
  fail_unless(mBA);
  fail_unless(mBA->order == 1);
  LOG("mBA %s secret %s",hashname_short(mBA->link->id),util_hex(mBA->secret,32,hex));
  fail_unless(util_cmp(hex,"9a972d28dcc211d43eafdca7877bed1bbeaec30fd3740f4b787355d10423ad12") == 0);

  mote_t bmAB = tmesh_seek(netA, cA, link->id);
  fail_unless(bmAB);
  fail_unless(bmAB->order == 0);
  LOG("bmBA %s secret %s",hashname_short(bmAB->beacon),util_hex(bmAB->secret,32,hex));
  fail_unless(util_cmp(hex,"9a972d28dcc211d43eafdca7877bed1bbeaec30fd3740f4b787355d10423ad12") == 0);

  mote_t mAB = tmesh_link(netA, cA, link);
  fail_unless(mAB);
  fail_unless(mAB->order == 0);
  LOG("mAB %s secret %s",hashname_short(mAB->link->id),util_hex(mAB->secret,32,hex));
  fail_unless(util_cmp(hex,"9a972d28dcc211d43eafdca7877bed1bbeaec30fd3740f4b787355d10423ad12") == 0);
  
  knock_t knBA = devB->knock;
  knBA->ready = 0;
  memset(mBA->nonce,0,8);
  memset(bmBA->nonce,2,8);
  fail_unless(tmesh_process(netB,10,0));
  fail_unless(knBA->mote == bmBA);
  LOG("BA tx is %d chan %d at %lu",knBA->tx,knBA->chan,knBA->start);
  fail_unless(knBA->chan == 35);
  fail_unless(knBA->tx == 0);

  knock_t knAB = devA->knock;
  knAB->ready = 0;
  memset(mAB->nonce,10,8);
  memset(bmAB->nonce,15,8);
  fail_unless(tmesh_process(netA,44444,0));
  fail_unless(knAB->mote == bmAB);
  LOG("AB tx is %d chan %d at %lu nonce %s",knAB->tx,knAB->chan,knAB->start,util_hex(mAB->nonce,8,NULL));
  fail_unless(knAB->chan == 35);
  fail_unless(knAB->tx == 1);

  // fake reception, with fake cake
  LOG("process netA");
  RXTX(knAB,knBA);
  fail_unless(tmesh_knocked(netA,knAB));
  fail_unless(tmesh_process(netA,67689,0));
  fail_unless(knAB->mote == bmAB);
  fail_unless(!bmAB->chunks);

  LOG("process netB");
  RXTX(knAB,knBA);
  fail_unless(tmesh_knocked(netB,knBA));
  fail_unless(tmesh_process(netB,22000,0));

  // dummy data for sync send
  netA->pubim = hashname_im(netA->mesh->keys, hashname_id(netA->mesh->keys,netA->mesh->keys));
  netB->pubim = hashname_im(netB->mesh->keys, hashname_id(netB->mesh->keys,netB->mesh->keys));

  // back to the future
  RXTX(knAB,knBA);
  fail_unless(tmesh_knocked(netA,knAB));
  LOG("mAB %lu mBA %lu",mAB->at,mBA->at);
  while(knBA->mote != bmBA)
  {
    knBA->ready = 0;
    fail_unless(tmesh_process(netB,knBA->stop,0));
  }
  LOG("BA tx is %d chan %d at %lu nonce %s",knBA->tx,knBA->chan,knAB->start,util_hex(mBA->nonce,8,NULL));
//  fail_unless(knBA->tx == 1);

  RXTX(knAB,knBA);
  LOG("mAB %lu mBA %lu",mAB->at,mBA->at);
  fail_unless(tmesh_knocked(netB,knBA));
  while(knAB->mote != bmAB)
  {
    knAB->ready = 0;
    fail_unless(tmesh_process(netA,knAB->stop,0));
  }
  LOG("AB tx is %d chan %d at %lu nonce %s",knAB->tx,knAB->chan,knAB->start,util_hex(mAB->nonce,8,NULL));
//  fail_unless(knAB->tx == 0);

  // in sync!
  fail_unless(!mBA->chunks);
  fail_unless(!mAB->chunks);
  mAB->at = mBA->at;
  LOG("mAB %lu mBA %lu",mAB->at,mBA->at);
  fail_unless(mAB->at == mBA->at);
  
  // continue establishing link
  printf("\n\n");
  int max = 40;
  mote_reset(mAB);
  mote_reset(mBA);
  mote_reset(bmAB);
  mote_reset(bmBA);
  mAB->at = mBA->at;
  bmAB->at = bmBA->at;
  uint32_t step = mAB->at;
  while(--max > 0 && !link_up(mBA->link) && !link_up(mAB->link))
  {
    printf("\n\n%d %u\n",max,step);

    tmesh_process(netA,step,0);
    tmesh_process(netB,step,0);

    LOG("AB %d %d/%d BA %d %d/%d",knAB->tx,knAB->start,knAB->stop,knBA->tx,knBA->start,knBA->stop);
    if(knAB->stop > step) step = knAB->stop;
    if(knBA->stop > step) step = knBA->stop;

    if(knAB->chan == knBA->chan)
    {
      printf("~~~~RXTX %u\n",step);
      RXTX(knAB,knBA);
      knAB->stopped = knAB->stop;
      knBA->stopped = knBA->stop;
    }else{
      knAB->err = knBA->err = 1;
    }

    tmesh_knocked(netA,knAB);
    tmesh_knocked(netB,knBA);

  }
  LOG("TODO linked by %d",max);
//  fail_unless(max);
*/
  return 0;
}
Пример #30
0
int main(int argc, char **argv)
{
  lob_t packet;
  packet = lob_new();
  fail_unless(packet);
  lob_free(packet);

  uint8_t buf[1024];
  char *hex = "001d7b2274797065223a2274657374222c22666f6f223a5b22626172225d7d616e792062696e61727921";
  uint8_t len = strlen(hex)/2;
  util_unhex(hex,strlen(hex),buf);
  packet = lob_parse(buf,len);
  fail_unless(packet);
  fail_unless(lob_len(packet));
  fail_unless(packet->head_len == 29);
  fail_unless(packet->body_len == 11);
  fail_unless(util_cmp(lob_get(packet,"type"),"test") == 0);
  fail_unless(util_cmp(lob_get(packet,"foo"),"[\"bar\"]") == 0);
  
  lob_free(packet);
  packet = lob_new();
  lob_set_base32(packet,"32",buf,len);
  fail_unless(lob_get(packet,"32"));
  fail_unless(strlen(lob_get(packet,"32")) == (base32_encode_length(len)-1));
  lob_t bin = lob_get_base32(packet,"32");
  fail_unless(bin);
  fail_unless(bin->body_len == len);

  lob_set(packet,"key","value");
  fail_unless(lob_keys(packet) == 2);

  // test sorting
  lob_set(packet,"zz","value");
  lob_set(packet,"a","value");
  lob_set(packet,"z","value");
  lob_sort(packet);
  fail_unless(util_cmp(lob_get_index(packet,0),"32") == 0);
  fail_unless(util_cmp(lob_get_index(packet,2),"a") == 0);
  fail_unless(util_cmp(lob_get_index(packet,4),"key") == 0);
  fail_unless(util_cmp(lob_get_index(packet,6),"z") == 0);
  fail_unless(util_cmp(lob_get_index(packet,8),"zz") == 0);
  lob_free(packet);
  
  // minimal comparison test
  lob_t a = lob_new();
  lob_set(a,"foo","bar");
  lob_t b = lob_new();
  lob_set(b,"foo","bar");
  fail_unless(lob_cmp(a,b) == 0);
  lob_set(b,"bar","foo");
  fail_unless(lob_cmp(a,b) != 0);

  // lots of basic list testing
  lob_t list = lob_new();
  lob_t item = lob_new();
  fail_unless(lob_push(list,item));
  fail_unless(lob_pop(list) == item);
  list = item->next;
  fail_unless((list = lob_unshift(list,item)));
  fail_unless(lob_shift(list) == item);
  list = item->next;
  fail_unless(lob_push(list,item));
  fail_unless(list->next == item);
  lob_t insert = lob_new();
  fail_unless(lob_insert(list,list,insert));
  fail_unless(list->next == insert);
  fail_unless(insert->next == item);
  fail_unless(lob_splice(list,insert));
  fail_unless(list->next == item);

  lob_t array = lob_array(list);
  fail_unless(array);
  fail_unless(util_cmp(lob_json(array),"[,]") == 0);

  fail_unless(lob_freeall(list) == NULL);

  // simple index testing
  lob_t index = lob_new();
  lob_t c1 = lob_new();
  lob_set(c1,"id","c1");
  lob_push(index,c1);
  lob_t c2 = lob_new();
  lob_set(c2,"id","c2");
  lob_push(index,c2);
  fail_unless(lob_match(index,"id","c1") == c1);
  fail_unless(lob_match(index,"id","c2") == c2);
  
  float f = 42.42;
  lob_t ft = lob_new();
  lob_head(ft,(uint8_t*)"{\"foo\":42.42}",13);
  fail_unless(lob_get_float(ft,"foo") == f);
  lob_set_float(ft,"bar2",f,2);
  fail_unless(lob_get_float(ft,"bar2") == f);
  lob_set_float(ft,"bar1",f,1);
  fail_unless(lob_get_cmp(ft,"bar1","42.4") == 0);
  lob_set_float(ft,"bar0",f,0);
  fail_unless(lob_get_int(ft,"bar0") == 42);
  LOG("floats %s",lob_json(ft));

  return 0;
}