mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge public next
This commit is contained in:
commit
fc934b38e1
27 changed files with 534 additions and 217 deletions
|
|
@ -453,8 +453,9 @@ if(${SRB2_CONFIG_HAVE_DISCORDRPC})
|
|||
if(${DISCORDRPC_FOUND})
|
||||
set(SRB2_HAVE_DISCORDRPC ON)
|
||||
add_definitions(-DHAVE_DISCORDRPC)
|
||||
set(SRB2_DISCORDRPC_SOURCES discord.c)
|
||||
set(SRB2_DISCORDRPC_HEADERS discord.h)
|
||||
add_definitions(-DUSE_STUN)
|
||||
set(SRB2_DISCORDRPC_SOURCES discord.c stun.c)
|
||||
set(SRB2_DISCORDRPC_HEADERS discord.h stun.h)
|
||||
prepend_sources(SRB2_DISCORDRPC_SOURCES)
|
||||
prepend_sources(SRB2_DISCORDRPC_HEADERS)
|
||||
source_group("Discord Rich Presence" FILES ${SRB2_DISCORDRPC_SOURCES} ${SRB2_DISCORDRPC_HEADERS})
|
||||
|
|
|
|||
|
|
@ -393,8 +393,8 @@ endif
|
|||
|
||||
ifdef HAVE_DISCORDRPC
|
||||
LIBS+=-ldiscord-rpc
|
||||
CFLAGS+=-DHAVE_DISCORDRPC
|
||||
OBJS+=$(OBJDIR)/discord.o
|
||||
CFLAGS+=-DHAVE_DISCORDRPC -DUSE_STUN
|
||||
OBJS+=$(OBJDIR)/discord.o $(OBJDIR)/stun.o
|
||||
endif
|
||||
|
||||
include blua/Makefile.cfg
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ enum
|
|||
/* Command buffer flags. */
|
||||
enum
|
||||
{
|
||||
COM_SAFE = 1,
|
||||
COM_SAFE = 0x01,
|
||||
};
|
||||
|
||||
typedef void (*com_func_t)(void);
|
||||
|
|
|
|||
|
|
@ -2346,7 +2346,10 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent)
|
|||
cl_mode = CL_CHECKFILES;
|
||||
}
|
||||
else
|
||||
{
|
||||
cl_mode = CL_ASKJOIN; // files need not be checked for the server.
|
||||
*asksent = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -3575,6 +3578,76 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_CURL
|
||||
/** Add a login for HTTP downloads. If the
|
||||
* user/password is missing, remove it.
|
||||
*
|
||||
* \sa Command_list_http_logins
|
||||
*/
|
||||
static void Command_set_http_login (void)
|
||||
{
|
||||
HTTP_login *login;
|
||||
HTTP_login **prev_next;
|
||||
|
||||
if (COM_Argc() < 2)
|
||||
{
|
||||
CONS_Printf(
|
||||
"set_http_login <URL> [user:password]: Set or remove a login to "
|
||||
"authenticate HTTP downloads.\n"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
login = CURLGetLogin(COM_Argv(1), &prev_next);
|
||||
|
||||
if (COM_Argc() == 2)
|
||||
{
|
||||
if (login)
|
||||
{
|
||||
(*prev_next) = login->next;
|
||||
CONS_Printf("Login for '%s' removed.\n", login->url);
|
||||
Z_Free(login);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (login)
|
||||
Z_Free(login->auth);
|
||||
else
|
||||
{
|
||||
login = ZZ_Alloc(sizeof *login);
|
||||
login->url = Z_StrDup(COM_Argv(1));
|
||||
}
|
||||
|
||||
login->auth = Z_StrDup(COM_Argv(2));
|
||||
|
||||
login->next = curl_logins;
|
||||
curl_logins = login;
|
||||
}
|
||||
}
|
||||
|
||||
/** List logins for HTTP downloads.
|
||||
*
|
||||
* \sa Command_set_http_login
|
||||
*/
|
||||
static void Command_list_http_logins (void)
|
||||
{
|
||||
HTTP_login *login;
|
||||
|
||||
for (
|
||||
login = curl_logins;
|
||||
login;
|
||||
login = login->next
|
||||
){
|
||||
CONS_Printf(
|
||||
"'%s' -> '%s'\n",
|
||||
login->url,
|
||||
login->auth
|
||||
);
|
||||
}
|
||||
}
|
||||
#endif/*HAVE_CURL*/
|
||||
|
||||
static CV_PossibleValue_t netticbuffer_cons_t[] = {{0, "MIN"}, {3, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_netticbuffer = CVAR_INIT ("netticbuffer", "1", CV_SAVE, netticbuffer_cons_t, NULL);
|
||||
|
||||
|
|
@ -3650,6 +3723,10 @@ void D_ClientServerInit(void)
|
|||
COM_AddCommand("reloadbans", Command_ReloadBan);
|
||||
COM_AddCommand("connect", Command_connect);
|
||||
COM_AddCommand("nodes", Command_Nodes);
|
||||
#ifdef HAVE_CURL
|
||||
COM_AddCommand("set_http_login", Command_set_http_login);
|
||||
COM_AddCommand("list_http_logins", Command_list_http_logins);
|
||||
#endif
|
||||
#ifdef PACKETDROP
|
||||
COM_AddCommand("drop", Command_Drop);
|
||||
COM_AddCommand("droprate", Command_Droprate);
|
||||
|
|
|
|||
|
|
@ -567,6 +567,7 @@ extern INT32 mapchangepending;
|
|||
|
||||
// Points inside doomcom
|
||||
extern doomdata_t *netbuffer;
|
||||
extern consvar_t cv_stunserver;
|
||||
extern consvar_t cv_httpsource;
|
||||
|
||||
extern consvar_t cv_showjoinaddress;
|
||||
|
|
|
|||
|
|
@ -749,6 +749,10 @@ void D_RegisterServerCommands(void)
|
|||
|
||||
CV_RegisterVar(&cv_dummyconsvar);
|
||||
|
||||
#ifdef USE_STUN
|
||||
CV_RegisterVar(&cv_stunserver);
|
||||
#endif
|
||||
|
||||
CV_RegisterVar(&cv_discordinvites);
|
||||
RegisterNetXCmd(XD_DISCORD, Got_DiscordInfo);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@ static UINT32 curl_origfilesize;
|
|||
static UINT32 curl_origtotalfilesize;
|
||||
static char *curl_realname = NULL;
|
||||
fileneeded_t *curl_curfile = NULL;
|
||||
HTTP_login *curl_logins;
|
||||
#endif
|
||||
|
||||
luafiletransfer_t *luafiletransfers = NULL;
|
||||
|
|
@ -476,10 +477,10 @@ INT32 CL_CheckFiles(void)
|
|||
|
||||
for (i = 0; i < fileneedednum; i++)
|
||||
{
|
||||
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_FALLBACK)
|
||||
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD || fileneeded[i].status == FS_FALLBACK)
|
||||
downloadrequired = true;
|
||||
|
||||
if (fileneeded[i].status == FS_FOUND || fileneeded[i].status == FS_NOTFOUND)
|
||||
if (fileneeded[i].status != FS_OPEN)
|
||||
filestoload++;
|
||||
|
||||
if (fileneeded[i].status != FS_NOTCHECKED) //since we're running this over multiple tics now, its possible for us to come across files checked in previous tics
|
||||
|
|
@ -1646,6 +1647,8 @@ int curlprogress_callback(void *clientp, double dltotal, double dlnow, double ul
|
|||
|
||||
void CURLPrepareFile(const char* url, int dfilenum)
|
||||
{
|
||||
HTTP_login *login;
|
||||
|
||||
#ifdef PARANOIA
|
||||
if (M_CheckParm("-nodownload"))
|
||||
I_Error("Attempted to download files in -nodownload mode");
|
||||
|
|
@ -1674,6 +1677,14 @@ void CURLPrepareFile(const char* url, int dfilenum)
|
|||
|
||||
curl_easy_setopt(http_handle, CURLOPT_USERAGENT, va("SRB2Kart/v%d.%d", VERSION, SUBVERSION)); // Set user agent as some servers won't accept invalid user agents.
|
||||
|
||||
// Authenticate if the user so wishes
|
||||
login = CURLGetLogin(url, NULL);
|
||||
|
||||
if (login)
|
||||
{
|
||||
curl_easy_setopt(http_handle, CURLOPT_USERPWD, login->auth);
|
||||
}
|
||||
|
||||
// Follow a redirect request, if sent by the server.
|
||||
curl_easy_setopt(http_handle, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
|
||||
|
|
@ -1775,4 +1786,27 @@ void CURLGetFile(void)
|
|||
curl_global_cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
HTTP_login *
|
||||
CURLGetLogin (const char *url, HTTP_login ***return_prev_next)
|
||||
{
|
||||
HTTP_login * login;
|
||||
HTTP_login ** prev_next;
|
||||
|
||||
for (
|
||||
prev_next = &curl_logins;
|
||||
( login = (*prev_next));
|
||||
prev_next = &login->next
|
||||
){
|
||||
if (strcmp(login->url, url) == 0)
|
||||
{
|
||||
if (return_prev_next)
|
||||
(*return_prev_next) = prev_next;
|
||||
|
||||
return login;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -72,6 +72,16 @@ extern UINT32 totalfilesrequestedsize;
|
|||
extern boolean curl_failedwebdownload;
|
||||
extern boolean curl_running;
|
||||
extern INT32 curl_transfers;
|
||||
|
||||
typedef struct HTTP_login HTTP_login;
|
||||
|
||||
extern struct HTTP_login
|
||||
{
|
||||
char * url;
|
||||
char * auth;
|
||||
HTTP_login * next;
|
||||
}
|
||||
*curl_logins;
|
||||
#endif
|
||||
|
||||
UINT8 *PutFileNeeded(UINT16 firstfile);
|
||||
|
|
@ -151,6 +161,7 @@ size_t nameonlylength(const char *s);
|
|||
#ifdef HAVE_CURL
|
||||
void CURLPrepareFile(const char* url, int dfilenum);
|
||||
void CURLGetFile(void);
|
||||
HTTP_login * CURLGetLogin (const char *url, HTTP_login ***return_prev_next);
|
||||
#endif
|
||||
|
||||
#endif // __D_NETFIL__
|
||||
|
|
|
|||
138
src/discord.c
138
src/discord.c
|
|
@ -12,9 +12,7 @@
|
|||
|
||||
#ifdef HAVE_DISCORDRPC
|
||||
|
||||
#ifdef HAVE_CURL
|
||||
#include <curl/curl.h>
|
||||
#endif // HAVE_CURL
|
||||
#include <time.h>
|
||||
|
||||
#include "i_system.h"
|
||||
#include "d_clisrv.h"
|
||||
|
|
@ -27,6 +25,8 @@
|
|||
#include "mserv.h" // cv_advertise
|
||||
#include "z_zone.h"
|
||||
#include "byteptr.h"
|
||||
#include "stun.h"
|
||||
#include "i_tcp.h" // current_port
|
||||
|
||||
#include "discord.h"
|
||||
#include "doomdef.h"
|
||||
|
|
@ -45,16 +45,7 @@ struct discordInfo_s discordInfo;
|
|||
|
||||
discordRequest_t *discordRequestList = NULL;
|
||||
|
||||
#ifdef HAVE_CURL
|
||||
struct SelfIPbuffer
|
||||
{
|
||||
CURL *curl;
|
||||
char *pointer;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
static char self_ip[IP_SIZE];
|
||||
#endif // HAVE_CURL
|
||||
|
||||
/*--------------------------------------------------
|
||||
static char *DRPC_XORIPString(const char *input)
|
||||
|
|
@ -335,39 +326,23 @@ void DRPC_Init(void)
|
|||
DRPC_UpdatePresence();
|
||||
}
|
||||
|
||||
#ifdef HAVE_CURL
|
||||
/*--------------------------------------------------
|
||||
static size_t DRPC_WriteServerIP(char *s, size_t size, size_t n, void *userdata)
|
||||
static void DRPC_GotServerIP(UINT32 address)
|
||||
|
||||
Writing function for use with curl. Only intended to be used with simple text.
|
||||
Callback triggered by successful STUN response.
|
||||
|
||||
Input Arguments:-
|
||||
s - Data to write
|
||||
size - Always 1.
|
||||
n - Length of data
|
||||
userdata - Passed in from CURLOPT_WRITEDATA, intended to be SelfIPbuffer
|
||||
address - IPv4 address of this machine, in network byte order.
|
||||
|
||||
Return:-
|
||||
Number of bytes wrote in this pass.
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
static size_t DRPC_WriteServerIP(char *s, size_t size, size_t n, void *userdata)
|
||||
static void DRPC_GotServerIP(UINT32 address)
|
||||
{
|
||||
struct SelfIPbuffer *buffer;
|
||||
size_t newlength;
|
||||
|
||||
buffer = userdata;
|
||||
|
||||
newlength = buffer->length + size*n;
|
||||
buffer->pointer = realloc(buffer->pointer, newlength+1);
|
||||
|
||||
memcpy(buffer->pointer + buffer->length, s, size*n);
|
||||
|
||||
buffer->pointer[newlength] = '\0';
|
||||
buffer->length = newlength;
|
||||
|
||||
return size*n;
|
||||
const unsigned char * p = (const unsigned char *)&address;
|
||||
sprintf(self_ip, "%u.%u.%u.%u:%u", p[0], p[1], p[2], p[3], current_port);
|
||||
DRPC_UpdatePresence();
|
||||
}
|
||||
#endif // HAVE_CURL
|
||||
|
||||
/*--------------------------------------------------
|
||||
static const char *DRPC_GetServerIP(void)
|
||||
|
|
@ -387,64 +362,21 @@ static const char *DRPC_GetServerIP(void)
|
|||
{
|
||||
// We're not the server, so we could successfully get the IP!
|
||||
// No need to do anything else :)
|
||||
return address;
|
||||
sprintf(self_ip, "%s:%u", address, current_port);
|
||||
return self_ip;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_CURL
|
||||
// This is a little bit goofy, but
|
||||
// there's practically no good way to get your own public IP address,
|
||||
// so we've gotta break out curl for this :V
|
||||
if (!self_ip[0])
|
||||
{
|
||||
CURL *curl;
|
||||
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
curl = curl_easy_init();
|
||||
|
||||
if (curl)
|
||||
{
|
||||
// The API to get your public IP address from.
|
||||
// Picked because it's stupid simple and it's been up for a long time.
|
||||
const char *api = "http://ip4only.me/api/";
|
||||
|
||||
struct SelfIPbuffer buffer;
|
||||
CURLcode success;
|
||||
|
||||
buffer.length = 0;
|
||||
buffer.pointer = malloc(buffer.length+1);
|
||||
buffer.pointer[0] = '\0';
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, api);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, DRPC_WriteServerIP);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
|
||||
|
||||
success = curl_easy_perform(curl);
|
||||
|
||||
if (success == CURLE_OK)
|
||||
{
|
||||
char *tmp;
|
||||
tmp = strtok(buffer.pointer, ",");
|
||||
|
||||
if (!strcmp(tmp, "IPv4")) // ensure correct type of IP
|
||||
{
|
||||
tmp = strtok(NULL, ",");
|
||||
strncpy(self_ip, tmp, IP_SIZE); // Yay, we have the IP :)
|
||||
}
|
||||
}
|
||||
|
||||
free(buffer.pointer);
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
|
||||
curl_global_cleanup();
|
||||
}
|
||||
|
||||
if (self_ip[0])
|
||||
{
|
||||
return self_ip;
|
||||
}
|
||||
else
|
||||
#endif // HAVE_CURL
|
||||
return NULL; // Could not get your IP for whatever reason, so we cannot do Discord invites
|
||||
{
|
||||
// There happens to be a good way to get it after all! :D
|
||||
STUN_bind(DRPC_GotServerIP);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
@ -510,19 +442,6 @@ void DRPC_UpdatePresence(void)
|
|||
// Server info
|
||||
if (netgame)
|
||||
{
|
||||
if (cv_advertise.value)
|
||||
{
|
||||
discordPresence.state = "Public";
|
||||
}
|
||||
else
|
||||
{
|
||||
discordPresence.state = "Private";
|
||||
}
|
||||
|
||||
discordPresence.partyId = server_context; // Thanks, whoever gave us Mumble support, for implementing the EXACT thing Discord wanted for this field!
|
||||
discordPresence.partySize = D_NumPlayers(); // Players in server
|
||||
discordPresence.partyMax = discordInfo.maxPlayers; // Max players
|
||||
|
||||
if (DRPC_InvitesAreAllowed() == true)
|
||||
{
|
||||
const char *join;
|
||||
|
|
@ -536,7 +455,24 @@ void DRPC_UpdatePresence(void)
|
|||
|
||||
joinSecretSet = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (cv_advertise.value)
|
||||
{
|
||||
discordPresence.state = "Public";
|
||||
}
|
||||
else
|
||||
{
|
||||
discordPresence.state = "Private";
|
||||
}
|
||||
|
||||
discordPresence.partyId = server_context; // Thanks, whoever gave us Mumble support, for implementing the EXACT thing Discord wanted for this field!
|
||||
discordPresence.partySize = D_NumPlayers(); // Players in server
|
||||
discordPresence.partyMax = discordInfo.maxPlayers; // Max players
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -152,6 +152,7 @@ static UINT8 UPNP_support = TRUE;
|
|||
#include "d_netfil.h"
|
||||
#include "i_tcp.h"
|
||||
#include "m_argv.h"
|
||||
#include "stun.h"
|
||||
|
||||
#include "doomstat.h"
|
||||
|
||||
|
|
@ -575,6 +576,13 @@ static boolean SOCK_Get(void)
|
|||
(void *)&fromaddress, &fromlen);
|
||||
if (c != ERRSOCKET)
|
||||
{
|
||||
#ifdef USE_STUN
|
||||
if (STUN_got_response(doomcom->data, c))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// find remote node number
|
||||
for (j = 1; j <= MAXNETNODES; j++) //include LAN
|
||||
{
|
||||
|
|
|
|||
|
|
@ -387,7 +387,8 @@ static int lib_pAproxDistance(lua_State *L)
|
|||
fixed_t dx = luaL_checkfixed(L, 1);
|
||||
fixed_t dy = luaL_checkfixed(L, 2);
|
||||
//HUDSAFE
|
||||
lua_pushfixed(L, P_AproxDistance(dx, dy));
|
||||
LUA_Deprecated(L, "P_AproxDistance", "FixedHypot");
|
||||
lua_pushfixed(L, FixedHypot(dx, dy));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -536,7 +536,6 @@ static luaL_Reg lib[] = {
|
|||
{"CV_StealthSet", lib_cvStealthSet},
|
||||
{"CV_AddValue", lib_cvAddValue},
|
||||
{"CONS_Printf", lib_consPrintf},
|
||||
{"CV_FindVar", lib_cvFindVar},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -109,10 +109,10 @@ void LUAh_PlayerQuit(player_t *plr, kickreason_t reason); // Hook for player qui
|
|||
boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping,
|
||||
UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms); // Hook for music changes
|
||||
|
||||
boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Allows to write to player cmd before the game does anything with them.
|
||||
boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Allows to write to player cmd before the game does anything with them.
|
||||
|
||||
void LUAh_IntermissionThinker(void); // Hook for Y_Ticker
|
||||
void LUAh_VoteThinker(void); // Hook for Y_VoteTicker
|
||||
void LUAh_VoteThinker(void); // Hook for Y_VoteTicker
|
||||
|
||||
#define LUAh_ShieldSpawn(player) LUAh_PlayerHook(player, hook_ShieldSpawn) // Hook for P_SpawnShieldOrb
|
||||
#define LUAh_ShieldSpecial(player) LUAh_PlayerHook(player, hook_ShieldSpecial) // Hook for shield abilities
|
||||
|
|
@ -128,4 +128,3 @@ boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_
|
|||
#define LUAh_PlayerThink(player) LUAh_PlayerHook(player, hook_PlayerThink) // Hook for P_PlayerThink
|
||||
boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname); // Hook for whether a jingle of the given music should continue playing
|
||||
void LUAh_GameQuit(void); // Hook for game quitting
|
||||
boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Hook for building player's ticcmd struct (Ported from SRB2Kart)
|
||||
|
|
|
|||
|
|
@ -26,25 +26,35 @@
|
|||
static int lib_iteratePlayers(lua_State *L)
|
||||
{
|
||||
INT32 i = -1;
|
||||
|
||||
if (lua_gettop(L) < 2)
|
||||
{
|
||||
//return luaL_error(L, "Don't call players.iterate() directly, use it as 'for player in players.iterate do <block> end'.");
|
||||
lua_pushcfunction(L, lib_iteratePlayers);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lua_settop(L, 2);
|
||||
lua_remove(L, 1); // state is unused.
|
||||
|
||||
if (!lua_isnil(L, 1))
|
||||
i = (INT32)(*((player_t **)luaL_checkudata(L, 1, META_PLAYER)) - players);
|
||||
for (i++; i < MAXPLAYERS; i++)
|
||||
|
||||
i++;
|
||||
|
||||
if (i == serverplayer)
|
||||
{
|
||||
return LUA_PushServerPlayer(L);
|
||||
}
|
||||
|
||||
for (; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
if (!players[i].mo)
|
||||
continue;
|
||||
LUA_PushUserdata(L, &players[i], META_PLAYER);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -57,10 +67,10 @@ static int lib_getPlayer(lua_State *L)
|
|||
lua_Integer i = luaL_checkinteger(L, 2);
|
||||
if (i < 0 || i >= MAXPLAYERS)
|
||||
return luaL_error(L, "players[] index %d out of range (0 - %d)", i, MAXPLAYERS-1);
|
||||
if (i == serverplayer)
|
||||
return LUA_PushServerPlayer(L);
|
||||
if (!playeringame[i])
|
||||
return 0;
|
||||
if (!players[i].mo)
|
||||
return 0;
|
||||
LUA_PushUserdata(L, &players[i], META_PLAYER);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -121,8 +131,6 @@ static int lib_iterateDisplayplayers(lua_State *L)
|
|||
if (i > splitscreen || !playeringame[displayplayers[i]])
|
||||
return 0; // Stop! There are no more players for us to go through. There will never be a player gap in displayplayers.
|
||||
|
||||
if (!players[displayplayers[i]].mo)
|
||||
continue;
|
||||
LUA_PushUserdata(L, &players[displayplayers[i]], META_PLAYER);
|
||||
lua_pushinteger(L, i); // push this to recall what number we were on for the next function call. I suppose this also means you can retrieve the splitscreen player number with 'for p, n in displayplayers.iterate'!
|
||||
return 2;
|
||||
|
|
@ -143,8 +151,6 @@ static int lib_getDisplayplayers(lua_State *L)
|
|||
return 0;
|
||||
if (!playeringame[displayplayers[i]])
|
||||
return 0;
|
||||
if (!players[displayplayers[i]].mo)
|
||||
return 0;
|
||||
LUA_PushUserdata(L, &players[displayplayers[i]], META_PLAYER);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -182,17 +188,8 @@ static int player_get(lua_State *L)
|
|||
lua_pushboolean(L, true);
|
||||
else if (fastcmp(field,"name"))
|
||||
lua_pushstring(L, player_names[plr-players]);
|
||||
else if (fastcmp(field,"realmo"))
|
||||
LUA_PushUserdata(L, plr->mo, META_MOBJ);
|
||||
// Kept for backward-compatibility
|
||||
// Should be fixed to work like "realmo" later
|
||||
else if (fastcmp(field,"mo"))
|
||||
{
|
||||
if (plr->spectator)
|
||||
lua_pushnil(L);
|
||||
else
|
||||
LUA_PushUserdata(L, plr->mo, META_MOBJ);
|
||||
}
|
||||
LUA_PushUserdata(L, plr->mo, META_MOBJ);
|
||||
else if (fastcmp(field,"cmd"))
|
||||
LUA_PushUserdata(L, &plr->cmd, META_TICCMD);
|
||||
else if (fastcmp(field,"playerstate"))
|
||||
|
|
@ -447,7 +444,7 @@ static int player_set(lua_State *L)
|
|||
if (hook_cmd_running)
|
||||
return luaL_error(L, "Do not alter player_t in BuildCMD code!");
|
||||
|
||||
if (fastcmp(field,"mo") || fastcmp(field,"realmo")) {
|
||||
if (fastcmp(field,"mo")) {
|
||||
mobj_t *newmo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
|
||||
plr->mo->player = NULL; // remove player pointer from old mobj
|
||||
(newmo->player = plr)->mo = newmo; // set player pointer for new mobj, and set new mobj as the player's mobj
|
||||
|
|
|
|||
|
|
@ -731,6 +731,14 @@ void LUA_PushUserdata(lua_State *L, void *data, const char *meta)
|
|||
lua_remove(L, -2); // remove LREG_VALID
|
||||
}
|
||||
|
||||
int LUA_PushServerPlayer(lua_State *L)
|
||||
{
|
||||
if ((!multiplayer || !(netgame || demo.playback)) && !playeringame[serverplayer])
|
||||
return 0;
|
||||
LUA_PushUserdata(L, &players[serverplayer], META_PLAYER);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// When userdata is freed, use this function to remove it from Lua.
|
||||
void LUA_InvalidateUserdata(void *data)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ void LUA_DumpFile(const char *filename);
|
|||
fixed_t LUA_EvalMath(const char *word);
|
||||
void LUA_PushLightUserdata(lua_State *L, void *data, const char *meta);
|
||||
void LUA_PushUserdata(lua_State *L, void *data, const char *meta);
|
||||
int LUA_PushServerPlayer(lua_State *L);
|
||||
void LUA_InvalidateUserdata(void *data);
|
||||
void LUA_InvalidateLevel(void);
|
||||
void LUA_InvalidateMapthings(void);
|
||||
|
|
|
|||
|
|
@ -18,8 +18,10 @@
|
|||
#define HAVE_SQRTF
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "m_fixed.h"
|
||||
#include "tables.h" // ANGLETOFINESHIFT
|
||||
|
||||
#ifdef __USE_C_FIXEDMUL__
|
||||
|
||||
|
|
@ -105,20 +107,34 @@ fixed_t FixedSqrt(fixed_t x)
|
|||
|
||||
fixed_t FixedHypot(fixed_t x, fixed_t y)
|
||||
{
|
||||
fixed_t ax, yx, yx2, yx1;
|
||||
if (abs(y) > abs(x)) // |y|>|x|
|
||||
// Moved the code from R_PointToDist2 to here,
|
||||
// since R_PointToDist2 did the same thing,
|
||||
// except less prone to overflowing.
|
||||
|
||||
angle_t angle;
|
||||
fixed_t dist;
|
||||
|
||||
x = abs(x);
|
||||
y = abs(y);
|
||||
|
||||
if (y > x)
|
||||
{
|
||||
ax = abs(y); // |y| => ax
|
||||
yx = FixedDiv(x, y); // (x/y)
|
||||
fixed_t temp;
|
||||
|
||||
temp = x;
|
||||
x = y;
|
||||
y = temp;
|
||||
}
|
||||
else // |x|>|y|
|
||||
{
|
||||
ax = abs(x); // |x| => ax
|
||||
yx = FixedDiv(y, x); // (x/y)
|
||||
}
|
||||
yx2 = FixedMul(yx, yx); // (x/y)^2
|
||||
yx1 = FixedSqrt(1 * FRACUNIT + yx2); // (1 + (x/y)^2)^1/2
|
||||
return FixedMul(ax, yx1); // |x|*((1 + (x/y)^2)^1/2)
|
||||
|
||||
if (!y)
|
||||
return x;
|
||||
|
||||
angle = (tantoangle[FixedDiv(y, x)>>DBITS] + ANGLE_90) >> ANGLETOFINESHIFT;
|
||||
|
||||
// use as cosine
|
||||
dist = FixedDiv(x, FINESINE(angle));
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
vector2_t *FV2_Load(vector2_t *vec, fixed_t x, fixed_t y)
|
||||
|
|
|
|||
55
src/m_swap.h
55
src/m_swap.h
|
|
@ -2,7 +2,7 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2020 by Sonic Team Junior.
|
||||
// Copyright (C) 1999-2018 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
|
|
@ -14,39 +14,34 @@
|
|||
#ifndef __M_SWAP__
|
||||
#define __M_SWAP__
|
||||
|
||||
// Endianess handling.
|
||||
// WAD files are stored little endian.
|
||||
#include "endian.h"
|
||||
|
||||
// Little to big endian
|
||||
#define SWAP_SHORT(x) ((INT16)(\
|
||||
(((UINT16)(x) & (UINT16)0x00ffU) << 8) \
|
||||
| \
|
||||
(((UINT16)(x) & (UINT16)0xff00U) >> 8))) \
|
||||
|
||||
#define SWAP_LONG(x) ((INT32)(\
|
||||
(((UINT32)(x) & (UINT32)0x000000ffUL) << 24) \
|
||||
| \
|
||||
(((UINT32)(x) & (UINT32)0x0000ff00UL) << 8) \
|
||||
| \
|
||||
(((UINT32)(x) & (UINT32)0x00ff0000UL) >> 8) \
|
||||
| \
|
||||
(((UINT32)(x) & (UINT32)0xff000000UL) >> 24)))
|
||||
|
||||
// Endianess handling.
|
||||
// WAD files are stored little endian.
|
||||
#ifdef SRB2_BIG_ENDIAN
|
||||
|
||||
#define SHORT(x) ((INT16)(\
|
||||
(((UINT16)(x) & (UINT16)0x00ffU) << 8) \
|
||||
| \
|
||||
(((UINT16)(x) & (UINT16)0xff00U) >> 8))) \
|
||||
|
||||
#define LONG(x) ((INT32)(\
|
||||
(((UINT32)(x) & (UINT32)0x000000ffUL) << 24) \
|
||||
| \
|
||||
(((UINT32)(x) & (UINT32)0x0000ff00UL) << 8) \
|
||||
| \
|
||||
(((UINT32)(x) & (UINT32)0x00ff0000UL) >> 8) \
|
||||
| \
|
||||
(((UINT32)(x) & (UINT32)0xff000000UL) >> 24)))
|
||||
|
||||
#define SHORT SWAP_SHORT
|
||||
#define LONG SWAP_LONG
|
||||
#define MSBF_SHORT(x) ((INT16)(x))
|
||||
#define MSBF_LONG(x) ((INT32)(x))
|
||||
#else
|
||||
#define SHORT(x) ((INT16)(x))
|
||||
#define LONG(x) ((INT32)(x))
|
||||
#endif
|
||||
|
||||
// Big to little endian
|
||||
#ifdef SRB2_LITTLE_ENDIAN
|
||||
#define BIGENDIAN_LONG(x) ((INT32)(((x)>>24)&0xff)|(((x)<<8)&0xff0000)|(((x)>>8)&0xff00)|(((x)<<24)&0xff000000))
|
||||
#define BIGENDIAN_SHORT(x) ((INT16)(((x)>>8)|((x)<<8)))
|
||||
#else
|
||||
#define BIGENDIAN_LONG(x) ((INT32)(x))
|
||||
#define BIGENDIAN_SHORT(x) ((INT16)(x))
|
||||
#define SHORT(x) ((INT16)(x))
|
||||
#define LONG(x) ((INT32)(x))
|
||||
#define MSBF_SHORT SWAP_SHORT
|
||||
#define MSBF_LONG SWAP_LONG
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -24,19 +24,6 @@
|
|||
#include "p_slopes.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
//
|
||||
// P_AproxDistance
|
||||
// Gives an estimation of distance (not exact)
|
||||
//
|
||||
fixed_t P_AproxDistance(fixed_t dx, fixed_t dy)
|
||||
{
|
||||
dx = abs(dx);
|
||||
dy = abs(dy);
|
||||
if (dx < dy)
|
||||
return dx + dy - (dx>>1);
|
||||
return dx + dy - (dy>>1);
|
||||
}
|
||||
|
||||
//
|
||||
// P_ClosestPointOnLine
|
||||
// Finds the closest point on a given line to the supplied point
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ typedef boolean (*traverser_t)(intercept_t *in);
|
|||
boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2,
|
||||
INT32 pflags, traverser_t ptrav);
|
||||
|
||||
FUNCMATH fixed_t P_AproxDistance(fixed_t dx, fixed_t dy);
|
||||
#define P_AproxDistance(dx, dy) FixedHypot(dx, dy)
|
||||
void P_ClosestPointOnLine(fixed_t x, fixed_t y, line_t *line, vertex_t *result);
|
||||
void P_ClosestPointOnLine3D(const vector3_t *p, const vector3_t *line, vector3_t *result);
|
||||
INT32 P_PointOnLineSide(fixed_t x, fixed_t y, line_t *line);
|
||||
|
|
|
|||
|
|
@ -876,6 +876,10 @@ static void Polyobj_carryThings(polyobj_t *po, fixed_t dx, fixed_t dy)
|
|||
|
||||
for (; mo; mo = mo->bnext)
|
||||
{
|
||||
// lastlook is used by the SPB to determine targets, do not let it affect it
|
||||
if (mo->type == MT_SPB)
|
||||
continue;
|
||||
|
||||
if (mo->lastlook == pomovecount)
|
||||
continue;
|
||||
|
||||
|
|
@ -1106,6 +1110,10 @@ static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta,
|
|||
|
||||
for (; mo; mo = mo->bnext)
|
||||
{
|
||||
// lastlook is used by the SPB to determine targets, do not let it affect it
|
||||
if (mo->type == MT_SPB)
|
||||
continue;
|
||||
|
||||
if (mo->lastlook == pomovecount)
|
||||
continue;
|
||||
|
||||
|
|
|
|||
|
|
@ -4303,6 +4303,7 @@ void P_PlayerThink(player_t *player)
|
|||
|
||||
if (player->playerstate == PST_DEAD)
|
||||
{
|
||||
LUAh_PlayerThink(player);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
24
src/r_main.c
24
src/r_main.c
|
|
@ -368,29 +368,7 @@ angle_t R_PointToAngle2(fixed_t pviewx, fixed_t pviewy, fixed_t x, fixed_t y)
|
|||
|
||||
fixed_t R_PointToDist2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1)
|
||||
{
|
||||
angle_t angle;
|
||||
fixed_t dx, dy, dist;
|
||||
|
||||
dx = abs(px1 - px2);
|
||||
dy = abs(py1 - py2);
|
||||
|
||||
if (dy > dx)
|
||||
{
|
||||
fixed_t temp;
|
||||
|
||||
temp = dx;
|
||||
dx = dy;
|
||||
dy = temp;
|
||||
}
|
||||
if (!dy)
|
||||
return dx;
|
||||
|
||||
angle = (tantoangle[FixedDiv(dy, dx)>>DBITS] + ANGLE_90) >> ANGLETOFINESHIFT;
|
||||
|
||||
// use as cosine
|
||||
dist = FixedDiv(dx, FINESINE(angle));
|
||||
|
||||
return dist;
|
||||
return FixedHypot(px1 - px2, py1 - py2);
|
||||
}
|
||||
|
||||
// Little extra utility. Works in the same way as R_PointToAngle2
|
||||
|
|
|
|||
|
|
@ -2336,7 +2336,7 @@ static boolean S_PlayMusic(boolean looping, UINT32 fadeinms)
|
|||
S_InitMusicVolume(); // switch between digi and sequence volume
|
||||
|
||||
if (S_MusicNotInFocus())
|
||||
S_PauseAudio();
|
||||
I_SetMusicVolume(0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2780,9 +2780,9 @@ static void PlayMusicIfUnfocused_OnChange(void)
|
|||
if (window_notinfocus)
|
||||
{
|
||||
if (cv_playmusicifunfocused.value)
|
||||
I_PauseSong();
|
||||
I_SetMusicVolume(0);
|
||||
else
|
||||
I_ResumeSong();
|
||||
S_InitMusicVolume();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -651,7 +651,7 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt)
|
|||
window_notinfocus = false;
|
||||
|
||||
if (!paused)
|
||||
S_ResumeAudio(); //resume it
|
||||
S_InitMusicVolume();
|
||||
|
||||
if (cv_gamesounds.value)
|
||||
S_EnableSound();
|
||||
|
|
@ -670,7 +670,7 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt)
|
|||
// Tell game we lost focus, pause music
|
||||
window_notinfocus = true;
|
||||
if (!cv_playmusicifunfocused.value)
|
||||
I_PauseSong();
|
||||
I_SetMusicVolume(0);
|
||||
if (!cv_playsoundifunfocused.value)
|
||||
S_DisableSound();
|
||||
|
||||
|
|
|
|||
235
src/stun.c
Normal file
235
src/stun.c
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2020 by James R.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file stun.c
|
||||
/// \brief RFC 5389 client implementation to fetch external IP address.
|
||||
|
||||
/* https://tools.ietf.org/html/rfc5389 */
|
||||
|
||||
#if defined (__linux__)
|
||||
#include <sys/random.h>
|
||||
#elif defined (_WIN32)
|
||||
#define _CRT_RAND_S
|
||||
#elif defined (__APPLE__)
|
||||
#include <CommonCrypto/CommonRandom.h>
|
||||
#else
|
||||
#error "Need CSPRNG."
|
||||
#endif
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "d_clisrv.h"
|
||||
#include "command.h"
|
||||
#include "i_net.h"
|
||||
#include "stun.h"
|
||||
|
||||
/* https://gist.github.com/zziuni/3741933 */
|
||||
/* I can only trust google to keep their shit up :y */
|
||||
consvar_t cv_stunserver = CVAR_INIT (
|
||||
"stunserver", "stun.l.google.com:19302", CV_SAVE, NULL, NULL
|
||||
);
|
||||
|
||||
static stun_callback_t stun_callback;
|
||||
|
||||
/* 18.4 STUN UDP and TCP Port Numbers */
|
||||
|
||||
#define STUN_PORT "3478"
|
||||
|
||||
/* 6. STUN Message Structure */
|
||||
|
||||
#define BIND_REQUEST 0x0001
|
||||
#define BIND_RESPONSE 0x0101
|
||||
|
||||
static const UINT32 MAGIC_COOKIE = MSBF_LONG (0x2112A442);
|
||||
|
||||
static char transaction_id[12];
|
||||
|
||||
/* 18.2 STUN Attribute Registry */
|
||||
|
||||
#define XOR_MAPPED_ADDRESS 0x0020
|
||||
|
||||
/* 15.1 MAPPED-ADDRESS */
|
||||
|
||||
#define STUN_IPV4 0x01
|
||||
|
||||
static SINT8
|
||||
STUN_node (void)
|
||||
{
|
||||
SINT8 node;
|
||||
|
||||
char * const colon = strchr(cv_stunserver.zstring, ':');
|
||||
|
||||
const char * const host = cv_stunserver.zstring;
|
||||
const char * const port = &colon[1];
|
||||
|
||||
I_Assert(I_NetMakeNodewPort != NULL);
|
||||
|
||||
if (colon != NULL)
|
||||
{
|
||||
*colon = '\0';
|
||||
|
||||
node = I_NetMakeNodewPort(host, port);
|
||||
|
||||
*colon = ':';
|
||||
}
|
||||
else
|
||||
{
|
||||
node = I_NetMakeNodewPort(host, STUN_PORT);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static void
|
||||
csprng
|
||||
(
|
||||
void * const buffer,
|
||||
const size_t size
|
||||
){
|
||||
#if defined (_WIN32)
|
||||
size_t o;
|
||||
|
||||
for (o = 0; o < size; o += sizeof (unsigned int))
|
||||
{
|
||||
rand_s((unsigned int *)&((char *)buffer)[o]);
|
||||
}
|
||||
#elif defined (__linux__)
|
||||
getrandom(buffer, size, 0U);
|
||||
#elif defined (__APPLE__)
|
||||
CCRandomGenerateBytes(buffer, size);
|
||||
#elif defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__)
|
||||
arc4random_buf(buffer, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
STUN_bind (stun_callback_t callback)
|
||||
{
|
||||
/* 6. STUN Message Structure */
|
||||
|
||||
const UINT16 type = MSBF_SHORT (BIND_REQUEST);
|
||||
|
||||
const SINT8 node = STUN_node();
|
||||
|
||||
doomcom->remotenode = node;
|
||||
doomcom->datalength = 20;
|
||||
|
||||
csprng(transaction_id, 12U);
|
||||
|
||||
memcpy(&doomcom->data[0], &type, 2U);
|
||||
memset(&doomcom->data[2], 0, 2U);
|
||||
memcpy(&doomcom->data[4], &MAGIC_COOKIE, 4U);
|
||||
memcpy(&doomcom->data[8], transaction_id, 12U);
|
||||
|
||||
stun_callback = callback;
|
||||
|
||||
I_NetSend();
|
||||
Net_CloseConnection(node);/* will handle response at I_NetGet */
|
||||
}
|
||||
|
||||
static size_t
|
||||
STUN_xor_mapped_address (const char * const value)
|
||||
{
|
||||
const UINT32 xaddr = *(const UINT32 *)&value[4];
|
||||
const UINT32 addr = xaddr ^ MAGIC_COOKIE;
|
||||
|
||||
(*stun_callback)(addr);
|
||||
|
||||
return 0U;
|
||||
}
|
||||
|
||||
static size_t
|
||||
align4 (size_t n)
|
||||
{
|
||||
return n + n % 4U;
|
||||
}
|
||||
|
||||
static size_t
|
||||
STUN_parse_attribute (const char * const attribute)
|
||||
{
|
||||
/* 15. STUN Attributes */
|
||||
const UINT16 type = MSBF_SHORT (*(const UINT16 *)&attribute[0]);
|
||||
const UINT16 length = MSBF_SHORT (*(const UINT16 *)&attribute[2]);
|
||||
|
||||
/* 15.2 XOR-MAPPED-ADDRESS */
|
||||
if (
|
||||
type == XOR_MAPPED_ADDRESS &&
|
||||
length == 8U &&
|
||||
(unsigned char)attribute[5] == STUN_IPV4
|
||||
){
|
||||
return STUN_xor_mapped_address(&attribute[4]);
|
||||
}
|
||||
|
||||
return align4(4U + length);
|
||||
}
|
||||
|
||||
boolean
|
||||
STUN_got_response
|
||||
(
|
||||
const char * const buffer,
|
||||
const size_t size
|
||||
){
|
||||
const char * const end = &buffer[size];
|
||||
|
||||
const char * p = &buffer[20];
|
||||
|
||||
UINT16 type;
|
||||
UINT16 length;
|
||||
|
||||
/*
|
||||
Check for STUN response.
|
||||
|
||||
Header is 20 bytes.
|
||||
XOR-MAPPED-ADDRESS attribute is required.
|
||||
Each attribute has a 2 byte header.
|
||||
The XOR-MAPPED-ADDRESS attribute also has a 8 byte value.
|
||||
This totals 10 bytes for the attribute.
|
||||
*/
|
||||
|
||||
if (size < 30U || stun_callback == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* 6. STUN Message Structure */
|
||||
|
||||
if (
|
||||
*(const UINT32 *)&buffer[4] == MAGIC_COOKIE &&
|
||||
memcmp(&buffer[8], transaction_id, 12U) == 0
|
||||
){
|
||||
type = MSBF_SHORT (*(const UINT16 *)&buffer[0]);
|
||||
length = MSBF_SHORT (*(const UINT16 *)&buffer[2]);
|
||||
|
||||
if (
|
||||
(type >> 14) == 0U &&
|
||||
(length & 0x02) == 0U &&
|
||||
(20U + length) <= size
|
||||
){
|
||||
if (type == BIND_RESPONSE)
|
||||
{
|
||||
do
|
||||
{
|
||||
length = STUN_parse_attribute(p);
|
||||
|
||||
if (length == 0U)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
p += length;
|
||||
}
|
||||
while (p < end) ;
|
||||
}
|
||||
|
||||
stun_callback = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
20
src/stun.h
Normal file
20
src/stun.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2020 by James R.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file stun.h
|
||||
/// \brief RFC 5389 client implementation to fetch external IP address.
|
||||
|
||||
#ifndef KART_STUN_H
|
||||
#define KART_STUN_H
|
||||
|
||||
typedef void (*stun_callback_t)(UINT32 address);
|
||||
|
||||
void STUN_bind (stun_callback_t);
|
||||
boolean STUN_got_response (const char * const buffer, const size_t size);
|
||||
|
||||
#endif/*KART_STUN_H*/
|
||||
Loading…
Add table
Reference in a new issue