ref: e8ed35d914bdf4445a4e915ca361f6eb26bbd611
parent: a734ef4f09cf5c4b7851b17f88f2970607ee25b2
author: Noam Preil <noam@pixelhero.dev>
date: Sun Dec 24 12:05:53 EST 2023
hand errors to client
--- a/neoventi.h
+++ b/neoventi.h
@@ -108,10 +108,12 @@
MinMatch = 3, /* shortest match possible */
- MinDecode = 8, /* minimum bits to decode a match or lit; >= 8 */
+ 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 */
+ MaxSeqMask = 8, /* number of bits in coding block mask */
+ MaxSeqStart = 256, /* max offset of initial coding block */
+
+ MaxPacketSize = 0x10008, /* largest possible protocol message */
};
int unwhack(uchar *dst, u16int dsize, uchar *src, u16int ssize);
--- a/server.c
+++ b/server.c
@@ -3,34 +3,55 @@
#include <bio.h>
#include "neoventi.h"
+
// 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, ...)
{
+ u16int len;
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
+ len = strlen(msg);
+ tbuf[2] = VtRerror;
+ tbuf[4] = len >> 8;
+ tbuf[5] = len & 0xFF;
+ memcpy(tbuf + 6, msg, len);
+ len += 4;
+ tbuf[0] = len >> 8;
+ tbuf[1] = len & 0xFF;
+ if(write(conn.fd, tbuf, len+2) != len+2)
+ fprint(2, "failed to report error: %r");
}
+ free(msg);
longjmp(conn.bounce, 1);
}
+static void
+vthangup(VtConn conn)
+{
+ longjmp(conn.bounce, 2);
+}
+
// Convenience function: reads a venti packet from conn into buf
-// Invariant: buf MUST have 0x10002 bytes available! see venti(6)
static void
vtrecv(VtConn conn, char *buf)
{
u16int len;
- 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)
- vterr(conn, nil, "failed to read message: %r");
+ switch(read(conn.fd, buf, 2)){
+ case 0:
+ vthangup(conn);
+ case 1:
+ vterr(conn, nil, "received a single byte for message size");
+ case 2:
+ len = (buf[0] << 8 | buf[1]);
+ if(read(conn.fd, buf + 2, len) != len)
+ vterr(conn, nil, "failed to read message: %r");
+ }
}
static void
@@ -55,19 +76,16 @@
u64int addr;
u16int size;
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");
+ buf[0] = (size+2)>>8;
+ buf[1] = (size+2) & 0xFF;
+ buf[2] = VtRread;
+ readclump((uchar*)buf+4, arena, addr, blocks);
+ if(write(conn.fd, buf, size + 4) != size+4)
+ vterr(conn, buf, "failed to write data");
}
static int
@@ -78,7 +96,7 @@
vtread(conn, buf);
return 1;
case VtTgoodbye:
- return 0;
+ vthangup(conn);
case VtTsync:
vterr(conn, buf, "TODO: sync not supported yet");
default:
@@ -107,12 +125,19 @@
static void
handle(int ctl, char *dir)
{
- char buf[0x10002];
+ char buf[MaxPacketSize];
VtConn conn;
- if(setjmp(conn.bounce) != 0){
+ switch(setjmp(conn.bounce)){
+ case 0:
+ break;
+ case 1:
fprint(2, "abandoning client: %r\n");
+ case 2:
close(conn.fd);
return;
+ default:
+ fprint(2, "internal error: unexpected bounce code\n");
+ break;
}
conn.fd = accept(ctl, dir);
if(conn.fd < 0)
@@ -120,7 +145,10 @@
vthello(conn, buf);
while(1){
vtrecv(conn, buf);
- vtconnhandle(conn, buf);
+ if(!vtconnhandle(conn, buf)){
+ close(conn.fd);
+ return;
+ }
}
}
@@ -139,4 +167,4 @@
close(ctl);
}
fprint(2, "server has died\n");
-}
\ No newline at end of file
+}