summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core.c31
-rw-r--r--src/core.h1
-rw-r--r--src/handler.c4
3 files changed, 27 insertions, 9 deletions
diff --git a/src/core.c b/src/core.c
index 6c7c542..b018207 100644
--- a/src/core.c
+++ b/src/core.c
@@ -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);
diff --git a/src/core.h b/src/core.h
index 4b35f82..76cffa2 100644
--- a/src/core.h
+++ b/src/core.h
@@ -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;
}