netcode seems functional

This commit is contained in:
Nishi 2026-01-29 19:42:00 +09:00
commit 0ee72e3446
Signed by: nishi
GPG key ID: 27EF69B208EB9343
10 changed files with 116 additions and 89 deletions

Binary file not shown.

Binary file not shown.

View file

@ -23,20 +23,20 @@ GSDECL void GSNetServerStep(GSNetServer net);
GSDECL void GSNetServerClose(GSNetServer net);
/* net_base.c */
GSDECL GSBool GSNetBaseHasData(int fd);
GSDECL int GSNetBaseServer(int port);
GSDECL int GSNetBaseClient(const char* hostname, int port, GSNetAddress* address);
GSDECL void GSNetBaseClose(int fd);
GSDECL int GSNetBaseRead(int fd, void* data, int size, GSNetAddress* address); /* always read 508 bytes! */
GSDECL void GSNetBaseWrite(int fd, void* data, int size, GSNetAddress* address);
GSDECL GSBool GSNetBaseHasData(GSNetSocket sock);
GSDECL GSNetSocket GSNetBaseServer(int port);
GSDECL GSNetSocket GSNetBaseClient(const char* hostname, int port, GSNetAddress* address);
GSDECL void GSNetBaseClose(GSNetSocket sock);
GSDECL int GSNetBaseRead(GSNetSocket sock, void* data, int size, GSNetAddress* address); /* always read 508 bytes! */
GSDECL void GSNetBaseWrite(GSNetSocket sock, void* data, int size, GSNetAddress* address);
/* net_packet.c */
GSDECL void GSNetPacketRead(int fd, GSNetPacket* packet, GSNetAddress* address);
GSDECL void GSNetPacketWrite(int fd, GSNetPacket* packet, GSNetAddress* address);
GSDECL void GSNetPacketRead(GSNetSocket sock, GSNetPacket* packet, GSNetAddress* address);
GSDECL void GSNetPacketWrite(GSNetSocket sock, GSNetPacket* packet, GSNetAddress* address);
/* net_state.c */
GSDECL void GSNetStateRead(GSNetState* state, int fd, GSNetPacket* packet, GSNetAddress* address);
GSDECL void GSNetStateWrite(GSNetState* state, int fd, GSNetAddress* address);
GSDECL void GSNetStateRead(GSNetState* state, GSNetSocket sock, GSNetPacket* packet, GSNetAddress* address);
GSDECL void GSNetStateWrite(GSNetState* state, GSNetSocket sock, GSNetAddress* address);
#ifdef __cplusplus
}

View file

