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
|
// only applies to player data. Block changes are written as soon as they
|
||||||
// are made, but in much smaller portions.
|
// are made, but in much smaller portions.
|
||||||
#define DISK_SYNC_INTERVAL 15000000
|
#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
|
// If defined, scales the frequency at which player movement updates are
|
||||||
// broadcast based on the amount of players, reducing overhead for higher
|
// broadcast based on the amount of players, reducing overhead for higher
|
||||||
// player counts. For very many players, makes movement look jittery.
|
// 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;
|
char *p = buf;
|
||||||
size_t total = 0;
|
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 requested, exit early when first byte not immediately available
|
||||||
if (require_first) {
|
if (require_first) {
|
||||||
ssize_t r = recv(client_fd, p, 1, MSG_PEEK);
|
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);
|
ssize_t r = recv(client_fd, p + total, n - total, 0);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||||
|
// handle network timeout
|
||||||
|
if (get_program_time() - last_update_time > NETWORK_TIMEOUT_TIME) return -1;
|
||||||
task_yield();
|
task_yield();
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
@@ -64,6 +70,7 @@ ssize_t recv_all (int client_fd, void *buf, size_t n, uint8_t require_first) {
|
|||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
total += r;
|
total += r;
|
||||||
|
last_update_time = get_program_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
total_bytes_received += total;
|
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;
|
const uint8_t *p = (const uint8_t *)buf;
|
||||||
ssize_t sent = 0;
|
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
|
// Busy-wait (with task yielding) until all data has been sent
|
||||||
while (sent < len) {
|
while (sent < len) {
|
||||||
ssize_t n = send(client_fd, p + sent, len - sent, MSG_NOSIGNAL);
|
ssize_t n = send(client_fd, p + sent, len - sent, MSG_NOSIGNAL);
|
||||||
if (n > 0) { // some data was sent, log it
|
if (n > 0) { // some data was sent, log it
|
||||||
sent += n;
|
sent += n;
|
||||||
|
last_update_time = get_program_time();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (n == 0) { // connection was closed, treat this as an error
|
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
|
// not yet ready to transmit, try again
|
||||||
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
|
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||||
|
// handle network timeout
|
||||||
|
if (get_program_time() - last_update_time > NETWORK_TIMEOUT_TIME) return -1;
|
||||||
task_yield();
|
task_yield();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user