ref: 7caa9585434c771bea1aaf6d3317b969df5afa9d
dir: /doom-udpip/
port udp/ip code from release. this works, but parts of the code suck and need to be altered. what sucks is that the doom networking protocol is shit. it's a peer-to-peer thing where each node needs to send frame information (ticcmd's) to every other node, and receive ticcmd's from every other node. any node that has a slower connection or is a slower machine will bring the game down for everyone. also, high bandwidth required. shitfuck n2: no port uses this protocol, since it sucks, and everyone implements their own incompatible crap, so no one port can talk to another, besides maybe the ports back to DOS. the code in i_net.c is unlikely to change too much though, unless this implementation is amended. one idea is to ask for chocolate-doom's networking protocol specs. chocolate-doom works fairly well, and supports a bunch of different OS', including openbsd, and being able to connect with 9front doom to another OS' shit is advanteageous, at least because live servers with bunches of players will be accessible. 9front doom and chocolate-doom _should_ be compatible, but idk. as it is, sdldoom might be able to connect to 9front doom with this patch, but good luck making sdldoom work. player 0 is special, and sets the game settings, sending them to the other nodes. testing this is more difficult without other patches because of the issues in the sound code, so try with doom-sndmus.patch and doom-sleep.patch. syntax: doom [-srv port] [-pn 0-3] [-net host!port...] defaults: udp port 666, player number 0 example for a 3 player game, two nodes being on the same host (for shits): u14% games/doom -altdeath -nomonsters -warp7 -net u6!666 u14!667 u6% games/doom -pn 1 -net u14!666 u14!667 u14-1% games/doom -pn 2 -srv 667 -net u14!666 u6!666 TODO: cf FIXME's in the code, conreq shit, more testing(?) diff -Naur a/sys/src/games/doom/i_net.c b/sys/src/games/doom/i_net.c --- a/sys/src/games/doom/i_net.c Wed Jan 18 01:13:24 2012 +++ b/sys/src/games/doom/i_net.c Wed Sep 16 06:45:07 2015 @@ -20,142 +20,298 @@ // //----------------------------------------------------------------------------- -static const char -rcsid[] = "$Id: m_bbox.c,v 1.1 1997/02/03 22:45:10 b1 Exp $"; - #include "doomdef.h" #include "doomstat.h" - -// #include "i_system.h" -// #include "d_event.h" -#include "d_net.h" +#include <bio.h> +#include <ndb.h> +#include <ip.h> #include "m_argv.h" - +#include "i_system.h" +#include "d_net.h" #include "i_net.h" +#include "w_wad.h" +typedef struct Addr Addr; -// -// I_InitNetwork -// -void I_InitNetwork (void) -{ -printf("PORTME i_net.c I_InitNetwork (use 9P)\n"); +enum{ + HDRSZ = 16+16+16+2+2 /* sizeof Udphdr w/o padding */ +}; - doomcom = malloc (sizeof(*doomcom)); - memset (doomcom, 0, sizeof(*doomcom)); +static char lsrv[6] = "666"; - /* set up for network */ - doomcom->ticdup = 1; - doomcom->extratics = 0; +struct Addr{ + Udphdr h; + char srv[6]; /* convenience */ + int ready; /* is connected to udp!*!lsrv */ + long called; +}; +static Addr raddr[MAXNETNODES]; -// netsend = PacketSend; -// netget = PacketGet; -// netgame = true; +static int ucfd; +static int udfd; +static int upfd[2]; +static int upid; - /* parse player number and host list */ -// doomcom->consoleplayer = myargv[i+1][0]-'1'; - doomcom->numnodes = 1; // this node for sure +static void +conreq(doomdata_t *d) +{ + int fd; + long t; + char ip[64]; + Addr *p; + + p = &raddr[doomcom->remotenode]; + + t = time(nil); + if(t - p->called < 1) + return; + + snprint(ip, sizeof ip, "%I", p->h.raddr); + if((fd = dial(netmkaddr(ip, "udp", p->srv), lsrv, nil, nil)) < 0) + sysfatal("dial: %r"); + if(write(fd, d, doomcom->datalength) != doomcom->datalength) + sysfatal("conreq: %r"); + close(fd); + p->called = t; +} - doomcom->id = DOOMCOM_ID; - doomcom->numplayers = doomcom->numnodes; +static void +dsend(void) +{ + int i; + uchar buf[HDRSZ+sizeof(doomdata_t)]; + doomdata_t d; + + hnputl(&d.checksum, netbuffer->checksum); + d.player = netbuffer->player; + d.retransmitfrom = netbuffer->retransmitfrom; + d.starttic = netbuffer->starttic; + d.numtics = netbuffer->numtics; + + for(i = 0; i < netbuffer->numtics; i++){ + d.cmds[i].forwardmove = netbuffer->cmds[i].forwardmove; + d.cmds[i].sidemove = netbuffer->cmds[i].sidemove; + hnputs(&d.cmds[i].angleturn, netbuffer->cmds[i].angleturn); + hnputs(&d.cmds[i].consistancy, netbuffer->cmds[i].consistancy); + d.cmds[i].chatchar = netbuffer->cmds[i].chatchar; + d.cmds[i].buttons = netbuffer->cmds[i].buttons; + } -/* - boolean trueval = true; - int i; - int p; - struct hostent* hostentry; // host information entry - - doomcom = malloc (sizeof (*doomcom) ); - memset (doomcom, 0, sizeof(*doomcom) ); - - // set up for network - i = M_CheckParm ("-dup"); - if (i && i< myargc-1) - { - doomcom->ticdup = myargv[i+1][0]-'0'; - if (doomcom->ticdup < 1) - doomcom->ticdup = 1; - if (doomcom->ticdup > 9) - doomcom->ticdup = 9; - } - else - doomcom-> ticdup = 1; - - if (M_CheckParm ("-extratic")) - doomcom-> extratics = 1; - else - doomcom-> extratics = 0; - - p = M_CheckParm ("-port"); - if (p && p<myargc-1) - { - DOOMPORT = atoi (myargv[p+1]); - printf ("using alternate port %i\n",DOOMPORT); - } - - // parse network game options, - // -net <consoleplayer> <host> <host> ... - i = M_CheckParm ("-net"); - if (!i) - { - // single player game - netgame = false; - doomcom->id = DOOMCOM_ID; - doomcom->numplayers = doomcom->numnodes = 1; - doomcom->deathmatch = false; - doomcom->consoleplayer = 0; - return; - } - - netsend = PacketSend; - netget = PacketGet; - netgame = true; - - // parse player number and host list - doomcom->consoleplayer = myargv[i+1][0]-'1'; - - doomcom->numnodes = 1; // this node for sure - - i++; - while (++i < myargc && myargv[i][0] != '-') - { - sendaddress[doomcom->numnodes].sin_family = AF_INET; - sendaddress[doomcom->numnodes].sin_port = htons(DOOMPORT); - if (myargv[i][0] == '.') - { - sendaddress[doomcom->numnodes].sin_addr.s_addr - = inet_addr (myargv[i]+1); + if(!raddr[doomcom->remotenode].ready){ + conreq(&d); + return; } + memcpy(buf, &raddr[doomcom->remotenode].h, HDRSZ); + memcpy(buf+HDRSZ, &d, sizeof d); + + i = doomcom->datalength + HDRSZ; + if(write(udfd, buf, i) != i) + sysfatal("dsend: %r"); +} + +static void +drecv(void) +{ + int n; + ushort i; + doomdata_t d; + + if(filelength(upfd[1]) < 1){ + doomcom->remotenode = -1; + return; + } + if((n = read(upfd[1], &d, sizeof d)) <= 0 + || read(upfd[1], &i, sizeof i) <= 0) + sysfatal("drecv: %r"); + + doomcom->remotenode = i; + doomcom->datalength = n; + + /* FIXME: proper read/write from/to struct */ + netbuffer->checksum = nhgetl(&d.checksum); + netbuffer->player = d.player; + netbuffer->retransmitfrom = d.retransmitfrom; + netbuffer->starttic = d.starttic; + netbuffer->numtics = d.numtics; + for(i = 0; i < netbuffer->numtics; i++){ + netbuffer->cmds[i].forwardmove = d.cmds[i].forwardmove; + netbuffer->cmds[i].sidemove = d.cmds[i].sidemove; + netbuffer->cmds[i].angleturn = nhgets(&d.cmds[i].angleturn); + netbuffer->cmds[i].consistancy = nhgets(&d.cmds[i].consistancy); + netbuffer->cmds[i].chatchar = d.cmds[i].chatchar; + netbuffer->cmds[i].buttons = d.cmds[i].buttons; + } +} + +static void +uproc(void) +{ + int n; + ushort i; + uchar buf[HDRSZ+sizeof(doomdata_t)]; + Udphdr h; + + for(;;){ + if((n = read(udfd, buf, sizeof buf)) <= 0) + break; + memcpy(&h, buf, HDRSZ); + + for(i = 0; i < doomcom->numnodes; i++) + if(equivip6(h.raddr, raddr[i].h.raddr) + && nhgets(h.rport) == nhgets(raddr[i].h.rport)) + break; + if(i == doomcom->numnodes) + continue; /* ignore messages from strangers */ + if(!raddr[i].ready){ /* FIXME: urgh */ + raddr[i].ready++; + memcpy(&raddr[i].h, &h, sizeof h); + } + + if(write(upfd[0], buf+HDRSZ, n - HDRSZ) != n - HDRSZ + || write(upfd[0], &i, sizeof i) != sizeof i) + break; + } +} + +void +I_NetCmd(void) +{ + if(doomcom->command == CMD_SEND) + dsend(); + else if(doomcom->command == CMD_GET) + drecv(); else - { - hostentry = gethostbyname (myargv[i]); - if (!hostentry) - I_Error ("gethostbyname: couldn't find %s", myargv[i]); - sendaddress[doomcom->numnodes].sin_addr.s_addr - = *(int *)hostentry->h_addr_list[0]; - } - doomcom->numnodes++; - } - - doomcom->id = DOOMCOM_ID; - doomcom->numplayers = doomcom->numnodes; -*/ + I_Error("invalid netcmd %d", doomcom->command); +} + +void +I_ShutdownNet(void) +{ + postnote(PNPROC, upid, "shutdown"); + close(upfd[0]); + close(upfd[1]); + close(udfd); + close(ucfd); +} + +static void +initudp(void) +{ + int pid; + char data[64], adir[40]; + + /* FIXME */ + //if(myipaddr(raddr[0].h.raddr, nil) < 0) + // sysfatal("myipaddr: %r"); + + if((ucfd = announce(netmkaddr("*", "udp", lsrv), adir)) < 0) + sysfatal("announce: %r"); + if(fprint(ucfd, "headers") < 0) + sysfatal("failed to set headers mode: %r"); + snprint(data, sizeof data, "%s/data", adir); + if((udfd = open(data, ORDWR)) < 0) + sysfatal("open: %r"); + + if(pipe(upfd) < 0) + sysfatal("pipe: %r"); + if((pid = rfork(RFPROC|RFMEM|RFFDG)) == 0){ + uproc(); + exits(nil); + } + upid = pid; +} + +static void +csip(char *s, Addr *a) /* raddr!rsrv */ +{ + int fd, n; + char buf[128], *f[3]; + + /* FIXME: get netmnt... */ + + if((fd = open("/net/cs", ORDWR)) < 0) + sysfatal("open: %r"); + + snprint(buf, sizeof buf, "udp!%s", s); + n = strlen(buf); + if(write(fd, buf, n) != n) + sysfatal("translating %s: %r", s); + + seek(fd, 0, 0); + if((n = read(fd, buf, sizeof(buf)-1)) <= 0) + sysfatal("reading cs tables: %r"); + buf[n] = 0; + close(fd); + + if(getfields(buf, f, 3, 1, " !") < 2) + sysfatal("bad cs entry %s", buf); + + if(parseip(a->h.raddr, f[1]) < 0) + sysfatal("parseip: %r"); + hnputs(a->h.rport, atoi(f[2])); /* FIXME */ + strncpy(a->srv, f[2], sizeof(a->srv)-1); +} + +static int +netopts(void) +{ + int i; + + if((i = M_CheckParm("-dup")) && i < myargc - 1){ + doomcom->ticdup = myargv[i+1][0] - '0'; + if(doomcom->ticdup < 1) + doomcom->ticdup = 1; + if(doomcom->ticdup > 9) + doomcom->ticdup = 9; + } + + if(M_CheckParm("-extratic")) + doomcom->extratics = 1; + + if((i = M_CheckParm("-srv")) && i < myargc - 1) + strncpy(lsrv, myargv[i+1], sizeof(lsrv)-1); + + /* [0-3], default 0; player 0 is special */ + if((i = M_CheckParm("-pn")) && i < myargc - 1) + doomcom->consoleplayer = myargv[i+1][0] - '0'; + + /* FIXME: d_net.c: don't use remoteaddr=0 as special case (max+1?) */ + /* remote host address list: -net raddr!rsrv.. */ + if((i = M_CheckParm("-net")) == 0){ + /* single player game */ + doomcom->id = DOOMCOM_ID; + doomcom->numplayers = doomcom->numnodes = 1; + doomcom->deathmatch = false; + netgame = false; + return -1; + } + doomcom->numnodes++; /* raddr[0] is special cased because ??? */ + while(++i < myargc && myargv[i][0] != '-'){ + csip(myargv[i], &raddr[doomcom->numnodes]); + doomcom->numnodes++; + } + + return 0; } +void +I_InitNetwork(void) +{ + doomcom = malloc(sizeof *doomcom); + memset(doomcom, 0, sizeof *doomcom); + + doomcom->ticdup = 1; + doomcom->extratics = 0; + if(netopts() < 0) + return; + if(doomcom->numnodes < 2) + I_Error("netgame with a single node"); + doomcom->id = DOOMCOM_ID; + doomcom->numplayers = doomcom->numnodes; + + fmtinstall('I', eipfmt); + initudp(); -void I_NetCmd (void) -{ -/* - if (doomcom->command == CMD_SEND) - { - netsend (); - } - else if (doomcom->command == CMD_GET) - { - netget (); - } - else - I_Error ("Bad net cmd: %i\n",doomcom->command); -*/ + netgame = true; } diff -Naur a/sys/src/games/doom/i_net.h b/sys/src/games/doom/i_net.h --- a/sys/src/games/doom/i_net.h Wed Jan 18 01:13:23 2012 +++ b/sys/src/games/doom/i_net.h Wed Sep 16 06:36:09 2015 @@ -35,6 +35,7 @@ void I_InitNetwork (void); void I_NetCmd (void); +void I_ShutdownNet (void); #endif diff -Naur a/sys/src/games/doom/i_system.c b/sys/src/games/doom/i_system.c --- a/sys/src/games/doom/i_system.c Wed Feb 5 08:58:15 2014 +++ b/sys/src/games/doom/i_system.c Wed Sep 16 06:36:09 2015 @@ -6,6 +6,7 @@ #include "i_system.h" #include "i_sound.h" #include "i_video.h" +#include "i_net.h" #include "d_net.h" #include "g_game.h" @@ -41,6 +42,7 @@ void I_Quit (void) { D_QuitNetGame (); + I_ShutdownNet(); I_ShutdownSound(); I_ShutdownMusic(); M_SaveDefaults (); @@ -85,6 +87,7 @@ G_CheckDemoStatus(); D_QuitNetGame (); + I_ShutdownNet(); I_ShutdownGraphics(); exits("I_Error"); diff -Naur a/sys/src/games/doom/w_wad.h b/sys/src/games/doom/w_wad.h --- a/sys/src/games/doom/w_wad.h Wed Jan 18 01:13:24 2012 +++ b/sys/src/games/doom/w_wad.h Wed Sep 16 06:38:33 2015 @@ -67,6 +67,7 @@ void* W_CacheLumpNum (int lump, int tag); void* W_CacheLumpName (char* name, int tag); +vlong filelength(int);