shithub: musw

Download patch

ref: ecc7d34e9229524a8d4340f0e127f1421029141c
parent: fd5dc301e4a69d7b7c1293aafe5b069b4ff400a4
author: rodri <rgl@antares-labs.eu>
date: Tue Feb 21 17:18:56 EST 2023

take the packet seq and ack into account during connection setup. added a player queue to keep clients around waiting for a party.

--- a/dat.h
+++ b/dat.h
@@ -64,6 +64,7 @@
 typedef struct DHparams DHparams;
 typedef struct NetConn NetConn;
 typedef struct Player Player;
+typedef struct Playerq Playerq;
 typedef struct Party Party;
 
 /*
@@ -98,7 +99,7 @@
 {
 	Point2 p, v;
 	double θ, ω;
-	double mass; /* kg */
+	double mass; /* in kg */
 };
 
 struct Bullet
@@ -172,12 +173,23 @@
 {
 	char *name;
 	NetConn *conn;
-	ulong okdown, kdown;
+	ulong oldkdown, kdown;
+	Player *next;
 };
 
+struct Playerq
+{
+	Player *head, *tail;
+	usize len;
+
+	void (*put)(Playerq*, Player*);
+	Player *(*get)(Playerq*);
+	void (*del)(Playerq*, Player*);
+};
+
 struct Party
 {
-	Player players[2];	/* the needle and the wedge */
+	Player *players[2];	/* the needle and the wedge */
 	Universe *u;
 	Party *prev, *next;
 };
--- a/fns.h
+++ b/fns.h
@@ -26,10 +26,13 @@
 /*
  * party
  */
-Party *newparty(Party*, Player[2]);
+Party *newparty(Party*, Player*, Player*);
 void delparty(Party*);
 void addparty(Party*, Party*);
 void initparty(Party*);
+Player *newplayer(char*, NetConn*);
+void delplayer(Player*);
+void initplayerq(Playerq*);
 
 /*
  * universe
--- a/musw.c
+++ b/musw.c
@@ -151,7 +151,7 @@
 {
 	Frame *frame;
 
-	frame = newframe(nil, NChi, 0, 0, 0, nil);
+	frame = newframe(nil, NChi, ntruerand(1000), 0, 0, nil);
 	sendp(egress, frame);
 	netconn.state = NCSConnecting;
 }
@@ -164,7 +164,7 @@
 	if(netconn.state != NCSConnected)
 		return;
 
-	frame = newframe(nil, NCinput, 0, 0, sizeof(kdown), nil);
+	frame = newframe(nil, NCinput, netconn.lastseq+1, 0, sizeof(kdown), nil);
 	pack(frame->data, frame->len, "k", kdown);
 	signframe(frame, netconn.dh.priv);
 	sendp(egress, frame);
@@ -264,6 +264,10 @@
 
 		switch(netconn.state){
 		case NCSConnecting:
+			if(frame->seq != netconn.lastseq + 1 &&
+			   frame->ack != netconn.lastseq)
+				goto discard;
+
 			switch(frame->type){
 			case NShi:
 				unpack(frame->data, frame->len, "kk", &netconn.dh.p, &netconn.dh.g);
@@ -316,6 +320,9 @@
 			}
 			break;
 		}
+
+		netconn.lastseq = frame->seq;
+		netconn.lastack = frame->ack;
 discard:
 		delframe(frame);
 	}
@@ -345,7 +352,10 @@
 				frame->udp.laddr, lport, frame->udp.raddr, rport, frame);
 		}
 
-		free(frame);
+		netconn.lastseq = frame->seq;
+		netconn.lastack = frame->ack;
+
+		delframe(frame);
 	}
 }
 
@@ -386,6 +396,14 @@
 }
 
 void
+drawconnecting(void)
+{
+	draw(screen, screen->r, display->black, nil, ZP);
+	string(screen, addpt(screen->r.min, Pt(100,300)), display->white, ZP, font, "connecting...");
+	flushimage(display, 1);
+}
+
+void
 redraw(void)
 {
 	lockdisplay(display);
@@ -472,10 +490,10 @@
 	screenrf.bx = Vec2(1, 0);
 	screenrf.by = Vec2(0,-1);
 
-	proccreate(kbdproc, nil, 4096);
+	proccreate(kbdproc, nil, mainstacksize);
 
-	/* TODO: draw a CONNECTING... sign */
-	/* TODO: set up an alarm for n secs and update the sign */
+	/* TODO: implement this properly with screens and iodial(2) */
+	drawconnecting();
 	fd = dial(server, nil, nil, nil);
 	if(fd < 0)
 		sysfatal("dial: %r");
--- a/muswd.c
+++ b/muswd.c
@@ -13,6 +13,7 @@
 int mainstacksize = 24*1024;
 
 Party theparty;
