shithub: neoventi

Download patch

ref: 8a603a071dc58deb4ab66b76572c5a82767fa8db
parent: dbb6fc6e19e87ac2e212637c1061d3af619d4f94
author: Noam Preil <noam@pixelhero.dev>
date: Fri Dec 22 01:16:23 EST 2023

modularize

--- a/main.c
+++ b/main.c
@@ -2,166 +2,15 @@
 #include <libc.h>
 #include <bio.h>
 
-#include "whack.h"
+#include "neoventi.h"
 
-#define	U8GET(p)	((p)[0])
-#define	U16GET(p)	(((p)[0]<<8)|(p)[1])
-#define	U32GET(p)	((u32int)(((p)[0]<<24)|((p)[1]<<16)|((p)[2]<<8)|(p)[3]))
-#define	U64GET(p)	(((u64int)U32GET(p)<<32)|(u64int)U32GET((p)+4))
-#define MACHINE "kaladin"
-
-typedef enum {
-	VtRerror	= 1,
-	VtTping		= 2,
-	VtRping,
-	VtThello	= 4,
-	VtRhello,
-	VtTgoodbye	= 6,
-	VtRgoodbye,	/* not used */
-	VtTauth0	= 8,
-	VtRauth0,
-	VtTauth1	= 10,
-	VtRauth1,
-	VtTread		= 12,
-	VtRread,
-	VtTwrite	= 14,
-	VtRwrite,
-	VtTsync		= 16,
-	VtRsync,
-	VtTmax
-} VtTag;
-
-enum {
-	/* blank space at beginning of partition - useful for config
-	 * or for when you accidentally {mount /dev/.../arenas /mnt/venti} */
-	PartBlank = 256 * 1024,
-	NameSize = 64,
-	/* FIXME make arena part head a full block? breaking change for new arena partitions, removes
-	 * need for special casing and magic around it. Just read the damn block. */
-	HeadSize = 512,
-	ArenaPartMagic = 0xa9e4a5e7U,
-	ISectMagic = 0xd15c5ec7U,
-	IBucketSize		= 6,
-	IEntrySize		= 38,
-	MaxAMap = 31*1024,
-	ClumpInfoSize = 25,
-	ABlockLog = 9, /* All reads are of 512 byte sectors??? Yikes. We should probably use a larger size, FIXME. */
-};
-
-typedef struct {
-	int fd;
-} VtConn;
-
-typedef struct {
-	char name[NameSize];
-	u32int clumpmagic;
-	u32int clumpmax;
-	u32int blocksize;
-	u32int version;
-	u32int ctime, wtime;
-
-	/* disk info */
-	u64int size;
-	u64int base;
-	int fd;
-	struct {
-		u32int clumps;
-	} memstats;
-} VtArena;
-
-typedef struct {
-	int		blocklog;		/* log2(blocksize) */
-	int		buckmax;		/* max. entries in a index bucket */
-	u32int		tabbase;		/* base address of index config table on disk */
-	u32int		tabsize;		/* max. bytes in index config */
-
-	u32int		version;
-	u32int		bucketmagic;
-	char		name[NameSize];	/* text label */
-	char		index[NameSize];	/* index owning the section */
-	u32int		blocksize;		/* size of hash buckets in index */
-	u32int		blockbase;		/* address of start of on disk index table */
-	u32int		blocks;			/* total blocks on disk; some may be unused */
-	u32int		start;			/* first bucket in this section */
-	u32int		stop;			/* limit of buckets in this section */
-	int fd;
-} VtISect;
-
-typedef struct {
-	char name[NameSize];
-	u64int start, stop;
-} MapEntry;
-
-struct {
-	u32int blocksize;
-	u32int buckets;
-	VtISect *sects;
-	int nsects;
-	u32int div;
-	u32int namap;
-	MapEntry *amap;
-} index;
-
 VtArena *arenas = nil;
 u32int numarenas = 0;
 
-int
-stru64int(char *s, u64int *r)
-{
-	char *t;
-	u64int n, nn, m;
-	int c;
-
-	m = ((u64int)~(u64int)0) / 10;
-	n = 0;
-	for(t = s; ; t++){
-		c = *t;
-		if(c < '0' || c > '9')
-			break;
-		if(n > m)
-			return -1;
-		nn = n * 10 + c - '0';
-		if(nn < n)
-			return -1;
-		n = nn;
-	}
-	*r = n;
-	return s != t && *t == '\0';
-}
-
-int
-u64log2(u64int v)
-{
-	for(int i = 0; i < 64; i++)
-		if((v >> i) <= 1)
-			return i;
-	return -1;
-}
-
-int
-stru32int(char *s, u32int *r)
-{
-	u64int tmp;
-	if(stru64int(s, &tmp) < 0)
-		return -1;
-	if(tmp & 0xFFFFFFFF00000000)
-		return -1;
-	*r = (u32int)(tmp & 0xFFFFFFFF);
-	return 0;
-}
-
-static int
-Brdu32(Biobufhdr *bio, u32int *u32)
-{
-	char *line = Brdline(bio, '\n');
-	if(line == nil)
-		return 0;
-	return stru32int(line, u32) == 0;
-}
-
 void
 parseargs(int argc, char **argv)
 {
+	USED(argv);
 	if(argc != 1)
 		sysfatal("TODO arg parsing");
 }
