NAT traversal patch from Adam Fazakerley

git-svn-id: https://svn.eduke32.com/eduke32@182 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
terminx 2006-05-23 23:43:18 +00:00
parent e73e8a9b9f
commit bc47dbdba1
5 changed files with 166 additions and 17 deletions

View file

@ -8,6 +8,7 @@
extern long myconnectindex, numplayers;
extern long connecthead, connectpoint2[MAXMULTIPLAYERS];
extern char syncstate;
extern int natfree; //Addfaz NatFree
long initmultiplayersparms(long argc, char **argv);
long initmultiplayerscycle(void);
@ -25,5 +26,9 @@ void flushpackets(void);
void genericmultifunction(long other, char *bufptr, long messleng, long command);
long isvalidipaddress(char *st);
void nfIncCP(void); //Addfaz NatFree
int nfCheckHF (long other); //Addfaz NatFree
int nfCheckCP(long other); //Addfaz NatFree
#endif // __mmulti_h__

View file

@ -78,6 +78,47 @@ static SOCKET mysock;
static long myip, myport = NETPORT, otherip[MAXPLAYERS], otherport[MAXPLAYERS];
static long snatchip = 0, snatchport = 0, danetmode = 255, netready = 0;
/*Addfaz NatFree Start*/
int natfree; //NatFree mode flag
int nfCurrentPlayer = 0; //Current NatFree player counter. Will only talk with one player at a time
int nfFinished = 0; //Flag that determines NatFree has found all players and set the correct port numbers [normal routines can then take place]
int HeardFrom[MAXPLAYERS]; //For connecthead
int HeardFrom2[MAXPLAYERS]; //For others
int nfCheckCP (long other) //Check if target player is our current NatFree Player
{
if (!natfree || nfFinished)
return 1;
else
if (nfCurrentPlayer == other) return 1;
return 0;
}
int nfCheckHF (long 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: Heard from everybody, Let's Rock!\n");
return;
}
}
}
/*Addfaz NatFree End*/
void netuninit ()
{
if (mysock != (SOCKET)INVALID_HANDLE_VALUE) closesocket(mysock);
@ -128,6 +169,20 @@ long netsend (long other, char *dabuf, long bufsiz) //0:buffer full... can't sen
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];
@ -151,6 +206,37 @@ long netread (long *other, char *dabuf, long bufsiz) //0:no packets in buffer
for(i=0;i<MAXPLAYERS;i++)
if ((otherip[i] == snatchip) && (otherport[i] == snatchport))
{ (*other) = i; break; }
/*Addfaz NatFree Start*/
if (natfree && !nfFinished)
{
if (!nfCheckHF((*other))) //Check if have heard from this player already
{
if (otherip[nfCurrentPlayer] == snatchip) //Check IP Matches
{
if (!nfCheckHF(nfCurrentPlayer) && !HeardFrom2[nfCurrentPlayer])
{
if (otherport[nfCurrentPlayer] != snatchport) //If Port numbers do not match
{
otherport[nfCurrentPlayer] = snatchport; //Correct the port number
initprintf("NatFree: Port number changed for player %i.\n", nfCurrentPlayer);
}
}
(*other) = nfCurrentPlayer; //Set pointer
if (!nfCheckHF(nfCurrentPlayer) && myconnectindex != connecthead)
{
HeardFrom[nfCurrentPlayer] = 1;
}
}
}
else
{
HeardFrom[i] = 1;
HeardFrom2[i] = 1;
}
}
/*Addfaz NatFree Endt*/
#if (SIMLAG > 1)
i = simlagcnt[*other]%(SIMLAG+1);
*(short *)&simlagfif[*other][i][0] = bufsiz; memcpy(&simlagfif[*other][i][2],dabuf,bufsiz);
@ -380,12 +466,13 @@ long initmultiplayerscycle(void)
getpacket(&i,0);
tims = GetTickCount();
if (myconnectindex == connecthead)
if (myconnectindex == connecthead) //Player 0 only
{
for(i=numplayers-1;i>0;i--)
if (!otherip[i]) break;
if (!i) {
netready = 1;
nfIncCP(); //Addfaz NatFree
netready = 1; //Player 0 is ready
return 0;
}
}
@ -454,7 +541,7 @@ void initmultiplayers (long argc, char **argv, char damultioption, char dacomrat
netready = 1;
}
void dosendpackets (long other)
void dosendpackets (long other) //Host to send intially, client to send to others once heard from host.
{
long i, j, k;
@ -500,7 +587,11 @@ void dosendpackets (long other)
*(unsigned short *)&pakbuf[k] = getcrc16(pakbuf,k); k += 2;
//printf("Send: "); for(i=0;i<k;i++) printf("%02x ",pakbuf[i]); printf("\n");
netsend(other,pakbuf,k);
/*Addfaz NatFree Start*/
if (nfCheckCP(other) || !natfree) //Clients only if heard from host
netsend(other,pakbuf,k);
/*Addfaz NatFree End*/
}
void sendpacket (long other, char *bufptr, long messleng)
@ -581,6 +672,17 @@ long getpacket (long *retother, char *bufptr)
pakbuf[k++] = (char)numplayers;
*(unsigned short *)&pakbuf[0] = (unsigned short)k;
*(unsigned short *)&pakbuf[k] = getcrc16(pakbuf,k); k += 2;
/*Addfaz NatFree Start*/
if (natfree && !nfCheckHF(other))
{
initprintf("NatFree: Heard from player %i\n", other);
HeardFrom[other] = 1;
HeardFrom2[other] = 1;
nfIncCP();
}
/*Addfaz NatFree End*/
netsend(other,pakbuf,k);
break;
}
@ -600,6 +702,16 @@ long getpacket (long *retother, char *bufptr)
otherip[connecthead] = snatchip;
otherport[connecthead] = snatchport;
netready = 1;
/*Addfaz NatFree Start*/
if (natfree)
{
initprintf("NatFree: Heard from head player %i\n", connecthead);
HeardFrom[connecthead] = 1;
HeardFrom2[connecthead] = 1;
nfIncCP();
}
/*Addfaz NatFree End*/
}
}
}
@ -641,6 +753,17 @@ long getpacket (long *retother, char *bufptr)
messleng = *(short *)&pakmem[j]; memcpy(bufptr,&pakmem[j+2],messleng);
*retother = i; ipak[i][icnt0[i]&(FIFSIZ-1)] = 0; icnt0[i]++;
//printf("Recv: "); for(i=0;i<messleng;i++) printf("%02x ",bufptr[i]); printf("\n");
/*Addfaz NatFree Start*/
if (natfree && !HeardFrom2[nfCurrentPlayer] && i == nfCurrentPlayer)
{
initprintf("NatFree: Heard from player %i\n", i);
HeardFrom2[nfCurrentPlayer] = 1;
HeardFrom[nfCurrentPlayer] = 1;
nfIncCP();
}
/*Addfaz NatFree End*/
return(messleng);
}
}

