shithub: musw

Download patch

ref: c1cdf0f980b92193953f05bf444b7c78f369a122
parent: e769c8684c1200f922ff41c6ef5d0cdd4fe0e67f
author: rodri <rgl@antares-labs.eu>
date: Thu Feb 9 16:01:00 EST 2023

implemented a packet processing pipeline. got rid of Lobby. began development of a network protocol.

--- a/dat.h
+++ b/dat.h
@@ -22,7 +22,24 @@
 };
 
 enum {
-	Framehdrsize	= 4+4+4+2,
+	NChi	= 10,	/* C wants to connect */
+	NShi,		/* S accepts */
+	NCdhx0	= 12,	/* C asks for p and g */
+	NSdhx0,		/* S sends them. it's not a negotiation */
+	NCdhx1	= 14,	/* C shares pubkey */
+	NSdhx1,		/* S shares pubkey */
+	NCnudge	= 16,
+	NSnudge,	/* check the pulse of the line */
+
+	NCinput	= 20,	/* C sends player input state */
+	NSsimstate,	/* S sends current simulation state */
+
+	NCbuhbye	= 30,
+	NSbuhbye
+};
+
+enum {
+	Framehdrsize	= 1+4+4+2,
 	MTU		= 1024
 };
 
@@ -36,10 +53,8 @@
 typedef struct Derivative Derivative;
 
 typedef struct Frame Frame;
-typedef struct Conn Conn;
-typedef struct PInput PInput;
+typedef struct NetConn NetConn;
 typedef struct Player Player;
-typedef struct Lobby Lobby;
 typedef struct Party Party;
 
 /*
@@ -118,44 +133,25 @@
 
 struct Frame
 {
-	Udphdr *udp;
-	uint seq;
-	uint ack;
-	uint id;
-	ushort len;
+	Udphdr udp;
+	u8int type;
+	u32int seq;
+	u32int ack;
+	u16int len;
 	uchar data[];
 };
 
-struct Conn
+struct NetConn
 {
-	char dir[40];
-	int ctl;
-	int data;
-	int status;
+	Udphdr udp;
+	int isconnected;
 };
 
-struct PInput
-{
-	ulong kdown;
-};
-
 struct Player
 {
 	char *name;
-	Conn conn;
-	PInput oldinput, input;
-};
-
-struct Lobby
-{
-	Player *seats;
-	ulong nseats;
-	ulong cap;
-
-	int (*takeseat)(Lobby*, char*, int, int);
-	int (*leaveseat)(Lobby*, ulong);
-	int (*getcouple)(Lobby*, Player*);
-	void (*purge)(Lobby*);
+	NetConn conn;
+	ulong okdown, kdown;
 };
 
 struct Party
--- a/fns.h
+++ b/fns.h
@@ -24,12 +24,6 @@
 int unpack(uchar*, int, char*, ...);
 
 /*
- * lobby
- */
-Lobby *newlobby(void);
-void dellobby(Lobby*);
-
-/*
  * party
  */
 Party *newparty(Party*, Player[2]);
