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;
}