shithub: musw

Download patch

ref: bdaa63a1a4604ada3539aeb50e4af144da3ba6f0
parent: f54a8666413d80db3bda3de6e17f795faf7790eb
author: rodri <rgl@antares-labs.eu>
date: Sun Jul 25 16:59:58 EDT 2021

implemented parties to hold PvP match info.
started serializing game state through the wire.
made some major changes to the Lobby struct, plus the ability to check the health of every connection.
added some more debug statements, did some cleanup and put more checks.

--- a/dat.h
+++ b/dat.h
@@ -2,8 +2,10 @@
 
 typedef struct GameState GameState;
 typedef struct Derivative Derivative;
-typedef struct Seats Seats;
+typedef struct Conn Conn;
+typedef struct Player Player;
 typedef struct Lobby Lobby;
+typedef struct Party Party;
 
 struct GameState
 {
@@ -15,18 +17,35 @@
 	double dx, dv;
 };
 
-struct Seats
+struct Conn
 {
-	int *fds;
-	ulong len;
-	ulong cap;
+	char dir[40];
+	int ctl;
+	int data;
 };
 
+struct Player
+{
+	char *name;
+	Conn conn;
+};
+
 struct Lobby
 {
-	Seats seats;
+	Player *seats;
+	ulong nseats;
+	ulong cap;
 
-	int (*takeseat)(Lobby*, int);
-	int (*getcouple)(Lobby*, int*);
+	int (*takeseat)(Lobby*, char*, int, int);
 	int (*leaveseat)(Lobby*, ulong);
+	int (*getcouple)(Lobby*, Player*);
+	void (*healthcheck)(Lobby*);
 };
+
+struct Party
+{
+	Player players[2];	/* the needle and the wedge */
+	Party *prev, *next;
+};
+
+extern Party theparty;
--- a/fns.h
+++ b/fns.h
@@ -26,3 +26,12 @@
  */
 Lobby *newlobby(void);
 void dellobby(Lobby*);
+
+/*
+ * lobby
+ */
+void inittheparty(void);
+Party *newparty(Player[2]);
+void delparty(Party*);
+void addparty(Party*);
+
--- a/lobby.c
+++ b/lobby.c
@@ -4,40 +4,75 @@
 #include "fns.h"
 
 static int
-lobby_takeseat(Lobby *l, int fd)
+lobby_takeseat(Lobby *l, char *dir, int cfd, int dfd)
 {
-	if(l->seats.len >= l->seats.cap){
-		l->seats.cap += 8;
-		l->seats.fds = erealloc(l->seats.fds, l->seats.cap*sizeof(*l->seats.fds));
+	if(l->nseats >= l->cap){
+		l->cap += 8;
+		l->seats = erealloc(l->seats, l->cap*sizeof(*l->seats));
 	}
 
-	l->seats.fds[l->seats.len] = fd;
-	return l->seats.len++;
+	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_getcouple(Lobby *l, int *fds)
+lobby_leaveseat(Lobby *l, ulong idx)
 {
-	if(l->seats.len >= 2){
-		fds[0] = l->seats.fds[l->seats.len-2];
-		fds[1] = l->seats.fds[l->seats.len-1];
+	if(idx >= l->cap)
+		return -1;
 
-		if(l->seats.len < l->seats.cap-2)
-			memmove(&l->seats.fds[l->seats.len], &l->seats.fds[l->seats.len+2], l->seats.cap*sizeof(int) - (l->seats.len + 2)*sizeof(int));
+	if(idx < l->cap - 1)
+		memmove(&l->seats[idx], &l->seats[idx+1], l->cap*sizeof(*l->seats) - (idx + 1)*sizeof(*l->seats));
 
-		l->seats.len -= 2;
+	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 int
-lobby_leaveseat(Lobby *l, ulong idx)
+static void
+lobby_healthcheck(Lobby *l)
 {
-	if(idx < l->seats.cap-1)
-		memmove(&l->seats.fds[idx], &l->seats.fds[idx+1], l->seats.cap*sizeof(int) - (idx + 1)*sizeof(int));
-	l->seats.len--;
-	return 0;
+	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 *
@@ -50,6 +85,7 @@
 	l->takeseat = lobby_takeseat;
 	l->getcouple = lobby_getcouple;
 	l->leaveseat = lobby_leaveseat;
+	l->healthcheck = lobby_healthcheck;
 
 	return l;
 }
@@ -57,6 +93,6 @@
 void
 dellobby(Lobby *l)
 {
-	free(l->seats.fds);
+	free(l->seats);
 	free(l);
 }
--- a/mkfile
+++ b/mkfile
@@ -11,6 +11,7 @@
 	nanosec.$O\
 	pack.$O\
 	lobby.$O\
+	party.$O\
 
 HFILES=\
 	dat.h\
--- a/musw.c
+++ b/musw.c
@@ -4,19 +4,26 @@
 #include "dat.h"
 #include "fns.h"
 
+int debug;
+
+
 void
 threadnetin(void *arg)
 {
-	char buf[256];
+	uchar buf[256];
 	int fd, n;
+	double x, v;
 	Ioproc *io;
 
 	fd = *((int*)arg);
 	io = ioproc();
 
-	while((n = ioread(io, fd, buf, sizeof buf)) > 0)
+	while((n = ioread(io, fd, buf, sizeof buf)) > 0){
+		unpack(buf, n, "dd", &x, &v);
+		n = snprint((char *)buf, sizeof buf, "state: x=%g v=%g\n", x, v);
 		if(iowrite(io, 1, buf, n) != n)
-			fprint(2, "netin iowrite: %r\n");
+			fprint(2, "iowrite: %r\n");
+	}
 	closeioproc(io);
 }
 
@@ -32,7 +39,7 @@
 
 	while((n = ioread(io, 0, buf, sizeof buf)) > 0)
 		if(iowrite(io, fd, buf, n) != n)
-			fprint(2, "netout iowrite: %r\n");
+			fprint(2, "iowrite: %r\n");
 	closeioproc(io);
 }
 
@@ -50,6 +57,9 @@
 	int fd;
 
 	ARGBEGIN{
+	case 'd':
+		debug++;
+		break;
 	default:
 		usage();
 	}ARGEND;
--- a/muswd.c
+++ b/muswd.c
@@ -55,15 +55,36 @@
 			continue;
 		}
 
-		lobby->takeseat(lobby, dfd);
+		lobby->takeseat(lobby, ldir, lcfd, dfd);
 
 		if(debug)
 			fprint(2, "added conn for %lud conns at %lud max\n",
-				lobby->seats.len, lobby->seats.cap);
+				lobby->nseats, lobby->cap);
 	}
 }
 
 void
