try to get windows poll() shim working
This commit is contained in:
@@ -442,7 +442,25 @@ union Range1f32
|
|||||||
DWORD input_mode;
|
DWORD input_mode;
|
||||||
DWORD output_mode;
|
DWORD output_mode;
|
||||||
} TermIOs;
|
} TermIOs;
|
||||||
|
// <poll.h> networking shim for windows
|
||||||
|
# define POLLIN 0x0001
|
||||||
|
# define POLLPRI 0x0002
|
||||||
|
# define POLLOUT 0x0004
|
||||||
|
# define POLLERR 0x0008
|
||||||
|
# define POLLHUP 0x0010
|
||||||
|
# define POLLNVAL 0x0020
|
||||||
|
|
||||||
|
typedef struct pollfd {
|
||||||
|
SOCKET fd;
|
||||||
|
short events;
|
||||||
|
short revents;
|
||||||
|
} pollfd_t;
|
||||||
|
|
||||||
|
typedef int nfds_t;
|
||||||
|
|
||||||
|
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
|
||||||
#else
|
#else
|
||||||
|
# include <poll.h>
|
||||||
# include <sys/socket.h>
|
# include <sys/socket.h>
|
||||||
# include <netinet/in.h>
|
# include <netinet/in.h>
|
||||||
# include <netdb.h>
|
# include <netdb.h>
|
||||||
|
|||||||
+64
-1
@@ -326,5 +326,68 @@ bool osThreadJoin(Thread handle, u64 endt_us) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn void osBarrierWait(Barrier barrier) {
|
fn void osBarrierWait(Barrier barrier) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// poll() shim using select() on windows
|
||||||
|
int poll(struct pollfd *fds, nfds_t nfds, int timeout) {
|
||||||
|
assert(nfds <= FD_SETSIZE);
|
||||||
|
|
||||||
|
fd_set read_fds, write_fds, except_fds;
|
||||||
|
struct timeval tv;
|
||||||
|
int ret, i;
|
||||||
|
SOCKET max_fd = 0;
|
||||||
|
|
||||||
|
if (!fds && nfds > 0) {
|
||||||
|
WSASetLastError(WSAEFAULT);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FD_ZERO(&read_fds);
|
||||||
|
FD_ZERO(&write_fds);
|
||||||
|
FD_ZERO(&except_fds);
|
||||||
|
|
||||||
|
for (i = 0; i < nfds; i++) {
|
||||||
|
fds[i].revents = 0;
|
||||||
|
|
||||||
|
if (fds[i].fd == INVALID_SOCKET) {
|
||||||
|
fds[i].revents |= POLLNVAL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fds[i].fd > max_fd)
|
||||||
|
max_fd = fds[i].fd;
|
||||||
|
|
||||||
|
if (fds[i].events & POLLIN)
|
||||||
|
FD_SET(fds[i].fd, &read_fds);
|
||||||
|
if (fds[i].events & POLLOUT)
|
||||||
|
FD_SET(fds[i].fd, &write_fds);
|
||||||
|
/* always watch for errors */
|
||||||
|
FD_SET(fds[i].fd, &except_fds);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeout >= 0) {
|
||||||
|
tv.tv_sec = timeout / 1000;
|
||||||
|
tv.tv_usec = (timeout % 1000) * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = select((int)(max_fd + 1), &read_fds, &write_fds, &except_fds, &tv);
|
||||||
|
if (ret == SOCKET_ERROR)
|
||||||
|
return -1;
|
||||||
|
if (ret == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
for (i = 0; i < nfds; i++) {
|
||||||
|
if (fds[i].fd == INVALID_SOCKET)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (FD_ISSET(fds[i].fd, &read_fds)) fds[i].revents |= POLLIN;
|
||||||
|
if (FD_ISSET(fds[i].fd, &write_fds)) fds[i].revents |= POLLOUT;
|
||||||
|
if (FD_ISSET(fds[i].fd, &except_fds)) fds[i].revents |= POLLERR;
|
||||||
|
|
||||||
|
if (fds[i].revents) ret++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|||||||
@@ -451,6 +451,8 @@ fn void handleIncomingMessage(u8* message, i32 len) {
|
|||||||
fn void* receiveNetworkUpdates(void* net_client) {
|
fn void* receiveNetworkUpdates(void* net_client) {
|
||||||
TCPClient client = *(TCPClient*)net_client;
|
TCPClient client = *(TCPClient*)net_client;
|
||||||
dbg("receiveNetworkUpdates() sock=%d\n", client.socket);
|
dbg("receiveNetworkUpdates() sock=%d\n", client.socket);
|
||||||
|
// TODO: handle the server DCing with out a segfault here.
|
||||||
|
// should try to reconnect with some kind of backoff
|
||||||
infiniteReadTCPClient(client.socket, &should_quit, handleIncomingMessage, addSystemMessage);
|
infiniteReadTCPClient(client.socket, &should_quit, handleIncomingMessage, addSystemMessage);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-5
@@ -1,5 +1,4 @@
|
|||||||
#include "../base/all.h"
|
#include "../base/all.h"
|
||||||
#include <poll.h>
|
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/1098897/what-is-the-largest-safe-udp-packet-size-on-the-internet
|
// https://stackoverflow.com/questions/1098897/what-is-the-largest-safe-udp-packet-size-on-the-internet
|
||||||
#define UDP_MAX_MESSAGE_LEN 508
|
#define UDP_MAX_MESSAGE_LEN 508
|
||||||
@@ -284,6 +283,7 @@ i32 recvMessage(i32 socket, u8* message_buffer, void (*addSystemMessage)(u8* msg
|
|||||||
|
|
||||||
void infiniteReadTCPServer(
|
void infiniteReadTCPServer(
|
||||||
TCPServer* server,
|
TCPServer* server,
|
||||||
|
bool* should_quit,
|
||||||
void (*handleMessage)(u8* udp_message, u32 udp_len, SocketAddress sending_address, i32 socket),
|
void (*handleMessage)(u8* udp_message, u32 udp_len, SocketAddress sending_address, i32 socket),
|
||||||
void (*closeConnection)(i32 socket_fd),
|
void (*closeConnection)(i32 socket_fd),
|
||||||
void (*addSystemMessage)(u8* msg)
|
void (*addSystemMessage)(u8* msg)
|
||||||
@@ -300,12 +300,11 @@ void infiniteReadTCPServer(
|
|||||||
u32 pollable_fd_count = 1;
|
u32 pollable_fd_count = 1;
|
||||||
|
|
||||||
i32 poll_event_count;
|
i32 poll_event_count;
|
||||||
bool should_keep_serving = true;
|
while (*should_quit == false) {
|
||||||
while (should_keep_serving) {
|
poll_event_count = poll(pollable_fds, pollable_fd_count, 3000); // times out after 3 seconds so that quitting the server will actually quit the server process in relatively short order.
|
||||||
poll_event_count = poll(pollable_fds, pollable_fd_count, -1);
|
|
||||||
if (poll_event_count == -1) {
|
if (poll_event_count == -1) {
|
||||||
// TODO handle error better
|
// TODO handle error better
|
||||||
should_keep_serving = false;
|
*should_quit = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for(u32 i = 0; i < pollable_fd_count; i++) {
|
for(u32 i = 0; i < pollable_fd_count; i++) {
|
||||||
|
|||||||
+11
-16
@@ -80,6 +80,7 @@ typedef struct Account {
|
|||||||
|
|
||||||
typedef struct Client {
|
typedef struct Client {
|
||||||
bool active;
|
bool active;
|
||||||
|
bool needs_systems_init;
|
||||||
i32 socket_fd;
|
i32 socket_fd;
|
||||||
u64 account_id;
|
u64 account_id;
|
||||||
SocketAddress address;
|
SocketAddress address;
|
||||||
@@ -424,7 +425,7 @@ fn void sendMessageAuctionBidResult(i32 socket_fd, SocketAddress addr, AuctionBi
|
|||||||
|
|
||||||
fn void handleIncomingMessage(u8* message, u32 len, SocketAddress sender, i32 socket) {
|
fn void handleIncomingMessage(u8* message, u32 len, SocketAddress sender, i32 socket) {
|
||||||
char sbuf[SBUFLEN] = {0};
|
char sbuf[SBUFLEN] = {0};
|
||||||
sprintf(sbuf, "%d: %s from %s:%d\n", len, command_type_strings[message[0]], inet_ntoa(sender.sin_addr), sender.sin_port);
|
sprintf(sbuf, "%d: %s from %s:%d\n", len, COMMAND_TYPE_STRINGS[message[0]], inet_ntoa(sender.sin_addr), sender.sin_port);
|
||||||
addSystemMessage((u8*)sbuf);
|
addSystemMessage((u8*)sbuf);
|
||||||
u32 msg_idx = 0;
|
u32 msg_idx = 0;
|
||||||
ParsedClientCommand parsed = {
|
ParsedClientCommand parsed = {
|
||||||
@@ -474,7 +475,7 @@ fn void handleIncomingMessage(u8* message, u32 len, SocketAddress sender, i32 so
|
|||||||
msg_idx += temp_str.length;
|
msg_idx += temp_str.length;
|
||||||
|
|
||||||
MemoryZero(sbuf, SBUFLEN);
|
MemoryZero(sbuf, SBUFLEN);
|
||||||
sprintf(sbuf, "Logging in player: %s %d %s\n", command_type_strings[parsed.type], name_len, message + 7);
|
sprintf(sbuf, "Logging in player: %s %d %s\n", COMMAND_TYPE_STRINGS[parsed.type], name_len, message + 7);
|
||||||
addSystemMessage((u8*)sbuf);
|
addSystemMessage((u8*)sbuf);
|
||||||
} break;
|
} break;
|
||||||
case CommandPayMortgage: {
|
case CommandPayMortgage: {
|
||||||
@@ -530,7 +531,7 @@ fn void* receiveNetworkUpdates(void* tcp_server) {
|
|||||||
char sbuf[SBUFLEN] = {0};
|
char sbuf[SBUFLEN] = {0};
|
||||||
sprintf(sbuf, "receiveNetworkUpdates() sock=%d\n", server.socket_fd);
|
sprintf(sbuf, "receiveNetworkUpdates() sock=%d\n", server.socket_fd);
|
||||||
addSystemMessage((u8*)sbuf);
|
addSystemMessage((u8*)sbuf);
|
||||||
infiniteReadTCPServer(&server, handleIncomingMessage, removeClientBySocketFd, addSystemMessage);
|
infiniteReadTCPServer(&server, &should_quit, handleIncomingMessage, removeClientBySocketFd, addSystemMessage);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -566,9 +567,6 @@ fn void* sendNetworkUpdates(void* tcp_server) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkMessage base_sys_msg = makeMessageSystemCommodities(&state.map[send_loop/2 % STAR_SYSTEM_COUNT]);
|
|
||||||
NetworkMessage base_pass_msg = makeMessageSystemPassengers(&state.map[send_loop/2 % STAR_SYSTEM_COUNT]);
|
|
||||||
|
|
||||||
lockMutex(&state.client_mutex); {
|
lockMutex(&state.client_mutex); {
|
||||||
// WARNING the `i` starts at 1 here because state.clients.items[0] is a "null" Client
|
// WARNING the `i` starts at 1 here because state.clients.items[0] is a "null" Client
|
||||||
for (u32 i = 1; i < state.clients.length; i++) {
|
for (u32 i = 1; i < state.clients.length; i++) {
|
||||||
@@ -578,14 +576,6 @@ fn void* sendNetworkUpdates(void* tcp_server) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (send_loop % 2 == 0) {
|
if (send_loop % 2 == 0) {
|
||||||
// every other "send-frame" we send each connnected client the current prices for a different system
|
|
||||||
// so that the prices mostly stay up to date pretty quickly without having to track changes
|
|
||||||
base_sys_msg.socket_fd = client.socket_fd;
|
|
||||||
sendTCPMessage(base_sys_msg);
|
|
||||||
// and the passenger offers
|
|
||||||
base_pass_msg.socket_fd = client.socket_fd;
|
|
||||||
sendTCPMessage(base_pass_msg);
|
|
||||||
|
|
||||||
// send the client the current auction details for their current system
|
// send the client the current auction details for their current system
|
||||||
Account* account = &state.accounts[client.account_id];
|
Account* account = &state.accounts[client.account_id];
|
||||||
if (!accountIsEmpty(account)) {
|
if (!accountIsEmpty(account)) {
|
||||||
@@ -610,7 +600,7 @@ fn void* sendNetworkUpdates(void* tcp_server) {
|
|||||||
// update all the changed systems
|
// update all the changed systems
|
||||||
NetworkMessage msg_data;
|
NetworkMessage msg_data;
|
||||||
for (u32 ii = 0; ii < STAR_SYSTEM_COUNT; ii++) {
|
for (u32 ii = 0; ii < STAR_SYSTEM_COUNT; ii++) {
|
||||||
if (state.map[ii].changed == true) {
|
if (state.map[ii].changed == true || client.needs_systems_init) {
|
||||||
// send commodities
|
// send commodities
|
||||||
msg_data = makeMessageSystemCommodities(&state.map[ii]);
|
msg_data = makeMessageSystemCommodities(&state.map[ii]);
|
||||||
msg_data.address = client.address;
|
msg_data.address = client.address;
|
||||||
@@ -639,6 +629,8 @@ fn void* sendNetworkUpdates(void* tcp_server) {
|
|||||||
sendTCPMessage(msg_data);
|
sendTCPMessage(msg_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state.clients.items[i].needs_systems_init = false;
|
||||||
}
|
}
|
||||||
} unlockMutex(&state.client_mutex);
|
} unlockMutex(&state.client_mutex);
|
||||||
|
|
||||||
@@ -783,12 +775,13 @@ fn void* gameLoop(void* params) {
|
|||||||
if (client_handle == 0) break;
|
if (client_handle == 0) break;
|
||||||
Account* account = &state.accounts[client->account_id];
|
Account* account = &state.accounts[client->account_id];
|
||||||
account->destination_sys_idx = msg.byte;
|
account->destination_sys_idx = msg.byte;
|
||||||
|
account->changed = true;
|
||||||
} break;
|
} break;
|
||||||
case CommandReadyStatus: {
|
case CommandReadyStatus: {
|
||||||
if (client_handle == 0) break;
|
if (client_handle == 0) break;
|
||||||
Account* account = &state.accounts[client->account_id];
|
Account* account = &state.accounts[client->account_id];
|
||||||
account->ship.ready_to_depart = msg.byte;
|
account->ship.ready_to_depart = msg.byte;
|
||||||
sendMessagePlayerDetails(client->socket_fd, account->ship, sender);
|
account->changed = true;
|
||||||
state.all_accounts_ready = true;
|
state.all_accounts_ready = true;
|
||||||
for (u32 i = 0; i < ACCOUNT_LEN; i++) {
|
for (u32 i = 0; i < ACCOUNT_LEN; i++) {
|
||||||
if (!accountIsEmpty(&state.accounts[i])) {
|
if (!accountIsEmpty(&state.accounts[i])) {
|
||||||
@@ -852,6 +845,7 @@ fn void* gameLoop(void* params) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
sys->changed = true;
|
sys->changed = true;
|
||||||
|
account->changed = true;
|
||||||
sendMessagePlayerDetails(client->socket_fd, account->ship, sender);
|
sendMessagePlayerDetails(client->socket_fd, account->ship, sender);
|
||||||
sendMessageTransactionResult(client->socket_fd, sender, qty_traded, is_buying_from_system, credit_value);
|
sendMessageTransactionResult(client->socket_fd, sender, qty_traded, is_buying_from_system, credit_value);
|
||||||
} break;
|
} break;
|
||||||
@@ -933,6 +927,7 @@ fn void* gameLoop(void* params) {
|
|||||||
outgoingMessageQueuePush(state.network_send_queue, &outgoing_message);
|
outgoingMessageQueuePush(state.network_send_queue, &outgoing_message);
|
||||||
addSystemMessage((u8*)"MessageNewAccountCreated sent\n");
|
addSystemMessage((u8*)"MessageNewAccountCreated sent\n");
|
||||||
}
|
}
|
||||||
|
client->needs_systems_init = true;
|
||||||
MemoryZero(sbuf, SBUFLEN);
|
MemoryZero(sbuf, SBUFLEN);
|
||||||
sprintf(sbuf, "client_handle=%d, acct_id=%d\n", client_handle, existing_account->id);
|
sprintf(sbuf, "client_handle=%d, acct_id=%d\n", client_handle, existing_account->id);
|
||||||
addSystemMessage((u8*)sbuf);
|
addSystemMessage((u8*)sbuf);
|
||||||
|
|||||||
+2
-1
@@ -378,10 +378,11 @@ typedef enum CommandType {
|
|||||||
CommandType_Count,
|
CommandType_Count,
|
||||||
} CommandType;
|
} CommandType;
|
||||||
|
|
||||||
static const char* command_type_strings[CommandType_Count] = {
|
static const char* COMMAND_TYPE_STRINGS[CommandType_Count] = {
|
||||||
"Invalid",
|
"Invalid",
|
||||||
"Login",
|
"Login",
|
||||||
"CreateCharacter",
|
"CreateCharacter",
|
||||||
|
"Transact",
|
||||||
"ReadyStatus",
|
"ReadyStatus",
|
||||||
"SetDestination",
|
"SetDestination",
|
||||||
"PayMortgage",
|
"PayMortgage",
|
||||||
|
|||||||
Reference in New Issue
Block a user