--- a/lobby.c
+++ /dev/null
@@ -1,101 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <ip.h>
-#include <draw.h>
-#include <geometry.h>
-#include "dat.h"
-#include "fns.h"
-
-static int
-lobby_takeseat(Lobby *l, char *dir, int cfd, int dfd)
-{
-	if(l->nseats >= l->cap){
-		l->cap += 8;
-		l->seats = erealloc(l->seats, l->cap*sizeof(*l->seats));
-	}
-
-	l->seats[l->nseats].name = nil;
-	memmove(l->seats[l->nseats].conn.dir, dir, sizeof l->seats[l->nseats].conn.dir);
-	l->seats[l->nseats].conn.ctl = cfd;
-	l->seats[l->nseats].conn.data = dfd;
-
-	return l->nseats++;
-}
-
-static int
-lobby_leaveseat(Lobby *l, ulong idx)
-{
-	if(idx >= l->cap)
-		return -1;
-
-	if(idx < l->cap - 1)
-		memmove(&l->seats[idx], &l->seats[idx+1], l->cap*sizeof(*l->seats) - (idx + 1)*sizeof(*l->seats));
-
-	return --l->nseats;
-}
-
-static int
-lobby_getcouple(Lobby *l, Player *couple)
-{
-	if(l->nseats >= 2){
-		couple[0] = l->seats[l->nseats-2];
-		couple[1] = l->seats[l->nseats-1];
-
-		if(l->nseats < l->cap - 2)
-			memmove(&l->seats[l->nseats], &l->seats[l->nseats+2], l->cap*sizeof(*l->seats) - (l->nseats + 2)*sizeof(*l->seats));
-
-		l->nseats -= 2;
-
-		return 0;
-	}
-
-	return -1;
-}
-
-static void
-lobby_purge(Lobby *l)
-{
-	char status[48], buf[16];
-	int i, fd;
-
-	for(i = 0; i < l->nseats; i++){
-		snprint(status, sizeof status, "%s/status", l->seats[i].conn.dir);
-
-		fd = open(status, OREAD);
-		if(fd < 0)
-			goto cleanup;
-
-		if(read(fd, buf, sizeof buf) > 0)
-			if(strncmp(buf, "Close", 5) == 0)
-				goto cleanup;
-			else{
-				close(fd);
-				continue;
-			}
-cleanup:
-		close(fd);
-		l->leaveseat(l, i);
-	}
-}
-
-Lobby *
-newlobby(void)
-{
-	Lobby *l;
-
-	l = emalloc(sizeof(Lobby));
-	memset(l, 0, sizeof(Lobby));
-	l->takeseat = lobby_takeseat;
-	l->getcouple = lobby_getcouple;
-	l->leaveseat = lobby_leaveseat;
-	l->purge = lobby_purge;
-
-	return l;
-}
-
-void
-dellobby(Lobby *l)
-{
-	free(l->seats);
-	free(l);
-}
--- a/mkfile
+++ b/mkfile
@@ -11,7 +11,6 @@
 	physics.$O\
 	nanosec.$O\
 	pack.$O\
-	lobby.$O\
 	party.$O\
 	universe.$O\
 	sprite.$O\
--- a/musw.c
+++ b/musw.c
@@ -35,7 +35,8 @@
 Universe *universe;
 VModel *needlemdl, *wedgemdl;
 Image *skymap;
-Channel *kchan;
+Channel *ingress;
+Channel *egress;
 char winspec[32];
 int debug;
 
@@ -143,6 +144,20 @@
 }
 
 void
+sendkeys(ulong kdown)
+{
+	Frame *frame;
+
+	frame = emalloc(sizeof(Frame)+sizeof(kdown));
+	frame->type = NCinput;
+	frame->seq = 0;
+	frame->ack = 0;
+	frame->len = sizeof(kdown);
+	pack(frame->data, frame->len, "k", kdown);
+	sendp(egress, frame);
+}
+
+void
 kbdproc(void *)
 {
 	Rune r;
@@ -188,10 +203,9 @@
 		}
 
 		if(debug)
-			fprint(2, "kdown %.*lub\n",
-				sizeof(kdown)*8, kdown);
+			fprint(2, "kdown %.*lub\n", sizeof(kdown)*8, kdown);
 
-		nbsendul(kchan, kdown);
+		sendkeys(kdown);
 	}
 }
 
@@ -198,46 +212,59 @@
 void
 threadnetrecv(void *arg)
 {
-	uchar buf[1024];
+	uchar buf[MTU];
 	int fd, n;
 	Ioproc *io;
+	Frame *frame;
 
+	threadsetname("threadnetrecv");
+
 	fd = *(int*)arg;
 	io = ioproc();
 
 	while((n = ioread(io, fd, buf, sizeof buf)) > 0){
-		unpack(buf, n, "PdPdP",
-			&universe->ships[0].p, &universe->ships[0].θ,
-			&universe->ships[1].p, &universe->ships[1].θ,
-			&universe->star.p);
+		frame = emalloc(sizeof(Frame)+(n-Framehdrsize));
+		unpack(buf, n, "f", frame);
+		sendp(ingress, frame);
 	}
 	closeioproc(io);
 }
 
 void
