From 775309861b51dd1f340d82074b7e9234f3e0675e Mon Sep 17 00:00:00 2001 From: rodri Date: Sat, 11 Feb 2023 00:26:30 +0000 Subject: implemented connection establishment with per client DHX. --- dat.h | 47 +++++++++++++------- fns.h | 12 ++++- mkfile | 1 + musw.c | 108 +++++++++++++++++++++++++++++++++++++------- muswd.c | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++++----------- net.c | 94 +++++++++++++++++++++++++++++++++++++++ pack.c | 3 +- 7 files changed, 360 insertions(+), 60 deletions(-) create mode 100644 net.c diff --git a/dat.h b/dat.h index 9727db3..89554bc 100644 --- a/dat.h +++ b/dat.h @@ -14,6 +14,12 @@ typedef enum { WEDGE } Kind; +typedef enum { + NCSDisconnected, + NCSConnecting, + NCSConnected +} NCState; + enum { SCRW = 640, SCRH = 480, @@ -22,24 +28,25 @@ enum { }; enum { - 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 */ + NChi = 10, /* C wants to connect */ + NShi, /* S accepts. sends P and G for DHX */ + NCdhx = 12, /* C shares pubkey */ + NSdhx, /* 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 + NSbuhbye, + + NSerror = 66 /* report an error */ }; enum { - Framehdrsize = 1+4+4+2, + ProtocolID = 0x5753554d, /* MUSW */ + Framehdrsize = 4+1+4+4+2, MTU = 1024 }; @@ -53,6 +60,7 @@ typedef struct Universe Universe; typedef struct Derivative Derivative; typedef struct Frame Frame; +typedef struct DHparams DHparams; typedef struct NetConn NetConn; typedef struct Player Player; typedef struct Party Party; @@ -63,7 +71,7 @@ typedef struct Party Party; struct VModel { Point2 *pts; - ulong npts; + usize npts; /* WIP * l(ine) → takes 2 points * c(urve) → takes 3 points @@ -134,6 +142,7 @@ struct Derivative struct Frame { Udphdr udp; + u32int id; /* ProtocolID */ u8int type; u32int seq; u32int ack; @@ -141,10 +150,18 @@ struct Frame uchar data[]; }; +struct DHparams +{ + ulong p, g, pub, sec, priv; +}; + struct NetConn { Udphdr udp; - int isconnected; + DHparams dh; + NCState state; + u32int lastseq; + u32int lastack; }; struct Player diff --git a/fns.h b/fns.h index 297a393..b4059ce 100644 --- a/fns.h +++ b/fns.h @@ -39,8 +39,18 @@ void deluniverse(Universe*); void inituniverse(Universe*); /* - * sprite + * sprite */ Sprite *newsprite(Image*, Point, Rectangle, int, ulong); Sprite *readsprite(char*, Point, Rectangle, int, ulong); void delsprite(Sprite*); + +/* + * net + */ +void dhgenpg(ulong*, ulong*); +ulong dhgenkey(ulong, ulong, ulong); +NetConn *newnetconn(NCState, Udphdr*); +void delnetconn(NetConn*); +Frame *newframe(Frame*, u8int, u32int, u32int, u16int, uchar*); +void delframe(Frame*); diff --git a/mkfile b/mkfile index 2125bca..3d7da33 100644 --- a/mkfile +++ b/mkfile @@ -14,6 +14,7 @@ OFILES=\ party.$O\ universe.$O\ sprite.$O\ + net.$O\ HFILES=\ dat.h\ diff --git a/musw.c b/musw.c index 12b0307..ca428bf 100644 --- a/musw.c +++ b/musw.c @@ -37,6 +37,7 @@ VModel *needlemdl, *wedgemdl; Image *skymap; Channel *ingress; Channel *egress; +NetConn netconn; char winspec[32]; int debug; @@ -85,7 +86,7 @@ readvmodel(char *file) continue; case 'v': if(tokenize(s, args, nelem(args)) != nelem(args)){ - werrstr("syntax error: %s:%lud 'v' expects %d args", + werrstr("syntax error: %s:%ld 'v' expects %d args", file, lineno, nelem(args)); free(mdl); Bterm(bin); @@ -143,16 +144,25 @@ drawship(Ship *ship, Image *dst) } } +void +initconn(void) +{ + Frame *frame; + + frame = newframe(nil, NChi, 0, 0, 0, nil); + sendp(egress, frame); + netconn.state = NCSConnecting; +} + 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); + if(netconn.state != NCSConnected) + return; + + frame = newframe(nil, NCinput, 0, 0, sizeof(kdown), nil); pack(frame->data, frame->len, "k", kdown); sendp(egress, frame); } @@ -214,6 +224,7 @@ threadnetrecv(void *arg) { uchar buf[MTU]; int fd, n; + ushort rport, lport; Ioproc *io; Frame *frame; @@ -223,9 +234,17 @@ threadnetrecv(void *arg) io = ioproc(); while((n = ioread(io, fd, buf, sizeof buf)) > 0){ - frame = emalloc(sizeof(Frame)+(n-Framehdrsize)); + frame = newframe(nil, 0, 0, 0, n-Framehdrsize, nil); unpack(buf, n, "f", frame); sendp(ingress, frame); + + if(debug){ + rport = frame->udp.rport[0]<<8 | frame->udp.rport[1]; + lport = frame->udp.lport[0]<<8 | frame->udp.lport[1]; + fprint(2, "%I!%ud ← %I!%ud | rcvd type %ud seq %ud ack %ud len %ud\n", + frame->udp.laddr, lport, frame->udp.raddr, rport, + frame->type, frame->seq, frame->ack, frame->len); + } } closeioproc(io); } @@ -233,20 +252,62 @@ threadnetrecv(void *arg) void threadnetppu(void *) { - Frame *frame; + Frame *frame, *newf; 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); + if(frame->id != ProtocolID) + goto discard; + + switch(netconn.state){ + case NCSConnecting: + switch(frame->type){ + case NShi: + unpack(frame->data, frame->len, "kk", &netconn.dh.p, &netconn.dh.g); + + newf = newframe(frame, NCdhx, 0, 0, sizeof(ulong), nil); + + netconn.dh.sec = truerand(); + pack(newf->data, newf->len, "k", dhgenkey(netconn.dh.g, netconn.dh.sec, netconn.dh.p)); + sendp(egress, newf); + + if(debug) + fprint(2, "\tsent pubkey %ld\n", dhgenkey(netconn.dh.g, netconn.dh.sec, netconn.dh.p)); + + break; + case NSdhx: + unpack(frame->data, frame->len, "k", &netconn.dh.pub); + netconn.state = NCSConnected; + + if(debug) + fprint(2, "\trecvd pubkey %ld\n", netconn.dh.pub); + + netconn.dh.priv = dhgenkey(netconn.dh.pub, netconn.dh.sec, netconn.dh.p); + break; + } break; - } + case NCSConnected: + 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; + case NSnudge: + newf = newframe(frame, NCnudge, 0, 0, 0, nil); + + sendp(egress, newf); + break; + case NSbuhbye: + netconn.state = NCSDisconnected; + break; + } + break; + } +discard: free(frame); } } @@ -256,6 +317,7 @@ threadnetsend(void *arg) { uchar buf[MTU]; int fd, n; + ushort rport, lport; Frame *frame; threadsetname("threadnetsend"); @@ -264,9 +326,18 @@ threadnetsend(void *arg) while((frame = recvp(egress)) != nil){ n = pack(buf, sizeof buf, "f", frame); - free(frame); if(write(fd, buf, n) != n) sysfatal("write: %r"); + + if(debug){ + rport = frame->udp.rport[0]<<8 | frame->udp.rport[1]; + lport = frame->udp.lport[0]<<8 | frame->udp.lport[1]; + fprint(2, "%I!%ud → %I!%ud | sent type %ud seq %ud ack %ud len %ud\n", + frame->udp.laddr, lport, frame->udp.raddr, rport, + frame->type, frame->seq, frame->ack, frame->len); + } + + free(frame); } } @@ -366,6 +437,7 @@ threadmain(int argc, char *argv[]) Ioproc *io; GEOMfmtinstall(); + fmtinstall('I', eipfmt); ARGBEGIN{ case 'd': debug++; @@ -415,6 +487,7 @@ threadmain(int argc, char *argv[]) ingress = chancreate(sizeof(Frame*), 8); egress = chancreate(sizeof(Frame*), 8); threadcreate(threadnetrecv, &fd, mainstacksize); + threadcreate(threadnetppu, nil, mainstacksize); threadcreate(threadnetsend, &fd, mainstacksize); threadcreate(threadresize, mc, mainstacksize); @@ -429,6 +502,9 @@ threadmain(int argc, char *argv[]) redraw(); + if(netconn.state == NCSDisconnected) + initconn(); + iosleep(io, HZ2MS(30)); } } diff --git a/muswd.c b/muswd.c index 435d130..9329545 100644 --- a/muswd.c +++ b/muswd.c @@ -11,15 +11,56 @@ int debug; int mainstacksize = 24*1024; Party theparty; +NetConn **conns; +usize nconns; +usize maxconns; Channel *ingress; Channel *egress; +void +putconn(NetConn *nc) +{ + if(++nconns > maxconns){ + conns = erealloc(conns, sizeof(NetConn*)*nconns); + maxconns = nconns; + } + conns[nconns-1] = nc; +} + +NetConn * +getconn(Frame *f) +{ + NetConn **nc; + + for(nc = conns; nc < conns+nconns; nc++) + if(memcmp(&(*nc)->udp, &f->udp, Udphdrsize) == 0) + return *nc; + return nil; +} + +int +popconn(NetConn *nc) +{ + NetConn **ncp, **ncpe; + + ncpe = conns+nconns; + + for(ncp = conns; ncp < conns+nconns; ncp++) + if(*ncp == nc){ + memmove(ncp, ncp+1, sizeof(NetConn*)*(ncpe-ncp-1)); + nconns--; + return 0; + } + return -1; +} + void threadnetrecv(void *arg) { uchar buf[MTU]; int fd, n; + ushort rport, lport; Ioproc *io; Frame *frame; @@ -29,9 +70,17 @@ threadnetrecv(void *arg) io = ioproc(); while((n = ioread(io, fd, buf, sizeof buf)) > 0){ - frame = emalloc(sizeof(Frame)+(n-Udphdrsize-Framehdrsize)); + frame = newframe(nil, 0, 0, 0, n-Udphdrsize-Framehdrsize, nil); unpack(buf, n, "F", frame); sendp(ingress, frame); + + if(debug){ + rport = frame->udp.rport[0]<<8 | frame->udp.rport[1]; + lport = frame->udp.lport[0]<<8 | frame->udp.lport[1]; + fprint(2, "%I!%ud ← %I!%ud | rcvd type %ud seq %ud ack %ud len %ud\n", + frame->udp.laddr, lport, frame->udp.raddr, rport, + frame->type, frame->seq, frame->ack, frame->len); + } } closeioproc(io); } @@ -39,29 +88,74 @@ threadnetrecv(void *arg) void threadnetppu(void *) { - ushort rport, lport; ulong kdown; - Frame *frame; + Frame *frame, *newf; + NetConn *nc; threadsetname("threadnetppu"); 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); + if(frame->id != ProtocolID) + goto discard; + + nc = getconn(frame); + if(nc == nil){ + if(frame->type == NChi){ + nc = newnetconn(NCSConnecting, &frame->udp); + putconn(nc); + + newf = newframe(frame, NShi, 0, 0, 2*sizeof(ulong), nil); + + dhgenpg(&nc->dh.p, &nc->dh.g); + pack(newf->data, newf->len, "kk", nc->dh.p, nc->dh.g); + sendp(egress, newf); + + if(debug) + fprint(2, "\tsent p %ld g %ld\n", nc->dh.p, nc->dh.g); + }else + goto discard; + } + + switch(nc->state){ + case NCSConnecting: + switch(frame->type){ + case NCdhx: + unpack(frame->data, frame->len, "k", &nc->dh.pub); + nc->state = NCSConnected; + + if(debug) + fprint(2, "\trecvd pubkey %ld\n", nc->dh.pub); + + newf = newframe(frame, NSdhx, 0, 0, sizeof(ulong), nil); + + nc->dh.sec = truerand(); + nc->dh.priv = dhgenkey(nc->dh.pub, nc->dh.sec, nc->dh.p); + pack(newf->data, newf->len, "k", dhgenkey(nc->dh.g, nc->dh.sec, nc->dh.p)); + sendp(egress, newf); + + if(debug) + fprint(2, "\tsent pubkey %ld\n", dhgenkey(nc->dh.g, nc->dh.sec, nc->dh.p)); + + break; + } + break; + case NCSConnected: + switch(frame->type){ + case NCinput: + unpack(frame->data, frame->len, "k", &kdown); + + if(debug) + fprint(2, "\t%.*lub\n", sizeof(kdown)*8, kdown); + + break; + case NCbuhbye: + popconn(nc); + free(nc); + break; } break; } - +discard: free(frame); } } @@ -71,6 +165,7 @@ threadnetsend(void *arg) { uchar buf[MTU]; int fd, n; + ushort rport, lport; Frame *frame; threadsetname("threadnetsend"); @@ -79,9 +174,18 @@ threadnetsend(void *arg) while((frame = recvp(egress)) != nil){ n = pack(buf, sizeof buf, "F", frame); - free(frame); if(write(fd, buf, n) != n) sysfatal("write: %r"); + + if(debug){ + rport = frame->udp.rport[0]<<8 | frame->udp.rport[1]; + lport = frame->udp.lport[0]<<8 | frame->udp.lport[1]; + fprint(2, "%I!%ud → %I!%ud | sent type %ud seq %ud ack %ud len %ud\n", + frame->udp.laddr, lport, frame->udp.raddr, rport, + frame->type, frame->seq, frame->ack, frame->len); + } + + free(frame); } } @@ -148,19 +252,16 @@ threadsim(void *) void fprintstats(int fd) { - ulong nparties = 0; + usize nparties = 0; Party *p; 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, 0UL, lobby->cap, -// nparties, 0UL); + fprint(fd, "curconns %lld\n" + "maxconns %lld\n" + "nparties %lld\n", + nconns, maxconns, nparties); } void @@ -172,10 +273,10 @@ fprintstates(int fd) for(p = theparty.next; p != &theparty; p = p->next, i++){ for(s = &p->u->ships[0]; s-p->u->ships < nelem(p->u->ships); s++){ - fprint(fd, "%lud s%lld k%d p %v v %v θ %g ω %g m %g f %d\n", + fprint(fd, "%ld s%lld k%d p %v v %v θ %g ω %g m %g f %d\n", i, s-p->u->ships, s->kind, s->p, s->v, s->θ, s->ω, s->mass, s->fuel); } - fprint(fd, "%lud S p %v m %g\n", i, p->u->star.p, p->u->star.mass); + fprint(fd, "%ld S p %v m %g\n", i, p->u->star.p, p->u->star.mass); } } diff --git a/net.c b/net.c new file mode 100644 index 0000000..d645eb4 --- /dev/null +++ b/net.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include +#include +#include "dat.h" +#include "fns.h" + +/* DHX */ + +void +dhgenpg(ulong *p, ulong *g) +{ + static ulong P = 97; + static ulong G = 71; + + *p = P; + *g = G; +} + +/* + * x = g^k mod p + */ +ulong +dhgenkey(ulong g, ulong k, ulong p) +{ + ulong r, y; + + y = 1; + + while(k > 0){ + r = k % 2; + if(r == 1) + y = y*g % p; + g = g*g % p; + k /= 2; + } + return y; +} + +/* NetConn */ + +NetConn * +newnetconn(NCState s, Udphdr *u) +{ + NetConn *nc; + + nc = emalloc(sizeof(NetConn)); + memset(nc, 0, sizeof(NetConn)); + if(u != nil) + memmove(&nc->udp, u, Udphdrsize); + nc->state = s; + + return nc; +} + +void +delnetconn(NetConn *nc) +{ + free(nc); +} + +/* Frame */ + +Frame * +newframe(Frame *pf, u8int type, u32int seq, u32int ack, u16int len, uchar *data) +{ + Frame *f; + + f = emalloc(sizeof(Frame)+len); + f->id = ProtocolID; + f->type = type; + if(pf != nil){ + memmove(&f->udp, &pf->udp, Udphdrsize); + f->seq = pf->seq+1; + f->ack = pf->seq; + }else{ + memset(&f->udp, 0, Udphdrsize); + f->seq = seq; + f->ack = ack; + } + f->len = len; + if(data != nil) + memmove(f->data, data, f->len); + + return f; +} + +void +delframe(Frame *f) +{ + free(f); +} diff --git a/pack.c b/pack.c index 08405ec..4680d73 100644 --- a/pack.c +++ b/pack.c @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -87,6 +86,7 @@ vpack(uchar *p, int n, char *fmt, va_list a) if(p+Framehdrsize+F->len > e) goto err; + put4(p, F->id), p += 4; *p++ = F->type; put4(p, F->seq), p += 4; put4(p, F->ack), p += 4; @@ -156,6 +156,7 @@ vunpack(uchar *p, int n, char *fmt, va_list a) if(F == nil) F = va_arg(a, Frame*); + F->id = get4(p), p += 4; F->type = *p++; F->seq = get4(p), p += 4; F->ack = get4(p), p += 4; -- cgit v1.2.3