diff options
-rw-r--r-- | dat.h | 18 | ||||
-rw-r--r-- | fns.h | 5 | ||||
-rw-r--r-- | musw.c | 30 | ||||
-rw-r--r-- | muswd.c | 99 | ||||
-rw-r--r-- | net.c | 2 | ||||
-rw-r--r-- | party.c | 103 |
6 files changed, 214 insertions, 43 deletions
@@ -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; }; @@ -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 @@ -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"); @@ -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); @@ -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) @@ -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; +} |