mirror of
https://github.com/p2r3/bareiron.git
synced 2025-10-01 23:25:09 +02:00
implement timeout on stalling connections
This commit is contained in:
@@ -50,6 +50,9 @@
|
||||
// only applies to player data. Block changes are written as soon as they
|
||||
// are made, but in much smaller portions.
|
||||
#define DISK_SYNC_INTERVAL 15000000
|
||||
// Time in microseconds to spend waiting for data transmission before
|
||||
// timing out. (default = 5s)
|
||||
#define NETWORK_TIMEOUT_TIME 5000000
|
||||
// If defined, scales the frequency at which player movement updates are
|
||||
// broadcast based on the amount of players, reducing overhead for higher
|
||||
// player counts. For very many players, makes movement look jittery.
|
||||
|
14
src/tools.c
14
src/tools.c
@@ -36,6 +36,10 @@ ssize_t recv_all (int client_fd, void *buf, size_t n, uint8_t require_first) {
|
||||
char *p = buf;
|
||||
size_t total = 0;
|
||||
|
||||
// Track time of last meaningful network update
|
||||
// Used to handle timeout when client is stalling
|
||||
int32_t last_update_time = get_program_time();
|
||||
|
||||
// If requested, exit early when first byte not immediately available
|
||||
if (require_first) {
|
||||
ssize_t r = recv(client_fd, p, 1, MSG_PEEK);
|
||||
@@ -52,6 +56,8 @@ ssize_t recv_all (int client_fd, void *buf, size_t n, uint8_t require_first) {
|
||||
ssize_t r = recv(client_fd, p + total, n - total, 0);
|
||||
if (r < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
// handle network timeout
|
||||
if (get_program_time() - last_update_time > NETWORK_TIMEOUT_TIME) return -1;
|
||||
task_yield();
|
||||
continue;
|
||||
} else {
|
||||
@@ -64,6 +70,7 @@ ssize_t recv_all (int client_fd, void *buf, size_t n, uint8_t require_first) {
|
||||
return total;
|
||||
}
|
||||
total += r;
|
||||
last_update_time = get_program_time();
|
||||
}
|
||||
|
||||
total_bytes_received += total;
|
||||
@@ -75,11 +82,16 @@ ssize_t send_all (int client_fd, const void *buf, ssize_t len) {
|
||||
const uint8_t *p = (const uint8_t *)buf;
|
||||
ssize_t sent = 0;
|
||||
|
||||
// Track time of last meaningful network update
|
||||
// Used to handle timeout when client is stalling
|
||||
int32_t last_update_time = get_program_time();
|
||||
|
||||
// Busy-wait (with task yielding) until all data has been sent
|
||||
while (sent < len) {
|
||||
ssize_t n = send(client_fd, p + sent, len - sent, MSG_NOSIGNAL);
|
||||
if (n > 0) { // some data was sent, log it
|
||||
sent += n;
|
||||
last_update_time = get_program_time();
|
||||
continue;
|
||||
}
|
||||
if (n == 0) { // connection was closed, treat this as an error
|
||||
@@ -88,6 +100,8 @@ ssize_t send_all (int client_fd, const void *buf, ssize_t len) {
|
||||
}
|
||||
// not yet ready to transmit, try again
|
||||
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
// handle network timeout
|
||||
if (get_program_time() - last_update_time > NETWORK_TIMEOUT_TIME) return -1;
|
||||
task_yield();
|
||||
continue;
|
||||
}
|
||||
|
Reference in New Issue
Block a user