+threadnetppu(void *)
+{
+	Frame *frame;
+
+	threadsetname("threadnetppu");
+
+	while((frame = recvp(ingress)) != nil){
+		switch(frame->type){
+		case NSsimstate:
+			unpack(frame->data, frame->len, "PdPdP",
+				&universe->ships[0].p, &universe->ships[0].θ,
+				&universe->ships[1].p, &universe->ships[1].θ,
+				&universe->star.p);
+			break;
+		}
+
+		free(frame);
+	}
+}
+
+void
 threadnetsend(void *arg)
 {
 	uchar buf[MTU];
 	int fd, n;
-	ulong kdown;
 	Frame *frame;
 
+	threadsetname("threadnetsend");
+
 	fd = *(int*)arg;
-	frame = emalloc(sizeof(Frame)+sizeof(kdown));
-	frame->udp = nil;
-	frame->seq = ntruerand(1000)>>1;
-	frame->ack = 0;
-	frame->id = truerand();
-	frame->len = sizeof(kdown);
 
-	for(;;){
-		kdown = recvul(kchan);
-
-		frame->seq++;
-
-		pack(frame->data, frame->len, "k", kdown);
-
-		n = pack(buf, sizeof buf, "F", frame);
+	while((frame = recvp(egress)) != nil){
+		n = pack(buf, sizeof buf, "f", frame);
+		free(frame);
 		if(write(fd, buf, n) != n)
 			sysfatal("write: %r");
 	}
@@ -273,7 +300,7 @@
 	skymap = readimage(display, fd, 1);
 	if(skymap == nil){
 darkness:
-		fprint(2, "couldn't read a sky map. falling back to darkness...\n");
+		fprint(2, "couldn't read the sky map. falling back to darkness...\n");
 		skymap = display->black;
 	}
 	close(fd);
@@ -364,7 +391,6 @@
 	screenrf.bx = Vec2(1, 0);
 	screenrf.by = Vec2(0,-1);
 
-	kchan = chancreate(sizeof kdown, 1);
 	proccreate(kbdproc, nil, 4096);
 
 	/* TODO: draw a CONNECTING... sign */
@@ -386,9 +412,11 @@
 
 	initskymap();
 
-	threadcreate(threadnetrecv, &fd, 4096);
-	threadcreate(threadnetsend, &fd, 4096);
-	threadcreate(threadresize, mc, 4096);
+	ingress = chancreate(sizeof(Frame*), 8);
+	egress = chancreate(sizeof(Frame*), 8);
+	threadcreate(threadnetrecv, &fd, mainstacksize);
+	threadcreate(threadnetsend, &fd, mainstacksize);
+	threadcreate(threadresize, mc, mainstacksize);
 
 	then = nanosec();
 	io = ioproc();
--- a/muswd.c
+++ b/muswd.c
@@ -8,66 +8,99 @@
 #include "fns.h"
 
 int debug;
+int mainstacksize = 24*1024;
 
-Lobby *lobby;
 Party theparty;
+Channel *ingress;
+Channel *egress;
 
 
 void
-threadlisten(void *arg)
+threadnetrecv(void *arg)
 {
-	uchar buf[MTU], *p, *e;
+	uchar buf[MTU];
 	int fd, n;
-	ushort rport, lport;
-	ulong kdown;
 	Ioproc *io;
 	Frame *frame;
 
+	threadsetname("threadnetrecv");
+
 	fd = *(int*)arg;
 	io = ioproc();
-	frame = emalloc(sizeof(Frame));
 
 	while((n = ioread(io, fd, buf, sizeof buf)) > 0){
-		p = buf;
-		e = buf+n;
+		frame = emalloc(sizeof(Frame)+(n-Udphdrsize-Framehdrsize));
+		unpack(buf, n, "F", frame);
+		sendp(ingress, frame);
+	}
+	closeioproc(io);
+}
 
-		unpack(p, e-p, "F", frame);
+void
+threadnetppu(void *)
+{
+	ushort rport, lport;
+	ulong kdown;
+	Frame *frame;
 
-		rport = frame->udp->rport[0]<<8 | frame->udp->rport[1];
-		lport = frame->udp->lport[0]<<8 | frame->udp->lport[1];
-		
-		unpack(frame->data, frame->len, "k", &kdown);
+	threadsetname("threadnetppu");
 
-		if(debug)
-			fprint(2, "%I!%d → %I!%d | %d (%d) rcvd seq %ud ack %ud id %ud len %ud %.*lub\n",
-				frame->udp->raddr, rport, frame->udp->laddr, lport, threadid(), getpid(), frame->seq, frame->ack, frame->id, frame->len, sizeof(kdown)*8, kdown);
+	while((frame = recvp(ingress)) != nil){
+		rport = frame->udp.rport[0]<<8 | frame->udp.rport[1];
+		lport = frame->udp.lport[0]<<8 | frame->udp.lport[1];
+
+		switch(frame->type){
+		case NCinput:
+			unpack(frame->data, frame->len, "k", &kdown);
+
+			if(debug){
+				fprint(2, "%I!%d ← %I!%d | rcvd type %ud seq %ud ack %ud len %ud %.*lub\n",
+					frame->udp.laddr, lport, frame->udp.raddr, rport,
+					frame->type, frame->seq, frame->ack, frame->len,
+					sizeof(kdown)*8, kdown);
+			}
+			break;
+		}
+
+		free(frame);
 	}
-	closeioproc(io);
 }
 
 void
+threadnetsend(void *arg)
+{
+	uchar buf[MTU];
+	int fd, n;
+	Frame *frame;
+
+	threadsetname("threadnetsend");
+
+	fd = *(int*)arg;
+
+	while((frame = recvp(egress)) != nil){
+		n = pack(buf, sizeof buf, "F", frame);
+		free(frame);
+		if(write(fd, buf, n) != n)
+			sysfatal("write: %r");
+	}
+}
+
+void
 broadcaststate(void)
 {
-	int i, n;
-	uchar buf[1024];
-	Player *player;
+	int i;
+	Frame *frame;
+//	Player *player;
 	Party *p;
 
 	for(p = theparty.next; p != &theparty; p = p->next){
-		n = pack(buf, sizeof buf, "PdPdP",
+		frame = emalloc(sizeof(Frame)+2*(3*8+8)+3*8);
+		pack(frame->data, frame->len, "PdPdP",
 			p->u->ships[0].p, p->u->ships[0].θ,
 			p->u->ships[1].p, p->u->ships[1].θ,
 			p->u->star.p);
 
 		for(i = 0; i < nelem(p->players); i++){
-			if(write(p->players[i].conn.data, buf, n) != n){
-				player = &p->players[i^1];
-				lobby->takeseat(lobby, player->conn.dir, player->conn.ctl, player->conn.data);
-				/* step back and delete the spoiled party */
-				p = p->prev;
-				delparty(p->next);
-				break;
-			}
 		}
 	}
 
@@ -79,7 +112,7 @@
 	uvlong then, now;
 	double frametime, Δt;
 	Ioproc *io;
-	Player couple[2];
+//	Player couple[2];
 	Party *p;
 
 	Δt = 0.01;
@@ -87,13 +120,11 @@
 	io = ioproc();
 
 	for(;;){
-		lobby->purge(lobby);
+//		if(lobby->getcouple(lobby, couple) != -1){
+//			newparty(&theparty, couple);
+//			theparty.prev->u->reset(theparty.prev->u);
+//		}
 
-		if(lobby->getcouple(lobby, couple) != -1){
-			newparty(&theparty, couple);
-			theparty.prev->u->reset(theparty.prev->u);
-		}
-
 		now = nanosec();
 		frametime = now - then;
 		then = now;
@@ -123,13 +154,13 @@
 	for(p = theparty.next; p != &theparty; p = p->next)
 		nparties++;
 
-	fprint(fd, "curplayers	%lud\n"
-		   "totplayers	%lud\n"
-		   "maxplayers	%lud\n"
-		   "curparties	%lud\n"
-		   "totparties	%lud\n",
-		lobby->nseats, (ulong)0, lobby->cap,
-		nparties, (ulong)0);
+//	fprint(fd, "curplayers	%lud\n"
+//		   "totplayers	%lud\n"
+//		   "maxplayers	%lud\n"
+//		   "curparties	%lud\n"
+//		   "totparties	%lud\n",
+//		lobby->nseats, 0UL, lobby->cap,
+//		nparties, 0UL);
 }
 
 void
@@ -232,11 +263,14 @@
 	if(debug)
 		fprint(2, "listening on %s\n", addr);
 
-	lobby = newlobby();
 	initparty(&theparty);
 
-	threadcreate(threadC2, nil, 4096);
-	threadcreate(threadlisten, &adfd, 4096);
-	threadcreate(threadsim, nil, 4096);
+	ingress = chancreate(sizeof(Frame*), 32);
+	egress = chancreate(sizeof(Frame*), 32);
+	threadcreate(threadC2, nil, mainstacksize);
+	threadcreate(threadnetrecv, &adfd, mainstacksize);
+	threadcreate(threadnetppu, nil, mainstacksize);
+	threadcreate(threadnetsend, &adfd, mainstacksize);
+	threadcreate(threadsim, nil, mainstacksize);
 	threadexits(nil);
 }
--- a/pack.c
+++ b/pack.c
@@ -1,5 +1,6 @@
 #include <u.h>
 #include <libc.h>
+#include <pool.h>
 #include <ip.h>
 #include <draw.h>
 #include <geometry.h>
@@ -37,7 +38,7 @@
 	ulong k;
 	FPdbleword d;
 	Point2 P;
-	Frame *F;
+	Frame *F = nil;
 
 	for(;;){
 		switch(*fmt++){
@@ -74,13 +75,25 @@
 		case 'F':
 			F = va_arg(a, Frame*);
 
+			if(p+Udphdrsize > e)
+				goto err;
+
+			memmove(p, &F->udp, Udphdrsize), p += Udphdrsize;
+			/* fallthrough */
+		case 'f':
+			if(F == nil)
+				F = va_arg(a, Frame*);
+
 			if(p+Framehdrsize+F->len > e)
 				goto err;
 
+			*p++ = F->type;
 			put4(p, F->seq), p += 4;
 			put4(p, F->ack), p += 4;
-			put4(p, F->id), p += 4;
 			put2(p, F->len), p += 2;
+
+			if(p+F->len > e)
+				goto err;
 			memmove(p, F->data, F->len), p += F->len;
 
 			break;
@@ -97,7 +110,7 @@
 	ulong k;
 	FPdbleword d;
 	Point2 P;
-	Frame *F;
+	Frame *F = nil;
 
 	for(;;){
 		switch(*fmt++){
@@ -129,24 +142,29 @@
 
 			break;
 		case 'F':
-			if(p+Udphdrsize+Framehdrsize > e)
+			if(p+Udphdrsize > e)
 				goto err;
 
 			F = va_arg(a, Frame*);
 
-			F->udp = (Udphdr*)p, p += Udphdrsize;
+			memmove(&F->udp, p, Udphdrsize), p += Udphdrsize;
+			/* fallthrough */
+		case 'f':
+			if(p+Framehdrsize > e)
+				goto err;
+
+			if(F == nil)
+				F = va_arg(a, Frame*);
+
+			F->type = *p++;
 			F->seq = get4(p), p += 4;
 			F->ack = get4(p), p += 4;
-			F->id = get4(p), p += 4;
 			F->len = get2(p), p += 2;
 
-			/* XXX: I'm not happy with this. */
 			if(p+F->len > e)
 				goto err;
 
-			F = erealloc(F, sizeof(Frame)+F->len);
-			memmove(F->data, p, F->len);
-			p += F->len;
+			memmove(F->data, p, F->len), p += F->len;
 
 			break;
 		}