// create/track a new channel for this open e3x_channel_t link_channel(link_t link, lob_t open) { chan_t chan; e3x_channel_t c3; if(!link || !open) return LOG("bad args"); // add an outgoing cid if none set if(!lob_get_int(open,"c")) lob_set_uint(open,"c",e3x_exchange_cid(link->x, NULL)); c3 = e3x_channel_new(open); if(!c3) return LOG("invalid open %s",lob_json(open)); LOG("new outgoing channel open: %s",lob_get(open,"type")); // add this channel to the link's channel index if(!(chan = malloc(sizeof (struct chan_struct)))) { e3x_channel_free(c3); return LOG("OOM"); } memset(chan,0,sizeof (struct chan_struct)); chan->c3 = c3; xht_set(link->channels, e3x_channel_uid(c3), chan); xht_set(link->index, e3x_channel_c(c3), chan); return c3; }
// 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")))) { LOG("\t<-- %s",lob_json(inner)); if(e3x_channel_receive(chan->c3, inner)) return LOG("channel receive error, dropping %s",lob_json(inner)); if(pipe) 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(!e3x_exchange_cid(link->x, inner)) return LOG("invalid channel open id %s",lob_json(inner)); if(pipe) 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; }
// encrypt and send this one packet on this pipe link_t link_direct(link_t link, lob_t inner, pipe_t pipe) { if(!link || !inner) return LOG("bad args"); if(!pipe && (!link->pipes || !(pipe = link->pipes->pipe))) return LOG("no network"); // add an outgoing cid if none set if(!lob_get_int(inner,"c")) lob_set_uint(inner,"c",e3x_exchange_cid(link->x, NULL)); pipe->send(pipe, e3x_exchange_send(link->x, inner), link); return link; }
// encrypt and send this one packet on this pipe link_t link_direct(link_t link, lob_t inner) { if(!link || !inner) return LOG("bad args"); if(!link->send_cb) { LOG_WARN("no network, dropping %s",lob_json(inner)); return NULL; } // add an outgoing cid if none set if(!lob_get_int(inner,"c")) lob_set_uint(inner,"c",e3x_exchange_cid(link->x, NULL)); lob_t outer = e3x_exchange_send(link->x, inner); lob_free(inner); return link_send(link, outer); }
// create/track a new channel for this open chan_t link_chan(link_t link, lob_t open) { chan_t c; if(!link || !open) return LOG("bad args"); // add an outgoing cid if none set if(!lob_get_int(open,"c")) lob_set_uint(open,"c",e3x_exchange_cid(link->x, NULL)); c = chan_new(open); if(!c) return LOG("invalid open %s",lob_json(open)); LOG("new outgoing channel %d open: %s",chan_id(c), lob_get(open,"type")); c->link = link; c->next = link->chans; link->chans = c; return c; }
// process a decrypted channel packet link_t link_receive(link_t link, lob_t inner) { chan_t c; if(!link || !inner) return LOG("bad args"); LOG("<-- %d",lob_get_int(inner,"c")); // see if existing channel and send there if((c = link_chan_get(link, lob_get_int(inner,"c")))) { LOG("found chan"); // consume inner chan_receive(c, inner); // process any changes link->chans = link_process_chan(link->chans, 0); return link; } // if it's an open, validate and fire event if(!lob_get(inner,"type")) { LOG("invalid channel open, no type %s",lob_json(inner)); lob_free(inner); return NULL; } if(!e3x_exchange_cid(link->x, inner)) { LOG("invalid channel open id %s",lob_json(inner)); lob_free(inner); return NULL; } inner = mesh_open(link->mesh,link,inner); if(inner) { LOG("unhandled channel open %s",lob_json(inner)); lob_free(inner); return NULL; } return link; }