shithub: patch

ref: d26b21913c1d6ff92961286fe0159a79096b3613
dir: patch/doom-udpip

View raw version
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);