168 lines
3.1 KiB
C
168 lines
3.1 KiB
C
#include"net_hi.h"
|
|
|
|
#include<stddef.h>
|
|
#include"enet.h"
|
|
#include<stdlib.h>
|
|
#include"stoon.h"
|
|
#include"net_server.h"
|
|
#include"net_client.h"
|
|
#include<math.h>
|
|
|
|
static void *ReqPeercodeUD;
|
|
static void(*ReqPeercodeCB)(void*, const char *peercode);
|
|
|
|
static struct Stoon stoon;
|
|
|
|
static bool inited = false;
|
|
static bool isHost;
|
|
|
|
typedef struct {
|
|
#define MASK_IPv4 1
|
|
#define MASK_IPv6 2
|
|
int mask;
|
|
ENetAddress v4;
|
|
ENetAddress v6;
|
|
} ToPunch;
|
|
static ToPunch *topunch = NULL;
|
|
static size_t topunchCount = 0;
|
|
|
|
static double Timeout = 0;
|
|
|
|
static bool connected = false;
|
|
|
|
bool net_hi_request_peercode(void *ud, void(*callback)(void*, const char *peercode)) {
|
|
if(inited) return false;
|
|
|
|
ReqPeercodeUD = ud;
|
|
ReqPeercodeCB = callback;
|
|
|
|
stoon = stoon_init("stun.easybell.de", 3478, 26656);
|
|
|
|
Timeout = 0;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool net_hi_setup(bool host) {
|
|
if(inited) return false;
|
|
|
|
stoon_kill(&stoon);
|
|
|
|
inited = true;
|
|
isHost = host;
|
|
|
|
if(host) {
|
|
net_server_init();
|
|
} else {
|
|
net_client_init();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void net_hi_update(double now) {
|
|
if(now <= Timeout) return;
|
|
|
|
if(ReqPeercodeCB) {
|
|
|
|
if(stoon_req(&stoon)) {
|
|
if(stoon_listen(&stoon)) {
|
|
uint8_t peercode[STOON_CONN_INFO_SIZE] = {};
|
|
stoon_serialize(&stoon, peercode);
|
|
|
|
ReqPeercodeCB(ReqPeercodeUD, peercode);
|
|
|
|
ReqPeercodeCB = NULL;
|
|
} else {
|
|
Timeout = now + 1;
|
|
}
|
|
} else {
|
|
Timeout = now + 1;
|
|
}
|
|
|
|
} else if(!inited) {
|
|
|
|
stoon_keepalive(&stoon);
|
|
|
|
Timeout = now + 1;
|
|
|
|
} else {
|
|
|
|
if(isHost) {
|
|
|
|
ENetHost *h = net_server_get_enethost();
|
|
|
|
ENetBuffer buf = {.data = "Punch!", .dataLength = 6};
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
Timeout = now + 1;
|
|
|
|
}
|
|
}
|
|
|
|
static void stoonpeer_to_enets(const char *peercode, ENetAddress *v4, ENetAddress *v6, int *mask) {
|
|
uint8_t *addr8 = (uint8_t*) &v4->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]);
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
void net_hi_add_punch(const char *peercode) {
|
|
int mask;
|
|
ENetAddress v4 = {}, v6 = {};
|
|
stoonpeer_to_enets(peercode, &v4, &v6, &mask);
|
|
|
|
topunch = realloc(topunch, sizeof(*topunch) * (++topunchCount));
|
|
topunch[topunchCount - 1] = (ToPunch) {
|
|
.v4 = v4,
|
|
.v6 = v6,
|
|
.mask = mask,
|
|
};
|
|
}
|
|
|
|
bool net_hi_connect(const char *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));
|
|
}
|
|
|
|
return net_client_connect(ip, port);
|
|
}
|