Plan 9 from Bell Labs’s /usr/web/sources/contrib/rcbilson/s3venti/s3venti.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


/* Copyright (c) 2008 Richard Bilson */
/* Portions copyright (c) 2004 Russ Cox */
#include "stdinc.h"
#include "dat.h"
#include "fns.h"

int verbose;

void
usage(void)
{
	fprint(2, "usage: s3/venti [-v] [-a address] [-b bucket] [-c configfile]\n");
	threadexitsall("usage");
}

static void
dowrite(S3Con *c, VtReq *r)
{
	S3writeblock(c, r);
	if(config.logfd >= 0)
		fprint(config.logfd, "write %V to s3\n", r->rx.score);
}

static Lump*
lcache(VtReq *r)
{
	u32int n;
	Lump *u;

	if(scorecmp(r->tx.score, zeroscore) == 0) {
		r->rx.data = packetalloc();
		return nil;
	}
	u = lookuplump(r->tx.score, r->tx.blocktype);
	if(u->data != nil){
		if(config.logfd >= 0)
			fprint(config.logfd, "read %V found in cache\n", r->tx.score);
		n = packetsize(u->data);
		if(n > r->tx.count){
			r->rx.error = vtstrdup("too big");;
			r->rx.msgtype = VtRerror;
			putlump(u);
		}
		r->rx.data = packetdup(u->data, 0, n);
		putlump(u);
		return nil;
	}
	return u;
}

static void
doread(S3Con *c, VtReq *r)
{
	Lump *u;

	u = lcache(r);
	if(!u)
		return;

	/* call dcache */

	if(config.logfd >= 0)
		fprint(config.logfd, "read %V from s3\n", r->tx.score);
	S3readblock(c, r);
	if(r->rx.msgtype != VtRerror)
		insertlump(u, packetdup(r->rx.data, 0, packetsize(r->rx.data)));
	putlump(u);
}

static void
checkmagic(S3Con *c)
{
	S3Req req;
	S3Resp resp;
	uchar block[AESbsize + magiclen];
	char *err;
	int len;

	memset(&req, 0, sizeof(req));
	req.method = "GET";
	req.resource = smprint("/%U/magic", config.bucket);
	if(err = S3request(c, &req, &resp)) {
		sysfatal("checkmagic request: %s", err);
	}
	if(memcmp(resp.result, "404", 3) == 0) {
		sysfatal("no magic found in %s; not an s3venti arena", config.bucket);
	}
	if(resp.result[0] != '2'){
		err = vtstrdup(resp.result);
		fprint(2, "s3 server returned %s", resp.result);
		S3responsefd(&resp, 2);
		threadexitsall("s3 error");
	}
	len = 0;
	do {
		long n = S3response(&resp, block, AESbsize + magiclen - len);
		if(n <= 0)
			sysfatal("checkmagic: EOF on response");
		len += n;
	} while(len < AESbsize + magiclen);
	
	if(config.key)
		decryptblock(block, magiclen, config.key);

	if(memcmp(block+AESbsize, magic, magiclen) != 0)
		sysfatal("checkmagic failed; bad passphrase?");
}

S3Vconfig config;

void
threadmain(int argc, char **argv)
{
	VtReq *r;
	VtSrv *srv;
	char *configfile, *address, *bucket, *logfile;
	S3Con c;

	fmtinstall('V', vtscorefmt);
	fmtinstall('F', vtfcallfmt);
	fmtinstall('Z', hdatefmt);
	fmtinstall('H', httpfmt);
	fmtinstall('U', hurlfmt);
	fmtinstall('[', encodefmt);
	
	address = nil;
	bucket = nil;
	configfile = "s3venti.conf";
	logfile = nil;

	ARGBEGIN{
	case 'v':
		verbose++;
		break;
	case 'a':
		address = EARGF(usage());
		break;
	case 'b':
		bucket = EARGF(usage());
		break;
	case 'c':
		configfile = EARGF(usage());
		break;
	case 'l':
		logfile = EARGF(usage());
		break;
	default:
		usage();
	}ARGEND

	if(s3vconfig(configfile, &config) < 0)
		sysfatal("can't init server");

	if(bucket)
		config.bucket = bucket;
	if(!config.bucket)
		sysfatal("no bucket specified");

	if(logfile){
		config.logfd = create(logfile, OWRITE|OAPPEND, 600);
		if(config.logfd < 0)
			sysfatal("can't open log file %s for writing", logfile);
	}

	if(!address){
		if(config.vaddr)
			address = config.vaddr;
		else
			address = "tcp!*!venti";
	}

	if(config.mem == 0xffffffffUL)
		config.mem = 1 * 1024 * 1024;
	if(0) fprint(2, "initialize %d bytes of lump cache for %d lumps\n",
		config.mem, config.mem / (8 * 1024));
	initlumpcache(config.mem, config.mem / (8 * 1024));

	chattyS3 = verbose > 1;
	S3open(&c, config.s3host, config.s3port);
	checkmagic(&c);

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

	while((r = vtgetreq(srv)) != nil){
		r->rx.msgtype = r->tx.msgtype+1;
		if(verbose)
			fprint(2, "<- %F\n", &r->tx);
		switch(r->tx.msgtype){
		case VtTping:
			break;
		case VtTgoodbye:
			break;
		case VtTread:
			doread(&c, r);
			break;
		case VtTwrite:
			dowrite(&c, r);
			break;
		case VtTsync:
			break;
		}
		if(verbose)
			fprint(2, "-> %F\n", &r->rx);
		vtrespond(r);
	}

	S3close(&c);

	threadexitsall(nil);
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].