mirror of
https://github.com/Minecraft-Community-Edition/client.git
synced 2026-05-23 01:24:32 +00:00
130 lines
3.5 KiB
C++
130 lines
3.5 KiB
C++
#pragma once
|
|
#include "P2PConnectionManager.h"
|
|
|
|
// STUN message types (RFC 5389)
|
|
#define STUN_BINDING_REQUEST 0x0001
|
|
#define STUN_BINDING_RESPONSE 0x0101
|
|
#define STUN_BINDING_ERROR_RESPONSE 0x0111
|
|
|
|
// STUN attribute types
|
|
#define STUN_ATTR_MAPPED_ADDRESS 0x0001
|
|
#define STUN_ATTR_XOR_MAPPED_ADDRESS 0x0020
|
|
#define STUN_ATTR_SOFTWARE 0x8022
|
|
|
|
// STUN magic cookie (RFC 5389)
|
|
#define STUN_MAGIC_COOKIE 0x2112A442
|
|
|
|
// STUN header size
|
|
#define STUN_HEADER_SIZE 20
|
|
|
|
// Max STUN response size
|
|
#define STUN_MAX_RESPONSE_SIZE 512
|
|
|
|
// NAT traversal timeouts
|
|
#define NAT_STUN_TIMEOUT_MS 3000
|
|
#define NAT_PUNCH_INTERVAL_MS 500
|
|
#define NAT_PUNCH_MAX_ATTEMPTS 10
|
|
#define NAT_PUNCH_TIMEOUT_MS 5000
|
|
|
|
// P2P keepalive interval
|
|
#define P2P_KEEPALIVE_INTERVAL_MS 2000
|
|
|
|
// P2P connection timeout (no data received)
|
|
#define P2P_CONNECTION_TIMEOUT_MS 10000
|
|
|
|
// STUN server entry
|
|
struct STUNServer
|
|
{
|
|
const char* hostname;
|
|
unsigned short port;
|
|
};
|
|
|
|
// Well-known public STUN servers
|
|
static const STUNServer g_STUNServers[] =
|
|
{
|
|
{ "stun.l.google.com", 19302 },
|
|
{ "stun1.l.google.com", 19302 },
|
|
{ "stun.stunprotocol.org", 3478 },
|
|
};
|
|
static const int g_numSTUNServers = sizeof(g_STUNServers) / sizeof(g_STUNServers[0]);
|
|
|
|
// STUN transaction ID (96 bits)
|
|
struct STUNTransactionID
|
|
{
|
|
unsigned char id[12];
|
|
};
|
|
|
|
// STUN message header
|
|
#pragma pack(push, 1)
|
|
struct STUNHeader
|
|
{
|
|
unsigned short type;
|
|
unsigned short length;
|
|
unsigned int magicCookie;
|
|
STUNTransactionID transactionID;
|
|
};
|
|
#pragma pack(pop)
|
|
|
|
// NAT type classification
|
|
enum ENATType
|
|
{
|
|
NAT_TYPE_UNKNOWN = 0,
|
|
NAT_TYPE_OPEN, // No NAT / directly reachable
|
|
NAT_TYPE_FULL_CONE, // Easy to traverse
|
|
NAT_TYPE_RESTRICTED_CONE, // Moderate - needs hole punch
|
|
NAT_TYPE_PORT_RESTRICTED, // Harder - needs coordinated punch
|
|
NAT_TYPE_SYMMETRIC // Hardest - may need relay
|
|
};
|
|
|
|
// Abstract STUN client interface
|
|
class ISTUNClient
|
|
{
|
|
public:
|
|
virtual ~ISTUNClient() {}
|
|
|
|
virtual bool DiscoverEndpoint(PeerEndpoint& outEndpoint) = 0;
|
|
|
|
// Classify NAT type (optional, for diagnostics)
|
|
virtual ENATType ClassifyNAT() = 0;
|
|
|
|
// Get last error description
|
|
virtual const char* GetLastError() = 0;
|
|
};
|
|
|
|
// NAT hole punch helper
|
|
class NATHolePuncher
|
|
{
|
|
public:
|
|
// Generate a STUN binding request
|
|
static int BuildBindingRequest(unsigned char* buffer, int bufferSize, STUNTransactionID& outTxnID);
|
|
|
|
// Parse a STUN binding response to extract mapped address
|
|
static bool ParseBindingResponse(const unsigned char* data, int dataSize,
|
|
const STUNTransactionID& expectedTxnID, PeerEndpoint& outEndpoint);
|
|
|
|
// Generate a hole punch probe packet
|
|
static int BuildPunchProbe(unsigned char* buffer, int bufferSize, PlayerUID senderUID);
|
|
|
|
// Check if received data is a punch probe and extract sender UID
|
|
static bool IsPunchProbe(const unsigned char* data, int dataSize, PlayerUID& outSenderUID);
|
|
|
|
// Generate a punch acknowledgment
|
|
static int BuildPunchAck(unsigned char* buffer, int bufferSize, PlayerUID senderUID);
|
|
|
|
// Check if received data is a punch acknowledgment
|
|
static bool IsPunchAck(const unsigned char* data, int dataSize, PlayerUID& outSenderUID);
|
|
|
|
// Generate a keepalive packet
|
|
static int BuildKeepalive(unsigned char* buffer, int bufferSize);
|
|
|
|
// Check if received data is a keepalive
|
|
static bool IsKeepalive(const unsigned char* data, int dataSize);
|
|
|
|
private:
|
|
// P2P protocol magic bytes to distinguish from game data
|
|
static const unsigned int P2P_MAGIC = 0x4D435032; // "MCP2"
|
|
static const unsigned char P2P_MSG_PROBE = 0x01;
|
|
static const unsigned char P2P_MSG_ACK = 0x02;
|
|
static const unsigned char P2P_MSG_KEEPALIVE = 0x03;
|
|
};
|