Extend network traversal to local addresses
This commit is contained in:
parent
e126db573a
commit
355df2ee44
22
src/luaapi.c
22
src/luaapi.c
@ -2224,9 +2224,9 @@ static int dagame_set_texture_reduction(lua_State *L) {
|
||||
}
|
||||
|
||||
int PeercodeHandler = LUA_NOREF;
|
||||
static void get_peercode_callback(void *ud, const char *peercode_bin) {
|
||||
char peercode[STOON_CONN_INFO_SIZE * 2 + 1] = {};
|
||||
for(int i = 0; i < STOON_CONN_INFO_SIZE; i++) {
|
||||
static void get_peercode_callback(void *ud, struct StoonPeercode *peercode_bin) {
|
||||
char peercode[sizeof(*peercode_bin) * 2 + 1] = {};
|
||||
for(int i = 0; i < sizeof(*peercode_bin); i++) {
|
||||
snprintf(peercode + i * 2, 3, "%02x", ((uint8_t*) peercode_bin)[i]);
|
||||
}
|
||||
|
||||
@ -2296,11 +2296,11 @@ static int get_peercode_bin(const char *peercode, char *peercode_bin) {
|
||||
if(!peercode) return 0;
|
||||
if(!peercode_bin) return 0;
|
||||
|
||||
if(strlen(peercode) < 2 * STOON_CONN_INFO_SIZE) {
|
||||
if(strlen(peercode) < 2 * sizeof(struct StoonPeercode)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(int i = 0; i < STOON_CONN_INFO_SIZE; i++) {
|
||||
for(int i = 0; i < sizeof(struct StoonPeercode); i++) {
|
||||
int b = 0;
|
||||
|
||||
if(peercode[i * 2 + 0] >= '0' && peercode[i * 2 + 0] <= '9') {
|
||||
@ -2328,8 +2328,8 @@ static int dagame_net_host(lua_State *L) {
|
||||
}
|
||||
|
||||
static int dagame_net_join(lua_State *L) {
|
||||
char peercode[STOON_CONN_INFO_SIZE];
|
||||
if(!get_peercode_bin(lua_tostring(L, 1), peercode)) {
|
||||
struct StoonPeercode peercode;
|
||||
if(!get_peercode_bin(lua_tostring(L, 1), &peercode)) {
|
||||
lua_pushliteral(L, "Invalid peercode");
|
||||
lua_error(L);
|
||||
return 0;
|
||||
@ -2337,20 +2337,20 @@ static int dagame_net_join(lua_State *L) {
|
||||
|
||||
net_hi_setup(false);
|
||||
|
||||
lua_pushboolean(L, net_hi_connect(peercode));
|
||||
lua_pushboolean(L, net_hi_connect(&peercode));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dagame_net_punch(lua_State *L) {
|
||||
char peercode[STOON_CONN_INFO_SIZE];
|
||||
if(!get_peercode_bin(lua_tostring(L, 1), peercode)) {
|
||||
struct StoonPeercode peercode;
|
||||
if(!get_peercode_bin(lua_tostring(L, 1), &peercode)) {
|
||||
lua_pushliteral(L, "Invalid peercode");
|
||||
lua_error(L);
|
||||
return 0;
|
||||
}
|
||||
|
||||
net_hi_add_punch(peercode);
|
||||
net_hi_add_punch(&peercode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -26,11 +26,7 @@ void net_client_init() {
|
||||
Game.isAuthority = 0;
|
||||
}
|
||||
|
||||
bool net_client_connect(const char *addr, uint16_t port) {
|
||||
ENetAddress eaddr;
|
||||
enet_address_set_host(&eaddr, addr);
|
||||
eaddr.port = port;
|
||||
|
||||
bool net_client_connect(ENetAddress eaddr) {
|
||||
peer = enet_host_connect(host, &eaddr, 1, 0);
|
||||
|
||||
ENetEvent ev;
|
||||
|
@ -1,7 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include"enet.h"
|
||||
|
||||
void net_client_init();
|
||||
bool net_client_connect(const char *addr, uint16_t port);
|
||||
bool net_client_connect(ENetAddress addr);
|
||||
void net_client_receive();
|
||||
void net_client_update();
|
||||
void net_client_dejitter();
|
||||
|
152
src/net_hi.c
152
src/net_hi.c
@ -7,9 +7,15 @@
|
||||
#include"net_server.h"
|
||||
#include"net_client.h"
|
||||
#include<math.h>
|
||||
#include"k3.h"
|
||||
|
||||
/*
|
||||
* Handles networking on a higher-level, combining hole punching with
|
||||
* basic client & server interface
|
||||
* */
|
||||
|
||||
static void *ReqPeercodeUD;
|
||||
static void(*ReqPeercodeCB)(void*, const char *peercode);
|
||||
static void(*ReqPeercodeCB)(void*, struct StoonPeercode *peercode);
|
||||
|
||||
static struct Stoon stoon;
|
||||
|
||||
@ -17,11 +23,11 @@ static bool inited = false;
|
||||
static bool isHost;
|
||||
|
||||
typedef struct {
|
||||
#define MASK_IPv4 1
|
||||
#define MASK_IPv6 2
|
||||
int mask;
|
||||
ENetAddress v4;
|
||||
ENetAddress v6;
|
||||
ENetAddress pv4;
|
||||
ENetAddress pv6;
|
||||
|
||||
ENetAddress lv4;
|
||||
ENetAddress lv6;
|
||||
} ToPunch;
|
||||
static ToPunch *topunch = NULL;
|
||||
static size_t topunchCount = 0;
|
||||
@ -30,13 +36,22 @@ static double Timeout = 0;
|
||||
|
||||
static bool connected = false;
|
||||
|
||||
bool net_hi_request_peercode(void *ud, void(*callback)(void*, const char *peercode)) {
|
||||
static uint16_t servport = 0;
|
||||
|
||||
bool net_hi_request_peercode(void *ud, void(*callback)(void*, struct StoonPeercode *peercode)) {
|
||||
if(inited) return false;
|
||||
|
||||
ReqPeercodeUD = ud;
|
||||
ReqPeercodeCB = callback;
|
||||
|
||||
stoon = stoon_init("stun.easybell.de", 3478, 26656);
|
||||
for(size_t port = 25000; port <= 26656; port++) {
|
||||
stoon = stoon_init("stun.easybell.de", 3478, port);
|
||||
|
||||
if(stoon.fd4 >= 0 || stoon.fd6 >= 0) {
|
||||
servport = port;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Timeout = 0;
|
||||
|
||||
@ -52,7 +67,7 @@ bool net_hi_setup(bool host) {
|
||||
isHost = host;
|
||||
|
||||
if(host) {
|
||||
net_server_init();
|
||||
net_server_init(servport);
|
||||
} else {
|
||||
net_client_init();
|
||||
}
|
||||
@ -67,16 +82,17 @@ void net_hi_update(double now) {
|
||||
|
||||
if(stoon_req(&stoon)) {
|
||||
if(stoon_listen(&stoon)) {
|
||||
uint8_t peercode[STOON_CONN_INFO_SIZE] = {};
|
||||
stoon_serialize(&stoon, peercode);
|
||||
|
||||
ReqPeercodeCB(ReqPeercodeUD, peercode);
|
||||
ReqPeercodeCB(ReqPeercodeUD, &stoon.peercode);
|
||||
|
||||
ReqPeercodeCB = NULL;
|
||||
} else {
|
||||
k3Log(k3_INFO, "stoon_listen failure");
|
||||
|
||||
Timeout = now + 1;
|
||||
}
|
||||
} else {
|
||||
k3Log(k3_INFO, "stoon_req failure");
|
||||
|
||||
Timeout = now + 1;
|
||||
}
|
||||
|
||||
@ -97,11 +113,11 @@ void net_hi_update(double now) {
|
||||
for(size_t tpi = 0; tpi < topunchCount; tpi++) {
|
||||
ToPunch *tp = &topunch[tpi];
|
||||
|
||||
if(tp->mask & MASK_IPv4) {
|
||||
enet_socket_send(h->socket, &tp->v4, &buf, 1);
|
||||
} else if(tp->mask & MASK_IPv6) {
|
||||
enet_socket_send(h->socket, &tp->v6, &buf, 1);
|
||||
}
|
||||
if(tp->lv6.port) enet_socket_send(h->socket, &tp->lv6, &buf, 1);
|
||||
if(tp->lv4.port) enet_socket_send(h->socket, &tp->lv4, &buf, 1);
|
||||
|
||||
if(tp->pv6.port) enet_socket_send(h->socket, &tp->pv6, &buf, 1);
|
||||
if(tp->pv4.port) enet_socket_send(h->socket, &tp->pv4, &buf, 1);
|
||||
}
|
||||
|
||||
}
|
||||
@ -111,57 +127,85 @@ void net_hi_update(double now) {
|
||||
}
|
||||
}
|
||||
|
||||
static void stoonpeer_to_enets(const char *peercode, ENetAddress *v4, ENetAddress *v6, int *mask) {
|
||||
uint8_t *addr8 = (uint8_t*) &v4->host;
|
||||
static bool stoonpeer_to_enet4(uint8_t *publicV4, uint8_t *publicP4, ENetAddress *enet) {
|
||||
memset(enet, 0, sizeof(*enet));
|
||||
|
||||
if(*(uint32_t*) publicV4 == 0 || *(uint16_t*) publicP4 == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t *addr8 = (uint8_t*) &enet->host;
|
||||
|
||||
memset(addr8, 0, 16);
|
||||
addr8[10] = 0xFF;
|
||||
addr8[11] = 0xFF;
|
||||
addr8[12] = peercode[0];
|
||||
addr8[13] = peercode[1];
|
||||
addr8[14] = peercode[2];
|
||||
addr8[15] = peercode[3];
|
||||
v4->port = ntohs(*(uint16_t*) &peercode[4]);
|
||||
addr8[12] = publicV4[0];
|
||||
addr8[13] = publicV4[1];
|
||||
addr8[14] = publicV4[2];
|
||||
addr8[15] = publicV4[3];
|
||||
enet->port = *(uint16_t*) publicP4;
|
||||
|
||||
memcpy(&v6->host, peercode + 6, 16);
|
||||
v6->port = ntohs(*(uint16_t*) &peercode[22]);
|
||||
|
||||
*mask = 0;
|
||||
if(v4->port) {
|
||||
*mask |= MASK_IPv4;
|
||||
}
|
||||
if(v6->port) {
|
||||
*mask |= MASK_IPv6;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void net_hi_add_punch(const char *peercode) {
|
||||
int mask;
|
||||
ENetAddress v4 = {}, v6 = {};
|
||||
stoonpeer_to_enets(peercode, &v4, &v6, &mask);
|
||||
static bool stoonpeer_to_enet6(uint8_t *publicV6, uint8_t *publicP6, ENetAddress *enet) {
|
||||
memset(enet, 0, sizeof(*enet));
|
||||
|
||||
if(*(uint32_t*) publicV6 == 0 || *(uint16_t*) publicP6 == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t *addr8 = (uint8_t*) &enet->host;
|
||||
|
||||
memcpy(addr8, publicV6, 16);
|
||||
enet->port = *(uint16_t*) publicP6;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void net_hi_add_punch(struct StoonPeercode *peercode) {
|
||||
topunch = realloc(topunch, sizeof(*topunch) * (++topunchCount));
|
||||
topunch[topunchCount - 1] = (ToPunch) {
|
||||
.v4 = v4,
|
||||
.v6 = v6,
|
||||
.mask = mask,
|
||||
};
|
||||
ToPunch *tp = &topunch[topunchCount - 1];
|
||||
|
||||
stoonpeer_to_enet4(peercode->publicV4, peercode->publicP4, &tp->pv4);
|
||||
stoonpeer_to_enet6(peercode->publicV6, peercode->publicP6, &tp->pv6);
|
||||
|
||||
stoonpeer_to_enet4(peercode->localV4, peercode->localP4, &tp->lv4);
|
||||
stoonpeer_to_enet6(peercode->localV6, peercode->localP6, &tp->lv6);
|
||||
}
|
||||
|
||||
bool net_hi_connect(const char *peercode) {
|
||||
bool net_hi_connect(struct StoonPeercode *peercode) {
|
||||
if(!inited) return false;
|
||||
|
||||
if(connected) return false;
|
||||
|
||||
char ip[64];
|
||||
int port;
|
||||
if(*(uint16_t*) (peercode + 22) == 0) {
|
||||
inet_ntop(AF_INET, peercode, ip, sizeof(ip));
|
||||
port = ntohs(*(uint16_t*) (peercode + 4));
|
||||
} else {
|
||||
inet_ntop(AF_INET6, peercode + 6, ip, sizeof(ip));
|
||||
port = ntohs(*(uint16_t*) (peercode + 22));
|
||||
ENetAddress pv4, pv6;
|
||||
stoonpeer_to_enet4(peercode->publicV4, peercode->publicP4, &pv4);
|
||||
stoonpeer_to_enet6(peercode->publicV6, peercode->publicP6, &pv6);
|
||||
|
||||
ENetAddress lv4, lv6;
|
||||
stoonpeer_to_enet4(peercode->localV4, peercode->localP4, &lv4);
|
||||
stoonpeer_to_enet6(peercode->localV6, peercode->localP6, &lv6);
|
||||
|
||||
if(lv6.port && net_client_connect(lv6)) {
|
||||
k3Log(k3_INFO, "Found local IPv6");
|
||||
return true;
|
||||
}
|
||||
if(lv4.port && net_client_connect(lv4)) {
|
||||
k3Log(k3_INFO, "Found local IPv4");
|
||||
return true;
|
||||
}
|
||||
|
||||
return net_client_connect(ip, port);
|
||||
if(pv6.port && net_client_connect(pv6)) {
|
||||
k3Log(k3_INFO, "Found remote IPv6");
|
||||
return true;
|
||||
}
|
||||
if(pv4.port && net_client_connect(pv4)) {
|
||||
k3Log(k3_INFO, "Found remote IPv4");
|
||||
return true;
|
||||
}
|
||||
|
||||
k3Log(k3_INFO, "Failed to establish connection");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -2,10 +2,12 @@
|
||||
|
||||
#include<stdbool.h>
|
||||
|
||||
bool net_hi_request_peercode(void *ud, void(*callback)(void*, const char *peercode));
|
||||
struct StoonPeercode;
|
||||
|
||||
bool net_hi_request_peercode(void *ud, void(*callback)(void*, struct StoonPeercode *peercode));
|
||||
bool net_hi_setup(bool host);
|
||||
void net_hi_update(double now);
|
||||
|
||||
void net_hi_add_punch(const char *peercode);
|
||||
void net_hi_add_punch(struct StoonPeercode *peercode);
|
||||
|
||||
bool net_hi_connect(const char *peercode);
|
||||
bool net_hi_connect(struct StoonPeercode *peercode);
|
||||
|
@ -18,8 +18,8 @@ struct Conn {
|
||||
#define MAX_PLAYERS 64
|
||||
static struct Conn conns[MAX_PLAYERS];
|
||||
|
||||
void net_server_init() {
|
||||
host = enet_host_create(&(ENetAddress) {.host = ENET_HOST_ANY, .port = 26656}, 16, 1, 0, 0);
|
||||
void net_server_init(uint16_t port) {
|
||||
host = enet_host_create(&(ENetAddress) {.host = ENET_HOST_ANY, .port = port}, 16, 1, 0, 0);
|
||||
|
||||
Game.isMultiplayer = 1;
|
||||
Game.isAuthority = 1;
|
||||
|
@ -5,7 +5,7 @@
|
||||
struct _ENetPeer;
|
||||
struct bstr;
|
||||
|
||||
void net_server_init();
|
||||
void net_server_init(uint16_t port);
|
||||
void net_server_receive();
|
||||
void net_server_update();
|
||||
|
||||
|
127
src/stoon.c
127
src/stoon.c
@ -17,6 +17,7 @@
|
||||
#include<string.h>
|
||||
#include<stdio.h>
|
||||
#include<errno.h>
|
||||
#include<ifaddrs.h>
|
||||
|
||||
#define STUN_BINDING_REQUEST 0x0001
|
||||
#define STUN_BINDING_INDICATION 0x1100
|
||||
@ -43,7 +44,7 @@ struct StunMsg {
|
||||
uint8_t id[12];
|
||||
};
|
||||
|
||||
static int stoon_init_mini(struct addrinfo *serv, uint16_t myport) {
|
||||
static int stoon_init_mini(struct Stoon *this, struct addrinfo *serv, uint16_t myport) {
|
||||
#ifdef _WIN32
|
||||
errno = 0;
|
||||
int fd = socket(serv->ai_family, serv->ai_socktype, serv->ai_protocol);
|
||||
@ -59,16 +60,71 @@ static int stoon_init_mini(struct addrinfo *serv, uint16_t myport) {
|
||||
char p[6];
|
||||
sprintf(p, "%u", myport);
|
||||
|
||||
struct addrinfo *myaddr;
|
||||
if(getaddrinfo(NULL, p, &(struct addrinfo) {.ai_family = serv->ai_family, .ai_socktype = SOCK_DGRAM, .ai_protocol = IPPROTO_UDP, .ai_flags = AI_PASSIVE}, &myaddr)) {
|
||||
struct addrinfo *myaddrinfo;
|
||||
if(getaddrinfo(NULL, p, &(struct addrinfo) {.ai_family = serv->ai_family, .ai_socktype = SOCK_DGRAM, .ai_protocol = IPPROTO_UDP, .ai_flags = AI_PASSIVE}, &myaddrinfo)) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
if(bind(fd, myaddr->ai_addr, myaddr->ai_addrlen)) {
|
||||
if(bind(fd, myaddrinfo->ai_addr, myaddrinfo->ai_addrlen)) {
|
||||
close(fd);
|
||||
return -2;
|
||||
}
|
||||
freeaddrinfo(myaddr);
|
||||
|
||||
freeaddrinfo(myaddrinfo);
|
||||
|
||||
#ifdef _WIN32
|
||||
IP_ADAPTER_ADDRESSES *addrs = malloc(1024 * 64);
|
||||
if(GetAdaptersAddresses(serv->ai_family, GAA_FLAG_SKIP_MULTICAST, NULL, &addrs) == NO_ERROR) {
|
||||
for(IP_ADAPTER_ADDRESSES *ifa = addrs; ifa; ifa = ifa->Next) {
|
||||
if(serv->ai_family == AF_INET6) {
|
||||
uint8_t *addr = (void*) &((struct sockaddr_in6*) ifa->FirstUnicastAddress->Address.lpSockaddr)->sin6_addr;
|
||||
if(addr[0] == 0 && addr[1] == 0 && addr[2] == 0 && addr[3] == 0 && addr[4] == 0 && addr[5] == 0 && addr[6] == 0 && addr[7] == 0 && addr[8] == 0 && addr[9] == 0 && addr[10] == 0 && addr[11] == 0 && addr[12] == 0 && addr[13] == 0 && addr[14] == 0 && (addr[15] == 0 || addr[15] == 1)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(this->peercode.localV6, addr, 16);
|
||||
memcpy(this->peercode.localP6, &myport, 2);
|
||||
} else {
|
||||
uint8_t *addr = (void*) &((struct sockaddr_in*) ifa->FirstUnicastAddress->Address.lpSockaddr)->sin_addr;
|
||||
if(addr[0] == 0 && addr[1] == 0 && addr[2] == 0 && addr[3] == 0 || addr[0] == 127 && addr[1] == 0 && addr[2] == 0 && addr[3] == 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(this->peercode.localV4, addr, 4);
|
||||
memcpy(this->peercode.localP4, &myport, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(addrs);
|
||||
#else
|
||||
struct ifaddrs *ifaddr;
|
||||
if(getifaddrs(&ifaddr) >= 0) {
|
||||
for(struct ifaddrs *ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
|
||||
if(ifa->ifa_addr->sa_family == serv->ai_family) {
|
||||
if(serv->ai_family == AF_INET6) {
|
||||
uint8_t *addr = (void*) &((struct sockaddr_in6*) ifa->ifa_addr)->sin6_addr;
|
||||
if(addr[0] == 0 && addr[1] == 0 && addr[2] == 0 && addr[3] == 0 && addr[4] == 0 && addr[5] == 0 && addr[6] == 0 && addr[7] == 0 && addr[8] == 0 && addr[9] == 0 && addr[10] == 0 && addr[11] == 0 && addr[12] == 0 && addr[13] == 0 && addr[14] == 0 && (addr[15] == 0 || addr[15] == 1)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(this->peercode.localV6, addr, 16);
|
||||
memcpy(this->peercode.localP6, &myport, 2);
|
||||
} else {
|
||||
uint8_t *addr = (void*) &((struct sockaddr_in*) ifa->ifa_addr)->sin_addr;
|
||||
if(addr[0] == 0 && addr[1] == 0 && addr[2] == 0 && addr[3] == 0 || addr[0] == 127 && addr[1] == 0 && addr[2] == 0 && addr[3] == 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(this->peercode.localV4, addr, 4);
|
||||
memcpy(this->peercode.localP4, &myport, 2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
freeifaddrs(ifaddr);
|
||||
}
|
||||
#endif
|
||||
|
||||
return fd;
|
||||
}
|
||||
@ -92,18 +148,16 @@ struct Stoon stoon_init(const char *stunhost, uint16_t stunport, uint16_t myport
|
||||
}
|
||||
}
|
||||
|
||||
struct Stoon ret;
|
||||
struct Stoon ret = {};
|
||||
|
||||
memset(&ret.my4, 0, sizeof(ret.my4));
|
||||
if(v4) {
|
||||
memcpy(&ret.stu4, v4->ai_addr, v4->ai_addrlen);
|
||||
ret.fd4 = stoon_init_mini(v4, myport);
|
||||
ret.fd4 = stoon_init_mini(&ret, v4, myport);
|
||||
} else ret.fd4 = -1;
|
||||
|
||||
memset(&ret.my6, 0, sizeof(ret.my6));
|
||||
if(v6) {
|
||||
memcpy(&ret.stu6, v6->ai_addr, v6->ai_addrlen);
|
||||
ret.fd6 = stoon_init_mini(v6, myport);
|
||||
ret.fd6 = stoon_init_mini(&ret, v6, myport);
|
||||
} else ret.fd6 = -1;
|
||||
|
||||
ret.poonchstage = 0;
|
||||
@ -121,12 +175,21 @@ static int stoon_req_mini(struct Stoon *this, int *fd, struct sockaddr *serv, in
|
||||
if(errno == ENETUNREACH) {
|
||||
close(*fd);
|
||||
*fd = -1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
int stoon_req(struct Stoon *this) {
|
||||
if(this->fd4 >= 0) stoon_req_mini(this, &this->fd4, (struct sockaddr*) &this->stu4, sizeof(struct sockaddr_in));
|
||||
if(this->fd6 >= 0) stoon_req_mini(this, &this->fd6, (struct sockaddr*) &this->stu6, sizeof(struct sockaddr_in6));
|
||||
|
||||
if(this->fd4 < 0 && this->fd6 < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int stoon_listen_mini(struct Stoon *this, int fd, struct sockaddr *serv, int servlen) {
|
||||
@ -161,11 +224,10 @@ static int stoon_listen_mini(struct Stoon *this, int fd, struct sockaddr *serv,
|
||||
uint16_t netfam = ntohs(((uint16_t*) d)[2]);
|
||||
uint16_t publicPort = ntohs(((uint16_t*) d)[3]) ^ (STUN_MAGIC >> 16);
|
||||
if(netfam == STUN_NETFAM_IPV4) {
|
||||
uint32_t publicIp = ntohl(((uint32_t*) d)[2]) ^ STUN_MAGIC;
|
||||
uint32_t publicIp = htonl(ntohl(((uint32_t*) d)[2]) ^ STUN_MAGIC);
|
||||
|
||||
this->my4.sin_family = AF_INET;
|
||||
memcpy(&this->my4.sin_addr, &publicIp, 4);
|
||||
this->my4.sin_port = htons(publicPort);
|
||||
memcpy(this->peercode.publicV4, &publicIp, 4);
|
||||
memcpy(this->peercode.publicP4, &publicPort, 2);
|
||||
|
||||
return 1;
|
||||
} else if(netfam == STUN_NETFAM_IPV6) {
|
||||
@ -175,9 +237,8 @@ static int stoon_listen_mini(struct Stoon *this, int fd, struct sockaddr *serv,
|
||||
publicIp[2] = ((uint32_t*) d)[4] ^ ((uint32_t*) res.base.id)[1];
|
||||
publicIp[3] = ((uint32_t*) d)[5] ^ ((uint32_t*) res.base.id)[2];
|
||||
|
||||
this->my6.sin6_family = AF_INET6;
|
||||
memcpy(&this->my6.sin6_addr, &publicIp, 16);
|
||||
this->my6.sin6_port = htons(publicPort);
|
||||
memcpy(this->peercode.publicV6, &publicIp, 16);
|
||||
memcpy(this->peercode.publicP6, &publicPort, 2);
|
||||
|
||||
return 1;
|
||||
} else {
|
||||
@ -188,12 +249,12 @@ static int stoon_listen_mini(struct Stoon *this, int fd, struct sockaddr *serv,
|
||||
d += 4 + attribLen;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
int stoon_listen(struct Stoon *this) {
|
||||
if(this->fd4 >= 0) if(stoon_listen_mini(this, this->fd4, (struct sockaddr*) &this->stu4, sizeof(struct sockaddr_in)) < 0) return 0;
|
||||
if(this->fd6 >= 0) if(stoon_listen_mini(this, this->fd6, (struct sockaddr*) &this->stu6, sizeof(struct sockaddr_in6)) < 0) return 0;
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
void stoon_keepalive(struct Stoon *this) {
|
||||
@ -217,31 +278,7 @@ void stoon_kill(struct Stoon *this) {
|
||||
this->fd6 = -1;
|
||||
}
|
||||
|
||||
int stoon_v4_available(struct Stoon *this) {
|
||||
return this->fd4 >= 0;
|
||||
}
|
||||
|
||||
int stoon_v6_available(struct Stoon *this) {
|
||||
return this->fd6 >= 0;
|
||||
}
|
||||
|
||||
void stoon_serialize(struct Stoon *this, uint8_t ret[static STOON_CONN_INFO_SIZE]) {
|
||||
if(this->fd4 >= 0) {
|
||||
memcpy(ret + 0, &this->my4.sin_addr, 4);
|
||||
memcpy(ret + 4, &this->my4.sin_port, 2);
|
||||
} else {
|
||||
memset(ret, 0, 6);
|
||||
}
|
||||
|
||||
if(this->fd6 >= 0) {
|
||||
memcpy(ret + 6, &this->my6.sin6_addr, 16);
|
||||
memcpy(ret + 22, &this->my6.sin6_port, 2);
|
||||
} else {
|
||||
memset(ret + 6, 0, 18);
|
||||
}
|
||||
}
|
||||
|
||||
int stoon_poonch(struct Stoon *this, const uint8_t peerdata[static STOON_CONN_INFO_SIZE]) {
|
||||
/*int stoon_poonch(struct Stoon *this, const uint8_t peerdata[static STOON_CONN_INFO_SIZE]) {
|
||||
struct {
|
||||
uint32_t addr4;
|
||||
uint16_t port4;
|
||||
@ -303,7 +340,7 @@ int stoon_poonch(struct Stoon *this, const uint8_t peerdata[static STOON_CONN_IN
|
||||
}
|
||||
|
||||
return STOON_POONCH_NO_KNOCK;
|
||||
}
|
||||
}*/
|
||||
|
||||
#ifdef STOON_STANDALONE
|
||||
int main() {
|
||||
|
29
src/stoon.h
29
src/stoon.h
@ -6,6 +6,7 @@
|
||||
|
||||
#include<stddef.h>
|
||||
#include<stdint.h>
|
||||
#include<stdbool.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include<winsock2.h>
|
||||
@ -16,8 +17,6 @@
|
||||
|
||||
/* Standalone hole punching libary (IPv4 & IPv6 compatible) */
|
||||
|
||||
#define STOON_CONN_INFO_SIZE (4 + 2 + 16 + 2)
|
||||
|
||||
#define POONCH_MAGIC 0x504F4348
|
||||
#define POONCH_STAGE_KNOCKING 0
|
||||
#define POONCH_STAGE_ACK 1
|
||||
@ -26,16 +25,30 @@ struct Poonch {
|
||||
uint32_t stage;
|
||||
};
|
||||
|
||||
struct StoonPeercode {
|
||||
uint8_t publicV4[4];
|
||||
uint8_t publicP4[2];
|
||||
|
||||
uint8_t publicV6[16];
|
||||
uint8_t publicP6[2];
|
||||
|
||||
uint8_t localV4[4];
|
||||
uint8_t localP4[2];
|
||||
|
||||
uint8_t localV6[16];
|
||||
uint8_t localP6[2];
|
||||
};
|
||||
|
||||
struct Stoon {
|
||||
struct sockaddr_in stu4;
|
||||
struct sockaddr_in my4;
|
||||
int fd4;
|
||||
|
||||
struct sockaddr_in6 stu6;
|
||||
struct sockaddr_in6 my6;
|
||||
int fd6;
|
||||
|
||||
uint8_t poonchstage;
|
||||
|
||||
struct StoonPeercode peercode;
|
||||
};
|
||||
|
||||
// stunhost: Self-explanatory
|
||||
@ -53,12 +66,8 @@ void stoon_keepalive(struct Stoon*);
|
||||
|
||||
void stoon_kill(struct Stoon*);
|
||||
|
||||
int stoon_v4_available(struct Stoon*);
|
||||
int stoon_v6_available(struct Stoon*);
|
||||
|
||||
void stoon_serialize(struct Stoon*, uint8_t ret[static STOON_CONN_INFO_SIZE]);
|
||||
|
||||
#define STOON_POONCH_INCOMPATIBLE_NETFAMS (-1)
|
||||
/*#define STOON_POONCH_INCOMPATIBLE_NETFAMS (-1)
|
||||
#define STOON_POONCH_NO_KNOCK 0
|
||||
#define STOON_POONCH_ACKED 1
|
||||
int stoon_poonch(struct Stoon*, const uint8_t peerdata[static STOON_CONN_INFO_SIZE]);
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user