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.master
parent
b7b410ddc2
commit
d6dbb6c979
31
src/core.c
31
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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue