ref: 1c2e71622257f7c2bc0d962bc3875358be9c82c5
parent: 2501a66f28dfc3bd04f8e83124ba5003583524bc
author: qwx <qwx@sciops.net>
date: Sun Apr 4 08:24:57 EDT 2021
Tmove/Tmovenear and protocol adjustments - Tmove to move to target node and Tmovenear to move towards target object; these two are different in that clicking inside an object implies finding the closest free and reachable spot near the object, which jps cannot handle. we already employ some shitty heuristics which don't really work well. the pathfinding system will have to be changed to handle both cases since one is a general case of the other. - terminate messages - put message size inside header, check it, and use that; we used to attempt to parse the entire message buffer, which is obviously wrong - T* values should not begin with 0 to avoid weird undetected bugs - allow spaces in packing strings for readability
--- a/com.c
+++ b/com.c
@@ -6,11 +6,11 @@
#include "fns.h"
enum{
- Hdrsz = 4,
+ Hdrsz = 2,
};
typedef struct Header Header;
struct Header{
- int empty;
+ ushort size;
};
static int
@@ -20,10 +20,12 @@
sz = 0;
for(;;){
+ n = 0;
switch(*fmt++){
default: sysfatal("vunpack: unknown format %c", fmt[-1]);
error: werrstr("vunpack: truncated message"); return -1;
case 0: return sz;
+ case ' ': break;
case 'h': n = sizeof(u8int); if(p + n > e) goto error;
*va_arg(a, int*) = GBIT8(p); p += n;
break;
@@ -30,9 +32,12 @@
case 's': n = sizeof(u16int); if(p + n > e) goto error;
*va_arg(a, int*) = GBIT16(p); p += n;
break;
- case 'l': n = sizeof(u32int); if(p + n > e) goto error;
+ case 'd': n = sizeof(u32int); if(p + n > e) goto error;
*va_arg(a, int*) = GBIT32(p); p += n;
break;
+ case 'l': n = sizeof(u32int); if(p + n > e) goto error;
+ *va_arg(a, long*) = GBIT32(p); p += n;
+ break;
case 'v': n = sizeof(u64int); if(p + n > e) goto error;
*va_arg(a, vlong*) = GBIT64(p); p += n;
break;
@@ -53,30 +58,86 @@
return n;
}
-static int
-reqmovenear(uchar *p, uchar *e)
+static Mobj *
+getmobj(Mobj *r)
{
- USED(p, e);
- return 0;
+ int n;
+ Mobj *mo;
+ Team *t;
+
+ n = r->idx >> Teamshift & Nteam - 1;
+ if(n > nteam){
+ werrstr("invalid team number %d", n);
+ return nil;
+ }
+ t = teams + n;
+ n = r->idx & Teamidxmask;
+ if(n > t->sz || (mo = t->mo[n]) == nil){
+ werrstr("obj index %d out of bounds", n);
+ return nil;
+ }
+ if(mo->idx != r->idx || mo->uuid != r->uuid
+ || mo->x != r->x || mo->y != r->y){
+ werrstr("phase error: %s at %d,%d has %#ux,%ld, req has %d,%d %#ux,%ld",
+ mo->o->name, mo->x, mo->y, mo->idx, mo->uuid,
+ r->x, r->y, r->idx, r->uuid);
+ return nil;
+ }
+ return mo;
}
static int
-reqmove(uchar *p, uchar *e)
+reqmovenear(uchar *p, uchar *e)
{
- USED(p, e);
- return 0;
+ int n;
+ Point click;
+ Mobj reqm, reqt, *mo, *tgt;
+
+ if((n = unpack(p, e, "dldd dd dldd",
+ &reqm.idx, &reqm.uuid, &reqm.x, &reqm.y,
+ &click.x, &click.y,
+ &reqt.idx, &reqt.uuid, &reqt.x, &reqt.y)) < 0)
+ goto error;
+ if((mo = getmobj(&reqm)) == nil)
+ goto error;
+ if((tgt = getmobj(&reqt)) == nil)
+ goto error;
+ if(click.x >= nodemapwidth || click.y >= nodemapheight){
+ werrstr("reqmove: invalid location %d,%d", click.x, click.y);
+ return -1;
+ }
+ moveone(click, mo, tgt);
+ return n;
+error:
+ return -1;
}
static int
-reqpause(uchar *p, uchar *e)
+reqmove(uchar *p, uchar *e)
{
- int dicks;
+ int n;
+ Point tgt;
+ Mobj reqm, *mo;
- /* FIXME: just a usage example, we don't really want dicks */
- if(unpack(p, e, "l", &dicks) < 0){
- fprint(2, "reqpause: %r\n");
+ if((n = unpack(p, e, "dldd dd",
+ &reqm.idx, &reqm.uuid, &reqm.x, &reqm.y,
+ &tgt.x, &tgt.y)) < 0)
+ goto error;
+ if((mo = getmobj(&reqm)) == nil)
+ goto error;
+ if(tgt.x >= nodemapwidth || tgt.y >= nodemapheight){
+ werrstr("reqmove: invalid target %d,%d", tgt.x, tgt.y);
return -1;
}
+ moveone(tgt, mo, nil);
+ return n;
+error:
+ return -1;
+}
+
+static int
+reqpause(uchar *, uchar *)
+{
pause ^= 1;
return 0;
}
@@ -84,9 +145,12 @@
static int
readhdr(Msg *m, Header *h)
{
- USED(h);
- if(m->sz <= Hdrsz)
+ if(unpack(m->buf, m->buf + m->sz, "s", &h->size) < 0
+ || h->size <= 0
+ || h->size != m->sz - Hdrsz){
+ werrstr("readhdr: malformed message");
return -1;
+ }
return 0;
}
@@ -98,10 +162,12 @@
int (*fn)(uchar*, uchar*);
Header h;
- if(readhdr(m, &h) < 0)
+ if(readhdr(m, &h) < 0){
+ dprint("parsemsg: %r\n");
return -1;
+ }
p = m->buf + Hdrsz;
- e = p + sizeof(m->buf) - Hdrsz;
+ e = m->buf + m->sz;
while(p < e){
type = *p++;
switch(type){
@@ -108,10 +174,14 @@
case Tpause: fn = reqpause; break;
case Tmove: fn = reqmove; break;
case Tmovenear: fn = reqmovenear; break;
- default: dprint("parse: invalid message type %ux\n", type); return -1;
+ case Teom:
+ if(p < e)
+ dprint("parsemsg: trailing data\n");
+ return 0;
+ default: dprint("parsemsg: invalid message type %ux\n", type); return -1;
}
if((n = fn(p, e)) < 0)
- dprint("parse: %r\n");
+ dprint("parsemsg: %r\n");
else
p += n;
}
@@ -134,9 +204,11 @@
copy: if(p + n > e) sysfatal("vpack: buffer overflow");
memcpy(p, u, n); p += n; break;
case 0: return sz;
+ case ' ': break;
case 'h': v = va_arg(a, int); PBIT8(u, v); n = sizeof(u8int); goto copy;
case 's': v = va_arg(a, int); PBIT16(u, v); n = sizeof(u16int); goto copy;
- case 'l': v = va_arg(a, int); PBIT32(u, v); n = sizeof(u32int); goto copy;
+ case 'd': v = va_arg(a, int); PBIT32(u, v); n = sizeof(u32int); goto copy;
+ case 'l': v = va_arg(a, long); PBIT32(u, v); n = sizeof(u32int); goto copy;
case 'v': w = va_arg(a, vlong); PBIT64(u, w); n = sizeof(u64int); goto copy;
}
sz += n;
@@ -146,18 +218,27 @@
static void
newmsg(Msg *m)
{
- Header h;
-
- USED(h);
m->sz += Hdrsz;
}
static int
-pack(Msg *m, char *fmt, ...)
+pack(uchar *p, uchar *e, char *fmt, ...)
{
int n;
va_list a;
+ va_start(a, fmt);
+ n = vpack(p, e, fmt, a);
+ va_end(a);
+ return n;
+}
+
+static int
+packmsg(Msg *m, char *fmt, ...)
+{
+ int n;
+ va_list a;
+
if(m->sz == 0)
newmsg(m);
va_start(a, fmt);
@@ -168,15 +249,23 @@
return n;
}
+void
+endmsg(Msg *m)
+{
+ packmsg(m, "h", Teom);
+ pack(m->buf, m->buf + Hdrsz, "s", m->sz - Hdrsz);
+}
+
int
-sendmovenear(Mobj *mo, Point click, Mobj *target)
+sendmovenear(Mobj *mo, Point click, Mobj *tgt)
{
Msg *m;
- /* FIXME */
m = getclbuf();
- USED(mo, click, target);
- if(pack(m, "h", Tmovenear) < 0){
+ if(packmsg(m, "h dldd dd dldd", Tmovenear,
+ mo->idx, mo->uuid, mo->x, mo->y,
+ click.x, click.y,
+ tgt->idx, tgt->uuid, tgt->x, tgt->y) < 0){
fprint(2, "sendmovenear: %r\n");
return -1;
}
@@ -184,14 +273,14 @@
}
int
-sendmove(Mobj *mo, Point target)
+sendmove(Mobj *mo, Point tgt)
{
Msg *m;
- /* FIXME */
m = getclbuf();
- USED(mo, target);
- if(pack(m, "h", Tmove) < 0){
+ if(packmsg(m, "h dldd dd", Tmove,
+ mo->idx, mo->uuid, mo->x, mo->y,
+ tgt.x, tgt.y) < 0){
fprint(2, "sendmove: %r\n");
return -1;
}
@@ -204,7 +293,7 @@
Msg *m;
m = getclbuf();
- if(pack(m, "hl", Tpause, 0) < 0){
+ if(packmsg(m, "h", Tpause) < 0){
fprint(2, "sendpause: %r\n");
return -1;
}
--- a/dat.h
+++ b/dat.h
@@ -202,10 +202,11 @@
extern int scale;
enum{
- Tquit,
+ Tquit = 0x1f,
Tpause,
Tmove,
Tmovenear,
+ Teom,
Nbuf = 4096,
};
--- a/drw.c
+++ b/drw.c
@@ -79,8 +79,6 @@
sendmovenear(selected[0], p, mo);
else
sendmove(selected[0], p);
- /* FIXME: expunge */
- moveone(p, selected[0], mo);
}
static void
--- a/fns.h
+++ b/fns.h
@@ -2,6 +2,7 @@
Msg* readnet(void);
void initnet(char*);
int parsemsg(Msg*);
+void endmsg(Msg*);
int sendmovenear(Mobj*, Point, Mobj*);
int sendmove(Mobj*, Point);
int sendpause(void);
--- a/net.c
+++ b/net.c
@@ -61,6 +61,7 @@
{
if(clbuf.sz == 0)
return;
+ endmsg(&clbuf);
write(clpfd[0], clbuf.buf, clbuf.sz);
clbuf.sz = 0;
}