diff --git a/mongoose.c b/mongoose.c index bb388a6b..37941566 100644 --- a/mongoose.c +++ b/mongoose.c @@ -2653,6 +2653,7 @@ int mg_parse_header(const char *str, const char *var_name, char *buf, } #ifdef USE_LUA +#include #include "lua_5.2.1.h" static void reg_string(struct lua_State *L, const char *name, const char *val) { @@ -2693,6 +2694,103 @@ static int lua_write(lua_State *L) { return 0; } +static int lsp_sock_close(lua_State *L) { + if (lua_gettop(L) > 0 && lua_istable(L, -1)) { + lua_getfield(L, -1, "sock"); + closesocket((sock_t) lua_tonumber(L, -1)); + } else { + return luaL_error(L, "invalid :close() call"); + } + return 1; +} + +static int lsp_sock_recv(lua_State *L) { + char buf[2000]; + int n; + + if (lua_gettop(L) > 0 && lua_istable(L, -1)) { + lua_getfield(L, -1, "sock"); + n = recv((sock_t) lua_tonumber(L, -1), buf, sizeof(buf), 0); + if (n <= 0) { + lua_pushnil(L); + } else { + lua_pushlstring(L, buf, n); + } + } else { + return luaL_error(L, "invalid :close() call"); + } + return 1; +} + +static int lsp_sock_send(lua_State *L) { + const char *buf; + size_t len, sent = 0; + int n, sock; + + if (lua_gettop(L) > 1 && lua_istable(L, -2) && lua_isstring(L, -1)) { + buf = lua_tolstring(L, -1, &len); + lua_getfield(L, -2, "sock"); + sock = (int) lua_tonumber(L, -1); + while (sent < len) { + if ((n = send(sock, buf + sent, len - sent, 0)) <= 0) { + break; + } + sent += n; + } + lua_pushnumber(L, n); + } else { + return luaL_error(L, "invalid :close() call"); + } + return 1; +} + +static const struct luaL_Reg luasocket_methods[] = { + {"close", lsp_sock_close}, + {"send", lsp_sock_send}, + {"recv", lsp_sock_recv}, + {NULL, NULL} +}; + +static sock_t conn2(const char *host, int port) { + struct sockaddr_in sin; + struct hostent *he = NULL; + sock_t sock = INVALID_SOCKET; + + if (host != NULL && + (he = gethostbyname(host)) != NULL && + (sock = socket(PF_INET, SOCK_STREAM, 0)) != INVALID_SOCKET) { + set_close_on_exec(sock); + sin.sin_family = AF_INET; + sin.sin_port = htons((uint16_t) port); + sin.sin_addr = * (struct in_addr *) he->h_addr_list[0]; + if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) != 0) { + closesocket(sock); + sock = INVALID_SOCKET; + } + } + return sock; +} + +static int lsp_connect(lua_State *L) { + sock_t sock; + + if (lua_isstring(L, -2) && lua_isnumber(L, -1)) { + sock = conn2(lua_tostring(L, -2), (int) lua_tonumber(L, -1)); + if (sock == INVALID_SOCKET) { + lua_pushnil(L); + } else { + lua_newtable(L); + reg_int(L, "sock", sock); + reg_string(L, "host", lua_tostring(L, -4)); + luaL_getmetatable(L, "luasocket"); + lua_setmetatable(L, -2); + } + } else { + return luaL_error(L, "connect(host,port): invalid parameter given."); + } + return 1; +} + static void prepare_lua_environment(struct mg_connection *ri, lua_State *L) { extern void luaL_openlibs(lua_State *); int i; @@ -2702,14 +2800,12 @@ static void prepare_lua_environment(struct mg_connection *ri, lua_State *L) { { extern int luaopen_lsqlite3(lua_State *); luaopen_lsqlite3(L); } #endif -#if 0 - luaL_newmetatable(L, static_luasocket_module_name); + luaL_newmetatable(L, "luasocket"); lua_pushliteral(L, "__index"); luaL_newlib(L, luasocket_methods); lua_rawset(L, -3); lua_pop(L, 1); lua_register(L, "connect", lsp_connect); -#endif if (ri == NULL) return;