shithub: musw

Download patch

ref: 615575f7dca0e43ecb23c4ab1ea7fd2e93c4e3b4
parent: dfb8bd8c95a5ff8633214f483f358d24071a7d8a
author: rodri <rgl@antares-labs.eu>
date: Thu Jul 22 23:38:18 EDT 2021

implemented a lobby for users waiting to join a party.
brought the pack/unpack procedures from ssh(1).

--- a/dat.h
+++ b/dat.h
@@ -2,7 +2,8 @@
 
 typedef struct GameState GameState;
 typedef struct Derivative Derivative;
-typedef struct Conn Conn;
+typedef struct Seats Seats;
+typedef struct Lobby Lobby;
 
 struct GameState
 {
@@ -14,9 +15,18 @@
 	double dx, dv;
 };
 
-struct Conn
+struct Seats
 {
 	int *fds;
-	ulong off;
+	ulong len;
 	ulong cap;
+};
+
+struct Lobby
+{
+	Seats seats;
+
+	int (*takeseat)(Lobby*, int);
+	int (*getcouple)(Lobby*, int*);
+	int (*leaveseat)(Lobby*, ulong);
 };
--- a/fns.h
+++ b/fns.h
@@ -1,5 +1,5 @@
 /*
- *	alloc
+ * alloc
  */
 void *emalloc(ulong);
 void *erealloc(void*, ulong);
@@ -6,11 +6,23 @@
 //Image *eallocimage(Display*, Rectangle, ulong, int, ulong);
 
 /*
- *	physics
+ * physics
  */
 void integrate(GameState*, double, double);
 
 /*
- *	nanosec
+ * nanosec
  */
 uvlong nanosec(void);
+
+/*
+ * pack
+ */
+int pack(uchar*, int, char*, ...);
+int unpack(uchar*, int, char*, ...);
+
+/*
+ * lobby
+ */
+Lobby *newlobby(void);
+void dellobby(Lobby*);
--- /dev/null
+++ b/lobby.c
@@ -1,0 +1,62 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "fns.h"
+
+static int
+lobby_takeseat(Lobby *l, int fd)
+{
+	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));
+	}
+
+	l->seats.fds[l->seats.len] = fd;
+	return l->seats.len++;
+}
+
+static int
+lobby_getcouple(Lobby *l, int *fds)
+{
+	if(l->seats.len >= 2){
+		fds[0] = l->seats.fds[l->seats.len-2];
+		fds[1] = l->seats.fds[l->seats.len-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));
+
+		l->seats.len -= 2;
+		return 0;
+	}
+	return -1;
+}
+
+static int
+lobby_leaveseat(Lobby *l, ulong idx)
+{
+	if(idx < l->seats.cap-1)
+		memmove(&l->seats.fds[idx], &l->seats.fds[idx+1], l->seats.cap*sizeof(int) - (l->seats.len + 1)*sizeof(int));
+	l->seats.len--;
+	return 0;
+}
+
+Lobby *
+newlobby(void)
+{
+	Lobby *l;
+
+	l = emalloc(sizeof(Lobby));
+	memset(l, 0, sizeof(*l));
+	l->takeseat = lobby_takeseat;
+	l->getcouple = lobby_getcouple;
+	l->leaveseat = lobby_leaveseat;
+
+	return l;
+}
+
+void
+dellobby(Lobby *l)
+{
+	free(l->seats.fds);
+	free(l);
+}
--- a/mkfile
+++ b/mkfile
@@ -9,6 +9,8 @@
 	alloc.$O\
 	physics.$O\
 	nanosec.$O\
+	pack.$O\
+	lobby.$O\
 
 HFILES=\
 	dat.h\
--- a/muswd.c
+++ b/muswd.c
@@ -9,8 +9,9 @@
 GameState state;
 double t, Δt;
 
-Conn conns;
+Lobby *lobby;
 
+
 static long
 _iolisten(va_list *arg)
 {
@@ -54,15 +55,11 @@
 			continue;
 		}
 
-		if(conns.off >= conns.cap){
-			conns.cap += 8;
-			conns.fds = erealloc(conns.fds, conns.cap*sizeof(*conns.fds));
-		}
-		conns.fds[conns.off++] = dfd;
+		lobby->takeseat(lobby, dfd);
 
 		if(debug)
-			fprint(2, "added conn %d for %lud conns at %lud max\n",
-				dfd, conns.off, conns.cap);
+			fprint(2, "added conn for %lud conns at %lud max\n",
+				lobby->seats.len, lobby->seats.cap);
 	}
 }
 
@@ -95,16 +92,16 @@
 		then = now;
 		timeacc += frametime/1e9;
 
-		for(i = 0; i < conns.off; i++)
-			if(fprint(conns.fds[i], "state: x=%g v=%g\n", state.x, state.v) < 0){
-				fprint(2, "client #%d hanged up\n", i+1);
-				if(conns.off < conns.cap-1)
-					memmove(&conns.fds[conns.off], &conns.fds[conns.off+1], conns.cap-conns.off - 1);
-				conns.off--;
+		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);
 
+				lobby->leaveseat(lobby, i);
+
 				if(debug)
 					fprint(2, "removed conn %d for %lud conns at %lud max\n",
-						i, conns.off, conns.cap);
+						i, lobby->seats.len, lobby->seats.cap);
 
 				i--;
 			}
@@ -146,8 +143,7 @@
 	if(acfd < 0)
 		sysfatal("announce: %r");
 
-	conns.fds = emalloc(2*sizeof(*conns.fds));
-	conns.cap = 2;
+	lobby = newlobby();
 
 	threadcreate(threadlisten, adir, 4096);
 	threadcreate(threadsim, nil, 4096);
--- /dev/null
+++ b/pack.c
@@ -1,0 +1,143 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "fns.h"
+
+/*
+ * these routines were taken directly from ssh(1).
+ * they serve as a reference.
+ */
+
+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;
+
+	for(;;){
+		switch(c = *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;
+			*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:
+	return -1;
+}
+
+static int
+vunpack(uchar *p, int n, char *fmt, va_list a)
+{
+	uchar *p0 = p, *e = p+n;
+	u32int u;
+//	mpint *m;
+	void *s;
+
+	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;
+			break;
+		}
+	}
+err:
+	return -1;
+}
+
+int
+pack(uchar *p, int n, char *fmt, ...)
+{
+	va_list a;
+
+	va_start(a, fmt);
+	n = vpack(p, n, fmt, a);
+	va_end(a);
+
+	return n;
+}
+
+int
+unpack(uchar *p, int n, char *fmt, ...)
+{
+	va_list a;
+
+	va_start(a, fmt);
+	n = vunpack(p, n, fmt, a);
+	va_end(a);
+
+	return n;
+}