@@ -193,6 +42,22 @@
 	return 1;
 }
 
+static int
+partopen(char *path, u64int *size)
+{
+	Dir *dir;
+	int fd;
+	fd = open(path, OREAD);
+	if(fd < 0)
+		return fd;
+	dir = dirfstat(fd);
+	if(dir == nil || dir->length == 0)
+		sysfatal("cannot determine size of partition '%s'", path);
+	*size = dir->length;
+	free(dir);
+	return fd;
+}
+
 static u64int
 partlen(int fd, char *path)
 {
@@ -489,7 +354,7 @@
 	return 0;
 }
 
-static int
+int
 vtreadlookup(u8int *score, VtArena *arena, u64int *addr, u16int *size, u8int *blocks)
 {
 	u8int *buf;
@@ -551,7 +416,7 @@
 	}
 }
 
-static int
+int
 readclump(uchar *dst, VtArena arena, u64int addr, u8int blocks)
 {
 	uchar *buf = malloc(blocks << ABlockLog);
@@ -593,75 +458,12 @@
 		sysfatal("failed to write data");
 }
 
-static int
-vtconnhandle(VtConn conn, char *buf)
-{
-	switch(buf[2]){
-	case VtTread:
-		vtread(conn, buf);
-		return 1;
-	case VtTgoodbye:
-		return 0;
-	case VtTsync:
-		print("we don't support vtsync yet. Hanging up!\n");
-		return 0;
-	default:
-		sysfatal("TODO safely hang up vtconns");
-	}
-	return 0;
-}
-
-static void
-handle(int ctl, char *dir)
-{
-	char buf[0x10002];
-	VtConn conn;
-	conn.fd = accept(ctl, dir);
-	if(conn.fd < 0)
-		sysfatal("failed to accept connection: %r");
-	print("received a connection at %s, fd %d\n", dir, conn.fd);
-	vtversion(conn);
-	if(!vtrecv(conn, buf))
-		sysfatal("msg recv failed: %r");
-	if(buf[2] != VtThello)
-		sysfatal("received message before hello: %d", buf[2]);
-	if(buf[4] != 0 || buf[5] != 2 || buf[6] != '0' || buf[7] != '2')
-		sysfatal("unsupported protocol version requested in Thello: %d %d %d %d", buf[4], buf[5], buf[6], buf[7]);
-	buf[2] = VtRhello;
-	buf[6] = 'n';
-	buf[7] = 'o';
-	buf[1] = 8;
-	if(write(conn.fd, buf, 10) != 10)
-		sysfatal("failed to rhello: %r");
-	while(vtrecv(conn, buf)){
-		if(!vtconnhandle(conn, buf))
-			break;
-	}
-	close(conn.fd);
-}
-
-static void
-serve(void)
-{
-	char adir[NETPATHLEN], dir[NETPATHLEN];
-	int fd, ctl;
-	fd = announce("tcp!127.1!14011", adir);
-	if(fd < 0)
-		sysfatal("%r");
-	procsetname("neoventi/server");
-	for(ctl = listen(adir, dir); ctl >= 0; ctl = listen(adir, dir)){
-		handle(ctl, dir);
-		close(ctl);
-	}
-	fprint(2, "server has died\n");
-}
-
 void
 main(int argc, char **argv)
 {
 	parseargs(argc, argv);
-	print("Initializing neoventi build 1...\n");
+	print("Initializing neoventi build 2...\n");
 	init();
 	validate();
-	serve();
+	serve("tcp!127.1!14011");
 }
--- a/mkfile
+++ b/mkfile
@@ -2,7 +2,7 @@
 
 TARG=neoventi
 BIN=/$objtype/bin
-OFILES=main.$O unwhack.$O
+OFILES=main.$O unwhack.$O server.$O util.$O
 
 HFILES=\
 
