diff options
-rw-r--r-- | main.c | 54 | ||||
-rw-r--r-- | plop.c | 73 | ||||
-rw-r--r-- | plop.h | 6 | ||||
-rw-r--r-- | request.h | 1 |
4 files changed, 74 insertions, 60 deletions
@@ -1,5 +1,5 @@ -#include <poll.h> #include <string.h> +#include <sys/epoll.h> #include <lauxlib.h> #include <lua.h> @@ -26,33 +26,51 @@ int main(int argc, char ** argv) return 2; // TODO: Document error codes/print usage information } - static const int max_clients = 200; + const int efd = epoll_create1(0); - int fdc = 0; - struct request * requests[max_clients]; - struct pollfd fdv[max_clients]; - - memset(requests, 0, sizeof(requests)); - memset(fdv, 0, sizeof(fdv)); + if (-1 == efd) + { + return 3; // TODO: Handle errors properly + } - fdv[0].fd = make_server(NULL, argv[1]); - fdv[0].events = POLLIN; - fdc++; + struct epoll_event e; + e.events = EPOLLIN; + e.data.ptr = NULL; // TODO: Consider putting server's Lua state in here? + const int server = make_server(NULL, argv[1]); // TODO: Check server's fd before ctl? - if (-1 == fdv[0].fd) + if (-1 == epoll_ctl(efd, EPOLL_CTL_ADD, server, &e)) { - return 1; // TODO: Document error codes/print usage information + return 4; // TODO: Handle errors properly } - while (0 < fdc && -1 != poll(fdv, fdc, -1)) + static const int MAX_EVENTS = 20; + struct epoll_event events[MAX_EVENTS]; + + while (1) { - int shift_by = 0; + int evc = epoll_wait(efd, events, MAX_EVENTS, -1); - for (int i = 1; i < fdc; ++i) + if (-1 == evc) { - shift_by = handle_client(L, &fdv[i], &requests[i], shift_by); + return 5; // TODO: Handle errors properly } - fdc = handle_server(fdv, fdc - shift_by, max_clients); + for (int i = 0; i < evc; ++i) + { + if (NULL == events[i].data.ptr) + { + if (-1 == handle_server(L, efd, server)) + { + return 6; // TODO: Handle errors properly + } + } + else + { + if (-1 == handle_client(L, &events[i])) + { + return 7; // TODO: Handle errors properly + } + } + } } } @@ -3,10 +3,10 @@ #include <errno.h> #include <fcntl.h> #include <netdb.h> -#include <poll.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sys/epoll.h> #include <sys/socket.h> #include <sys/types.h> #include <unistd.h> @@ -113,29 +113,19 @@ int load_handler(lua_State * L, const char * path) return LUA_OK; } -/// Progresses the connection for a client and shifts it back in the array. -/// `pfd` must be at least `shift_by + 1`-th element of the array. +/// Handles client events. /// \param L Server's Lua state -/// \param pfd Element in array processed by poll -/// \param request Pointer to request context associated with current client -/// \param shift_by Element will be moved by in array this many indices -/// \return Shift value for next handler -/// \see poll(2) -int handle_client(lua_State * L, struct pollfd * pfd, struct request ** request, const int shift_by) +/// \param event Event for client +/// \return -1 if an error occured +int handle_client(lua_State * L, struct epoll_event * event) { - if (0 == pfd->revents) - { - return shift_by; - } - - if (~(POLLIN | POLLOUT) & pfd->revents) - { - return -1; // TODO: Handle errors properly - } + // TODO: Temporary shenanigans to avoid too much changes. + struct request * r = (struct request *) event->data.ptr; + struct request ** request = &r; - if (-1 == parse_request(L, pfd->fd, request)) + if (-1 == parse_request(L, (*request)->fd, request)) { - respond_only_status(pfd->fd, STATUS_BAD_REQUEST); + respond_only_status((*request)->fd, STATUS_BAD_REQUEST); return -1; // TODO: Handle errors properly } @@ -149,16 +139,14 @@ int handle_client(lua_State * L, struct pollfd * pfd, struct request ** request, if (NULL != body) { - respond_with_body(pfd->fd, STATUS_OK, body, (int) length); + respond_with_body((*request)->fd, STATUS_OK, body, (int) length); } else { - respond_only_status(pfd->fd, STATUS_INTERNAL_SERVER_ERROR); + respond_only_status((*request)->fd, STATUS_INTERNAL_SERVER_ERROR); } - close(pfd->fd); - (pfd - shift_by)->fd = -1; - (pfd - shift_by)->events = pfd->events; + close((*request)->fd); if (NULL != *request) { @@ -166,32 +154,39 @@ int handle_client(lua_State * L, struct pollfd * pfd, struct request ** request, *request = NULL; } - return shift_by + 1; + return 0; } /// Accepts awaiting connections if any. -/// \param fdv Array of descriptors for poll -/// \param fdc Number of valid descriptors in the array including the server -/// \param size Size limit for the array -/// \return Number of valid descriptors in the array or -1 if an error occurred. -/// \see poll(2) -int handle_server(struct pollfd * fdv, int fdc, const int size) +/// \param L Server's Lua state +/// \param efd File descriptor for epoll's context +/// \param server File descriptor for server socket +/// \return -1 if an error occured +int handle_server(lua_State * L, const int efd, const int server) { - if (0 == fdv[0].revents) + struct epoll_event e; + e.events = EPOLLIN; // TODO: Add EPOLLOUT? + + const int client = accept(server, NULL, NULL); + if (-1 == client) { - return fdc; + return -1; // TODO: Consider not crashing entire server because of one accept. } - while (size > fdc + 1 && -1 != (fdv[fdc].fd = accept(fdv[0].fd, NULL, NULL))) + // TODO: Request is not the enitre state of the client. Make them distinct along with responses. + struct request * request = new_request(L); + if (NULL == request) { - fdv[fdc].events = POLLIN | POLLOUT; - fdc++; + return -1; } - if (EWOULDBLOCK != errno && EAGAIN != errno) + request->fd = client; + e.data.ptr = request; + + if (-1 == epoll_ctl(efd, EPOLL_CTL_ADD, client, &e)) { return -1; } - return fdc; + return 0; } @@ -1,6 +1,6 @@ #pragma once -#include <poll.h> +#include <sys/epoll.h> #include <lua.h> @@ -9,5 +9,5 @@ int make_server(const char *, const char *); int load_handler(lua_State *, const char *); -int handle_client(lua_State *, struct pollfd *, struct request **, const int); -int handle_server(struct pollfd *, int, const int); +int handle_client(lua_State *, struct epoll_event *); +int handle_server(lua_State *, const int, const int); @@ -18,6 +18,7 @@ struct request int reference; struct span temp; int expected_data_length; + int fd; }; struct request * new_request(lua_State *); |