ref: d2c0ab7a62b7a2c99c4c491ce55466859429571b
parent: f959555dc653ecf54d75b180fcd018075e652e93
author: rodri <rgl@antares-labs.eu>
date: Fri May 5 18:35:14 EDT 2023
handle player quits gracefully. also fixed a bug whereby a player would never be freed if no party was happening, and another one where deleting a player from the player queue would cause a nil pointer deref.
--- a/dat.h
+++ b/dat.h
@@ -32,11 +32,13 @@
NShi, /* S accepts. sends P and G for DHX */
NCdhx = 12, /* C shares pubkey */
NSdhx, /* S shares pubkey */
- NCnudge = 16,
+ NCnudge = 16, /* nudge ACK */
NSnudge, /* check the pulse of the line */
NCinput = 20, /* C sends player input state */
NSsimstate, /* S sends current simulation state */
+ NCawol = 22, /* AWOL ACK */
+ NSawol, /* notify the adversary flew away */
NCbuhbye = 30,
NSbuhbye,
--- a/musw.c
+++ b/musw.c
@@ -232,6 +232,26 @@
}
void
+buhbye(void)
+{
+ Frame *frame;
+ int i, naptime;
+
+ if(netconn.state != NCSConnected)
+ return;
+
+ i = 10;
+ naptime = 2000/i;
+ while(i--){
+ frame = newframe(nil, NCbuhbye, netconn.lastseq+1, 0, 0, nil);
+ signframe(frame, netconn.dh.priv);
+ sendp(egress, frame);
+
+ sleep(naptime);
+ }
+}
+
+void
sendkeys(ulong kdown)
{
Frame *frame;
@@ -273,8 +293,12 @@
}
if(buf[0] == 'c'){
if(utfrune(buf, Kdel)){
+defenestrate:
close(fd);
threadexitsall(nil);
+ }else if(utfrune(buf, 'q')){
+ buhbye();
+ goto defenestrate;
}
}
if(buf[0] != 'k' && buf[0] != 'K')
@@ -415,6 +439,15 @@
sendp(egress, newf);
break;
+ case NSawol:
+ weplaying = 0;
+
+ newf = newframe(nil, NCawol, frame->seq+1, frame->seq, 0, nil);
+ signframe(newf, netconn.dh.priv);
+
+ sendp(egress, newf);
+
+ break;
case NSbuhbye:
weplaying = 0;
netconn.state = NCSDisconnected;
@@ -607,6 +640,8 @@
State *playing_δ(State *s, void*)
{
+ if(!weplaying)
+ return &gamestates[GSMatching];
return s;
}
--- a/muswd.c
+++ b/muswd.c
@@ -47,6 +47,8 @@
{
int i;
Party *p;
+ Player *adv;
+ Frame *f;
/*
* kick the player and put their adversary back in the
@@ -55,16 +57,25 @@
for(p = theparty.next; p != &theparty; p = p->next)
for(i = 0; i < nelem(p->players); i++)
if(p->players[i] == player){
- delplayer(p->players[i]);
- players.put(&players, p->players[i^1]);
+ adv = p->players[i^1];
+
+ players.put(&players, adv);
delparty(p);
+
+ /* notify the adversary */
+ f = newframe(&adv->conn->udp, NSawol, 0, 0, 0, nil);
+ signframe(f, adv->conn->dh.priv);
+ sendp(egress, f);
+
+ return;
}
/*
- * also clean the player queue
- * TODO: has nothing to do with the party
+ * make sure to free the player even if there's no
+ * party going on.
*/
players.del(&players, player);
+ delplayer(player);
}
int
--- a/party.c
+++ b/party.c
@@ -117,7 +117,7 @@
return;
}
- for(np = pq->head; np->next != nil; np = np->next)
+ for(np = pq->head; np != nil && np->next != nil; np = np->next)
if(np->next == p){
np->next = np->next->next;
p->next = nil;
--- a/vmodeled/vmodeled.man
+++ b/vmodeled/vmodeled.man
@@ -6,9 +6,7 @@
.I file
.SH DESCRIPTION
.I Vmodeled
-is a vector model—
-.B VModel
-—editor created with the purpose of customizing
+is a vector model (VModel) editor created with the purpose of customizing
.IR musw (1)
ships defined in the
.B vmdl