From 615575f7dca0e43ecb23c4ab1ea7fd2e93c4e3b4 Mon Sep 17 00:00:00 2001 From: rodri Date: Fri, 23 Jul 2021 03:38:18 +0000 Subject: implemented a lobby for users waiting to join a party. brought the pack/unpack procedures from ssh(1). --- dat.h | 16 ++++++-- fns.h | 18 ++++++-- lobby.c | 62 ++++++++++++++++++++++++++++ mkfile | 2 + muswd.c | 30 ++++++-------- pack.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 248 insertions(+), 23 deletions(-) create mode 100644 lobby.c create mode 100644 pack.c diff --git a/dat.h b/dat.h index 66db045..fb790ae 100644 --- a/dat.h +++ b/dat.h @@ -2,7 +2,8 @@ typedef struct GameState GameState; typedef struct Derivative Derivative; -typedef struct Conn Conn; +typedef struct Seats Seats; +typedef struct Lobby Lobby; struct GameState { @@ -14,9 +15,18 @@ struct Derivative double dx, dv; }; -struct Conn +struct Seats { int *fds; - ulong off; + ulong len; ulong cap; }; + +struct Lobby +{ + Seats seats; + + int (*takeseat)(Lobby*, int); + int (*getcouple)(Lobby*, int*); + int (*leaveseat)(Lobby*, ulong); +}; diff --git a/fns.h b/fns.h index d94ff5b..99a3603 100644 --- a/fns.h +++ b/fns.h @@ -1,16 +1,28 @@ /* - * alloc + * alloc */ void *emalloc(ulong); void *erealloc(void*, ulong); //Image *eallocimage(Display*, Rectangle, ulong, int, ulong); /* - * physics + * physics */ void integrate(GameState*, double, double); /* - * nanosec + * nanosec */ uvlong nanosec(void); + +/* + * pack + */ +int pack(uchar*, int, char*, ...); +int unpack(uchar*, int, char*, ...); + +/* + * lobby + */ +Lobby *newlobby(void); +void dellobby(Lobby*); diff --git a/lobby.c b/lobby.c new file mode 100644 index 0000000..62322ad --- /dev/null +++ b/lobby.c @@ -0,0 +1,62 @@ +#include +#include +#include "dat.h" +#include "fns.h" + +static int +lobby_takeseat(Lobby *l, int fd) +{ + 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)); + } + + l->seats.fds[l->seats.len] = fd; + return l->seats.len++; +} + +static int +lobby_getcouple(Lobby *l, int *fds) +{ + 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->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)); + + l->seats.len -= 2; + return 0; + } + return -1; +} + +static int +lobby_leaveseat(Lobby *l, ulong idx) +{ + if(idx < l->seats.cap-1) + memmove(&l->seats.fds[idx], &l->seats.fds[idx+1], l->seats.cap*sizeof(int) - (l->seats.len + 1)*sizeof(int)); + l->seats.len--; + return 0; +} + +Lobby * +newlobby(void) +{ + Lobby *l; + + l = emalloc(sizeof(Lobby)); + memset(l, 0, sizeof(*l)); + l->takeseat = lobby_takeseat; + l->getcouple = lobby_getcouple; + l->leaveseat = lobby_leaveseat; + + return l; +} + +void +dellobby(Lobby *l) +{ + free(l->seats.fds); + free(l); +} diff --git a/mkfile b/mkfile index c3b9295..115f0b5 100644 --- a/mkfile +++ b/mkfile @@ -9,6 +9,8 @@ OFILES=\ alloc.$O\ physics.$O\ nanosec.$O\ + pack.$O\ + lobby.$O\ HFILES=\ dat.h\ diff --git a/muswd.c b/muswd.c index c652b39..249e516 100644 --- a/muswd.c +++ b/muswd.c @@ -9,7 +9,8 @@ int debug; GameState state; double t, Δt; -Conn conns; +Lobby *lobby; + static long _iolisten(va_list *arg) @@ -54,15 +55,11 @@ threadlisten(void *arg) continue; } - if(conns.off >= conns.cap){ - conns.cap += 8; - conns.fds = erealloc(conns.fds, conns.cap*sizeof(*conns.fds)); - } - conns.fds[conns.off++] = dfd; + lobby->takeseat(lobby, dfd); if(debug) - fprint(2, "added conn %d for %lud conns at %lud max\n", - dfd, conns.off, conns.cap); + fprint(2, "added conn for %lud conns at %lud max\n", + lobby->seats.len, lobby->seats.cap); } } @@ -95,16 +92,16 @@ threadsim(void *) then = now; timeacc += frametime/1e9; - for(i = 0; i < conns.off; i++) - if(fprint(conns.fds[i], "state: x=%g v=%g\n", state.x, state.v) < 0){ - fprint(2, "client #%d hanged up\n", i+1); - if(conns.off < conns.cap-1) - memmove(&conns.fds[conns.off], &conns.fds[conns.off+1], conns.cap-conns.off - 1); - conns.off--; + 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); + + lobby->leaveseat(lobby, i); if(debug) fprint(2, "removed conn %d for %lud conns at %lud max\n", - i, conns.off, conns.cap); + i, lobby->seats.len, lobby->seats.cap); i--; } @@ -146,8 +143,7 @@ threadmain(int argc, char *argv[]) if(acfd < 0) sysfatal("announce: %r"); - conns.fds = emalloc(2*sizeof(*conns.fds)); - conns.cap = 2; + lobby = newlobby(); threadcreate(threadlisten, adir, 4096); threadcreate(threadsim, nil, 4096); diff --git a/pack.c b/pack.c new file mode 100644 index 0000000..5899dbd --- /dev/null +++ b/pack.c @@ -0,0 +1,143 @@ +#include +#include +#include "dat.h" +#include "fns.h" + +/* + * these routines were taken directly from ssh(1). + * they serve as a reference. + */ + +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; + + for(;;){ + switch(c = *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; + break; + } + } +err: + return -1; +} + +static int +vunpack(uchar *p, int n, char *fmt, va_list a) +{ + uchar *p0 = p, *e = p+n; + u32int u; +// mpint *m; + void *s; + + 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; + break; + } + } +err: + return -1; +} + +int +pack(uchar *p, int n, char *fmt, ...) +{ + va_list a; + + va_start(a, fmt); + n = vpack(p, n, fmt, a); + va_end(a); + + return n; +} + +int +unpack(uchar *p, int n, char *fmt, ...) +{ + va_list a; + + va_start(a, fmt); + n = vunpack(p, n, fmt, a); + va_end(a); + + return n; +} -- cgit v1.2.3