Beispiel #1
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 #2
0
/*
 * This is a tee(1) implementation that works on pipes. It doesn't copy
 * any data, it simply references the 'in' pages on the 'out' pipe.
 * The 'flags' used are the SPLICE_F_* variants, currently the only
 * applicable one is SPLICE_F_NONBLOCK.
 */
static long do_tee(struct file *in, struct file *out, size_t len,
		   unsigned int flags)
{
	struct pipe_inode_info *ipipe = pipe_info(in->f_dentry->d_inode);
	struct pipe_inode_info *opipe = pipe_info(out->f_dentry->d_inode);
	int ret = -EINVAL;

	/*
	 * Duplicate the contents of ipipe to opipe without actually
	 * copying the data.
	 */
	if (ipipe && opipe && ipipe != opipe) {
		/*
		 * Keep going, unless we encounter an error. The ipipe/opipe
		 * ordering doesn't really matter.
		 */
		ret = link_ipipe_prep(ipipe, flags);
		if (!ret) {
			ret = link_opipe_prep(opipe, flags);
			if (!ret) {
				ret = link_pipe(ipipe, opipe, len, flags);
				if (!ret && (flags & SPLICE_F_NONBLOCK))
					ret = -EAGAIN;
			}
		}
	}

	return ret;
}
Beispiel #3
0
link_t mesh_add(mesh_t mesh, lob_t json, pipe_t pipe)
{
  link_t link;
  lob_t keys, paths;
  uint8_t csid;

  if(!mesh || !json) return LOG("bad args");
  LOG("mesh add %s",lob_json(json));
  link = link_get(mesh, hashname_vchar(lob_get(json,"hashname")));
  keys = lob_get_json(json,"keys");
  paths = lob_get_array(json,"paths");
  if(!link) link = link_keys(mesh, keys);
  if(!link) LOG("no hashname");
  
  LOG("loading keys/paths");
  if(keys && (csid = hashname_id(mesh->keys,keys))) link_load(link, csid, keys);

  // handle any pipe/paths
  if(pipe) link_pipe(link, pipe);
  lob_t path;
  for(path=paths;path;path = lob_next(path)) link_path(link,path);
  
  lob_free(keys);
  lob_freeall(paths);

  return link;
}
Beispiel #4
0
// try to turn a path into a pipe
pipe_t link_path(link_t link, lob_t path)
{
  pipe_t pipe;

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

  if(!(pipe = mesh_path(link->mesh, link, path))) return NULL;
  link_pipe(link, pipe);
  return pipe;
}
Beispiel #5
0
int main(int argc, char **argv)
{
  mesh_t meshA = mesh_new(3);
  fail_unless(meshA);
  lob_t secretsA = mesh_generate(meshA);
  fail_unless(secretsA);

  mesh_t meshB = mesh_new(3);
  fail_unless(meshB);
  lob_t secretsB = mesh_generate(meshB);
  fail_unless(secretsB);
  
  net_serial_t netA = net_serial_new(meshA, NULL);
  fail_unless(netA);
  pipe_t pAB = net_serial_add(netA, "sAB", readerA, writerA, 64);
  fail_unless(pAB);

  net_serial_t netB = net_serial_new(meshB, NULL);
  fail_unless(netB);
  pipe_t pBA = net_serial_add(netB, "sBA", readerB, writerB, 64);
  fail_unless(pBA);

  link_t linkAB = link_pipe(link_keys(meshA, meshB->keys), pAB);
  link_t linkBA = link_pipe(link_keys(meshB, meshA->keys), pBA);
  fail_unless(linkAB);
  fail_unless(linkBA);

  link_sync(linkAB);
  // let serial go go go
  int loop;
  for(loop = 2000; loop; loop--)
  {
    net_serial_loop(netB);
    net_serial_loop(netA);
  }

  LOG("BA %d AB %d",e3x_exchange_out(linkBA->x,0),e3x_exchange_out(linkAB->x,0));
  fail_unless(e3x_exchange_out(linkBA->x,0) >= e3x_exchange_out(linkAB->x,0));
  fail_unless(e3x_exchange_out(linkBA->x,0) == e3x_exchange_out(linkAB->x,0));


  return 0;
}
Beispiel #6
0
pipe_t pipe_sync(pipe_t p, uint8_t down)
{
  if(!p) return NULL;
  p->down = down;
  lob_t list, next;
  for(list=p->links;list;list = next)
  {
    next = lob_next(list);
    link_t link = list->arg;
    link_pipe(link, p); // will remove pipe if it's down
  }
  return p;
}
Beispiel #7
0
net_loopback_t net_loopback_new(mesh_t a, mesh_t b)
{
  net_loopback_t pair;

  if(!(pair = malloc(sizeof (struct net_loopback_struct)))) return LOG("OOM");
  memset(pair,0,sizeof (struct net_loopback_struct));
  if(!(pair->pipe = pipe_new("pair")))
  {
    free(pair);
    return LOG("OOM");
  }
  pair->a = a;
  pair->b = b;
  pair->pipe->id = strdup("loopback");
  pair->pipe->arg = pair;
  pair->pipe->send = pair_send;

  // ensure they're linked and piped together
  link_pipe(link_keys(a,b->keys),pair->pipe);
  link_pipe(link_keys(b,a->keys),pair->pipe);

  return pair;
}
Beispiel #8
0
// process an incoming handshake
link_t link_receive_handshake(link_t link, lob_t inner, pipe_t pipe)
{
  link_t ready;
  uint32_t out, err;
  seen_t seen;
  uint8_t csid = 0;
  char *hexid;
  lob_t attached, outer = lob_linked(inner);

  if(!link || !inner || !outer) return LOG("bad args");
  hexid = lob_get(inner, "csid");
  if(!lob_get(link->mesh->keys, hexid)) return LOG("unsupported csid %s",hexid);
  util_unhex(hexid, 2, &csid);
  attached = lob_parse(inner->body, inner->body_len);
  if(!link->key && link_key(link->mesh, attached, csid) != link) return LOG("invalid/mismatch link handshake");
  if((err = e3x_exchange_verify(link->x,outer))) return LOG("handshake verification fail: %d",err);

  out = e3x_exchange_out(link->x,0);
  ready = link_up(link);

  // if bad at, always send current handshake
  if(e3x_exchange_in(link->x, lob_get_uint(inner,"at")) < out)
  {
    LOG("old/bad at: %s (%d,%d,%d)",lob_json(inner),lob_get_int(inner,"at"),e3x_exchange_in(link->x,0),e3x_exchange_out(link->x,0));
    // just reset pipe seen and call link_sync to resend handshake
    for(seen = link->pipes;pipe && seen;seen = seen->next) if(seen->pipe == pipe) seen->at = 0;
    lob_free(link_sync(link));
    return NULL;
  }

  // trust/add this pipe
  if(pipe) link_pipe(link,pipe);

  // try to sync ephemeral key
  if(!e3x_exchange_sync(link->x,outer)) return LOG("sync failed");
  
  // we may need to re-sync
  if(out != e3x_exchange_out(link->x,0)) lob_free(link_sync(link));
  
  // notify of ready state change
  if(!ready && link_up(link))
  {
    LOG("link ready");
    mesh_link(link->mesh, link);
  }
  
  return link;
}
Beispiel #9
0
void proxy_attach(ape_proxy *proxy, char *pipe, int allow_write, acetables *g_ape)
{
	ape_proxy_pipe *to;
	transpipe *gpipe;
	
	if (proxy == NULL || ((gpipe = get_pipe(pipe, g_ape)) == NULL)) {
		return;
	}
	to = xmalloc(sizeof(*to));
	memcpy(to->pipe, gpipe->pubid, strlen(gpipe->pubid)+1);

	to->allow_write = allow_write;
	
	to->next = proxy->to;
	proxy->to = to;
	
	proxy->nlink++;
	
	link_pipe(gpipe, proxy->pipe, proxy_detach);
}
Beispiel #10
0
static void
link_exec_set_io_thread (gpointer data, gboolean immediate)
{
	GError *error = NULL;
	gboolean to_io_thread = TRUE;

	if (link_is_io_in_thread)
		return;

	link_lock ();
	g_mutex_lock (link_cmd_queue_lock);

	link_is_io_in_thread = TRUE;
	
	link_thread_context = g_main_context_new ();
	link_thread_loop = g_main_loop_new (link_thread_context, TRUE);

	link_connections_move_io_T (to_io_thread);
	link_servers_move_io_T     (to_io_thread);

	if (link_pipe (link_wakeup_fds) < 0)
		g_error ("Can't create CORBA main-thread wakeup pipe");

	link_main_source = link_source_create_watch
		(link_thread_context, LINK_WAKEUP_POLL,
		 NULL, (G_IO_IN | G_IO_PRI),
		 link_mainloop_handle_input, NULL);
	
	link_io_thread = g_thread_create_full
		(link_io_thread_fn, NULL, 256 * 1024, TRUE, FALSE,
		 G_THREAD_PRIORITY_NORMAL, &error);
	
	if (!link_io_thread || error)
		g_error ("Failed to create linc worker thread");

	g_main_loop_quit (link_loop);

	g_mutex_unlock (link_cmd_queue_lock);
	link_unlock ();
}
Beispiel #11
0
// process an incoming handshake
link_t link_handshake(link_t link, lob_t inner, lob_t outer, pipe_t pipe)
{
  link_t ready;
  uint32_t out;

  if(!link || !inner || !outer) return LOG("bad args");
  if(!link->key && link_key(link->mesh,inner) != link) return LOG("invalid/mismatch handshake key");
  out = exchange3_out(link->x,0);
  ready = link_ready(link);

  // if bad at, always send current handshake
  if(exchange3_in(link->x, lob_get_int(inner,"at")) < out)
  {
    LOG("old/bad at: %s (%d,%d,%d)",lob_json(inner),lob_get_int(inner,"at"),exchange3_in(link->x,0),exchange3_out(link->x,0));
    if(pipe) pipe->send(pipe,exchange3_handshake(link->x),link);
    return NULL;
  }

  // trust/add this pipe
  if(pipe) link_pipe(link,pipe);

  // try to sync ephemeral key
  if(!exchange3_sync(link->x,outer)) return LOG("sync failed");
  
  // we may need to re-sync
  if(out != exchange3_out(link->x,0)) link_sync(link);
  
  // notify of ready state change
  if(!ready && link_ready(link))
  {
    LOG("link ready");
    mesh_link(link->mesh, link);
  }
  
  return link;
}