+broadcaststate(void)
+{
+	int i, n;
+	uchar buf[256];
+	Party *p;
+
+	if(debug)
+		fprint(2, "state: x=%g v=%g\n", state.x, state.v);
+
+	for(p = theparty.next; p != &theparty; p = p->next)
+		for(i = 0; i < nelem(p->players); i++){
+			n = pack(buf, sizeof buf, "dd", state.x, state.v);
+			if(write(p->players[i].conn.data, buf, n) != n){
+				lobby->takeseat(lobby, p->players[i^1].conn.dir, p->players[i^1].conn.ctl, p->players[i^1].conn.data);
+				delparty(p);
+			}
+		}
+
+}
+
+void
 resetsim(void)
 {
 	t = 0;
@@ -74,10 +95,10 @@
 void
 threadsim(void *)
 {
-	int i;
 	uvlong then, now;
 	double frametime, timeacc;
 	Ioproc *io;
+	Player couple[2];
 
 	Δt = 0.01;
 	then = nanosec();
@@ -87,25 +108,31 @@
 	resetsim();
 
 	for(;;){
-		now = nanosec();
-		frametime = now - then;
-		then = now;
-		timeacc += frametime/1e9;
+		lobby->healthcheck(lobby);
 
-		for(i = 0; i < lobby->seats.len; i++)
-			if(fprint(lobby->seats.fds[i], "state: x=%g v=%g\n", state.x, state.v) < 0){
-				if(debug)
-					fprint(2, "client #%d hanged up\n", i+1);
+		if(debug){
+			Party *p;
+			ulong nparties = 0;
 
-				lobby->leaveseat(lobby, i);
+			for(p = theparty.next; p != &theparty; p = p->next)
+				nparties++;
 
-				if(debug)
-					fprint(2, "removed conn %d for %lud conns at %lud max\n",
-						i, lobby->seats.len, lobby->seats.cap);
+			fprint(2, "lobby status: %lud conns at %lud cap\n",
+				lobby->nseats, lobby->cap);
+			fprint(2, "party status: %lud parties going on\n",
+				nparties);
+		}
 
-				i--;
-			}
+		if(lobby->getcouple(lobby, couple) != -1)
+			newparty(couple);
 
+		broadcaststate();
+
+		now = nanosec();
+		frametime = now - then;
+		then = now;
+		timeacc += frametime/1e9;
+
 		while(timeacc >= Δt){
 			integrate(&state, t, Δt);
 			timeacc -= Δt;
@@ -119,7 +146,7 @@
 void
 usage(void)
 {
-	fprint(2, "usage: %s [-d]\n", argv0);
+	fprint(2, "usage: %s [-d] [-a addr]\n", argv0);
 	threadexitsall("usage");
 }
 
@@ -127,9 +154,13 @@
 threadmain(int argc, char *argv[])
 {
 	int acfd;
-	char adir[40];
+	char adir[40], *addr;
 
+	addr = "udp!*!112";
 	ARGBEGIN{
+	case 'a':
+		addr = EARGF(usage());
+		break;
 	case 'd':
 		debug++;
 		break;
@@ -139,11 +170,15 @@
 	if(argc != 0)
 		usage();
 
-	acfd = announce("tcp!*!112", adir);
+	acfd = announce(addr, adir);
 	if(acfd < 0)
 		sysfatal("announce: %r");
 
+	if(debug)
+		fprint(2, "listening on %s\n", addr);
+
 	lobby = newlobby();
+	inittheparty();
 
 	threadcreate(threadlisten, adir, 4096);
 	threadcreate(threadsim, nil, 4096);
--- a/pack.c
+++ b/pack.c
@@ -3,59 +3,38 @@
 #include "dat.h"
 #include "fns.h"
 
-/*
- * these routines were taken directly from ssh(1).
- * they serve as a reference.
- */
+static ulong
+get4(uchar *p)
+{
+	return p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3];
+}
 
+static void
+put4(uchar *p, ulong u)
+{
+	p[0] = u>>24, p[1] = u>>16, p[2] = u>>8, p[3] = u;
+}
+
 static int
 vpack(uchar *p, int n, char *fmt, va_list a)
 {
 	uchar *p0 = p, *e = p+n;
-	u32int u;
-//	mpint *m;
-	void *s;
-	int c;
+	FPdbleword d;
 
 	for(;;){
-		switch(c = *fmt++){
+		switch(*fmt++){
 		case '\0':
 			return p - p0;
-		case '_':
-			if(++p > e) goto err;
+		case 'd':
+			d.x = va_arg(a, double);
+
+			if(p+8 > e)
+				goto err;
+
+			put4(p, d.hi), p += 4;
+			put4(p, d.lo), p += 4;
+
 			break;
-		case '.':
-			*va_arg(a, void**) = p;
-			break;
-		case 'b':
-			if(p >= e) goto err;
-			*p++ = va_arg(a, int);
-			break;
-		case 'm':
-//			m = va_arg(a, mpint*);
-//			u = (mpsignif(m)+8)/8;
-			if(p+4 > e) goto err;
-//			PUT4(p, u), p += 4;
-			if(u > e-p) goto err;
-//			mptober(m, p, u), p += u;
-			break;
-		case '[':
-		case 's':
-			s = va_arg(a, void*);
-			u = va_arg(a, int);
-			if(c == 's'){
-				if(p+4 > e) goto err;
-//				PUT4(p, u), p += 4;
-			}
-			if(u > e-p) goto err;
-			memmove(p, s, u);
-			p += u;
-			break;
-		case 'u':
-			u = va_arg(a, int);
-			if(p+4 > e) goto err;
-//			PUT4(p, u), p += 4;
-			break;
 		}
 	}
 err:
@@ -66,51 +45,20 @@
 vunpack(uchar *p, int n, char *fmt, va_list a)
 {
 	uchar *p0 = p, *e = p+n;
-	u32int u;
-//	mpint *m;
-	void *s;
+	FPdbleword d;
 
 	for(;;){
 		switch(*fmt++){
 		case '\0':
 			return p - p0;
-		case '_':
-			if(++p > e) goto err;
-			break;
-		case '.':
-			*va_arg(a, void**) = p;
-			break;
-		case 'b':
-			if(p >= e) goto err;
-			*va_arg(a, int*) = *p++;
-			break;
-		case 'm':
-			if(p+4 > e) goto err;
-//			u = GET4(p), p += 4;
-			if(u > e-p) goto err;
-//			m = va_arg(a, mpint*);
-//			betomp(p, u, m), p += u;
-			break;
-		case 's':
-			if(p+4 > e) goto err;
-//			u = GET4(p), p += 4;
-			if(u > e-p) goto err;
-			*va_arg(a, void**) = p;
-			*va_arg(a, int*) = u;
-			p += u;
-			break;
-		case '[':
-			s = va_arg(a, void*);
-			u = va_arg(a, int);
-			if(u > e-p) goto err;
-			memmove(s, p, u);
-			p += u;
-			break;
-		case 'u':
-			if(p+4 > e) goto err;
-//			u = GET4(p);
-			*va_arg(a, int*) = u;
-			p += 4;
+		case 'd':
+			if(p+8 > e)
+				goto err;
+
+			d.hi = get4(p), p += 4;
+			d.lo = get4(p), p += 4;
+			*va_arg(a, double*) = d.x;
+
 			break;
 		}
 	}
--- /dev/null
+++ b/party.c
@@ -1,0 +1,44 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "fns.h"
+
+Party theparty;
+
+
+void
+inittheparty(void)
+{
+	theparty.next = theparty.prev = &theparty;
+}
+
+Party *
+newparty(Player *players)
+{
+	Party *p;
+
+	p = emalloc(sizeof(Party));
+	p->players[0] = players[0];
+	p->players[1] = players[1];
+
+	addparty(p);
+
+	return p;
+}
+
+void
+delparty(Party *p)
+{
+	p->next->prev = p->prev;
+	p->prev->next = p->next;
+	free(p);
+}
+
+void
+addparty(Party *p)
+{
+	p->prev = theparty.prev;
+	p->next = &theparty;
+	theparty.prev->next = p;
+	theparty.prev = p;
+}