diff --git a/polymer/eduke32/Makefile b/polymer/eduke32/Makefile index 987adde48..03bc7eac1 100644 --- a/polymer/eduke32/Makefile +++ b/polymer/eduke32/Makefile @@ -18,7 +18,6 @@ USE_OPENGL = 1 NOASM = 0 LINKED_GTK = 0 BUILD32_ON_64 = 0 -RANCID_NETWORKING = 1 # Debugging/Build options RELEASE?=1 @@ -242,11 +241,7 @@ endif include Makefile.deps -ifneq (0,$(RANCID_NETWORKING)) - duke3d_h+=$(EINC)/mmulti_unstable.h -else - duke3d_h+=$(EINC)/mmulti.h -endif +duke3d_h+=$(EINC)/mmulti_unstable.h .PHONY: enginelib editorlib enginelib editorlib: @@ -257,7 +252,7 @@ endif $(MAKE) -C $(EROOT)/ "OBJ=../$(EOBJ)" \ SUPERBUILD=$(SUPERBUILD) POLYMOST=$(POLYMOST) DEBUGANYWAY=$(DEBUGANYWAY)\ USE_OPENGL=$(USE_OPENGL) BUILD32_ON_64=$(BUILD32_ON_64) \ - NOASM=$(NOASM) RELEASE=$(RELEASE) OPTLEVEL=$(OPTLEVEL) RANCID_NETWORKING=$(RANCID_NETWORKING) $@ + NOASM=$(NOASM) RELEASE=$(RELEASE) OPTLEVEL=$(OPTLEVEL) $@ ifeq ($(PRETTY_OUTPUT),1) printf "\033[K\033[0;35mChanging dir to \033[1;35m$(CURDIR)\033[0;35m \033[0m\n" endif diff --git a/polymer/eduke32/Makefile.msvc b/polymer/eduke32/Makefile.msvc index e878ceac2..19dd3e7df 100644 --- a/polymer/eduke32/Makefile.msvc +++ b/polymer/eduke32/Makefile.msvc @@ -30,7 +30,7 @@ DXROOT="U:\SDKs\Microsoft DirectX SDK (April 2007) MSSDKROOT="N:\Program Files\Microsoft Visual Studio 9.0\VC PLATFORMSDK="N:\Program Files\Microsoft Visual Studio 9.0\VC\PlatformSDK -ENGINEOPTS=/DSUPERBUILD /DPOLYMOST /DUSE_OPENGL /DRANCID_NETWORKING /DPOLYMER +ENGINEOPTS=/DSUPERBUILD /DPOLYMOST /DUSE_OPENGL /DPOLYMER CC=cl AS=ml diff --git a/polymer/eduke32/build/Makefile b/polymer/eduke32/build/Makefile index 9bb35b3b1..2f8fec3a9 100644 --- a/polymer/eduke32/build/Makefile +++ b/polymer/eduke32/build/Makefile @@ -17,7 +17,6 @@ PRETTY_OUTPUT = 1 # USE_OPENGL - enables OpenGL support in Polymost # NOASM - disables the use of inline assembly pragmas # LINKED_GTK - enables compile-time linkage to GTK -# RANCID_NETWORKING - enable network backend from rancidmeat port # SUPERBUILD ?= 1 @@ -27,7 +26,6 @@ USE_OPENGL ?= 1 NOASM ?= 0 LINKED_GTK ?= 0 BUILD32_ON_64 ?= 0 -RANCID_NETWORKING ?= 0 ifeq (0,$(USE_OPENGL)) POLYMER = 0 @@ -145,11 +143,7 @@ ifeq (1,$(POLYMER)) ENGINEOBJS+= $(OBJ)/polymer.$o endif -ifneq (0,$(RANCID_NETWORKING)) - ENGINEOBJS+= $(OBJ)/mmulti_unstable.$o -else - ENGINEOBJS+= $(OBJ)/mmulti.$o -endif +ENGINEOBJS+= $(OBJ)/mmulti_unstable.$o EDITOROBJS=$(OBJ)/build.$o \ $(OBJ)/config.$o diff --git a/polymer/eduke32/build/Makefile.deps b/polymer/eduke32/build/Makefile.deps index 1eb47e7ab..642fb3c1c 100644 --- a/polymer/eduke32/build/Makefile.deps +++ b/polymer/eduke32/build/Makefile.deps @@ -20,9 +20,6 @@ $(OBJ)/kplib.$o: $(SRC)/kplib.c $(INC)/compat.h $(OBJ)/fastlz.$o: $(SRC)/fastlz.c $(INC)/fastlz.h $(OBJ)/lzwnew.$o: $(SRC)/lzwnew.c $(OBJ)/md4.$o: $(SRC)/md4.c $(INC)/md4.h $(INC)/compat.h -$(OBJ)/mmulti_null.$o: $(SRC)/mmulti_null.c $(INC)/mmulti.h -$(OBJ)/mmulti.$o: $(SRC)/mmulti.c $(INC)/mmulti.h -# $(OBJ)/enet_mmulti.$o: $(SRC)/enet_mmulti.cpp $(INC)/enet_mmulti.h $(OBJ)/mmulti_unstable.$o: $(SRC)/mmulti_unstable.c $(INC)/mmulti_unstable.h $(OBJ)/osd.$o: $(SRC)/osd.c $(INC)/build.h $(INC)/osd.h $(INC)/compat.h $(INC)/baselayer.h $(OBJ)/pragmas.$o: $(SRC)/pragmas.c $(INC)/compat.h diff --git a/polymer/eduke32/build/Makefile.shared b/polymer/eduke32/build/Makefile.shared index d7fd388c0..8b3243215 100644 --- a/polymer/eduke32/build/Makefile.shared +++ b/polymer/eduke32/build/Makefile.shared @@ -163,10 +163,6 @@ endif BUILDCFLAGS+= -DRENDERTYPE$(RENDERTYPE)=1 -ifneq (0,$(RANCID_NETWORKING)) -# LIBS+= -lenet - BUILDCFLAGS+= -DRANCID_NETWORKING -endif ifneq (0,$(SUPERBUILD)) BUILDCFLAGS+= -DSUPERBUILD endif diff --git a/polymer/eduke32/build/include/mmulti.h b/polymer/eduke32/build/include/mmulti.h deleted file mode 100644 index 0103da68b..000000000 --- a/polymer/eduke32/build/include/mmulti.h +++ /dev/null @@ -1,33 +0,0 @@ -// mmulti.h - -#ifndef __mmulti_h__ -#define __mmulti_h__ - -#define MAXMULTIPLAYERS 16 - -extern int32_t myconnectindex, numplayers; -extern int32_t connecthead, connectpoint2[MAXMULTIPLAYERS]; -extern char syncstate; -extern int32_t natfree; //Addfaz NatFree - -int32_t initmultiplayersparms(int32_t argc, char **argv); -int32_t initmultiplayerscycle(void); - -void mmulti_initmultiplayers(int32_t argc, char **argv); -void mmulti_setpackettimeout(int32_t datimeoutcount, int32_t daresendagaincount); -void mmulti_uninitmultiplayers(void); -void mmulti_sendlogon(void); -void mmulti_sendlogoff(void); -int32_t mmulti_getoutputcirclesize(void); -void mmulti_sendpacket(int32_t other, char *bufptr, int32_t messleng); -int32_t mmulti_getpacket(int32_t *other, char *bufptr); -void mmulti_flushpackets(void); -void mmulti_generic(int32_t other, char *bufptr, int32_t messleng, int32_t command); -int32_t isvalidipaddress(char *st); - -void nfIncCP(void); //Addfaz NatFree -int32_t nfCheckHF (int32_t other); //Addfaz NatFree -int32_t nfCheckCP(int32_t other); //Addfaz NatFree - -#endif // __mmulti_h__ - diff --git a/polymer/eduke32/build/include/mmulti_unstable.h b/polymer/eduke32/build/include/mmulti_unstable.h index b5803e33c..8a89486a4 100644 --- a/polymer/eduke32/build/include/mmulti_unstable.h +++ b/polymer/eduke32/build/include/mmulti_unstable.h @@ -16,7 +16,7 @@ int32_t mmulti_getpacket(int32_t *other, char *bufptr); void mmulti_flushpackets(void); void mmulti_generic(int32_t other, char *bufptr, int32_t messleng, int32_t command); -extern int32_t natfree; +extern int32_t natfree, numplayers; #endif diff --git a/polymer/eduke32/build/src/mmulti.c b/polymer/eduke32/build/src/mmulti.c deleted file mode 100644 index a33d9a5a2..000000000 --- a/polymer/eduke32/build/src/mmulti.c +++ /dev/null @@ -1,914 +0,0 @@ -#include -#include -#include -#include - -#include "compat.h" - -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#include -#else -#include -#include -#ifndef __BEOS__ -#include -#endif -#ifdef __sun -#include -#endif -#include -#include -#include -#define SOCKET int32_t -#define INVALID_HANDLE_VALUE (-1) -#define INVALID_SOCKET (-1) -#define SOCKET_ERROR (-1) -#define closesocket close -#define ioctlsocket ioctl -#define LPHOSTENT struct hostent * - -#include -static int32_t GetTickCount(void) -{ - struct timeval tv; - int32_t ti; - if (gettimeofday(&tv,NULL) < 0) return 0; - // tv is sec.usec, GTC gives msec - ti = tv.tv_sec * 1000; - ti += tv.tv_usec / 1000; - return ti; -} -#endif - -#ifdef KSFORBUILD -# include "compat.h" -# include "baselayer.h" -# define printf initprintf -#endif - -#ifndef min -#define min(a,b) ((a)<(b)?(a):(b)) -#endif - -#define MAXPLAYERS 16 -#define MAXPAKSIZ 576 - - -#define PAKRATE 250 //Packet rate/sec limit ... necessary? -int32_t packetrate = PAKRATE; -#define SIMMIS 0 //Release:0 Test:100 Packets per 256 missed. -#define SIMLAG 0 //Release:0 Test: 10 Packets to delay receipt -#if (SIMLAG != 0) -static int32_t simlagcnt[MAXPLAYERS]; -static char simlagfif[MAXPLAYERS][SIMLAG+1][MAXPAKSIZ+2]; -#endif -#if ((SIMMIS != 0) || (SIMLAG != 0)) -#pragma message("\n\nWARNING! INTENTIONAL PACKET LOSS SIMULATION IS ENABLED!\nREMEMBER TO CHANGE SIMMIS&SIMLAG to 0 before RELEASE!\n\n") -#endif - -int32_t myconnectindex, numplayers; -int32_t connecthead, connectpoint2[MAXPLAYERS]; - -static int32_t tims, lastsendtims[MAXPLAYERS]; -static char pakbuf[MAXPAKSIZ]; - -#define FIFSIZ 512 //16384/40 = 6min:49sec -static int32_t ipak[MAXPLAYERS][FIFSIZ], icnt0[MAXPLAYERS]; -static int32_t opak[MAXPLAYERS][FIFSIZ], ocnt0[MAXPLAYERS], ocnt1[MAXPLAYERS]; -static char pakmem[4194304]; static int32_t pakmemi = 1; - -#define NETPORT 0x5bd9 -static SOCKET mysock; -static int32_t myip, myport = NETPORT, otherip[MAXPLAYERS], otherport[MAXPLAYERS]; -static int32_t snatchip = 0, snatchport = 0, danetmode = 255, netready = 0; - -#ifdef _WIN32 -int32_t wsainitialized = 0; -#endif - -/*Addfaz NatFree Start*/ -int32_t natfree; //NatFree mode flag -int32_t nfCurrentPlayer = 0; //Current NatFree player counter. Will only talk with one player at a time -int32_t nfFinished = 0; //Flag that determines NatFree has found all players and set the correct port numbers [normal routines can then take place] -int32_t HeardFrom[MAXPLAYERS]; //For connecthead -int32_t HeardFrom2[MAXPLAYERS]; //For others - -int32_t nfCheckCP(int32_t other) //Check if target player is our current NatFree Player -{ - if (!natfree || nfFinished) - return 1; - else if (nfCurrentPlayer == other) return 1; - - return 0; -} - -int32_t nfCheckHF(int32_t other) //function to check if we've heard from a player -{ - if (HeardFrom[other] == 1) - return 1; - else - return 0; -} - -void nfIncCP() //function to handle currentplayer increment -{ - if (natfree && !nfFinished) - { - nfCurrentPlayer++; //Increment player counter - if (nfCurrentPlayer == myconnectindex) nfCurrentPlayer++; //Bypass my index - if (nfCurrentPlayer >= numplayers) - { - nfFinished = 1; //Set NatFree finished flag. Perform non-natfree networking routines - initprintf("natfree: all players accounted for.\n"); - return; - } - } -} -/*Addfaz NatFree End*/ - -void netuninit() -{ - if (mysock != (SOCKET)INVALID_HANDLE_VALUE) closesocket(mysock); -#ifdef _WIN32 - if (wsainitialized) - WSACleanup(); -#endif -} - -static int32_t set_socket_blockmode(SOCKET socket, int32_t onOrOff) -{ -#ifdef _WIN32 - uint32_t flags; -#else - int32_t flags; -#endif - int32_t rc = 0; - - /* set socket to be (non-)blocking. */ - -#ifdef _WIN32 - flags = (onOrOff) ? 0 : 1; - rc = (ioctlsocket(socket, FIONBIO, (void *)&flags) == 0); -#else - flags = fcntl(socket, F_GETFL, 0); - if (flags != -1) - { - if (onOrOff) - flags &= ~O_NONBLOCK; - else - flags |= O_NONBLOCK; - rc = (fcntl(socket, F_SETFL, flags) == 0); - } -#endif - - return(rc); -} - -int32_t netinit(int32_t portnum) -{ - LPHOSTENT lpHostEnt; - char hostnam[256]; - struct sockaddr_in ip; -#ifdef __BEOS__ - int32_t i; -#endif - -#ifdef _WIN32 - if (wsainitialized == 0) - { - WSADATA ws; - - if (WSAStartup(0x101,&ws) == SOCKET_ERROR) return(0); - wsainitialized = 1; - } -#endif - - mysock = socket(AF_INET,SOCK_DGRAM,0); if (mysock == INVALID_SOCKET) return(0); -#ifdef __BEOS__ - i = 1; if (setsockopt(mysock,SOL_SOCKET,SO_NONBLOCK,&i,sizeof(i)) < 0) return(0); -#else -// i = 1; if (ioctlsocket(mysock,FIONBIO,(uint32_t *)&i) == SOCKET_ERROR) return(0); - if (!set_socket_blockmode(mysock,0)) return(0); -#endif - - ip.sin_family = AF_INET; - ip.sin_addr.s_addr = INADDR_ANY; - ip.sin_port = htons(portnum); - if (bind(mysock,(struct sockaddr *)&ip,sizeof(ip)) != SOCKET_ERROR) - { - myport = portnum; - if (gethostname(hostnam,sizeof(hostnam)) != SOCKET_ERROR) - if ((lpHostEnt = gethostbyname(hostnam))) - { - myip = ip.sin_addr.s_addr = *(int32_t *)lpHostEnt->h_addr; - printf("mmulti: This machine's IP is %s\n", inet_ntoa(ip.sin_addr)); - } - return(1); - } - return(0); -} - -int32_t netsend(int32_t other, char *dabuf, int32_t bufsiz) //0:buffer full... can't send -{ - struct sockaddr_in ip; - - if (!otherip[other]) return(0); - - /*Addfaz NatFree Start*/ - if (natfree && !nfFinished) - { - if (other == connecthead && !nfCheckHF(connecthead)) - return(0); //Only greet the connecthead if we've heard from them. - - if (myconnectindex != connecthead) - { - if (!nfCheckCP(other) && other != connecthead) - return(0); //Only connect to currentplayer or connecthead - else if (!nfCheckCP(other) && !nfCheckHF(other)) - return(0); - } - } - /*Addfaz NatFree End*/ - - ip.sin_family = AF_INET; - ip.sin_addr.s_addr = otherip[other]; - ip.sin_port = otherport[other]; - return(sendto(mysock,dabuf,bufsiz,0,(struct sockaddr *)&ip,sizeof(struct sockaddr_in)) != SOCKET_ERROR); -} - -int32_t netread(int32_t *other, char *dabuf, int32_t bufsiz) //0:no packets in buffer -{ - struct sockaddr_in ip; - int32_t i; - - i = sizeof(ip); - - if (recvfrom(mysock,dabuf,bufsiz,0,(struct sockaddr *)&ip,(socklen_t *)&i) == -1) return(0); -#if (SIMMIS > 0) - if ((rand()&255) < SIMMIS) return(0); -#endif - - snatchip = (int32_t)ip.sin_addr.s_addr; snatchport = (int32_t)ip.sin_port; - - (*other) = myconnectindex; - for (i=0; i 1) - i = simlagcnt[*other]%(SIMLAG+1); - *(int16_t *)&simlagfif[*other][i][0] = bufsiz; Bmemcpy(&simlagfif[*other][i][2],dabuf,bufsiz); - simlagcnt[*other]++; if (simlagcnt[*other] < SIMLAG+1) return(0); - i = simlagcnt[*other]%(SIMLAG+1); - bufsiz = *(int16_t *)&simlagfif[*other][i][0]; Bmemcpy(dabuf,&simlagfif[*other][i][2],bufsiz); -#endif - - return(1); -} - -int32_t isvalidipaddress(char *st) -{ - int32_t i, bcnt, num; - - bcnt = 0; num = 0; - for (i=0; st[i]; i++) - { - if (st[i] == '.') { bcnt++; num = 0; continue; } - if (st[i] == ':') - { - if (bcnt != 3) return(0); - num = 0; - for (i++; st[i]; i++) - { - if ((st[i] >= '0') && (st[i] <= '9')) - { num = num*10+st[i]-'0'; if (num >= 65536) return(0); } - else return(0); - } - return(1); - } - if ((st[i] >= '0') && (st[i] <= '9')) - { num = num*10+st[i]-'0'; if (num >= 256) return(0); } - - } - return(bcnt == 3); -} - -//---------------------------------- Obsolete variables&functions ---------------------------------- -char syncstate = 0; -void mmulti_setpackettimeout(int32_t datimeoutcount, int32_t daresendagaincount) { UNREFERENCED_PARAMETER(datimeoutcount); UNREFERENCED_PARAMETER(daresendagaincount); } -void mmulti_generic(int32_t other, char *bufptr, int32_t messleng, int32_t command) -{ - UNREFERENCED_PARAMETER(other); - UNREFERENCED_PARAMETER(bufptr); - UNREFERENCED_PARAMETER(messleng); - UNREFERENCED_PARAMETER(command); -} -int32_t mmulti_getoutputcirclesize() { return(0); } -void mmulti_flushpackets() {} -void mmulti_sendlogon() {} -void mmulti_sendlogoff() {} -//-------------------------------------------------------------------------------------------------- - -static int32_t crctab16[256]; -static void initcrc16() -{ - int32_t i, j, k, a; - for (j=0; j<256; j++) - { - for (i=7,k=(j<<8),a=0; i>=0; i--,k=((k<<1)&65535)) - { - if ((k^a)&0x8000) a = ((a<<1)&65535)^0x1021; - else a = ((a<<1)&65535); - } - crctab16[j] = (a&65535); - } -} -#define updatecrc16(crc,dat) crc = (((crc<<8)&65535)^crctab16[((((uint16_t)crc)>>8)&65535)^dat]) -static uint16_t getcrc16(char *buffer, int32_t bufleng) -{ - int32_t i, j; - - j = 0; - for (i=bufleng-1; i>=0; i--) updatecrc16(j,buffer[i]); - return((uint16_t)(j&65535)); -} - -void mmulti_uninitmultiplayers() { netuninit(); } - -int32_t mmulti_getpacket(int32_t *, char *); -static void initmultiplayers_reset(void) -{ - int32_t i; - - initcrc16(); - memset(icnt0,0,sizeof(icnt0)); - memset(ocnt0,0,sizeof(ocnt0)); - memset(ocnt1,0,sizeof(ocnt1)); - memset(ipak,0,sizeof(ipak)); - //memset(opak,0,sizeof(opak)); //Don't need to init opak - //memset(pakmem,0,sizeof(pakmem)); //Don't need to init pakmem -#if (SIMLAG > 1) - memset(simlagcnt,0,sizeof(simlagcnt)); -#endif - - lastsendtims[0] = GetTickCount(); - for (i=1; i 1024 && j<65535) portnum = j; - - printf("mmulti: Using port %d\n", portnum); - } - } - - netinit(portnum); - - for (i=0; i= '0') && (argv[i][4] <= '9')) - { - numplayers = (argv[i][4]-'0'); - if ((argv[i][5] >= '0') && (argv[i][5] <= '9')) numplayers = numplayers*10+(argv[i][5]-'0'); - printf("mmulti: %d-player game\n", numplayers); - } - printf("mmulti: Master-slave mode\n"); - } - else if (argv[i][2] == '1') - { - danetmode = 1; - myconnectindex = daindex; daindex++; - printf("mmulti: Peer-to-peer mode\n"); - } - continue; - } - else if ((argv[i][1] == 'P') || (argv[i][1] == 'p')) continue; - } - - st = Bstrdup(argv[i]); if (!st) break; - if (isvalidipaddress(st)) - { - if ((danetmode == 1) && (daindex == myconnectindex)) daindex++; - for (j=0; st[j]; j++) - { - if (st[j] == ':') - { otherport[daindex] = htons((uint16_t)atol(&st[j+1])); st[j] = 0; break; } - } - otherip[daindex] = inet_addr(st); - printf("mmulti: Player %d at %s:%d\n",daindex,st,ntohs(otherport[daindex])); - daindex++; - } - else - { - LPHOSTENT lph; - uint16_t pt = htons(NETPORT); - - for (j=0; st[j]; j++) - if (st[j] == ':') - { pt = htons((uint16_t)atol(&st[j+1])); st[j] = 0; break; } - if ((lph = gethostbyname(st))) - { - if ((danetmode == 1) && (daindex == myconnectindex)) daindex++; - otherip[daindex] = *(int32_t *)lph->h_addr; - otherport[daindex] = pt; - printf("mmulti: Player %d at %s:%d (%s)\n",daindex, - inet_ntoa(*(struct in_addr *)lph->h_addr),ntohs(pt),argv[i]); - daindex++; - } - else printf("mmulti: Failed resolving %s\n",argv[i]); - } - Bfree(st); - } - if ((danetmode == 255) && (daindex)) { numplayers = 2; danetmode = 0; } //an IP w/o /n# defaults to /n0 - if ((numplayers >= 2) && (daindex) && (!danetmode)) myconnectindex = 1; - if (daindex > numplayers) numplayers = daindex; - - //for(i=0;i>8)&255,(otherip[i]>>16)&255,((uint32_t)otherip[i])>>24,ntohs(otherport[i])); - - connecthead = 0; - for (i=0; i= 2)) || (numplayers == 2)); - return (numplayers >= 2); -} - -int32_t initmultiplayerscycle(void) -{ - int32_t i, k; -// extern int32_t totalclock; - - idle(); - - mmulti_getpacket(&i,0); - - tims = GetTickCount(); - if (myconnectindex == connecthead) //Player 0 only - { - for (i=numplayers-1; i>0; i--) - if (!otherip[i]) break; - if (!i) - { - nfIncCP(); //Addfaz NatFree - netready = 1; //Player 0 is ready - return 0; - } - } - else - { - if (netready) return 0; - if (tims < lastsendtims[connecthead]) lastsendtims[connecthead] = tims; - if (tims >= lastsendtims[connecthead]+250) //1000/PAKRATE) - { - lastsendtims[connecthead] = tims; - - // short crc16ofs; //offset of crc16 - // int32_t icnt0; //-1 (special packet for MMULTI.C's player collection) - // ... - // unsigned short crc16; //CRC16 of everything except crc16 - k = 2; - *(int32_t *)&pakbuf[k] = -1; k += 4; - pakbuf[k++] = 0xaa; - *(uint16_t *)&pakbuf[0] = (uint16_t)k; - *(uint16_t *)&pakbuf[k] = getcrc16(pakbuf,k); k += 2; - netsend(connecthead,pakbuf,k); - } - } - - return 1; -} - -void mmulti_initmultiplayers(int32_t argc, char **argv, char damultioption, char dacomrateoption, char dapriority) -{ - UNREFERENCED_PARAMETER(damultioption); - UNREFERENCED_PARAMETER(dacomrateoption); - UNREFERENCED_PARAMETER(dapriority); - - if (initmultiplayersparms(argc,argv)) - { -#if 0 - int32_t i, j, k, otims; - //Console code seems to crash Win98 upon quitting game - //it's not necessary and it's not portable anyway - char tbuf[1024]; - uint32_t u; - HANDLE hconsout; - AllocConsole(); - SetConsoleTitle("Multiplayer status..."); - hconsout = GetStdHandle(STD_OUTPUT_HANDLE); - otims = 0; -#endif - while (initmultiplayerscycle()) - { -#if 0 - if ((tims < otims) || (tims > otims+100)) - { - otims = tims; - sprintf(tbuf,"\rWait for players (%d/%d): ",myconnectindex,numplayers); - for (i=0; i "); continue; } - if (!otherip[i]) { strcat(tbuf,"?.?.?.?:? "); continue; } - sprintf(&tbuf[strlen(tbuf)],"%d.%d.%d.%d:%04x ",otherip[i]&255,(otherip[i]>>8)&255,(otherip[i]>>16)&255,(((uint32_t)otherip[i])>>24),otherport[i]); - } - WriteConsole(hconsout,tbuf,strlen(tbuf),&u,0); - } - } - FreeConsole(); -#else - } -#endif - } - netready = 1; -} - -void mmulti_dosendpackets(int32_t other) //Host to send intially, client to send to others once heard from host. -{ - int32_t i, j, k; - - if (!otherip[other]) return; - - //Packet format: - // short crc16ofs; //offset of crc16 - // int32_t icnt0; //earliest unacked packet - // char ibits[32]; //ack status of packets icnt0<=i>3)+k] |= (1<<((i-icnt0[other])&7)); - k += 32; - - while ((ocnt0[other] < ocnt1[other]) && (!opak[other][ocnt0[other]&(FIFSIZ-1)])) ocnt0[other]++; - for (i=ocnt0[other]; i (int32_t)sizeof(pakbuf)) break; - - *(uint16_t *)&pakbuf[k] = (uint16_t)j; k += 2; - *(int32_t *)&pakbuf[k] = i; k += 4; - Bmemcpy(&pakbuf[k],&pakmem[opak[other][i&(FIFSIZ-1)]+2],j); k += j; - } - *(uint16_t *)&pakbuf[k] = 0; k += 2; - *(uint16_t *)&pakbuf[0] = (uint16_t)k; - *(uint16_t *)&pakbuf[k] = getcrc16(pakbuf,k); k += 2; - - //printf("Send: "); for(i=0;i (int32_t)sizeof(pakmem)) pakmemi = 1; - opak[other][ocnt1[other]&(FIFSIZ-1)] = pakmemi; - *(int16_t *)&pakmem[pakmemi] = messleng; - Bmemcpy(&pakmem[pakmemi+2],bufptr,messleng); pakmemi += messleng+2; - ocnt1[other]++; - - //printf("Send: "); for(i=0;i=0; i=connectpoint2[i]) - { - if (i != myconnectindex) mmulti_dosendpackets(i); - if ((!danetmode) && (myconnectindex != connecthead)) break; //slaves in M/S mode only send to master - } - } - - while (netread(&other,pakbuf,sizeof(pakbuf))) - { - //Packet format: - // short crc16ofs; //offset of crc16 - // int32_t icnt0; //earliest unacked packet - // char ibits[32]; //ack status of packets icnt0<=i>3)+k]&(1<<((i-ic0)&7))) - opak[other][i&(FIFSIZ-1)] = 0; - k += 32; - - messleng = (int32_t)(*(uint16_t *)&pakbuf[k]); k += 2; - while (messleng) - { - j = *(int32_t *)&pakbuf[k]; k += 4; - if ((j >= icnt0[other]) && (!ipak[other][j&(FIFSIZ-1)])) - { - if (pakmemi+messleng+2 > (int32_t)sizeof(pakmem)) pakmemi = 1; - ipak[other][j&(FIFSIZ-1)] = pakmemi; - *(int16_t *)&pakmem[pakmemi] = messleng; - Bmemcpy(&pakmem[pakmemi+2],&pakbuf[k],messleng); pakmemi += messleng+2; - } - k += messleng; - messleng = (int32_t)(*(uint16_t *)&pakbuf[k]); k += 2; - } - } - } - } - - //Return next valid packet from any player - if (!bufptr) return(0); - for (i=connecthead; i>=0; i=connectpoint2[i]) - { - if (i != myconnectindex) - { - j = ipak[i][icnt0[i]&(FIFSIZ-1)]; - if (j) - { - messleng = *(int16_t *)&pakmem[j]; Bmemcpy(bufptr,&pakmem[j+2],messleng); - *retother = i; ipak[i][icnt0[i]&(FIFSIZ-1)] = 0; icnt0[i]++; - //printf("Recv: "); for(i=0;ih_addr))->s_addr; - dest_addr.sin_family = AF_INET; - dest_addr.sin_port = htons(port); - - memset(&(dest_addr.sin_zero), '\0', 8); - - mysock = socket(PF_INET, SOCK_STREAM, 0); - - if (mysock == INVALID_SOCKET) - { - initprintf("mmulti: socket() error in getexternaladdress() (%d)\n",errno); - return(0); - } - - if (connect(mysock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr)) == SOCKET_ERROR) - { - initprintf("mmulti: connect() error in getexternaladdress() (%d)\n",errno); - return(0); - } - - bytes_sent = send(mysock, req, strlen(req), 0); - if (bytes_sent == SOCKET_ERROR) - { - initprintf("mmulti: send() error in getexternaladdress() (%d)\n",errno); - return(0); - } - - // initprintf("sent %d bytes\n",bytes_sent); - recv(mysock, (char *)&tempbuf, sizeof(tempbuf), 0); - closesocket(mysock); - j = Bstrlen(text); - for (i=Bstrlen(tempbuf); i>0; i--) - if (!Bstrncmp(&tempbuf[i], text, j)) - { - i += j; - j = 0; - while (isdigit(tempbuf[i]) || (tempbuf[i] == '.')) - { - ipaddr[j] = tempbuf[i]; - i++, j++; - } - ipaddr[j++] = '\0'; - break; - } - Bmemcpy(buffer,&ipaddr,j); - return(1); -} diff --git a/polymer/eduke32/build/src/mmulti_null.c b/polymer/eduke32/build/src/mmulti_null.c deleted file mode 100644 index c59c3b453..000000000 --- a/polymer/eduke32/build/src/mmulti_null.c +++ /dev/null @@ -1,75 +0,0 @@ -// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman -// Ken Silverman's official web site: "http://www.advsys.net/ken" -// See the included license file "BUILDLIC.TXT" for license info. -// -// This file has been modified from Ken Silverman's original release -// by Jonathon Fowler (jonof@edgenetwk.com) - - -#include "mmulti.h" - - -int32_t myconnectindex, numplayers; -int32_t connecthead, connectpoint2[MAXMULTIPLAYERS]; -char syncstate = 0; - -int32_t isvalidipaddress(char *st) -{ - return 0; -} - -int32_t initmultiplayersparms(int32_t argc, char **argv) -{ - return 0; -} - -int32_t initmultiplayerscycle(void) -{ - return 0; -} - -void mmulti_initmultiplayers(int32_t argc, char **argv, char damultioption, char dacomrateoption, char dapriority) -{ - numplayers = 1; myconnectindex = 0; - connecthead = 0; connectpoint2[0] = -1; -} - -void mmulti_setpackettimeout(int32_t datimeoutcount, int32_t daresendagaincount) -{ -} - -void mmulti_uninitmultiplayers(void) -{ -} - -void mmulti_sendlogon(void) -{ -} - -void mmulti_sendlogoff(void) -{ -} - -int32_t mmulti_getoutputcirclesize(void) -{ - return 0; -} - -void mmulti_sendpacket(int32_t other, char *bufptr, int32_t messleng) -{ -} - -int32_t mmulti_getpacket(int32_t *other, char *bufptr) -{ - return 0; -} - -void mmulti_flushpackets(void) -{ -} - -void mmulti_generic(int32_t other, char *bufptr, int32_t messleng, int32_t command) -{ -} - - diff --git a/polymer/eduke32/build/src/mmulti_unstable.c b/polymer/eduke32/build/src/mmulti_unstable.c index c49105220..fcaffd445 100644 --- a/polymer/eduke32/build/src/mmulti_unstable.c +++ b/polymer/eduke32/build/src/mmulti_unstable.c @@ -1,2172 +1,2160 @@ -/* - * "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman - * Ken Silverman's official web site: "http://www.advsys.net/ken" - * See the included license file "BUILDLIC.TXT" for license info. - * This file has been modified from Ken Silverman's original release - */ - -#include -#include -#include -#include -#include -#include - -#include "mmulti_unstable.h" -// #include -#include "compat.h" -#include "baselayer.h" - -//STL -//#include -//#include "buildqueue.h" - -// #include "platform.h" - -#ifdef _WIN32 -#define PLATFORM_WIN32 1 -#else -#define PLATFORM_UNIX 1 - -#include -static int32_t GetTickCount(void) +/* + * "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman + * Ken Silverman's official web site: "http://www.advsys.net/ken" + * See the included license file "BUILDLIC.TXT" for license info. + * This file has been modified from Ken Silverman's original release + */ + +#include +#include +#include +#include +#include +#include + +#include "mmulti_unstable.h" +// #include +#include "compat.h" +#include "baselayer.h" + +//STL +//#include +//#include "buildqueue.h" + +// #include "platform.h" + +#ifdef _WIN32 +#define PLATFORM_WIN32 1 +#else +#define PLATFORM_UNIX 1 +#endif + +#define UDP_NETWORKING 1 + +#include "pragmas.h" + +#define MAXPLAYERS 16 +#define BAKSIZ 16384 +#define SIMULATEERRORS 0 +#define SHOWSENDPACKETS 0 +#define SHOWGETPACKETS 0 +#define PRINTERRORS 0 + +#define updatecrc16(crc,dat) crc = (((crc<<8)&65535)^crctable[((((uint16_t)crc)>>8)&65535)^dat]) + +static int32_t incnt[MAXPLAYERS], outcntplc[MAXPLAYERS], outcntend[MAXPLAYERS]; +static char errorgotnum[MAXPLAYERS]; +static char errorfixnum[MAXPLAYERS]; +static char errorresendnum[MAXPLAYERS]; +#if (PRINTERRORS) +static char lasterrorgotnum[MAXPLAYERS]; +#endif + +int32_t crctable[256]; +int32_t tmpmax[8]; //addfaz variable addition (you could probs think of something better) +int32_t itmp = 0; //addfaz router fix STUN + +static uint8_t lastpacket[576]; +char inlastpacket = 0; +static int32_t lastpacketfrom, lastpacketleng; + +extern int32_t totalclock; /* MUST EXTERN 1 ANNOYING VARIABLE FROM GAME */ +static int32_t timeoutcount = 60, resendagaincount = 4, lastsendtime[MAXPLAYERS]; + +int32_t natfree; //NatFree mode flag + +static int16_t bakpacketptr[MAXPLAYERS][256], bakpacketlen[MAXPLAYERS][256]; +static uint16_t bakpacketbuf[BAKSIZ]; +static int32_t bakpacketplc = 0; + +int32_t myconnectindex, numplayers; +int32_t connecthead, connectpoint2[MAXPLAYERS]; +char syncstate = 0; + +#define MAXPACKETSIZE 2048 +#define PACKET_START_GAME 0x1337 + +enum commit_cmd_t { - struct timeval tv; - int32_t ti; - if (gettimeofday(&tv,NULL) < 0) return 0; - // tv is sec.usec, GTC gives msec - ti = tv.tv_sec * 1000; - ti += tv.tv_usec / 1000; - return ti; -} -#endif - -#define UDP_NETWORKING 1 - -#include "pragmas.h" - -#define MAXPLAYERS 16 -#define BAKSIZ 16384 -#define SIMULATEERRORS 0 -#define SHOWSENDPACKETS 0 -#define SHOWGETPACKETS 0 -#define PRINTERRORS 0 - -#define updatecrc16(crc,dat) crc = (((crc<<8)&65535)^crctable[((((uint16_t)crc)>>8)&65535)^dat]) - -static int32_t incnt[MAXPLAYERS], outcntplc[MAXPLAYERS], outcntend[MAXPLAYERS]; -static char errorgotnum[MAXPLAYERS]; -static char errorfixnum[MAXPLAYERS]; -static char errorresendnum[MAXPLAYERS]; -#if (PRINTERRORS) -static char lasterrorgotnum[MAXPLAYERS]; -#endif - -int32_t crctable[256]; -int32_t tmpmax[8]; //addfaz variable addition (you could probs think of something better) -int32_t itmp = 0; //addfaz router fix STUN - -static uint8_t lastpacket[576]; -char inlastpacket = 0; -static int32_t lastpacketfrom, lastpacketleng; - -extern int32_t totalclock; /* MUST EXTERN 1 ANNOYING VARIABLE FROM GAME */ -static int32_t timeoutcount = 60, resendagaincount = 4, lastsendtime[MAXPLAYERS]; - -int32_t natfree; //NatFree mode flag - -static int16_t bakpacketptr[MAXPLAYERS][256], bakpacketlen[MAXPLAYERS][256]; -static uint16_t bakpacketbuf[BAKSIZ]; -static int32_t bakpacketplc = 0; - -int32_t myconnectindex, numplayers; -int32_t connecthead, connectpoint2[MAXPLAYERS]; -char syncstate = 0; - -#define MAXPACKETSIZE 2048 -#define PACKET_START_GAME 0x1337 - -enum commit_cmd_t -{ - COMMIT_CMD_SEND = 1, - COMMIT_CMD_GET = 2, - COMMIT_CMD_SENDTOALL = 3, - COMMIT_CMD_SENDTOALLOTHERS = 4, - COMMIT_CMD_SCORE = 5, -}; - -typedef struct gcomtype_t -{ - int16_t command; /* 1-send, 2-get */ - int16_t other; /* dest for send, set by get (-1 = no packet) */ - int16_t numbytes; - int16_t myconnectindex; - int16_t numplayers; - int16_t filler; - char buffer[MAXPACKETSIZE]; -} gcomtype; -static gcomtype *gcom; - -/* -// -// Packet queue data structs -// -typedef struct packet_wrapper -{ - unsigned long packetnumber; - gcomtype packet; -} PACKETWRAPPER; - -typedef PACKETWRAPPER packet_buffer; - -unsigned long currentpacketnumber[MAXPLAYERS]; - -// -// Packet Buffer -// -packet_buffer pBuff[256]; -*/ - - -/* -typedef struct -{ - char buffer[MAXPACKETSIZE]; -}PACKET; -*/ - -//typedef std::vector PacketQueue; - -static struct allowed_addr_t -{ - int32_t host; - uint16_t port; -} allowed_addresses[MAXPLAYERS]; /* only respond to these IPs. */ - -// Queue of out going packets. -//PacketQueue outgoingPacketQueue; -//outgoingPacketQueue.reserve(128); - -gcomtype *init_network_transport(int32_t argc, char **argv); -void deinit_network_transport(gcomtype *gcom); -//void callcommit(void); -void mmulti_dosendpackets(int32_t other); - - -static void initcrc(void) -{ - int32_t i, j, k, a; - - for (j=0; j<256; j++) /* Calculate CRC table */ - { - k = (j<<8); a = 0; - for (i=7; i>=0; i--) - { - if (((k^a)&0x8000) > 0) - a = ((a<<1)&65535) ^ 0x1021; /* 0x1021 = genpoly */ - else - a = ((a<<1)&65535); - k = ((k<<1)&65535); - } - crctable[j] = (a&65535); - } -} - - -int32_t getcrc(char *buffer, int32_t bufleng) -{ - int32_t i, j; - - j = 0; - for (i=bufleng-1; i>=0; i--) updatecrc16(j,buffer[i]); - return(j&65535); -} - -void mmulti_initmultiplayers(int32_t argc, char **argv) -{ - int32_t i; - - UNREFERENCED_PARAMETER(argc); - - initcrc(); - for (i=0; i 0; i--) - { - const char *arg = argv[i]; - char ch = *arg; - if ((ch == '-') || (ch == '/')) - { - if (Bstrcasecmp(arg + 1, "net") == 0) - break; - } - } -#endif - - if (!argc) - { -// initprintf("network: No configuration file specified!\n"); - numplayers = 1; myconnectindex = 0; - connecthead = 0; connectpoint2[0] = -1; - return; - } - - gcom = init_network_transport(argc, argv); - if (gcom == NULL) - { - initprintf("Network transport initialization failed. Aborting...\n"); - numplayers = 1; myconnectindex = 0; - connecthead = 0; connectpoint2[0] = -1; - return; - } - - numplayers = gcom->numplayers; - myconnectindex = gcom->myconnectindex-1; -#if (SIMULATEERRORS != 0) - srand(myconnectindex*24572457+345356); -#endif - connecthead = 0; - for (i=0; i lasterrorgotnum[other]) - { - lasterrorgotnum[other]++; - initprintf(" MeWant %ld",incnt[other]&255); - } -#endif - - if (outcntplc[other]+1 == outcntend[other]) - { /* Send 1 sub-packet */ - k = 0; - gcom->buffer[k++] = (outcntplc[other]&255); - gcom->buffer[k++] = (errorgotnum[other]&7)+((errorresendnum[other]&7)<<3); - gcom->buffer[k++] = (incnt[other]&255); - - j = bakpacketptr[other][outcntplc[other]&255]; - messleng = bakpacketlen[other][outcntplc[other]&255]; - for (i=0; ibuffer[k++] = bakpacketbuf[(i+j)&(BAKSIZ-1)]; - outcntplc[other]++; - } - else - { /* Send 2 sub-packets */ - k = 0; - gcom->buffer[k++] = (outcntplc[other]&255); - gcom->buffer[k++] = (errorgotnum[other]&7)+((errorresendnum[other]&7)<<3)+128; - gcom->buffer[k++] = (incnt[other]&255); - - /* First half-packet */ - j = bakpacketptr[other][outcntplc[other]&255]; - messleng = bakpacketlen[other][outcntplc[other]&255]; - gcom->buffer[k++] = (uint8_t)(messleng&255); - gcom->buffer[k++] = (uint8_t)(messleng>>8); - for (i=0; ibuffer[k++] = bakpacketbuf[(i+j)&(BAKSIZ-1)]; - outcntplc[other]++; - - /* Second half-packet */ - j = bakpacketptr[other][outcntplc[other]&255]; - messleng = bakpacketlen[other][outcntplc[other]&255]; - for (i=0; ibuffer[k++] = bakpacketbuf[(i+j)&(BAKSIZ-1)]; - outcntplc[other]++; - - } - - dacrc = getcrc(gcom->buffer,(int16_t)k); - gcom->buffer[k++] = (dacrc&255); - gcom->buffer[k++] = (dacrc>>8); - - gcom->other = other+1; - gcom->numbytes = k; - -#if (SHOWSENDPACKETS) - initprintf("Send(%ld): ",gcom->other); - for (i=0; inumbytes; i++) initprintf("%2x ",gcom->buffer[i]); - initprintf("\n"); -#endif - -#if (SIMULATEERRORS != 0) - if (!(rand()&SIMULATEERRORS)) gcom->buffer[rand()%gcom->numbytes] = (rand()&255); - if (rand()&SIMULATEERRORS) -#endif - { - gcom->command = COMMIT_CMD_SEND; - callcommit(); - } -} - - -void mmulti_sendpacket(int32_t other, char *bufptr, int32_t messleng) -{ - int32_t i = 0; - int32_t j = 0; - - if (numplayers < 2) return; - - i = 0; - if (bakpacketlen[other][(outcntend[other]-1)&255] == messleng) - { - j = bakpacketptr[other][(outcntend[other]-1)&255]; - for (i=messleng-1; i>=0; i--) - if (bakpacketbuf[(i+j)&(BAKSIZ-1)] != bufptr[i]) break; - } - bakpacketlen[other][outcntend[other]&255] = messleng; - - if (i < 0) /* Point to last packet to save space on bakpacketbuf */ - bakpacketptr[other][outcntend[other]&255] = j; - else - { - bakpacketptr[other][outcntend[other]&255] = bakpacketplc; - for (i=0; i=0; i=connectpoint2[i]) - { - if (i != myconnectindex) - mmulti_sendpacket(i,tempbuf,2L); - if ((udpmode == udpmode_client) && (myconnectindex != connecthead)) break; //slaves in M/S mode only send to master - } -} - -int32_t mmulti_getoutputcirclesize(void) -{ - return(0); -} - -int32_t mmulti_getpacket(int32_t *other, char *bufptr) -{ - int32_t i, messleng; - uint16_t dacrc; - - if (numplayers < 2 || gcom == NULL) return(0); - - for (i=connecthead; i>=0; i=connectpoint2[i]) - { - if (i != myconnectindex) - { - // FIXME: this is probably not so great - if (udpmode != udpmode_peer) mmulti_dosendpackets(i); - if (totalclock < lastsendtime[i]) lastsendtime[i] = totalclock; - if (totalclock > lastsendtime[i]+timeoutcount) - { -#if (PRINTERRORS) - initprintf(" TimeOut!"); -#endif - errorgotnum[i] = errorfixnum[i]+1; - - if ((outcntplc[i] == outcntend[i]) && (outcntplc[i] > 0)) - { outcntplc[i]--; lastsendtime[i] = totalclock; } - else - lastsendtime[i] += resendagaincount; - mmulti_dosendpackets(i); - /* } */ - } - } - if ((udpmode == udpmode_client) && (myconnectindex != connecthead)) break; //slaves in M/S mode only send to master - } - - if (inlastpacket != 0) - { - /* 2ND half of good double-packet */ - inlastpacket = 0; - *other = lastpacketfrom; - Bmemcpy(bufptr,lastpacket,lastpacketleng); - return(lastpacketleng); - } - - gcom->command = COMMIT_CMD_GET; - callcommit(); - -#if (SHOWGETPACKETS) - if (gcom->other != -1) - { - initprintf(" Get(%ld): ",gcom->other); - for (i=0; inumbytes; i++) initprintf("%2x ",gcom->buffer[i]); - initprintf("\n"); - } -#endif - - if (gcom->other < 0) return(0); - *other = gcom->other-1; - - messleng = gcom->numbytes; - - dacrc = ((uint16_t)gcom->buffer[messleng-2]); - dacrc += (((uint16_t)gcom->buffer[messleng-1])<<8); - if (dacrc != getcrc(gcom->buffer,(int16_t)(messleng-2))) /* CRC check */ - { -#if (PRINTERRORS) - initprintf("\n%ld CRC",gcom->buffer[0]); -#endif - errorgotnum[*other] = errorfixnum[*other]+1; - return(0); - } - - while ((errorfixnum[*other]&7) != ((gcom->buffer[1]>>3)&7)) - errorfixnum[*other]++; - - if ((gcom->buffer[1]&7) != (errorresendnum[*other]&7)) - { - errorresendnum[*other]++; - outcntplc[*other] = (outcntend[*other]&0xffffff00)+gcom->buffer[2]; - if (outcntplc[*other] > outcntend[*other]) outcntplc[*other] -= 256; - } - - if (gcom->buffer[0] != (incnt[*other]&255)) /* CNT check */ - { - if (((incnt[*other]-gcom->buffer[0])&255) > 32) - { - errorgotnum[*other] = errorfixnum[*other]+1; -#if (PRINTERRORS) - initprintf("\n%ld CNT",gcom->buffer[0]); -#endif - } -#if (PRINTERRORS) - else - { - if (!(gcom->buffer[1]&128)) /* single else double packet */ - initprintf("\n%ld cnt",gcom->buffer[0]); - else - { - if (((gcom->buffer[0]+1)&255) == (incnt[*other]&255)) - { - /* GOOD! Take second half of double packet */ -#if (PRINTERRORS) - initprintf("\n%ld-%ld .û ",gcom->buffer[0],(gcom->buffer[0]+1)&255); -#endif - messleng = ((int32_t)gcom->buffer[3]) + (((int32_t)gcom->buffer[4])<<8); - lastpacketleng = gcom->numbytes-7-messleng; - Bmemcpy(bufptr,&gcom->buffer[messleng+5],lastpacketleng); - incnt[*other]++; - return(lastpacketleng); - } - else - initprintf("\n%ld-%ld cnt ",gcom->buffer[0],(gcom->buffer[0]+1)&255); - } - } -#endif - return(0); - } - - /* PACKET WAS GOOD! */ - if ((gcom->buffer[1]&128) == 0) /* Single packet */ - { -#if (PRINTERRORS) - initprintf("\n%ld û ",gcom->buffer[0]); -#endif - - messleng = gcom->numbytes-5; - - Bmemcpy(bufptr,&gcom->buffer[3],messleng); - - incnt[*other]++; - return(messleng); - } - - /* Double packet */ -#if (PRINTERRORS) - initprintf("\n%ld-%ld ûû ",gcom->buffer[0],(gcom->buffer[0]+1)&255); -#endif - - messleng = ((int32_t)gcom->buffer[3]) + (((int32_t)gcom->buffer[4])<<8); - lastpacketleng = gcom->numbytes-7-messleng; - inlastpacket = 1; lastpacketfrom = *other; - - Bmemcpy(bufptr,&gcom->buffer[5],messleng); - Bmemcpy(lastpacket,&gcom->buffer[messleng+5],lastpacketleng); - - incnt[*other] += 2; - return(messleng); -} - -void mmulti_flushpackets() -{ -#if 1 - int32_t i; - - if (numplayers < 2) return; - - do - { - gcom->command = COMMIT_CMD_GET; - callcommit(); - } - while (gcom->other >= 0); - - for (i=connecthead; i>=0; i=connectpoint2[i]) - { - incnt[i] = 0L; - outcntplc[i] = 0L; - outcntend[i] = 0L; - errorgotnum[i] = 0; - errorfixnum[i] = 0; - errorresendnum[i] = 0; - lastsendtime[i] = totalclock; - } -#endif -} - -void mmulti_generic(int32_t other, char *bufptr, int32_t messleng, int32_t command) -{ - if (numplayers < 2) return; - - gcom->command = command; - gcom->numbytes = min(messleng,MAXPACKETSIZE); - copybuf(bufptr,gcom->buffer,(gcom->numbytes+3)>>2); - gcom->other = other+1; - callcommit(); - -} - -#if PLATFORM_WIN32 -# include -# define EWOULDBLOCK WSAEWOULDBLOCK -# define ECONNREFUSED WSAECONNRESET -# define socklen_t size_t -# define netstrerror() win32netstrerror() -# define neterrno() WSAGetLastError() -# define sockettype SOCKET -# define socketclose(x) closesocket(x) -#else -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# define netstrerror() strerror(errno) -# define neterrno() errno -# define sockettype int32_t -# define socketclose(x) close(x) -# ifndef MSG_ERRQUEUE /* legacy glibc header workaround... */ -# define MSG_ERRQUEUE 0x2000 -# endif -#endif - -#define SOCKET_SHUTDOWN_BOTH 2 - -#include "cache1d.h" /* kopen4load for cfg file. */ - -#define IPSEG1(ip) ((((uint32_t) ip) & 0xFF000000) >> 24) -#define IPSEG2(ip) ((((uint32_t) ip) & 0x00FF0000) >> 16) -#define IPSEG3(ip) ((((uint32_t) ip) & 0x0000FF00) >> 8) -#define IPSEG4(ip) ((((uint32_t) ip) & 0x000000FF) ) - -#define BUILD_DEFAULT_UDP_PORT 23513 /* eh...why not? */ -#define CLIENT_POLL_DELAY 5000 /* ms between pings at peer-to-peer startup. */ -#define HEADER_PEER_GREETING 245 - -static sockettype udpsocket = -1; -static uint16_t udpport = BUILD_DEFAULT_UDP_PORT; - -#if PLATFORM_WIN32 -/* - * Figure out what the last failing Win32 API call was, and - * generate a human-readable string for the error message. - * - * The return value is a static buffer that is overwritten with - * each call to this function. - * - * Code lifted from PhysicsFS: http://icculus.org/physfs/ - */ -static const char *win32netstrerror(void) -{ - static TCHAR msgbuf[255]; - TCHAR *ptr = msgbuf; - - FormatMessage( - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - WSAGetLastError(), /*GetLastError(),*/ - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ - msgbuf, - sizeof(msgbuf) / sizeof(TCHAR), - NULL - ); - - /* chop off newlines. */ - for (ptr = msgbuf; *ptr; ptr++) - { - if ((*ptr == '\n') || (*ptr == '\r')) - { - *ptr = ' '; - break; - } /* if */ - } /* for */ - - return((const char *) msgbuf); -} /* win32strerror */ -#endif - -static char *static_ipstring(int32_t ip) -{ - static char s[16]; - Bsprintf(s, "%u.%u.%u.%u", IPSEG1(ip), IPSEG2(ip), IPSEG3(ip), IPSEG4(ip)); - return(s); -} - - -static int32_t send_udp_packet(int32_t ip, uint16_t port, void *pkt, size_t pktsize) -{ - /* !!! FIXME: See if this would ever block. */ - /* !!! FIXME: See if this would send a partial packet. */ - struct sockaddr_in addr; - int32_t rc; - - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(ip); - addr.sin_port = htons(port); - - rc = sendto(udpsocket, pkt, pktsize, 0, - (struct sockaddr *) &addr, sizeof(addr)); - - if (rc != (int32_t) pktsize) - { - initprintf("sendto err rc==%d when sending %d to %s:%d [%s].\n", - rc, (int32_t) pktsize, static_ipstring(ip), (int32_t) port, - netstrerror()); - return(0); - } - - /*initprintf("Sent %d byte packet to %s:%d\n", (int32_t) pktsize, static_ipstring(ip), (int32_t) port);*/ - - return(1); -} - - -static void process_udp_send_queue(void) -{ - /* Fill this in if the non-blocking socket becomes an issue. */ -} - - -static int32_t get_udp_packet(int32_t *ip, uint16_t *_port, void *pkt, size_t pktsize) -{ - int32_t err = 0; - struct sockaddr_in addr; - uint16_t port; - socklen_t fromlen = sizeof(addr); - int32_t valid = 0; - int32_t i; - - /* FIXME: Will this ever receive a partial packet? */ - int32_t rc = recvfrom(udpsocket, pkt, pktsize, 0, (struct sockaddr *) &addr, -#ifdef _WIN32 - (int32_t *)&fromlen); -#else - (uint32_t *)&fromlen); -#endif - - if (rc == -1) - err = neterrno(); - -#if !PLATFORM_WIN32 - /* !!! FIXME: Linux specific? */ - if (rc == -1) /* fill in the addr structure on error... */ - { - socklen_t l = sizeof(addr); - recvfrom(udpsocket, NULL, 0, MSG_ERRQUEUE, - (struct sockaddr *) &addr, &l); - } -#endif - - *ip = ntohl(addr.sin_addr.s_addr); - port = ntohs(addr.sin_port); - if (_port) - *_port = port; - - /* - * Reject packets from unallowed IPs. Prevents (ha) DoS attacks and - * other confusion... - */ - if (gcom == NULL) - { - if (natfree) //if stun is enabled - { - if ((allowed_addresses[itmp].host == *ip) - && (allowed_addresses[itmp].port == port)) - { - valid = 1; //only accept packets from the current player (itmp) and no one else - } - else - { - return 0; //reject packets from other players - } - } - else - { - valid = 1; - } - } - else - { - for (i = 1; i <= gcom->numplayers; i++) - { - if ((allowed_addresses[i].host == *ip) - && (allowed_addresses[i].port == port)) - - { - valid = i; - - //initprintf ("Packet received from %s:%d\n",static_ipstring(*ip), (int32_t) port); - - break; - } - - } - } - - /*if (!valid) - { - - static int32_t unallowed_ip_spam = 0; - if (unallowed_ip_spam <= 100) - { - initprintf("Packet received from unallowed IP %s:%d\n", - static_ipstring(*ip), (int32_t) port); - if (unallowed_ip_spam == 100) - initprintf("(Disabling further unallowed IP spam.)\n"); - unallowed_ip_spam++; - } - - return(0); - } */ - - if (rc == -1) - { - if ((err == EAGAIN) || (err == EWOULDBLOCK)) - rc = 0; - - else if (err == ECONNREFUSED) //"connection reset by peer" in winsock - { - - // This means that we sent a packet to an unopened port, and - // it responded by telling us to piss off. Take them out of the - // allowed list. We check gcom so that we don't worry about this - // during detection when game might still be loading elsewhere. - - if (gcom != NULL) - { - allowed_addresses[valid].host = 0; - initprintf("%s:%d refused packets. Removed from game.\n", - static_ipstring(*ip), (int32_t) port); - } - // !!! FIXME: Actually boot player, too. - } - - else - { - initprintf("recvfrom err rc==%d when getting %d from %s:%d [%s].\n", - rc, (int32_t) pktsize, static_ipstring(*ip), (int32_t) port, - netstrerror()); - } - } -//else initprintf("Got %d byte packet from %s:%d\n", (int32_t) rc, static_ipstring(*ip), (int32_t) port); - //initprintf( "IP from client %d", *ip); - return(rc); -} - - -static char *read_whole_file(const char *cfgfile) -{ - char *buf; - int32_t len, rc; - int32_t handle; - - if (cfgfile == NULL) - return(NULL); - - handle = kopen4load((char *)cfgfile, 0); - if (handle == -1) - { -// initprintf("ERROR: Failed to open config file [%s].\n", cfgfile); - return(NULL); - } - - len = kfilelength(handle); - buf = (char *) Bmalloc(len + 2); - if (!buf) - { - kclose(handle); - return(NULL); - } - - rc = kread(handle, buf, len); - kclose(handle); - if (rc != len) - { - Bfree(buf); - return(NULL); - } - - buf[len] = '\0'; - buf[len+1] = '\0'; - return(buf); -} - -static char *get_token(char **ptr) -{ - char *retval; - char *p = *ptr; - if (*p == '\0') - return(NULL); - - while ((*p != '\0') && (isspace(*p))) - p++; - - if (*p == '\0') /* nothing but whitespace. */ - return(NULL); - - retval = p; - while ((*p != '\0') && (!isspace(*p))) - p++; - - *p = '\0'; - *ptr = p + 1; - - /*initprintf("Got token [%s].\n", retval);*/ - return(retval); -} - -static int32_t set_socket_blockmode(int32_t onOrOff) -{ - uint32_t flags; - int32_t rc = 0; - - /* set socket to be (non-)blocking. */ - -#if PLATFORM_WIN32 - flags = (onOrOff) ? 0 : 1; - rc = (ioctlsocket(udpsocket, FIONBIO, (void *) &flags) == 0); -#else - flags = fcntl(udpsocket, F_GETFL, 0); - if ((signed)flags != -1) - { - if (onOrOff) - flags &= ~O_NONBLOCK; - else - flags |= O_NONBLOCK; - rc = (fcntl(udpsocket, F_SETFL, flags) == 0); - } -#endif - - if (!rc) - { - initprintf("set socket %sblocking failed: %s\n", - ((onOrOff) ? "" : "non-"), netstrerror()); - } - - return(rc); -} - - -static int32_t set_socket_broadcast(int32_t onOrOff) -{ - int32_t f = (onOrOff) ? 1 : 0; - int32_t rc; - - /* give socket clearance to broadcast. */ - rc = setsockopt(udpsocket, SOL_SOCKET, SO_BROADCAST, (char *)(&f), sizeof(f)) == 0; - if (!rc) - { - initprintf("%sset SO_BROADCAST failed: %s\n", - ((onOrOff) ? "" : "un"), netstrerror()); - } - - return(rc); -} - - -static int32_t open_udp_socket(int32_t ip, int32_t port) -{ - struct sockaddr_in addr; - -// initprintf("Setting up UDP interface %s:%d...\n", static_ipstring(ip), port); - if (natfree) - { - //initprintf("Stun is currently %s\n", (natfree) ? "Enabled":"Disabled"); - initprintf("network: Stun enabled\n"); - } - - udpsocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); - if ((signed)udpsocket == -1) - { - initprintf("network: socket creation failed: %s\n", netstrerror()); - return(0); - } - - if (!set_socket_blockmode(0)) - return(0); - -#if !PLATFORM_WIN32 - { - /* !!! FIXME: Might be Linux (not Unix, not BSD, not WinSock) specific. */ - int32_t flags = 1; - setsockopt(udpsocket, IPPROTO_IP, IP_RECVERR, &flags, sizeof(flags)); - } -#endif - - memset(&addr, '\0', sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(ip); - addr.sin_port = htons((uint16_t)port); - if (bind(udpsocket, (struct sockaddr *) &addr, sizeof(addr)) == -1) - { - initprintf("network: socket binding failed: %s\n", netstrerror()); - return(0); - } - - return(1); -} - -typedef struct peergreeting_t -{ - char dummy1; /* so these don't confuse game after load. */ - char dummy2; /* so these don't confuse game after load. */ - char dummy3; /* so these don't confuse game after load. */ - char header; /* always HEADER_PEER_GREETING (245). */ - uint16_t id; -} PacketPeerGreeting; - - -static void send_peer_greeting(int32_t ip, uint16_t port, int16_t myid) -{ - PacketPeerGreeting packet; - memset(&packet, '\0', sizeof(packet)); - packet.header = HEADER_PEER_GREETING; - packet.id = B_SWAP16(myid); - send_udp_packet(ip, port, &packet, sizeof(packet)); -} - -/* server init. */ -static int32_t wait_for_other_players(gcomtype *gcom, int32_t myip) -{ - PacketPeerGreeting packet; - uint16_t my_id = 1; // we're always 1 so we sort as the first player - int32_t i, j; - int32_t rc; - int32_t ip; - uint16_t port; - uint16_t heard_from[MAXPLAYERS]; - int32_t max; - int32_t remaining; - - memset(heard_from, '\0', sizeof(heard_from)); - - remaining = max = gcom->numplayers - 1; - - initprintf("Waiting for %d player%s...\n", remaining, remaining==1 ? "":"s"); - if (remaining == 0) - { - initprintf("Hmmm... don't have time to play with myself!\n"); - return(0); - } - - while (remaining && !quitevent) - { - handleevents(); - - idle(); - - process_udp_send_queue(); - - rc = get_udp_packet(&ip, &port, &packet, sizeof(packet)); - - //this is so we don't get unexpected packet errors from players already heard from - - if ((rc > 0) && (ip) && ((ip != myip) || (port != udpport))) - { - char *ipstr = static_ipstring(ip); - - if (rc != sizeof(packet)) - { - initprintf("network: Missized packet or fragment from %s:%i ?!\n", ipstr, port); - continue; - } - else if (packet.header != HEADER_PEER_GREETING) - { - initprintf("network: Unexpected packet type from %s:%i ?!\n", ipstr, port); - continue; - } - - for (i = 0; i < max; i++) - { - if (!heard_from[i] || heard_from[i] == B_SWAP16(packet.id)) - break; - } - - if (i == max) - initprintf("network: Disallowed player %s:%d ?!\n", ipstr, port); - else if (heard_from[i] == 0) - { - packet.id = B_SWAP16(packet.id); - heard_from[i] = packet.id; - allowed_addresses[i].host = ip; /* bcast needs this. */ - allowed_addresses[i].port = port; - remaining--; - - initprintf("%s:%i (id 0x%X) connected, %d player%s left.\n", - ipstr, (unsigned)port ,(int32_t) packet.id, - remaining, remaining == 1 ? "" : "s"); - - /* make sure they've heard from us at all... */ - /* !!! FIXME: Could be fatal if packet is dropped... */ - - send_peer_greeting(allowed_addresses[i].host, - allowed_addresses[i].port, - my_id); - } - } - } - - if (quitevent) - { - initprintf("network: Connection attempt aborted.\n"); - return(0); - } - - // found all the clients expected so relay all greetings - for (j=max; j>=0; j--) - if (allowed_addresses[j].host) - { - int32_t ii; - - // send another copy of our greeting just in case they missed it - send_peer_greeting(allowed_addresses[j].host, - allowed_addresses[j].port, - my_id); - - for (ii = 0; ii < max; ii++) - send_peer_greeting(allowed_addresses[j].host, - allowed_addresses[j].port, - heard_from[ii]); - - // greeting with 0x1337 id starts the game for clients - send_peer_greeting(allowed_addresses[j].host, - allowed_addresses[j].port, - PACKET_START_GAME); - } - - /* ok, now everyone is talking to you. Sort them into player numbers... */ - - heard_from[max] = my_id; /* so we sort, too... */ - allowed_addresses[max].host = myip; - allowed_addresses[max].port = udpport; - - do - { - remaining = 0; - for (i = 0; i < max; i++) - { - if (heard_from[i] == heard_from[i+1]) /* blah. */ - { - initprintf("network: ERROR: Two players have the same random ID!\n"); - initprintf("network: ERROR: Please restart the game to generate new IDs.\n"); - return(0); - } - - else if (heard_from[i] > heard_from[i+1]) - { - int32_t tmpi; - int16_t tmps; - - tmps = heard_from[i]; - heard_from[i] = heard_from[i+1]; - heard_from[i+1] = tmps; - - tmpi = allowed_addresses[i].host; - allowed_addresses[i].host = allowed_addresses[i+1].host; - allowed_addresses[i+1].host = tmpi; - - tmps = allowed_addresses[i].port; - allowed_addresses[i].port = allowed_addresses[i+1].port; - allowed_addresses[i+1].port = tmps; - - remaining = 1; /* yay for bubble sorting! */ - } - } - } - while (remaining); - - /* - * Now we're sorted. But, the local player is referred to by both his - * player number and player index ZERO, so bump everyone up one to - * their actual index and fill in local player as item zero. - */ - - memmove(&allowed_addresses[1], &allowed_addresses[0], - sizeof(allowed_addresses) - sizeof(allowed_addresses[0])); - allowed_addresses[0].host = myip; - - gcom->myconnectindex = 0; - for (i = 1; i <= gcom->numplayers; i++) - { - ip = (allowed_addresses[i].host); - - - if (ip == myip) - { - if (udpport == allowed_addresses[i].port) - gcom->myconnectindex = i; - } - - initprintf("network: player #%i at %s:%i\n", i,static_ipstring(ip),allowed_addresses[i].port); - } -// assert(gcom->myconnectindex); - - initprintf("network: We are player #%i\n", gcom->myconnectindex); - - return(1); -} - -/* client init. */ -static int32_t connect_to_server(gcomtype *gcom, int32_t myip) -{ - PacketPeerGreeting packet; - uint16_t my_id = 0; - int32_t i; - int32_t rc; - int32_t ip; - uint16_t port; - int32_t first_send = 1; - uint16_t heard_from[MAXPLAYERS]; - uint32_t resendat; - int32_t max; - int32_t remaining; - - memset(heard_from, '\0', sizeof(heard_from)); - - gcom->numplayers = 2; - - while (my_id == 0) /* player number is based on id, low to high. */ - { - my_id = (unsigned short)GetTickCount(); - // my_id = (uint16_t) rand(); - } - - initprintf("network: Using 0x%X as client ID\n", my_id); - - resendat = getticks(); - remaining = max = gcom->numplayers - 1; - - initprintf("network: Waiting for %d player%s...\n", remaining, remaining==1 ? "":"s"); - if (remaining == 0) - { - initprintf("Hmmm... don't have time to play with myself!\n"); - return(0); - } - - while (remaining && !quitevent) - { - handleevents(); - - if (resendat <= getticks()) - { - for (i = 0; (i < max) || natfree ; i++) - { - - //only checking one player at a time works - //this is where special formatting of allow lines comes in - if (!heard_from[i]) - { - initprintf("network: %s %s:%d...\n",first_send?"Connecting to":"Retrying", - static_ipstring(allowed_addresses[i].host),allowed_addresses[i].port); - - send_peer_greeting(allowed_addresses[i].host, - allowed_addresses[i].port, - my_id); - } - } - first_send = 0; - resendat += CLIENT_POLL_DELAY; - } - - idle(); - process_udp_send_queue(); - - rc = get_udp_packet(&ip, &port, &packet, sizeof(packet)); - - //this is so we don't get unexpected packet errors from players already heard from - - if ((rc > 0) && (ip) && ((ip != myip) || (port != udpport))) - { - char *ipstr = static_ipstring(ip); - - if (rc != sizeof(packet)) - { - initprintf("network: Missized packet or fragment from %s:%i ?!\n", ipstr, port); - continue; - } - else if (packet.header != HEADER_PEER_GREETING) - { - initprintf("network: Unexpected packet type from %s:%i ?!\n", ipstr, port); - continue; - } - - for (i=0; inumplayers++; - max++; - } - } - } - } - - if (quitevent) - { - initprintf("network: Connection attempt aborted.\n"); - return(0); - } - - /* ok, now everyone is talking to you. Sort them into player numbers... */ - - heard_from[max] = my_id; /* so we sort, too... */ - allowed_addresses[max].host = myip; - allowed_addresses[max].port = udpport; - - do - { - remaining = 0; - for (i = 0; i < max; i++) - { - if (heard_from[i] == heard_from[i+1]) /* blah. */ - { - initprintf("network: ERROR: Two players have the same random ID!\n"); - initprintf("network: ERROR: Please restart the game to generate new IDs.\n"); - return(0); - } - - else if (heard_from[i] > heard_from[i+1]) - { - int32_t tmpi; - int16_t tmps; - - tmps = heard_from[i]; - heard_from[i] = heard_from[i+1]; - heard_from[i+1] = tmps; - - tmpi = allowed_addresses[i].host; - allowed_addresses[i].host = allowed_addresses[i+1].host; - allowed_addresses[i+1].host = tmpi; - - tmps = allowed_addresses[i].port; - allowed_addresses[i].port = allowed_addresses[i+1].port; - allowed_addresses[i+1].port = tmps; - - remaining = 1; /* yay for bubble sorting! */ - } - } - } - while (remaining); - - /* - * Now we're sorted. But, the local player is referred to by both his - * player number and player index ZERO, so bump everyone up one to - * their actual index and fill in local player as item zero. - */ - - memmove(&allowed_addresses[1], &allowed_addresses[0], - sizeof(allowed_addresses) - sizeof(allowed_addresses[0])); - allowed_addresses[0].host = myip; - - gcom->myconnectindex = 0; - for (i = 1; i <= gcom->numplayers; i++) - { - ip = (allowed_addresses[i].host); - - if (ip == myip) - { - if (udpport == allowed_addresses[i].port) - gcom->myconnectindex = i; - } - -// initprintf("network: player #%i with id %d\n",i,heard_from[i]); - } -// assert(gcom->myconnectindex); - -// initprintf("network: We are player #%i\n", gcom->myconnectindex); - - return(1); -} - - -/* peer to peer init. */ -static int32_t connect_to_everyone(gcomtype *gcom, int32_t myip, int32_t bcast) -{ - PacketPeerGreeting packet; - uint16_t my_id = 0; - int32_t i; - int32_t rc; - int32_t ip; - uint16_t port; - int32_t first_send = 1; - uint16_t heard_from[MAXPLAYERS]; - uint32_t resendat; - int32_t max; - int32_t remaining; - - if (bcast) - { - if (gcom->numplayers > 1) - { - initprintf("network: Error: can't do both 'broadcast' and 'allow'.\n"); - return(0); - } - - if (!set_socket_broadcast(1)) - return(0); - - gcom->numplayers = bcast + 1; - } - - memset(heard_from, '\0', sizeof(heard_from)); - - while (my_id == 0) /* player number is based on id, low to high. */ - { - /* struct timeval tv; - gettimeofday(&tv, NULL); - my_id = (unsigned short)tv.tv_usec; //HACK */ - my_id = (uint16_t) rand(); - } - - - initprintf("network: Using 0x%X as client ID\n", my_id); - - resendat = getticks(); - remaining = max = gcom->numplayers - 1; - - initprintf("Waiting for %d player%s...\n", remaining, remaining==1 ? "":"s"); - if (remaining == 0) - { - initprintf("Hmmm... don't have time to play with myself!\n"); - return(0); - } - - while (remaining && !quitevent) - { - handleevents(); - - if (resendat <= getticks()) - { - if (bcast) - { - initprintf("%sroadcasting greeting...\n", first_send ? "B":"Reb"); - /* !!! FIXME: This is...probably not right. */ - send_peer_greeting(0xFFFFFFFF, udpport, my_id); - } - else - { - for (i = 0; (i < max) || natfree ; i++) - { - - //only checking one player at a time works - //this is where special formatting of allow lines comes in - if (natfree) - { - i = itmp; //addfaz router fix - } - - if (!heard_from[i]) - { - initprintf("network: %s %s:%d...\n",first_send?"Connecting to":"Retrying", - static_ipstring(allowed_addresses[i].host),allowed_addresses[i].port); - - send_peer_greeting(allowed_addresses[i].host, - allowed_addresses[i].port, - my_id); - } - - // If this is stun-enabled then don't loop. - if (natfree) - { - break; - } - } - } - first_send = 0; - resendat += CLIENT_POLL_DELAY; - } - - idle(); - process_udp_send_queue(); - - rc = get_udp_packet(&ip, &port, &packet, sizeof(packet)); - - //this is so we don't get unexpected packet errors from players already heard from - - if (natfree) - { - //addfaz router/stun addition *Start* - //this is so we are not dealing with players already heard from. - for (i = 0; i < max; i++) - { - if (ip == allowed_addresses[i].host && - port == allowed_addresses[i].port) - { - if (heard_from[i] != 0) //if we've heard from player already. - { - rc = 0; - } - } - } - //addfaz router/stun addition *End* - } - - - if ((rc > 0) && (ip) && ((ip != myip) || (port != udpport))) - { - char *ipstr = static_ipstring(ip); - - for (i = 0; i < max; i++) - { - - ////addfaz NAT addition *START*//// - if (natfree) - { - if (tmpmax[i] != 1) - { - if (allowed_addresses[i].host == ip) - { - if (allowed_addresses[i].port != port) - { - initprintf("network: Port number for player %d changed from %d to %d.\n",i,allowed_addresses[i].port,port); - /* initprintf("Different player Port Number detected. %s:%i\n",ipstr, - allowed_addresses[i].port); - initprintf("Changed to %s:%i, player may be behind a firewall.\n", ipstr, port); //addfaz NAT addition */ - allowed_addresses[i].port = port; - } - } - } - } - ////addfaz NAT addition *END*//// - - if ((ip == allowed_addresses[i].host) && - (port == allowed_addresses[i].port)) //addfaz NAT line addition - { - break; - } - - if ((bcast) && (allowed_addresses[i].host == 0)) - break; /* select this slot. */ - - } - - if (i == max) - initprintf("network: Disallowed player %s:%d ?!\n", ipstr, port); - - else if (rc != sizeof(packet)) - initprintf("network: Missized packet or fragment from %s:%i ?!\n", ipstr, port); - - else if (packet.header != HEADER_PEER_GREETING) - initprintf("network: Unexpected packet type from %s:%i ?!\n", ipstr, port); - - else if (heard_from[i] == 0) - { - packet.id = B_SWAP16(packet.id); - heard_from[i] = packet.id; - allowed_addresses[i].host = ip; /* bcast needs this. */ - allowed_addresses[i].port = port; - remaining--; - - initprintf("network: Connected to %s:%i (id 0x%X). %d player%s left.\n", - ipstr, port ,(int32_t) packet.id, - remaining, remaining == 1 ? "" : "s"); - - /* make sure they've heard from us at all... */ - /* !!! FIXME: Could be fatal if packet is dropped... */ - send_peer_greeting(allowed_addresses[i].host, - allowed_addresses[i].port, - my_id); - - if (natfree) - { - itmp++; //addfaz router/stun addition (goto next player) - } - else - { - tmpmax[i] = 1; //addfaz line addition - } - } - } - } - - if (quitevent) - { - initprintf("network: Connection attempt aborted.\n"); - return(0); - } - - /* ok, now everyone is talking to you. Sort them into player numbers... */ - - heard_from[max] = my_id; /* so we sort, too... */ - allowed_addresses[max].host = myip; - allowed_addresses[max].port = udpport; - - do - { - remaining = 0; - for (i = 0; i < max; i++) - { - if (heard_from[i] == heard_from[i+1]) /* blah. */ - { - initprintf("network: ERROR: Two players have the same random ID!\n"); - initprintf("network: ERROR: Please restart the game to generate new IDs.\n"); - return(0); - } - - else if (heard_from[i] > heard_from[i+1]) - { - int32_t tmpi; - int16_t tmps; - - tmps = heard_from[i]; - heard_from[i] = heard_from[i+1]; - heard_from[i+1] = tmps; - - tmpi = allowed_addresses[i].host; - allowed_addresses[i].host = allowed_addresses[i+1].host; - allowed_addresses[i+1].host = tmpi; - - tmps = allowed_addresses[i].port; - allowed_addresses[i].port = allowed_addresses[i+1].port; - allowed_addresses[i+1].port = tmps; - - remaining = 1; /* yay for bubble sorting! */ - } - } - } - while (remaining); - - /* - * Now we're sorted. But, the local player is referred to by both his - * player number and player index ZERO, so bump everyone up one to - * their actual index and fill in local player as item zero. - */ - - memmove(&allowed_addresses[1], &allowed_addresses[0], - sizeof(allowed_addresses) - sizeof(allowed_addresses[0])); - allowed_addresses[0].host = myip; - - gcom->myconnectindex = 0; - for (i = 1; i <= gcom->numplayers; i++) - { - ip = (allowed_addresses[i].host); - - - if (ip == myip) - { - if (udpport == allowed_addresses[i].port) - gcom->myconnectindex = i; - } - - initprintf("network: player #%i at %s:%i\n", i,static_ipstring(ip),allowed_addresses[i].port); - } -// assert(gcom->myconnectindex); - - initprintf("network: We are player #%i\n", gcom->myconnectindex); - - /* - * Ok, we should have specific IPs and ports for all players, and - * therefore shouldn't broadcast anymore. Disable permission to do so, - * just in case, so we aren't flooding the LAN with broadcasted packets. - */ - set_socket_broadcast(0); - - return(1); -} - -static int32_t parse_ip(const char *str, int32_t *ip) -{ - int32_t ip1, ip2, ip3, ip4; - - if (Bstrcasecmp(str, "any") == 0) - { - *ip = 0; - return(1); - } - - if (sscanf(str, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4) != 4) - { - initprintf("\"%s\" is not a valid IP address.\n", str); - return(0); - } - - /* we _should_ check that 0 <= ip? <= 255, but it'll fail later anyhow. */ - - *ip = (((ip1 & 0xFF) << 24) | - ((ip2 & 0xFF) << 16) | - ((ip3 & 0xFF) << 8) | - ((ip4 & 0xFF))); - - return(1); -} - -static int32_t parse_interface(char *str, int32_t *ip, uint16_t *udpport) -{ - char *ptr = strchr(str, ':'); - if (ptr) /* portnum specified? */ - *ptr = '\0'; - - if (!parse_ip(str, ip)) - return(0); - - *udpport = BUILD_DEFAULT_UDP_PORT; - if (ptr != NULL) /* port specified? */ - { - ptr++; - if (Bstrcasecmp(ptr, "any") == 0) - *udpport = 0; - else - *udpport = (int16_t) atoi(ptr); - } - - return(1); -} - -static int32_t initialize_sockets(void) -{ -#if PLATFORM_WIN32 - int32_t rc; - WSADATA data; -// initprintf("initializing WinSock...\n"); - rc = WSAStartup(0x0101, &data); - if (rc != 0) - { - initprintf("WinSock failed to initialize! [err==%d].\n", rc); - return(0); - } - else - { - /* initprintf("WinSock initialized.\n"); - initprintf(" - Caller uses version %d.%d, highest supported is %d.%d.\n", - data.wVersion >> 8, data.wVersion & 0xFF, - data.wHighVersion >> 8, data.wHighVersion & 0xFF); - initprintf(" - Implementation description: [%s].\n", data.szDescription); - initprintf(" - System status: [%s].\n", data.szSystemStatus); - initprintf(" - Max sockets: %d.\n", data.iMaxSockets); - initprintf(" - Max UDP datagram size: %d.\n", data.iMaxUdpDg); */ - } -#endif - - return(1); -} - -static void deinitialize_sockets(void) -{ -#if PLATFORM_WIN32 - WSACleanup(); -#endif -} - -int32_t isvalidipaddress(char *st) -{ - int32_t i, bcnt, num; - - bcnt = 0; num = 0; - for (i=0; st[i]; i++) - { - if (st[i] == '.') { bcnt++; num = 0; continue; } - if (st[i] == ':') - { - if (bcnt != 3) return(0); - num = 0; - for (i++; st[i]; i++) - { - if ((st[i] >= '0') && (st[i] <= '9')) - { num = num*10+st[i]-'0'; if (num >= 65536) return(0); } - else return(0); - } - return(1); - } - if ((st[i] >= '0') && (st[i] <= '9')) - { num = num*10+st[i]-'0'; if (num >= 256) return(0); } - - } - return(bcnt == 3); -} - -static int32_t parse_udp_config(int32_t argc, char **argv, gcomtype *gcom) -{ - char *buf; - char *tok; - char *ptr; - int32_t ip = 0; /* interface */ - int32_t bcast = 0; - - buf = read_whole_file(argv[0]); /* we must free this. */ - if (buf == NULL) - { - // do JF-style argv parsing here - int32_t i, j, daindex; - int32_t danetmode = 255; - char *st; - - daindex = 0; - - // if (!argv) return 0; - // go looking for the port, if specified - for (i=0; i 1024 && j<65535) udpport = j; - - initprintf("network: Using port %d\n", udpport); - } - } - - for (i=0; inumplayers = 1; - if (argv[i][2] == '0') - { - danetmode = 0; - udpmode = udpmode_client; - if ((argv[i][3] == ':') && (argv[i][4] >= '0') && (argv[i][4] <= '9')) - { - udpmode = udpmode_server; - gcom->numplayers = (argv[i][4]-'0'); - if ((argv[i][5] >= '0') && (argv[i][5] <= '9')) gcom->numplayers = gcom->numplayers*10+(argv[i][5]-'0'); - initprintf("network: %d-player game server\n", gcom->numplayers--); - } - initprintf("network: Master-slave mode\n"); - } - else if (argv[i][2] == '1') - { - danetmode = 1; - udpmode = udpmode_peer; - myconnectindex = daindex; -// daindex++; - initprintf("network: Peer-to-peer mode\n"); - } - continue; - } - else if ((argv[i][1] == 'P') || (argv[i][1] == 'p')) continue; - } - - st = Bstrdup(argv[i]); - if (!st) break; - if (isvalidipaddress(st)) - { -// if ((danetmode == 1) && (daindex == myconnectindex)) daindex++; - parse_interface(st, &allowed_addresses[daindex].host, &allowed_addresses[daindex].port); - initprintf("network: Player %d at %s:%d\n",daindex,st,allowed_addresses[daindex].port); - daindex++; - } - else - { - struct hostent * lph; - uint16_t pt = BUILD_DEFAULT_UDP_PORT; - - for (j=0; st[j]; j++) - if (st[j] == ':') - { pt = (uint16_t)atol(&st[j+1]); st[j] = 0; break; } - if ((lph = gethostbyname(st))) - { -// if ((danetmode == 1) && (daindex == myconnectindex)) daindex++; - allowed_addresses[daindex].host = ntohl(*(int32_t *)lph->h_addr); - allowed_addresses[daindex].port = pt; - initprintf("network: Player %d at %s:%d (%s)\n",daindex, - inet_ntoa(*(struct in_addr *)lph->h_addr),pt,argv[i]); - daindex++; - } - else initprintf("network: Failed resolving %s\n",argv[i]); - } - Bfree(st); - } - if ((danetmode == 255) && (daindex)) { gcom->numplayers = 2; udpmode = udpmode_client; } //an IP w/o /n# defaults to /n0 - // if ((numplayers >= 2) && (daindex) && (!danetmode)) myconnectindex = 1; - if (daindex > gcom->numplayers) gcom->numplayers = daindex; - } - else - { - initprintf("network: Using '%s' as configuration file\n", argv[0]); - - ptr = buf; - while ((tok = get_token(&ptr)) != NULL) - { - int32_t bogus = 1; - - if (Bstrcasecmp(tok, "interface") == 0) - { - if ((tok = get_token(&ptr)) && - (parse_interface(tok, &ip, &udpport))) - { - bogus = 0; - } - initprintf("network: Using interface %s:%d\n", - static_ipstring(ip), (int32_t) udpport); - } - - else if (Bstrcasecmp(tok, "mode") == 0) - { - if ((tok = get_token(&ptr)) != NULL) - { - bogus = 0; - if (Bstrcasecmp(tok, "server") == 0) - udpmode = udpmode_server; - else if (Bstrcasecmp(tok, "client") == 0) - udpmode = udpmode_client; - else if (Bstrcasecmp(tok, "peer") == 0) - udpmode = udpmode_peer; - else - bogus = 1; - - if (!bogus) - initprintf("You want to be in [%s] mode\n", tok); - } - } - - else if (Bstrcasecmp(tok, "broadcast") == 0) - { - if ((tok = get_token(&ptr)) != NULL) - { - bcast = atoi(tok); - if (bcast > MAXPLAYERS - 1) - { - initprintf("WARNING: Too many broadcast players.\n"); - bcast = MAXPLAYERS - 1; - } - - bogus = 0; - } - } - - else if (Bstrcasecmp(tok, "allow") == 0) - { - int32_t host; - uint16_t port=BUILD_DEFAULT_UDP_PORT; - if ((tok = get_token(&ptr)) != NULL) - { - if (gcom->numplayers >= MAXPLAYERS - 1) - initprintf("WARNING: Too many allowed IP addresses.\n"); - - else if (parse_interface(tok, &host, &port)) - { - allowed_addresses[gcom->numplayers].host = host; - allowed_addresses[gcom->numplayers].port = port; - gcom->numplayers++; - bogus = 0; - } - } - } - - else if (Bstrcasecmp(tok, "players") == 0) - { - if ((tok = get_token(&ptr)) != NULL) - { - bogus = 0; - if (udpmode == udpmode_server) - gcom->numplayers = atoi(tok)-1; - else - bogus = 1; - } - } - - if (bogus) - initprintf("bogus token! [%s]\n", tok); - } - - Bfree(buf); - } - - if (open_udp_socket(ip, udpport)) - { - gcom->numplayers++; /* that's you. */ - if (udpmode == udpmode_server) - return(wait_for_other_players(gcom, ip)); - else if (udpmode == udpmode_client) - return(connect_to_server(gcom, ip)); - else if (udpmode == udpmode_peer) - return(connect_to_everyone(gcom, ip, bcast)); - - initprintf("wtf?!"); /* Should be handled by a udpmode above... */ -// assert(0); - } - - return(0); -} - - -gcomtype *init_network_transport(int32_t argc, char **argv) -{ - gcomtype *retval; - -// initprintf("\n\nUDP NETWORK TRANSPORT INITIALIZING...\n"); - - if (!initialize_sockets()) - return(NULL); - - srand(time(NULL)); - - retval = (gcomtype *)Bmalloc(sizeof(gcomtype)); - if (retval != NULL) - { - int32_t rc; -// char *cfgfile = ARGV[argpos]; - - memset(retval, '\0', sizeof(gcomtype)); - memset(allowed_addresses, '\0', sizeof(allowed_addresses)); - udpsocket = -1; - udpport = BUILD_DEFAULT_UDP_PORT; - udpmode = udpmode_peer; - - rc = parse_udp_config(argc, argv, retval); - - if (!rc) - { - Bfree(retval); - deinit_network_transport(NULL); - return(NULL); - } -// retval->gametype = 3; /* gametype: 1-serial,2-modem,3-net */ - } - - return(retval); -} - - -void deinit_network_transport(gcomtype *gcom) -{ -// initprintf("\n\nUDP NETWORK TRANSPORT DEINITIALIZING...\n"); - - if (gcom != NULL) - { - initprintf(" ...freeing gcom structure...\n"); - Bfree(gcom); - } - - if ((signed)udpsocket != -1) - { - initprintf(" ...closing socket...\n"); - set_socket_blockmode(1); /* block while socket drains. */ - shutdown(udpsocket, SOCKET_SHUTDOWN_BOTH); - socketclose(udpsocket); - udpsocket = -1; - } - - deinitialize_sockets(); - - initprintf("UDP networking uninitialized successfully.\n"); -} - - -void callcommit(void) -{ - int32_t ip, i, rc; - uint16_t port; - - if ((signed)udpsocket == -1) - return; - - process_udp_send_queue(); - - switch (gcom->command) - { - case COMMIT_CMD_GET: - rc = get_udp_packet(&ip, &port, gcom->buffer, sizeof(gcom->buffer)); - if (rc > 0) - { - gcom->numbytes = rc; /* size of new packet. */ - for (i = 1; i <= gcom->numplayers; i++) - { - if ((allowed_addresses[i].host == ip) && - (allowed_addresses[i].port == port)) - { - gcom->other = i; - return; - } - } - /* if you manage to hit this, it'll report no packet avail. */ - } - - gcom->numbytes = 0; - gcom->other = -1; /* no packet available. */ - break; - - case COMMIT_CMD_SEND: - if ((gcom->other < 0) || (gcom->other > gcom->numplayers)) - { - initprintf("NET TRANSPORT ERROR: send to player out of range\n"); - return; - } - - ip = allowed_addresses[gcom->other].host; - if (ip == 0) /* dropped player? */ - return; - - port = allowed_addresses[gcom->other].port; - - if (!send_udp_packet(ip, port, gcom->buffer, gcom->numbytes)) - { - initprintf("NET TRANSPORT ERROR: send failed to %s:%d\n", - static_ipstring(ip), (int32_t) port); - } - break; - - case COMMIT_CMD_SENDTOALL: - /* skip player zero, 'cause that's a duplicate of local IP. */ - for (i = 1; i <= gcom->numplayers; i++) - { - ip = allowed_addresses[i].host; - if (ip == 0) /* dropped player? */ - continue; - - port = allowed_addresses[i].port; - - if (!send_udp_packet(ip, port, gcom->buffer, gcom->numbytes)) - { - initprintf("NET TRANSPORT ERROR: send failed to %s:%d\n", - static_ipstring(ip), (int32_t) port); - } - } - break; - - case COMMIT_CMD_SENDTOALLOTHERS: - /* skip player zero, 'cause that's a duplicate of local IP. */ - for (i = 1; i <= gcom->numplayers; i++) - { - if (i == gcom->myconnectindex) /* local player. */ - continue; - - ip = allowed_addresses[i].host; - if (ip == 0) /* dropped player? */ - continue; - - port = allowed_addresses[i].port; - - if (!send_udp_packet(ip, port, gcom->buffer, gcom->numbytes)) - { - initprintf("NET TRANSPORT ERROR: send failed to %s:%d\n", - static_ipstring(ip), (int32_t) port); - } - } - break; - - /* ?! - case COMMIT_CMD_SCORE: - break; - */ - - default: - initprintf("NET TRANSPORT ERROR: Unknown command %d\n", gcom->command); - gcom->other = -1; /* oh well. */ - break; - } -} - -/* end of mmulti.c ... */ - + COMMIT_CMD_SEND = 1, + COMMIT_CMD_GET = 2, + COMMIT_CMD_SENDTOALL = 3, + COMMIT_CMD_SENDTOALLOTHERS = 4, + COMMIT_CMD_SCORE = 5, +}; + +typedef struct gcomtype_t +{ + int16_t command; /* 1-send, 2-get */ + int16_t other; /* dest for send, set by get (-1 = no packet) */ + int16_t numbytes; + int16_t myconnectindex; + int16_t numplayers; + int16_t filler; + char buffer[MAXPACKETSIZE]; +} gcomtype; +static gcomtype *gcom; + +/* +// +// Packet queue data structs +// +typedef struct packet_wrapper +{ + unsigned long packetnumber; + gcomtype packet; +} PACKETWRAPPER; + +typedef PACKETWRAPPER packet_buffer; + +unsigned long currentpacketnumber[MAXPLAYERS]; + +// +// Packet Buffer +// +packet_buffer pBuff[256]; +*/ + + +/* +typedef struct +{ + char buffer[MAXPACKETSIZE]; +}PACKET; +*/ + +//typedef std::vector PacketQueue; + +static struct allowed_addr_t +{ + int32_t host; + uint16_t port; +} allowed_addresses[MAXPLAYERS]; /* only respond to these IPs. */ + +// Queue of out going packets. +//PacketQueue outgoingPacketQueue; +//outgoingPacketQueue.reserve(128); + +gcomtype *init_network_transport(int32_t argc, char **argv); +void deinit_network_transport(gcomtype *gcom); +//void callcommit(void); +void mmulti_dosendpackets(int32_t other); + + +static void initcrc(void) +{ + int32_t i, j, k, a; + + for (j=0; j<256; j++) /* Calculate CRC table */ + { + k = (j<<8); a = 0; + for (i=7; i>=0; i--) + { + if (((k^a)&0x8000) > 0) + a = ((a<<1)&65535) ^ 0x1021; /* 0x1021 = genpoly */ + else + a = ((a<<1)&65535); + k = ((k<<1)&65535); + } + crctable[j] = (a&65535); + } +} + + +int32_t getcrc(char *buffer, int32_t bufleng) +{ + int32_t i, j; + + j = 0; + for (i=bufleng-1; i>=0; i--) updatecrc16(j,buffer[i]); + return(j&65535); +} + +void mmulti_initmultiplayers(int32_t argc, char **argv) +{ + int32_t i; + + UNREFERENCED_PARAMETER(argc); + + initcrc(); + for (i=0; i 0; i--) + { + const char *arg = argv[i]; + char ch = *arg; + if ((ch == '-') || (ch == '/')) + { + if (Bstrcasecmp(arg + 1, "net") == 0) + break; + } + } +#endif + + if (!argc) + { +// initprintf("network: No configuration file specified!\n"); + numplayers = 1; myconnectindex = 0; + connecthead = 0; connectpoint2[0] = -1; + return; + } + + gcom = init_network_transport(argc, argv); + if (gcom == NULL) + { + initprintf("Network transport initialization failed. Aborting...\n"); + numplayers = 1; myconnectindex = 0; + connecthead = 0; connectpoint2[0] = -1; + return; + } + + numplayers = gcom->numplayers; + myconnectindex = gcom->myconnectindex-1; +#if (SIMULATEERRORS != 0) + srand(myconnectindex*24572457+345356); +#endif + connecthead = 0; + for (i=0; i lasterrorgotnum[other]) + { + lasterrorgotnum[other]++; + initprintf(" MeWant %ld",incnt[other]&255); + } +#endif + + if (outcntplc[other]+1 == outcntend[other]) + { /* Send 1 sub-packet */ + k = 0; + gcom->buffer[k++] = (outcntplc[other]&255); + gcom->buffer[k++] = (errorgotnum[other]&7)+((errorresendnum[other]&7)<<3); + gcom->buffer[k++] = (incnt[other]&255); + + j = bakpacketptr[other][outcntplc[other]&255]; + messleng = bakpacketlen[other][outcntplc[other]&255]; + for (i=0; ibuffer[k++] = bakpacketbuf[(i+j)&(BAKSIZ-1)]; + outcntplc[other]++; + } + else + { /* Send 2 sub-packets */ + k = 0; + gcom->buffer[k++] = (outcntplc[other]&255); + gcom->buffer[k++] = (errorgotnum[other]&7)+((errorresendnum[other]&7)<<3)+128; + gcom->buffer[k++] = (incnt[other]&255); + + /* First half-packet */ + j = bakpacketptr[other][outcntplc[other]&255]; + messleng = bakpacketlen[other][outcntplc[other]&255]; + gcom->buffer[k++] = (uint8_t)(messleng&255); + gcom->buffer[k++] = (uint8_t)(messleng>>8); + for (i=0; ibuffer[k++] = bakpacketbuf[(i+j)&(BAKSIZ-1)]; + outcntplc[other]++; + + /* Second half-packet */ + j = bakpacketptr[other][outcntplc[other]&255]; + messleng = bakpacketlen[other][outcntplc[other]&255]; + for (i=0; ibuffer[k++] = bakpacketbuf[(i+j)&(BAKSIZ-1)]; + outcntplc[other]++; + + } + + dacrc = getcrc(gcom->buffer,(int16_t)k); + gcom->buffer[k++] = (dacrc&255); + gcom->buffer[k++] = (dacrc>>8); + + gcom->other = other+1; + gcom->numbytes = k; + +#if (SHOWSENDPACKETS) + initprintf("Send(%ld): ",gcom->other); + for (i=0; inumbytes; i++) initprintf("%2x ",gcom->buffer[i]); + initprintf("\n"); +#endif + +#if (SIMULATEERRORS != 0) + if (!(rand()&SIMULATEERRORS)) gcom->buffer[rand()%gcom->numbytes] = (rand()&255); + if (rand()&SIMULATEERRORS) +#endif + { + gcom->command = COMMIT_CMD_SEND; + callcommit(); + } +} + + +void mmulti_sendpacket(int32_t other, char *bufptr, int32_t messleng) +{ + int32_t i = 0; + int32_t j = 0; + + if (numplayers < 2) return; + + i = 0; + if (bakpacketlen[other][(outcntend[other]-1)&255] == messleng) + { + j = bakpacketptr[other][(outcntend[other]-1)&255]; + for (i=messleng-1; i>=0; i--) + if (bakpacketbuf[(i+j)&(BAKSIZ-1)] != bufptr[i]) break; + } + bakpacketlen[other][outcntend[other]&255] = messleng; + + if (i < 0) /* Point to last packet to save space on bakpacketbuf */ + bakpacketptr[other][outcntend[other]&255] = j; + else + { + bakpacketptr[other][outcntend[other]&255] = bakpacketplc; + for (i=0; i=0; i=connectpoint2[i]) + { + if (i != myconnectindex) + mmulti_sendpacket(i,tempbuf,2L); + if ((udpmode == udpmode_client) && (myconnectindex != connecthead)) break; //slaves in M/S mode only send to master + } +} + +int32_t mmulti_getoutputcirclesize(void) +{ + return(0); +} + +int32_t mmulti_getpacket(int32_t *other, char *bufptr) +{ + int32_t i, messleng; + uint16_t dacrc; + + if (numplayers < 2 || gcom == NULL) return(0); + + for (i=connecthead; i>=0; i=connectpoint2[i]) + { + if (i != myconnectindex) + { + // FIXME: this is probably not so great + if (udpmode != udpmode_peer) mmulti_dosendpackets(i); + if (totalclock < lastsendtime[i]) lastsendtime[i] = totalclock; + if (totalclock > lastsendtime[i]+timeoutcount) + { +#if (PRINTERRORS) + initprintf(" TimeOut!"); +#endif + errorgotnum[i] = errorfixnum[i]+1; + + if ((outcntplc[i] == outcntend[i]) && (outcntplc[i] > 0)) + { outcntplc[i]--; lastsendtime[i] = totalclock; } + else + lastsendtime[i] += resendagaincount; + mmulti_dosendpackets(i); + /* } */ + } + } + if ((udpmode == udpmode_client) && (myconnectindex != connecthead)) break; //slaves in M/S mode only send to master + } + + if (inlastpacket != 0) + { + /* 2ND half of good double-packet */ + inlastpacket = 0; + *other = lastpacketfrom; + Bmemcpy(bufptr,lastpacket,lastpacketleng); + return(lastpacketleng); + } + + gcom->command = COMMIT_CMD_GET; + callcommit(); + +#if (SHOWGETPACKETS) + if (gcom->other != -1) + { + initprintf(" Get(%ld): ",gcom->other); + for (i=0; inumbytes; i++) initprintf("%2x ",gcom->buffer[i]); + initprintf("\n"); + } +#endif + + if (gcom->other < 0) return(0); + *other = gcom->other-1; + + messleng = gcom->numbytes; + + dacrc = ((uint16_t)gcom->buffer[messleng-2]); + dacrc += (((uint16_t)gcom->buffer[messleng-1])<<8); + if (dacrc != getcrc(gcom->buffer,(int16_t)(messleng-2))) /* CRC check */ + { +#if (PRINTERRORS) + initprintf("\n%ld CRC",gcom->buffer[0]); +#endif + errorgotnum[*other] = errorfixnum[*other]+1; + return(0); + } + + while ((errorfixnum[*other]&7) != ((gcom->buffer[1]>>3)&7)) + errorfixnum[*other]++; + + if ((gcom->buffer[1]&7) != (errorresendnum[*other]&7)) + { + errorresendnum[*other]++; + outcntplc[*other] = (outcntend[*other]&0xffffff00)+gcom->buffer[2]; + if (outcntplc[*other] > outcntend[*other]) outcntplc[*other] -= 256; + } + + if (gcom->buffer[0] != (incnt[*other]&255)) /* CNT check */ + { + if (((incnt[*other]-gcom->buffer[0])&255) > 32) + { + errorgotnum[*other] = errorfixnum[*other]+1; +#if (PRINTERRORS) + initprintf("\n%ld CNT",gcom->buffer[0]); +#endif + } +#if (PRINTERRORS) + else + { + if (!(gcom->buffer[1]&128)) /* single else double packet */ + initprintf("\n%ld cnt",gcom->buffer[0]); + else + { + if (((gcom->buffer[0]+1)&255) == (incnt[*other]&255)) + { + /* GOOD! Take second half of double packet */ +#if (PRINTERRORS) + initprintf("\n%ld-%ld .û ",gcom->buffer[0],(gcom->buffer[0]+1)&255); +#endif + messleng = ((int32_t)gcom->buffer[3]) + (((int32_t)gcom->buffer[4])<<8); + lastpacketleng = gcom->numbytes-7-messleng; + Bmemcpy(bufptr,&gcom->buffer[messleng+5],lastpacketleng); + incnt[*other]++; + return(lastpacketleng); + } + else + initprintf("\n%ld-%ld cnt ",gcom->buffer[0],(gcom->buffer[0]+1)&255); + } + } +#endif + return(0); + } + + /* PACKET WAS GOOD! */ + if ((gcom->buffer[1]&128) == 0) /* Single packet */ + { +#if (PRINTERRORS) + initprintf("\n%ld û ",gcom->buffer[0]); +#endif + + messleng = gcom->numbytes-5; + + Bmemcpy(bufptr,&gcom->buffer[3],messleng); + + incnt[*other]++; + return(messleng); + } + + /* Double packet */ +#if (PRINTERRORS) + initprintf("\n%ld-%ld ûû ",gcom->buffer[0],(gcom->buffer[0]+1)&255); +#endif + + messleng = ((int32_t)gcom->buffer[3]) + (((int32_t)gcom->buffer[4])<<8); + lastpacketleng = gcom->numbytes-7-messleng; + inlastpacket = 1; lastpacketfrom = *other; + + Bmemcpy(bufptr,&gcom->buffer[5],messleng); + Bmemcpy(lastpacket,&gcom->buffer[messleng+5],lastpacketleng); + + incnt[*other] += 2; + return(messleng); +} + +void mmulti_flushpackets() +{ +#if 1 + int32_t i; + + if (numplayers < 2) return; + + do + { + gcom->command = COMMIT_CMD_GET; + callcommit(); + } + while (gcom->other >= 0); + + for (i=connecthead; i>=0; i=connectpoint2[i]) + { + incnt[i] = 0L; + outcntplc[i] = 0L; + outcntend[i] = 0L; + errorgotnum[i] = 0; + errorfixnum[i] = 0; + errorresendnum[i] = 0; + lastsendtime[i] = totalclock; + } +#endif +} + +void mmulti_generic(int32_t other, char *bufptr, int32_t messleng, int32_t command) +{ + if (numplayers < 2) return; + + gcom->command = command; + gcom->numbytes = min(messleng,MAXPACKETSIZE); + copybuf(bufptr,gcom->buffer,(gcom->numbytes+3)>>2); + gcom->other = other+1; + callcommit(); + +} + +#if PLATFORM_WIN32 +# include +# define EWOULDBLOCK WSAEWOULDBLOCK +# define ECONNREFUSED WSAECONNRESET +# define socklen_t size_t +# define netstrerror() win32netstrerror() +# define neterrno() WSAGetLastError() +# define sockettype SOCKET +# define socketclose(x) closesocket(x) +#else +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# define netstrerror() strerror(errno) +# define neterrno() errno +# define sockettype int32_t +# define socketclose(x) close(x) +# ifndef MSG_ERRQUEUE /* legacy glibc header workaround... */ +# define MSG_ERRQUEUE 0x2000 +# endif +#endif + +#define SOCKET_SHUTDOWN_BOTH 2 + +#include "cache1d.h" /* kopen4load for cfg file. */ + +#define IPSEG1(ip) ((((uint32_t) ip) & 0xFF000000) >> 24) +#define IPSEG2(ip) ((((uint32_t) ip) & 0x00FF0000) >> 16) +#define IPSEG3(ip) ((((uint32_t) ip) & 0x0000FF00) >> 8) +#define IPSEG4(ip) ((((uint32_t) ip) & 0x000000FF) ) + +#define BUILD_DEFAULT_UDP_PORT 23513 /* eh...why not? */ +#define CLIENT_POLL_DELAY 5000 /* ms between pings at peer-to-peer startup. */ +#define HEADER_PEER_GREETING 245 + +static sockettype udpsocket = -1; +static uint16_t udpport = BUILD_DEFAULT_UDP_PORT; + +#if PLATFORM_WIN32 +/* + * Figure out what the last failing Win32 API call was, and + * generate a human-readable string for the error message. + * + * The return value is a static buffer that is overwritten with + * each call to this function. + * + * Code lifted from PhysicsFS: http://icculus.org/physfs/ + */ +static const char *win32netstrerror(void) +{ + static TCHAR msgbuf[255]; + TCHAR *ptr = msgbuf; + + FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + WSAGetLastError(), /*GetLastError(),*/ + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ + msgbuf, + sizeof(msgbuf) / sizeof(TCHAR), + NULL + ); + + /* chop off newlines. */ + for (ptr = msgbuf; *ptr; ptr++) + { + if ((*ptr == '\n') || (*ptr == '\r')) + { + *ptr = ' '; + break; + } /* if */ + } /* for */ + + return((const char *) msgbuf); +} /* win32strerror */ +#endif + +static char *static_ipstring(int32_t ip) +{ + static char s[16]; + Bsprintf(s, "%u.%u.%u.%u", IPSEG1(ip), IPSEG2(ip), IPSEG3(ip), IPSEG4(ip)); + return(s); +} + + +static int32_t send_udp_packet(int32_t ip, uint16_t port, void *pkt, size_t pktsize) +{ + /* !!! FIXME: See if this would ever block. */ + /* !!! FIXME: See if this would send a partial packet. */ + struct sockaddr_in addr; + int32_t rc; + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(ip); + addr.sin_port = htons(port); + + rc = sendto(udpsocket, pkt, pktsize, 0, + (struct sockaddr *) &addr, sizeof(addr)); + + if (rc != (int32_t) pktsize) + { + initprintf("sendto err rc==%d when sending %d to %s:%d [%s].\n", + rc, (int32_t) pktsize, static_ipstring(ip), (int32_t) port, + netstrerror()); + return(0); + } + + /*initprintf("Sent %d byte packet to %s:%d\n", (int32_t) pktsize, static_ipstring(ip), (int32_t) port);*/ + + return(1); +} + + +static void process_udp_send_queue(void) +{ + /* Fill this in if the non-blocking socket becomes an issue. */ +} + + +static int32_t get_udp_packet(int32_t *ip, uint16_t *_port, void *pkt, size_t pktsize) +{ + int32_t err = 0; + struct sockaddr_in addr; + uint16_t port; + socklen_t fromlen = sizeof(addr); + int32_t valid = 0; + int32_t i; + + /* FIXME: Will this ever receive a partial packet? */ + int32_t rc = recvfrom(udpsocket, pkt, pktsize, 0, (struct sockaddr *) &addr, +#ifdef _WIN32 + (int32_t *)&fromlen); +#else + (uint32_t *)&fromlen); +#endif + + if (rc == -1) + err = neterrno(); + +#if !PLATFORM_WIN32 + /* !!! FIXME: Linux specific? */ + if (rc == -1) /* fill in the addr structure on error... */ + { + socklen_t l = sizeof(addr); + recvfrom(udpsocket, NULL, 0, MSG_ERRQUEUE, + (struct sockaddr *) &addr, &l); + } +#endif + + *ip = ntohl(addr.sin_addr.s_addr); + port = ntohs(addr.sin_port); + if (_port) + *_port = port; + + /* + * Reject packets from unallowed IPs. Prevents (ha) DoS attacks and + * other confusion... + */ + if (gcom == NULL) + { + if (natfree) //if stun is enabled + { + if ((allowed_addresses[itmp].host == *ip) + && (allowed_addresses[itmp].port == port)) + { + valid = 1; //only accept packets from the current player (itmp) and no one else + } + else + { + return 0; //reject packets from other players + } + } + else + { + valid = 1; + } + } + else + { + for (i = 1; i <= gcom->numplayers; i++) + { + if ((allowed_addresses[i].host == *ip) + && (allowed_addresses[i].port == port)) + + { + valid = i; + + //initprintf ("Packet received from %s:%d\n",static_ipstring(*ip), (int32_t) port); + + break; + } + + } + } + + /*if (!valid) + { + + static int32_t unallowed_ip_spam = 0; + if (unallowed_ip_spam <= 100) + { + initprintf("Packet received from unallowed IP %s:%d\n", + static_ipstring(*ip), (int32_t) port); + if (unallowed_ip_spam == 100) + initprintf("(Disabling further unallowed IP spam.)\n"); + unallowed_ip_spam++; + } + + return(0); + } */ + + if (rc == -1) + { + if ((err == EAGAIN) || (err == EWOULDBLOCK)) + rc = 0; + + else if (err == ECONNREFUSED) //"connection reset by peer" in winsock + { + + // This means that we sent a packet to an unopened port, and + // it responded by telling us to piss off. Take them out of the + // allowed list. We check gcom so that we don't worry about this + // during detection when game might still be loading elsewhere. + + if (gcom != NULL) + { + allowed_addresses[valid].host = 0; + initprintf("%s:%d refused packets. Removed from game.\n", + static_ipstring(*ip), (int32_t) port); + } + // !!! FIXME: Actually boot player, too. + } + + else + { + initprintf("recvfrom err rc==%d when getting %d from %s:%d [%s].\n", + rc, (int32_t) pktsize, static_ipstring(*ip), (int32_t) port, + netstrerror()); + } + } +//else initprintf("Got %d byte packet from %s:%d\n", (int32_t) rc, static_ipstring(*ip), (int32_t) port); + //initprintf( "IP from client %d", *ip); + return(rc); +} + + +static char *read_whole_file(const char *cfgfile) +{ + char *buf; + int32_t len, rc; + int32_t handle; + + if (cfgfile == NULL) + return(NULL); + + handle = kopen4load((char *)cfgfile, 0); + if (handle == -1) + { +// initprintf("ERROR: Failed to open config file [%s].\n", cfgfile); + return(NULL); + } + + len = kfilelength(handle); + buf = (char *) Bmalloc(len + 2); + if (!buf) + { + kclose(handle); + return(NULL); + } + + rc = kread(handle, buf, len); + kclose(handle); + if (rc != len) + { + Bfree(buf); + return(NULL); + } + + buf[len] = '\0'; + buf[len+1] = '\0'; + return(buf); +} + +static char *get_token(char **ptr) +{ + char *retval; + char *p = *ptr; + if (*p == '\0') + return(NULL); + + while ((*p != '\0') && (isspace(*p))) + p++; + + if (*p == '\0') /* nothing but whitespace. */ + return(NULL); + + retval = p; + while ((*p != '\0') && (!isspace(*p))) + p++; + + *p = '\0'; + *ptr = p + 1; + + /*initprintf("Got token [%s].\n", retval);*/ + return(retval); +} + +static int32_t set_socket_blockmode(int32_t onOrOff) +{ + uint32_t flags; + int32_t rc = 0; + + /* set socket to be (non-)blocking. */ + +#if PLATFORM_WIN32 + flags = (onOrOff) ? 0 : 1; + rc = (ioctlsocket(udpsocket, FIONBIO, (void *) &flags) == 0); +#else + flags = fcntl(udpsocket, F_GETFL, 0); + if ((signed)flags != -1) + { + if (onOrOff) + flags &= ~O_NONBLOCK; + else + flags |= O_NONBLOCK; + rc = (fcntl(udpsocket, F_SETFL, flags) == 0); + } +#endif + + if (!rc) + { + initprintf("set socket %sblocking failed: %s\n", + ((onOrOff) ? "" : "non-"), netstrerror()); + } + + return(rc); +} + + +static int32_t set_socket_broadcast(int32_t onOrOff) +{ + int32_t f = (onOrOff) ? 1 : 0; + int32_t rc; + + /* give socket clearance to broadcast. */ + rc = setsockopt(udpsocket, SOL_SOCKET, SO_BROADCAST, (char *)(&f), sizeof(f)) == 0; + if (!rc) + { + initprintf("%sset SO_BROADCAST failed: %s\n", + ((onOrOff) ? "" : "un"), netstrerror()); + } + + return(rc); +} + + +static int32_t open_udp_socket(int32_t ip, int32_t port) +{ + struct sockaddr_in addr; + +// initprintf("Setting up UDP interface %s:%d...\n", static_ipstring(ip), port); + if (natfree) + { + //initprintf("Stun is currently %s\n", (natfree) ? "Enabled":"Disabled"); + initprintf("network: Stun enabled\n"); + } + + udpsocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + if ((signed)udpsocket == -1) + { + initprintf("network: socket creation failed: %s\n", netstrerror()); + return(0); + } + + if (!set_socket_blockmode(0)) + return(0); + +#if !PLATFORM_WIN32 + { + /* !!! FIXME: Might be Linux (not Unix, not BSD, not WinSock) specific. */ + int32_t flags = 1; + setsockopt(udpsocket, IPPROTO_IP, IP_RECVERR, &flags, sizeof(flags)); + } +#endif + + memset(&addr, '\0', sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(ip); + addr.sin_port = htons((uint16_t)port); + if (bind(udpsocket, (struct sockaddr *) &addr, sizeof(addr)) == -1) + { + initprintf("network: socket binding failed: %s\n", netstrerror()); + return(0); + } + + return(1); +} + +typedef struct peergreeting_t +{ + char header; /* always HEADER_PEER_GREETING (245). */ + uint16_t id; +} PacketPeerGreeting; + + +static void send_peer_greeting(int32_t ip, uint16_t port, int16_t myid) +{ + PacketPeerGreeting packet; + memset(&packet, '\0', sizeof(packet)); + packet.header = HEADER_PEER_GREETING; + packet.id = B_SWAP16(myid); + send_udp_packet(ip, port, &packet, sizeof(packet)); +} + +/* server init. */ +static int32_t wait_for_other_players(gcomtype *gcom, int32_t myip) +{ + PacketPeerGreeting packet; + uint16_t my_id = 1; // we're always 1 so we sort as the first player + int32_t i, j; + int32_t rc; + int32_t ip; + uint16_t port; + uint16_t heard_from[MAXPLAYERS]; + int32_t max; + int32_t remaining; + + memset(heard_from, '\0', sizeof(heard_from)); + + remaining = max = gcom->numplayers - 1; + + initprintf("Waiting for %d player%s...\n", remaining, remaining==1 ? "":"s"); + if (remaining == 0) + { + initprintf("Hmmm... don't have time to play with myself!\n"); + return(0); + } + + while (remaining && !quitevent) + { + handleevents(); + + idle(); + + process_udp_send_queue(); + + rc = get_udp_packet(&ip, &port, &packet, sizeof(packet)); + + //this is so we don't get unexpected packet errors from players already heard from + + if ((rc > 0) && (ip) && ((ip != myip) || (port != udpport))) + { + char *ipstr = static_ipstring(ip); + + if (rc != sizeof(packet)) + { + initprintf("network: Missized packet or fragment from %s:%i ?!\n", ipstr, port); + continue; + } + else if (packet.header != HEADER_PEER_GREETING) + { + initprintf("network: Unexpected packet type from %s:%i ?!\n", ipstr, port); + continue; + } + + for (i = 0; i < max; i++) + { + if (!heard_from[i] || heard_from[i] == B_SWAP16(packet.id)) + break; + } + + if (i == max) + initprintf("network: Disallowed player %s:%d ?!\n", ipstr, port); + else if (heard_from[i] == 0) + { + packet.id = B_SWAP16(packet.id); + heard_from[i] = packet.id; + allowed_addresses[i].host = ip; /* bcast needs this. */ + allowed_addresses[i].port = port; + remaining--; + + initprintf("%s:%i (id 0x%X) connected, %d player%s left.\n", + ipstr, (unsigned)port ,(int32_t) packet.id, + remaining, remaining == 1 ? "" : "s"); + + /* make sure they've heard from us at all... */ + /* !!! FIXME: Could be fatal if packet is dropped... */ + + send_peer_greeting(allowed_addresses[i].host, + allowed_addresses[i].port, + my_id); + } + } + } + + if (quitevent) + { + initprintf("network: Connection attempt aborted.\n"); + return(0); + } + + // found all the clients expected so relay all greetings + for (j=max; j>=0; j--) + if (allowed_addresses[j].host) + { + int32_t ii; + + // send another copy of our greeting just in case they missed it + send_peer_greeting(allowed_addresses[j].host, + allowed_addresses[j].port, + my_id); + + for (ii = 0; ii < max; ii++) + send_peer_greeting(allowed_addresses[j].host, + allowed_addresses[j].port, + heard_from[ii]); + + // greeting with 0x1337 id starts the game for clients + send_peer_greeting(allowed_addresses[j].host, + allowed_addresses[j].port, + PACKET_START_GAME); + } + + /* ok, now everyone is talking to you. Sort them into player numbers... */ + + heard_from[max] = my_id; /* so we sort, too... */ + allowed_addresses[max].host = myip; + allowed_addresses[max].port = udpport; + + do + { + remaining = 0; + for (i = 0; i < max; i++) + { + if (heard_from[i] == heard_from[i+1]) /* blah. */ + { + initprintf("network: ERROR: Two players have the same random ID!\n"); + initprintf("network: ERROR: Please restart the game to generate new IDs.\n"); + quitevent = 1; + return(0); + } + + else if (heard_from[i] > heard_from[i+1]) + { + int32_t tmpi; + int16_t tmps; + + tmps = heard_from[i]; + heard_from[i] = heard_from[i+1]; + heard_from[i+1] = tmps; + + tmpi = allowed_addresses[i].host; + allowed_addresses[i].host = allowed_addresses[i+1].host; + allowed_addresses[i+1].host = tmpi; + + tmps = allowed_addresses[i].port; + allowed_addresses[i].port = allowed_addresses[i+1].port; + allowed_addresses[i+1].port = tmps; + + remaining = 1; /* yay for bubble sorting! */ + } + } + } + while (remaining); + + /* + * Now we're sorted. But, the local player is referred to by both his + * player number and player index ZERO, so bump everyone up one to + * their actual index and fill in local player as item zero. + */ + + memmove(&allowed_addresses[1], &allowed_addresses[0], + sizeof(allowed_addresses) - sizeof(allowed_addresses[0])); + allowed_addresses[0].host = myip; + + gcom->myconnectindex = 0; + for (i = 1; i <= gcom->numplayers; i++) + { + ip = (allowed_addresses[i].host); + + + if (ip == myip) + { + if (udpport == allowed_addresses[i].port) + gcom->myconnectindex = i; + } + + initprintf("network: Player #%i at %s:%i\n", i,static_ipstring(ip),allowed_addresses[i].port); + } +// assert(gcom->myconnectindex); + + initprintf("network: Server initialized.\n"); + + return(1); +} + +/* client init. */ +static int32_t connect_to_server(gcomtype *gcom, int32_t myip) +{ + PacketPeerGreeting packet; + uint16_t my_id = 0; + int32_t i; + int32_t rc; + int32_t ip; + uint16_t port; + int32_t first_send = 1; + uint16_t heard_from[MAXPLAYERS]; + uint32_t resendat; + int32_t max; + int32_t remaining; + + memset(heard_from, '\0', sizeof(heard_from)); + + gcom->numplayers = 2; + + while (my_id == 0) /* player number is based on id, low to high. */ + { + srand(myip + udpport); + my_id = rand() % USHRT_MAX; + } + + srand(1); + + initprintf("network: Using 0x%X as client ID\n", my_id); + + resendat = getticks(); + remaining = max = gcom->numplayers - 1; + + initprintf("network: Waiting for %d player%s...\n", remaining, remaining==1 ? "":"s"); + if (remaining == 0) + { + initprintf("Hmmm... don't have time to play with myself!\n"); + return(0); + } + + while (remaining && !quitevent) + { + handleevents(); + + if (resendat <= getticks()) + { + for (i = 0; (i < max) || natfree ; i++) + { + + //only checking one player at a time works + //this is where special formatting of allow lines comes in + if (!heard_from[i]) + { + initprintf("network: %s %s:%d...\n",first_send?"Connecting to":"Retrying", + static_ipstring(allowed_addresses[i].host),allowed_addresses[i].port); + + send_peer_greeting(allowed_addresses[i].host, + allowed_addresses[i].port, + my_id); + } + } + first_send = 0; + resendat += CLIENT_POLL_DELAY; + } + + idle(); + process_udp_send_queue(); + + rc = get_udp_packet(&ip, &port, &packet, sizeof(packet)); + + //this is so we don't get unexpected packet errors from players already heard from + + if ((rc > 0) && (ip) && ((ip != myip) || (port != udpport))) + { + char *ipstr = static_ipstring(ip); + + if (rc != sizeof(packet)) + { + initprintf("network: Missized packet or fragment from %s:%i ?!\n", ipstr, port); + continue; + } + else if (packet.header != HEADER_PEER_GREETING) + { + initprintf("network: Unexpected packet type from %s:%i ?!\n", ipstr, port); + continue; + } + + for (i=0; inumplayers++; + max++; + } + } + } + } + + if (quitevent) + { + initprintf("network: Connection attempt aborted.\n"); + return(0); + } + + /* ok, now everyone is talking to you. Sort them into player numbers... */ + + heard_from[max] = my_id; /* so we sort, too... */ + allowed_addresses[max].host = myip; + allowed_addresses[max].port = udpport; + + do + { + remaining = 0; + for (i = 0; i < max; i++) + { + if (heard_from[i] == heard_from[i+1]) /* blah. */ + { + initprintf("network: ERROR: Two players have the same random ID!\n"); + initprintf("network: ERROR: Please restart the game to generate new IDs.\n"); + return(0); + } + + else if (heard_from[i] > heard_from[i+1]) + { + int32_t tmpi; + int16_t tmps; + + tmps = heard_from[i]; + heard_from[i] = heard_from[i+1]; + heard_from[i+1] = tmps; + + tmpi = allowed_addresses[i].host; + allowed_addresses[i].host = allowed_addresses[i+1].host; + allowed_addresses[i+1].host = tmpi; + + tmps = allowed_addresses[i].port; + allowed_addresses[i].port = allowed_addresses[i+1].port; + allowed_addresses[i+1].port = tmps; + + remaining = 1; /* yay for bubble sorting! */ + } + } + } + while (remaining); + + /* + * Now we're sorted. But, the local player is referred to by both his + * player number and player index ZERO, so bump everyone up one to + * their actual index and fill in local player as item zero. + */ + + memmove(&allowed_addresses[1], &allowed_addresses[0], + sizeof(allowed_addresses) - sizeof(allowed_addresses[0])); + allowed_addresses[0].host = myip; + + gcom->myconnectindex = 0; + for (i = 1; i <= gcom->numplayers; i++) + { + ip = (allowed_addresses[i].host); + + if (ip == myip) + { + if (udpport == allowed_addresses[i].port) + gcom->myconnectindex = i; + } + +// initprintf("network: player #%i with id %d\n",i,heard_from[i]); + } +// assert(gcom->myconnectindex); + +// initprintf("network: We are player #%i\n", gcom->myconnectindex); + + return(1); +} + + +/* peer to peer init. */ +static int32_t connect_to_everyone(gcomtype *gcom, int32_t myip, int32_t bcast) +{ + PacketPeerGreeting packet; + uint16_t my_id = 0; + int32_t i; + int32_t rc; + int32_t ip; + uint16_t port; + int32_t first_send = 1; + uint16_t heard_from[MAXPLAYERS]; + uint32_t resendat; + int32_t max; + int32_t remaining; + + if (bcast) + { + if (gcom->numplayers > 1) + { + initprintf("network: Error: can't do both 'broadcast' and 'allow'.\n"); + return(0); + } + + if (!set_socket_broadcast(1)) + return(0); + + gcom->numplayers = bcast + 1; + } + + memset(heard_from, '\0', sizeof(heard_from)); + + while (my_id == 0) /* player number is based on id, low to high. */ + { + srand(myip + udpport); + my_id = rand() % USHRT_MAX; + } + + srand(1); + + initprintf("network: Using 0x%X as client ID\n", my_id); + + resendat = getticks(); + remaining = max = gcom->numplayers - 1; + + initprintf("Waiting for %d player%s...\n", remaining, remaining==1 ? "":"s"); + if (remaining == 0) + { + initprintf("Hmmm... don't have time to play with myself!\n"); + return(0); + } + + while (remaining && !quitevent) + { + handleevents(); + + if (resendat <= getticks()) + { + if (bcast) + { + initprintf("%sroadcasting greeting...\n", first_send ? "B":"Reb"); + /* !!! FIXME: This is...probably not right. */ + send_peer_greeting(0xFFFFFFFF, udpport, my_id); + } + else + { + for (i = 0; (i < max) || natfree ; i++) + { + + //only checking one player at a time works + //this is where special formatting of allow lines comes in + if (natfree) + { + i = itmp; //addfaz router fix + } + + if (!heard_from[i]) + { + initprintf("network: %s %s:%d...\n",first_send?"Connecting to":"Retrying", + static_ipstring(allowed_addresses[i].host),allowed_addresses[i].port); + + send_peer_greeting(allowed_addresses[i].host, + allowed_addresses[i].port, + my_id); + } + + // If this is stun-enabled then don't loop. + if (natfree) + { + break; + } + } + } + first_send = 0; + resendat += CLIENT_POLL_DELAY; + } + + idle(); + process_udp_send_queue(); + + rc = get_udp_packet(&ip, &port, &packet, sizeof(packet)); + + //this is so we don't get unexpected packet errors from players already heard from + + if (natfree) + { + //addfaz router/stun addition *Start* + //this is so we are not dealing with players already heard from. + for (i = 0; i < max; i++) + { + if (ip == allowed_addresses[i].host && + port == allowed_addresses[i].port) + { + if (heard_from[i] != 0) //if we've heard from player already. + { + rc = 0; + } + } + } + //addfaz router/stun addition *End* + } + + + if ((rc > 0) && (ip) && ((ip != myip) || (port != udpport))) + { + char *ipstr = static_ipstring(ip); + + for (i = 0; i < max; i++) + { + + ////addfaz NAT addition *START*//// + if (natfree) + { + if (tmpmax[i] != 1) + { + if (allowed_addresses[i].host == ip) + { + if (allowed_addresses[i].port != port) + { + initprintf("network: Port number for player %d changed from %d to %d.\n",i,allowed_addresses[i].port,port); + /* initprintf("Different player Port Number detected. %s:%i\n",ipstr, + allowed_addresses[i].port); + initprintf("Changed to %s:%i, player may be behind a firewall.\n", ipstr, port); //addfaz NAT addition */ + allowed_addresses[i].port = port; + } + } + } + } + ////addfaz NAT addition *END*//// + + if ((ip == allowed_addresses[i].host) && + (port == allowed_addresses[i].port)) //addfaz NAT line addition + { + break; + } + + if ((bcast) && (allowed_addresses[i].host == 0)) + break; /* select this slot. */ + + } + + if (i == max) + initprintf("network: Disallowed player %s:%d ?!\n", ipstr, port); + + else if (rc != sizeof(packet)) + initprintf("network: Missized packet or fragment from %s:%i ?!\n", ipstr, port); + + else if (packet.header != HEADER_PEER_GREETING) + initprintf("network: Unexpected packet type from %s:%i ?!\n", ipstr, port); + + else if (heard_from[i] == 0) + { + packet.id = B_SWAP16(packet.id); + heard_from[i] = packet.id; + allowed_addresses[i].host = ip; /* bcast needs this. */ + allowed_addresses[i].port = port; + remaining--; + + initprintf("network: Connected to %s:%i (id 0x%X). %d player%s left.\n", + ipstr, port ,(int32_t) packet.id, + remaining, remaining == 1 ? "" : "s"); + + /* make sure they've heard from us at all... */ + /* !!! FIXME: Could be fatal if packet is dropped... */ + send_peer_greeting(allowed_addresses[i].host, + allowed_addresses[i].port, + my_id); + + if (natfree) + { + itmp++; //addfaz router/stun addition (goto next player) + } + else + { + tmpmax[i] = 1; //addfaz line addition + } + } + } + } + + if (quitevent) + { + initprintf("network: Connection attempt aborted.\n"); + return(0); + } + + /* ok, now everyone is talking to you. Sort them into player numbers... */ + + heard_from[max] = my_id; /* so we sort, too... */ + allowed_addresses[max].host = myip; + allowed_addresses[max].port = udpport; + + do + { + remaining = 0; + for (i = 0; i < max; i++) + { + if (heard_from[i] == heard_from[i+1]) /* blah. */ + { + initprintf("network: ERROR: Two players have the same random ID!\n"); + initprintf("network: ERROR: Please restart the game to generate new IDs.\n"); + quitevent = 1; + return(0); + } + + else if (heard_from[i] > heard_from[i+1]) + { + int32_t tmpi; + int16_t tmps; + + tmps = heard_from[i]; + heard_from[i] = heard_from[i+1]; + heard_from[i+1] = tmps; + + tmpi = allowed_addresses[i].host; + allowed_addresses[i].host = allowed_addresses[i+1].host; + allowed_addresses[i+1].host = tmpi; + + tmps = allowed_addresses[i].port; + allowed_addresses[i].port = allowed_addresses[i+1].port; + allowed_addresses[i+1].port = tmps; + + remaining = 1; /* yay for bubble sorting! */ + } + } + } + while (remaining); + + /* + * Now we're sorted. But, the local player is referred to by both his + * player number and player index ZERO, so bump everyone up one to + * their actual index and fill in local player as item zero. + */ + + memmove(&allowed_addresses[1], &allowed_addresses[0], + sizeof(allowed_addresses) - sizeof(allowed_addresses[0])); + allowed_addresses[0].host = myip; + + gcom->myconnectindex = 0; + for (i = 1; i <= gcom->numplayers; i++) + { + ip = (allowed_addresses[i].host); + + + if (ip == myip) + { + if (udpport == allowed_addresses[i].port) + gcom->myconnectindex = i; + } + + initprintf("network: Player #%i at %s:%i\n", i,static_ipstring(ip),allowed_addresses[i].port); + } +// assert(gcom->myconnectindex); + + initprintf("network: We are player #%i\n", gcom->myconnectindex); + + /* + * Ok, we should have specific IPs and ports for all players, and + * therefore shouldn't broadcast anymore. Disable permission to do so, + * just in case, so we aren't flooding the LAN with broadcasted packets. + */ + set_socket_broadcast(0); + + return(1); +} + +static int32_t parse_ip(const char *str, int32_t *ip) +{ + int32_t ip1, ip2, ip3, ip4; + + if (Bstrcasecmp(str, "any") == 0) + { + *ip = 0; + return(1); + } + + if (sscanf(str, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4) != 4) + { + initprintf("\"%s\" is not a valid IP address.\n", str); + return(0); + } + + /* we _should_ check that 0 <= ip? <= 255, but it'll fail later anyhow. */ + + *ip = (((ip1 & 0xFF) << 24) | + ((ip2 & 0xFF) << 16) | + ((ip3 & 0xFF) << 8) | + ((ip4 & 0xFF))); + + return(1); +} + +static int32_t parse_interface(char *str, int32_t *ip, uint16_t *udpport) +{ + char *ptr = strchr(str, ':'); + if (ptr) /* portnum specified? */ + *ptr = '\0'; + + if (!parse_ip(str, ip)) + return(0); + + *udpport = BUILD_DEFAULT_UDP_PORT; + if (ptr != NULL) /* port specified? */ + { + ptr++; + if (Bstrcasecmp(ptr, "any") == 0) + *udpport = 0; + else + *udpport = (int16_t) atoi(ptr); + } + + return(1); +} + +static int32_t initialize_sockets(void) +{ +#if PLATFORM_WIN32 + int32_t rc; + WSADATA data; +// initprintf("initializing WinSock...\n"); + rc = WSAStartup(0x0101, &data); + if (rc != 0) + { + initprintf("WinSock failed to initialize! [err==%d].\n", rc); + return(0); + } + else + { + /* initprintf("WinSock initialized.\n"); + initprintf(" - Caller uses version %d.%d, highest supported is %d.%d.\n", + data.wVersion >> 8, data.wVersion & 0xFF, + data.wHighVersion >> 8, data.wHighVersion & 0xFF); + initprintf(" - Implementation description: [%s].\n", data.szDescription); + initprintf(" - System status: [%s].\n", data.szSystemStatus); + initprintf(" - Max sockets: %d.\n", data.iMaxSockets); + initprintf(" - Max UDP datagram size: %d.\n", data.iMaxUdpDg); */ + } +#endif + + return(1); +} + +static void deinitialize_sockets(void) +{ +#if PLATFORM_WIN32 + WSACleanup(); +#endif +} + +int32_t isvalidipaddress(char *st) +{ + int32_t i, bcnt, num; + + bcnt = 0; num = 0; + for (i=0; st[i]; i++) + { + if (st[i] == '.') { bcnt++; num = 0; continue; } + if (st[i] == ':') + { + if (bcnt != 3) return(0); + num = 0; + for (i++; st[i]; i++) + { + if ((st[i] >= '0') && (st[i] <= '9')) + { num = num*10+st[i]-'0'; if (num >= 65536) return(0); } + else return(0); + } + return(1); + } + if ((st[i] >= '0') && (st[i] <= '9')) + { num = num*10+st[i]-'0'; if (num >= 256) return(0); } + + } + return(bcnt == 3); +} + +static int32_t parse_udp_config(int32_t argc, char **argv, gcomtype *gcom) +{ + char *buf; + char *tok; + char *ptr; + int32_t ip = 0; /* interface */ + int32_t bcast = 0; + + buf = read_whole_file(argv[0]); /* we must free this. */ + if (buf == NULL) + { + // do JF-style argv parsing here + int32_t i, j, daindex; + int32_t danetmode = 255; + char *st; + + daindex = 0; + + // if (!argv) return 0; + // go looking for the port, if specified + for (i=0; i 1024 && j<65535) udpport = j; + + initprintf("network: Using port %d\n", udpport); + } + } + + for (i=0; inumplayers = 1; + if (argv[i][2] == '0') + { + danetmode = 0; + udpmode = udpmode_client; + if ((argv[i][3] == ':') && (argv[i][4] >= '0') && (argv[i][4] <= '9')) + { + udpmode = udpmode_server; + gcom->numplayers = (argv[i][4]-'0'); + if ((argv[i][5] >= '0') && (argv[i][5] <= '9')) gcom->numplayers = gcom->numplayers*10+(argv[i][5]-'0'); + initprintf("network: %d-player game server\n", gcom->numplayers--); + } + initprintf("network: Master-slave mode\n"); + } + else if (argv[i][2] == '1') + { + danetmode = 1; + udpmode = udpmode_peer; + myconnectindex = daindex; +// daindex++; + initprintf("network: Peer-to-peer mode\n"); + } + continue; + } + else if ((argv[i][1] == 'P') || (argv[i][1] == 'p')) continue; + } + + st = Bstrdup(argv[i]); + if (!st) break; + if (isvalidipaddress(st)) + { +// if ((danetmode == 1) && (daindex == myconnectindex)) daindex++; + parse_interface(st, &allowed_addresses[daindex].host, &allowed_addresses[daindex].port); + initprintf("network: Player %d at %s:%d\n",daindex,st,allowed_addresses[daindex].port); + daindex++; + } + else + { + struct hostent * lph; + uint16_t pt = BUILD_DEFAULT_UDP_PORT; + + for (j=0; st[j]; j++) + if (st[j] == ':') + { pt = (uint16_t)atol(&st[j+1]); st[j] = 0; break; } + if ((lph = gethostbyname(st))) + { +// if ((danetmode == 1) && (daindex == myconnectindex)) daindex++; + allowed_addresses[daindex].host = ntohl(*(int32_t *)lph->h_addr); + allowed_addresses[daindex].port = pt; + initprintf("network: Player %d at %s:%d (%s)\n",daindex, + inet_ntoa(*(struct in_addr *)lph->h_addr),pt,argv[i]); + daindex++; + } + else initprintf("network: Failed resolving %s\n",argv[i]); + } + Bfree(st); + } + if ((danetmode == 255) && (daindex)) { gcom->numplayers = 2; udpmode = udpmode_client; } //an IP w/o /n# defaults to /n0 + // if ((numplayers >= 2) && (daindex) && (!danetmode)) myconnectindex = 1; + if (daindex > gcom->numplayers) gcom->numplayers = daindex; + } + else + { + initprintf("network: Using '%s' as configuration file\n", argv[0]); + + ptr = buf; + while ((tok = get_token(&ptr)) != NULL) + { + int32_t bogus = 1; + + if (Bstrcasecmp(tok, "interface") == 0) + { + if ((tok = get_token(&ptr)) && + (parse_interface(tok, &ip, &udpport))) + { + bogus = 0; + } + initprintf("network: Using interface %s:%d\n", + static_ipstring(ip), (int32_t) udpport); + } + + else if (Bstrcasecmp(tok, "mode") == 0) + { + if ((tok = get_token(&ptr)) != NULL) + { + bogus = 0; + if (Bstrcasecmp(tok, "server") == 0) + udpmode = udpmode_server; + else if (Bstrcasecmp(tok, "client") == 0) + udpmode = udpmode_client; + else if (Bstrcasecmp(tok, "peer") == 0) + udpmode = udpmode_peer; + else + bogus = 1; + + if (!bogus) + initprintf("You want to be in [%s] mode\n", tok); + } + } + + else if (Bstrcasecmp(tok, "broadcast") == 0) + { + if ((tok = get_token(&ptr)) != NULL) + { + bcast = atoi(tok); + if (bcast > MAXPLAYERS - 1) + { + initprintf("WARNING: Too many broadcast players.\n"); + bcast = MAXPLAYERS - 1; + } + + bogus = 0; + } + } + + else if (Bstrcasecmp(tok, "allow") == 0) + { + int32_t host; + uint16_t port=BUILD_DEFAULT_UDP_PORT; + if ((tok = get_token(&ptr)) != NULL) + { + if (gcom->numplayers >= MAXPLAYERS - 1) + initprintf("WARNING: Too many allowed IP addresses.\n"); + + else if (parse_interface(tok, &host, &port)) + { + allowed_addresses[gcom->numplayers].host = host; + allowed_addresses[gcom->numplayers].port = port; + gcom->numplayers++; + bogus = 0; + } + } + } + + else if (Bstrcasecmp(tok, "players") == 0) + { + if ((tok = get_token(&ptr)) != NULL) + { + bogus = 0; + if (udpmode == udpmode_server) + gcom->numplayers = atoi(tok)-1; + else + bogus = 1; + } + } + + if (bogus) + initprintf("bogus token! [%s]\n", tok); + } + + Bfree(buf); + } + + if (open_udp_socket(ip, udpport)) + { + gcom->numplayers++; /* that's you. */ + if (udpmode == udpmode_server) + return(wait_for_other_players(gcom, ip)); + else if (udpmode == udpmode_client) + return(connect_to_server(gcom, ip)); + else if (udpmode == udpmode_peer) + return(connect_to_everyone(gcom, ip, bcast)); + + initprintf("wtf?!"); /* Should be handled by a udpmode above... */ +// assert(0); + } + + return(0); +} + + +gcomtype *init_network_transport(int32_t argc, char **argv) +{ + gcomtype *retval; + +// initprintf("\n\nUDP NETWORK TRANSPORT INITIALIZING...\n"); + + if (!initialize_sockets()) + return(NULL); + + srand(time(NULL)); + + retval = (gcomtype *)Bmalloc(sizeof(gcomtype)); + if (retval != NULL) + { + int32_t rc; +// char *cfgfile = ARGV[argpos]; + + memset(retval, '\0', sizeof(gcomtype)); + memset(allowed_addresses, '\0', sizeof(allowed_addresses)); + udpsocket = -1; + udpport = BUILD_DEFAULT_UDP_PORT; + udpmode = udpmode_peer; + + rc = parse_udp_config(argc, argv, retval); + + if (!rc) + { + Bfree(retval); + deinit_network_transport(NULL); + return(NULL); + } +// retval->gametype = 3; /* gametype: 1-serial,2-modem,3-net */ + } + + return(retval); +} + + +void deinit_network_transport(gcomtype *gcom) +{ +// initprintf("\n\nUDP NETWORK TRANSPORT DEINITIALIZING...\n"); + + if (gcom != NULL) + { + initprintf(" ...freeing gcom structure...\n"); + Bfree(gcom); + } + + if ((signed)udpsocket != -1) + { + initprintf(" ...closing socket...\n"); + set_socket_blockmode(1); /* block while socket drains. */ + shutdown(udpsocket, SOCKET_SHUTDOWN_BOTH); + socketclose(udpsocket); + udpsocket = -1; + } + + deinitialize_sockets(); + + initprintf("UDP networking uninitialized successfully.\n"); +} + + +void callcommit(void) +{ + int32_t ip, i, rc; + uint16_t port; + + if ((signed)udpsocket == -1) + return; + + process_udp_send_queue(); + + switch (gcom->command) + { + case COMMIT_CMD_GET: + rc = get_udp_packet(&ip, &port, gcom->buffer, sizeof(gcom->buffer)); + if (rc > 0) + { + gcom->numbytes = rc; /* size of new packet. */ + for (i = 1; i <= gcom->numplayers; i++) + { + if ((allowed_addresses[i].host == ip) && + (allowed_addresses[i].port == port)) + { + gcom->other = i; + return; + } + } + /* if you manage to hit this, it'll report no packet avail. */ + } + + gcom->numbytes = 0; + gcom->other = -1; /* no packet available. */ + break; + + case COMMIT_CMD_SEND: + if ((gcom->other < 0) || (gcom->other > gcom->numplayers)) + { + initprintf("NET TRANSPORT ERROR: send to player out of range\n"); + return; + } + + ip = allowed_addresses[gcom->other].host; + if (ip == 0) /* dropped player? */ + return; + + port = allowed_addresses[gcom->other].port; + + if (!send_udp_packet(ip, port, gcom->buffer, gcom->numbytes)) + { + initprintf("NET TRANSPORT ERROR: send failed to %s:%d\n", + static_ipstring(ip), (int32_t) port); + } + break; + + case COMMIT_CMD_SENDTOALL: + /* skip player zero, 'cause that's a duplicate of local IP. */ + for (i = 1; i <= gcom->numplayers; i++) + { + ip = allowed_addresses[i].host; + if (ip == 0) /* dropped player? */ + continue; + + port = allowed_addresses[i].port; + + if (!send_udp_packet(ip, port, gcom->buffer, gcom->numbytes)) + { + initprintf("NET TRANSPORT ERROR: send failed to %s:%d\n", + static_ipstring(ip), (int32_t) port); + } + } + break; + + case COMMIT_CMD_SENDTOALLOTHERS: + /* skip player zero, 'cause that's a duplicate of local IP. */ + for (i = 1; i <= gcom->numplayers; i++) + { + if (i == gcom->myconnectindex) /* local player. */ + continue; + + ip = allowed_addresses[i].host; + if (ip == 0) /* dropped player? */ + continue; + + port = allowed_addresses[i].port; + + if (!send_udp_packet(ip, port, gcom->buffer, gcom->numbytes)) + { + initprintf("NET TRANSPORT ERROR: send failed to %s:%d\n", + static_ipstring(ip), (int32_t) port); + } + } + break; + + /* ?! + case COMMIT_CMD_SCORE: + break; + */ + + default: + initprintf("NET TRANSPORT ERROR: Unknown command %d\n", gcom->command); + gcom->other = -1; /* oh well. */ + break; + } +} + +/* end of mmulti.c ... */ + diff --git a/polymer/eduke32/build/src/osd.c b/polymer/eduke32/build/src/osd.c index 43c15b6e0..6f5b03ba0 100644 --- a/polymer/eduke32/build/src/osd.c +++ b/polymer/eduke32/build/src/osd.c @@ -8,7 +8,7 @@ #include "baselayer.h" #include "cache1d.h" #include "pragmas.h" -#include "mmulti.h" +#include "mmulti_unstable.h" symbol_t *symbols = NULL; static symbol_t *addnewsymbol(const char *name); diff --git a/polymer/eduke32/build/src/polymost.c b/polymer/eduke32/build/src/polymost.c index 85e3143bd..30c8e73b9 100644 --- a/polymer/eduke32/build/src/polymost.c +++ b/polymer/eduke32/build/src/polymost.c @@ -738,7 +738,7 @@ void polymost_glinit() } else rewind(cacheindexptr); - cachefilehandle = Bopen(TEXCACHEFILE,BO_BINARY|BO_CREAT|BO_APPEND|BO_RDWR,BS_IREAD|BS_IWRITE); + cachefilehandle = Bopen(TEXCACHEFILE, BO_BINARY|BO_CREAT|BO_APPEND|BO_RDWR, BS_IREAD|BS_IWRITE); if (cachefilehandle < 0) { @@ -757,7 +757,9 @@ void polymost_glinit() } curcacheindex = firstcacheindex; - initprintf("Cache contains %d bytes of garbage data\n",Blseek(cachefilehandle, 0, BSEEK_END)-i); + i = Blseek(cachefilehandle, 0, BSEEK_END)-i; + if (i) + initprintf("Cache contains %d bytes of garbage data\n",i); // Blseek(cachefilehandle, 0, BSEEK_SET); } diff --git a/polymer/eduke32/build/src/winlayer.c b/polymer/eduke32/build/src/winlayer.c index 26504ca38..d99f75582 100644 --- a/polymer/eduke32/build/src/winlayer.c +++ b/polymer/eduke32/build/src/winlayer.c @@ -38,7 +38,7 @@ #include "build.h" #include "a.h" #include "osd.h" -#include "mmulti.h" +#include "mmulti_unstable.h" // undefine to restrict windowed resolutions to conventional sizes #define ANY_WINDOWED_SIZE diff --git a/polymer/eduke32/source/config.c b/polymer/eduke32/source/config.c index 84c10bc6e..976f3c619 100644 --- a/polymer/eduke32/source/config.c +++ b/polymer/eduke32/source/config.c @@ -662,12 +662,6 @@ int32_t CONFIG_ReadSetup(void) SCRIPT_GetString(ud.config.scripthandle, "Comm Setup","RTSName",&ud.rtsname[0]); -#ifndef RANCID_NETWORKING - // The packetrate mechanism is specific to the eduke32 networking code - SCRIPT_GetNumber(ud.config.scripthandle, "Comm Setup", "Rate",(int32_t *)&packetrate); - packetrate = min(max(packetrate,50),1000); -#endif - SCRIPT_GetNumber(ud.config.scripthandle, "Setup","ConfigVersion",&ud.configversion); SCRIPT_GetNumber(ud.config.scripthandle, "Setup","ForceSetup",&ud.config.ForceSetup); SCRIPT_GetNumber(ud.config.scripthandle, "Setup","NoAutoLoad",&ud.config.NoAutoLoad); @@ -1239,12 +1233,6 @@ void CONFIG_WriteSetup(void) SCRIPT_PutString(ud.config.scripthandle, "Comm Setup","PlayerName",&szPlayerName[0]); SCRIPT_PutString(ud.config.scripthandle, "Comm Setup","RTSName",&ud.rtsname[0]); -#ifndef RANCID_NETWORKING - // The packetrate mechanism is specific to the eduke32 networking code - SCRIPT_PutNumber(ud.config.scripthandle, "Comm Setup", "Rate", packetrate, FALSE, FALSE); -#endif - - SCRIPT_PutString(ud.config.scripthandle, "Setup","SelectedGRP",&duke3dgrp[0]); // #ifdef _WIN32 diff --git a/polymer/eduke32/source/duke3d.h b/polymer/eduke32/source/duke3d.h index 0391cf1b1..d73804000 100644 --- a/polymer/eduke32/source/duke3d.h +++ b/polymer/eduke32/source/duke3d.h @@ -39,11 +39,7 @@ extern "C" { #include "cache1d.h" #include "pragmas.h" -#ifdef RANCID_NETWORKING #include "mmulti_unstable.h" -#else -#include "mmulti.h" -#endif #include "baselayer.h" @@ -636,9 +632,6 @@ extern char g_numVolumes; extern int32_t g_lastSaveSlot; extern int32_t g_restorePalette; -#ifndef RANCID_NETWORKING -extern int32_t packetrate; -#endif extern int32_t cachecount; extern char boardfilename[BMAX_PATH]; diff --git a/polymer/eduke32/source/game.c b/polymer/eduke32/source/game.c index a3db560e0..a8568aa2d 100644 --- a/polymer/eduke32/source/game.c +++ b/polymer/eduke32/source/game.c @@ -71,9 +71,6 @@ static int32_t g_noSound = 0; static int32_t g_noMusic = 0; static char *CommandMap = NULL; static char *CommandName = NULL; -#ifndef RANCID_NETWORKING -static char *CommandNet = NULL; -#endif static int32_t g_keepAddr = 0; int32_t CommandWeaponChoice = 0; static struct strllist @@ -9308,25 +9305,7 @@ static void G_CheckCommandLine(int32_t argc, const char **argv) i++; continue; } -#ifndef RANCID_NETWORKING - if (!Bstrcasecmp(c+1,"rmnet")) - { - if (argc > i+1) - { - g_noSetup = TRUE; - g_networkBroadcastMode = 1; - CommandNet = (char *)argv[i+1]; - i++; - } - i++; - continue; - } -#endif - if (!Bstrcasecmp(c+1,"net") -#ifdef RANCID_NETWORKING - || !Bstrcasecmp(c+1,"rmnet") -#endif - ) + if (!Bstrcasecmp(c+1,"net") || !Bstrcasecmp(c+1,"rmnet")) { g_noSetup = TRUE; firstnet = i; @@ -10178,20 +10157,6 @@ static void G_Startup(void) for (i=0; inumparms == 0) - { - OSD_Printf("\"rate\" is \"%d\"\n", packetrate); - return OSDCMD_SHOWHELP; - } - else if (parm->numparms != 1) return OSDCMD_SHOWHELP; - - i = Batol(parm->parms[0]); - - if (i >= 40 && i <= 1000) - { - packetrate = i; - OSD_Printf("rate %d\n", packetrate); - } - else OSD_Printf("rate: value out of range\n"); -#endif - UNREFERENCED_PARAMETER(parm); - return OSDCMD_OK; -} -*/ - static int32_t osdcmd_restartsound(const osdfuncparm_t *parm) { UNREFERENCED_PARAMETER(parm);