From 4fdf60a4c9ce16dd459e05ad7664010ea45c43db Mon Sep 17 00:00:00 2001 From: Aki Date: Wed, 24 Feb 2021 01:04:57 +0100 Subject: Started progress towards coroutine-based connection handling --- Makefile | 11 +++++------ connection.c | 23 +++++++++-------------- connection.h | 6 +----- plop.c | 51 +++++++++++++++++++++++++++++++++------------------ stream.c | 23 +++++++++++++++++++++++ stream.h | 10 ++++++++++ 6 files changed, 81 insertions(+), 43 deletions(-) create mode 100644 stream.c create mode 100644 stream.h diff --git a/Makefile b/Makefile index c1e137f..68c7d65 100644 --- a/Makefile +++ b/Makefile @@ -5,13 +5,12 @@ LDLIBS+=-llua5.3 PREFIX?=/usr/local SHARE?=$(PREFIX)/share -plop: connection.o main.o plop.o response.o request.o +plop: connection.o main.o plop.o stream.o -main.o: plop.h request.h -plop.o: connection.h plop.h request.h response.h -request.o: connection.h request.h -response.o: response.h -connection.o: connection.h request.h +main.o: plop.h +plop.o: connection.h plop.h stream.h +connection.o: connection.h +stream.o: stream.h clean: rm -f plop *.o diff --git a/connection.c b/connection.c index f987d65..055b498 100644 --- a/connection.c +++ b/connection.c @@ -15,6 +15,8 @@ /// \return Pointer to connection or NULL if an error occured struct connection * connection_new(lua_State * L, const int client) { + (void) L; // TODO: Review if lua_State is still needed for connections and server handler. + struct connection * c = malloc(sizeof(struct connection)); if (NULL == c) @@ -25,29 +27,22 @@ struct connection * connection_new(lua_State * L, const int client) memset(c, 0, sizeof(struct connection)); c->fd = client; - c->L = lua_newthread(L); - c->lua_ref = luaL_ref(L, LUA_REGISTRYINDEX); + c->ref = LUA_NOREF; + c->L = NULL; return c; } -/// Clears the state of connection readying it for new request. -/// \param c Connection to clear -void connection_clear(struct connection * c) -{ - if (NULL != c->request) - { - free_request(c->request); - } -} - /// Frees all resources associated with the connection. /// \param L Server's Lua state /// \param c Connection to free void connection_free(lua_State * L, struct connection * c) { - connection_clear(c); - luaL_unref(L, LUA_REGISTRYINDEX, c->lua_ref); + if (LUA_NOREF != c->ref) + { + luaL_unref(L, LUA_REGISTRYINDEX, c->ref); + } + close(c->fd); // TODO: Check for errors in close()? free(c); } diff --git a/connection.h b/connection.h index 3a7b32a..88cd6b8 100644 --- a/connection.h +++ b/connection.h @@ -2,16 +2,12 @@ #include -#include "request.h" - struct connection { int fd; - int lua_ref; + int ref; lua_State * L; - struct request * request; }; struct connection * connection_new(lua_State *, const int); -void connection_clear(struct connection *); void connection_free(lua_State *, struct connection *); diff --git a/plop.c b/plop.c index 592fca0..980ce90 100644 --- a/plop.c +++ b/plop.c @@ -16,8 +16,7 @@ #include #include "connection.h" -#include "request.h" -#include "response.h" +#include "stream.h" /// Initializes new Lua state for the server. /// \return Lua state @@ -139,27 +138,43 @@ int plop_load_handler(lua_State * L, const char * path) /// \return -1 if an error occured int plop_handle_client(lua_State * L, struct epoll_event * event) { - struct connection * connection = (struct connection *) event->data.ptr; + struct connection * c = (struct connection *) event->data.ptr; + int nargs = 0; - if (-1 == parse_request(connection)) + if (NULL == c->L) { - lua_newtable(connection->L); - lua_pushstring(connection->L, "status"); - lua_pushinteger(connection->L, 400); // TODO: How about a function that generates error responses? - lua_rawset(connection->L, -3); - } - else // TODO: 0 may mean EAGAIN, stuff will be bad very soon from here. - { - // TODO: Push the handler to stack earlier to avoid shifting it. - lua_getglobal(connection->L, "handler"); - lua_insert(connection->L, 1); - lua_call(connection->L, 5, 1); + c->L = lua_newthread(L); + + if (NULL == c->L) + { + return -1; // TODO: Fail only this connection? + } + + c->ref = luaL_ref(L, LUA_REGISTRYINDEX); + + lua_getglobal(c->L, "handler"); + stream_push_new(c->L, c->fd); + nargs = 1; } - int result = response_send(connection->L, connection->fd); - connection_free(L, connection); + int result = lua_resume(c->L, NULL, nargs); + connection_free(L, c); // TODO: Allow consistent connections? - return result; + switch (result) + { + case LUA_OK: + { + return 0; + } + case LUA_YIELD: + { + return 0; + } + default: + { + return -1; + } + } } /// Accepts awaiting connections if any. diff --git a/stream.c b/stream.c new file mode 100644 index 0000000..d6a5254 --- /dev/null +++ b/stream.c @@ -0,0 +1,23 @@ +#include "stream.h" + +#include +#include + +/// Creates and pushes new Stream into the Lua stack. +/// \param L Lua state to push to +/// \param fd File descriptor used by stream +/// \return TODO +int stream_push_new(lua_State * L, const int fd) +{ + struct stream * s = lua_newuserdata(L, sizeof(struct stream)); + s->fd = fd; + + if (1 == luaL_newmetatable(L, "stream")) + { + // TODO: initialize metatable for stream + } + + lua_setmetatable(L, -2); + + return LUA_OK; +} diff --git a/stream.h b/stream.h new file mode 100644 index 0000000..5762bc8 --- /dev/null +++ b/stream.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +struct stream +{ + int fd; +}; + +int stream_push_new(lua_State *, const int); -- cgit v1.1