diff --git a/src/aws.c b/src/aws.c index 20317775691f41e502aaa41e46c4166d7c9dc27f..18d8fad8e2d2ae1ca2cb05e3891239b917a181d2 100644 --- a/src/aws.c +++ b/src/aws.c @@ -23,6 +23,10 @@ #include "utils/sock_util.h" #include "utils/w_epoll.h" +static const char HTTP_HEADER[] = "HTTP/1.0 200 OK\r\nContent-Length: %ld\r\nConnection: close\r\n\r\n"; + +static const char NOT_FOUND[] = "HTTP/1.0 404 Not Found\r\n\r\n"; + /* server socket file descriptor */ static int listenfd; @@ -60,20 +64,11 @@ int parse_header(struct connection *conn) http_parser_init(&conn->request_parser, HTTP_REQUEST); conn->request_parser.data = conn; - http_parser_execute(&conn->request_parser, &settings_on_path, conn->recv_buffer, strlen(conn->recv_buffer)); + http_parser_execute(&conn->request_parser, &settings_on_path, + conn->recv_buffer, strlen(conn->recv_buffer)); return 0; } -//static void connection_prepare_send_reply_header(struct connection *conn) -//{ -///* TODO: Prepare the connection buffer to send the reply header. */ -//} - -//static void connection_prepare_send_404(struct connection *conn) -//{ -///* TODO: Prepare the connection buffer to send the 404 header. */ -//} - static enum resource_type connection_get_resource_type(struct connection *conn) { conn->res_type = RESOURCE_TYPE_NONE; @@ -84,6 +79,22 @@ static enum resource_type connection_get_resource_type(struct connection *conn) return conn->res_type; } +static void connection_prepare_send_reply_header(struct connection *conn) +{ + connection_get_resource_type(conn); + conn->send_len = snprintf(conn->send_buffer, BUFSIZ, + HTTP_HEADER, conn->file_size); + dlog(LOG_INFO, "Set header with len %zu\n", conn->send_len); + conn->state = STATE_SENDING_HEADER; +} + +static void connection_prepare_send_404(struct connection *conn) +{ + conn->state = STATE_SENDING_404; + strcpy(conn->send_buffer, NOT_FOUND); + conn->send_len = strlen(NOT_FOUND); +} + int connection_open_file(struct connection *conn) { struct stat stat_buf; @@ -196,12 +207,9 @@ struct connection *connection_create(int sockfd) void connection_remove(struct connection *conn) { - dlog(LOG_INFO, "Client disconnected1\n"); DIE(w_epoll_remove_ptr(epollfd, conn->sockfd, conn) < 0, "Could not remove sockfd from epoll"); - dlog(LOG_INFO, "Client disconnected2\n"); DIE(tcp_close_connection(conn->sockfd) < 0, "Could not close connection"); - dlog(LOG_INFO, "Client disconnected3\n"); DIE(io_destroy(conn->ctx) != 0, "Could not destroy io ctx"); dlog(LOG_INFO, "Client disconnected\n"); conn->state = STATE_CONNECTION_CLOSED; @@ -233,32 +241,51 @@ void receive_data(struct connection *conn) enum connection_state connection_send_static(struct connection *conn) { - /* TODO: Send static data using sendfile(2). */ - return STATE_NO_STATE; -} + int rc; -int connection_send_data(struct connection *conn) -{ - /* May be used as a helper function. */ - /* TODO: Send as much data as possible from the connection send buffer. - * Returns the number of bytes sent or -1 if an error occurred - */ - return -1; + rc = sendfile(conn->sockfd, conn->fd, + &conn->file_pos, conn->file_size - conn->file_pos); + if (rc < 0) + if (errno != EAGAIN) + dlog(LOG_ERR, "sendfile failed"); + if (conn->file_pos == conn->file_size) { + DIE(close(conn->fd), "Cannot close fd\n"); + dlog(LOG_INFO, "Finished sendfile()\n"); + conn->state = STATE_DATA_SENT; + } + return conn->state; } int connection_send_dynamic(struct connection *conn) { - /* TODO: Read data asynchronously. - * Returns 0 on success and -1 on error. - */ + int rc; + + rc = send(conn->sockfd, conn->send_buffer + conn->send_pos, + conn->send_len - conn->send_pos, 0); + if (rc < 0) { + if (errno != EAGAIN && errno != EWOULDBLOCK) { + dlog(LOG_ERR, "send failed"); + return -1; + } + } else { + conn->send_pos += rc; + } + dlog(LOG_INFO, "Sending from send_buffer (with offset %zu): %zu bytes\n", + conn->send_pos, conn->send_len - conn->send_pos); + if (conn->send_pos == conn->send_len) { + conn->async_read_len += conn->send_len; + dlog(LOG_INFO, "Finished sending dynamic file segment\n"); + if (conn->async_read_len == conn->file_size) { + conn->state = STATE_DATA_SENT; + dlog(LOG_INFO, "Finished sending dynamic file fully\n"); + DIE(close(conn->fd), "Cannot close fd\n"); + } else { + connection_start_async_io(conn); + } + } return 0; } - -static const char HTTP_HEADER[] = "HTTP/1.0 200 OK\r\nContent-Length: %ld\r\nConnection: close\r\n\r\n"; - -static const char NOT_FOUND[] = "HTTP/1.0 404 Not Found\r\n\r\n"; - void handle_input(struct connection *conn) { switch (conn->state) { @@ -282,24 +309,17 @@ void handle_output(struct connection *conn) case STATE_REQUEST_RECEIVED: parse_header(conn); rc = connection_open_file(conn); - if (rc >= 0) { - connection_get_resource_type(conn); - conn->send_len = snprintf(conn->send_buffer, BUFSIZ, - HTTP_HEADER, conn->file_size); - dlog(LOG_INFO, "Set header with len %zu\n", conn->send_len); - conn->state = STATE_SENDING_HEADER; - } else { - conn->state = STATE_SENDING_404; - strcpy(conn->send_buffer, NOT_FOUND); - conn->send_len = strlen(NOT_FOUND); - } + if (rc >= 0) + connection_prepare_send_reply_header(conn); + else + connection_prepare_send_404(conn); break; case STATE_SENDING_HEADER: rc = send(conn->sockfd, conn->send_buffer + conn->send_pos, conn->send_len - conn->send_pos, 0); if (rc < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK) - DIE(rc < -1, "Could not send header"); + dlog(LOG_ERR, "Could not send header"); } else { conn->send_pos += rc; if (conn->send_pos == conn->send_len) { @@ -310,7 +330,8 @@ void handle_output(struct connection *conn) connection_start_async_io(conn); break; case RESOURCE_TYPE_STATIC: - dlog(LOG_INFO, "Finished sending header:\n%s", conn->send_buffer); + dlog(LOG_INFO, "Finished sending header:\n%s", + conn->send_buffer); conn->state = STATE_SENDING_DATA; break; default: @@ -328,39 +349,10 @@ void handle_output(struct connection *conn) case STATE_SENDING_DATA: switch (conn->res_type) { case RESOURCE_TYPE_DYNAMIC: - rc = send(conn->sockfd, conn->send_buffer + conn->send_pos, - conn->send_len - conn->send_pos, 0); - if (rc < 0) { - if (errno != EAGAIN && errno != EWOULDBLOCK) - DIE(rc < 0, "send failed"); - } else { - conn->send_pos += rc; - } - dlog(LOG_INFO, "Sending from send_buffer (with offset %zu): %zu bytes\n", - conn->send_pos, conn->send_len - conn->send_pos); - if (conn->send_pos == conn->send_len) { - conn->async_read_len += conn->send_len; - dlog(LOG_INFO, "Finished sending dynamic file segment\n"); - if (conn->async_read_len == conn->file_size) { - conn->state = STATE_DATA_SENT; - dlog(LOG_INFO, "Finished sending dynamic file fully\n"); - close(conn->fd); - } else { - connection_start_async_io(conn); - } - } + connection_send_dynamic(conn); break; case RESOURCE_TYPE_STATIC: - rc = sendfile(conn->sockfd, conn->fd, - &conn->file_pos, conn->file_size - conn->file_pos); - if (rc < 0) - if (errno != EAGAIN) - DIE(1, "sendfile failed"); - if (conn->file_pos == conn->file_size) { - DIE(close(conn->fd), "Cannot close fd\n"); - dlog(LOG_INFO, "Finished sendfile()\n"); - conn->state = STATE_DATA_SENT; - } + connection_send_static(conn); break; default: DIE(1, "Could not figure out resource type"); @@ -403,7 +395,8 @@ int main(void) rc = w_epoll_add_fd_in(epollfd, listenfd); DIE(rc < 0, "w_epoll_add_fd_in failed"); - dlog(LOG_INFO, "Server waiting for connections on port %d\n", AWS_LISTEN_PORT); + dlog(LOG_INFO, "Server waiting for connections on port %d\n", + AWS_LISTEN_PORT); /* server main loop */ while (1) {