+Playerq players;
 NetConn **conns;
 usize nconns;
 usize maxconns;
@@ -41,6 +42,28 @@
 	return nil;
 }
 
+/* TODO: this is an ugly hack. nc should probably reference the player back */
+void
+dissolveparty(NetConn *nc)
+{
+	int i;
+	Party *p;
+	Player *player;
+
+	for(p = theparty.next; p != &theparty; p = p->next)
+		for(i = 0; i < nelem(p->players); i++)
+			if(p->players[i]->conn == nc){
+				delplayer(p->players[i]);
+				players.put(&players, p->players[i^1]);
+				delparty(p);
+			}
+
+	/* also clean the player queue */
+	for(player = players.head; player != nil; player = player->next)
+		if(player->conn == nc)
+			players.del(&players, player);
+}
+
 int
 popconn(NetConn *nc)
 {
@@ -52,6 +75,8 @@
 		if(*ncp == nc){
 			memmove(ncp, ncp+1, sizeof(NetConn*)*(ncpe-ncp-1));
 			nconns--;
+			dissolveparty(nc); /* TODO: ugly hack. */
+			delnetconn(nc);
 			return 0;
 		}
 	return -1;
@@ -70,11 +95,10 @@
 		elapsed = curts - (*ncp)->lastrecvts;
 		elapsednudge = curts - (*ncp)->lastnudgets;
 
-		if((*ncp)->state == NCSConnected && elapsed > ConnTimeout){
+		if((*ncp)->state == NCSConnected && elapsed > ConnTimeout)
 			popconn(*ncp);
-			delnetconn(*ncp);
-		}else if((*ncp)->state == NCSConnected && elapsednudge > 1000){ /* every second */
-			f = newframe(&(*ncp)->udp, NSnudge, 0, 0, 0, nil);
+		else if((*ncp)->state == NCSConnected && elapsednudge > 1000){ /* every second */
+			f = newframe(&(*ncp)->udp, NSnudge, (*ncp)->lastseq+1, 0, 0, nil);
 			signframe(f, (*ncp)->dh.priv);
 			sendp(egress, f);
 
@@ -143,15 +167,19 @@
 				goto discard;
 		}
 
-		nc->lastrecvts = nanosec()/1e6;
-
 		switch(nc->state){
 		case NCSConnecting:
+			if(frame->seq != nc->lastseq + 1 &&
+			   frame->ack != nc->lastseq)
+				goto discard;
+
 			switch(frame->type){
 			case NCdhx:
 				unpack(frame->data, frame->len, "k", &nc->dh.pub);
 				nc->state = NCSConnected;
 
+				players.put(&players, newplayer(nil, nc));
+
 				if(debug)
 					fprint(2, "\trcvd pubkey %ld\n", nc->dh.pub);
 
@@ -185,11 +213,14 @@
 				break;
 			case NCbuhbye:
 				popconn(nc);
-				delnetconn(nc);
 				break;
 			}
 			break;
 		}
+
+		nc->lastrecvts = nanosec()/1e6;
+		nc->lastseq = frame->seq;
+		nc->lastack = frame->ack;
 discard:
 		delframe(frame);
 	}
@@ -202,6 +233,7 @@
 	int fd, n;
 	ushort rport, lport;
 	Frame *frame;
+	NetConn *nc;
 
 	threadsetname("threadnetsend");
 
@@ -219,7 +251,13 @@
 				frame->udp.laddr, lport, frame->udp.raddr, rport, frame);
 		}
 
-		free(frame);
+		nc = getconn(frame);
+		if(nc != nil){
+			nc->lastseq = frame->seq;
+			nc->lastack = frame->ack;
+		}
+
+		delframe(frame);
 	}
 }
 
@@ -228,19 +266,22 @@
 {
 	int i;
 	Frame *frame;
-//	Player *player;
+	NetConn *pnc;
 	Party *p;
 
-	for(p = theparty.next; p != &theparty; p = p->next){
-		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(p = theparty.next; p != &theparty; p = p->next)
 		for(i = 0; i < nelem(p->players); i++){
+			pnc = p->players[i]->conn;
+
+			frame = newframe(&pnc->udp, NSsimstate, pnc->lastseq+1, 0, 2*(3*8+8)+3*8, nil);
+			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);
+			signframe(frame, pnc->dh.priv);
+
+			sendp(egress, frame);
 		}
-	}
 
 }
 
@@ -250,7 +291,6 @@
 	uvlong then, now;
 	double frametime, Δt;
 	Ioproc *io;
-//	Player couple[2];
 	Party *p;
 
 	Δt = 0.01;