@ -49,8 +49,8 @@ typedef struct _GSNetPacketHeader GSNetPacketHeader;
typedef struct _GSNetPacket GSNetPacket;
typedef struct _GSNetAddress GSNetAddress;
typedef struct _GSBinary GSBinary;
typedef struct _GSNetState GSNetState;
typedef struct _GSNetKV GSNetKV;
typedef struct _GSNetState GSNetState;
typedef struct _GSNetKV GSNetKV;
#ifdef _GEARSRC
typedef struct _GSClient* GSClient;
typedef struct _GSServer* GSServer;
@ -65,6 +65,7 @@ typedef struct _GSSoundEngine* GSSoundEngine;
typedef struct _GSSound* GSSound;
typedef struct _GSNetClient* GSNetClient;
typedef struct _GSNetServer* GSNetServer;
typedef struct _GSNetSocket* GSNetSocket;
typedef struct _GSModelFace GSModelFace;
typedef struct _GSModelMaterial GSModelMaterial;
@ -84,6 +85,7 @@ typedef void* GSSoundEngine;
typedef void* GSSound;
typedef void* GSNetClient;
typedef void* GSNetServer;
typedef void* GSNetSocket;
#endif
typedef float GSNumber;
typedef GSNumber GSVector2[2];
@ -147,10 +149,10 @@ struct _GSNetState {
unsigned int rxindex;
unsigned int rxtotal;
unsigned int txseq;
unsigned int txindex;
unsigned int txtotal;
unsigned int txstate;
unsigned int txseq;
unsigned int txindex;
unsigned int txtotal;
unsigned int txstate;
unsigned long txtick;
GSBinary* rx;
@ -161,7 +163,7 @@ struct _GSNetState {
struct _GSNetKV {
GSNetAddress key;
GSNetState value;
GSNetState value;
};
#ifdef _GEARSRC
@ -279,20 +281,25 @@ struct _GSSoundEngine {
struct _GSNetClient {
GSEngine engine;
int fd;
GSNetSocket sock;
GSNetAddress address;
GSNetState state;
GSNetState state;
};
struct _GSNetServer {
GSEngine engine;
int fd;
GSNetSocket sock;
GSNetKV* client;
};
struct _GSNetSocket {
int fd;
GSBool client;
};
struct _GSClient {
GSEngine engine;

View file

@ -24,7 +24,7 @@ static int new_socket(void) {
return fd;
}
GSBool GSNetBaseHasData(int fd) {
GSBool GSNetBaseHasData(GSNetSocket sock) {
fd_set fds;
struct timeval tv;
@ -33,21 +33,22 @@ GSBool GSNetBaseHasData(int fd) {
FD_ZERO(&fds);
FD_SET(fd, &fds);
FD_SET(sock->fd, &fds);
select(FD_SETSIZE, &fds, NULL, NULL, &tv);
if(FD_ISSET(fd, &fds)) return GSTrue;
if(FD_ISSET(sock->fd, &fds)) return GSTrue;
return GSFalse;
}
int GSNetBaseServer(int port) {
GSNetSocket GSNetBaseServer(int port) {
GSNetSocket sock;
int fd;
struct sockaddr_in addr;
int yes = 1;
if((fd = new_socket()) < 0) return -1;
if((fd = new_socket()) < 0) return NULL;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&yes, sizeof(yes));
@ -55,17 +56,22 @@ int GSNetBaseServer(int port) {
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(port);
sock = malloc(sizeof(*sock));
sock->fd = fd;
sock->client = 0;
if(bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
GSNetBaseClose(fd);
return -1;
GSNetBaseClose(sock);
return NULL;
}
return fd;
return sock;
}
int GSNetBaseClient(const char* hostname, int port, GSNetAddress* address) {
struct sockaddr_in addr;
GSNetSocket GSNetBaseClient(const char* hostname, int port, GSNetAddress* address) {
GSNetSocket sock;
int fd;
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(hostname);
@ -73,50 +79,64 @@ int GSNetBaseClient(const char* hostname, int port, GSNetAddress* address) {
if(addr.sin_addr.s_addr == 0xffffffff) {
struct hostent* host = gethostbyname(hostname);
if(host == NULL) return -1;
if(host == NULL) return NULL;
addr.sin_addr.s_addr = *(GSU32*)host->h_addr_list[0];
}
if(address != NULL){
if(address != NULL) {
address->address = addr.sin_addr.s_addr;
address->port = addr.sin_port;
}
if((fd = new_socket()) < 0) return -1;
if((fd = new_socket()) < 0) return NULL;
sock = malloc(sizeof(*sock));
sock->fd = fd;
sock->client = 1;
connect(fd, (struct sockaddr*)&addr, sizeof(addr));
return fd;
return sock;
}
void GSNetBaseClose(int fd) {
void GSNetBaseClose(GSNetSocket sock) {
#ifdef _WIN32
closesocket(fd);
closesocket(sock->fd);
#else
close(fd);
close(sock->fd);
#endif
free(sock);
}
int GSNetBaseRead(int fd, void* data, int size, GSNetAddress* address) {
struct sockaddr_in addr;
int len = sizeof(addr);
int n;
int GSNetBaseRead(GSNetSocket sock, void* data, int size, GSNetAddress* address) {
int n;
n = recvfrom(fd, data, size, 0, (struct sockaddr*)&addr, &len);
if(sock->client) {
n = recv(sock->fd, data, size, 0);
} else {
struct sockaddr_in addr;
int len = sizeof(addr);
address->address = addr.sin_addr.s_addr;
address->port = addr.sin_port;
n = recvfrom(sock->fd, data, size, 0, (struct sockaddr*)&addr, &len);
address->address = addr.sin_addr.s_addr;
address->port = addr.sin_port;
}
return n;
}
void GSNetBaseWrite(int fd, void* data, int size, GSNetAddress* address) {
struct sockaddr_in addr;
void GSNetBaseWrite(GSNetSocket sock, void* data, int size, GSNetAddress* address) {
if(sock->client) {
send(sock->fd, data, size, 0);
} else {
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = address->address;
addr.sin_port = address->port;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = address->address;
addr.sin_port = address->port;
sendto(fd, data, size, 0, (struct sockaddr*)&addr, sizeof(addr));
sendto(sock->fd, data, size, 0, (struct sockaddr*)&addr, sizeof(addr));
}
}

View file

@ -12,7 +12,7 @@ GSNetClient GSNetClientOpen(GSClient client, const char* hostname, int port) {
net->engine = client->engine;
if((net->fd = GSNetBaseClient(hostname, port, &net->address)) < 0) {
if((net->sock = GSNetBaseClient(hostname, port, &net->address)) < 0) {
GSLog(client->engine, GSLogError, "Failed to initialize socket");
GSNetClientClose(net);
@ -22,8 +22,8 @@ GSNetClient GSNetClientOpen(GSClient client, const char* hostname, int port) {
net->state.engine = net->engine;
GSBinary b;
b.data = strdup("Hello");
b.size = 5;
b.data = strdup("Hello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello world");
b.size = strlen(b.data);
arrput(net->state.tx, b);
return net;
@ -32,16 +32,16 @@ GSNetClient GSNetClientOpen(GSClient client, const char* hostname, int port) {
void GSNetClientStep(GSNetClient net) {
GSNetPacket pkt;
while(GSNetBaseHasData(net->fd)){
GSNetPacketRead(net->fd, &pkt, &net->address);
GSNetStateRead(&net->state, net->fd, &pkt, &net->address);
while(GSNetBaseHasData(net->sock)) {
GSNetPacketRead(net->sock, &pkt, &net->address);
GSNetStateRead(&net->state, net->sock, &pkt, &net->address);
}
GSNetStateWrite(&net->state, net->fd, &net->address);
GSNetStateWrite(&net->state, net->sock, &net->address);
}
void GSNetClientClose(GSNetClient net) {
if(net->fd >= 0) GSNetBaseClose(net->fd);
if(net->sock != NULL) GSNetBaseClose(net->sock);
free(net);
}

View file

@ -2,10 +2,10 @@
#include <GearSrc/Endian.h>
void GSNetPacketRead(int fd, GSNetPacket* packet, GSNetAddress* address) {
void GSNetPacketRead(GSNetSocket sock, GSNetPacket* packet, GSNetAddress* address) {
unsigned char buf[508];
packet->size = GSNetBaseRead(fd, buf, 508, address) - sizeof(packet->header);
packet->size = GSNetBaseRead(sock, buf, 508, address) - sizeof(packet->header);
memcpy(&packet->header, buf, sizeof(packet->header));
memcpy(packet->data, buf + sizeof(packet->header), packet->size);
@ -14,7 +14,7 @@ void GSNetPacketRead(int fd, GSNetPacket* packet, GSNetAddress* address) {
packet->header.seq = GSEndianSwapU32BE(packet->header.seq);
}
void GSNetPacketWrite(int fd, GSNetPacket* packet, GSNetAddress* address) {
void GSNetPacketWrite(GSNetSocket sock, GSNetPacket* packet, GSNetAddress* address) {
GSNetPacketHeader header = packet->header;
unsigned char buf[508];
@ -24,5 +24,5 @@ void GSNetPacketWrite(int fd, GSNetPacket* packet, GSNetAddress* address) {
memcpy(buf, &header, sizeof(header));
memcpy(buf + sizeof(header), packet->data, packet->size);
GSNetBaseWrite(fd, buf, sizeof(header) + packet->size, address);
GSNetBaseWrite(sock, buf, sizeof(header) + packet->size, address);
}

View file

@ -11,7 +11,7 @@ GSNetServer GSNetServerOpen(GSServer server, int port) {
net->engine = server->engine;
if((net->fd = GSNetBaseServer(port)) < 0) {
if((net->sock = GSNetBaseServer(port)) < 0) {
GSLog(server->engine, GSLogError, "Failed to initialize socket");
GSNetServerClose(net);
@ -22,32 +22,32 @@ GSNetServer GSNetServerOpen(GSServer server, int port) {
}
void GSNetServerStep(GSNetServer net) {
int i;
GSNetPacket pkt;
int i;
GSNetPacket pkt;
GSNetAddress addr;
while(GSNetBaseHasData(net->fd)){
while(GSNetBaseHasData(net->sock)) {
GSNetState v;
memset(&v, 0, sizeof(v));
v.engine = net->engine;
GSNetPacketRead(net->fd, &pkt, &addr);
GSNetPacketRead(net->sock, &pkt, &addr);
i = hmgeti(net->client, addr);
if(i != -1) v = net->client[i].value;
GSNetStateRead(&v, net->fd, &pkt, &addr);
GSNetStateRead(&v, net->sock, &pkt, &addr);
hmput(net->client, addr, v);
}
for(i = 0; i < hmlen(net->client); i++){
GSNetStateWrite(&net->client[i].value, net->fd, &net->client[i].key);
for(i = 0; i < hmlen(net->client); i++) {
GSNetStateWrite(&net->client[i].value, net->sock, &net->client[i].key);
}
}
void GSNetServerClose(GSNetServer net) {
if(net->fd >= 0) GSNetBaseClose(net->fd);
if(net->sock >= 0) GSNetBaseClose(net->sock);
free(net);
}

View file

@ -10,14 +10,14 @@ enum states {
WaitingAcknowledge
};
void GSNetStateRead(GSNetState* state, int fd, GSNetPacket* packet, GSNetAddress* address){
void GSNetStateRead(GSNetState* state, GSNetSocket sock, GSNetPacket* packet, GSNetAddress* address) {
if(packet->header.flag & GSNetPacketFlagAcknowledge) {
if(arrlen(state->tx) > 0 && state->txstate == WaitingAcknowledge && state->txindex == packet->header.index && state->txseq == packet->header.seq) {
GSLog(state->engine, GSLogDebug, "Received ACK packet %d:%d", state->txindex, state->txseq);
state->txstate = Acknowledged;
state->txseq++;
if(state->txseq == (state->txtotal + 1)){
if(state->txseq == (state->txtotal + 1)) {
state->txseq = 0;
state->txindex++;
@ -35,14 +35,14 @@ void GSNetStateRead(GSNetState* state, int fd, GSNetPacket* packet, GSNetAddress
pkt.header.seq = state->rxseq;
pkt.size = 0;
if(state->rxseq == 0){
if(state->rxseq == 0) {
state->rxtotal = GSEndianSwapU32BE(*(GSU32*)pkt.data);
}
GSNetPacketWrite(fd, &pkt, address);
GSNetPacketWrite(sock, &pkt, address);
state->rxseq++;
if(state->rxseq == (state->rxtotal + 1)){
if(state->rxseq == (state->rxtotal + 1)) {
state->rxseq = 0;
state->rxindex++;
}
@ -50,18 +50,18 @@ void GSNetStateRead(GSNetState* state, int fd, GSNetPacket* packet, GSNetAddress
}
}
void GSNetStateWrite(GSNetState* state, int fd, GSNetAddress* address){
if(arrlen(state->tx) > 0){
if(state->txstate == Acknowledged){
int n = state->tx[0].size;
void GSNetStateWrite(GSNetState* state, GSNetSocket sock, GSNetAddress* address) {
if(arrlen(state->tx) > 0) {
if(state->txstate == Acknowledged) {
int n = state->tx[0].size;
GSNetPacket pkt;
if(state->txseq == 0){
if(state->txseq == 0) {
GSU32 t;
state->txtotal = 0;
while(n > 0){
while(n > 0) {
n -= 508 - sizeof(pkt.header);
state->txtotal++;
}
@ -70,25 +70,25 @@ void GSNetStateWrite(GSNetState* state, int fd, GSNetAddress* address){
memcpy(pkt.data, &t, 4);
pkt.size = 4;
}else{
} else {
int m = 508 - sizeof(pkt.header);
int n = m * (state->txseq - 1);
pkt.size = (n > m) ? m : n;
memcpy(pkt.data, ((unsigned char*)state->tx[0].data) + n, pkt.size);
}
pkt.header.flag = 0;
pkt.header.flag = 0;
pkt.header.index = state->txindex;
pkt.header.seq = state->txseq;
pkt.header.seq = state->txseq;
GSNetPacketWrite(fd, &pkt, address);
GSNetPacketWrite(sock, &pkt, address);
state->txstate = WaitingAcknowledge;
if(state->engine->param->get_tick != NULL) state->txtick = state->engine->param->get_tick();
GSLog(state->engine, GSLogDebug, "Sent packet %d:%d", state->txindex, state->txseq);
}else if(state->engine->param->get_tick == NULL){
}else if((state->engine->param->get_tick() - state->txtick) >= 500){
} else if(state->engine->param->get_tick == NULL) {
} else if((state->engine->param->get_tick() - state->txtick) >= 500) {
GSLog(state->engine, GSLogDebug, "Lost packet %d:%d", state->txindex, state->txseq);
state->txstate = Acknowledged;

@ -1 +1 @@
Subproject commit 64c3cdb4a511b0b9efcd538a4c1bc82cbbda7dc8
Subproject commit bbb20f081ef347f074912091e0f641b8104fc69a