diff options
Diffstat (limited to 'lem/streams/core.c')
-rw-r--r-- | lem/streams/core.c | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/lem/streams/core.c b/lem/streams/core.c new file mode 100644 index 0000000..e9ed9f4 --- /dev/null +++ b/lem/streams/core.c @@ -0,0 +1,258 @@ +/* + * This file is part of LEM, a Lua Event Machine. + * Copyright 2011-2012 Emil Renner Berthing + * + * LEM is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * LEM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LEM. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> + +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <netinet/tcp.h> +#include <netdb.h> + +#if defined(__FreeBSD__) || defined(__APPLE__) +#include <netinet/in.h> +#else +#include <sys/sendfile.h> +#endif + +#include <streams.h> + +#include "sendfile.c" +#include "stream.c" +#include "server.c" +#include "tcp.c" +#include "parsers.c" + +static int +module_index(lua_State *T) +{ + const char *key = lua_tostring(T, 2); + int fd; + + if (strcmp(key, "stdin") == 0) + fd = 0; + else if (strcmp(key, "stdout") == 0) + fd = 1; + else if (strcmp(key, "stderr") == 0) + fd = 2; + else + return 0; + + /* make the socket non-blocking */ + if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { + lua_pushnil(T); + lua_pushfstring(T, "error making filedescriptor non-blocking: %s", + strerror(errno)); + return 2; + } + + if (fd == 0) + (void)istream_new(T, fd, lua_upvalueindex(1)); + else + (void)ostream_new(T, fd, lua_upvalueindex(2)); + + /* save this object so we don't initialize it again */ + lua_pushvalue(T, 2); + lua_pushvalue(T, -2); + lua_rawset(T, 1); + + return 1; +} + +int +luaopen_lem_streams_core(lua_State *L) +{ + /* create module table */ + lua_newtable(L); + + /* create metatable for sendfile objects */ + lua_newtable(L); + /* mt.__index = mt */ + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + /* mt.__gc = <sendfile_gc> */ + lua_pushcfunction(L, sendfile_gc); + lua_setfield(L, -2, "__gc"); + /* mt.close = <sendfile_close> */ + lua_pushcfunction(L, sendfile_close); + lua_setfield(L, -2, "close"); + /* mt.size = <sendfile_size> */ + lua_pushcfunction(L, sendfile_size); + lua_setfield(L, -2, "size"); + /* insert table */ + lua_setfield(L, -2, "SendFile"); + + /* insert sendfile function */ + lua_getfield(L, -1, "SendFile"); /* upvalue 1 = SendFile */ + lua_pushcclosure(L, sendfile_open, 1); + lua_setfield(L, -2, "sendfile"); + + /* create metatable for input stream objects */ + lua_newtable(L); + /* mt.__index = mt */ + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + /* mt.__gc = <stream_close> */ + lua_pushcfunction(L, istream_close); + lua_setfield(L, -2, "__gc"); + /* mt.closed = <stream_closed> */ + lua_pushcfunction(L, stream_closed); + lua_setfield(L, -2, "closed"); + /* mt.busy = <stream_busy> */ + lua_pushcfunction(L, stream_busy); + lua_setfield(L, -2, "busy"); + /* mt.interrupt = <stream_interrupt> */ + lua_pushcfunction(L, stream_interrupt); + lua_setfield(L, -2, "interrupt"); + /* mt.close = <istream_close> */ + lua_pushcfunction(L, istream_close); + lua_setfield(L, -2, "close"); + /* mt.readp = <stream_readp> */ + lua_pushcfunction(L, stream_readp); + lua_setfield(L, -2, "readp"); + /* insert table */ + lua_setfield(L, -2, "IStream"); + + /* create metatable for output stream objects */ + lua_newtable(L); + /* mt.__index = mt */ + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + /* mt.__gc = <ostream_close> */ + lua_pushcfunction(L, ostream_close); + lua_setfield(L, -2, "__gc"); + /* mt.closed = <stream_closed> */ + lua_pushcfunction(L, stream_closed); + lua_setfield(L, -2, "closed"); + /* mt.busy = <stream_busy> */ + lua_pushcfunction(L, stream_busy); + lua_setfield(L, -2, "busy"); + /* mt.interrupt = <stream_interrupt> */ + lua_pushcfunction(L, stream_interrupt); + lua_setfield(L, -2, "interrupt"); + /* mt.close = <ostream_close> */ + lua_pushcfunction(L, ostream_close); + lua_setfield(L, -2, "close"); + /* mt.write = <stream_write> */ + lua_pushcfunction(L, stream_write); + lua_setfield(L, -2, "write"); + /* mt.cork = <stream_cork> */ + lua_pushcfunction(L, stream_cork); + lua_setfield(L, -2, "cork"); + /* mt.uncork = <stream_uncork> */ + lua_pushcfunction(L, stream_uncork); + lua_setfield(L, -2, "uncork"); + /* mt.sendfile = <ostream_sendfile> */ + lua_pushcfunction(L, stream_sendfile); + lua_setfield(L, -2, "sendfile"); + /* insert table */ + lua_setfield(L, -2, "OStream"); + + /* create metatable for server objects */ + lua_newtable(L); + /* mt.__index = mt */ + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + /* mt.__gc = <server_close> */ + lua_pushcfunction(L, server_close); + lua_setfield(L, -2, "__gc"); + /* mt.closed = <server_closed> */ + lua_pushcfunction(L, server_closed); + lua_setfield(L, -2, "closed"); + /* mt.busy = <server_busy> */ + lua_pushcfunction(L, server_busy); + lua_setfield(L, -2, "busy"); + /* mt.close = <server_close> */ + lua_pushcfunction(L, server_close); + lua_setfield(L, -2, "close"); + /* mt.interrupt = <server_interrupt> */ + lua_pushcfunction(L, server_interrupt); + lua_setfield(L, -2, "interrupt"); + /* mt.accept = <server_accept> */ + lua_getfield(L, -2, "IStream"); /* upvalue 1 = IStream */ + lua_getfield(L, -3, "OStream"); /* upvalue 2 = OStream */ + lua_pushcclosure(L, server_accept, 2); + lua_setfield(L, -2, "accept"); + /* mt.autospawn = <server_autospawn> */ + lua_getfield(L, -2, "IStream"); /* upvalue 1 = IStream */ + lua_getfield(L, -3, "OStream"); /* upvalue 2 = OStream */ + lua_pushcclosure(L, server_autospawn, 2); + lua_setfield(L, -2, "autospawn"); + /* insert table */ + lua_setfield(L, -2, "Server"); + + /* insert open function */ + lua_getfield(L, -1, "IStream"); /* upvalue 1 = IStream */ + lua_getfield(L, -2, "OStream"); /* upvalue 2 = OStream */ + lua_pushcclosure(L, stream_open, 2); + lua_setfield(L, -2, "open"); + /* insert popen function */ + lua_getfield(L, -1, "IStream"); /* upvalue 1 = IStream */ + lua_getfield(L, -2, "OStream"); /* upvalue 2 = OStream */ + lua_pushcclosure(L, stream_popen, 2); + lua_setfield(L, -2, "popen"); + + /* insert the connect function */ + lua_getfield(L, -1, "IStream"); /* upvalue 1 = IStream */ + lua_getfield(L, -2, "OStream"); /* upvalue 2 = OStream */ + lua_pushcclosure(L, tcp_connect, 2); + lua_setfield(L, -2, "tcp_connect"); + /* insert the tcp4_listen function */ + lua_getfield(L, -1, "Server"); /* upvalue 1 = Server */ + lua_pushcclosure(L, tcp4_listen, 1); + lua_setfield(L, -2, "tcp4_listen"); + /* insert the tcp6_listen function */ + lua_getfield(L, -1, "Server"); /* upvalue 1 = Server */ + lua_pushcclosure(L, tcp6_listen, 1); + lua_setfield(L, -2, "tcp6_listen"); + + /* create parser table */ + lua_createtable(L, 0, 4); + /* push parser_line */ + lua_pushlightuserdata(L, (void *)&parser_available); + lua_setfield(L, -2, "available"); + /* push parser_target */ + lua_pushlightuserdata(L, (void *)&parser_target); + lua_setfield(L, -2, "target"); + /* push parser_all */ + lua_pushlightuserdata(L, (void *)&parser_all); + lua_setfield(L, -2, "*a"); + /* push parser_line */ + lua_pushlightuserdata(L, (void *)&parser_line); + lua_setfield(L, -2, "*l"); + /* insert parser table */ + lua_setfield(L, -2, "parsers"); + + /* create metatable for the module */ + lua_newtable(L); + /* insert the index function */ + lua_getfield(L, -2, "IStream"); /* upvalue 1 = IStream */ + lua_getfield(L, -3, "OStream"); /* upvalue 2 = OStream */ + lua_pushcclosure(L, module_index, 2); + lua_setfield(L, -2, "__index"); + + /* set the metatable */ + lua_setmetatable(L, -2); + + return 1; +} |