Plan 9 from Bell Labs’s /usr/web/sources/contrib/vsrinivas/vtrc.c

Copyright © 2009 Alcatel-Lucent.
Distributed under the Lucent Public License version 1.02.
Download the Plan 9 distribution.


/* 
 * Reconnecting Venti proxy
 *
 * Proxies requests to a remove Venti; if the connection to a remove server 
 * fails, it keeps retrying the request till a connection can be reestablished
 *
 * Usage:
 * 	vtrc -a listenaddress -h hostventi [-v]
 * vtrc listens on listenaddress, proxying connections to hostventi
 *
 * based on Russ Cox's venti/ro.c
 */

#include <u.h>
#include <libc.h>
#include <venti.h>
#include <libsec.h>
#include <avl.h>

#ifndef _UNISTD_H_
#pragma varargck type "F" VtFcall*
#pragma varargck type "T" void
#endif

char *za = nil;
VtConn *z =nil;
int verbose;
QLock vtconnlock;

enum
{
  STACK = 4096
};

/* called with the vtconnlock held */
void try_reconnect(void) {
	if (z != nil)
		vtfreeconn(z);
	z = vtdial(za);
	if (z != nil)
		vtconnect(z);
}

void
usage(void)
{
  fprint(2, "usage: vtrc [-v] [-a address] [-h address]\n");
  exits("usage");
}

void
readthread(void *v)
{
  char err[ERRMAX];
  VtReq *r;
  uchar *buf;
  int n = -1;
	
  r = v;
  buf = vtmalloc(r->tx.count);

  qlock(&vtconnlock); for (;;) {
	n = -1;
	if (z != nil)
		n = vtread(z, r->tx.score, r->tx.blocktype, buf, r->tx.count);

	if (n < 0)
		try_reconnect();
	else
		break;
  } qunlock(&vtconnlock);

  r->rx.data = packetforeign(buf, n, free, buf);

  vtrespond(r);
}

void
writethread(void *v) {
  VtReq *r;
  int n = -1;

  r = v;
	
  packetsha1(r->tx.data, r->rx.score);
  
  qlock(&vtconnlock); for (;;) {
	n = -1;
	if (z != nil)
		n = vtwritepacket(z, r->rx.score, r->tx.blocktype, r->tx.data);

	if (n < 0)
		try_reconnect();
	else
		break;
  } qunlock(&vtconnlock);

  vtrespond(r);
}

VtSrv *srv;

void
coreproc(void *v) {
	VtReq *r1;
	
	while((r1 = vtgetreq(srv)) != nil){
		r1->rx.msgtype = r1->tx.msgtype+1;
		if(verbose)
			fprint(2, "<- %F\n", &r1->tx);
		switch(r1->tx.msgtype){
		case VtTping:
			vtrespond(r1);
			break;
		case VtTgoodbye:
			vtrespond(r1);
			break;
		case VtTread:
			proccreate(readthread, r1, 16384);
			continue;
		case VtTwrite:
			proccreate(writethread, r1, 16384);
			continue;
		case VtTsync:
			vtrespond(r1);
			break;
		}
		if(verbose)
			fprint(2, "-> %F\n", &r1->rx);
	}
}

void
threadmain(int argc, char **argv)
{
	char *address, *ventiaddress;

	fmtinstall('F', vtfcallfmt);
	fmtinstall('V', vtscorefmt);
	
	address = "tcp!*!venti";
	ventiaddress = nil;
	
	ARGBEGIN{
	case 'v':
		verbose++;
		break;
	case 'a':
		address = EARGF(usage());
		break;
	case 'h':
		ventiaddress = EARGF(usage());
		break;
	default:
		usage();
	}ARGEND

	if((z = vtdial(ventiaddress)) == nil)
		sysfatal("vtdial %s: %r", ventiaddress);
	if(vtconnect(z) < 0)
		sysfatal("vtconnect: %r");

	za = ventiaddress;
	if (za == nil)
		sysfatal("no remote address");

	srv = vtlisten(address);
	if(srv == nil)
		sysfatal("vtlisten %s: %r", address);

	print("vtrc: Ice Nine, Baby\n");
	
	rfork(RFNOTEG);
	proccreate(coreproc, nil, 4096*16);

	exits(nil);
}


Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2009 Alcatel-Lucent. All Rights Reserved.
Comments to webmaster@plan9.bell-labs.com.