diff options
author | tiptorrent development team <tiptorrent@soleta.eu> | 2021-09-10 17:06:35 +0200 |
---|---|---|
committer | tiptorrent development team <tiptorrent@soleta.eu> | 2021-09-29 15:48:11 +0200 |
commit | d6dbb6c979bc785e501cf109a7d155635b1647ea (patch) | |
tree | 2ccbde66d426ee9a32cad4c73f95d1726254b6ef /src | |
parent | b7b410ddc2b84c06801bc2b2320bbeaf7f3fa936 (diff) |
add a close wait state
Wait for clients to close the connection, then:
- create redirection.
- activate pending clients.
Do no refresh timeout while in close wait state.
Diffstat (limited to 'src')
-rw-r--r-- | src/core.c | 31 | ||||
-rw-r--r-- | src/core.h | 1 | ||||
-rw-r--r-- | src/handler.c | 4 |
3 files changed, 27 insertions, 9 deletions
@@ -107,6 +107,8 @@ static int tip_client_recv(struct tip_client *cli, int events) return ret; } +static int tip_client_redirect_create(const struct tip_client *cli); + static void tip_client_read_cb(struct ev_loop *loop, struct ev_io *io, int events) { struct tip_client *cli; @@ -115,10 +117,11 @@ static void tip_client_read_cb(struct ev_loop *loop, struct ev_io *io, int event cli = container_of(io, struct tip_client, io); ret = tip_client_recv(cli, events); - if (ret <= 0) + if (ret < 0) goto close; - ev_timer_again(loop, &cli->timer); + if (cli->state != TIP_CLIENT_CLOSE_WAIT) + ev_timer_again(loop, &cli->timer); cli->buf_len += ret; if (cli->buf_len >= sizeof(cli->buf)) { @@ -167,12 +170,24 @@ static void tip_client_read_cb(struct ev_loop *loop, struct ev_io *io, int event ev_io_set(&cli->io, tip_client_socket(cli), EV_READ | EV_WRITE); ev_io_start(loop, &cli->io); break; + case TIP_CLIENT_CLOSE_WAIT: + if (ret == 0) { + syslog(LOG_INFO, "client %s:%hu has closed the connection with us\n", + inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port)); + goto shutdown; + } + syslog(LOG_ERR, "unexpected data from client %s:%hu while waiting to close\n", + inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port)); + goto close; default: syslog(LOG_ERR, "unknown read state, critical internal error for %s:%hu\n", inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port)); goto close; } return; +shutdown: + if (cli->size > FILE_SIZE_THRESHOLD) + tip_client_redirect_create(cli); close: ev_timer_stop(loop, &cli->timer); tip_client_release(loop, cli); @@ -259,9 +274,12 @@ static void tip_client_write_cb(struct ev_loop *loop, struct ev_io *io, int even break; case TIP_CLIENT_PROCESSING_REQUEST_3: ret = tip_client_state_process_payload_bulk(cli); - if (ret > 0) - goto shutdown; - else if (ret < 0) { + if (ret > 0) { + /* entering TIP_CLIENT_CLOSE_WAIT state. */ + ev_io_stop(loop, &cli->io); + ev_io_set(&cli->io, tip_client_socket(cli), EV_READ); + ev_io_start(loop, &cli->io); + } else if (ret < 0) { syslog(LOG_ERR, "Failed to process HTTP request from %s:%hu\n", inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port)); @@ -274,9 +292,6 @@ static void tip_client_write_cb(struct ev_loop *loop, struct ev_io *io, int even goto close; } return; -shutdown: - if (cli->size > FILE_SIZE_THRESHOLD) - tip_client_redirect_create(cli); close: ev_timer_stop(loop, &cli->timer); tip_client_release(loop, cli); @@ -23,6 +23,7 @@ enum tip_client_state { TIP_CLIENT_PROCESSING_REQUEST, TIP_CLIENT_PROCESSING_REQUEST_2, TIP_CLIENT_PROCESSING_REQUEST_3, + TIP_CLIENT_CLOSE_WAIT, }; struct tip_client { diff --git a/src/handler.c b/src/handler.c index ab9fdc4..164a484 100644 --- a/src/handler.c +++ b/src/handler.c @@ -148,8 +148,10 @@ int tip_client_state_process_payload_bulk(struct tip_client *cli) { sendfile(tip_client_socket(cli), cli->fd, &cli->offset, BLOCK); - if (cli->offset >= cli->size) + if (cli->offset >= cli->size) { + cli->state = TIP_CLIENT_CLOSE_WAIT; return 1; + } return 0; } |