Start IPv6 - Lord help me

This commit is contained in:
2026-06-03 11:20:19 +02:00
parent 00bd711501
commit da50b4e8c1
5 changed files with 87 additions and 0 deletions

View File

@@ -14,6 +14,9 @@ Check if Block FullVerify is actually verifying fully (not missing any condition
A loophole in the reorg penalty system could potentially exist where someone broadcasts blocks one-at-a-time. Determine a solution to this.
IPv6 support for the P2P node. Come on guys, it's 2026. RFC 2460 was in 1998. It's about time.
Like if someone is behind NAT, fine, workable. CGNAT? Lmao good luck.
TO TEST:
Implement Horizen's "Reorg Penalty" system to make it harder for the young chain to be attacked by a powerful miner.

View File

@@ -19,8 +19,17 @@ typedef enum {
typedef struct tcp_connection_t tcp_connection_t;
struct tcp_connection_t {
// TODO: We should make it so only ONE of this needs to be available.
// Because of my temporary "I just need something that works" horseshit that I'm about to write, you'll need IPv4 and IPv6 is optional.
// Note to self: Don't pull an IETF and some "NAT exists, we're fine" bullshit, because if we end up with our eqvivalent of Teredo or CGNAT, I'm gonna be fucking pissed.
// And no, the solution isn't "eh, just bind to 0.0.0.0 and ignore it", because if we do that, we'll inevitably end up with a host that only has IPv6 and then we'll be fucked.
// Honestly, I'm proud of whoever runs IPv6-only. Brave soul.
int sockFd;
struct sockaddr_in peerAddr;
#ifdef USE_IPV6
int sockFd6; // For IPv6 support
struct sockaddr_in6 peerAddr6; // For IPv6 support
#endif
uint32_t connectionId;
tcp_connection_role_t role;
@@ -54,6 +63,7 @@ int TcpConnection_SetDataBuffer(tcp_connection_t* conn, const unsigned char* dat
void TcpConnection_ResetFramingState(tcp_connection_t* conn);
int TcpConnection_FeedFramedData(tcp_connection_t* conn, const unsigned char* input, size_t inputLen);
// This just takes a socket ID, so it's independent from the v4/v6 stuff. It works for both.
int TcpConnection_SendRaw(int sockFd, const void* data, size_t len);
int TcpConnection_SendFramed(tcp_connection_t* conn, const void* payload, size_t payloadLen);

View File

@@ -11,7 +11,12 @@
typedef struct {
int sockFd;
struct sockaddr_in addr;
#ifdef USE_IPV6
int sockFd6; // IPv6 support
struct sockaddr_in6 addr6; // IPv6 support
#endif
int opt;
int opt6; // IPv6 support
int isRunning;
void* owner;

View File

@@ -214,10 +214,26 @@ int TcpConnection_SendFramed(tcp_connection_t* conn, const void* payload, size_t
pthread_mutex_lock(&conn->sendLock);
#ifdef USE_IPV6
int sock;
if (conn->sockFd6 >= 0) {
// IPv6 is available, attempt to send on it. If it fails, we'll fall back to IPv4 if available.
sock = conn->sockFd6;
} else {
// IPv4 fallback
sock = conn->sockFd;
}
int rc = TcpConnection_SendRaw(sock, &beLen, sizeof(beLen));
if (rc == 0 && payloadLen > 0) {
rc = TcpConnection_SendRaw(sock, payload, payloadLen);
}
#else
int rc = TcpConnection_SendRaw(conn->sockFd, &beLen, sizeof(beLen));
if (rc == 0 && payloadLen > 0) {
rc = TcpConnection_SendRaw(conn->sockFd, payload, payloadLen);
}
#endif
pthread_mutex_unlock(&conn->sendLock);
@@ -235,6 +251,11 @@ void TcpConnection_RequestClose(tcp_connection_t* conn) {
if (conn->sockFd >= 0) {
shutdown(conn->sockFd, SHUT_RDWR);
}
#ifdef USE_IPV6
if (conn->sockFd6 >= 0) {
shutdown(conn->sockFd6, SHUT_RDWR);
}
#endif
}
pthread_mutex_unlock(&conn->stateLock);
}

View File

@@ -172,6 +172,9 @@ tcp_server_t* TcpServer_Create() {
svr->isRunning = 0;
svr->maxClients = 0;
svr->clientsArrPtr = NULL;
#ifdef USE_IPV6
svr->sockFd6 = -1;
#endif
if (pthread_mutex_init(&svr->clientsMutex, NULL) != 0) {
free(svr);
@@ -217,6 +220,28 @@ void TcpServer_Init(tcp_server_t* ptr, unsigned short port, const char* addr) {
close(ptr->sockFd);
ptr->sockFd = -1;
}
#ifdef USE_IPV6
// IPv6 support
ptr->sockFd6 = socket(AF_INET6, SOCK_STREAM, 0);
if (ptr->sockFd6 >= 0) {
ptr->opt6 = 1;
setsockopt(ptr->sockFd6, SOL_SOCKET, SO_REUSEADDR, &ptr->opt6, sizeof(int));
memset(&ptr->addr6, 0, sizeof(ptr->addr6));
ptr->addr6.sin6_family = AF_INET6;
ptr->addr6.sin6_port = htons(port);
inet_pton(AF_INET6, addr, &ptr->addr6.sin6_addr);
if (bind(ptr->sockFd6, (struct sockaddr*)&ptr->addr6, sizeof(ptr->addr6)) < 0) {
close(ptr->sockFd6);
ptr->sockFd6 = -1;
}
} else {
ptr->sockFd6 = -1; // IPv6 is optional, so if it isn't available, we just set it to -1
}
#else
// Safety for my future "I forgot the ifdef guard" self
ptr->sockFd6 = -1; // IPv6 not supported in this build
#endif
}
void TcpServer_Start(tcp_server_t* ptr, int maxcons) {
@@ -228,6 +253,15 @@ void TcpServer_Start(tcp_server_t* ptr, int maxcons) {
return;
}
#ifdef USE_IPV6
if (ptr->sockFd6 >= 0) {
if (listen(ptr->sockFd6, maxcons) < 0) {
close(ptr->sockFd6);
ptr->sockFd6 = -1;
}
}
#endif
pthread_mutex_lock(&ptr->clientsMutex);
ptr->maxClients = (size_t)maxcons;
@@ -268,6 +302,14 @@ void TcpServer_Stop(tcp_server_t* ptr) {
ptr->sockFd = -1;
}
#ifdef USE_IPV6
if (ptr->sockFd6 >= 0) {
shutdown(ptr->sockFd6, SHUT_RDWR);
close(ptr->sockFd6);
ptr->sockFd6 = -1;
}
#endif
if (ptr->svrThread != 0 && !pthread_equal(ptr->svrThread, pthread_self())) {
pthread_join(ptr->svrThread, NULL);
}
@@ -339,6 +381,12 @@ void TcpServer_KillClient(tcp_server_t* ptr, tcp_connection_t* cli) {
so_linger.l_linger = 0;
setsockopt(cli->sockFd, SOL_SOCKET, SO_LINGER, &so_linger, sizeof(so_linger));
#ifdef USE_IPV6
if (cli->sockFd6 >= 0) {
setsockopt(cli->sockFd6, SOL_SOCKET, SO_LINGER, &so_linger, sizeof(so_linger));
}
#endif
TcpServer_Disconnect(ptr, cli);
}