--- /dev/null
+++ b/neoventi.h
@@ -1,0 +1,124 @@
+#define	U8GET(p)	((p)[0])
+#define	U16GET(p)	(((p)[0]<<8)|(p)[1])
+#define	U32GET(p)	((u32int)(((p)[0]<<24)|((p)[1]<<16)|((p)[2]<<8)|(p)[3]))
+#define	U64GET(p)	(((u64int)U32GET(p)<<32)|(u64int)U32GET((p)+4))
+#define MACHINE "kaladin"
+
+enum {
+	VtRerror = 1,
+	VtTping,
+	VtRping,
+	VtThello,
+	VtRhello,
+	VtTgoodbye,
+	VtRgoodbye,
+	VtTauth0,
+	VtRauth0,
+	VtTauth1,
+	VtRauth1,
+	VtTread,
+	VtRread,
+	VtTwrite,
+	VtRwrite,
+	VtTsync,
+	VtRsync,
+	VtTmax,
+};
+
+enum {
+	/* blank space at beginning of partition - useful for config
+	 * or for when you accidentally {mount /dev/.../arenas /mnt/venti} */
+	PartBlank = 256 * 1024,
+	NameSize = 64,
+	/* FIXME make arena part head a full block? breaking change for new arena partitions, removes
+	 * need for special casing and magic around it. Just read the damn block. */
+	HeadSize = 512,
+	ArenaPartMagic = 0xa9e4a5e7U,
+	ISectMagic = 0xd15c5ec7U,
+	IBucketSize		= 6,
+	IEntrySize		= 38,
+	MaxAMap = 31*1024,
+	ClumpInfoSize = 25,
+	ABlockLog = 9, /* All reads are of 512 byte sectors??? Yikes. We should probably use a larger size, FIXME. */
+};
+
+typedef struct {
+	int fd;
+} VtConn;
+
+typedef struct {
+	char name[NameSize];
+	u32int clumpmagic;
+	u32int clumpmax;
+	u32int blocksize;
+	u32int version;
+	u32int ctime, wtime;
+
+	/* disk info */
+	u64int size;
+	u64int base;
+	int fd;
+	struct {
+		u32int clumps;
+	} memstats;
+} VtArena;
+
+typedef struct {
+	int		blocklog;		/* log2(blocksize) */
+	int		buckmax;		/* max. entries in a index bucket */
+	u32int		tabbase;		/* base address of index config table on disk */
+	u32int		tabsize;		/* max. bytes in index config */
+
+	u32int		version;
+	u32int		bucketmagic;
+	char		name[NameSize];	/* text label */
+	char		index[NameSize];	/* index owning the section */
+	u32int		blocksize;		/* size of hash buckets in index */
+	u32int		blockbase;		/* address of start of on disk index table */
+	u32int		blocks;			/* total blocks on disk; some may be unused */
+	u32int		start;			/* first bucket in this section */
+	u32int		stop;			/* limit of buckets in this section */
+	int fd;
+} VtISect;
+
+typedef struct {
+	char name[NameSize];
+	u64int start, stop;
+} MapEntry;
+
+struct {
+	u32int blocksize;
+	u32int buckets;
+	VtISect *sects;
+	int nsects;
+	u32int div;
+	u32int namap;
+	MapEntry *amap;
+} index;
+
+enum
+{
+	WhackStats	= 8,
+	WhackMaxOff	= 16*1024,	/* max allowed offset */
+
+	HashLog		= 14,
+	HashSize	= 1<<HashLog,
+	HashMask	= HashSize - 1,
+
+	MinMatch	= 3,		/* shortest match possible */
+
+	MinDecode	= 8,		/* minimum bits to decode a match or lit; >= 8 */
+
+	MaxSeqMask	= 8,		/* number of bits in coding block mask */
+	MaxSeqStart	= 256		/* max offset of initial coding block */
+}; 
+
+int	unwhack(uchar *dst, u16int dsize, uchar *src, u16int ssize);
+void serve(char *addr);
+int readclump(uchar *dst, VtArena arena, u64int addr, u8int blocks);
+/* Looks up a score in the index */
+int vtreadlookup(u8int *score, VtArena *arena, u64int *addr, u16int *size, u8int *blocks);
+int Brdu32(Biobufhdr *bio, u32int *u32);
+int stru32int(char *s, u32int *r);
+int stru64int(char *s, u64int *r);
+int u64log2(u64int v);
--- /dev/null
+++ b/server.c
@@ -1,0 +1,122 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "neoventi.h"
+
+// Convenience function: reads a venti packed from conn into buf
+// Invariant: buf MUST have 0x10002 bytes available! see venti(6)
+static int
+vtrecv(VtConn conn, char *buf)
+{
+	u16int len;
+	if(read(conn.fd, buf, 2) != 2){
+		werrstr("Failed to read message size: %r");
+		return 0;
+	}
+	len = (buf[0] << 8 | buf[1]);
+	if(read(conn.fd, buf + 2, len) != len){
+		werrstr("Failed to read message: %r");
+		return 0;
+	}
+	return 1;
+}
+
+static void
+vtversion(VtConn conn)
+{
+	char c;
+	if(fprint(conn.fd, "venti-02-neoventi\n") == 18)
+		while(read(conn.fd, &c, 1) == 1)
+			if(c == '\n')
+				return;
+	fprint(conn.fd, "FUCK OFF\n");
+	close(conn.fd);
+	sysfatal("venti handshake failed: %r");
+}
+
+static void
+vtread(VtConn conn, char *buf)
+{
+	u8int *score;
+	VtArena arena;
+	u64int addr;
+	u16int size;
+	u32int off;
+	u8int blocks;
+	uchar *dbuf;
+	score = (u8int*)buf + 4;
+	if(!vtreadlookup(score, &arena, &addr, &size, &blocks))
+		sysfatal("todo graceful read errors");
+	// Response: VtRread, msg tag, data
+	dbuf = malloc(4 + size);
+	dbuf[0] = (size+2)>>8;
+	dbuf[1] = (size+2) & 0xFF;
+	dbuf[2] = VtRread;
+	dbuf[3] = buf[3];
+	readclump(dbuf+4, arena, addr, blocks);
+	if(write(conn.fd, dbuf, size + 4) != size+4)
+		sysfatal("failed to write data");
+}
+
+static int
+vtconnhandle(VtConn conn, char *buf)
+{
+	switch(buf[2]){
+	case VtTread:
+		vtread(conn, buf);
+		return 1;
+	case VtTgoodbye:
+		return 0;
+	case VtTsync:
+		print("we don't support vtsync yet. Hanging up!\n");
+		return 0;
+	default:
+		sysfatal("TODO safely hang up vtconns");
+	}
+	return 0;
+}
+
+static void
+handle(int ctl, char *dir)
+{
+	char buf[0x10002];
+	VtConn conn;
+	conn.fd = accept(ctl, dir);
+	if(conn.fd < 0)
+		sysfatal("failed to accept connection: %r");
+	print("received a connection at %s, fd %d\n", dir, conn.fd);
+	vtversion(conn);
+	if(!vtrecv(conn, buf))
+		sysfatal("msg recv failed: %r");
+	if(buf[2] != VtThello)
+		sysfatal("received message before hello: %d", buf[2]);
+	if(buf[4] != 0 || buf[5] != 2 || buf[6] != '0' || buf[7] != '2')
+		sysfatal("unsupported protocol version requested in Thello: %d %d %d %d", buf[4], buf[5], buf[6], buf[7]);
+	buf[2] = VtRhello;
+	buf[6] = 'n';
+	buf[7] = 'o';
+	buf[1] = 8;
+	if(write(conn.fd, buf, 10) != 10)
+		sysfatal("failed to rhello: %r");
+	while(vtrecv(conn, buf)){
+		if(!vtconnhandle(conn, buf))
+			break;
+	}
+	close(conn.fd);
+}
+
+void
+serve(char *addr)
+{
+	char adir[NETPATHLEN], dir[NETPATHLEN];
+	int fd, ctl;
+	fd = announce(addr, adir);
+	if(fd < 0)
+		sysfatal("%r");
+	procsetname("neoventi/server");
+	for(ctl = listen(adir, dir); ctl >= 0; ctl = listen(adir, dir)){
+		handle(ctl, dir);
+		close(ctl);
+	}
+	fprint(2, "server has died\n");
+}
\ No newline at end of file
--- /dev/null
+++ b/util.c
@@ -1,0 +1,58 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "neoventi.h"
+
+int
+stru64int(char *s, u64int *r)
+{
+	char *t;
+	u64int n, nn, m;
+	int c;
+
+	m = ((u64int)~(u64int)0) / 10;
+	n = 0;
+	for(t = s; ; t++){
+		c = *t;
+		if(c < '0' || c > '9')
+			break;
+		if(n > m)
+			return -1;
+		nn = n * 10 + c - '0';
+		if(nn < n)
+			return -1;
+		n = nn;
+	}
+	*r = n;
+	return s != t && *t == '\0';
+}
+
+int
+u64log2(u64int v)
+{
+	for(int i = 0; i < 64; i++)
+		if((v >> i) <= 1)
+			return i;
+	return -1;
+}
+
+int
+stru32int(char *s, u32int *r)
+{
+	u64int tmp;
+	if(stru64int(s, &tmp) < 0)
+		return -1;
+	if(tmp & 0xFFFFFFFF00000000)
+		return -1;
+	*r = (u32int)(tmp & 0xFFFFFFFF);
+	return 0;
+}
+
+int
+Brdu32(Biobufhdr *bio, u32int *u32)
+{
+	char *line = Brdline(bio, '\n');
+	if(line == nil)
+		return 0;
+	return stru32int(line, u32) == 0;
+}