shithub: patch

ref: bef4378c5cac18cea163dcdd6aea424e08e56ebf
dir: /doom-udpip/

View raw version
diff 790a516884e45ee2a3a11b915f5e125a0ccb02ca uncommitted
--- a/sys/src/games/doom/i_net.c
+++ b/sys/src/games/doom/i_net.c
@@ -20,142 +20,296 @@
 //
 //-----------------------------------------------------------------------------
 
-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 <thread.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)
+enum{
+	HDRSZ = 16+16+16+2+2	/* sizeof Udphdr w/o padding */
+};
+
+static char lsrv[6] = "666";
+
+struct Addr{
+	Udphdr h;
+	char srv[6];	/* convenience */
+	int ready;	/* is connected to udp!*!lsrv */
+	long called;
+};
+static Addr raddr[MAXNETNODES];
+
+static int ucfd;
+static int udfd;
+static int upfd[2];
+static int upid;
+
+
+static void
+conreq(doomdata_t *d)
 {
-printf("PORTME i_net.c I_InitNetwork (use 9P)\n");
+	int fd;
+	long t;
+	char ip[64];
+	Addr *p;
 
-	doomcom = malloc (sizeof(*doomcom));
-	memset (doomcom, 0, sizeof(*doomcom));
+	p = &raddr[doomcom->remotenode];
 
-	/* set up for network */
-	doomcom->ticdup = 1;
-	doomcom->extratics = 0;
+	t = time(nil);
+	if(t - p->called < 1)
+		return;
 
-//	netsend = PacketSend;
-//	netget = PacketGet;
-//	netgame = true;
+	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;
+}
 
-	/* parse player number and host list */
-//	doomcom->consoleplayer = myargv[i+1][0]-'1';
+static void
+dsend(void)
+{
+	int i;
+	uchar buf[HDRSZ+sizeof(doomdata_t)];
+	doomdata_t d;
 
-	doomcom->numnodes = 1;	// this node for sure
+	hnputl(&d.checksum, netbuffer->checksum);
+	d.player = netbuffer->player;
+	d.retransmitfrom = netbuffer->retransmitfrom;
+	d.starttic = netbuffer->starttic;
+	d.numtics = netbuffer->numtics;
 
-	doomcom->id = DOOMCOM_ID;
-	doomcom->numplayers = doomcom->numnodes;
+	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;
-    }
+	if(!raddr[doomcom->remotenode].ready){
+		conreq(&d);
+		return;
+	}
+	memcpy(buf, &raddr[doomcom->remotenode].h, HDRSZ);
+	memcpy(buf+HDRSZ, &d, sizeof d);
 
-    netsend = PacketSend;
-    netget = PacketGet;
-    netgame = true;
+	i = doomcom->datalength + HDRSZ;
+	if(write(udfd, buf, i) != i)
+		sysfatal("dsend: %r");
+}
 
-    // parse player number and host list
-    doomcom->consoleplayer = myargv[i+1][0]-'1';
+static void
+drecv(void)
+{
+	int n;
+	ushort i;
+	doomdata_t d;
 
-    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(filelength(upfd[1]) < 1){
+		doomcom->remotenode = -1;
+		return;
 	}
-	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];
+	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;
 	}
-	doomcom->numnodes++;
-    }
-	
-    doomcom->id = DOOMCOM_ID;
-    doomcom->numplayers = doomcom->numnodes;
-*/
 }
 
+static void
+uproc(void*)
+{
+	int n;
+	ushort i;
+	uchar buf[HDRSZ+sizeof(doomdata_t)];
+	Udphdr h;
 
-void I_NetCmd (void)
+	upid = getpid();
+	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)
-    {
-	netsend ();
-    }
-    else if (doomcom->command == CMD_GET)
-    {
-	netget ();
-    }
-    else
-	I_Error ("Bad net cmd: %i\n",doomcom->command);
-*/
+	if(doomcom->command == CMD_SEND)
+		dsend();
+	else if(doomcom->command == CMD_GET)
+		drecv();
+	else
+		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)
+{
+	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(procrfork(uproc, nil, mainstacksize, RFFDG) < 0)
+		sysfatal("procrfork: %r");
+}
+
+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();
+
+	netgame = true;
 }
--- a/sys/src/games/doom/i_net.h
+++ b/sys/src/games/doom/i_net.h
@@ -35,6 +35,7 @@
 
 void I_InitNetwork (void);
 void I_NetCmd (void);
+void I_ShutdownNet (void);
 
 
 #endif
--- a/sys/src/games/doom/i_system.c
+++ b/sys/src/games/doom/i_system.c
@@ -6,6 +6,7 @@
 #include "i_system.h"
 #include "i_sound.h"
 #include "i_video.h"
+#include "i_net.h"
 
 #include "d_main.h"
 #include "d_net.h"
@@ -42,6 +43,7 @@
 void I_Quit (void)
 {
 	D_QuitNetGame ();
+	I_ShutdownNet();
 	I_ShutdownSound();
 	I_ShutdownMusic();
 	M_SaveDefaults ();
@@ -86,6 +88,7 @@
 	G_CheckDemoStatus();
 
     D_QuitNetGame ();
+    I_ShutdownNet();
     I_ShutdownGraphics();
 
     exits("I_Error");
--- a/sys/src/games/doom/w_wad.h
+++ b/sys/src/games/doom/w_wad.h
@@ -67,6 +67,8 @@
 void*	W_CacheLumpNum (int lump, int tag);
 void*	W_CacheLumpName (char* name, int tag);
 
+vlong	filelength(int);
+
 #endif
 //-----------------------------------------------------------------------------
 //