ref: c1cdf0f980b92193953f05bf444b7c78f369a122
parent: e769c8684c1200f922ff41c6ef5d0cdd4fe0e67f
author: rodri <rgl@antares-labs.eu>
date: Thu Feb 9 16:01:00 EST 2023
implemented a packet processing pipeline. got rid of Lobby. began development of a network protocol.
--- a/dat.h
+++ b/dat.h
@@ -22,7 +22,24 @@
};
enum {
- Framehdrsize = 4+4+4+2,
+ NChi = 10, /* C wants to connect */
+ NShi, /* S accepts */
+ NCdhx0 = 12, /* C asks for p and g */
+ NSdhx0, /* S sends them. it's not a negotiation */
+ NCdhx1 = 14, /* C shares pubkey */
+ NSdhx1, /* S shares pubkey */
+ NCnudge = 16,
+ NSnudge, /* check the pulse of the line */
+
+ NCinput = 20, /* C sends player input state */
+ NSsimstate, /* S sends current simulation state */
+
+ NCbuhbye = 30,
+ NSbuhbye
+};
+
+enum {
+ Framehdrsize = 1+4+4+2,
MTU = 1024
};
@@ -36,10 +53,8 @@
typedef struct Derivative Derivative;
typedef struct Frame Frame;
-typedef struct Conn Conn;
-typedef struct PInput PInput;
+typedef struct NetConn NetConn;
typedef struct Player Player;
-typedef struct Lobby Lobby;
typedef struct Party Party;
/*
@@ -118,44 +133,25 @@
struct Frame
{
- Udphdr *udp;
- uint seq;
- uint ack;
- uint id;
- ushort len;
+ Udphdr udp;
+ u8int type;
+ u32int seq;
+ u32int ack;
+ u16int len;
uchar data[];
};
-struct Conn
+struct NetConn
{
- char dir[40];
- int ctl;
- int data;
- int status;
+ Udphdr udp;
+ int isconnected;
};
-struct PInput
-{
- ulong kdown;
-};
-
struct Player
{
char *name;
- Conn conn;
- PInput oldinput, input;
-};
-
-struct Lobby
-{
- Player *seats;
- ulong nseats;
- ulong cap;
-
- int (*takeseat)(Lobby*, char*, int, int);
- int (*leaveseat)(Lobby*, ulong);
- int (*getcouple)(Lobby*, Player*);
- void (*purge)(Lobby*);
+ NetConn conn;
+ ulong okdown, kdown;
};
struct Party
--- a/fns.h
+++ b/fns.h
@@ -24,12 +24,6 @@
int unpack(uchar*, int, char*, ...);
/*
- * lobby
- */
-Lobby *newlobby(void);
-void dellobby(Lobby*);
-
-/*
* party
*/
Party *newparty(Party*, Player[2]);
--- a/lobby.c
+++ /dev/null
@@ -1,101 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <ip.h>
-#include <draw.h>
-#include <geometry.h>
-#include "dat.h"
-#include "fns.h"
-
-static int
-lobby_takeseat(Lobby *l, char *dir, int cfd, int dfd)
-{
- if(l->nseats >= l->cap){
- l->cap += 8;
- l->seats = erealloc(l->seats, l->cap*sizeof(*l->seats));
- }
-
- 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, Player *couple)
-{
- if(l->nseats >= 2){
- couple[0] = l->seats[l->nseats-2];
- couple[1] = l->seats[l->nseats-1];
-
- 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;
-
- return 0;
- }
-
- return -1;
-}
-
-static void
-lobby_purge(Lobby *l)
-{
- 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 *
-newlobby(void)
-{
- Lobby *l;
-
- l = emalloc(sizeof(Lobby));
- memset(l, 0, sizeof(Lobby));
- l->takeseat = lobby_takeseat;
- l->getcouple = lobby_getcouple;
- l->leaveseat = lobby_leaveseat;
- l->purge = lobby_purge;
-
- return l;
-}
-
-void
-dellobby(Lobby *l)
-{
- free(l->seats);
- free(l);
-}
--- a/mkfile
+++ b/mkfile
@@ -11,7 +11,6 @@
physics.$O\
nanosec.$O\
pack.$O\
- lobby.$O\
party.$O\
universe.$O\
sprite.$O\
--- a/musw.c
+++ b/musw.c
@@ -35,7 +35,8 @@
Universe *universe;
VModel *needlemdl, *wedgemdl;
Image *skymap;
-Channel *kchan;
+Channel *ingress;
+Channel *egress;
char winspec[32];
int debug;
@@ -143,6 +144,20 @@
}
void
+sendkeys(ulong kdown)
+{
+ Frame *frame;
+
+ frame = emalloc(sizeof(Frame)+sizeof(kdown));
+ frame->type = NCinput;
+ frame->seq = 0;
+ frame->ack = 0;
+ frame->len = sizeof(kdown);
+ pack(frame->data, frame->len, "k", kdown);
+ sendp(egress, frame);
+}
+
+void
kbdproc(void *)
{
Rune r;
@@ -188,10 +203,9 @@
}
if(debug)
- fprint(2, "kdown %.*lub\n",
- sizeof(kdown)*8, kdown);
+ fprint(2, "kdown %.*lub\n", sizeof(kdown)*8, kdown);
- nbsendul(kchan, kdown);
+ sendkeys(kdown);
}
}
@@ -198,46 +212,59 @@
void
threadnetrecv(void *arg)
{
- uchar buf[1024];
+ uchar buf[MTU];
int fd, n;
Ioproc *io;
+ Frame *frame;
+ threadsetname("threadnetrecv");
+
fd = *(int*)arg;
io = ioproc();
while((n = ioread(io, fd, buf, sizeof buf)) > 0){
- unpack(buf, n, "PdPdP",
- &universe->ships[0].p, &universe->ships[0].θ,
- &universe->ships[1].p, &universe->ships[1].θ,
- &universe->star.p);
+ frame = emalloc(sizeof(Frame)+(n-Framehdrsize));
+ unpack(buf, n, "f", frame);
+ sendp(ingress, frame);
}
closeioproc(io);
}
void
+threadnetppu(void *)
+{
+ Frame *frame;
+
+ threadsetname("threadnetppu");
+
+ while((frame = recvp(ingress)) != nil){
+ switch(frame->type){
+ case NSsimstate:
+ unpack(frame->data, frame->len, "PdPdP",
+ &universe->ships[0].p, &universe->ships[0].θ,
+ &universe->ships[1].p, &universe->ships[1].θ,
+ &universe->star.p);
+ break;
+ }
+
+ free(frame);
+ }
+}
+
+void
threadnetsend(void *arg)
{
uchar buf[MTU];
int fd, n;
- ulong kdown;
Frame *frame;
+ threadsetname("threadnetsend");
+
fd = *(int*)arg;
- frame = emalloc(sizeof(Frame)+sizeof(kdown));
- frame->udp = nil;
- frame->seq = ntruerand(1000)>>1;
- frame->ack = 0;
- frame->id = truerand();
- frame->len = sizeof(kdown);
- for(;;){
- kdown = recvul(kchan);
-
- frame->seq++;
-
- pack(frame->data, frame->len, "k", kdown);
-
- n = pack(buf, sizeof buf, "F", frame);
+ while((frame = recvp(egress)) != nil){
+ n = pack(buf, sizeof buf, "f", frame);
+ free(frame);
if(write(fd, buf, n) != n)
sysfatal("write: %r");
}
@@ -273,7 +300,7 @@
skymap = readimage(display, fd, 1);
if(skymap == nil){
darkness:
- fprint(2, "couldn't read a sky map. falling back to darkness...\n");
+ fprint(2, "couldn't read the sky map. falling back to darkness...\n");
skymap = display->black;
}
close(fd);
@@ -364,7 +391,6 @@
screenrf.bx = Vec2(1, 0);
screenrf.by = Vec2(0,-1);
- kchan = chancreate(sizeof kdown, 1);
proccreate(kbdproc, nil, 4096);
/* TODO: draw a CONNECTING... sign */
@@ -386,9 +412,11 @@
initskymap();
- threadcreate(threadnetrecv, &fd, 4096);
- threadcreate(threadnetsend, &fd, 4096);
- threadcreate(threadresize, mc, 4096);
+ ingress = chancreate(sizeof(Frame*), 8);
+ egress = chancreate(sizeof(Frame*), 8);
+ threadcreate(threadnetrecv, &fd, mainstacksize);
+ threadcreate(threadnetsend, &fd, mainstacksize);
+ threadcreate(threadresize, mc, mainstacksize);
then = nanosec();
io = ioproc();
--- a/muswd.c
+++ b/muswd.c
@@ -8,66 +8,99 @@
#include "fns.h"
int debug;
+int mainstacksize = 24*1024;
-Lobby *lobby;
Party theparty;
+Channel *ingress;
+Channel *egress;
void
-threadlisten(void *arg)
+threadnetrecv(void *arg)
{
- uchar buf[MTU], *p, *e;
+ uchar buf[MTU];
int fd, n;
- ushort rport, lport;
- ulong kdown;
Ioproc *io;
Frame *frame;
+ threadsetname("threadnetrecv");
+
fd = *(int*)arg;
io = ioproc();
- frame = emalloc(sizeof(Frame));
while((n = ioread(io, fd, buf, sizeof buf)) > 0){
- p = buf;
- e = buf+n;
+ frame = emalloc(sizeof(Frame)+(n-Udphdrsize-Framehdrsize));
+ unpack(buf, n, "F", frame);
+ sendp(ingress, frame);
+ }
+ closeioproc(io);
+}
- unpack(p, e-p, "F", frame);
+void
+threadnetppu(void *)
+{
+ ushort rport, lport;
+ ulong kdown;
+ Frame *frame;
- rport = frame->udp->rport[0]<<8 | frame->udp->rport[1];
- lport = frame->udp->lport[0]<<8 | frame->udp->lport[1];
-
- unpack(frame->data, frame->len, "k", &kdown);
+ threadsetname("threadnetppu");
- if(debug)
- fprint(2, "%I!%d → %I!%d | %d (%d) rcvd seq %ud ack %ud id %ud len %ud %.*lub\n",
- frame->udp->raddr, rport, frame->udp->laddr, lport, threadid(), getpid(), frame->seq, frame->ack, frame->id, frame->len, sizeof(kdown)*8, kdown);
+ while((frame = recvp(ingress)) != nil){
+ rport = frame->udp.rport[0]<<8 | frame->udp.rport[1];
+ lport = frame->udp.lport[0]<<8 | frame->udp.lport[1];
+
+ switch(frame->type){
+ case NCinput:
+ unpack(frame->data, frame->len, "k", &kdown);
+
+ if(debug){
+ fprint(2, "%I!%d ← %I!%d | rcvd type %ud seq %ud ack %ud len %ud %.*lub\n",
+ frame->udp.laddr, lport, frame->udp.raddr, rport,
+ frame->type, frame->seq, frame->ack, frame->len,
+ sizeof(kdown)*8, kdown);
+ }
+ break;
+ }
+
+ free(frame);
}
- closeioproc(io);
}
void
+threadnetsend(void *arg)
+{
+ uchar buf[MTU];
+ int fd, n;
+ Frame *frame;
+
+ threadsetname("threadnetsend");
+
+ fd = *(int*)arg;
+
+ while((frame = recvp(egress)) != nil){
+ n = pack(buf, sizeof buf, "F", frame);
+ free(frame);
+ if(write(fd, buf, n) != n)
+ sysfatal("write: %r");
+ }
+}
+
+void
broadcaststate(void)
{
- int i, n;
- uchar buf[1024];
- Player *player;
+ int i;
+ Frame *frame;
+// Player *player;
Party *p;
for(p = theparty.next; p != &theparty; p = p->next){
- n = pack(buf, sizeof buf, "PdPdP",
+ 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(i = 0; i < nelem(p->players); i++){
- if(write(p->players[i].conn.data, buf, n) != n){
- player = &p->players[i^1];
- lobby->takeseat(lobby, player->conn.dir, player->conn.ctl, player->conn.data);
- /* step back and delete the spoiled party */
- p = p->prev;
- delparty(p->next);
- break;
- }
}
}
@@ -79,7 +112,7 @@
uvlong then, now;
double frametime, Δt;
Ioproc *io;
- Player couple[2];
+// Player couple[2];
Party *p;
Δt = 0.01;
@@ -87,13 +120,11 @@
io = ioproc();
for(;;){
- lobby->purge(lobby);
+// if(lobby->getcouple(lobby, couple) != -1){
+// newparty(&theparty, couple);
+// theparty.prev->u->reset(theparty.prev->u);
+// }
- if(lobby->getcouple(lobby, couple) != -1){
- newparty(&theparty, couple);
- theparty.prev->u->reset(theparty.prev->u);
- }
-
now = nanosec();
frametime = now - then;
then = now;
@@ -123,13 +154,13 @@
for(p = theparty.next; p != &theparty; p = p->next)
nparties++;
- fprint(fd, "curplayers %lud\n"
- "totplayers %lud\n"
- "maxplayers %lud\n"
- "curparties %lud\n"
- "totparties %lud\n",
- lobby->nseats, (ulong)0, lobby->cap,
- nparties, (ulong)0);
+// fprint(fd, "curplayers %lud\n"
+// "totplayers %lud\n"
+// "maxplayers %lud\n"
+// "curparties %lud\n"
+// "totparties %lud\n",
+// lobby->nseats, 0UL, lobby->cap,
+// nparties, 0UL);
}
void
@@ -232,11 +263,14 @@
if(debug)
fprint(2, "listening on %s\n", addr);
- lobby = newlobby();
initparty(&theparty);
- threadcreate(threadC2, nil, 4096);
- threadcreate(threadlisten, &adfd, 4096);
- threadcreate(threadsim, nil, 4096);
+ ingress = chancreate(sizeof(Frame*), 32);
+ egress = chancreate(sizeof(Frame*), 32);
+ threadcreate(threadC2, nil, mainstacksize);
+ threadcreate(threadnetrecv, &adfd, mainstacksize);
+ threadcreate(threadnetppu, nil, mainstacksize);
+ threadcreate(threadnetsend, &adfd, mainstacksize);
+ threadcreate(threadsim, nil, mainstacksize);
threadexits(nil);
}
--- a/pack.c
+++ b/pack.c
@@ -1,5 +1,6 @@
#include <u.h>
#include <libc.h>
+#include <pool.h>
#include <ip.h>
#include <draw.h>
#include <geometry.h>
@@ -37,7 +38,7 @@
ulong k;
FPdbleword d;
Point2 P;
- Frame *F;
+ Frame *F = nil;
for(;;){
switch(*fmt++){
@@ -74,13 +75,25 @@
case 'F':
F = va_arg(a, Frame*);
+ if(p+Udphdrsize > e)
+ goto err;
+
+ memmove(p, &F->udp, Udphdrsize), p += Udphdrsize;
+ /* fallthrough */
+ case 'f':
+ if(F == nil)
+ F = va_arg(a, Frame*);
+
if(p+Framehdrsize+F->len > e)
goto err;
+ *p++ = F->type;
put4(p, F->seq), p += 4;
put4(p, F->ack), p += 4;
- put4(p, F->id), p += 4;
put2(p, F->len), p += 2;
+
+ if(p+F->len > e)
+ goto err;
memmove(p, F->data, F->len), p += F->len;
break;
@@ -97,7 +110,7 @@
ulong k;
FPdbleword d;
Point2 P;
- Frame *F;
+ Frame *F = nil;
for(;;){
switch(*fmt++){
@@ -129,24 +142,29 @@
break;
case 'F':
- if(p+Udphdrsize+Framehdrsize > e)
+ if(p+Udphdrsize > e)
goto err;
F = va_arg(a, Frame*);
- F->udp = (Udphdr*)p, p += Udphdrsize;
+ memmove(&F->udp, p, Udphdrsize), p += Udphdrsize;
+ /* fallthrough */
+ case 'f':
+ if(p+Framehdrsize > e)
+ goto err;
+
+ if(F == nil)
+ F = va_arg(a, Frame*);
+
+ F->type = *p++;
F->seq = get4(p), p += 4;
F->ack = get4(p), p += 4;
- F->id = get4(p), p += 4;
F->len = get2(p), p += 2;
- /* XXX: I'm not happy with this. */
if(p+F->len > e)
goto err;
- F = erealloc(F, sizeof(Frame)+F->len);
- memmove(F->data, p, F->len);
- p += F->len;
+ memmove(F->data, p, F->len), p += F->len;
break;
}