From bdaa63a1a4604ada3539aeb50e4af144da3ba6f0 Mon Sep 17 00:00:00 2001 From: rodri Date: Sun, 25 Jul 2021 20:59:58 +0000 Subject: implemented parties to hold PvP match info. started serializing game state through the wire. made some major changes to the Lobby struct, plus the ability to check the health of every connection. added some more debug statements, did some cleanup and put more checks. --- dat.h | 35 +++++++++++++++----- fns.h | 9 +++++ lobby.c | 76 +++++++++++++++++++++++++++++++------------ mkfile | 1 + musw.c | 18 +++++++--- muswd.c | 75 ++++++++++++++++++++++++++++++------------ pack.c | 114 ++++++++++++++++++---------------------------------------------- party.c | 44 +++++++++++++++++++++++++ 8 files changed, 237 insertions(+), 135 deletions(-) create mode 100644 party.c diff --git a/dat.h b/dat.h index fb790ae..9ea1f7f 100644 --- a/dat.h +++ b/dat.h @@ -2,8 +2,10 @@ typedef struct GameState GameState; typedef struct Derivative Derivative; -typedef struct Seats Seats; +typedef struct Conn Conn; +typedef struct Player Player; typedef struct Lobby Lobby; +typedef struct Party Party; struct GameState { @@ -15,18 +17,35 @@ struct Derivative double dx, dv; }; -struct Seats +struct Conn { - int *fds; - ulong len; - ulong cap; + char dir[40]; + int ctl; + int data; +}; + +struct Player +{ + char *name; + Conn conn; }; struct Lobby { - Seats seats; + Player *seats; + ulong nseats; + ulong cap; - int (*takeseat)(Lobby*, int); - int (*getcouple)(Lobby*, int*); + int (*takeseat)(Lobby*, char*, int, int); int (*leaveseat)(Lobby*, ulong); + int (*getcouple)(Lobby*, Player*); + void (*healthcheck)(Lobby*); }; + +struct Party +{ + Player players[2]; /* the needle and the wedge */ + Party *prev, *next; +}; + +extern Party theparty; diff --git a/fns.h b/fns.h index 99a3603..a925117 100644 --- a/fns.h +++ b/fns.h @@ -26,3 +26,12 @@ int unpack(uchar*, int, char*, ...); */ Lobby *newlobby(void); void dellobby(Lobby*); + +/* + * lobby + */ +void inittheparty(void); +Party *newparty(Player[2]); +void delparty(Party*); +void addparty(Party*); + diff --git a/lobby.c b/lobby.c index 4004983..2007f2a 100644 --- a/lobby.c +++ b/lobby.c @@ -4,40 +4,75 @@ #include "fns.h" static int -lobby_takeseat(Lobby *l, int fd) +lobby_takeseat(Lobby *l, char *dir, int cfd, int dfd) { - 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)); + if(l->nseats >= l->cap){ + l->cap += 8; + l->seats = erealloc(l->seats, l->cap*sizeof(*l->seats)); } - l->seats.fds[l->seats.len] = fd; - return l->seats.len++; + l->seats[l->nseats].name = nil; + memmove(l->seats[l->nseats].conn.dir, dir, sizeof l->seats[l->nseats].conn.dir); + l->seats[l->nseats].conn.ctl = cfd; + l->seats[l->nseats].conn.data = dfd; + + return l->nseats++; +} + +static int +lobby_leaveseat(Lobby *l, ulong idx) +{ + if(idx >= l->cap) + return -1; + + if(idx < l->cap - 1) + memmove(&l->seats[idx], &l->seats[idx+1], l->cap*sizeof(*l->seats) - (idx + 1)*sizeof(*l->seats)); + + return --l->nseats; } static int -lobby_getcouple(Lobby *l, int *fds) +lobby_getcouple(Lobby *l, Player *couple) { - 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->nseats >= 2){ + couple[0] = l->seats[l->nseats-2]; + couple[1] = l->seats[l->nseats-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)); + if(l->nseats < l->cap - 2) + memmove(&l->seats[l->nseats], &l->seats[l->nseats+2], l->cap*sizeof(*l->seats) - (l->nseats + 2)*sizeof(*l->seats)); + + l->nseats -= 2; - l->seats.len -= 2; return 0; } + return -1; } -static int -lobby_leaveseat(Lobby *l, ulong idx) +static void +lobby_healthcheck(Lobby *l) { - if(idx < l->seats.cap-1) - memmove(&l->seats.fds[idx], &l->seats.fds[idx+1], l->seats.cap*sizeof(int) - (idx + 1)*sizeof(int)); - l->seats.len--; - return 0; + char status[48], buf[16]; + int i, fd; + + for(i = 0; i < l->nseats; i++){ + snprint(status, sizeof status, "%s/status", l->seats[i].conn.dir); + + fd = open(status, OREAD); + if(fd < 0) + goto cleanup; + + if(read(fd, buf, sizeof buf) > 0) + if(strncmp(buf, "Close", 5) == 0) + goto cleanup; + else{ + close(fd); + continue; + } +cleanup: + close(fd); + l->leaveseat(l, i); + } } Lobby * @@ -50,6 +85,7 @@ newlobby(void) l->takeseat = lobby_takeseat; l->getcouple = lobby_getcouple; l->leaveseat = lobby_leaveseat; + l->healthcheck = lobby_healthcheck; return l; } @@ -57,6 +93,6 @@ newlobby(void) void dellobby(Lobby *l) { - free(l->seats.fds); + free(l->seats); free(l); } diff --git a/mkfile b/mkfile index 115f0b5..c9c09ff 100644 --- a/mkfile +++ b/mkfile @@ -11,6 +11,7 @@ OFILES=\ nanosec.$O\ pack.$O\ lobby.$O\ + party.$O\ HFILES=\ dat.h\ diff --git a/musw.c b/musw.c index a88f0fc..1b40264 100644 --- a/musw.c +++ b/musw.c @@ -4,19 +4,26 @@ #include "dat.h" #include "fns.h" +int debug; + + void threadnetin(void *arg) { - char buf[256]; + uchar buf[256]; int fd, n; + double x, v; Ioproc *io; fd = *((int*)arg); io = ioproc(); - while((n = ioread(io, fd, buf, sizeof buf)) > 0) + while((n = ioread(io, fd, buf, sizeof buf)) > 0){ + unpack(buf, n, "dd", &x, &v); + n = snprint((char *)buf, sizeof buf, "state: x=%g v=%g\n", x, v); if(iowrite(io, 1, buf, n) != n) - fprint(2, "netin iowrite: %r\n"); + fprint(2, "iowrite: %r\n"); + } closeioproc(io); } @@ -32,7 +39,7 @@ threadnetout(void *arg) while((n = ioread(io, 0, buf, sizeof buf)) > 0) if(iowrite(io, fd, buf, n) != n) - fprint(2, "netout iowrite: %r\n"); + fprint(2, "iowrite: %r\n"); closeioproc(io); } @@ -50,6 +57,9 @@ threadmain(int argc, char *argv[]) int fd; ARGBEGIN{ + case 'd': + debug++; + break; default: usage(); }ARGEND; diff --git a/muswd.c b/muswd.c index 249e516..b3667e2 100644 --- a/muswd.c +++ b/muswd.c @@ -55,14 +55,35 @@ threadlisten(void *arg) continue; } - lobby->takeseat(lobby, dfd); + lobby->takeseat(lobby, ldir, lcfd, dfd); if(debug) fprint(2, "added conn for %lud conns at %lud max\n", - lobby->seats.len, lobby->seats.cap); + lobby->nseats, lobby->cap); } } +void +broadcaststate(void) +{ + int i, n; + uchar buf[256]; + Party *p; + + if(debug) + fprint(2, "state: x=%g v=%g\n", state.x, state.v); + + for(p = theparty.next; p != &theparty; p = p->next) + for(i = 0; i < nelem(p->players); i++){ + n = pack(buf, sizeof buf, "dd", state.x, state.v); + if(write(p->players[i].conn.data, buf, n) != n){ + lobby->takeseat(lobby, p->players[i^1].conn.dir, p->players[i^1].conn.ctl, p->players[i^1].conn.data); + delparty(p); + } + } + +} + void resetsim(void) { @@ -74,10 +95,10 @@ resetsim(void) void threadsim(void *) { - int i; uvlong then, now; double frametime, timeacc; Ioproc *io; + Player couple[2]; Δt = 0.01; then = nanosec(); @@ -87,24 +108,30 @@ threadsim(void *) resetsim(); for(;;){ - now = nanosec(); - frametime = now - then; - then = now; - timeacc += frametime/1e9; + lobby->healthcheck(lobby); - 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); + if(debug){ + Party *p; + ulong nparties = 0; - lobby->leaveseat(lobby, i); + for(p = theparty.next; p != &theparty; p = p->next) + nparties++; - if(debug) - fprint(2, "removed conn %d for %lud conns at %lud max\n", - i, lobby->seats.len, lobby->seats.cap); + fprint(2, "lobby status: %lud conns at %lud cap\n", + lobby->nseats, lobby->cap); + fprint(2, "party status: %lud parties going on\n", + nparties); + } - i--; - } + if(lobby->getcouple(lobby, couple) != -1) + newparty(couple); + + broadcaststate(); + + now = nanosec(); + frametime = now - then; + then = now; + timeacc += frametime/1e9; while(timeacc >= Δt){ integrate(&state, t, Δt); @@ -119,7 +146,7 @@ threadsim(void *) void usage(void) { - fprint(2, "usage: %s [-d]\n", argv0); + fprint(2, "usage: %s [-d] [-a addr]\n", argv0); threadexitsall("usage"); } @@ -127,9 +154,13 @@ void threadmain(int argc, char *argv[]) { int acfd; - char adir[40]; + char adir[40], *addr; + addr = "udp!*!112"; ARGBEGIN{ + case 'a': + addr = EARGF(usage()); + break; case 'd': debug++; break; @@ -139,11 +170,15 @@ threadmain(int argc, char *argv[]) if(argc != 0) usage(); - acfd = announce("tcp!*!112", adir); + acfd = announce(addr, adir); if(acfd < 0) sysfatal("announce: %r"); + if(debug) + fprint(2, "listening on %s\n", addr); + lobby = newlobby(); + inittheparty(); threadcreate(threadlisten, adir, 4096); threadcreate(threadsim, nil, 4096); diff --git a/pack.c b/pack.c index 5899dbd..d60800d 100644 --- a/pack.c +++ b/pack.c @@ -3,58 +3,37 @@ #include "dat.h" #include "fns.h" -/* - * these routines were taken directly from ssh(1). - * they serve as a reference. - */ +static ulong +get4(uchar *p) +{ + return p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3]; +} + +static void +put4(uchar *p, ulong u) +{ + p[0] = u>>24, p[1] = u>>16, p[2] = u>>8, p[3] = u; +} 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; + FPdbleword d; for(;;){ - switch(c = *fmt++){ + 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; - *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; + case 'd': + d.x = va_arg(a, double); + + if(p+8 > e) + goto err; + + put4(p, d.hi), p += 4; + put4(p, d.lo), p += 4; + break; } } @@ -66,51 +45,20 @@ static int vunpack(uchar *p, int n, char *fmt, va_list a) { uchar *p0 = p, *e = p+n; - u32int u; -// mpint *m; - void *s; + FPdbleword d; 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; + case 'd': + if(p+8 > e) + goto err; + + d.hi = get4(p), p += 4; + d.lo = get4(p), p += 4; + *va_arg(a, double*) = d.x; + break; } } diff --git a/party.c b/party.c new file mode 100644 index 0000000..d6b0e52 --- /dev/null +++ b/party.c @@ -0,0 +1,44 @@ +#include +#include +#include "dat.h" +#include "fns.h" + +Party theparty; + + +void +inittheparty(void) +{ + theparty.next = theparty.prev = &theparty; +} + +Party * +newparty(Player *players) +{ + Party *p; + + p = emalloc(sizeof(Party)); + p->players[0] = players[0]; + p->players[1] = players[1]; + + addparty(p); + + return p; +} + +void +delparty(Party *p) +{ + p->next->prev = p->prev; + p->prev->next = p->next; + free(p); +} + +void +addparty(Party *p) +{ + p->prev = theparty.prev; + p->next = &theparty; + theparty.prev->next = p; + theparty.prev = p; +} -- cgit v1.2.3