diff --git a/src/aws.c b/src/aws.c index adccd9b7bfa51eb3b039bd3e170c5d383427f445..44fa4201007a05987fb89ab8e41cb5439c36e5f4 100644 --- a/src/aws.c +++ b/src/aws.c @@ -56,7 +56,7 @@ struct connection *connection_create(int sockfd) { struct connection *conn; - conn = (struct connection*)malloc(sizeof(struct connection)); + conn = (struct connection *)malloc(sizeof(struct connection)); DIE(!conn, "malloc() failed\n"); conn->fd = -1; @@ -104,12 +104,12 @@ void connection_remove(struct connection *conn) close(conn->sockfd); free(conn); - dlog(LOG_INFO,"Server closed connection with: %s.\n", client_addr); + dlog(LOG_INFO, "Server closed connection with: %s.\n", client_addr); } /***** * Handle a new connection request on the server socket. -*****/ + *****/ void handle_new_connection(void) { struct sockaddr_in client_addr; @@ -120,7 +120,7 @@ void handle_new_connection(void) /* Accept new connection. */ clientfd = accept(listenfd, (struct sockaddr *) &client_addr, &size_addr); DIE(clientfd < 0, "accept() failed\n"); - dlog(LOG_INFO,"Server accepted connection from: %s:%d\n", + dlog(LOG_INFO, "Server accepted connection from: %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); /* Set socket to be non-blocking. */ @@ -144,7 +144,7 @@ void handle_new_connection(void) /***** * Receive message on socket. * Store message in recv_buffer in struct connection. -*****/ + *****/ int receive_data(struct connection *conn) { char client_addr[101], *buffer; @@ -161,7 +161,7 @@ int receive_data(struct connection *conn) connection_remove(conn); return -1; } - + conn->recv_len += recv_bytes; return 0; } @@ -173,11 +173,10 @@ int receive_data(struct connection *conn) *****/ void connection_set_resource_type(struct connection *conn) { - if (conn->request_path[2] == 's') { + if (conn->request_path[2] == 's') conn->res_type = RESOURCE_TYPE_STATIC; - } else if (conn->request_path[2] =='d') { + else if (conn->request_path[2] == 'd') conn->res_type = RESOURCE_TYPE_DYNAMIC; - } } /***** @@ -210,8 +209,10 @@ void parse_header(struct connection *conn) *****/ void connection_open_file(struct connection *conn) { + struct stat st; + conn->fd = open(conn->request_path, O_RDONLY); - + if (conn->fd < 0) { strcpy(conn->send_buffer, HTTP_404); conn->send_len = strlen(HTTP_404); @@ -219,7 +220,6 @@ void connection_open_file(struct connection *conn) strcpy(conn->send_buffer, HTTP_200); conn->send_len = strlen(HTTP_200); - struct stat st; stat(conn->request_path, &st); conn->file_size = st.st_size; conn->file_pos = 0; @@ -240,7 +240,7 @@ int connection_send_buffer(struct connection *conn) DIE(rc == -1, "get_peer_address() failed\n"); bytes_sent = send(conn->sockfd, conn->send_buffer, conn->send_len, 0); - + if (bytes_sent <= 0) { dlog(LOG_INFO, "Server can't comunicate with: %s.\n", client_addr); @@ -271,7 +271,7 @@ int connection_send_static(struct connection *conn) DIE(rc == -1, "get_peer_address() failed\n"); bytes_sent = sendfile(conn->sockfd, conn->fd, &conn->file_pos, conn->file_size); - + if (bytes_sent <= 0) { dlog(LOG_INFO, "Server can't comunicate with: %s.\n", client_addr); @@ -283,33 +283,39 @@ int connection_send_static(struct connection *conn) return 0; } -/***** +/***** * Starts asynchronous operation (read from file). * Uses io_submit(2) & friends for reading data asynchronously. -*****/ + *****/ void connection_start_async_io(struct connection *conn) { int rc; - conn->async_read_len = BUFSIZ < conn->file_size ? BUFSIZ : conn->file_size; + /* Prepare the io control block. */ + conn->async_read_len = 16 * BUFSIZ < conn->file_size ? 16 * BUFSIZ : conn->file_size; memset(&conn->iocb, 0, sizeof(conn->iocb)); io_prep_pread(&conn->iocb, conn->fd, conn->send_buffer, conn->async_read_len, conn->file_pos); + /* Associate the operation with a fd. */ conn->eventfd = eventfd(0, 0); + DIE(conn->eventfd == -1, "eventfd() failed\n"); io_set_eventfd(&conn->iocb, conn->eventfd); + /* We won't send something to client, until this operation is done. */ rc = w_epoll_remove_ptr(epollfd, conn->sockfd, conn); - DIE(rc == -1, "w_epoll_add_ptr_in() failed\n"); + DIE(rc == -1, "w_epoll_remove_ptr() failed\n"); + /* We need to know when the operation is done. */ rc = w_epoll_add_ptr_in(epollfd, conn->eventfd, conn); DIE(rc == -1, "w_epoll_add_ptr_in() failed\n"); + /* Setup the context. */ memset(&conn->ctx, 0, sizeof(io_context_t)); rc = io_setup(1, &conn->ctx); DIE(rc, "io_setup() failed\n"); + /* Start the operation. */ rc = io_submit(conn->ctx, 1, conn->piocb); - dlog(LOG_INFO, "%s %d\n", strerror(errno), rc); DIE(rc < 0, "io_submit() failed\n"); } @@ -326,8 +332,12 @@ void connection_complete_async_io(struct connection *conn) rc = w_epoll_add_ptr_out(epollfd, conn->sockfd, conn); DIE(rc == -1, "w_epoll_add_ptr_out() failed\n"); - /*Why i can not put this at begining?*/ - io_destroy(conn->ctx); + /* Why i can not put this at begining? */ + rc = io_destroy(conn->ctx); + DIE(rc, "io_destroy() failed\n"); + + rc = close(conn->eventfd); + DIE(rc, "close() failed\n"); conn->eventfd = -1; conn->send_len = conn->async_read_len; @@ -339,11 +349,11 @@ void connection_complete_async_io(struct connection *conn) /***** * Read data asynchronously and put it in connection send buffer, * which is further sent to client. -*****/ + *****/ int connection_send_dynamic(struct connection *conn) { char client_addr[101]; - int rc, bytes_sent; + int rc; rc = get_peer_address(conn->sockfd, client_addr, 100); DIE(rc == -1, "get_peer_address() failed\n"); @@ -353,17 +363,15 @@ int connection_send_dynamic(struct connection *conn) return 0; } - bytes_sent = connection_send_buffer(conn); - + connection_send_buffer(conn); return 0; } /***** * Send as much data as possible from the connection send buffer / connection file. -*****/ + *****/ int connection_send_data(struct connection *conn) { - char client_addr[101]; int rc; @@ -371,7 +379,7 @@ int connection_send_data(struct connection *conn) DIE(rc == -1, "get_peer_address() failed\n"); if (conn->state == STATE_SENDING_HEADER) { - connection_send_buffer(conn); + rc = connection_send_buffer(conn); if (!conn->send_len) { dlog(LOG_INFO, "Server sent reply header to: %s.\n", client_addr); @@ -386,9 +394,9 @@ int connection_send_data(struct connection *conn) if (conn->state == STATE_SENDING_DATA) { if (conn->res_type == RESOURCE_TYPE_STATIC) - connection_send_static(conn); + rc = connection_send_static(conn); else - connection_send_dynamic(conn); + rc = connection_send_dynamic(conn); if (!conn->send_len && !conn->file_size) { dlog(LOG_INFO, "Server sent a file to: %s.\n", client_addr); @@ -396,7 +404,7 @@ int connection_send_data(struct connection *conn) } } - return 0; + return rc; } @@ -405,12 +413,12 @@ int connection_send_data(struct connection *conn) * Receives data from him and sends data to him. *****/ void handle_client(uint32_t event, struct connection *conn) -{ +{ int rc; char *buffer_end; if (event & EPOLLIN) { - rc = receive_data(conn); + rc = receive_data(conn); if (rc == -1) return; @@ -426,13 +434,11 @@ void handle_client(uint32_t event, struct connection *conn) DIE(rc == -1, "w_epoll_update_ptr_out() failed\n"); conn->state = STATE_SENDING_HEADER; } - + if (event & EPOLLOUT) { rc = connection_send_data(conn); DIE(rc == -1, "connection_send_data() failed\n"); } - - dlog(LOG_INFO, "%d %d\n", (int)conn->send_len, (int)conn->file_size); } int main(void) @@ -459,7 +465,7 @@ int main(void) /* Wait for events. */ rc = epoll_wait(epollfd, &recv_ev, 1, -1); - DIE(rc <= 0, "epoll_wait() failed\n"); + DIE(rc <= 0, "epoll_wait() failed\n"); /* Switch event type: * - new connection requests (on server socket) @@ -467,19 +473,12 @@ int main(void) */ struct connection *conn = (struct connection *)recv_ev.data.ptr; - if (recv_ev.data.fd == listenfd) { - dlog(LOG_INFO, "New connection\n"); + if (recv_ev.data.fd == listenfd) handle_new_connection(); - } else if (conn->eventfd >= 0) { - dlog(LOG_INFO, "Finished io asynchronous\n"); - conn->state = STATE_SENDING_DATA; + else if (conn->eventfd >= 0) connection_complete_async_io(conn); - } else { - dlog(LOG_INFO, "Resolve request\n"); - dlog(LOG_INFO, "%d %d\n", BUFSIZ, (int)conn->async_read_len); - + else handle_client(recv_ev.events, conn); - } } close(listenfd); diff --git a/src/aws.h b/src/aws.h index 208d0efed09fd156ec676f62e53c768468b659e4..80639b764e097a371e200faf5d965b8f4e6d5a1c 100644 --- a/src/aws.h +++ b/src/aws.h @@ -63,7 +63,7 @@ struct connection { size_t recv_len; /* Used for sending data (headers, 404 or data populated through async IO). */ - char send_buffer[BUFSIZ]; + char send_buffer[16 * BUFSIZ]; size_t send_len; size_t send_pos; off_t file_pos; diff --git a/src/utils/debug.h b/src/utils/debug.h index 7f2101f3ccf545e7063a78690d23dd2617b59f7f..3c2d69acefc386cebb3d1ffe5e8a057561d9835d 100644 --- a/src/utils/debug.h +++ b/src/utils/debug.h @@ -41,8 +41,6 @@ enum { fprintf(stderr, " [%s(), %s:%u] " format, \ __func__, __FILE__, __LINE__, \ ##__VA_ARGS__) -#else -#define dprintf(format, ...) #endif #if defined DEBUG @@ -51,8 +49,6 @@ enum { if (level <= LOG_LEVEL) \ dprintf(format, ##__VA_ARGS__); \ } while (0) -#else -#define dlog(level, format, ...) #endif #ifdef __cplusplus