Beispiel #1
0
// new incoming block channel, set up handler
lob_t block_on_open(link_t link, lob_t open)
{
  ext_block_t block;
  if(!link) return open;
  if(lob_get_cmp(open,"type","block")) return open;

  if((block = xht_get(link->index, "block")))
  {
    LOG("note: new incoming block channel replacing existing one");
    // TODO delete old channel
  }else{
    LOG("incoming block channel open");

    // create new block
    if(!(block = malloc(sizeof (struct ext_block_struct)))) return LOG("OOM");
    memset(block,0,sizeof (struct ext_block_struct));
    block->link = link;
    // add to list of all blocks
    block->next = xht_get(link->mesh->index, "blocks");
    xht_set(link->mesh->index, "blocks", block);
  }

  // create new channel for this block handler
  block->chan = link_channel(link, open);
  link_handle(link,block->chan,block_chan_handler,block);

  return NULL;
}
Beispiel #2
0
// process a decrypted channel packet
link_t link_receive(link_t link, lob_t inner, pipe_t pipe)
{
  chan_t chan;

  if(!link || !inner) return LOG("bad args");

  // see if existing channel and send there
  if((chan = xht_get(link->index, lob_get(inner,"c"))))
  {
    if(channel3_receive(chan->c3, inner)) return LOG("channel receive error, dropping %s",lob_json(inner));
    link_pipe(link,pipe); // we trust the pipe at this point
    if(chan->handle) chan->handle(link, chan->c3, chan->arg);
    // check if there's any packets to be sent back
    return link_flush(link, chan->c3, NULL);
  }

  // if it's an open, validate and fire event
  if(!lob_get(inner,"type")) return LOG("invalid channel open, no type %s",lob_json(inner));
  if(!exchange3_cid(link->x, inner)) return LOG("invalid channel open id %s",lob_json(inner));
  link_pipe(link,pipe); // we trust the pipe at this point
  inner = mesh_open(link->mesh,link,inner);
  if(inner)
  {
   LOG("unhandled channel open %s",lob_json(inner));
   lob_free(inner);
   return NULL;
  }
  
  return link;
}
Beispiel #3
0
// internal, get or create a pipe
pipe_t tcp4_pipe(net_tcp4_t net, char *ip, int port)
{
  pipe_t pipe;
  pipe_tcp4_t to;
  char id[23];

  snprintf(id,23,"%s:%d",ip,port);
  pipe = xht_get(net->pipes,id);
  if(pipe) return pipe;

  LOG("new pipe to %s",id);

  // create new tcp4 pipe
  if(!(pipe = pipe_new("tcp4"))) return NULL;
  if(!(pipe->arg = to = malloc(sizeof (struct pipe_tcp4_struct)))) return pipe_free(pipe);
  memset(to,0,sizeof (struct pipe_tcp4_struct));
  to->net = net;
  to->sa.sin_family = AF_INET;
  inet_aton(ip, &(to->sa.sin_addr));
  to->sa.sin_port = htons(port);
  if(!(to->chunks = chunks_new(0))) return tcp4_free(pipe);

  // set up pipe
  pipe->id = strdup(id);
  xht_set(net->pipes,pipe->id,pipe);
  pipe->send = tcp4_send;

  return pipe;
}
Beispiel #4
0
// set up internal handler for all incoming packets on this channel
link_t link_handle(link_t link, channel3_t c3, void (*handle)(link_t link, channel3_t c3, void *arg), void *arg)
{
  chan_t chan;
  if(!link || !c3) return LOG("bad args");
  chan = xht_get(link->channels, channel3_uid(c3));
  if(!chan) return LOG("unknown channel %s",channel3_uid(c3));

  chan->handle = handle;
  chan->arg = arg;

  return link;
}
Beispiel #5
0
// get the next incoming block, if any, packet->arg is the link it came from
lob_t ext_block_receive(mesh_t mesh)
{
  ext_block_t block;
  if(!mesh) return LOG("bad args");
  block = xht_get(mesh->index, "blocks");
  for(;block && block->cache; block = block->next)
  {
    // TODO get next block and remove/return it
  }

  return NULL;
}
Beispiel #6
0
pipe_t tcp4_path(link_t link, lob_t path)
{
  net_tcp4_t net;
  char *ip;
  int port;

  // just sanity check the path first
  if(!link || !path) return NULL;
  if(!(net = xht_get(link->mesh->index, MUID))) return NULL;
  if(util_cmp("tcp4",lob_get(path,"type"))) return NULL;
  if(!(ip = lob_get(path,"ip"))) return LOG("missing ip");
  if((port = lob_get_int(path,"port")) <= 0) return LOG("missing port");
  return tcp4_pipe(net, ip, port);
}
Beispiel #7
0
// creates/reuses a single default block channel on the link
link_t ext_block_send(link_t link, lob_t block)
{
  channel3_t chan;
  if(!link || !block) return LOG("bad args");
  
  if(!(chan = xht_get(link->index,"block")))
  {
    // TODO create outgoing channel
    xht_set(link->index,"block",chan);
  }
  
  // break block into packets and send

  return link;
}
Beispiel #8
0
link_t link_get(mesh_t mesh, char *hashname)
{
  link_t link;
  hashname_t id;

  if(!mesh || !hashname) return LOG("invalid args");
  link = xht_get(mesh->index,hashname);
  if(!link)
  {
    id = hashname_str(hashname);
    if(!id) return LOG("invalid hashname %s",hashname);
    link = link_new(mesh,id);
  }

  return link;
}
Beispiel #9
0
pipe_t net_serial_add(net_serial_t net, const char *name, int (*read)(void), int (*write)(uint8_t *buf, size_t len), uint8_t buffer)
{
  pipe_t pipe;
  pipe_serial_t to;

  // just sanity checks
  if(!net || !name || !read || !write) return NULL;

  pipe = xht_get(net->pipes, name);
  if(!pipe)
  {
    if(!(pipe = pipe_new("serial"))) return NULL;
    if(!(pipe->arg = to = malloc(sizeof (struct pipe_serial_struct)))) return pipe_free(pipe);
    memset(to,0,sizeof (struct pipe_serial_struct));
    to->net = net;
    if(!(to->chunks = util_chunks_new(buffer)))
    {
      free(to);
      return pipe_free(pipe);
    }

    // set up pipe
    pipe->id = strdup(name);
    xht_set(net->pipes,pipe->id,pipe);
    pipe->send = serial_send;
    
  }else{
    if(!(to = (pipe_serial_t)pipe->arg)) return NULL;
  }

  // these can be modified
  to->read = read;
  to->write = write;

  return pipe;
}
Beispiel #10
0
net_serial_t net_serial_send(net_serial_t net, const char *name, lob_t packet)
{
  if(!net || !name || !packet) return NULL;
  serial_send(xht_get(net->pipes, name), packet, NULL);
  return net;
}
Beispiel #11
0
thtp_t thtp_get(switch_t s)
{
  thtp_t t;
  t = xht_get(s->index,"thtp");
  return t ? t : thtp_new(s,NULL);
}
Beispiel #12
0
void ext_thtp(chan_t c)
{
  lob_t p, buf, req, match, note;
  char *path;
  thtp_t t = thtp_get(c->s);

  // incoming note as an answer
  if((note = chan_notes(c)))
  {
    DEBUG_PRINTF("got note resp %.*s",note->json_len,note->json);
    thtp_send(c,lob_linked(note));
    lob_free(note);
    return;
  }

  while((p = chan_pop(c)))
  {
    if(!c->arg)
    {
      c->arg = buf = p;
    }else{
      buf = c->arg;
      lob_append(buf,p->body,p->body_len);
      lob_free(p);
    }
    // for now we're processing whole-requests-at-once, to do streaming we can try parsing note->body for the headers anytime
    if(c->ended) continue;

    // parse the payload
    p = lob_parse(buf->body,buf->body_len);

    // this is a response, send it
    if((note = lob_unlink(buf)))
    {
      lob_free(buf);
      if(p)
      {
        DEBUG_PRINTF("got response %.*s for %.*s",p->json_len,p->json,note->json_len,note->json);        
      }
      lob_link(note,p);
      lob_set_str(note,"thtp","resp");
      chan_reply(c,note);
      chan_end(c,NULL);
      return;
    }

    // this is an incoming request
    lob_free(buf);
    if(!p) return (void)chan_fail(c,"422");
    req = p;

    DEBUG_PRINTF("thtp req packet %.*s", req->json_len, req->json);
    path = lob_get_str(req,"path");
    match = xht_get(t->index,path);
    if(!match) match = _thtp_glob(t,path);
    if(!match)
    {
      chan_fail(c,"404");
      lob_free(req);
      return;
    }

    // built in response
    if(lob_linked(match))
    {
      thtp_send(c,lob_linked(match));
      lob_free(req);
      return;
    }
    
    // attach and route request to a new note
    note = lob_copy(match);
    lob_link(note,req);
    lob_set_str(note,"thtp","req");
    if(chan_reply(c,note) == 0) return;

    chan_fail(c,"500");
    lob_free(req);
  }
  
  // optionally sends ack if needed
  chan_ack(c);
}