View file

@ -7736,6 +7736,7 @@ void checkcommandline(int argc,char **argv)
continue;
}
if (!Bstrcasecmp(c+1,"stun")) {
natfree = 1; //Addfaz NatFree
i++;
continue;
}

View file

@ -1606,6 +1606,7 @@ cheat_for_port_credits:
"",
"Thanks to these people for their input and contributions:",
"",
"Adam Fazakerley",
"Ed Coolidge",
"Javier Martinez",
"Jeff Hart",

View file

@ -389,6 +389,17 @@ int osdcmd_addpath(const osdfuncparm_t *parm)
return OSDCMD_OK;
}
int osdcmd_initgroupfile(const osdfuncparm_t *parm)
{
char file[BMAX_PATH];
if (parm->numparms != 1) return OSDCMD_SHOWHELP;
strcpy(file,parm->parms[0]);
initgroupfile(file);
return OSDCMD_OK;
}
int osdcmd_cmenu(const osdfuncparm_t *parm)
{
if (parm->numparms != 1) return OSDCMD_SHOWHELP;
@ -681,8 +692,6 @@ int registerosdcommands(void)
OSD_RegisterFunction(cvar[i].name, cvar[i].helpstr, osdcmd_cvar_set);
}
OSD_RegisterFunction("echo","echo [text]: echoes text to the console", osdcmd_echo);
if (VOLUMEONE) {
OSD_RegisterFunction("changelevel","changelevel <level>: warps to the given level", osdcmd_changelevel);
} else {
@ -690,29 +699,39 @@ int registerosdcommands(void)
OSD_RegisterFunction("map","map <mapfile>: loads the given user map", osdcmd_map);
OSD_RegisterFunction("mpmap","mpmap <mapfile>: sets user map name in multiplayer", osdcmd_mpmap);
}
OSD_RegisterFunction("addpath","addpath <path>: adds path to game filesystem", osdcmd_addpath);
OSD_RegisterFunction("cl_statusbarmode","cl_statusbarmode: enable/disable status bar drawing hack", osdcmd_setstatusbarmode);
OSD_RegisterFunction("cl_statusbarscale","cl_statusbarscale: changes the status bar scale", osdcmd_setstatusbarscale);
OSD_RegisterFunction("cmenu","cmenu <#>: jumps to menu", osdcmd_cmenu);
OSD_RegisterFunction("echo","echo [text]: echoes text to the console", osdcmd_echo);
OSD_RegisterFunction("exec","exec <scriptfile>: executes a script", osdcmd_exec);
OSD_RegisterFunction("god","god: toggles god mode", osdcmd_god);
OSD_RegisterFunction("fileinfo","fileinfo <file>: gets a file's information", osdcmd_fileinfo);
OSD_RegisterFunction("gamma","gamma <value>: changes brightness", osdcmd_gamma);
OSD_RegisterFunction("give","give <all|health|weapons|ammo|armor|keys|inventory>: gives requested item", osdcmd_give);
OSD_RegisterFunction("god","god: toggles god mode", osdcmd_god);
OSD_RegisterFunction("initgroupfile","initgroupfile <path>: adds a grp file into the game filesystem", osdcmd_initgroupfile);
OSD_RegisterFunction("name","name: change your multiplayer nickname", osdcmd_name);
OSD_RegisterFunction("noclip","noclip: toggles clipping mode", osdcmd_noclip);
OSD_RegisterFunction("cl_statusbarscale","cl_statusbarscale: changes the status bar scale", osdcmd_setstatusbarscale);
OSD_RegisterFunction("cl_statusbarmode","cl_statusbarmode: enable/disable status bar drawing hack", osdcmd_setstatusbarmode);
OSD_RegisterFunction("sensitivity","sensitivity <value>: changes the mouse sensitivity", osdcmd_sensitivity);
OSD_RegisterFunction("spawn","spawn <picnum> [palnum] [cstat] [ang] [x y z]: spawns a sprite with the given properties",osdcmd_spawn);
OSD_RegisterFunction("setvar","setvar <gamevar> <value>: sets the value of a gamevar", osdcmd_setvar);
OSD_RegisterFunction("addpath","addpath <path>: adds path to game filesystem", osdcmd_addpath);
OSD_RegisterFunction("fileinfo","fileinfo <file>: gets a file's information", osdcmd_fileinfo);
OSD_RegisterFunction("quit","quit: exits the game immediately", osdcmd_quit);
OSD_RegisterFunction("restartvid","restartvid: reinitialised the video mode",osdcmd_restartvid);
OSD_RegisterFunction("vidmode","vidmode [xdim ydim] [bpp] [fullscreen]: immediately change the video mode",osdcmd_vidmode);
OSD_RegisterFunction("usemouse","usemouse: enables input from the mouse if it is present",osdcmd_usemousejoy);
OSD_RegisterFunction("sensitivity","sensitivity <value>: changes the mouse sensitivity", osdcmd_sensitivity);
OSD_RegisterFunction("setvar","setvar <gamevar> <value>: sets the value of a gamevar", osdcmd_setvar);
OSD_RegisterFunction("spawn","spawn <picnum> [palnum] [cstat] [ang] [x y z]: spawns a sprite with the given properties",osdcmd_spawn);
OSD_RegisterFunction("usejoystick","usejoystick: enables input from the joystick if it is present",osdcmd_usemousejoy);
OSD_RegisterFunction("usemouse","usemouse: enables input from the mouse if it is present",osdcmd_usemousejoy);
OSD_RegisterFunction("vidmode","vidmode [xdim ydim] [bpp] [fullscreen]: immediately change the video mode",osdcmd_vidmode);
//baselayer_onvideomodechange = onvideomodechange;