Merge branch 'master' into hitlag-retry

This commit is contained in:
Sally Coolatta 2020-11-10 21:37:09 -05:00
commit 2b3a86d4b4
33 changed files with 718 additions and 233 deletions

View file

@ -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})

View file

@ -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

View file

@ -35,7 +35,7 @@ enum
/* Command buffer flags. */
enum
{
COM_SAFE = 1,
COM_SAFE = 0x01,
};
typedef void (*com_func_t)(void);

View file

@ -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);
@ -5487,7 +5564,10 @@ static void CL_SendClientCmd(void)
boolean mis = false;
if (lowest_lag && ( gametic % lowest_lag ))
{
cl_packetmissed = true;
return;
}
netbuffer->packettype = PT_CLIENTCMD;

View file

@ -37,7 +37,7 @@ applications may follow different packet versions.
// be transmitted.
// Networking and tick handling related.
#define BACKUPTICS 32
#define BACKUPTICS 1024
#define TICQUEUE 512 // more than enough for most timeouts....
#define MAXTEXTCMD 256
//
@ -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;

View file

@ -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);
}

View file

@ -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

View file

@ -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__

View file

@ -9317,6 +9317,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_WATERTRAILUNDERLAY7",
"S_WATERTRAILUNDERLAY8",
"S_SPINDASHDUST",
"S_SPINDASHWIND",
#ifdef SEENAMES
"S_NAMECHECK",
#endif
@ -10397,6 +10400,9 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_WATERTRAIL",
"MT_WATERTRAILUNDERLAY",
"MT_SPINDASHDUST",
"MT_SPINDASHWIND",
#ifdef SEENAMES
"MT_NAMECHECK",
#endif

View file

@ -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
{

View file

@ -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
{

View file

@ -730,6 +730,9 @@ char sprnames[NUMSPRITES + 1][5] =
"DBCL", // Drift boost clip
"DBNC", // Drift boost clip's sparks
"DBST", // Drift boost plume
"SDDS", // Spindash dust
"SDWN", // Spindash wind
};
char spr2names[NUMPLAYERSPRITES][5] =
@ -5026,6 +5029,9 @@ state_t states[NUMSTATES] =
{SPR_WTRL, FF_TRANS50|FF_PAPERSPRITE|14, 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAILUNDERLAY7
{SPR_WTRL, FF_TRANS50|FF_PAPERSPRITE|15, 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAILUNDERLAY8
{SPR_SDDS, FF_ANIMATE, 9, {NULL}, 9, 1, S_NULL}, // S_SPINDASHDUST
{SPR_SDWN, FF_ANIMATE|FF_PAPERSPRITE, 18, {NULL}, 9, 2, S_NULL}, // S_SPINDASHWIND
#ifdef SEENAMES
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK
#endif
@ -8560,7 +8566,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
25*FRACUNIT, // mass
0, // damage
sfx_None, // activesound
MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags
MF_SOLID|MF_SPRING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
S_YELLOWSPRING2 // raisestate
},
@ -8587,7 +8593,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
40*FRACUNIT, // mass
0, // damage
sfx_None, // activesound
MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags
MF_SOLID|MF_SPRING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
S_REDSPRING2 // raisestate
},
@ -8614,7 +8620,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
64*FRACUNIT, // mass
0, // damage
sfx_None, // activesound
MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags
MF_SOLID|MF_SPRING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
S_BLUESPRING2 // raisestate
},
@ -8641,7 +8647,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
15*FRACUNIT, // mass
0, // damage
sfx_None, // activesound
MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags
MF_SOLID|MF_SPRING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
S_GREYSPRING2 // raisestate
},
@ -8668,7 +8674,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
25*FRACUNIT, // mass
25*FRACUNIT, // damage
sfx_None, // activesound
MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags
MF_SOLID|MF_SPRING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
S_YDIAG2 // raisestate
},
@ -8695,7 +8701,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
40*FRACUNIT, // mass
40*FRACUNIT, // damage
sfx_None, // activesound
MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags
MF_SOLID|MF_SPRING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
S_RDIAG2 // raisestate
},
@ -8722,7 +8728,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
64*FRACUNIT, // mass
64*FRACUNIT, // damage
sfx_None, // activesound
MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags
MF_SOLID|MF_SPRING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
S_BDIAG2 // raisestate
},
@ -8749,7 +8755,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
15*FRACUNIT, // mass
15*FRACUNIT, // damage
sfx_None, // activesound
MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags
MF_SOLID|MF_SPRING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
S_GDIAG2 // raisestate
},
@ -28675,6 +28681,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_SPINDASHDUST
-1, // doomednum
S_SPINDASHDUST, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
12*FRACUNIT, // radius
24*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_SPINDASHWIND
-1, // doomednum
S_SPINDASHWIND, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
12*FRACUNIT, // radius
24*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
// ============================================================================================================================//
#ifdef SEENAMES

View file

@ -1002,6 +1002,9 @@ typedef enum sprite
SPR_DBNC, // Drift boost clip's sparks
SPR_DBST, // Drift boost plume
SPR_SDDS, // Spindash dust
SPR_SDWN, // Spindash wind
SPR_FIRSTFREESLOT,
SPR_LASTFREESLOT = SPR_FIRSTFREESLOT + NUMSPRITEFREESLOTS - 1,
NUMSPRITES
@ -5177,6 +5180,9 @@ typedef enum state
S_WATERTRAILUNDERLAY7,
S_WATERTRAILUNDERLAY8,
S_SPINDASHDUST,
S_SPINDASHWIND,
#ifdef SEENAMES
S_NAMECHECK,
#endif
@ -6277,6 +6283,9 @@ typedef enum mobj_type
MT_WATERTRAIL,
MT_WATERTRAILUNDERLAY,
MT_SPINDASHDUST,
MT_SPINDASHWIND,
#ifdef SEENAMES
MT_NAMECHECK,
#endif

View file

@ -2044,7 +2044,7 @@ static fixed_t K_FlameShieldDashVar(INT32 val)
return (3*FRACUNIT/4) + (((val * FRACUNIT) / TICRATE) / 2);
}
tic_t K_GetSpindashChargeTime(player_t *player)
INT16 K_GetSpindashChargeTime(player_t *player)
{
// more charge time for higher speed
// Tails = 2s, Mighty = 3s, Fang = 4s, Metal = 4s
@ -6849,10 +6849,67 @@ boolean K_PlayerEBrake(player_t *player)
&& player->powers[pw_nocontrol] == 0;
}
static void K_KartSpindashDust(mobj_t *parent)
{
fixed_t rad = FixedDiv(FixedHypot(parent->radius, parent->radius), parent->scale);
INT32 i;
for (i = 0; i < 2; i++)
{
fixed_t hmomentum = P_RandomRange(6, 12) * parent->scale;
fixed_t vmomentum = P_RandomRange(2, 6) * parent->scale;
angle_t ang = parent->player->drawangle + ANGLE_180;
SINT8 flip = 1;
mobj_t *dust;
if (i & 1)
ang -= ANGLE_45;
else
ang += ANGLE_45;
dust = P_SpawnMobjFromMobj(parent,
FixedMul(rad, FINECOSINE(ang >> ANGLETOFINESHIFT)),
FixedMul(rad, FINESINE(ang >> ANGLETOFINESHIFT)),
0, MT_SPINDASHDUST
);
flip = P_MobjFlip(dust);
dust->momx = FixedMul(hmomentum, FINECOSINE(ang >> ANGLETOFINESHIFT));
dust->momy = FixedMul(hmomentum, FINESINE(ang >> ANGLETOFINESHIFT));
dust->momz = vmomentum * flip;
}
}
static void K_KartSpindashWind(mobj_t *parent)
{
mobj_t *wind = P_SpawnMobjFromMobj(parent,
P_RandomRange(-36,36) * FRACUNIT,
P_RandomRange(-36,36) * FRACUNIT,
FixedDiv(parent->height / 2, parent->scale) + (P_RandomRange(-20,20) * FRACUNIT),
MT_SPINDASHWIND
);
P_SetTarget(&wind->target, parent);
if (parent->momx || parent->momy)
wind->angle = R_PointToAngle2(0, 0, parent->momx, parent->momy);
else
wind->angle = parent->player->drawangle;
wind->momx = 3 * parent->momx / 4;
wind->momy = 3 * parent->momy / 4;
wind->momz = 3 * parent->momz / 4;
K_MatchGenericExtraFlags(wind, parent);
}
static void K_KartSpindash(player_t *player)
{
const tic_t MAXCHARGETIME = K_GetSpindashChargeTime(player);
const INT16 MAXCHARGETIME = K_GetSpindashChargeTime(player);
ticcmd_t *cmd = &player->cmd;
boolean spawnWind = (leveltime % 2 == 0);
if (player->kartstuff[k_spindash] > 0 && (cmd->buttons & (BT_DRIFT|BT_BRAKE)) != (BT_DRIFT|BT_BRAKE))
{
@ -6878,6 +6935,17 @@ static void K_KartSpindash(player_t *player)
S_StartSound(player->mo, sfx_s23c);
}
if ((player->kartstuff[k_spindashboost] > 0) && (spawnWind == true))
{
K_KartSpindashWind(player->mo);
}
if (player->kartstuff[k_spindashboost] > (TICRATE/2))
{
K_KartSpindashDust(player->mo);
}
if (K_PlayerEBrake(player) == false)
{
player->kartstuff[k_spindash] = 0;
@ -6892,26 +6960,36 @@ static void K_KartSpindash(player_t *player)
if ((cmd->buttons & (BT_DRIFT|BT_BRAKE)) == (BT_DRIFT|BT_BRAKE))
{
INT16 chargetime = MAXCHARGETIME - ++player->kartstuff[k_spindash];
boolean spawnOldEffect = true;
if (chargetime <= (MAXCHARGETIME / 2))
{
K_KartSpindashDust(player->mo);
spawnOldEffect = false;
}
if (chargetime <= (MAXCHARGETIME / 4) && spawnWind == true)
{
K_KartSpindashWind(player->mo);
}
if (chargetime > 0)
{
UINT16 soundcharge = 0;
UINT8 add = 0;
while ((soundcharge += ++add) < chargetime);
if (soundcharge == chargetime)
{
K_SpawnDashDustRelease(player);
if (spawnOldEffect == true)
K_SpawnDashDustRelease(player);
S_StartSound(player->mo, sfx_s3kab);
}
}
else if (chargetime < -TICRATE)
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_NORMAL);
else
{
if (player->kartstuff[k_spindash] % 4 == 0)
{
K_SpawnDashDustRelease(player);
K_FlameDashLeftoverSmoke(player->mo);
}
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_NORMAL);
}
}
}

View file

@ -79,7 +79,7 @@ void K_StripItems(player_t *player);
void K_StripOther(player_t *player);
void K_MomentumToFacing(player_t *player);
boolean K_ApplyOffroad(player_t *player);
tic_t K_GetSpindashChargeTime(player_t *player);
INT16 K_GetSpindashChargeTime(player_t *player);
fixed_t K_GetSpindashChargeSpeed(player_t *player);
fixed_t K_GetKartSpeedFromStat(UINT8 kartspeed);
fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower);

View file

@ -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;
}

View file

@ -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}
};

View file

@ -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)

View file

@ -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

View file

@ -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)
{

View file

@ -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);

View file

@ -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)

View file

@ -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,30 +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))
#define SHORT(x) ((INT16)(x))
#define LONG(x) ((INT32)(x))
#define MSBF_SHORT SWAP_SHORT
#define MSBF_LONG SWAP_LONG
#endif
// Big to little endian

View file

@ -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

View file

@ -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);

View file

@ -5623,6 +5623,9 @@ static void P_MobjSceneryThink(mobj_t *mobj)
if (mobj->tics > 0)
mobj->drawflags ^= MFD_DONTDRAW;
break;
case MT_SPINDASHWIND:
mobj->drawflags ^= MFD_DONTDRAW;
break;
case MT_VWREF:
case MT_VWREB:
{
@ -11597,8 +11600,11 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
static void P_SetAmbush(mobj_t *mobj)
{
if (mobj->type == MT_YELLOWDIAG || mobj->type == MT_REDDIAG || mobj->type == MT_BLUEDIAG)
mobj->angle += ANGLE_22h;
if (mobj->flags & MF_SPRING)
{
// gravity toggle
mobj->flags ^= MF_NOGRAVITY;
}
if (mobj->flags & MF_NIGHTSITEM)
{
@ -11627,9 +11633,6 @@ static void P_SetAmbush(mobj_t *mobj)
static void P_SetObjectSpecial(mobj_t *mobj)
{
if (mobj->type == MT_YELLOWDIAG || mobj->type == MT_REDDIAG || mobj->type == MT_BLUEDIAG)
mobj->flags |= MF_NOGRAVITY;
if ((mobj->flags & MF_MONITOR) && mobj->info->speed != 0)
{
// flag for strong/weak random boxes

View file

@ -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;

View file

@ -4308,6 +4308,7 @@ void P_PlayerThink(player_t *player)
if (player->playerstate == PST_DEAD)
{
LUAh_PlayerThink(player);
return;
}
}

View file

@ -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

View file

@ -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();
}
}

View file

@ -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
View 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
View 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*/