diff options
-rw-r--r-- | dat.h | 35 | ||||
-rw-r--r-- | fns.h | 9 | ||||
-rw-r--r-- | lobby.c | 76 | ||||
-rw-r--r-- | mkfile | 1 | ||||
-rw-r--r-- | musw.c | 18 | ||||
-rw-r--r-- | muswd.c | 75 | ||||
-rw-r--r-- | pack.c | 114 | ||||
-rw-r--r-- | party.c | 44 |
8 files changed, 237 insertions, 135 deletions
@@ -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; @@ -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*); + @@ -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); } @@ -11,6 +11,7 @@ OFILES=\ nanosec.$O\ pack.$O\ lobby.$O\ + party.$O\ HFILES=\ dat.h\ @@ -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; @@ -55,15 +55,36 @@ 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) { t = 0; @@ -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); @@ -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; } } @@ -0,0 +1,44 @@ +#include <u.h> +#include <libc.h> +#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; +} |