ref: a734ef4f09cf5c4b7851b17f88f2970607ee25b2
parent: 8a603a071dc58deb4ab66b76572c5a82767fa8db
author: Noam Preil <noam@pixelhero.dev>
date: Sun Dec 24 11:37:59 EST 2023
error handling skeleton
--- a/main.c
+++ b/main.c
@@ -25,7 +25,6 @@
return 0;
if(*nmap > MaxAMap)
return 0;
- print("reading %d map entries\n", *nmap);*map = realloc(*map, *nmap * sizeof(MapEntry));
for(i = 0; i < *nmap; i += 1){s = Brdline(b, '\n');
@@ -37,7 +36,6 @@
sysfatal("corrupt index map: %s", fields[1]);if(stru64int(fields[2], &(*map)[i].stop) < 0)
sysfatal("corrupt index map: %s", fields[2]);- // print("amap entry %d: [%llud, %llud)\n", i, (*map)[i].start, (*map)[i].stop);}
return 1;
}
@@ -116,7 +114,6 @@
if(Bseek(&bio, tabbase, 0) != tabbase)
sysfatal("seek failed: %r");parsemap(&bio, &map, &nmap);
- print("found %d arenas\n", nmap);arenas = realloc(arenas, sizeof(VtArena) * (nmap + numarenas));
if(!arenas)
sysfatal("oom");@@ -232,7 +229,6 @@
sysfatal("invalid magic found in index header");if(!Brdu32(&bio, &version) || version != 1)
sysfatal("failed to read version or version unsupported");- print("Parsing index v1...\n");line = Brdline(&bio, '\n');
if(Blinelen(&bio) >= NameSize)
sysfatal("invalid or corrupt index: name too big");@@ -462,8 +458,9 @@
main(int argc, char **argv)
{parseargs(argc, argv);
- print("Initializing neoventi build 2...\n");+ print("Initializing neoventi build 3... ");init();
validate();
+ print("initialized, launching server.\n"); serve("tcp!127.1!14011");}
--- a/neoventi.h
+++ b/neoventi.h
@@ -30,7 +30,7 @@
* 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
+ /* FIXME(design break) 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,
@@ -44,6 +44,7 @@
typedef struct {int fd;
+ jmp_buf bounce;
} VtConn;
typedef struct {--- a/server.c
+++ b/server.c
@@ -3,22 +3,34 @@
#include <bio.h>
#include "neoventi.h"
-// Convenience function: reads a venti packed from conn into buf
+// Handles an error on `conn` handling client request `tbuf`
+// Only the tag must be preserved in the buffer
+static void
+vterr(VtConn conn, char *tbuf, char *msg, ...)
+{+ va_list args;
+ va_start(args, msg);
+ msg = vsmprint(msg, args);
+ werrstr(msg);
+ free(msg);
+ va_end(args);
+ if(tbuf != nil){+ // TODO: send Rerror message
+ }
+ longjmp(conn.bounce, 1);
+}
+
+// Convenience function: reads a venti packet from conn into buf
// Invariant: buf MUST have 0x10002 bytes available! see venti(6)
-static int
+static void
vtrecv(VtConn conn, char *buf)
{u16int len;
- if(read(conn.fd, buf, 2) != 2){- werrstr("Failed to read message size: %r");- return 0;
- }
+ if(read(conn.fd, buf, 2) != 2)
+ vterr(conn, nil, "failed to read message size: %r");
len = (buf[0] << 8 | buf[1]);
- if(read(conn.fd, buf + 2, len) != len){- werrstr("Failed to read message: %r");- return 0;
- }
- return 1;
+ if(read(conn.fd, buf + 2, len) != len)
+ vterr(conn, nil, "failed to read message: %r");
}
static void
@@ -25,13 +37,14 @@
vtversion(VtConn conn)
{char c;
+ // Response is one line of unknown size; discard bytes until EOL
if(fprint(conn.fd, "venti-02-neoventi\n") == 18)
while(read(conn.fd, &c, 1) == 1)
if(c == '\n')
return;
+ // If the handshake fails, make it clear there's a problem and give up
fprint(conn.fd, "FUCK OFF\n");
- close(conn.fd);
- sysfatal("venti handshake failed: %r");+ vterr(conn, nil, "handshake failed");
}
static void
@@ -41,7 +54,6 @@
VtArena arena;
u64int addr;
u16int size;
- u32int off;
u8int blocks;
uchar *dbuf;
score = (u8int*)buf + 4;
@@ -68,41 +80,48 @@
case VtTgoodbye:
return 0;
case VtTsync:
- print("we don't support vtsync yet. Hanging up!\n");- return 0;
+ vterr(conn, buf, "TODO: sync not supported yet");
default:
- sysfatal("TODO safely hang up vtconns");+ vterr(conn, buf, "TODO safely hang up vtconns");
}
return 0;
}
static void
-handle(int ctl, char *dir)
+vthello(VtConn conn, char *buf)
{- 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");+ vtrecv(conn, buf);
if(buf[2] != VtThello)
- sysfatal("received message before hello: %d", buf[2]);+ vterr(conn, buf, "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]);+ vterr(conn, buf, "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;
+ vterr(conn, buf, "failed to rhello: %r");
+}
+
+static void
+handle(int ctl, char *dir)
+{+ char buf[0x10002];
+ VtConn conn;
+ if(setjmp(conn.bounce) != 0){+ fprint(2, "abandoning client: %r\n");
+ close(conn.fd);
+ return;
}
- close(conn.fd);
+ conn.fd = accept(ctl, dir);
+ if(conn.fd < 0)
+ vterr(conn, nil, "failed to accept connection: %r");
+ vthello(conn, buf);
+ while(1){+ vtrecv(conn, buf);
+ vtconnhandle(conn, buf);
+ }
}
void
@@ -115,6 +134,7 @@
sysfatal("%r"); procsetname("neoventi/server"); for(ctl = listen(adir, dir); ctl >= 0; ctl = listen(adir, dir)){+ // TODO: handle the client in a worker, allow multiple clients
handle(ctl, dir);
close(ctl);
}
--
⑨