@@ -258,10 +298,8 @@
 	io = ioproc();
 
 	for(;;){
-//		if(lobby->getcouple(lobby, couple) != -1){
-//			newparty(&theparty, couple);
-//			theparty.prev->u->reset(theparty.prev->u);
-//		}
+		if(players.len >= 2)
+			newparty(&theparty, players.get(&players), players.get(&players));
 
 		now = nanosec();
 		frametime = now - then;
@@ -295,8 +333,9 @@
 
 	fprint(fd, "curconns	%lld\n"
 		   "maxconns	%lld\n"
+		   "nplayers	%lld\n"
 		   "nparties	%lld\n",
-		nconns, maxconns, nparties);
+		nconns, maxconns, players.len, nparties);
 }
 
 void
@@ -316,7 +355,13 @@
 }
 
 
-/* Command & Control */
+/*
+ * Command & Control
+ *
+ *	- show stats: prints some server stats
+ *	- show states: prints the state of running simulations
+ *	- debug [on|off]: toggles debug mode
+ */
 void
 threadC2(void *)
 {
@@ -348,6 +393,11 @@
 					fprintstats(pfd[1]);
 				else if(strcmp(cmdargs[1], "states") == 0)
 					fprintstates(pfd[1]);
+			}else if(strcmp(cmdargs[0], "debug") == 0){
+				if(strcmp(cmdargs[1], "on") == 0)
+					debug = 1;
+				else if(strcmp(cmdargs[1], "off") == 0)
+					debug = 0;
 			}
 		}
 	}
@@ -401,6 +451,7 @@
 		fprint(2, "listening on %s\n", addr);
 
 	initparty(&theparty);
+	initplayerq(&players);
 
 	ingress = chancreate(sizeof(Frame*), 32);
 	egress = chancreate(sizeof(Frame*), 32);
--- a/net.c
+++ b/net.c
@@ -22,7 +22,7 @@
 }
 
 /*
- * x = g^k mod p
+ * y = g^k mod p
  */
 ulong
 dhgenkey(ulong g, ulong k, ulong p)
--- a/party.c
+++ b/party.c
@@ -8,16 +8,19 @@
 #include "dat.h"
 #include "fns.h"
 
+/* Party */
+
 Party *
-newparty(Party *p, Player *players)
+newparty(Party *p, Player *player0, Player *player1)
 {
 	Party *np;
 
 	np = emalloc(sizeof(Party));
-	np->players[0] = players[0];
-	np->players[1] = players[1];
+	np->players[0] = player0;
+	np->players[1] = player1;
 
 	np->u = newuniverse();
+	inituniverse(np->u);
 
 	addparty(p, np);
 
@@ -34,12 +37,12 @@
 }
 
 void
-addparty(Party *theparty, Party *p)
+addparty(Party *p, Party *np)
 {
-	p->prev = theparty->prev;
-	p->next = theparty;
-	theparty->prev->next = p;
-	theparty->prev = p;
+	np->prev = p->prev;
+	np->next = p;
+	p->prev->next = np;
+	p->prev = np;
 }
 
 void
@@ -46,4 +49,88 @@
 initparty(Party *p)
 {
 	p->next = p->prev = p;
+}
+
+/* Player */
+
+Player *
+newplayer(char *name, NetConn *nc)
+{
+	Player *p;
+
+	p = emalloc(sizeof(Player));
+	p->name = name? strdup(name): nil;
+	p->conn = nc;
+	p->oldkdown = p->kdown = 0;
+	p->next = nil;
+
+	return p;
+}
+
+void
+delplayer(Player *p)
+{
+	free(p->name);
+	free(p);
+}
+
+/* Player queue */
+
+static void
+playerq_put(Playerq *pq, Player *p)
+{
+	if(pq->tail == nil)
+		pq->head = pq->tail = p;
+	else{
+		pq->tail->next = p;
+		pq->tail = p;
+	}
+	pq->len++;
+}
+
+static Player *
+playerq_get(Playerq *pq)
+{
+	Player *p;
+
+	if(pq->head == nil)
+		return nil;
+
+	p = pq->head;
+	if(pq->head == pq->tail)
+		pq->head = pq->tail = nil;
+	else{
+		pq->head = p->next;
+		p->next = nil;
+	}
+	pq->len--;
+	return p;
+}
+
+static void
+playerq_del(Playerq *pq, Player *p)
+{
+	Player *np;
+
+	if(pq->head == p){
+		pq->pop(pq);
+		return;
+	}
+
+	for(np = pq->head; np->next != nil; np = np->next)
+		if(np->next == p){
+			np->next = np->next->next;
+			p->next = nil;
+			pq->len--;
+		}
+}
+
+void
+initplayerq(Playerq *pq)
+{
+	pq->head = pq->tail = nil;
+	pq->len = 0;
+	pq->put = playerq_put;
+	pq->get = playerq_get;
+	pq->del = playerq_del;
 }