mirror of
https://git.do.srb2.org/KartKrew/Kart-Public.git
synced 2024-12-27 04:41:23 +00:00
Hole punching
This commit is contained in:
parent
52879a7632
commit
ba5b6aa7af
6 changed files with 161 additions and 23 deletions
|
@ -1908,6 +1908,8 @@ static void SendAskInfo(INT32 node)
|
||||||
// now allowed traffic from the host to us in, so once the MS relays
|
// now allowed traffic from the host to us in, so once the MS relays
|
||||||
// our address to the host, it'll be able to speak to us.
|
// our address to the host, it'll be able to speak to us.
|
||||||
HSendPacket(node, false, 0, sizeof (askinfo_pak));
|
HSendPacket(node, false, 0, sizeof (askinfo_pak));
|
||||||
|
|
||||||
|
I_NetRequestHolePunch();
|
||||||
}
|
}
|
||||||
|
|
||||||
serverelem_t serverlist[MAXSERVERLIST];
|
serverelem_t serverlist[MAXSERVERLIST];
|
||||||
|
@ -5725,6 +5727,19 @@ static void UpdatePingTable(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void RenewHolePunch(void)
|
||||||
|
{
|
||||||
|
static time_t past;
|
||||||
|
|
||||||
|
const time_t now = time(NULL);
|
||||||
|
|
||||||
|
if ((now - past) > 20)
|
||||||
|
{
|
||||||
|
I_NetRegisterHolePunch();
|
||||||
|
past = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Handle timeouts to prevent definitive freezes from happenning
|
// Handle timeouts to prevent definitive freezes from happenning
|
||||||
static void HandleNodeTimeouts(void)
|
static void HandleNodeTimeouts(void)
|
||||||
{
|
{
|
||||||
|
@ -5759,6 +5774,11 @@ FILESTAMP
|
||||||
MasterClient_Ticker();
|
MasterClient_Ticker();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (serverrunning)
|
||||||
|
{
|
||||||
|
RenewHolePunch();
|
||||||
|
}
|
||||||
|
|
||||||
if (client)
|
if (client)
|
||||||
{
|
{
|
||||||
// send keep alive
|
// send keep alive
|
||||||
|
@ -5818,6 +5838,11 @@ FILESTAMP
|
||||||
MasterClient_Ticker(); // Acking the Master Server
|
MasterClient_Ticker(); // Acking the Master Server
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (serverrunning)
|
||||||
|
{
|
||||||
|
RenewHolePunch();
|
||||||
|
}
|
||||||
|
|
||||||
if (client)
|
if (client)
|
||||||
{
|
{
|
||||||
if (!resynch_local_inprogress)
|
if (!resynch_local_inprogress)
|
||||||
|
|
|
@ -49,6 +49,8 @@ tic_t connectiontimeout = (10*TICRATE);
|
||||||
doomcom_t *doomcom = NULL;
|
doomcom_t *doomcom = NULL;
|
||||||
/// \brief network packet data, points inside doomcom
|
/// \brief network packet data, points inside doomcom
|
||||||
doomdata_t *netbuffer = NULL;
|
doomdata_t *netbuffer = NULL;
|
||||||
|
/// \brief hole punching packet, also points inside doomcom
|
||||||
|
holepunch_t *holepunchpacket = NULL;
|
||||||
|
|
||||||
#ifdef DEBUGFILE
|
#ifdef DEBUGFILE
|
||||||
FILE *debugfile = NULL; // put some net info in a file during the game
|
FILE *debugfile = NULL; // put some net info in a file during the game
|
||||||
|
@ -72,6 +74,8 @@ boolean (*I_NetCanGet)(void) = NULL;
|
||||||
void (*I_NetCloseSocket)(void) = NULL;
|
void (*I_NetCloseSocket)(void) = NULL;
|
||||||
void (*I_NetFreeNodenum)(INT32 nodenum) = NULL;
|
void (*I_NetFreeNodenum)(INT32 nodenum) = NULL;
|
||||||
SINT8 (*I_NetMakeNodewPort)(const char *address, const char* port) = NULL;
|
SINT8 (*I_NetMakeNodewPort)(const char *address, const char* port) = NULL;
|
||||||
|
void (*I_NetRequestHolePunch)(void) = NULL;
|
||||||
|
void (*I_NetRegisterHolePunch)(void) = NULL;
|
||||||
boolean (*I_NetOpenSocket)(void) = NULL;
|
boolean (*I_NetOpenSocket)(void) = NULL;
|
||||||
boolean (*I_Ban) (INT32 node) = NULL;
|
boolean (*I_Ban) (INT32 node) = NULL;
|
||||||
void (*I_ClearBans)(void) = NULL;
|
void (*I_ClearBans)(void) = NULL;
|
||||||
|
@ -1335,6 +1339,7 @@ boolean D_CheckNetGame(void)
|
||||||
I_Error("Too many nodes (%d), max:%d", doomcom->numnodes, MAXNETNODES);
|
I_Error("Too many nodes (%d), max:%d", doomcom->numnodes, MAXNETNODES);
|
||||||
|
|
||||||
netbuffer = (doomdata_t *)(void *)&doomcom->data;
|
netbuffer = (doomdata_t *)(void *)&doomcom->data;
|
||||||
|
holepunchpacket = (holepunch_t *)(void *)&doomcom->data;
|
||||||
|
|
||||||
#ifdef DEBUGFILE
|
#ifdef DEBUGFILE
|
||||||
#ifdef _arch_dreamcast
|
#ifdef _arch_dreamcast
|
||||||
|
|
17
src/i_net.h
17
src/i_net.h
|
@ -77,11 +77,19 @@ typedef struct
|
||||||
char data[MAXPACKETLENGTH];
|
char data[MAXPACKETLENGTH];
|
||||||
} ATTRPACK doomcom_t;
|
} ATTRPACK doomcom_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
INT32 magic;
|
||||||
|
INT32 addr;
|
||||||
|
INT16 port;
|
||||||
|
} ATTRPACK holepunch_t;
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern doomcom_t *doomcom;
|
extern doomcom_t *doomcom;
|
||||||
|
extern holepunch_t *holepunchpacket;
|
||||||
|
|
||||||
/** \brief return packet in doomcom struct
|
/** \brief return packet in doomcom struct
|
||||||
*/
|
*/
|
||||||
|
@ -140,6 +148,15 @@ extern boolean (*I_NetOpenSocket)(void);
|
||||||
extern void (*I_NetCloseSocket)(void);
|
extern void (*I_NetCloseSocket)(void);
|
||||||
|
|
||||||
|
|
||||||
|
/** \brief send a hole punching request
|
||||||
|
*/
|
||||||
|
extern void (*I_NetRequestHolePunch)(void);
|
||||||
|
|
||||||
|
/** \brief register this machine on the hole punching server
|
||||||
|
*/
|
||||||
|
extern void (*I_NetRegisterHolePunch)(void);
|
||||||
|
|
||||||
|
|
||||||
extern boolean (*I_Ban) (INT32 node);
|
extern boolean (*I_Ban) (INT32 node);
|
||||||
extern void (*I_ClearBans)(void);
|
extern void (*I_ClearBans)(void);
|
||||||
extern const char *(*I_GetNodeAddress) (INT32 node);
|
extern const char *(*I_GetNodeAddress) (INT32 node);
|
||||||
|
|
134
src/i_tcp.c
134
src/i_tcp.c
|
@ -241,6 +241,7 @@ static size_t broadcastaddresses = 0;
|
||||||
static boolean nodeconnected[MAXNETNODES+1];
|
static boolean nodeconnected[MAXNETNODES+1];
|
||||||
static mysockaddr_t banned[MAXBANS];
|
static mysockaddr_t banned[MAXBANS];
|
||||||
static UINT8 bannedmask[MAXBANS];
|
static UINT8 bannedmask[MAXBANS];
|
||||||
|
static const INT32 hole_punch_magic = MSBF_LONG (0x52eb11);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static size_t numbans = 0;
|
static size_t numbans = 0;
|
||||||
|
@ -597,6 +598,27 @@ void Command_Numnodes(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NONET
|
#ifndef NONET
|
||||||
|
static boolean hole_punch(ssize_t c)
|
||||||
|
{
|
||||||
|
if (c == 10 && holepunchpacket->magic == hole_punch_magic)
|
||||||
|
{
|
||||||
|
mysockaddr_t addr;
|
||||||
|
addr.ip4.sin_family = AF_INET;
|
||||||
|
addr.ip4.sin_addr.s_addr = holepunchpacket->addr;
|
||||||
|
addr.ip4.sin_port = holepunchpacket->port;
|
||||||
|
sendto(mysockets[0], NULL, 0, 0, &addr.any, sizeof addr.ip4);
|
||||||
|
|
||||||
|
CONS_Debug(DBG_NETPLAY,
|
||||||
|
"hole punching request from %s\n", SOCK_AddrToStr(&addr));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Returns true if a packet was received from a new node, false in all other cases
|
// Returns true if a packet was received from a new node, false in all other cases
|
||||||
static boolean SOCK_Get(void)
|
static boolean SOCK_Get(void)
|
||||||
{
|
{
|
||||||
|
@ -620,6 +642,11 @@ static boolean SOCK_Get(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (hole_punch(c))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// find remote node number
|
// find remote node number
|
||||||
for (j = 1; j <= MAXNETNODES; j++) //include LAN
|
for (j = 1; j <= MAXNETNODES; j++) //include LAN
|
||||||
{
|
{
|
||||||
|
@ -1319,17 +1346,14 @@ void I_ShutdownTcpDriver(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NONET
|
#ifndef NONET
|
||||||
static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port)
|
static boolean SOCK_GetAddr(struct sockaddr_in *sin, const char *address, const char *port, boolean test)
|
||||||
{
|
{
|
||||||
SINT8 newnode = -1;
|
|
||||||
struct my_addrinfo *ai = NULL, *runp, hints;
|
struct my_addrinfo *ai = NULL, *runp, hints;
|
||||||
int gaie;
|
int gaie;
|
||||||
|
|
||||||
if (!port || !port[0])
|
if (!port || !port[0])
|
||||||
port = DEFAULTPORT;
|
port = DEFAULTPORT;
|
||||||
|
|
||||||
DEBFILE(va("Creating new node: %s@%s\n", address, port));
|
|
||||||
|
|
||||||
memset (&hints, 0x00, sizeof (hints));
|
memset (&hints, 0x00, sizeof (hints));
|
||||||
hints.ai_flags = 0;
|
hints.ai_flags = 0;
|
||||||
hints.ai_family = AF_UNSPEC;
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
@ -1337,30 +1361,91 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port)
|
||||||
hints.ai_protocol = IPPROTO_UDP;
|
hints.ai_protocol = IPPROTO_UDP;
|
||||||
|
|
||||||
gaie = I_getaddrinfo(address, port, &hints, &ai);
|
gaie = I_getaddrinfo(address, port, &hints, &ai);
|
||||||
if (gaie == 0)
|
|
||||||
{
|
if (gaie != 0)
|
||||||
newnode = getfreenode();
|
|
||||||
}
|
|
||||||
if (newnode == -1)
|
|
||||||
{
|
{
|
||||||
I_freeaddrinfo(ai);
|
I_freeaddrinfo(ai);
|
||||||
return -1;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
runp = ai;
|
||||||
|
|
||||||
|
if (test)
|
||||||
|
{
|
||||||
|
while (runp != NULL)
|
||||||
|
{
|
||||||
|
if (sendto(mysockets[0], NULL, 0, 0, runp->ai_addr, runp->ai_addrlen) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
runp = runp->ai_next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runp != NULL)
|
||||||
|
memcpy(sin, runp->ai_addr, runp->ai_addrlen);
|
||||||
|
|
||||||
|
I_freeaddrinfo(ai);
|
||||||
|
|
||||||
|
return (runp != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port)
|
||||||
|
{
|
||||||
|
SINT8 newnode = getfreenode();
|
||||||
|
|
||||||
|
DEBFILE(va("Creating new node: %s@%s\n", address, port));
|
||||||
|
|
||||||
|
if (newnode != -1)
|
||||||
|
{
|
||||||
|
if (!SOCK_GetAddr(&clientaddress[newnode].ip4, address, port, true))
|
||||||
|
{
|
||||||
|
nodeconnected[newnode] = false;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newnode;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rendezvous(int size)
|
||||||
|
{
|
||||||
|
char *addrs = strdup(cv_rendezvousserver.string);
|
||||||
|
|
||||||
|
char *host = strtok(addrs, ":");
|
||||||
|
char *port = strtok(NULL, ":");
|
||||||
|
|
||||||
|
mysockaddr_t rzv;
|
||||||
|
|
||||||
|
if (SOCK_GetAddr(&rzv.ip4, host, (port ? port : "7777"), false))
|
||||||
|
{
|
||||||
|
holepunchpacket->magic = hole_punch_magic;
|
||||||
|
sendto(mysockets[0], doomcom->data, size, 0, &rzv.any, sizeof rzv.ip4);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
runp = ai;
|
|
||||||
|
|
||||||
while (runp != NULL)
|
|
||||||
{
|
{
|
||||||
// find ip of the server
|
CONS_Alert(CONS_ERROR, "Failed to contact rendezvous server (%s).\n",
|
||||||
if (sendto(mysockets[0], NULL, 0, 0, runp->ai_addr, runp->ai_addrlen) == 0)
|
cv_rendezvousserver.string);
|
||||||
{
|
|
||||||
memcpy(&clientaddress[newnode], runp->ai_addr, runp->ai_addrlen);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
runp = runp->ai_next;
|
|
||||||
}
|
}
|
||||||
I_freeaddrinfo(ai);
|
|
||||||
return newnode;
|
free(addrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SOCK_RequestHolePunch(void)
|
||||||
|
{
|
||||||
|
mysockaddr_t * addr = &clientaddress[doomcom->remotenode];
|
||||||
|
|
||||||
|
holepunchpacket->addr = addr->ip4.sin_addr.s_addr;
|
||||||
|
holepunchpacket->port = addr->ip4.sin_port;
|
||||||
|
|
||||||
|
CONS_Debug(DBG_NETPLAY,
|
||||||
|
"requesting hole punch to node %s\n", SOCK_AddrToStr(addr));
|
||||||
|
|
||||||
|
rendezvous(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SOCK_RegisterHolePunch(void)
|
||||||
|
{
|
||||||
|
rendezvous(4);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1387,6 +1472,9 @@ static boolean SOCK_OpenSocket(void)
|
||||||
I_NetCanGet = SOCK_CanGet;
|
I_NetCanGet = SOCK_CanGet;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
I_NetRequestHolePunch = SOCK_RequestHolePunch;
|
||||||
|
I_NetRegisterHolePunch = SOCK_RegisterHolePunch;
|
||||||
|
|
||||||
// build the socket but close it first
|
// build the socket but close it first
|
||||||
SOCK_CloseSocket();
|
SOCK_CloseSocket();
|
||||||
return UDP_Socket();
|
return UDP_Socket();
|
||||||
|
|
|
@ -68,6 +68,7 @@ static CV_PossibleValue_t masterserver_update_rate_cons_t[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
consvar_t cv_masterserver = {"masterserver", "https://ms.kartkrew.org/ms/api", CV_SAVE|CV_CALL, NULL, MasterServer_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
consvar_t cv_masterserver = {"masterserver", "https://ms.kartkrew.org/ms/api", CV_SAVE|CV_CALL, NULL, MasterServer_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||||
|
consvar_t cv_rendezvousserver = {"rendezvousserver", "jart-dev.jameds.org", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||||
consvar_t cv_servername = {"servername", "SRB2Kart server", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Update_parameters, 0, NULL, NULL, 0, 0, NULL};
|
consvar_t cv_servername = {"servername", "SRB2Kart server", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Update_parameters, 0, NULL, NULL, 0, 0, NULL};
|
||||||
consvar_t cv_server_contact = {"server_contact", "", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Update_parameters, 0, NULL, NULL, 0, 0, NULL};
|
consvar_t cv_server_contact = {"server_contact", "", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Update_parameters, 0, NULL, NULL, 0, 0, NULL};
|
||||||
|
|
||||||
|
@ -99,6 +100,7 @@ void AddMServCommands(void)
|
||||||
CV_RegisterVar(&cv_masterserver_debug);
|
CV_RegisterVar(&cv_masterserver_debug);
|
||||||
CV_RegisterVar(&cv_masterserver_token);
|
CV_RegisterVar(&cv_masterserver_token);
|
||||||
CV_RegisterVar(&cv_advertise);
|
CV_RegisterVar(&cv_advertise);
|
||||||
|
CV_RegisterVar(&cv_rendezvousserver);
|
||||||
CV_RegisterVar(&cv_servername);
|
CV_RegisterVar(&cv_servername);
|
||||||
CV_RegisterVar(&cv_server_contact);
|
CV_RegisterVar(&cv_server_contact);
|
||||||
#ifdef MASTERSERVER
|
#ifdef MASTERSERVER
|
||||||
|
|
|
@ -58,6 +58,7 @@ extern consvar_t cv_masterserver_update_rate;
|
||||||
extern consvar_t cv_masterserver_timeout;
|
extern consvar_t cv_masterserver_timeout;
|
||||||
extern consvar_t cv_masterserver_debug;
|
extern consvar_t cv_masterserver_debug;
|
||||||
extern consvar_t cv_masterserver_token;
|
extern consvar_t cv_masterserver_token;
|
||||||
|
extern consvar_t cv_rendezvousserver;
|
||||||
|
|
||||||
extern consvar_t cv_advertise;
|
extern consvar_t cv_advertise;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue