mirror of
https://git.do.srb2.org/KartKrew/Kart-Public.git
synced 2025-01-12 21:01:00 +00:00
Use STUN instead of curl to fetch the public IP address for Discord
RFC 5389 is a standard protocol that can be used for this instead of ip4.me. I may have gone overboard on the CSPRNG... It was fun though.
This commit is contained in:
parent
e2749f8fdc
commit
b8bfe9b83a
8 changed files with 305 additions and 109 deletions
|
@ -440,8 +440,8 @@ endif
|
||||||
|
|
||||||
ifdef HAVE_DISCORDRPC
|
ifdef HAVE_DISCORDRPC
|
||||||
LIBS+=-ldiscord-rpc
|
LIBS+=-ldiscord-rpc
|
||||||
CFLAGS+=-DHAVE_DISCORDRPC
|
CFLAGS+=-DHAVE_DISCORDRPC -DUSE_STUN
|
||||||
OBJS+=$(OBJDIR)/discord.o
|
OBJS+=$(OBJDIR)/discord.o $(OBJDIR)/stun.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifndef NO_LUA
|
ifndef NO_LUA
|
||||||
|
|
|
@ -502,6 +502,7 @@ extern INT32 mapchangepending;
|
||||||
|
|
||||||
// Points inside doomcom
|
// Points inside doomcom
|
||||||
extern doomdata_t *netbuffer;
|
extern doomdata_t *netbuffer;
|
||||||
|
extern consvar_t cv_stunserver;
|
||||||
extern consvar_t cv_httpsource;
|
extern consvar_t cv_httpsource;
|
||||||
extern consvar_t cv_showjoinaddress;
|
extern consvar_t cv_showjoinaddress;
|
||||||
extern consvar_t cv_playbackspeed;
|
extern consvar_t cv_playbackspeed;
|
||||||
|
|
|
@ -714,6 +714,10 @@ void D_RegisterServerCommands(void)
|
||||||
|
|
||||||
CV_RegisterVar(&cv_dummyconsvar);
|
CV_RegisterVar(&cv_dummyconsvar);
|
||||||
|
|
||||||
|
#ifdef USE_STUN
|
||||||
|
CV_RegisterVar(&cv_stunserver);
|
||||||
|
#endif
|
||||||
|
|
||||||
CV_RegisterVar(&cv_discordinvites);
|
CV_RegisterVar(&cv_discordinvites);
|
||||||
RegisterNetXCmd(XD_DISCORD, Got_DiscordInfo);
|
RegisterNetXCmd(XD_DISCORD, Got_DiscordInfo);
|
||||||
}
|
}
|
||||||
|
|
138
src/discord.c
138
src/discord.c
|
@ -12,9 +12,7 @@
|
||||||
|
|
||||||
#ifdef HAVE_DISCORDRPC
|
#ifdef HAVE_DISCORDRPC
|
||||||
|
|
||||||
#ifdef HAVE_CURL
|
#include <time.h>
|
||||||
#include <curl/curl.h>
|
|
||||||
#endif // HAVE_CURL
|
|
||||||
|
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
#include "d_clisrv.h"
|
#include "d_clisrv.h"
|
||||||
|
@ -27,6 +25,8 @@
|
||||||
#include "mserv.h" // cv_advertise
|
#include "mserv.h" // cv_advertise
|
||||||
#include "z_zone.h"
|
#include "z_zone.h"
|
||||||
#include "byteptr.h"
|
#include "byteptr.h"
|
||||||
|
#include "stun.h"
|
||||||
|
#include "i_tcp.h" // current_port
|
||||||
|
|
||||||
#include "discord.h"
|
#include "discord.h"
|
||||||
#include "doomdef.h"
|
#include "doomdef.h"
|
||||||
|
@ -45,16 +45,7 @@ struct discordInfo_s discordInfo;
|
||||||
|
|
||||||
discordRequest_t *discordRequestList = NULL;
|
discordRequest_t *discordRequestList = NULL;
|
||||||
|
|
||||||
#ifdef HAVE_CURL
|
|
||||||
struct SelfIPbuffer
|
|
||||||
{
|
|
||||||
CURL *curl;
|
|
||||||
char *pointer;
|
|
||||||
size_t length;
|
|
||||||
};
|
|
||||||
|
|
||||||
static char self_ip[IP_SIZE];
|
static char self_ip[IP_SIZE];
|
||||||
#endif // HAVE_CURL
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
static char *DRPC_XORIPString(const char *input)
|
static char *DRPC_XORIPString(const char *input)
|
||||||
|
@ -335,39 +326,23 @@ void DRPC_Init(void)
|
||||||
DRPC_UpdatePresence();
|
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:-
|
Input Arguments:-
|
||||||
s - Data to write
|
address - IPv4 address of this machine, in network byte order.
|
||||||
size - Always 1.
|
|
||||||
n - Length of data
|
|
||||||
userdata - Passed in from CURLOPT_WRITEDATA, intended to be SelfIPbuffer
|
|
||||||
|
|
||||||
Return:-
|
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;
|
const unsigned char * p = (const unsigned char *)&address;
|
||||||
size_t newlength;
|
sprintf(self_ip, "%u.%u.%u.%u:%u", p[0], p[1], p[2], p[3], current_port);
|
||||||
|
DRPC_UpdatePresence();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
#endif // HAVE_CURL
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
static const char *DRPC_GetServerIP(void)
|
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!
|
// We're not the server, so we could successfully get the IP!
|
||||||
// No need to do anything else :)
|
// 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])
|
if (self_ip[0])
|
||||||
|
{
|
||||||
return self_ip;
|
return self_ip;
|
||||||
|
}
|
||||||
else
|
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
|
// Server info
|
||||||
if (netgame)
|
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)
|
if (DRPC_InvitesAreAllowed() == true)
|
||||||
{
|
{
|
||||||
const char *join;
|
const char *join;
|
||||||
|
@ -536,7 +455,24 @@ void DRPC_UpdatePresence(void)
|
||||||
|
|
||||||
joinSecretSet = true;
|
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
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -182,6 +182,7 @@ static UINT8 UPNP_support = TRUE;
|
||||||
#include "d_netfil.h"
|
#include "d_netfil.h"
|
||||||
#include "i_tcp.h"
|
#include "i_tcp.h"
|
||||||
#include "m_argv.h"
|
#include "m_argv.h"
|
||||||
|
#include "stun.h"
|
||||||
|
|
||||||
#include "doomstat.h"
|
#include "doomstat.h"
|
||||||
|
|
||||||
|
@ -612,6 +613,13 @@ static boolean SOCK_Get(void)
|
||||||
(void *)&fromaddress, &fromlen);
|
(void *)&fromaddress, &fromlen);
|
||||||
if (c != ERRSOCKET)
|
if (c != ERRSOCKET)
|
||||||
{
|
{
|
||||||
|
#ifdef USE_STUN
|
||||||
|
if (STUN_got_response(doomcom->data, c))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// find remote node number
|
// find remote node number
|
||||||
for (j = 1; j <= MAXNETNODES; j++) //include LAN
|
for (j = 1; j <= MAXNETNODES; j++) //include LAN
|
||||||
{
|
{
|
||||||
|
|
17
src/m_swap.h
17
src/m_swap.h
|
@ -16,16 +16,12 @@
|
||||||
|
|
||||||
#include "endian.h"
|
#include "endian.h"
|
||||||
|
|
||||||
// Endianess handling.
|
#define SWAP_SHORT(x) ((INT16)(\
|
||||||
// WAD files are stored little endian.
|
|
||||||
#ifdef SRB2_BIG_ENDIAN
|
|
||||||
|
|
||||||
#define SHORT(x) ((INT16)(\
|
|
||||||
(((UINT16)(x) & (UINT16)0x00ffU) << 8) \
|
(((UINT16)(x) & (UINT16)0x00ffU) << 8) \
|
||||||
| \
|
| \
|
||||||
(((UINT16)(x) & (UINT16)0xff00U) >> 8))) \
|
(((UINT16)(x) & (UINT16)0xff00U) >> 8))) \
|
||||||
|
|
||||||
#define LONG(x) ((INT32)(\
|
#define SWAP_LONG(x) ((INT32)(\
|
||||||
(((UINT32)(x) & (UINT32)0x000000ffUL) << 24) \
|
(((UINT32)(x) & (UINT32)0x000000ffUL) << 24) \
|
||||||
| \
|
| \
|
||||||
(((UINT32)(x) & (UINT32)0x0000ff00UL) << 8) \
|
(((UINT32)(x) & (UINT32)0x0000ff00UL) << 8) \
|
||||||
|
@ -34,9 +30,18 @@
|
||||||
| \
|
| \
|
||||||
(((UINT32)(x) & (UINT32)0xff000000UL) >> 24)))
|
(((UINT32)(x) & (UINT32)0xff000000UL) >> 24)))
|
||||||
|
|
||||||
|
// Endianess handling.
|
||||||
|
// WAD files are stored little endian.
|
||||||
|
#ifdef SRB2_BIG_ENDIAN
|
||||||
|
#define SHORT SWAP_SHORT
|
||||||
|
#define LONG SWAP_LONG
|
||||||
|
#define MSBF_SHORT(x) ((INT16)(x))
|
||||||
|
#define MSBF_LONG(x) ((INT32)(x))
|
||||||
#else
|
#else
|
||||||
#define SHORT(x) ((INT16)(x))
|
#define SHORT(x) ((INT16)(x))
|
||||||
#define LONG(x) ((INT32)(x))
|
#define LONG(x) ((INT32)(x))
|
||||||
|
#define MSBF_SHORT SWAP_SHORT
|
||||||
|
#define MSBF_LONG SWAP_LONG
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
222
src/stun.c
Normal file
222
src/stun.c
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
// 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)
|
||||||
|
//#include <ntsecapi.h>
|
||||||
|
#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 = {
|
||||||
|
"stunserver", "stun.l.google.com:19302", CV_SAVE, NULL,
|
||||||
|
NULL, 0, NULL, NULL, 0, 0, NULL/* C90 moment */
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
#if defined (__linux__)
|
||||||
|
getrandom(transaction_id, 12U, 0U);
|
||||||
|
#elif defined (_WIN32)
|
||||||
|
//RtlGenRandom(transaction_id, 12UL);
|
||||||
|
#elif defined (__APPLE__)
|
||||||
|
CCRandomGenerateBytes(stun_transcation_id, 12U);
|
||||||
|
#elif defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__)
|
||||||
|
arc4random_buf(transaction_id, 12U);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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…
Reference in a new issue