aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrodri <rgl@antares-labs.eu>2023-02-21 22:18:56 +0000
committerrodri <rgl@antares-labs.eu>2023-02-21 22:18:56 +0000
commitecc7d34e9229524a8d4340f0e127f1421029141c (patch)
treeb1e1a9dea5f4a31da7a87826d698b709419a5309
parentfd5dc301e4a69d7b7c1293aafe5b069b4ff400a4 (diff)
downloadmusw-ecc7d34e9229524a8d4340f0e127f1421029141c.tar.gz
musw-ecc7d34e9229524a8d4340f0e127f1421029141c.tar.bz2
musw-ecc7d34e9229524a8d4340f0e127f1421029141c.zip
take the packet seq and ack into account during connection setup. added a player queue to keep clients around waiting for a party.
-rw-r--r--dat.h18
-rw-r--r--fns.h5
-rw-r--r--musw.c30
-rw-r--r--muswd.c99
-rw-r--r--net.c2
-rw-r--r--party.c103
6 files changed, 214 insertions, 43 deletions
diff --git a/dat.h b/dat.h
index 0e44b4d..5820845 100644
--- a/dat.h
+++ b/dat.h
@@ -64,6 +64,7 @@ typedef struct Frame Frame;
typedef struct DHparams DHparams;
typedef struct NetConn NetConn;
typedef struct Player Player;
+typedef struct Playerq Playerq;
typedef struct Party Party;
/*
@@ -98,7 +99,7 @@ struct Particle
{
Point2 p, v;
double θ, ω;
- double mass; /* kg */
+ double mass; /* in kg */
};
struct Bullet
@@ -172,12 +173,23 @@ struct Player
{
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;
};
diff --git a/fns.h b/fns.h
index a8dbaca..b0ff100 100644
--- a/fns.h
+++ b/fns.h
@@ -26,10 +26,13 @@ int unpack(uchar*, int, char*, ...);
/*
* 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
diff --git a/musw.c b/musw.c
index 08d1272..25acdb0 100644
--- a/musw.c
+++ b/musw.c
@@ -151,7 +151,7 @@ initconn(void)
{
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 @@ sendkeys(ulong kdown)
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 @@ threadnetppu(void *)
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 @@ threadnetppu(void *)
}
break;
}
+
+ netconn.lastseq = frame->seq;
+ netconn.lastack = frame->ack;
discard:
delframe(frame);
}
@@ -345,7 +352,10 @@ threadnetsend(void *arg)
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 @@ darkness:
}
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 @@ threadmain(int argc, char *argv[])
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");
diff --git a/muswd.c b/muswd.c
index c85b5a0..602223b 100644
--- a/muswd.c
+++ b/muswd.c
@@ -13,6 +13,7 @@ int debug;
int mainstacksize = 24*1024;
Party theparty;
+Playerq players;
NetConn **conns;
usize nconns;
usize maxconns;
@@ -41,6 +42,28 @@ getconn(Frame *f)
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 @@ popconn(NetConn *nc)
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 @@ nudgeconns(ulong curts)
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 @@ threadnetppu(void *)
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 @@ threadnetppu(void *)
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 @@ threadnetsend(void *arg)
int fd, n;
ushort rport, lport;
Frame *frame;
+ NetConn *nc;
threadsetname("threadnetsend");
@@ -219,7 +251,13 @@ threadnetsend(void *arg)
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 @@ broadcaststate(void)
{
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 @@ threadsim(void *)
uvlong then, now;
double frametime, Δt;
Ioproc *io;
-// Player couple[2];
Party *p;
Δt = 0.01;
@@ -258,10 +298,8 @@ threadsim(void *)
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 @@ fprintstats(int fd)
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 @@ fprintstates(int fd)
}
-/* 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 @@ threadC2(void *)
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 @@ threadmain(int argc, char *argv[])
fprint(2, "listening on %s\n", addr);
initparty(&theparty);
+ initplayerq(&players);
ingress = chancreate(sizeof(Frame*), 32);
egress = chancreate(sizeof(Frame*), 32);
diff --git a/net.c b/net.c
index 58542ba..d208311 100644
--- a/net.c
+++ b/net.c
@@ -22,7 +22,7 @@ dhgenpg(ulong *p, ulong *g)
}
/*
- * x = g^k mod p
+ * y = g^k mod p
*/
ulong
dhgenkey(ulong g, ulong k, ulong p)
diff --git a/party.c b/party.c
index 6199b87..87cf1f8 100644
--- 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 @@ delparty(Party *p)
}
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
@@ -47,3 +50,87 @@ 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;
+}