k4/src/net_hi.c
mid 0ba2cdee1c
Some checks failed
k4 Build Test / do_the_build (push) Failing after 59s
Remove __in6_u usage
2025-05-11 15:26:25 +03:00

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