Exemplo n.º 1
0
// internal to clean up written data
util_chunks_t _util_chunks_gc(util_chunks_t chunks)
{
  size_t len;
  if(!chunks) return NULL;

//  LOG("CHUNK GC %d %d %s",chunks,chunks->writeat,util_hex(chunks->writing,chunks->writelen,NULL));

  // nothing to do
  if(!chunks->writing || !chunks->writeat || !chunks->writelen) return chunks;

  len = chunks->writing[0]+1;
  if(len > chunks->writelen) return LOG("bad chunk write data");

  // the current chunk hasn't beeen written yet
  if(chunks->writeat < len) return chunks;

  // remove the current chunk
  chunks->writelen -= len;
  chunks->writeat -= len;
  memmove(chunks->writing,chunks->writing+len,chunks->writelen);
  chunks->writing = util_reallocf(chunks->writing, chunks->writelen);

  // tail recurse to eat any more chunks
  return _util_chunks_gc(chunks);
}
Exemplo n.º 2
0
// get any packets that have been reassembled from incoming chunks
lob_t util_chunks_receive(util_chunks_t chunks)
{
  uint32_t at, len, start;
  uint8_t *buf, *append;
  lob_t ret;

  if(!chunks || !chunks->reading) return NULL;

  // skip over any 0 acks in the start
  for(start = 0; start < chunks->readlen && chunks->reading[start] == 0; start += 1);

  // check for complete packet and get its length
  for(len = 0, at = start;at < chunks->readlen && chunks->reading[at]; at += chunks->reading[at]+1) len += chunks->reading[at];

  if(!len || at >= chunks->readlen) return NULL;
  
  if(!(buf = malloc(len))) return LOG("OOM %d",len);
  // copy in the body of each chunk
  for(at = start, append = buf; chunks->reading[at]; append += chunks->reading[at], at += chunks->reading[at]+1)
  {
    memcpy(append, chunks->reading+(at+1), chunks->reading[at]);
  }
  ret = lob_decloak(buf,len);
  free(buf);
  
  // advance the reading buffer the whole packet, shrink
  at++;
  chunks->readlen -= at;
  memmove(chunks->reading,chunks->reading+at,chunks->readlen);
  chunks->reading = util_reallocf(chunks->reading,chunks->readlen);

  return ret;
}
Exemplo n.º 3
0
// internal to append read data
util_chunks_t _util_chunks_append(util_chunks_t chunks, uint8_t *block, size_t len)
{
  if(!chunks || !block || !len) return chunks;
  if(!chunks->reading) chunks->readlen = chunks->acked = 0; // be paranoid
  chunks->readlen += len;
  if(!(chunks->reading = util_reallocf(chunks->reading, chunks->readlen))) return LOG("OOM"); 
  memcpy(chunks->reading+(chunks->readlen-len),block,len);
  return chunks;
}
Exemplo n.º 4
0
// get paths from host and query
lob_t util_uri_paths(lob_t uri)
{
  uint32_t i;
  uint16_t port;
  uint8_t *buf;
  size_t len;
  char *key, *value;
  lob_t paths, query = lob_linked(uri);
  if(!query) return NULL;
  paths = NULL;
  
  // gen paths from host/port
  if((port = lob_get_uint(uri,"port")))
  {
    key = lob_get(uri,"host");
    paths = lob_chain(paths);
    lob_set(paths,"type","upd4");
    lob_set(paths,"ip",key);
    lob_set_uint(paths,"port",port);
    paths = lob_chain(paths);
    lob_set(paths,"type","tcp4");
    lob_set(paths,"ip",key);
    lob_set_uint(paths,"port",port);
  }

  // loop through all keyval pairs to find paths
  buf = NULL;
  for(i=0;(key = lob_get_index(query,i));i+=2)
  {
    value = lob_get_index(query,i+1);
    if(util_cmp(key,"paths") != 0 || !value) continue;
    len = base32_decode_floor(strlen(value));
    buf = util_reallocf(buf,len);
    if(!buf) continue;
    if(base32_decode(value,strlen(value),buf,len) < len) continue;
    paths = lob_link(lob_parse(buf,len), paths);
  }
  free(buf);
  
  return paths;
}
Exemplo n.º 5
0
// sends an ack if neccessary, after any more chunks have been received and none waiting to send
util_chunks_t util_chunks_ack(util_chunks_t chunks)
{
  uint32_t count = 0, zeros = 0, at;

  if(!chunks->readlen) return NULL;

  // walk through read data and count chunks
  for(at = chunks->reading[0];at < chunks->readlen; at += chunks->reading[at])
  {
    count++;
    if(chunks->reading[at] == 0) zeros++;
    else zeros = 0;
    at++; // add chunk size byte
  }

//  LOG("count %d acked %d first %d len %d zeros %d",count,chunks->acked,chunks->reading[0],chunks->readlen,zeros);

  // no new chunks
  if(count == chunks->acked) return NULL;

  // implicitly unblock after any new chunks
  util_chunks_next(chunks);

  // don't ack if the last received was an ack
  if(zeros > 1 && (count - chunks->acked) == 1) return NULL;

  chunks->acked = count;
  
  // skip the ack if there's already a chunk waiting
  if(chunks->writeat != chunks->writelen) return chunks;

  // write a zero ack chunk
  if(!(chunks->writing = util_reallocf(chunks->writing, chunks->writelen+1))) return LOG("OOM");
  memset(chunks->writing+chunks->writelen,0,1); // zeros are acks
  chunks->writelen++;

  return chunks;
  
}
Exemplo n.º 6
0
// turn this packet into chunks
util_chunks_t util_chunks_send(util_chunks_t chunks, lob_t out)
{
  uint32_t start, at;
  size_t len;
  uint8_t *raw, size, rounds = 1; // TODO random rounds?
  
  // validate and gc first
  if(!_util_chunks_gc(chunks) || !(len = lob_len(out))) return chunks;
  if(chunks->cloak) len += (8*rounds);

  start = chunks->writelen;
  chunks->writelen += len;
  chunks->writelen += CEIL(len,chunks->space); // include space for per-chunk start byte
  chunks->writelen++; // space for terminating 0
  if(!(chunks->writing = util_reallocf(chunks->writing, chunks->writelen)))
  {
    chunks->writelen = chunks->writeat = 0;
    return LOG("OOM");
  }
  
  raw = lob_raw(out);
  if(chunks->cloak) raw = lob_cloak(out, rounds);
  
  for(at = 0; at < len;)
  {
    size = ((len-at) < chunks->space) ? (uint8_t)(len-at) : chunks->space;
    chunks->writing[start] = size;
    start++;
    memcpy(chunks->writing+start,raw+at,size);
    at += size;
    start += size;
  }
  chunks->writing[start] = 0; // end of chunks, full packet
  
  if(chunks->cloak) free(raw);
  
  return chunks;
}
Exemplo n.º 7
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;
}