diff --git a/src/event_loop/event_loop.c b/src/event_loop/event_loop.c index 5887407..6dddf3c 100644 --- a/src/event_loop/event_loop.c +++ b/src/event_loop/event_loop.c @@ -14,20 +14,12 @@ #include "picohttpparser.h" static int event_loop_fd_set_nb(int fd) { - int flags = fcntl(fd, F_GETFL, 0); - - if (errno) { - return -1; - } + int flags = fcntl(fd, F_GETFL); flags |= O_NONBLOCK; fcntl(fd, F_SETFL, flags); - if (errno) { - return -1; - } - return 0; } @@ -98,8 +90,6 @@ int event_loop_accept(event_loop *loop, int fd) { return -4; } - /* printf("New connection with fd %i\n", connfd); */ - return 0; } @@ -175,23 +165,22 @@ void event_loop_run(event_loop *el, int port) { // poll for active fds // the timeout argument doesn't matter here int rv = poll(poll_args, (nfds_t)poll_args_count, 1000); - /* printf("poll"); */ - if (rv < 0) { return; } // process active connections - for (size_t i = 1; i < poll_args_count; ++i) { + for (size_t i = 1; i < poll_args_count; i++) { if (poll_args[i].revents) { conn = el->connections[poll_args[i].fd]; + event_loop_conn_io(conn); if (conn->state == event_loop_conn_state_end) { - /* printf("free %i\n", conn->fd); */ // client closed normally, or something bad happened. // destroy this connection el->connections[conn->fd] = NULL; + close(conn->fd); free(conn); } @@ -200,7 +189,7 @@ void event_loop_run(event_loop *el, int port) { // try to accept a new connection if the listening fd is active if (poll_args[0].revents) { - (void)event_loop_accept(el, fd); + event_loop_accept(el, fd); } } } diff --git a/src/event_loop/event_loop_conn.c b/src/event_loop/event_loop_conn.c index afc4f79..bdc5160 100644 --- a/src/event_loop/event_loop_conn.c +++ b/src/event_loop/event_loop_conn.c @@ -14,7 +14,7 @@ #include "event_loop_internal.h" -const char http_200_ok[] = "HTTP/1.1 200 OK\nConnection: close\nContent-Length: 5\n\nhello"; +const char http_200_ok[] = "HTTP/1.1 200 OK\nContent-Length: 5\n\nhello"; bool event_loop_conn_io_res(event_loop_conn *conn) { ssize_t res = 0; @@ -41,7 +41,8 @@ bool event_loop_conn_io_res(event_loop_conn *conn) { // After writing a response, we switch back to request mode to process a next // request if (conn->wbuf_sent == conn->wbuf_size) { - conn->state = conn->close_after_write ? event_loop_conn_state_end : event_loop_conn_state_req; + conn->state = conn->close_after_write ? event_loop_conn_state_end + : event_loop_conn_state_req; /* c->wbuf_sent = 0; */ /* c->wbuf_size = 0; */ @@ -53,6 +54,11 @@ bool event_loop_conn_io_res(event_loop_conn *conn) { } bool try_one_request(event_loop_conn *conn) { + // We definitely can't do anything with zero bytes. + if (conn->rbuf_size == 0) { + return false; + } + /* if (conn->process_func != NULL) { */ /* conn->process_func(conn); */ /* } */ @@ -69,18 +75,19 @@ bool try_one_request(event_loop_conn *conn) { &minor_version, headers, &num_headers, 0); if (res > 0) { + /* conn->close_after_write = true; */ // TODO allow HTTP pipelining - conn->close_after_write = true; - /* for (int i = 0; i < num_headers; i++) { */ - /* printf("%.*s: ", headers[i].name_len, headers[i].name); */ - /* printf("%.*s\n", headers[i].value_len, headers[i].value); */ - /* if (strncmp("Connection", headers[i].name, headers[i].name_len) == 0) { */ - /* if (strncmp("close", headers[i].value, headers[i].value_len) == 0) { */ - /* printf("close\n"); */ - /* break; */ - /* } */ - /* } */ - /* } */ + /* conn->close_after_write = true; */ + for (int i = 0; i < num_headers; i++) { + /* printf("%.*s: ", headers[i].name_len, headers[i].name); */ + /* printf("%.*s\n", headers[i].value_len, headers[i].value); */ + if (strncmp("Connection", headers[i].name, headers[i].name_len) == 0) { + if (strncmp("close", headers[i].value, headers[i].value_len) == 0) { + conn->close_after_write = true; + break; + } + } + } memcpy(conn->wbuf, http_200_ok, sizeof(http_200_ok) - 1); @@ -96,7 +103,8 @@ bool try_one_request(event_loop_conn *conn) { // End the connection if the http request is invalid, or when the response // is too large to fit into a single read buffer - } else if (res == -1 || (res == -2 && conn->rbuf_size == EVENT_LOOP_BUFFER_SIZE)) { + } else if (res == -1 || + (res == -2 && conn->rbuf_size == EVENT_LOOP_BUFFER_SIZE)) { conn->state = event_loop_conn_state_end; } @@ -135,6 +143,8 @@ bool event_loop_conn_io_req(event_loop_conn *conn) { // change the result. if (res == 0) { conn->state = event_loop_conn_state_end; + + return false; } // We switch to processing mode if we've reached the end of the data stream, @@ -151,7 +161,8 @@ bool event_loop_conn_io_req(event_loop_conn *conn) { // Try to process requests one by one. // Try to process requests one by one. // Why is there a loop? Please read the explanation of "pipelining". - while (try_one_request(conn)) {}; + while (try_one_request(conn)) { + }; // We can keep reading as long as we're in request mode return conn->state == event_loop_conn_state_req; @@ -167,7 +178,6 @@ void conn_state_res(event_loop_conn *conn) { void conn_state_req(event_loop_conn *conn) { while (event_loop_conn_io_req(conn)) { } - /* printf("done req"); */ } void event_loop_conn_io(event_loop_conn *conn) { diff --git a/src/event_loop/event_loop_internal.h b/src/event_loop/event_loop_internal.h index 2ee8af3..ef10191 100644 --- a/src/event_loop/event_loop_internal.h +++ b/src/event_loop/event_loop_internal.h @@ -1,9 +1,9 @@ #ifndef LANDER_EVENT_LOOP_INTERNAL #define LANDER_EVENT_LOOP_INTERNAL +#include #include #include -#include #include "event_loop.h"