diff --git a/src/client/http/Request.cpp b/src/client/http/Request.cpp index 88061ff80..8912e24ce 100644 --- a/src/client/http/Request.cpp +++ b/src/client/http/Request.cpp @@ -2,6 +2,37 @@ #include "RequestManager.h" +#ifndef NOHTTP +void SetupCurlEasyCiphers(CURL *easy) +{ +#ifdef SECURE_CIPHERS_ONLY + curl_version_info_data *version_info = curl_version_info(CURLVERSION_NOW); + ByteString ssl_type = version_info->ssl_version; + if (ssl_type.Contains("OpenSSL")) + { + curl_easy_setopt(easy, CURLOPT_SSL_CIPHER_LIST, "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-GCM-SHA256"); +#ifdef REQUEST_USE_CURL_TLSV13CL + curl_easy_setopt(easy, CURLOPT_TLS13_CIPHERS, "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_8_SHA256:TLS_AES_128_CCM_SHA256"); +#endif + } + else if (ssl_type.Contains("Schannel")) + { + // TODO: add more cipher algorithms + curl_easy_setopt(easy, CURLOPT_SSL_CIPHER_LIST, "CALG_ECDH_EPHEM"); + } +#endif + // TODO: Find out what TLS1.2 is supported on, might need to also allow TLS1.0 + curl_easy_setopt(easy, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); +#if defined(CURL_AT_LEAST_VERSION) && CURL_AT_LEAST_VERSION(7, 70, 0) + curl_easy_setopt(easy, CURLOPT_SSL_OPTIONS, CURLSSLOPT_REVOKE_BEST_EFFORT); +#elif defined(CURL_AT_LEAST_VERSION) && CURL_AT_LEAST_VERSION(7, 44, 0) + curl_easy_setopt(easy, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE); +#elif defined(WIN) +# error "That's unfortunate." +#endif +} +#endif + namespace http { #ifndef NOHTTP @@ -181,31 +212,8 @@ namespace http curl_easy_setopt(easy, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTPS | CURLPROTO_HTTP); #endif -#ifdef SECURE_CIPHERS_ONLY - curl_version_info_data* version_info = curl_version_info(CURLVERSION_NOW); - ByteString ssl_type = version_info->ssl_version; - if (ssl_type.Contains("OpenSSL")) - { - curl_easy_setopt(easy, CURLOPT_SSL_CIPHER_LIST, "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-GCM-SHA256"); -#ifdef REQUEST_USE_CURL_TLSV13CL - curl_easy_setopt(easy, CURLOPT_TLS13_CIPHERS, "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_8_SHA256:TLS_AES_128_CCM_SHA256"); -#endif - } - else if (ssl_type.Contains("Schannel")) - { - // TODO: add more cipher algorithms - curl_easy_setopt(easy, CURLOPT_SSL_CIPHER_LIST, "CALG_ECDH_EPHEM"); - } -#endif - // TODO: Find out what TLS1.2 is supported on, might need to also allow TLS1.0 - curl_easy_setopt(easy, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); -#if defined(CURL_AT_LEAST_VERSION) && CURL_AT_LEAST_VERSION(7, 70, 0) - curl_easy_setopt(easy, CURLOPT_SSL_OPTIONS, CURLSSLOPT_REVOKE_BEST_EFFORT); -#elif defined(CURL_AT_LEAST_VERSION) && CURL_AT_LEAST_VERSION(7, 44, 0) - curl_easy_setopt(easy, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE); -#elif defined(WIN) -# error "That's unfortunate." -#endif + SetupCurlEasyCiphers(easy); + curl_easy_setopt(easy, CURLOPT_MAXREDIRS, 10L); curl_easy_setopt(easy, CURLOPT_ERRORBUFFER, error_buffer); diff --git a/src/config/meson.build b/src/config/meson.build index 214e8915d..b9d92080f 100644 --- a/src/config/meson.build +++ b/src/config/meson.build @@ -1,3 +1,9 @@ -subdir('powder') -subdir('render') -subdir('font') +if get_option('build_powder') + subdir('powder') +endif +if get_option('build_render') + subdir('render') +endif +if get_option('build_font') + subdir('font') +endif diff --git a/src/lua/LuaScriptInterface.cpp b/src/lua/LuaScriptInterface.cpp index c4ea4e8f0..444272c92 100644 --- a/src/lua/LuaScriptInterface.cpp +++ b/src/lua/LuaScriptInterface.cpp @@ -24,6 +24,8 @@ #include "LuaTextbox.h" #include "LuaWindow.h" +#include "LuaTCPSocket.h" + #include "gui/interface/Window.h" #include "gui/interface/Engine.h" #include "gui/game/GameView.h" @@ -60,9 +62,7 @@ extern "C" #endif #include #include -#include "luasocket/luasocket.h" } -#include "socket.lua.h" #include "eventcompat.lua.h" // idea from mniip, makes things much simpler @@ -148,22 +148,6 @@ LuaScriptInterface::LuaScriptInterface(GameController * c, GameModel * m): luaL_openlibs(l); luaopen_bit(l); - // load built-in luasocket and luasec - lua_getglobal(l, "package"); - lua_getfield(l, -1, "preload"); - lua_pushcfunction(l, luaopen_socket_core); - lua_setfield(l, -2, "socket.core"); - if (luaL_loadbuffer(l, (const char *)socket_lua, socket_lua_size, "@[built-in socket.lua]")) - { - throw std::runtime_error(ByteString("failed to load built-in luasocket: ") + lua_tostring(l, -1)); - } - lua_setfield(l, -2, "socket"); - lua_pop(l, 2); - if (luaL_dostring(l, "socket = require(\"socket\")")) - { - throw std::runtime_error(ByteString("failed to load built-in luasocket: ") + lua_tostring(l, -1)); - } - lua_pushstring(l, "Luacon_ci"); lua_pushlightuserdata(l, this); lua_settable(l, LUA_REGISTRYINDEX); @@ -178,6 +162,7 @@ LuaScriptInterface::LuaScriptInterface(GameController * c, GameModel * m): initPlatformAPI(); initEventAPI(); initHttpAPI(); + initSocketAPI(); //Old TPT API int currentElementMeta, currentElement; @@ -4010,21 +3995,24 @@ void LuaScriptInterface::initHttpAPI() lua_pushcfunction(l, http_request_gc); lua_setfield(l, -2, "__gc"); lua_newtable(l); - lua_pushcfunction(l, http_request_status); - lua_setfield(l, -2, "status"); - lua_pushcfunction(l, http_request_progress); - lua_setfield(l, -2, "progress"); - lua_pushcfunction(l, http_request_cancel); - lua_setfield(l, -2, "cancel"); - lua_pushcfunction(l, http_request_finish); - lua_setfield(l, -2, "finish"); - lua_setfield(l, -2, "__index"); - struct luaL_Reg httpAPIMethods [] = { - {"get", http_get}, - {"post", http_post}, - {NULL, NULL} + struct luaL_Reg httpRequestIndexMethods[] = { + { "status", http_request_status }, + { "progress", http_request_progress }, + { "cancel", http_request_cancel }, + { "finish", http_request_finish }, + { NULL, NULL } }; - luaL_register(l, "http", httpAPIMethods); + luaL_register(l, NULL, httpRequestIndexMethods); + lua_setfield(l, -2, "__index"); + lua_pop(l, 1); + lua_newtable(l); + struct luaL_Reg httpMethods[] = { + { "get", http_get }, + { "post", http_post }, + { NULL, NULL } + }; + luaL_register(l, NULL, httpMethods); + lua_setglobal(l, "http"); } bool LuaScriptInterface::HandleEvent(LuaEvents::EventTypes eventType, Event * event) @@ -4333,4 +4321,10 @@ LuaScriptInterface::~LuaScriptInterface() { lua_close(l); delete legacy; } + +void LuaScriptInterface::initSocketAPI() +{ + LuaTCPSocket::Open(l); +} + #endif diff --git a/src/lua/LuaScriptInterface.h b/src/lua/LuaScriptInterface.h index 6cc2ee588..a1cf6d412 100644 --- a/src/lua/LuaScriptInterface.h +++ b/src/lua/LuaScriptInterface.h @@ -186,6 +186,8 @@ class LuaScriptInterface: public CommandInterface static int http_get(lua_State * l); static int http_post(lua_State * l); + void initSocketAPI(); + std::vector lua_el_func_v, lua_gr_func_v, lua_cd_func_v; std::vector lua_el_mode_v; diff --git a/src/lua/LuaTCPSocket.cpp b/src/lua/LuaTCPSocket.cpp new file mode 100644 index 000000000..294cfa6aa --- /dev/null +++ b/src/lua/LuaTCPSocket.cpp @@ -0,0 +1,665 @@ +#include "LuaTCPSocket.h" + +#ifndef NOHTTP +# include "common/String.h" +# include +# include +# include +# include +#endif +#include +#include +#ifdef WIN +# include +# include +#else +# include +# include +#endif + +void SetupCurlEasyCiphers(CURL *easy); + +namespace LuaTCPSocket +{ + static double Now() + { +#ifdef WIN + FILETIME rt; + GetSystemTimeAsFileTime(&rt); + return (rt.dwLowDateTime + (uint64_t(rt.dwHighDateTime) << 32) - uint64_t(116444736000000000ULL)) / 1e7; +#else + struct timeval rt; + gettimeofday(&rt, (struct timezone *)NULL); + return rt.tv_sec + rt.tv_usec / 1e6; +#endif + } + + static int GetTime(lua_State *l) + { + lua_pushnumber(l, Now()); + return 1; + } + + static void Timeout(double timeout) + { +#ifdef WIN + if (timeout < 0.0) timeout = 0.0; + if (timeout < DBL_MAX / 1000.0) timeout *= 1000.0; + if (timeout > INT_MAX) timeout = INT_MAX; + ::Sleep(int(timeout)); +#else + struct timespec req, rem; + if (timeout < 0.0) timeout = 0.0; + if (timeout > INT_MAX) timeout = INT_MAX; + req.tv_sec = int(timeout); + req.tv_nsec = int((timeout - req.tv_sec) * 1000000000); + if (req.tv_nsec > 999999999) req.tv_nsec = 999999999; + while (nanosleep(&req, &rem)) + { + req.tv_sec = rem.tv_sec; + req.tv_nsec = rem.tv_nsec; + } +#endif + } + + static int Sleep(lua_State *l) + { + Timeout(luaL_checknumber(l, 1)); + return 0; + } + +#ifndef NOHTTP + enum Status + { + StatusReady, + StatusConnecting, + StatusConnected, + StatusDead, + }; + + struct TCPSocket + { + CURL *easy; + CURLM *multi; + char errorBuf[CURL_ERROR_SIZE]; + Status status; + bool timeoutIndefinite; + bool blocking; + double timeout; + std::vector recvBuf; + size_t stashedLen; + bool readClosed; + bool writeClosed; + }; + + static void Reset(TCPSocket *tcps) + { + if (tcps->multi) + { + curl_multi_remove_handle(tcps->multi, tcps->easy); + curl_multi_cleanup(tcps->multi); + tcps->multi = nullptr; + } + if (tcps->easy) + { + curl_easy_cleanup(tcps->easy); + tcps->easy = nullptr; + } + tcps->status = StatusDead; + } + + static bool ConnectPerform(TCPSocket *tcps, CURLcode *res) + { + while (true) + { + int dontcare; + auto mres = curl_multi_perform(tcps->multi, &dontcare); + struct CURLMsg *msg; + while ((msg = curl_multi_info_read(tcps->multi, &dontcare))) + { + if (msg->msg == CURLMSG_DONE) + { + *res = msg->data.result; + return true; + } + }; + if (mres != CURLM_CALL_MULTI_PERFORM) + { + break; + } + } + return false; + } + + static int New(lua_State *l) + { + auto *tcps = (TCPSocket *)lua_newuserdata(l, sizeof(TCPSocket)); + new (tcps) TCPSocket; + tcps->errorBuf[0] = 0; + tcps->easy = curl_easy_init(); + tcps->status = StatusReady; + tcps->timeoutIndefinite = true; + tcps->blocking = true; + tcps->stashedLen = 0; + tcps->readClosed = false; + tcps->writeClosed = false; + if (!tcps->easy) + { + Reset(tcps); + return luaL_error(l, "curl_easy_init failed"); + } + tcps->multi = curl_multi_init(); + if (!tcps->multi) + { + Reset(tcps); + return luaL_error(l, "curl_multi_init failed"); + } + curl_multi_add_handle(tcps->multi, tcps->easy); + luaL_newmetatable(l, "TCPSocket"); + lua_setmetatable(l, -2); + return 1; + } + + static int GC(lua_State *l) + { + auto *tcps = (TCPSocket *)luaL_checkudata(l, 1, "TCPSocket"); + Reset(tcps); + tcps->~TCPSocket(); + return 0; + } + + static int Close(lua_State *l) + { + auto *tcps = (TCPSocket *)luaL_checkudata(l, 1, "TCPSocket"); + Reset(tcps); + return 0; + } + + static int Send(lua_State *l) + { + auto *tcps = (TCPSocket *)luaL_checkudata(l, 1, "TCPSocket"); + if (tcps->status != StatusConnected) + { + return luaL_error(l, "attempt to send on socket while not connected"); + } + size_t dlenu; + auto *data = luaL_checklstring(l, 2, &dlenu); + auto dlen = int(dlenu); + auto first = luaL_optinteger(l, 3, 1); + auto last = luaL_optinteger(l, 4, -1); + if (first < 0) first += dlen + 1; + if (last < 0) last += dlen + 1; + if (first < 1) first = 1; + if (first > dlen) first = dlen; + if (last < 1) last = 1; + if (last > dlen) last = dlen; + auto begin = first - 1; + auto end = last; + data += begin; + auto len = size_t((end > begin) ? (end - begin) : 0); + auto startedAt = Now(); + size_t writtenTotal = 0; + while (true) + { + size_t writtenNow = 0; + CURLcode res = CURLE_OK; + if (!tcps->writeClosed) + { + curl_easy_send(tcps->easy, &data[writtenTotal], len - writtenTotal, &writtenNow); + } + writtenTotal += writtenNow; + if (writtenTotal >= len) + { + break; + } + switch (res) + { + case CURLE_OK: + case CURLE_AGAIN: + break; + + default: + tcps->writeClosed = true; + break; + } + if (tcps->writeClosed) + { + Reset(tcps); + lua_pushnil(l); + lua_pushliteral(l, "closed"); + lua_pushinteger(l, writtenTotal); + return 3; + } + if (res == CURLE_AGAIN) + { + if (tcps->blocking && (tcps->timeoutIndefinite || startedAt + tcps->timeout > Now())) + { + // * Using a platform-dependent primitive to "wait" on the socket is + // not worth the trouble: sockets shouldn't be used with timeouts + // anyway because they freeze the game. + Timeout(0.01); + continue; + } + lua_pushnil(l); + lua_pushliteral(l, "timeout"); + lua_pushinteger(l, writtenTotal); + return 3; + } + } + lua_pushinteger(l, writtenTotal); + return 1; + } + + static int ReceiveNoPrefix(lua_State *l) + { + auto *tcps = (TCPSocket *)luaL_checkudata(l, 1, "TCPSocket"); + if (tcps->status != StatusConnected) + { + return luaL_error(l, "attempt to receive on socket while not connected"); + } + enum + { + readN, + readAll, + readLine, + } pattern = readN; + size_t len = 4096; + if (lua_isstring(l, 2) && !strcmp(lua_tostring(l, 2), "*a")) + { + pattern = readAll; + } + else if (lua_isstring(l, 2) && !strcmp(lua_tostring(l, 2), "*l")) + { + pattern = readLine; + } + else + { + len = size_t(luaL_checkinteger(l, 2)); + } + if (pattern == readAll || pattern == readLine) + { + len += tcps->stashedLen; + } + if (tcps->recvBuf.size() < len) + { + tcps->recvBuf.resize(len); + } + auto startedAt = Now(); + size_t readTotal = 0; + size_t returning = 0; + int retn = 1; + while (true) + { + size_t readNow = 0; + CURLcode res = CURLE_OK; + if (tcps->stashedLen) + { + readNow = tcps->stashedLen; + tcps->stashedLen = 0; + } + else + { + res = curl_easy_recv(tcps->easy, &tcps->recvBuf[readTotal], len - readTotal, &readNow); + } + readTotal += readNow; + returning = readTotal; + if (pattern == readN && readTotal >= len) + { + returning = len; + break; + } + if (pattern == readLine) + { + bool foundLF = false; + for (size_t i = 0; i < readTotal; ++i) + { + if (tcps->recvBuf[i] == '\n') + { + returning = i + 1; + foundLF = true; + break; + } + } + if (foundLF) + { + break; + } + } + switch (res) + { + case CURLE_OK: + if (!readNow) + { + tcps->readClosed = true; + } + break; + + case CURLE_AGAIN: + break; + + default: + tcps->readClosed = true; + break; + } + if (tcps->readClosed) + { + Reset(tcps); + if (pattern == readAll) + { + // * Closed "*a" patterns don't return an error. + break; + } + lua_pushnil(l); + lua_pushliteral(l, "closed"); + if (pattern == readLine) + { + // * Closed "*l" patterns don't return partial lines. + returning = 0; + } + retn = 3; + break; + } + if (readTotal == len && (pattern == readAll || pattern == readLine)) + { + len += len; + if (tcps->recvBuf.size() < len) + { + tcps->recvBuf.resize(len); + } + } + if (res == CURLE_AGAIN) + { + if (tcps->blocking && (tcps->timeoutIndefinite || startedAt + tcps->timeout > Now())) + { + // * Using a platform-dependent primitive to "wait" on the socket is + // not worth the trouble: sockets shouldn't be used with timeouts + // anyway because they freeze the game. + Timeout(0.01); + continue; + } + lua_pushnil(l); + lua_pushliteral(l, "timeout"); + if (pattern == readLine) + { + // * Timed-out "*l" patterns don't return partial lines. + returning = 0; + } + retn = 3; + break; + } + } + tcps->stashedLen = readTotal - returning; + if (pattern == readLine) + { + auto curOut = 0U; + for (auto curIn = 0U; curIn < returning; ++curIn) + { + if (tcps->recvBuf[curIn] != '\r' && tcps->recvBuf[curIn] != '\n') + { + tcps->recvBuf[curOut] = tcps->recvBuf[curIn]; + curOut += 1; + } + } + returning = curOut; + } + lua_pushlstring(l, &tcps->recvBuf[0], returning); + // * This copy makes ReceiveNoPrefix quadratic if there's a lot of stuff in + // the stash (as a result of a *very* long line being returned by an "*l" + // pattern and then whatever was left being stashed) and it's all *very* + // short lines (compared to the previous *very* long one, from the point + // of view of an "*l" pattern). Handling this edge case in a special, + // sub-quadratic way isn't worth the effort. + std::copy( + &tcps->recvBuf[readTotal - tcps->stashedLen], + &tcps->recvBuf[readTotal], + &tcps->recvBuf[0] + ); + return retn; + } + + static int Receive(lua_State *l) + { + bool prefix = false; + if (lua_gettop(l) >= 3) + { + prefix = true; + lua_tostring(l, 3); + } + int ret = ReceiveNoPrefix(l); + if (prefix) + { + lua_pushvalue(l, 3); + lua_insert(l, -2); + lua_concat(l, 2); + } + return ret; + } + + static int Connect(lua_State *l) + { + auto *tcps = (TCPSocket *)luaL_checkudata(l, 1, "TCPSocket"); + if (tcps->status == StatusDead) + { + return luaL_error(l, "attempt to connect dead socket"); + } + if (tcps->status == StatusConnected) + { + return luaL_error(l, "attempt to connect connected socket"); + } + auto startedAt = Now(); + while (true) + { + if (tcps->status != StatusConnecting) + { + tcps->status = StatusConnecting; + // * Using CURLPROTO_HTTPS and CURLPROTO_HTTP with CURL_HTTP_VERSION_1_0 + // because these really don't send anything while connecting if + // CURLOPT_CONNECT_ONLY is 1 and there are no proxies involved. The + // only ugly bit is that we have to prepend http:// or https:// to + // the hostnames. + curl_easy_setopt(tcps->easy, CURLOPT_ERRORBUFFER, tcps->errorBuf); + curl_easy_setopt(tcps->easy, CURLOPT_CONNECT_ONLY, 1L); + ByteString address = luaL_checkstring(l, 2); + curl_easy_setopt(tcps->easy, CURLOPT_PORT, long(luaL_checkinteger(l, 3))); + curl_easy_setopt(tcps->easy, CURLOPT_NOSIGNAL, 1L); + curl_easy_setopt(tcps->easy, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + if (lua_toboolean(l, 4)) + { + curl_easy_setopt(tcps->easy, CURLOPT_PROTOCOLS, CURLPROTO_HTTPS); + curl_easy_setopt(tcps->easy, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTPS); + SetupCurlEasyCiphers(tcps->easy); + address = "https://" + address; + } + else + { + curl_easy_setopt(tcps->easy, CURLOPT_PROTOCOLS, CURLPROTO_HTTP); + curl_easy_setopt(tcps->easy, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP); + address = "http://" + address; + } + curl_easy_setopt(tcps->easy, CURLOPT_URL, address.c_str()); + } + CURLcode res; + if (!ConnectPerform(tcps, &res)) + { + if (tcps->blocking && (tcps->timeoutIndefinite || startedAt + tcps->timeout > Now())) + { + // * Using a platform-dependent primitive to "wait" on the socket is + // not worth the trouble: sockets shouldn't be used with timeouts + // anyway because they freeze the game. + Timeout(0.01); + continue; + } + lua_pushnil(l); + lua_pushliteral(l, "timeout"); + return 2; + } + if (res != CURLE_OK) + { + Reset(tcps); + lua_pushnil(l); + lua_pushstring(l, tcps->errorBuf); + return 2; + } + break; + } + tcps->status = StatusConnected; + lua_pushinteger(l, 1); + return 1; + } + + static int LastError(lua_State *l) + { + auto *tcps = (TCPSocket *)luaL_checkudata(l, 1, "TCPSocket"); + lua_pushstring(l, tcps->errorBuf); + return 1; + } + + static int GetStatus(lua_State *l) + { + auto *tcps = (TCPSocket *)luaL_checkudata(l, 1, "TCPSocket"); + switch (tcps->status) + { + case StatusReady: lua_pushliteral(l, "ready"); break; + case StatusConnecting: lua_pushliteral(l, "connecting"); break; + case StatusConnected: lua_pushliteral(l, "connected"); break; + case StatusDead: lua_pushliteral(l, "dead"); break; + } + return 1; + } + + static int GetPeerName(lua_State *l) + { + auto *tcps = (TCPSocket *)luaL_checkudata(l, 1, "TCPSocket"); + if (tcps->status != StatusConnected) + { + return luaL_error(l, "attempt to get remote socket info while not connected"); + } + char *address; + curl_easy_getinfo(tcps->easy, CURLINFO_PRIMARY_IP, &address); + lua_pushstring(l, address); + long port; + curl_easy_getinfo(tcps->easy, CURLINFO_PRIMARY_PORT, &port); + lua_pushinteger(l, port); + return 2; + } + + static int SetTimeout(lua_State *l) + { + auto *tcps = (TCPSocket *)luaL_checkudata(l, 1, "TCPSocket"); + tcps->blocking = true; + if (lua_isnoneornil(l, 2)) + { + tcps->timeoutIndefinite = true; + } + else + { + tcps->timeoutIndefinite = false; + tcps->timeout = luaL_checknumber(l, 2); + if (int(tcps->timeout) == 0) + { + tcps->blocking = false; + } + } + return 0; + } + + static int GetSockName(lua_State *l) + { + auto *tcps = (TCPSocket *)luaL_checkudata(l, 1, "TCPSocket"); + if (tcps->status != StatusConnected) + { + return luaL_error(l, "attempt to get local socket info while not connected"); + } + char *address; + curl_easy_getinfo(tcps->easy, CURLINFO_LOCAL_IP, &address); + lua_pushstring(l, address); + long port; + curl_easy_getinfo(tcps->easy, CURLINFO_LOCAL_PORT, &port); + lua_pushinteger(l, port); + return 2; + } + + static int SetOption(lua_State *l) + { + auto *tcps = (TCPSocket *)luaL_checkudata(l, 1, "TCPSocket"); + auto *option = luaL_checkstring(l, 2); + if (!strcmp(option, "keepalive")) + { + curl_easy_setopt(tcps->easy, CURLOPT_TCP_KEEPALIVE, long(lua_toboolean(l, 3))); + return 0; + } + else if (!strcmp(option, "tcp-nodelay")) + { + curl_easy_setopt(tcps->easy, CURLOPT_TCP_NODELAY, long(lua_toboolean(l, 3))); + return 0; + } + else if (!strcmp(option, "verify-peer")) + { + curl_easy_setopt(tcps->easy, CURLOPT_SSL_VERIFYPEER, long(lua_toboolean(l, 3))); + return 0; + } + return luaL_error(l, "unknown option"); + } + + static int Shutdown(lua_State *l) + { + auto *tcps = (TCPSocket *)luaL_checkudata(l, 1, "TCPSocket"); + auto *direction = luaL_optstring(l, 2, "both"); + if (!strcmp(direction, "receive")) + { + tcps->readClosed = true; + return 0; + } + else if (!strcmp(direction, "send")) + { + tcps->writeClosed = true; + return 0; + } + else if (!strcmp(direction, "both")) + { + tcps->readClosed = true; + tcps->writeClosed = true; + return 0; + } + return luaL_error(l, "unknown direction"); + } +#endif + + void Open(lua_State *l) + { +#ifndef NOHTTP + luaL_newmetatable(l, "TCPSocket"); + lua_pushcfunction(l, LuaTCPSocket::GC); + lua_setfield(l, -2, "__gc"); + lua_newtable(l); + struct luaL_Reg tcpSocketIndexMethods[] = { + { "connect", LuaTCPSocket::Connect }, + { "close", LuaTCPSocket::Close }, + { "send", LuaTCPSocket::Send }, + { "receive", LuaTCPSocket::Receive }, + { "lasterror", LuaTCPSocket::LastError }, + { "status", LuaTCPSocket::GetStatus }, + { "getpeername", LuaTCPSocket::GetPeerName }, + { "getsockname", LuaTCPSocket::GetSockName }, + { "settimeout", LuaTCPSocket::SetTimeout }, + { "setoption", LuaTCPSocket::SetOption }, + { "shutdown", LuaTCPSocket::Shutdown }, + { NULL, NULL }, + }; + luaL_register(l, NULL, tcpSocketIndexMethods); + lua_setfield(l, -2, "__index"); + lua_pop(l, 1); +#endif + lua_newtable(l); + struct luaL_Reg socketMethods[] = { +#ifndef NOHTTP + { "tcp", LuaTCPSocket::New }, +#endif + { "sleep", LuaTCPSocket::Sleep }, + { "gettime", LuaTCPSocket::GetTime }, + { NULL, NULL }, + }; + luaL_register(l, NULL, socketMethods); + lua_setglobal(l, "socket"); + } +} diff --git a/src/lua/LuaTCPSocket.h b/src/lua/LuaTCPSocket.h new file mode 100644 index 000000000..93d87fac5 --- /dev/null +++ b/src/lua/LuaTCPSocket.h @@ -0,0 +1,10 @@ +#pragma once + +#include "Config.h" + +#include "LuaCompat.h" + +namespace LuaTCPSocket +{ + void Open(lua_State *l); +} diff --git a/src/lua/luasocket/LICENSE b/src/lua/luasocket/LICENSE deleted file mode 100644 index b63545107..000000000 --- a/src/lua/luasocket/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -LuaSocket 3.0 license -Copyright © 2004-2013 Diego Nehab - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/src/lua/luasocket/auxiliar.c b/src/lua/luasocket/auxiliar.c deleted file mode 100644 index 93a66a09f..000000000 --- a/src/lua/luasocket/auxiliar.c +++ /dev/null @@ -1,154 +0,0 @@ -/*=========================================================================*\ -* Auxiliar routines for class hierarchy manipulation -* LuaSocket toolkit -\*=========================================================================*/ -#include "luasocket.h" -#include "auxiliar.h" -#include -#include - -/*-------------------------------------------------------------------------*\ -* Initializes the module -\*-------------------------------------------------------------------------*/ -int auxiliar_open(lua_State *L) { - (void) L; - return 0; -} - -/*-------------------------------------------------------------------------*\ -* Creates a new class with given methods -* Methods whose names start with __ are passed directly to the metatable. -\*-------------------------------------------------------------------------*/ -void auxiliar_newclass(lua_State *L, const char *classname, luaL_Reg *func) { - luaL_newmetatable(L, classname); /* mt */ - /* create __index table to place methods */ - lua_pushstring(L, "__index"); /* mt,"__index" */ - lua_newtable(L); /* mt,"__index",it */ - /* put class name into class metatable */ - lua_pushstring(L, "class"); /* mt,"__index",it,"class" */ - lua_pushstring(L, classname); /* mt,"__index",it,"class",classname */ - lua_rawset(L, -3); /* mt,"__index",it */ - /* pass all methods that start with _ to the metatable, and all others - * to the index table */ - for (; func->name; func++) { /* mt,"__index",it */ - lua_pushstring(L, func->name); - lua_pushcfunction(L, func->func); - lua_rawset(L, func->name[0] == '_' ? -5: -3); - } - lua_rawset(L, -3); /* mt */ - lua_pop(L, 1); -} - -/*-------------------------------------------------------------------------*\ -* Prints the value of a class in a nice way -\*-------------------------------------------------------------------------*/ -int auxiliar_tostring(lua_State *L) { - char buf[32]; - if (!lua_getmetatable(L, 1)) goto error; - lua_pushstring(L, "__index"); - lua_gettable(L, -2); - if (!lua_istable(L, -1)) goto error; - lua_pushstring(L, "class"); - lua_gettable(L, -2); - if (!lua_isstring(L, -1)) goto error; - sprintf(buf, "%p", lua_touserdata(L, 1)); - lua_pushfstring(L, "%s: %s", lua_tostring(L, -1), buf); - return 1; -error: - lua_pushstring(L, "invalid object passed to 'auxiliar.c:__tostring'"); - lua_error(L); - return 1; -} - -/*-------------------------------------------------------------------------*\ -* Insert class into group -\*-------------------------------------------------------------------------*/ -void auxiliar_add2group(lua_State *L, const char *classname, const char *groupname) { - luaL_getmetatable(L, classname); - lua_pushstring(L, groupname); - lua_pushboolean(L, 1); - lua_rawset(L, -3); - lua_pop(L, 1); -} - -/*-------------------------------------------------------------------------*\ -* Make sure argument is a boolean -\*-------------------------------------------------------------------------*/ -int auxiliar_checkboolean(lua_State *L, int objidx) { - if (!lua_isboolean(L, objidx)) - auxiliar_typeerror(L, objidx, lua_typename(L, LUA_TBOOLEAN)); - return lua_toboolean(L, objidx); -} - -/*-------------------------------------------------------------------------*\ -* Return userdata pointer if object belongs to a given class, abort with -* error otherwise -\*-------------------------------------------------------------------------*/ -void *auxiliar_checkclass(lua_State *L, const char *classname, int objidx) { - void *data = auxiliar_getclassudata(L, classname, objidx); - if (!data) { - char msg[45]; - sprintf(msg, "%.35s expected", classname); - luaL_argerror(L, objidx, msg); - } - return data; -} - -/*-------------------------------------------------------------------------*\ -* Return userdata pointer if object belongs to a given group, abort with -* error otherwise -\*-------------------------------------------------------------------------*/ -void *auxiliar_checkgroup(lua_State *L, const char *groupname, int objidx) { - void *data = auxiliar_getgroupudata(L, groupname, objidx); - if (!data) { - char msg[45]; - sprintf(msg, "%.35s expected", groupname); - luaL_argerror(L, objidx, msg); - } - return data; -} - -/*-------------------------------------------------------------------------*\ -* Set object class -\*-------------------------------------------------------------------------*/ -void auxiliar_setclass(lua_State *L, const char *classname, int objidx) { - luaL_getmetatable(L, classname); - if (objidx < 0) objidx--; - lua_setmetatable(L, objidx); -} - -/*-------------------------------------------------------------------------*\ -* Get a userdata pointer if object belongs to a given group. Return NULL -* otherwise -\*-------------------------------------------------------------------------*/ -void *auxiliar_getgroupudata(lua_State *L, const char *groupname, int objidx) { - if (!lua_getmetatable(L, objidx)) - return NULL; - lua_pushstring(L, groupname); - lua_rawget(L, -2); - if (lua_isnil(L, -1)) { - lua_pop(L, 2); - return NULL; - } else { - lua_pop(L, 2); - return lua_touserdata(L, objidx); - } -} - -/*-------------------------------------------------------------------------*\ -* Get a userdata pointer if object belongs to a given class. Return NULL -* otherwise -\*-------------------------------------------------------------------------*/ -void *auxiliar_getclassudata(lua_State *L, const char *classname, int objidx) { - return luaL_testudata(L, objidx, classname); -} - -/*-------------------------------------------------------------------------*\ -* Throws error when argument does not have correct type. -* Used to be part of lauxlib in Lua 5.1, was dropped from 5.2. -\*-------------------------------------------------------------------------*/ -int auxiliar_typeerror (lua_State *L, int narg, const char *tname) { - const char *msg = lua_pushfstring(L, "%s expected, got %s", tname, - luaL_typename(L, narg)); - return luaL_argerror(L, narg, msg); -} diff --git a/src/lua/luasocket/auxiliar.h b/src/lua/luasocket/auxiliar.h deleted file mode 100644 index e8c3ead82..000000000 --- a/src/lua/luasocket/auxiliar.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef AUXILIAR_H -#define AUXILIAR_H -/*=========================================================================*\ -* Auxiliar routines for class hierarchy manipulation -* LuaSocket toolkit (but completely independent of other LuaSocket modules) -* -* A LuaSocket class is a name associated with Lua metatables. A LuaSocket -* group is a name associated with a class. A class can belong to any number -* of groups. This module provides the functionality to: -* -* - create new classes -* - add classes to groups -* - set the class of objects -* - check if an object belongs to a given class or group -* - get the userdata associated to objects -* - print objects in a pretty way -* -* LuaSocket class names follow the convention {}. Modules -* can define any number of classes and groups. The module tcp.c, for -* example, defines the classes tcp{master}, tcp{client} and tcp{server} and -* the groups tcp{client,server} and tcp{any}. Module functions can then -* perform type-checking on their arguments by either class or group. -* -* LuaSocket metatables define the __index metamethod as being a table. This -* table has one field for each method supported by the class, and a field -* "class" with the class name. -* -* The mapping from class name to the corresponding metatable and the -* reverse mapping are done using lauxlib. -\*=========================================================================*/ - -#include "luasocket.h" - -#ifndef _WIN32 -#pragma GCC visibility push(hidden) -#endif - -int auxiliar_open(lua_State *L); -void auxiliar_newclass(lua_State *L, const char *classname, luaL_Reg *func); -int auxiliar_tostring(lua_State *L); -void auxiliar_add2group(lua_State *L, const char *classname, const char *group); -int auxiliar_checkboolean(lua_State *L, int objidx); -void *auxiliar_checkclass(lua_State *L, const char *classname, int objidx); -void *auxiliar_checkgroup(lua_State *L, const char *groupname, int objidx); -void auxiliar_setclass(lua_State *L, const char *classname, int objidx); -void *auxiliar_getgroupudata(lua_State *L, const char *groupname, int objidx); -void *auxiliar_getclassudata(lua_State *L, const char *groupname, int objidx); -int auxiliar_typeerror(lua_State *L, int narg, const char *tname); - -#ifndef _WIN32 -#pragma GCC visibility pop -#endif - -#endif /* AUXILIAR_H */ diff --git a/src/lua/luasocket/buffer.c b/src/lua/luasocket/buffer.c deleted file mode 100644 index ac5c53176..000000000 --- a/src/lua/luasocket/buffer.c +++ /dev/null @@ -1,270 +0,0 @@ -/*=========================================================================*\ -* Input/Output interface for Lua programs -* LuaSocket toolkit -\*=========================================================================*/ -#include "luasocket.h" -#include "buffer.h" - -/*=========================================================================*\ -* Internal function prototypes -\*=========================================================================*/ -static int recvraw(p_buffer buf, size_t wanted, luaL_Buffer *b); -static int recvline(p_buffer buf, luaL_Buffer *b); -static int recvall(p_buffer buf, luaL_Buffer *b); -static int buffer_get(p_buffer buf, const char **data, size_t *count); -static void buffer_skip(p_buffer buf, size_t count); -static int sendraw(p_buffer buf, const char *data, size_t count, size_t *sent); - -/* min and max macros */ -#ifndef MIN -#define MIN(x, y) ((x) < (y) ? x : y) -#endif -#ifndef MAX -#define MAX(x, y) ((x) > (y) ? x : y) -#endif - -/*=========================================================================*\ -* Exported functions -\*=========================================================================*/ -/*-------------------------------------------------------------------------*\ -* Initializes module -\*-------------------------------------------------------------------------*/ -int buffer_open(lua_State *L) { - (void) L; - return 0; -} - -/*-------------------------------------------------------------------------*\ -* Initializes C structure -\*-------------------------------------------------------------------------*/ -void buffer_init(p_buffer buf, p_io io, p_timeout tm) { - buf->first = buf->last = 0; - buf->io = io; - buf->tm = tm; - buf->received = buf->sent = 0; - buf->birthday = timeout_gettime(); -} - -/*-------------------------------------------------------------------------*\ -* object:getstats() interface -\*-------------------------------------------------------------------------*/ -int buffer_meth_getstats(lua_State *L, p_buffer buf) { - lua_pushnumber(L, (lua_Number) buf->received); - lua_pushnumber(L, (lua_Number) buf->sent); - lua_pushnumber(L, timeout_gettime() - buf->birthday); - return 3; -} - -/*-------------------------------------------------------------------------*\ -* object:setstats() interface -\*-------------------------------------------------------------------------*/ -int buffer_meth_setstats(lua_State *L, p_buffer buf) { - buf->received = (long) luaL_optnumber(L, 2, (lua_Number) buf->received); - buf->sent = (long) luaL_optnumber(L, 3, (lua_Number) buf->sent); - if (lua_isnumber(L, 4)) buf->birthday = timeout_gettime() - lua_tonumber(L, 4); - lua_pushnumber(L, 1); - return 1; -} - -/*-------------------------------------------------------------------------*\ -* object:send() interface -\*-------------------------------------------------------------------------*/ -int buffer_meth_send(lua_State *L, p_buffer buf) { - int top = lua_gettop(L); - int err = IO_DONE; - size_t size = 0, sent = 0; - const char *data = luaL_checklstring(L, 2, &size); - long start = (long) luaL_optnumber(L, 3, 1); - long end = (long) luaL_optnumber(L, 4, -1); - timeout_markstart(buf->tm); - if (start < 0) start = (long) (size+start+1); - if (end < 0) end = (long) (size+end+1); - if (start < 1) start = (long) 1; - if (end > (long) size) end = (long) size; - if (start <= end) err = sendraw(buf, data+start-1, end-start+1, &sent); - /* check if there was an error */ - if (err != IO_DONE) { - lua_pushnil(L); - lua_pushstring(L, buf->io->error(buf->io->ctx, err)); - lua_pushnumber(L, (lua_Number) (sent+start-1)); - } else { - lua_pushnumber(L, (lua_Number) (sent+start-1)); - lua_pushnil(L); - lua_pushnil(L); - } -#ifdef LUASOCKET_DEBUG - /* push time elapsed during operation as the last return value */ - lua_pushnumber(L, timeout_gettime() - timeout_getstart(buf->tm)); -#endif - return lua_gettop(L) - top; -} - -/*-------------------------------------------------------------------------*\ -* object:receive() interface -\*-------------------------------------------------------------------------*/ -int buffer_meth_receive(lua_State *L, p_buffer buf) { - int err = IO_DONE, top = lua_gettop(L); - luaL_Buffer b; - size_t size; - const char *part = luaL_optlstring(L, 3, "", &size); - timeout_markstart(buf->tm); - /* initialize buffer with optional extra prefix - * (useful for concatenating previous partial results) */ - luaL_buffinit(L, &b); - luaL_addlstring(&b, part, size); - /* receive new patterns */ - if (!lua_isnumber(L, 2)) { - const char *p= luaL_optstring(L, 2, "*l"); - if (p[0] == '*' && p[1] == 'l') err = recvline(buf, &b); - else if (p[0] == '*' && p[1] == 'a') err = recvall(buf, &b); - else luaL_argcheck(L, 0, 2, "invalid receive pattern"); - /* get a fixed number of bytes (minus what was already partially - * received) */ - } else { - double n = lua_tonumber(L, 2); - size_t wanted = (size_t) n; - luaL_argcheck(L, n >= 0, 2, "invalid receive pattern"); - if (size == 0 || wanted > size) - err = recvraw(buf, wanted-size, &b); - } - /* check if there was an error */ - if (err != IO_DONE) { - /* we can't push anyting in the stack before pushing the - * contents of the buffer. this is the reason for the complication */ - luaL_pushresult(&b); - lua_pushstring(L, buf->io->error(buf->io->ctx, err)); - lua_pushvalue(L, -2); - lua_pushnil(L); - lua_replace(L, -4); - } else { - luaL_pushresult(&b); - lua_pushnil(L); - lua_pushnil(L); - } -#ifdef LUASOCKET_DEBUG - /* push time elapsed during operation as the last return value */ - lua_pushnumber(L, timeout_gettime() - timeout_getstart(buf->tm)); -#endif - return lua_gettop(L) - top; -} - -/*-------------------------------------------------------------------------*\ -* Determines if there is any data in the read buffer -\*-------------------------------------------------------------------------*/ -int buffer_isempty(p_buffer buf) { - return buf->first >= buf->last; -} - -/*=========================================================================*\ -* Internal functions -\*=========================================================================*/ -/*-------------------------------------------------------------------------*\ -* Sends a block of data (unbuffered) -\*-------------------------------------------------------------------------*/ -#define STEPSIZE 8192 -static int sendraw(p_buffer buf, const char *data, size_t count, size_t *sent) { - p_io io = buf->io; - p_timeout tm = buf->tm; - size_t total = 0; - int err = IO_DONE; - while (total < count && err == IO_DONE) { - size_t done = 0; - size_t step = (count-total <= STEPSIZE)? count-total: STEPSIZE; - err = io->send(io->ctx, data+total, step, &done, tm); - total += done; - } - *sent = total; - buf->sent += total; - return err; -} - -/*-------------------------------------------------------------------------*\ -* Reads a fixed number of bytes (buffered) -\*-------------------------------------------------------------------------*/ -static int recvraw(p_buffer buf, size_t wanted, luaL_Buffer *b) { - int err = IO_DONE; - size_t total = 0; - while (err == IO_DONE) { - size_t count; const char *data; - err = buffer_get(buf, &data, &count); - count = MIN(count, wanted - total); - luaL_addlstring(b, data, count); - buffer_skip(buf, count); - total += count; - if (total >= wanted) break; - } - return err; -} - -/*-------------------------------------------------------------------------*\ -* Reads everything until the connection is closed (buffered) -\*-------------------------------------------------------------------------*/ -static int recvall(p_buffer buf, luaL_Buffer *b) { - int err = IO_DONE; - size_t total = 0; - while (err == IO_DONE) { - const char *data; size_t count; - err = buffer_get(buf, &data, &count); - total += count; - luaL_addlstring(b, data, count); - buffer_skip(buf, count); - } - if (err == IO_CLOSED) { - if (total > 0) return IO_DONE; - else return IO_CLOSED; - } else return err; -} - -/*-------------------------------------------------------------------------*\ -* Reads a line terminated by a CR LF pair or just by a LF. The CR and LF -* are not returned by the function and are discarded from the buffer -\*-------------------------------------------------------------------------*/ -static int recvline(p_buffer buf, luaL_Buffer *b) { - int err = IO_DONE; - while (err == IO_DONE) { - size_t count, pos; const char *data; - err = buffer_get(buf, &data, &count); - pos = 0; - while (pos < count && data[pos] != '\n') { - /* we ignore all \r's */ - if (data[pos] != '\r') luaL_addchar(b, data[pos]); - pos++; - } - if (pos < count) { /* found '\n' */ - buffer_skip(buf, pos+1); /* skip '\n' too */ - break; /* we are done */ - } else /* reached the end of the buffer */ - buffer_skip(buf, pos); - } - return err; -} - -/*-------------------------------------------------------------------------*\ -* Skips a given number of bytes from read buffer. No data is read from the -* transport layer -\*-------------------------------------------------------------------------*/ -static void buffer_skip(p_buffer buf, size_t count) { - buf->received += count; - buf->first += count; - if (buffer_isempty(buf)) - buf->first = buf->last = 0; -} - -/*-------------------------------------------------------------------------*\ -* Return any data available in buffer, or get more data from transport layer -* if buffer is empty -\*-------------------------------------------------------------------------*/ -static int buffer_get(p_buffer buf, const char **data, size_t *count) { - int err = IO_DONE; - p_io io = buf->io; - p_timeout tm = buf->tm; - if (buffer_isempty(buf)) { - size_t got; - err = io->recv(io->ctx, buf->data, BUF_SIZE, &got, tm); - buf->first = 0; - buf->last = got; - } - *count = buf->last - buf->first; - *data = buf->data + buf->first; - return err; -} diff --git a/src/lua/luasocket/buffer.h b/src/lua/luasocket/buffer.h deleted file mode 100644 index a0901fcc8..000000000 --- a/src/lua/luasocket/buffer.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef BUF_H -#define BUF_H -/*=========================================================================*\ -* Input/Output interface for Lua programs -* LuaSocket toolkit -* -* Line patterns require buffering. Reading one character at a time involves -* too many system calls and is very slow. This module implements the -* LuaSocket interface for input/output on connected objects, as seen by -* Lua programs. -* -* Input is buffered. Output is *not* buffered because there was no simple -* way of making sure the buffered output data would ever be sent. -* -* The module is built on top of the I/O abstraction defined in io.h and the -* timeout management is done with the timeout.h interface. -\*=========================================================================*/ -#include "luasocket.h" -#include "io.h" -#include "timeout.h" - -/* buffer size in bytes */ -#define BUF_SIZE 8192 - -/* buffer control structure */ -typedef struct t_buffer_ { - double birthday; /* throttle support info: creation time, */ - size_t sent, received; /* bytes sent, and bytes received */ - p_io io; /* IO driver used for this buffer */ - p_timeout tm; /* timeout management for this buffer */ - size_t first, last; /* index of first and last bytes of stored data */ - char data[BUF_SIZE]; /* storage space for buffer data */ -} t_buffer; -typedef t_buffer *p_buffer; - -#ifndef _WIN32 -#pragma GCC visibility push(hidden) -#endif - -int buffer_open(lua_State *L); -void buffer_init(p_buffer buf, p_io io, p_timeout tm); -int buffer_meth_getstats(lua_State *L, p_buffer buf); -int buffer_meth_setstats(lua_State *L, p_buffer buf); -int buffer_meth_send(lua_State *L, p_buffer buf); -int buffer_meth_receive(lua_State *L, p_buffer buf); -int buffer_isempty(p_buffer buf); - -#ifndef _WIN32 -#pragma GCC visibility pop -#endif - -#endif /* BUF_H */ diff --git a/src/lua/luasocket/compat.c b/src/lua/luasocket/compat.c deleted file mode 100644 index 34ffdaf71..000000000 --- a/src/lua/luasocket/compat.c +++ /dev/null @@ -1,39 +0,0 @@ -#include "luasocket.h" -#include "compat.h" - -#if LUA_VERSION_NUM==501 - -/* -** Adapted from Lua 5.2 -*/ -void luasocket_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { - luaL_checkstack(L, nup+1, "too many upvalues"); - for (; l->name != NULL; l++) { /* fill the table with given functions */ - int i; - lua_pushstring(L, l->name); - for (i = 0; i < nup; i++) /* copy upvalues to the top */ - lua_pushvalue(L, -(nup+1)); - lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ - lua_settable(L, -(nup + 3)); - } - lua_pop(L, nup); /* remove upvalues */ -} - -/* -** Duplicated from Lua 5.2 -*/ -void *luasocket_testudata (lua_State *L, int ud, const char *tname) { - void *p = lua_touserdata(L, ud); - if (p != NULL) { /* value is a userdata? */ - if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ - luaL_getmetatable(L, tname); /* get correct metatable */ - if (!lua_rawequal(L, -1, -2)) /* not the same? */ - p = NULL; /* value is a userdata with wrong metatable */ - lua_pop(L, 2); /* remove both metatables */ - return p; - } - } - return NULL; /* value is not a userdata with a metatable */ -} - -#endif diff --git a/src/lua/luasocket/compat.h b/src/lua/luasocket/compat.h deleted file mode 100644 index fa2d7d7c6..000000000 --- a/src/lua/luasocket/compat.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef COMPAT_H -#define COMPAT_H - -#if LUA_VERSION_NUM==501 - -#ifndef _WIN32 -#pragma GCC visibility push(hidden) -#endif - -void luasocket_setfuncs (lua_State *L, const luaL_Reg *l, int nup); -void *luasocket_testudata ( lua_State *L, int arg, const char *tname); - -#ifndef _WIN32 -#pragma GCC visibility pop -#endif - -#define luaL_setfuncs luasocket_setfuncs -#define luaL_testudata luasocket_testudata - -#endif - -#endif diff --git a/src/lua/luasocket/except.c b/src/lua/luasocket/except.c deleted file mode 100644 index 9c3317f26..000000000 --- a/src/lua/luasocket/except.c +++ /dev/null @@ -1,129 +0,0 @@ -/*=========================================================================*\ -* Simple exception support -* LuaSocket toolkit -\*=========================================================================*/ -#include "luasocket.h" -#include "except.h" -#include - -#if LUA_VERSION_NUM < 502 -#define lua_pcallk(L, na, nr, err, ctx, cont) \ - (((void)ctx),((void)cont),lua_pcall(L, na, nr, err)) -#endif - -#if LUA_VERSION_NUM < 503 -typedef int lua_KContext; -#endif - -/*=========================================================================*\ -* Internal function prototypes. -\*=========================================================================*/ -static int global_protect(lua_State *L); -static int global_newtry(lua_State *L); -static int protected_(lua_State *L); -static int finalize(lua_State *L); -static int do_nothing(lua_State *L); - -/* except functions */ -static luaL_Reg func[] = { - {"newtry", global_newtry}, - {"protect", global_protect}, - {NULL, NULL} -}; - -/*-------------------------------------------------------------------------*\ -* Try factory -\*-------------------------------------------------------------------------*/ -static void wrap(lua_State *L) { - lua_createtable(L, 1, 0); - lua_pushvalue(L, -2); - lua_rawseti(L, -2, 1); - lua_pushvalue(L, lua_upvalueindex(1)); - lua_setmetatable(L, -2); -} - -static int finalize(lua_State *L) { - if (!lua_toboolean(L, 1)) { - lua_pushvalue(L, lua_upvalueindex(2)); - lua_call(L, 0, 0); - lua_settop(L, 2); - wrap(L); - lua_error(L); - return 0; - } else return lua_gettop(L); -} - -static int do_nothing(lua_State *L) { - (void) L; - return 0; -} - -static int global_newtry(lua_State *L) { - lua_settop(L, 1); - if (lua_isnil(L, 1)) lua_pushcfunction(L, do_nothing); - lua_pushvalue(L, lua_upvalueindex(1)); - lua_insert(L, -2); - lua_pushcclosure(L, finalize, 2); - return 1; -} - -/*-------------------------------------------------------------------------*\ -* Protect factory -\*-------------------------------------------------------------------------*/ -static int unwrap(lua_State *L) { - if (lua_istable(L, -1) && lua_getmetatable(L, -1)) { - int r = lua_rawequal(L, -1, lua_upvalueindex(1)); - lua_pop(L, 1); - if (r) { - lua_pushnil(L); - lua_rawgeti(L, -2, 1); - return 1; - } - } - return 0; -} - -static int protected_finish(lua_State *L, int status, lua_KContext ctx) { - (void)ctx; - if (status != 0 && status != LUA_YIELD) { - if (unwrap(L)) return 2; - else return lua_error(L); - } else return lua_gettop(L); -} - -#if LUA_VERSION_NUM == 502 -static int protected_cont(lua_State *L) { - int ctx = 0; - int status = lua_getctx(L, &ctx); - return protected_finish(L, status, ctx); -} -#else -#define protected_cont protected_finish -#endif - -static int protected_(lua_State *L) { - int status; - lua_pushvalue(L, lua_upvalueindex(2)); - lua_insert(L, 1); - status = lua_pcallk(L, lua_gettop(L) - 1, LUA_MULTRET, 0, 0, protected_cont); - return protected_finish(L, status, 0); -} - -static int global_protect(lua_State *L) { - lua_settop(L, 1); - lua_pushvalue(L, lua_upvalueindex(1)); - lua_insert(L, 1); - lua_pushcclosure(L, protected_, 2); - return 1; -} - -/*-------------------------------------------------------------------------*\ -* Init module -\*-------------------------------------------------------------------------*/ -int except_open(lua_State *L) { - lua_newtable(L); /* metatable for wrapped exceptions */ - lua_pushboolean(L, 0); - lua_setfield(L, -2, "__metatable"); - luaL_setfuncs(L, func, 1); - return 0; -} diff --git a/src/lua/luasocket/except.h b/src/lua/luasocket/except.h deleted file mode 100644 index 71c31fd4d..000000000 --- a/src/lua/luasocket/except.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef EXCEPT_H -#define EXCEPT_H -/*=========================================================================*\ -* Exception control -* LuaSocket toolkit (but completely independent from other modules) -* -* This provides support for simple exceptions in Lua. During the -* development of the HTTP/FTP/SMTP support, it became aparent that -* error checking was taking a substantial amount of the coding. These -* function greatly simplify the task of checking errors. -* -* The main idea is that functions should return nil as their first return -* values when they find an error, and return an error message (or value) -* following nil. In case of success, as long as the first value is not nil, -* the other values don't matter. -* -* The idea is to nest function calls with the "try" function. This function -* checks the first value, and, if it's falsy, wraps the second value in a -* table with metatable and calls "error" on it. Otherwise, it returns all -* values it received. Basically, it works like the Lua "assert" function, -* but it creates errors targeted specifically at "protect". -* -* The "newtry" function is a factory for "try" functions that call a -* finalizer in protected mode before calling "error". -* -* The "protect" function returns a new function that behaves exactly like -* the function it receives, but the new function catches exceptions thrown -* by "try" functions and returns nil followed by the error message instead. -* -* With these three functions, it's easy to write functions that throw -* exceptions on error, but that don't interrupt the user script. -\*=========================================================================*/ - -#include "luasocket.h" - -#ifndef _WIN32 -#pragma GCC visibility push(hidden) -#endif - -int except_open(lua_State *L); - -#ifndef _WIN32 -#pragma GCC visibility pop -#endif - -#endif diff --git a/src/lua/luasocket/inet.c b/src/lua/luasocket/inet.c deleted file mode 100644 index ec73feadc..000000000 --- a/src/lua/luasocket/inet.c +++ /dev/null @@ -1,537 +0,0 @@ -/*=========================================================================*\ -* Internet domain functions -* LuaSocket toolkit -\*=========================================================================*/ -#include "luasocket.h" -#include "inet.h" - -#include -#include -#include - -/*=========================================================================*\ -* Internal function prototypes. -\*=========================================================================*/ -static int inet_global_toip(lua_State *L); -static int inet_global_getaddrinfo(lua_State *L); -static int inet_global_tohostname(lua_State *L); -static int inet_global_getnameinfo(lua_State *L); -static void inet_pushresolved(lua_State *L, struct hostent *hp); -static int inet_global_gethostname(lua_State *L); - -/* DNS functions */ -static luaL_Reg func[] = { - { "toip", inet_global_toip}, - { "getaddrinfo", inet_global_getaddrinfo}, - { "tohostname", inet_global_tohostname}, - { "getnameinfo", inet_global_getnameinfo}, - { "gethostname", inet_global_gethostname}, - { NULL, NULL} -}; - -/*-------------------------------------------------------------------------*\ -* Initializes module -\*-------------------------------------------------------------------------*/ -int inet_open(lua_State *L) -{ - lua_pushstring(L, "dns"); - lua_newtable(L); - luaL_setfuncs(L, func, 0); - lua_settable(L, -3); - return 0; -} - -/*=========================================================================*\ -* Global Lua functions -\*=========================================================================*/ -/*-------------------------------------------------------------------------*\ -* Returns all information provided by the resolver given a host name -* or ip address -\*-------------------------------------------------------------------------*/ -static int inet_gethost(const char *address, struct hostent **hp) { - struct in_addr addr; - if (inet_aton(address, &addr)) - return socket_gethostbyaddr((char *) &addr, sizeof(addr), hp); - else - return socket_gethostbyname(address, hp); -} - -/*-------------------------------------------------------------------------*\ -* Returns all information provided by the resolver given a host name -* or ip address -\*-------------------------------------------------------------------------*/ -static int inet_global_tohostname(lua_State *L) { - const char *address = luaL_checkstring(L, 1); - struct hostent *hp = NULL; - int err = inet_gethost(address, &hp); - if (err != IO_DONE) { - lua_pushnil(L); - lua_pushstring(L, socket_hoststrerror(err)); - return 2; - } - lua_pushstring(L, hp->h_name); - inet_pushresolved(L, hp); - return 2; -} - -static int inet_global_getnameinfo(lua_State *L) { - char hbuf[NI_MAXHOST]; - char sbuf[NI_MAXSERV]; - int i, ret; - struct addrinfo hints; - struct addrinfo *resolved, *iter; - const char *host = luaL_optstring(L, 1, NULL); - const char *serv = luaL_optstring(L, 2, NULL); - - if (!(host || serv)) - luaL_error(L, "host and serv cannot be both nil"); - - memset(&hints, 0, sizeof(hints)); - hints.ai_socktype = SOCK_STREAM; - hints.ai_family = AF_UNSPEC; - - ret = getaddrinfo(host, serv, &hints, &resolved); - if (ret != 0) { - lua_pushnil(L); - lua_pushstring(L, socket_gaistrerror(ret)); - return 2; - } - - lua_newtable(L); - for (i = 1, iter = resolved; iter; i++, iter = iter->ai_next) { - getnameinfo(iter->ai_addr, (socklen_t) iter->ai_addrlen, - hbuf, host? (socklen_t) sizeof(hbuf): 0, - sbuf, serv? (socklen_t) sizeof(sbuf): 0, 0); - if (host) { - lua_pushnumber(L, i); - lua_pushstring(L, hbuf); - lua_settable(L, -3); - } - } - freeaddrinfo(resolved); - - if (serv) { - lua_pushstring(L, sbuf); - return 2; - } else { - return 1; - } -} - -/*-------------------------------------------------------------------------*\ -* Returns all information provided by the resolver given a host name -* or ip address -\*-------------------------------------------------------------------------*/ -static int inet_global_toip(lua_State *L) -{ - const char *address = luaL_checkstring(L, 1); - struct hostent *hp = NULL; - int err = inet_gethost(address, &hp); - if (err != IO_DONE) { - lua_pushnil(L); - lua_pushstring(L, socket_hoststrerror(err)); - return 2; - } - lua_pushstring(L, inet_ntoa(*((struct in_addr *) hp->h_addr))); - inet_pushresolved(L, hp); - return 2; -} - -int inet_optfamily(lua_State* L, int narg, const char* def) -{ - static const char* optname[] = { "unspec", "inet", "inet6", NULL }; - static int optvalue[] = { AF_UNSPEC, AF_INET, AF_INET6, 0 }; - - return optvalue[luaL_checkoption(L, narg, def, optname)]; -} - -int inet_optsocktype(lua_State* L, int narg, const char* def) -{ - static const char* optname[] = { "stream", "dgram", NULL }; - static int optvalue[] = { SOCK_STREAM, SOCK_DGRAM, 0 }; - - return optvalue[luaL_checkoption(L, narg, def, optname)]; -} - -static int inet_global_getaddrinfo(lua_State *L) -{ - const char *hostname = luaL_checkstring(L, 1); - struct addrinfo *iterator = NULL, *resolved = NULL; - struct addrinfo hints; - int i = 1, ret = 0; - memset(&hints, 0, sizeof(hints)); - hints.ai_socktype = SOCK_STREAM; - hints.ai_family = AF_UNSPEC; - ret = getaddrinfo(hostname, NULL, &hints, &resolved); - if (ret != 0) { - lua_pushnil(L); - lua_pushstring(L, socket_gaistrerror(ret)); - return 2; - } - lua_newtable(L); - for (iterator = resolved; iterator; iterator = iterator->ai_next) { - char hbuf[NI_MAXHOST]; - ret = getnameinfo(iterator->ai_addr, (socklen_t) iterator->ai_addrlen, - hbuf, (socklen_t) sizeof(hbuf), NULL, 0, NI_NUMERICHOST); - if (ret){ - freeaddrinfo(resolved); - lua_pushnil(L); - lua_pushstring(L, socket_gaistrerror(ret)); - return 2; - } - lua_pushnumber(L, i); - lua_newtable(L); - switch (iterator->ai_family) { - case AF_INET: - lua_pushliteral(L, "family"); - lua_pushliteral(L, "inet"); - lua_settable(L, -3); - break; - case AF_INET6: - lua_pushliteral(L, "family"); - lua_pushliteral(L, "inet6"); - lua_settable(L, -3); - break; - case AF_UNSPEC: - lua_pushliteral(L, "family"); - lua_pushliteral(L, "unspec"); - lua_settable(L, -3); - break; - default: - lua_pushliteral(L, "family"); - lua_pushliteral(L, "unknown"); - lua_settable(L, -3); - break; - } - lua_pushliteral(L, "addr"); - lua_pushstring(L, hbuf); - lua_settable(L, -3); - lua_settable(L, -3); - i++; - } - freeaddrinfo(resolved); - return 1; -} - -/*-------------------------------------------------------------------------*\ -* Gets the host name -\*-------------------------------------------------------------------------*/ -static int inet_global_gethostname(lua_State *L) -{ - char name[257]; - name[256] = '\0'; - if (gethostname(name, 256) < 0) { - lua_pushnil(L); - lua_pushstring(L, socket_strerror(errno)); - return 2; - } else { - lua_pushstring(L, name); - return 1; - } -} - -/*=========================================================================*\ -* Lua methods -\*=========================================================================*/ -/*-------------------------------------------------------------------------*\ -* Retrieves socket peer name -\*-------------------------------------------------------------------------*/ -int inet_meth_getpeername(lua_State *L, p_socket ps, int family) -{ - int err; - struct sockaddr_storage peer; - socklen_t peer_len = sizeof(peer); - char name[INET6_ADDRSTRLEN]; - char port[6]; /* 65535 = 5 bytes + 0 to terminate it */ - if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) { - lua_pushnil(L); - lua_pushstring(L, socket_strerror(errno)); - return 2; - } - err = getnameinfo((struct sockaddr *) &peer, peer_len, - name, INET6_ADDRSTRLEN, - port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); - if (err) { - lua_pushnil(L); - lua_pushstring(L, gai_strerror(err)); - return 2; - } - lua_pushstring(L, name); - lua_pushinteger(L, (int) strtol(port, (char **) NULL, 10)); - switch (family) { - case AF_INET: lua_pushliteral(L, "inet"); break; - case AF_INET6: lua_pushliteral(L, "inet6"); break; - case AF_UNSPEC: lua_pushliteral(L, "unspec"); break; - default: lua_pushliteral(L, "unknown"); break; - } - return 3; -} - -/*-------------------------------------------------------------------------*\ -* Retrieves socket local name -\*-------------------------------------------------------------------------*/ -int inet_meth_getsockname(lua_State *L, p_socket ps, int family) -{ - int err; - struct sockaddr_storage peer; - socklen_t peer_len = sizeof(peer); - char name[INET6_ADDRSTRLEN]; - char port[6]; /* 65535 = 5 bytes + 0 to terminate it */ - if (getsockname(*ps, (SA *) &peer, &peer_len) < 0) { - lua_pushnil(L); - lua_pushstring(L, socket_strerror(errno)); - return 2; - } - err=getnameinfo((struct sockaddr *)&peer, peer_len, - name, INET6_ADDRSTRLEN, port, 6, NI_NUMERICHOST | NI_NUMERICSERV); - if (err) { - lua_pushnil(L); - lua_pushstring(L, gai_strerror(err)); - return 2; - } - lua_pushstring(L, name); - lua_pushstring(L, port); - switch (family) { - case AF_INET: lua_pushliteral(L, "inet"); break; - case AF_INET6: lua_pushliteral(L, "inet6"); break; - case AF_UNSPEC: lua_pushliteral(L, "unspec"); break; - default: lua_pushliteral(L, "unknown"); break; - } - return 3; -} - -/*=========================================================================*\ -* Internal functions -\*=========================================================================*/ -/*-------------------------------------------------------------------------*\ -* Passes all resolver information to Lua as a table -\*-------------------------------------------------------------------------*/ -static void inet_pushresolved(lua_State *L, struct hostent *hp) -{ - char **alias; - struct in_addr **addr; - int i, resolved; - lua_newtable(L); resolved = lua_gettop(L); - lua_pushstring(L, "name"); - lua_pushstring(L, hp->h_name); - lua_settable(L, resolved); - lua_pushstring(L, "ip"); - lua_pushstring(L, "alias"); - i = 1; - alias = hp->h_aliases; - lua_newtable(L); - if (alias) { - while (*alias) { - lua_pushnumber(L, i); - lua_pushstring(L, *alias); - lua_settable(L, -3); - i++; alias++; - } - } - lua_settable(L, resolved); - i = 1; - lua_newtable(L); - addr = (struct in_addr **) hp->h_addr_list; - if (addr) { - while (*addr) { - lua_pushnumber(L, i); - lua_pushstring(L, inet_ntoa(**addr)); - lua_settable(L, -3); - i++; addr++; - } - } - lua_settable(L, resolved); -} - -/*-------------------------------------------------------------------------*\ -* Tries to create a new inet socket -\*-------------------------------------------------------------------------*/ -const char *inet_trycreate(p_socket ps, int family, int type, int protocol) { - const char *err = socket_strerror(socket_create(ps, family, type, protocol)); - if (err == NULL && family == AF_INET6) { - int yes = 1; - setsockopt(*ps, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&yes, sizeof(yes)); - } - return err; -} - -/*-------------------------------------------------------------------------*\ -* "Disconnects" a DGRAM socket -\*-------------------------------------------------------------------------*/ -const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm) -{ - switch (family) { - case AF_INET: { - struct sockaddr_in sin; - memset((char *) &sin, 0, sizeof(sin)); - sin.sin_family = AF_UNSPEC; - sin.sin_addr.s_addr = INADDR_ANY; - return socket_strerror(socket_connect(ps, (SA *) &sin, - sizeof(sin), tm)); - } - case AF_INET6: { - struct sockaddr_in6 sin6; - struct in6_addr addrany = IN6ADDR_ANY_INIT; - memset((char *) &sin6, 0, sizeof(sin6)); - sin6.sin6_family = AF_UNSPEC; - sin6.sin6_addr = addrany; - return socket_strerror(socket_connect(ps, (SA *) &sin6, - sizeof(sin6), tm)); - } - } - return NULL; -} - -/*-------------------------------------------------------------------------*\ -* Tries to connect to remote address (address, port) -\*-------------------------------------------------------------------------*/ -const char *inet_tryconnect(p_socket ps, int *family, const char *address, - const char *serv, p_timeout tm, struct addrinfo *connecthints) -{ - struct addrinfo *iterator = NULL, *resolved = NULL; - const char *err = NULL; - int current_family = *family; - /* try resolving */ - err = socket_gaistrerror(getaddrinfo(address, serv, - connecthints, &resolved)); - if (err != NULL) { - if (resolved) freeaddrinfo(resolved); - return err; - } - for (iterator = resolved; iterator; iterator = iterator->ai_next) { - timeout_markstart(tm); - /* create new socket if necessary. if there was no - * bind, we need to create one for every new family - * that shows up while iterating. if there was a - * bind, all families will be the same and we will - * not enter this branch. */ - if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) { - socket_destroy(ps); - err = inet_trycreate(ps, iterator->ai_family, - iterator->ai_socktype, iterator->ai_protocol); - if (err) continue; - current_family = iterator->ai_family; - /* set non-blocking before connect */ - socket_setnonblocking(ps); - } - /* try connecting to remote address */ - err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr, - (socklen_t) iterator->ai_addrlen, tm)); - /* if success or timeout is zero, break out of loop */ - if (err == NULL || timeout_iszero(tm)) { - *family = current_family; - break; - } - } - freeaddrinfo(resolved); - /* here, if err is set, we failed */ - return err; -} - -/*-------------------------------------------------------------------------*\ -* Tries to accept a socket -\*-------------------------------------------------------------------------*/ -const char *inet_tryaccept(p_socket server, int family, p_socket client, - p_timeout tm) { - socklen_t len; - t_sockaddr_storage addr; - switch (family) { - case AF_INET6: len = sizeof(struct sockaddr_in6); break; - case AF_INET: len = sizeof(struct sockaddr_in); break; - default: len = sizeof(addr); break; - } - return socket_strerror(socket_accept(server, client, (SA *) &addr, - &len, tm)); -} - -/*-------------------------------------------------------------------------*\ -* Tries to bind socket to (address, port) -\*-------------------------------------------------------------------------*/ -const char *inet_trybind(p_socket ps, int *family, const char *address, - const char *serv, struct addrinfo *bindhints) { - struct addrinfo *iterator = NULL, *resolved = NULL; - const char *err = NULL; - int current_family = *family; - /* translate luasocket special values to C */ - if (strcmp(address, "*") == 0) address = NULL; - if (!serv) serv = "0"; - /* try resolving */ - err = socket_gaistrerror(getaddrinfo(address, serv, bindhints, &resolved)); - if (err) { - if (resolved) freeaddrinfo(resolved); - return err; - } - /* iterate over resolved addresses until one is good */ - for (iterator = resolved; iterator; iterator = iterator->ai_next) { - if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) { - socket_destroy(ps); - err = inet_trycreate(ps, iterator->ai_family, - iterator->ai_socktype, iterator->ai_protocol); - if (err) continue; - current_family = iterator->ai_family; - } - /* try binding to local address */ - err = socket_strerror(socket_bind(ps, (SA *) iterator->ai_addr, - (socklen_t) iterator->ai_addrlen)); - /* keep trying unless bind succeeded */ - if (err == NULL) { - *family = current_family; - /* set to non-blocking after bind */ - socket_setnonblocking(ps); - break; - } - } - /* cleanup and return error */ - freeaddrinfo(resolved); - /* here, if err is set, we failed */ - return err; -} - -/*-------------------------------------------------------------------------*\ -* Some systems do not provide these so that we provide our own. -\*-------------------------------------------------------------------------*/ -#ifdef LUASOCKET_INET_ATON -int inet_aton(const char *cp, struct in_addr *inp) -{ - unsigned int a = 0, b = 0, c = 0, d = 0; - int n = 0, r; - unsigned long int addr = 0; - r = sscanf(cp, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n); - if (r == 0 || n == 0) return 0; - cp += n; - if (*cp) return 0; - if (a > 255 || b > 255 || c > 255 || d > 255) return 0; - if (inp) { - addr += a; addr <<= 8; - addr += b; addr <<= 8; - addr += c; addr <<= 8; - addr += d; - inp->s_addr = htonl(addr); - } - return 1; -} -#endif - -#ifdef LUASOCKET_INET_PTON -int inet_pton(int af, const char *src, void *dst) -{ - struct addrinfo hints, *res; - int ret = 1; - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = af; - hints.ai_flags = AI_NUMERICHOST; - if (getaddrinfo(src, NULL, &hints, &res) != 0) return -1; - if (af == AF_INET) { - struct sockaddr_in *in = (struct sockaddr_in *) res->ai_addr; - memcpy(dst, &in->sin_addr, sizeof(in->sin_addr)); - } else if (af == AF_INET6) { - struct sockaddr_in6 *in = (struct sockaddr_in6 *) res->ai_addr; - memcpy(dst, &in->sin6_addr, sizeof(in->sin6_addr)); - } else { - ret = -1; - } - freeaddrinfo(res); - return ret; -} - -#endif diff --git a/src/lua/luasocket/inet.h b/src/lua/luasocket/inet.h deleted file mode 100644 index 5618b61b3..000000000 --- a/src/lua/luasocket/inet.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef INET_H -#define INET_H -/*=========================================================================*\ -* Internet domain functions -* LuaSocket toolkit -* -* This module implements the creation and connection of internet domain -* sockets, on top of the socket.h interface, and the interface of with the -* resolver. -* -* The function inet_aton is provided for the platforms where it is not -* available. The module also implements the interface of the internet -* getpeername and getsockname functions as seen by Lua programs. -* -* The Lua functions toip and tohostname are also implemented here. -\*=========================================================================*/ -#include "luasocket.h" -#include "socket.h" -#include "timeout.h" - -#ifdef _WIN32 -#define LUASOCKET_INET_ATON -#endif - -#ifndef _WIN32 -#pragma GCC visibility push(hidden) -#endif - -int inet_open(lua_State *L); - -int inet_optfamily(lua_State* L, int narg, const char* def); -int inet_optsocktype(lua_State* L, int narg, const char* def); - -int inet_meth_getpeername(lua_State *L, p_socket ps, int family); -int inet_meth_getsockname(lua_State *L, p_socket ps, int family); - -const char *inet_trycreate(p_socket ps, int family, int type, int protocol); -const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm); -const char *inet_tryconnect(p_socket ps, int *family, const char *address, const char *serv, p_timeout tm, struct addrinfo *connecthints); -const char *inet_tryaccept(p_socket server, int family, p_socket client, p_timeout tm); -const char *inet_trybind(p_socket ps, int *family, const char *address, const char *serv, struct addrinfo *bindhints); - -#ifdef LUASOCKET_INET_ATON -int inet_aton(const char *cp, struct in_addr *inp); -#endif - -#ifdef LUASOCKET_INET_PTON -const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt); -int inet_pton(int af, const char *src, void *dst); -#endif - -#ifndef _WIN32 -#pragma GCC visibility pop -#endif - -#endif /* INET_H */ diff --git a/src/lua/luasocket/io.c b/src/lua/luasocket/io.c deleted file mode 100644 index 5ad4b3afc..000000000 --- a/src/lua/luasocket/io.c +++ /dev/null @@ -1,28 +0,0 @@ -/*=========================================================================*\ -* Input/Output abstraction -* LuaSocket toolkit -\*=========================================================================*/ -#include "luasocket.h" -#include "io.h" - -/*-------------------------------------------------------------------------*\ -* Initializes C structure -\*-------------------------------------------------------------------------*/ -void io_init(p_io io, p_send send, p_recv recv, p_error error, void *ctx) { - io->send = send; - io->recv = recv; - io->error = error; - io->ctx = ctx; -} - -/*-------------------------------------------------------------------------*\ -* I/O error strings -\*-------------------------------------------------------------------------*/ -const char *io_strerror(int err) { - switch (err) { - case IO_DONE: return NULL; - case IO_CLOSED: return "closed"; - case IO_TIMEOUT: return "timeout"; - default: return "unknown error"; - } -} diff --git a/src/lua/luasocket/io.h b/src/lua/luasocket/io.h deleted file mode 100644 index b8a54df6e..000000000 --- a/src/lua/luasocket/io.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef IO_H -#define IO_H -/*=========================================================================*\ -* Input/Output abstraction -* LuaSocket toolkit -* -* This module defines the interface that LuaSocket expects from the -* transport layer for streamed input/output. The idea is that if any -* transport implements this interface, then the buffer.c functions -* automatically work on it. -* -* The module socket.h implements this interface, and thus the module tcp.h -* is very simple. -\*=========================================================================*/ -#include "luasocket.h" -#include "timeout.h" - -/* IO error codes */ -enum { - IO_DONE = 0, /* operation completed successfully */ - IO_TIMEOUT = -1, /* operation timed out */ - IO_CLOSED = -2, /* the connection has been closed */ - IO_UNKNOWN = -3 -}; - -/* interface to error message function */ -typedef const char *(*p_error) ( - void *ctx, /* context needed by send */ - int err /* error code */ -); - -/* interface to send function */ -typedef int (*p_send) ( - void *ctx, /* context needed by send */ - const char *data, /* pointer to buffer with data to send */ - size_t count, /* number of bytes to send from buffer */ - size_t *sent, /* number of bytes sent uppon return */ - p_timeout tm /* timeout control */ -); - -/* interface to recv function */ -typedef int (*p_recv) ( - void *ctx, /* context needed by recv */ - char *data, /* pointer to buffer where data will be writen */ - size_t count, /* number of bytes to receive into buffer */ - size_t *got, /* number of bytes received uppon return */ - p_timeout tm /* timeout control */ -); - -/* IO driver definition */ -typedef struct t_io_ { - void *ctx; /* context needed by send/recv */ - p_send send; /* send function pointer */ - p_recv recv; /* receive function pointer */ - p_error error; /* strerror function */ -} t_io; -typedef t_io *p_io; - -#ifndef _WIN32 -#pragma GCC visibility push(hidden) -#endif - -void io_init(p_io io, p_send send, p_recv recv, p_error error, void *ctx); -const char *io_strerror(int err); - -#ifndef _WIN32 -#pragma GCC visibility pop -#endif - -#endif /* IO_H */ diff --git a/src/lua/luasocket/luasocket.c b/src/lua/luasocket/luasocket.c deleted file mode 100644 index 0fd99f703..000000000 --- a/src/lua/luasocket/luasocket.c +++ /dev/null @@ -1,104 +0,0 @@ -/*=========================================================================*\ -* LuaSocket toolkit -* Networking support for the Lua language -* Diego Nehab -* 26/11/1999 -* -* This library is part of an effort to progressively increase the network -* connectivity of the Lua language. The Lua interface to networking -* functions follows the Sockets API closely, trying to simplify all tasks -* involved in setting up both client and server connections. The provided -* IO routines, however, follow the Lua style, being very similar to the -* standard Lua read and write functions. -\*=========================================================================*/ - -#include "luasocket.h" -#include "auxiliar.h" -#include "except.h" -#include "timeout.h" -#include "buffer.h" -#include "inet.h" -#include "tcp.h" -#include "udp.h" -#include "select.h" - -/*-------------------------------------------------------------------------*\ -* Internal function prototypes -\*-------------------------------------------------------------------------*/ -static int global_skip(lua_State *L); -static int global_unload(lua_State *L); -static int base_open(lua_State *L); - -/*-------------------------------------------------------------------------*\ -* Modules and functions -\*-------------------------------------------------------------------------*/ -static const luaL_Reg mod[] = { - {"auxiliar", auxiliar_open}, - {"except", except_open}, - {"timeout", timeout_open}, - {"buffer", buffer_open}, - {"inet", inet_open}, - {"tcp", tcp_open}, - {"udp", udp_open}, - {"select", select_open}, - {NULL, NULL} -}; - -static luaL_Reg func[] = { - {"skip", global_skip}, - {"__unload", global_unload}, - {NULL, NULL} -}; - -/*-------------------------------------------------------------------------*\ -* Skip a few arguments -\*-------------------------------------------------------------------------*/ -static int global_skip(lua_State *L) { - int amount = (int) luaL_checkinteger(L, 1); - int ret = lua_gettop(L) - amount - 1; - return ret >= 0 ? ret : 0; -} - -/*-------------------------------------------------------------------------*\ -* Unloads the library -\*-------------------------------------------------------------------------*/ -static int global_unload(lua_State *L) { - (void) L; - socket_close(); - return 0; -} - -/*-------------------------------------------------------------------------*\ -* Setup basic stuff. -\*-------------------------------------------------------------------------*/ -static int base_open(lua_State *L) { - if (socket_open()) { - /* export functions (and leave namespace table on top of stack) */ - lua_newtable(L); - luaL_setfuncs(L, func, 0); -#ifdef LUASOCKET_DEBUG - lua_pushstring(L, "_DEBUG"); - lua_pushboolean(L, 1); - lua_rawset(L, -3); -#endif - /* make version string available to scripts */ - lua_pushstring(L, "_VERSION"); - lua_pushstring(L, LUASOCKET_VERSION); - lua_rawset(L, -3); - return 1; - } else { - lua_pushstring(L, "unable to initialize library"); - lua_error(L); - return 0; - } -} - -/*-------------------------------------------------------------------------*\ -* Initializes all library modules. -\*-------------------------------------------------------------------------*/ -LUASOCKET_API int luaopen_socket_core(lua_State *L) { - int i; - base_open(L); - for (i = 0; mod[i].name; i++) mod[i].func(L); - return 1; -} diff --git a/src/lua/luasocket/luasocket.h b/src/lua/luasocket/luasocket.h deleted file mode 100644 index d22b1bead..000000000 --- a/src/lua/luasocket/luasocket.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef LUASOCKET_H -#define LUASOCKET_H -/*=========================================================================*\ -* LuaSocket toolkit -* Networking support for the Lua language -* Diego Nehab -* 9/11/1999 -\*=========================================================================*/ - -/*-------------------------------------------------------------------------* \ -* Current socket library version -\*-------------------------------------------------------------------------*/ -#define LUASOCKET_VERSION "LuaSocket 3.0-rc1" -#define LUASOCKET_COPYRIGHT "Copyright (C) 1999-2013 Diego Nehab" - -/*-------------------------------------------------------------------------*\ -* This macro prefixes all exported API functions -\*-------------------------------------------------------------------------*/ -#ifndef LUASOCKET_API -#ifdef _WIN32 -#define LUASOCKET_API __declspec(dllexport) -#else -#define LUASOCKET_API __attribute__ ((visibility ("default"))) -#endif -#endif - -#include "lua.h" -#include "lauxlib.h" -#include "compat.h" - -/*-------------------------------------------------------------------------*\ -* Initializes the library. -\*-------------------------------------------------------------------------*/ -LUASOCKET_API int luaopen_socket_core(lua_State *L); - -#endif /* LUASOCKET_H */ diff --git a/src/lua/luasocket/meson.build b/src/lua/luasocket/meson.build deleted file mode 100644 index aa86d7aa1..000000000 --- a/src/lua/luasocket/meson.build +++ /dev/null @@ -1,25 +0,0 @@ -luaconsole_files += files( - 'auxiliar.c', - 'buffer.c', - 'compat.c', - 'except.c', - 'inet.c', - 'io.c', - 'luasocket.c', - 'options.c', - 'select.c', - 'tcp.c', - 'timeout.c', - 'udp.c', -) -luaconsole_files += to_array.process('socket.lua', extra_args: 'socket_lua') - -if copt_platform == 'win' - luaconsole_files += files( - 'wsocket.c', - ) -else - luaconsole_files += files( - 'usocket.c', - ) -endif diff --git a/src/lua/luasocket/options.c b/src/lua/luasocket/options.c deleted file mode 100644 index 9cf4e3efb..000000000 --- a/src/lua/luasocket/options.c +++ /dev/null @@ -1,456 +0,0 @@ -/*=========================================================================*\ -* Common option interface -* LuaSocket toolkit -\*=========================================================================*/ -#include "luasocket.h" -#include "auxiliar.h" -#include "options.h" -#include "inet.h" -#include - -/*=========================================================================*\ -* Internal functions prototypes -\*=========================================================================*/ -static int opt_setmembership(lua_State *L, p_socket ps, int level, int name); -static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name); -static int opt_setboolean(lua_State *L, p_socket ps, int level, int name); -static int opt_getboolean(lua_State *L, p_socket ps, int level, int name); -static int opt_setint(lua_State *L, p_socket ps, int level, int name); -static int opt_getint(lua_State *L, p_socket ps, int level, int name); -static int opt_set(lua_State *L, p_socket ps, int level, int name, - void *val, int len); -static int opt_get(lua_State *L, p_socket ps, int level, int name, - void *val, int* len); - -/*=========================================================================*\ -* Exported functions -\*=========================================================================*/ -/*-------------------------------------------------------------------------*\ -* Calls appropriate option handler -\*-------------------------------------------------------------------------*/ -int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps) -{ - const char *name = luaL_checkstring(L, 2); /* obj, name, ... */ - while (opt->name && strcmp(name, opt->name)) - opt++; - if (!opt->func) { - char msg[57]; - sprintf(msg, "unsupported option `%.35s'", name); - luaL_argerror(L, 2, msg); - } - return opt->func(L, ps); -} - -int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps) -{ - const char *name = luaL_checkstring(L, 2); /* obj, name, ... */ - while (opt->name && strcmp(name, opt->name)) - opt++; - if (!opt->func) { - char msg[57]; - sprintf(msg, "unsupported option `%.35s'", name); - luaL_argerror(L, 2, msg); - } - return opt->func(L, ps); -} - -// ------------------------------------------------------- -/* enables reuse of local address */ -int opt_set_reuseaddr(lua_State *L, p_socket ps) -{ - return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEADDR); -} - -int opt_get_reuseaddr(lua_State *L, p_socket ps) -{ - return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEADDR); -} - -// ------------------------------------------------------- -/* enables reuse of local port */ -int opt_set_reuseport(lua_State *L, p_socket ps) -{ - return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEPORT); -} - -int opt_get_reuseport(lua_State *L, p_socket ps) -{ - return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEPORT); -} - -// ------------------------------------------------------- -/* disables the Nagle algorithm */ -int opt_set_tcp_nodelay(lua_State *L, p_socket ps) -{ - return opt_setboolean(L, ps, IPPROTO_TCP, TCP_NODELAY); -} - -int opt_get_tcp_nodelay(lua_State *L, p_socket ps) -{ - return opt_getboolean(L, ps, IPPROTO_TCP, TCP_NODELAY); -} - -// ------------------------------------------------------- -#ifdef TCP_KEEPIDLE - -int opt_get_tcp_keepidle(lua_State *L, p_socket ps) -{ - return opt_getint(L, ps, IPPROTO_TCP, TCP_KEEPIDLE); -} - -int opt_set_tcp_keepidle(lua_State *L, p_socket ps) -{ - return opt_setint(L, ps, IPPROTO_TCP, TCP_KEEPIDLE); -} - -#endif - -// ------------------------------------------------------- -#ifdef TCP_KEEPCNT - -int opt_get_tcp_keepcnt(lua_State *L, p_socket ps) -{ - return opt_getint(L, ps, IPPROTO_TCP, TCP_KEEPCNT); -} - -int opt_set_tcp_keepcnt(lua_State *L, p_socket ps) -{ - return opt_setint(L, ps, IPPROTO_TCP, TCP_KEEPCNT); -} - -#endif - -// ------------------------------------------------------- -#ifdef TCP_KEEPINTVL - -int opt_get_tcp_keepintvl(lua_State *L, p_socket ps) -{ - return opt_getint(L, ps, IPPROTO_TCP, TCP_KEEPINTVL); -} - -int opt_set_tcp_keepintvl(lua_State *L, p_socket ps) -{ - return opt_setint(L, ps, IPPROTO_TCP, TCP_KEEPINTVL); -} - -#endif - -// ------------------------------------------------------- -int opt_set_keepalive(lua_State *L, p_socket ps) -{ - return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE); -} - -int opt_get_keepalive(lua_State *L, p_socket ps) -{ - return opt_getboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE); -} - -// ------------------------------------------------------- -int opt_set_dontroute(lua_State *L, p_socket ps) -{ - return opt_setboolean(L, ps, SOL_SOCKET, SO_DONTROUTE); -} - -int opt_get_dontroute(lua_State *L, p_socket ps) -{ - return opt_getboolean(L, ps, SOL_SOCKET, SO_DONTROUTE); -} - -// ------------------------------------------------------- -int opt_set_broadcast(lua_State *L, p_socket ps) -{ - return opt_setboolean(L, ps, SOL_SOCKET, SO_BROADCAST); -} - -int opt_get_broadcast(lua_State *L, p_socket ps) -{ - return opt_getboolean(L, ps, SOL_SOCKET, SO_BROADCAST); -} - -// ------------------------------------------------------- -int opt_set_recv_buf_size(lua_State *L, p_socket ps) -{ - return opt_setint(L, ps, SOL_SOCKET, SO_RCVBUF); -} - -int opt_get_recv_buf_size(lua_State *L, p_socket ps) -{ - return opt_getint(L, ps, SOL_SOCKET, SO_RCVBUF); -} - -// ------------------------------------------------------- -int opt_get_send_buf_size(lua_State *L, p_socket ps) -{ - return opt_getint(L, ps, SOL_SOCKET, SO_SNDBUF); -} - -int opt_set_send_buf_size(lua_State *L, p_socket ps) -{ - return opt_setint(L, ps, SOL_SOCKET, SO_SNDBUF); -} - -// ------------------------------------------------------- -int opt_set_ip6_unicast_hops(lua_State *L, p_socket ps) -{ - return opt_setint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS); -} - -int opt_get_ip6_unicast_hops(lua_State *L, p_socket ps) -{ - return opt_getint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS); -} - -// ------------------------------------------------------- -int opt_set_ip6_multicast_hops(lua_State *L, p_socket ps) -{ - return opt_setint(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_HOPS); -} - -int opt_get_ip6_multicast_hops(lua_State *L, p_socket ps) -{ - return opt_getint(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_HOPS); -} - -// ------------------------------------------------------- -int opt_set_ip_multicast_loop(lua_State *L, p_socket ps) -{ - return opt_setboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP); -} - -int opt_get_ip_multicast_loop(lua_State *L, p_socket ps) -{ - return opt_getboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP); -} - -// ------------------------------------------------------- -int opt_set_ip6_multicast_loop(lua_State *L, p_socket ps) -{ - return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP); -} - -int opt_get_ip6_multicast_loop(lua_State *L, p_socket ps) -{ - return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP); -} - -// ------------------------------------------------------- -int opt_set_linger(lua_State *L, p_socket ps) -{ - struct linger li; /* obj, name, table */ - if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE)); - lua_pushstring(L, "on"); - lua_gettable(L, 3); - if (!lua_isboolean(L, -1)) - luaL_argerror(L, 3, "boolean 'on' field expected"); - li.l_onoff = (u_short) lua_toboolean(L, -1); - lua_pushstring(L, "timeout"); - lua_gettable(L, 3); - if (!lua_isnumber(L, -1)) - luaL_argerror(L, 3, "number 'timeout' field expected"); - li.l_linger = (u_short) lua_tonumber(L, -1); - return opt_set(L, ps, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof(li)); -} - -int opt_get_linger(lua_State *L, p_socket ps) -{ - struct linger li; /* obj, name */ - int len = sizeof(li); - int err = opt_get(L, ps, SOL_SOCKET, SO_LINGER, (char *) &li, &len); - if (err) - return err; - lua_newtable(L); - lua_pushboolean(L, li.l_onoff); - lua_setfield(L, -2, "on"); - lua_pushinteger(L, li.l_linger); - lua_setfield(L, -2, "timeout"); - return 1; -} - -// ------------------------------------------------------- -int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps) -{ - return opt_setint(L, ps, IPPROTO_IP, IP_MULTICAST_TTL); -} - -// ------------------------------------------------------- -int opt_set_ip_multicast_if(lua_State *L, p_socket ps) -{ - const char *address = luaL_checkstring(L, 3); /* obj, name, ip */ - struct in_addr val; - val.s_addr = htonl(INADDR_ANY); - if (strcmp(address, "*") && !inet_aton(address, &val)) - luaL_argerror(L, 3, "ip expected"); - return opt_set(L, ps, IPPROTO_IP, IP_MULTICAST_IF, - (char *) &val, sizeof(val)); -} - -int opt_get_ip_multicast_if(lua_State *L, p_socket ps) -{ - struct in_addr val; - socklen_t len = sizeof(val); - if (getsockopt(*ps, IPPROTO_IP, IP_MULTICAST_IF, (char *) &val, &len) < 0) { - lua_pushnil(L); - lua_pushstring(L, "getsockopt failed"); - return 2; - } - lua_pushstring(L, inet_ntoa(val)); - return 1; -} - -// ------------------------------------------------------- -int opt_set_ip_add_membership(lua_State *L, p_socket ps) -{ - return opt_setmembership(L, ps, IPPROTO_IP, IP_ADD_MEMBERSHIP); -} - -int opt_set_ip_drop_membersip(lua_State *L, p_socket ps) -{ - return opt_setmembership(L, ps, IPPROTO_IP, IP_DROP_MEMBERSHIP); -} - -// ------------------------------------------------------- -int opt_set_ip6_add_membership(lua_State *L, p_socket ps) -{ - return opt_ip6_setmembership(L, ps, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP); -} - -int opt_set_ip6_drop_membersip(lua_State *L, p_socket ps) -{ - return opt_ip6_setmembership(L, ps, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP); -} -// ------------------------------------------------------- -int opt_get_ip6_v6only(lua_State *L, p_socket ps) -{ - return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY); -} - -int opt_set_ip6_v6only(lua_State *L, p_socket ps) -{ - return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY); -} - -// ------------------------------------------------------- -int opt_get_error(lua_State *L, p_socket ps) -{ - int val = 0; - socklen_t len = sizeof(val); - if (getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *) &val, &len) < 0) { - lua_pushnil(L); - lua_pushstring(L, "getsockopt failed"); - return 2; - } - lua_pushstring(L, socket_strerror(val)); - return 1; -} - -/*=========================================================================*\ -* Auxiliar functions -\*=========================================================================*/ -static int opt_setmembership(lua_State *L, p_socket ps, int level, int name) -{ - struct ip_mreq val; /* obj, name, table */ - if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE)); - lua_pushstring(L, "multiaddr"); - lua_gettable(L, 3); - if (!lua_isstring(L, -1)) - luaL_argerror(L, 3, "string 'multiaddr' field expected"); - if (!inet_aton(lua_tostring(L, -1), &val.imr_multiaddr)) - luaL_argerror(L, 3, "invalid 'multiaddr' ip address"); - lua_pushstring(L, "interface"); - lua_gettable(L, 3); - if (!lua_isstring(L, -1)) - luaL_argerror(L, 3, "string 'interface' field expected"); - val.imr_interface.s_addr = htonl(INADDR_ANY); - if (strcmp(lua_tostring(L, -1), "*") && - !inet_aton(lua_tostring(L, -1), &val.imr_interface)) - luaL_argerror(L, 3, "invalid 'interface' ip address"); - return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); -} - -static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name) -{ - struct ipv6_mreq val; /* obj, opt-name, table */ - memset(&val, 0, sizeof(val)); - if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE)); - lua_pushstring(L, "multiaddr"); - lua_gettable(L, 3); - if (!lua_isstring(L, -1)) - luaL_argerror(L, 3, "string 'multiaddr' field expected"); -#ifndef _WIN32 // for some reason, this just doesn't seem to want to exist in ws2_32 on win32 but works fine on win64 -- LBPHacker - if (!inet_pton(AF_INET6, lua_tostring(L, -1), &val.ipv6mr_multiaddr)) -#endif - luaL_argerror(L, 3, "invalid 'multiaddr' ip address"); - lua_pushstring(L, "interface"); - lua_gettable(L, 3); - /* By default we listen to interface on default route - * (sigh). However, interface= can override it. We should - * support either number, or name for it. Waiting for - * windows port of if_nametoindex */ - if (!lua_isnil(L, -1)) { - if (lua_isnumber(L, -1)) { - val.ipv6mr_interface = (unsigned int) lua_tonumber(L, -1); - } else - luaL_argerror(L, -1, "number 'interface' field expected"); - } - return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); -} - -static -int opt_get(lua_State *L, p_socket ps, int level, int name, void *val, int* len) -{ - socklen_t socklen = *len; - if (getsockopt(*ps, level, name, (char *) val, &socklen) < 0) { - lua_pushnil(L); - lua_pushstring(L, "getsockopt failed"); - return 2; - } - *len = socklen; - return 0; -} - -static -int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len) -{ - if (setsockopt(*ps, level, name, (char *) val, len) < 0) { - lua_pushnil(L); - lua_pushstring(L, "setsockopt failed"); - return 2; - } - lua_pushnumber(L, 1); - return 1; -} - -static int opt_getboolean(lua_State *L, p_socket ps, int level, int name) -{ - int val = 0; - int len = sizeof(val); - int err = opt_get(L, ps, level, name, (char *) &val, &len); - if (err) - return err; - lua_pushboolean(L, val); - return 1; -} - -static int opt_setboolean(lua_State *L, p_socket ps, int level, int name) -{ - int val = auxiliar_checkboolean(L, 3); /* obj, name, bool */ - return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); -} - -static int opt_getint(lua_State *L, p_socket ps, int level, int name) -{ - int val = 0; - int len = sizeof(val); - int err = opt_get(L, ps, level, name, (char *) &val, &len); - if (err) - return err; - lua_pushnumber(L, val); - return 1; -} - -static int opt_setint(lua_State *L, p_socket ps, int level, int name) -{ - int val = (int) lua_tonumber(L, 3); /* obj, name, int */ - return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); -} diff --git a/src/lua/luasocket/options.h b/src/lua/luasocket/options.h deleted file mode 100644 index 41f733748..000000000 --- a/src/lua/luasocket/options.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef OPTIONS_H -#define OPTIONS_H -/*=========================================================================*\ -* Common option interface -* LuaSocket toolkit -* -* This module provides a common interface to socket options, used mainly by -* modules UDP and TCP. -\*=========================================================================*/ - -#include "luasocket.h" -#include "socket.h" - -/* option registry */ -typedef struct t_opt { - const char *name; - int (*func)(lua_State *L, p_socket ps); -} t_opt; -typedef t_opt *p_opt; - -#ifndef _WIN32 -#pragma GCC visibility push(hidden) -#endif - -int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps); -int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps); - -int opt_set_reuseaddr(lua_State *L, p_socket ps); -int opt_get_reuseaddr(lua_State *L, p_socket ps); - -int opt_set_reuseport(lua_State *L, p_socket ps); -int opt_get_reuseport(lua_State *L, p_socket ps); - -int opt_set_tcp_nodelay(lua_State *L, p_socket ps); -int opt_get_tcp_nodelay(lua_State *L, p_socket ps); - -#ifdef TCP_KEEPIDLE -int opt_set_tcp_keepidle(lua_State *L, p_socket ps); -int opt_get_tcp_keepidle(lua_State *L, p_socket ps); -#endif - -#ifdef TCP_KEEPCNT -int opt_set_tcp_keepcnt(lua_State *L, p_socket ps); -int opt_get_tcp_keepcnt(lua_State *L, p_socket ps); -#endif - -#ifdef TCP_KEEPINTVL -int opt_set_tcp_keepintvl(lua_State *L, p_socket ps); -int opt_get_tcp_keepintvl(lua_State *L, p_socket ps); -#endif - -int opt_set_keepalive(lua_State *L, p_socket ps); -int opt_get_keepalive(lua_State *L, p_socket ps); - -int opt_set_dontroute(lua_State *L, p_socket ps); -int opt_get_dontroute(lua_State *L, p_socket ps); - -int opt_set_broadcast(lua_State *L, p_socket ps); -int opt_get_broadcast(lua_State *L, p_socket ps); - -int opt_set_recv_buf_size(lua_State *L, p_socket ps); -int opt_get_recv_buf_size(lua_State *L, p_socket ps); - -int opt_set_send_buf_size(lua_State *L, p_socket ps); -int opt_get_send_buf_size(lua_State *L, p_socket ps); - -int opt_set_ip6_unicast_hops(lua_State *L, p_socket ps); -int opt_get_ip6_unicast_hops(lua_State *L, p_socket ps); - -int opt_set_ip6_multicast_hops(lua_State *L, p_socket ps); -int opt_get_ip6_multicast_hops(lua_State *L, p_socket ps); - -int opt_set_ip_multicast_loop(lua_State *L, p_socket ps); -int opt_get_ip_multicast_loop(lua_State *L, p_socket ps); - -int opt_set_ip6_multicast_loop(lua_State *L, p_socket ps); -int opt_get_ip6_multicast_loop(lua_State *L, p_socket ps); - -int opt_set_linger(lua_State *L, p_socket ps); -int opt_get_linger(lua_State *L, p_socket ps); - -int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps); - -int opt_set_ip_multicast_if(lua_State *L, p_socket ps); -int opt_get_ip_multicast_if(lua_State *L, p_socket ps); - -int opt_set_ip_add_membership(lua_State *L, p_socket ps); -int opt_set_ip_drop_membersip(lua_State *L, p_socket ps); - -int opt_set_ip6_add_membership(lua_State *L, p_socket ps); -int opt_set_ip6_drop_membersip(lua_State *L, p_socket ps); - -int opt_set_ip6_v6only(lua_State *L, p_socket ps); -int opt_get_ip6_v6only(lua_State *L, p_socket ps); - -int opt_get_error(lua_State *L, p_socket ps); - -#ifndef _WIN32 -#pragma GCC visibility pop -#endif - -#endif diff --git a/src/lua/luasocket/pierror.h b/src/lua/luasocket/pierror.h deleted file mode 100644 index cb773ab7f..000000000 --- a/src/lua/luasocket/pierror.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PIERROR_H -#define PIERROR_H -/*=========================================================================*\ -* Error messages -* Defines platform independent error messages -\*=========================================================================*/ - -#define PIE_HOST_NOT_FOUND "host not found" -#define PIE_ADDRINUSE "address already in use" -#define PIE_ISCONN "already connected" -#define PIE_ACCESS "permission denied" -#define PIE_CONNREFUSED "connection refused" -#define PIE_CONNABORTED "closed" -#define PIE_CONNRESET "closed" -#define PIE_TIMEDOUT "timeout" -#define PIE_AGAIN "temporary failure in name resolution" -#define PIE_BADFLAGS "invalid value for ai_flags" -#define PIE_BADHINTS "invalid value for hints" -#define PIE_FAIL "non-recoverable failure in name resolution" -#define PIE_FAMILY "ai_family not supported" -#define PIE_MEMORY "memory allocation failure" -#define PIE_NONAME "host or service not provided, or not known" -#define PIE_OVERFLOW "argument buffer overflow" -#define PIE_PROTOCOL "resolved protocol is unknown" -#define PIE_SERVICE "service not supported for socket type" -#define PIE_SOCKTYPE "ai_socktype not supported" - -#endif diff --git a/src/lua/luasocket/select.c b/src/lua/luasocket/select.c deleted file mode 100644 index bb47c4592..000000000 --- a/src/lua/luasocket/select.c +++ /dev/null @@ -1,214 +0,0 @@ -/*=========================================================================*\ -* Select implementation -* LuaSocket toolkit -\*=========================================================================*/ -#include "luasocket.h" - -#include "socket.h" -#include "timeout.h" -#include "select.h" - -#include - -/*=========================================================================*\ -* Internal function prototypes. -\*=========================================================================*/ -static t_socket getfd(lua_State *L); -static int dirty(lua_State *L); -static void collect_fd(lua_State *L, int tab, int itab, - fd_set *set, t_socket *max_fd); -static int check_dirty(lua_State *L, int tab, int dtab, fd_set *set); -static void return_fd(lua_State *L, fd_set *set, t_socket max_fd, - int itab, int tab, int start); -static void make_assoc(lua_State *L, int tab); -static int global_select(lua_State *L); - -/* functions in library namespace */ -static luaL_Reg func[] = { - {"select", global_select}, - {NULL, NULL} -}; - -/*-------------------------------------------------------------------------*\ -* Initializes module -\*-------------------------------------------------------------------------*/ -int select_open(lua_State *L) { - lua_pushstring(L, "_SETSIZE"); - lua_pushinteger(L, FD_SETSIZE); - lua_rawset(L, -3); - lua_pushstring(L, "_SOCKETINVALID"); - lua_pushinteger(L, SOCKET_INVALID); - lua_rawset(L, -3); - luaL_setfuncs(L, func, 0); - return 0; -} - -/*=========================================================================*\ -* Global Lua functions -\*=========================================================================*/ -/*-------------------------------------------------------------------------*\ -* Waits for a set of sockets until a condition is met or timeout. -\*-------------------------------------------------------------------------*/ -static int global_select(lua_State *L) { - int rtab, wtab, itab, ret, ndirty; - t_socket max_fd = SOCKET_INVALID; - fd_set rset, wset; - t_timeout tm; - double t = luaL_optnumber(L, 3, -1); - FD_ZERO(&rset); FD_ZERO(&wset); - lua_settop(L, 3); - lua_newtable(L); itab = lua_gettop(L); - lua_newtable(L); rtab = lua_gettop(L); - lua_newtable(L); wtab = lua_gettop(L); - collect_fd(L, 1, itab, &rset, &max_fd); - collect_fd(L, 2, itab, &wset, &max_fd); - ndirty = check_dirty(L, 1, rtab, &rset); - t = ndirty > 0? 0.0: t; - timeout_init(&tm, t, -1); - timeout_markstart(&tm); - ret = socket_select(max_fd+1, &rset, &wset, NULL, &tm); - if (ret > 0 || ndirty > 0) { - return_fd(L, &rset, max_fd+1, itab, rtab, ndirty); - return_fd(L, &wset, max_fd+1, itab, wtab, 0); - make_assoc(L, rtab); - make_assoc(L, wtab); - return 2; - } else if (ret == 0) { - lua_pushstring(L, "timeout"); - return 3; - } else { - luaL_error(L, "select failed"); - return 3; - } -} - -/*=========================================================================*\ -* Internal functions -\*=========================================================================*/ -static t_socket getfd(lua_State *L) { - t_socket fd = SOCKET_INVALID; - lua_pushstring(L, "getfd"); - lua_gettable(L, -2); - if (!lua_isnil(L, -1)) { - lua_pushvalue(L, -2); - lua_call(L, 1, 1); - if (lua_isnumber(L, -1)) { - double numfd = lua_tonumber(L, -1); - fd = (numfd >= 0.0)? (t_socket) numfd: SOCKET_INVALID; - } - } - lua_pop(L, 1); - return fd; -} - -static int dirty(lua_State *L) { - int is = 0; - lua_pushstring(L, "dirty"); - lua_gettable(L, -2); - if (!lua_isnil(L, -1)) { - lua_pushvalue(L, -2); - lua_call(L, 1, 1); - is = lua_toboolean(L, -1); - } - lua_pop(L, 1); - return is; -} - -static void collect_fd(lua_State *L, int tab, int itab, - fd_set *set, t_socket *max_fd) { - int i = 1, n = 0; - /* nil is the same as an empty table */ - if (lua_isnil(L, tab)) return; - /* otherwise we need it to be a table */ - luaL_checktype(L, tab, LUA_TTABLE); - for ( ;; ) { - t_socket fd; - lua_pushnumber(L, i); - lua_gettable(L, tab); - if (lua_isnil(L, -1)) { - lua_pop(L, 1); - break; - } - /* getfd figures out if this is a socket */ - fd = getfd(L); - if (fd != SOCKET_INVALID) { - /* make sure we don't overflow the fd_set */ -#ifdef _WIN32 - if (n >= FD_SETSIZE) - luaL_argerror(L, tab, "too many sockets"); -#else - if (fd >= FD_SETSIZE) - luaL_argerror(L, tab, "descriptor too large for set size"); -#endif - FD_SET(fd, set); - n++; - /* keep track of the largest descriptor so far */ - if (*max_fd == SOCKET_INVALID || *max_fd < fd) - *max_fd = fd; - /* make sure we can map back from descriptor to the object */ - lua_pushnumber(L, (lua_Number) fd); - lua_pushvalue(L, -2); - lua_settable(L, itab); - } - lua_pop(L, 1); - i = i + 1; - } -} - -static int check_dirty(lua_State *L, int tab, int dtab, fd_set *set) { - int ndirty = 0, i = 1; - if (lua_isnil(L, tab)) - return 0; - for ( ;; ) { - t_socket fd; - lua_pushnumber(L, i); - lua_gettable(L, tab); - if (lua_isnil(L, -1)) { - lua_pop(L, 1); - break; - } - fd = getfd(L); - if (fd != SOCKET_INVALID && dirty(L)) { - lua_pushnumber(L, ++ndirty); - lua_pushvalue(L, -2); - lua_settable(L, dtab); - FD_CLR(fd, set); - } - lua_pop(L, 1); - i = i + 1; - } - return ndirty; -} - -static void return_fd(lua_State *L, fd_set *set, t_socket max_fd, - int itab, int tab, int start) { - t_socket fd; - for (fd = 0; fd < max_fd; fd++) { - if (FD_ISSET(fd, set)) { - lua_pushnumber(L, ++start); - lua_pushnumber(L, (lua_Number) fd); - lua_gettable(L, itab); - lua_settable(L, tab); - } - } -} - -static void make_assoc(lua_State *L, int tab) { - int i = 1, atab; - lua_newtable(L); atab = lua_gettop(L); - for ( ;; ) { - lua_pushnumber(L, i); - lua_gettable(L, tab); - if (!lua_isnil(L, -1)) { - lua_pushnumber(L, i); - lua_pushvalue(L, -2); - lua_settable(L, atab); - lua_pushnumber(L, i); - lua_settable(L, atab); - } else { - lua_pop(L, 1); - break; - } - i = i+1; - } -} diff --git a/src/lua/luasocket/select.h b/src/lua/luasocket/select.h deleted file mode 100644 index 5d45fe753..000000000 --- a/src/lua/luasocket/select.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef SELECT_H -#define SELECT_H -/*=========================================================================*\ -* Select implementation -* LuaSocket toolkit -* -* Each object that can be passed to the select function has to export -* method getfd() which returns the descriptor to be passed to the -* underlying select function. Another method, dirty(), should return -* true if there is data ready for reading (required for buffered input). -\*=========================================================================*/ - -#ifndef _WIN32 -#pragma GCC visibility push(hidden) -#endif - -int select_open(lua_State *L); - -#ifndef _WIN32 -#pragma GCC visibility pop -#endif - -#endif /* SELECT_H */ diff --git a/src/lua/luasocket/socket.h b/src/lua/luasocket/socket.h deleted file mode 100644 index 63573de5d..000000000 --- a/src/lua/luasocket/socket.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef SOCKET_H -#define SOCKET_H -/*=========================================================================*\ -* Socket compatibilization module -* LuaSocket toolkit -* -* BSD Sockets and WinSock are similar, but there are a few irritating -* differences. Also, not all *nix platforms behave the same. This module -* (and the associated usocket.h and wsocket.h) factor these differences and -* creates a interface compatible with the io.h module. -\*=========================================================================*/ -#include "io.h" - -/*=========================================================================*\ -* Platform specific compatibilization -\*=========================================================================*/ -#ifdef _WIN32 -#include "wsocket.h" -#else -#include "usocket.h" -#endif - -/*=========================================================================*\ -* The connect and accept functions accept a timeout and their -* implementations are somewhat complicated. We chose to move -* the timeout control into this module for these functions in -* order to simplify the modules that use them. -\*=========================================================================*/ -#include "timeout.h" - -/* we are lazy... */ -typedef struct sockaddr SA; - -/*=========================================================================*\ -* Functions bellow implement a comfortable platform independent -* interface to sockets -\*=========================================================================*/ -int socket_open(void); -int socket_close(void); -void socket_destroy(p_socket ps); -void socket_shutdown(p_socket ps, int how); -int socket_sendto(p_socket ps, const char *data, size_t count, - size_t *sent, SA *addr, socklen_t addr_len, p_timeout tm); -int socket_recvfrom(p_socket ps, char *data, size_t count, - size_t *got, SA *addr, socklen_t *addr_len, p_timeout tm); - -void socket_setnonblocking(p_socket ps); -void socket_setblocking(p_socket ps); - -int socket_waitfd(p_socket ps, int sw, p_timeout tm); -int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, - p_timeout tm); - -int socket_connect(p_socket ps, SA *addr, socklen_t addr_len, p_timeout tm); -int socket_create(p_socket ps, int domain, int type, int protocol); -int socket_bind(p_socket ps, SA *addr, socklen_t addr_len); -int socket_listen(p_socket ps, int backlog); -int socket_accept(p_socket ps, p_socket pa, SA *addr, - socklen_t *addr_len, p_timeout tm); - -const char *socket_hoststrerror(int err); -const char *socket_gaistrerror(int err); -const char *socket_strerror(int err); - -/* these are perfect to use with the io abstraction module - and the buffered input module */ -int socket_send(p_socket ps, const char *data, size_t count, - size_t *sent, p_timeout tm); -int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm); -int socket_write(p_socket ps, const char *data, size_t count, - size_t *sent, p_timeout tm); -int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm); -const char *socket_ioerror(p_socket ps, int err); - -int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp); -int socket_gethostbyname(const char *addr, struct hostent **hp); - -#endif /* SOCKET_H */ diff --git a/src/lua/luasocket/socket.lua b/src/lua/luasocket/socket.lua deleted file mode 100644 index d1c0b1649..000000000 --- a/src/lua/luasocket/socket.lua +++ /dev/null @@ -1,149 +0,0 @@ ------------------------------------------------------------------------------ --- LuaSocket helper module --- Author: Diego Nehab ------------------------------------------------------------------------------ - ------------------------------------------------------------------------------ --- Declare module and import dependencies ------------------------------------------------------------------------------ -local base = _G -local string = require("string") -local math = require("math") -local socket = require("socket.core") - -local _M = socket - ------------------------------------------------------------------------------ --- Exported auxiliar functions ------------------------------------------------------------------------------ -function _M.connect4(address, port, laddress, lport) - return socket.connect(address, port, laddress, lport, "inet") -end - -function _M.connect6(address, port, laddress, lport) - return socket.connect(address, port, laddress, lport, "inet6") -end - -function _M.bind(host, port, backlog) - if host == "*" then host = "0.0.0.0" end - local addrinfo, err = socket.dns.getaddrinfo(host); - if not addrinfo then return nil, err end - local sock, res - err = "no info on address" - for i, alt in base.ipairs(addrinfo) do - if alt.family == "inet" then - sock, err = socket.tcp4() - else - sock, err = socket.tcp6() - end - if not sock then return nil, err end - sock:setoption("reuseaddr", true) - res, err = sock:bind(alt.addr, port) - if not res then - sock:close() - else - res, err = sock:listen(backlog) - if not res then - sock:close() - else - return sock - end - end - end - return nil, err -end - -_M.try = _M.newtry() - -function _M.choose(table) - return function(name, opt1, opt2) - if base.type(name) ~= "string" then - name, opt1, opt2 = "default", name, opt1 - end - local f = table[name or "nil"] - if not f then base.error("unknown key (".. base.tostring(name) ..")", 3) - else return f(opt1, opt2) end - end -end - ------------------------------------------------------------------------------ --- Socket sources and sinks, conforming to LTN12 ------------------------------------------------------------------------------ --- create namespaces inside LuaSocket namespace -local sourcet, sinkt = {}, {} -_M.sourcet = sourcet -_M.sinkt = sinkt - -_M.BLOCKSIZE = 2048 - -sinkt["close-when-done"] = function(sock) - return base.setmetatable({ - getfd = function() return sock:getfd() end, - dirty = function() return sock:dirty() end - }, { - __call = function(self, chunk, err) - if not chunk then - sock:close() - return 1 - else return sock:send(chunk) end - end - }) -end - -sinkt["keep-open"] = function(sock) - return base.setmetatable({ - getfd = function() return sock:getfd() end, - dirty = function() return sock:dirty() end - }, { - __call = function(self, chunk, err) - if chunk then return sock:send(chunk) - else return 1 end - end - }) -end - -sinkt["default"] = sinkt["keep-open"] - -_M.sink = _M.choose(sinkt) - -sourcet["by-length"] = function(sock, length) - return base.setmetatable({ - getfd = function() return sock:getfd() end, - dirty = function() return sock:dirty() end - }, { - __call = function() - if length <= 0 then return nil end - local size = math.min(socket.BLOCKSIZE, length) - local chunk, err = sock:receive(size) - if err then return nil, err end - length = length - string.len(chunk) - return chunk - end - }) -end - -sourcet["until-closed"] = function(sock) - local done - return base.setmetatable({ - getfd = function() return sock:getfd() end, - dirty = function() return sock:dirty() end - }, { - __call = function() - if done then return nil end - local chunk, err, partial = sock:receive(socket.BLOCKSIZE) - if not err then return chunk - elseif err == "closed" then - sock:close() - done = 1 - return partial - else return nil, err end - end - }) -end - - -sourcet["default"] = sourcet["until-closed"] - -_M.source = _M.choose(sourcet) - -return _M diff --git a/src/lua/luasocket/tcp.c b/src/lua/luasocket/tcp.c deleted file mode 100644 index 5876bfb87..000000000 --- a/src/lua/luasocket/tcp.c +++ /dev/null @@ -1,471 +0,0 @@ -/*=========================================================================*\ -* TCP object -* LuaSocket toolkit -\*=========================================================================*/ -#include "luasocket.h" - -#include "auxiliar.h" -#include "socket.h" -#include "inet.h" -#include "options.h" -#include "tcp.h" - -#include - -/*=========================================================================*\ -* Internal function prototypes -\*=========================================================================*/ -static int global_create(lua_State *L); -static int global_create4(lua_State *L); -static int global_create6(lua_State *L); -static int global_connect(lua_State *L); -static int meth_connect(lua_State *L); -static int meth_listen(lua_State *L); -static int meth_getfamily(lua_State *L); -static int meth_bind(lua_State *L); -static int meth_send(lua_State *L); -static int meth_getstats(lua_State *L); -static int meth_setstats(lua_State *L); -static int meth_getsockname(lua_State *L); -static int meth_getpeername(lua_State *L); -static int meth_shutdown(lua_State *L); -static int meth_receive(lua_State *L); -static int meth_accept(lua_State *L); -static int meth_close(lua_State *L); -static int meth_getoption(lua_State *L); -static int meth_setoption(lua_State *L); -static int meth_gettimeout(lua_State *L); -static int meth_settimeout(lua_State *L); -static int meth_getfd(lua_State *L); -static int meth_setfd(lua_State *L); -static int meth_dirty(lua_State *L); - -/* tcp object methods */ -static luaL_Reg tcp_methods[] = { - {"__gc", meth_close}, - {"__tostring", auxiliar_tostring}, - {"accept", meth_accept}, - {"bind", meth_bind}, - {"close", meth_close}, - {"connect", meth_connect}, - {"dirty", meth_dirty}, - {"getfamily", meth_getfamily}, - {"getfd", meth_getfd}, - {"getoption", meth_getoption}, - {"getpeername", meth_getpeername}, - {"getsockname", meth_getsockname}, - {"getstats", meth_getstats}, - {"setstats", meth_setstats}, - {"listen", meth_listen}, - {"receive", meth_receive}, - {"send", meth_send}, - {"setfd", meth_setfd}, - {"setoption", meth_setoption}, - {"setpeername", meth_connect}, - {"setsockname", meth_bind}, - {"settimeout", meth_settimeout}, - {"gettimeout", meth_gettimeout}, - {"shutdown", meth_shutdown}, - {NULL, NULL} -}; - -/* socket option handlers */ -static t_opt optget[] = { - {"keepalive", opt_get_keepalive}, - {"reuseaddr", opt_get_reuseaddr}, - {"reuseport", opt_get_reuseport}, - {"tcp-nodelay", opt_get_tcp_nodelay}, -#ifdef TCP_KEEPIDLE - {"tcp-keepidle", opt_get_tcp_keepidle}, -#endif -#ifdef TCP_KEEPCNT - {"tcp-keepcnt", opt_get_tcp_keepcnt}, -#endif -#ifdef TCP_KEEPINTVL - {"tcp-keepintvl", opt_get_tcp_keepintvl}, -#endif - {"linger", opt_get_linger}, - {"error", opt_get_error}, - {"recv-buffer-size", opt_get_recv_buf_size}, - {"send-buffer-size", opt_get_send_buf_size}, - {NULL, NULL} -}; - -static t_opt optset[] = { - {"keepalive", opt_set_keepalive}, - {"reuseaddr", opt_set_reuseaddr}, - {"reuseport", opt_set_reuseport}, - {"tcp-nodelay", opt_set_tcp_nodelay}, -#ifdef TCP_KEEPIDLE - {"tcp-keepidle", opt_set_tcp_keepidle}, -#endif -#ifdef TCP_KEEPCNT - {"tcp-keepcnt", opt_set_tcp_keepcnt}, -#endif -#ifdef TCP_KEEPINTVL - {"tcp-keepintvl", opt_set_tcp_keepintvl}, -#endif - {"ipv6-v6only", opt_set_ip6_v6only}, - {"linger", opt_set_linger}, - {"recv-buffer-size", opt_set_recv_buf_size}, - {"send-buffer-size", opt_set_send_buf_size}, - {NULL, NULL} -}; - -/* functions in library namespace */ -static luaL_Reg func[] = { - {"tcp", global_create}, - {"tcp4", global_create4}, - {"tcp6", global_create6}, - {"connect", global_connect}, - {NULL, NULL} -}; - -/*-------------------------------------------------------------------------*\ -* Initializes module -\*-------------------------------------------------------------------------*/ -int tcp_open(lua_State *L) -{ - /* create classes */ - auxiliar_newclass(L, "tcp{master}", tcp_methods); - auxiliar_newclass(L, "tcp{client}", tcp_methods); - auxiliar_newclass(L, "tcp{server}", tcp_methods); - /* create class groups */ - auxiliar_add2group(L, "tcp{master}", "tcp{any}"); - auxiliar_add2group(L, "tcp{client}", "tcp{any}"); - auxiliar_add2group(L, "tcp{server}", "tcp{any}"); - /* define library functions */ - luaL_setfuncs(L, func, 0); - return 0; -} - -/*=========================================================================*\ -* Lua methods -\*=========================================================================*/ -/*-------------------------------------------------------------------------*\ -* Just call buffered IO methods -\*-------------------------------------------------------------------------*/ -static int meth_send(lua_State *L) { - p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1); - return buffer_meth_send(L, &tcp->buf); -} - -static int meth_receive(lua_State *L) { - p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1); - return buffer_meth_receive(L, &tcp->buf); -} - -static int meth_getstats(lua_State *L) { - p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1); - return buffer_meth_getstats(L, &tcp->buf); -} - -static int meth_setstats(lua_State *L) { - p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1); - return buffer_meth_setstats(L, &tcp->buf); -} - -/*-------------------------------------------------------------------------*\ -* Just call option handler -\*-------------------------------------------------------------------------*/ -static int meth_getoption(lua_State *L) -{ - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - return opt_meth_getoption(L, optget, &tcp->sock); -} - -static int meth_setoption(lua_State *L) -{ - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - return opt_meth_setoption(L, optset, &tcp->sock); -} - -/*-------------------------------------------------------------------------*\ -* Select support methods -\*-------------------------------------------------------------------------*/ -static int meth_getfd(lua_State *L) -{ - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - lua_pushnumber(L, (int) tcp->sock); - return 1; -} - -/* this is very dangerous, but can be handy for those that are brave enough */ -static int meth_setfd(lua_State *L) -{ - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - tcp->sock = (t_socket) luaL_checknumber(L, 2); - return 0; -} - -static int meth_dirty(lua_State *L) -{ - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - lua_pushboolean(L, !buffer_isempty(&tcp->buf)); - return 1; -} - -/*-------------------------------------------------------------------------*\ -* Waits for and returns a client object attempting connection to the -* server object -\*-------------------------------------------------------------------------*/ -static int meth_accept(lua_State *L) -{ - p_tcp server = (p_tcp) auxiliar_checkclass(L, "tcp{server}", 1); - p_timeout tm = timeout_markstart(&server->tm); - t_socket sock; - const char *err = inet_tryaccept(&server->sock, server->family, &sock, tm); - /* if successful, push client socket */ - if (err == NULL) { - p_tcp clnt = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); - auxiliar_setclass(L, "tcp{client}", -1); - /* initialize structure fields */ - memset(clnt, 0, sizeof(t_tcp)); - socket_setnonblocking(&sock); - clnt->sock = sock; - io_init(&clnt->io, (p_send) socket_send, (p_recv) socket_recv, - (p_error) socket_ioerror, &clnt->sock); - timeout_init(&clnt->tm, -1, -1); - buffer_init(&clnt->buf, &clnt->io, &clnt->tm); - clnt->family = server->family; - return 1; - } else { - lua_pushnil(L); - lua_pushstring(L, err); - return 2; - } -} - -/*-------------------------------------------------------------------------*\ -* Binds an object to an address -\*-------------------------------------------------------------------------*/ -static int meth_bind(lua_State *L) { - p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{master}", 1); - const char *address = luaL_checkstring(L, 2); - const char *port = luaL_checkstring(L, 3); - const char *err; - struct addrinfo bindhints; - memset(&bindhints, 0, sizeof(bindhints)); - bindhints.ai_socktype = SOCK_STREAM; - bindhints.ai_family = tcp->family; - bindhints.ai_flags = AI_PASSIVE; - err = inet_trybind(&tcp->sock, &tcp->family, address, port, &bindhints); - if (err) { - lua_pushnil(L); - lua_pushstring(L, err); - return 2; - } - lua_pushnumber(L, 1); - return 1; -} - -/*-------------------------------------------------------------------------*\ -* Turns a master tcp object into a client object. -\*-------------------------------------------------------------------------*/ -static int meth_connect(lua_State *L) { - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - const char *address = luaL_checkstring(L, 2); - const char *port = luaL_checkstring(L, 3); - struct addrinfo connecthints; - const char *err; - memset(&connecthints, 0, sizeof(connecthints)); - connecthints.ai_socktype = SOCK_STREAM; - /* make sure we try to connect only to the same family */ - connecthints.ai_family = tcp->family; - timeout_markstart(&tcp->tm); - err = inet_tryconnect(&tcp->sock, &tcp->family, address, port, - &tcp->tm, &connecthints); - /* have to set the class even if it failed due to non-blocking connects */ - auxiliar_setclass(L, "tcp{client}", 1); - if (err) { - lua_pushnil(L); - lua_pushstring(L, err); - return 2; - } - lua_pushnumber(L, 1); - return 1; -} - -/*-------------------------------------------------------------------------*\ -* Closes socket used by object -\*-------------------------------------------------------------------------*/ -static int meth_close(lua_State *L) -{ - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - socket_destroy(&tcp->sock); - lua_pushnumber(L, 1); - return 1; -} - -/*-------------------------------------------------------------------------*\ -* Returns family as string -\*-------------------------------------------------------------------------*/ -static int meth_getfamily(lua_State *L) -{ - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - if (tcp->family == AF_INET6) { - lua_pushliteral(L, "inet6"); - return 1; - } else if (tcp->family == AF_INET) { - lua_pushliteral(L, "inet4"); - return 1; - } else { - lua_pushliteral(L, "inet4"); - return 1; - } -} - -/*-------------------------------------------------------------------------*\ -* Puts the sockt in listen mode -\*-------------------------------------------------------------------------*/ -static int meth_listen(lua_State *L) -{ - p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{master}", 1); - int backlog = (int) luaL_optnumber(L, 2, 32); - int err = socket_listen(&tcp->sock, backlog); - if (err != IO_DONE) { - lua_pushnil(L); - lua_pushstring(L, socket_strerror(err)); - return 2; - } - /* turn master object into a server object */ - auxiliar_setclass(L, "tcp{server}", 1); - lua_pushnumber(L, 1); - return 1; -} - -/*-------------------------------------------------------------------------*\ -* Shuts the connection down partially -\*-------------------------------------------------------------------------*/ -static int meth_shutdown(lua_State *L) -{ - /* SHUT_RD, SHUT_WR, SHUT_RDWR have the value 0, 1, 2, so we can use method index directly */ - static const char* methods[] = { "receive", "send", "both", NULL }; - p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1); - int how = luaL_checkoption(L, 2, "both", methods); - socket_shutdown(&tcp->sock, how); - lua_pushnumber(L, 1); - return 1; -} - -/*-------------------------------------------------------------------------*\ -* Just call inet methods -\*-------------------------------------------------------------------------*/ -static int meth_getpeername(lua_State *L) -{ - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - return inet_meth_getpeername(L, &tcp->sock, tcp->family); -} - -static int meth_getsockname(lua_State *L) -{ - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - return inet_meth_getsockname(L, &tcp->sock, tcp->family); -} - -/*-------------------------------------------------------------------------*\ -* Just call tm methods -\*-------------------------------------------------------------------------*/ -static int meth_settimeout(lua_State *L) -{ - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - return timeout_meth_settimeout(L, &tcp->tm); -} - -static int meth_gettimeout(lua_State *L) -{ - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - return timeout_meth_gettimeout(L, &tcp->tm); -} - -/*=========================================================================*\ -* Library functions -\*=========================================================================*/ -/*-------------------------------------------------------------------------*\ -* Creates a master tcp object -\*-------------------------------------------------------------------------*/ -static int tcp_create(lua_State *L, int family) { - p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); - memset(tcp, 0, sizeof(t_tcp)); - /* set its type as master object */ - auxiliar_setclass(L, "tcp{master}", -1); - /* if family is AF_UNSPEC, we leave the socket invalid and - * store AF_UNSPEC into family. This will allow it to later be - * replaced with an AF_INET6 or AF_INET socket upon first use. */ - tcp->sock = SOCKET_INVALID; - tcp->family = family; - io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv, - (p_error) socket_ioerror, &tcp->sock); - timeout_init(&tcp->tm, -1, -1); - buffer_init(&tcp->buf, &tcp->io, &tcp->tm); - if (family != AF_UNSPEC) { - const char *err = inet_trycreate(&tcp->sock, family, SOCK_STREAM, 0); - if (err != NULL) { - lua_pushnil(L); - lua_pushstring(L, err); - return 2; - } - socket_setnonblocking(&tcp->sock); - } - return 1; -} - -static int global_create(lua_State *L) { - return tcp_create(L, AF_UNSPEC); -} - -static int global_create4(lua_State *L) { - return tcp_create(L, AF_INET); -} - -static int global_create6(lua_State *L) { - return tcp_create(L, AF_INET6); -} - -static int global_connect(lua_State *L) { - const char *remoteaddr = luaL_checkstring(L, 1); - const char *remoteserv = luaL_checkstring(L, 2); - const char *localaddr = luaL_optstring(L, 3, NULL); - const char *localserv = luaL_optstring(L, 4, "0"); - int family = inet_optfamily(L, 5, "unspec"); - p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); - struct addrinfo bindhints, connecthints; - const char *err = NULL; - /* initialize tcp structure */ - memset(tcp, 0, sizeof(t_tcp)); - io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv, - (p_error) socket_ioerror, &tcp->sock); - timeout_init(&tcp->tm, -1, -1); - buffer_init(&tcp->buf, &tcp->io, &tcp->tm); - tcp->sock = SOCKET_INVALID; - tcp->family = AF_UNSPEC; - /* allow user to pick local address and port */ - memset(&bindhints, 0, sizeof(bindhints)); - bindhints.ai_socktype = SOCK_STREAM; - bindhints.ai_family = family; - bindhints.ai_flags = AI_PASSIVE; - if (localaddr) { - err = inet_trybind(&tcp->sock, &tcp->family, localaddr, - localserv, &bindhints); - if (err) { - lua_pushnil(L); - lua_pushstring(L, err); - return 2; - } - } - /* try to connect to remote address and port */ - memset(&connecthints, 0, sizeof(connecthints)); - connecthints.ai_socktype = SOCK_STREAM; - /* make sure we try to connect only to the same family */ - connecthints.ai_family = tcp->family; - err = inet_tryconnect(&tcp->sock, &tcp->family, remoteaddr, remoteserv, - &tcp->tm, &connecthints); - if (err) { - socket_destroy(&tcp->sock); - lua_pushnil(L); - lua_pushstring(L, err); - return 2; - } - auxiliar_setclass(L, "tcp{client}", -1); - return 1; -} diff --git a/src/lua/luasocket/tcp.h b/src/lua/luasocket/tcp.h deleted file mode 100644 index 9b282efeb..000000000 --- a/src/lua/luasocket/tcp.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef TCP_H -#define TCP_H -/*=========================================================================*\ -* TCP object -* LuaSocket toolkit -* -* The tcp.h module is basicly a glue that puts together modules buffer.h, -* timeout.h socket.h and inet.h to provide the LuaSocket TCP (AF_INET, -* SOCK_STREAM) support. -* -* Three classes are defined: master, client and server. The master class is -* a newly created tcp object, that has not been bound or connected. Server -* objects are tcp objects bound to some local address. Client objects are -* tcp objects either connected to some address or returned by the accept -* method of a server object. -\*=========================================================================*/ -#include "luasocket.h" - -#include "buffer.h" -#include "timeout.h" -#include "socket.h" - -typedef struct t_tcp_ { - t_socket sock; - t_io io; - t_buffer buf; - t_timeout tm; - int family; -} t_tcp; - -typedef t_tcp *p_tcp; - -#ifndef _WIN32 -#pragma GCC visibility push(hidden) -#endif - -int tcp_open(lua_State *L); - -#ifndef _WIN32 -#pragma GCC visibility pop -#endif - -#endif /* TCP_H */ diff --git a/src/lua/luasocket/timeout.c b/src/lua/luasocket/timeout.c deleted file mode 100644 index 2bdc0698c..000000000 --- a/src/lua/luasocket/timeout.c +++ /dev/null @@ -1,226 +0,0 @@ -/*=========================================================================*\ -* Timeout management functions -* LuaSocket toolkit -\*=========================================================================*/ -#include "luasocket.h" - -#include "auxiliar.h" -#include "timeout.h" - -#include -#include -#include - -#ifdef _WIN32 -#include -#else -#include -#include -#endif - -/* min and max macros */ -#ifndef MIN -#define MIN(x, y) ((x) < (y) ? x : y) -#endif -#ifndef MAX -#define MAX(x, y) ((x) > (y) ? x : y) -#endif - -/*=========================================================================*\ -* Internal function prototypes -\*=========================================================================*/ -static int timeout_lua_gettime(lua_State *L); -static int timeout_lua_sleep(lua_State *L); - -static luaL_Reg func[] = { - { "gettime", timeout_lua_gettime }, - { "sleep", timeout_lua_sleep }, - { NULL, NULL } -}; - -/*=========================================================================*\ -* Exported functions. -\*=========================================================================*/ -/*-------------------------------------------------------------------------*\ -* Initialize structure -\*-------------------------------------------------------------------------*/ -void timeout_init(p_timeout tm, double block, double total) { - tm->block = block; - tm->total = total; -} - -/*-------------------------------------------------------------------------*\ -* Determines how much time we have left for the next system call, -* if the previous call was successful -* Input -* tm: timeout control structure -* Returns -* the number of ms left or -1 if there is no time limit -\*-------------------------------------------------------------------------*/ -double timeout_get(p_timeout tm) { - if (tm->block < 0.0 && tm->total < 0.0) { - return -1; - } else if (tm->block < 0.0) { - double t = tm->total - timeout_gettime() + tm->start; - return MAX(t, 0.0); - } else if (tm->total < 0.0) { - return tm->block; - } else { - double t = tm->total - timeout_gettime() + tm->start; - return MIN(tm->block, MAX(t, 0.0)); - } -} - -/*-------------------------------------------------------------------------*\ -* Returns time since start of operation -* Input -* tm: timeout control structure -* Returns -* start field of structure -\*-------------------------------------------------------------------------*/ -double timeout_getstart(p_timeout tm) { - return tm->start; -} - -/*-------------------------------------------------------------------------*\ -* Determines how much time we have left for the next system call, -* if the previous call was a failure -* Input -* tm: timeout control structure -* Returns -* the number of ms left or -1 if there is no time limit -\*-------------------------------------------------------------------------*/ -double timeout_getretry(p_timeout tm) { - if (tm->block < 0.0 && tm->total < 0.0) { - return -1; - } else if (tm->block < 0.0) { - double t = tm->total - timeout_gettime() + tm->start; - return MAX(t, 0.0); - } else if (tm->total < 0.0) { - double t = tm->block - timeout_gettime() + tm->start; - return MAX(t, 0.0); - } else { - double t = tm->total - timeout_gettime() + tm->start; - return MIN(tm->block, MAX(t, 0.0)); - } -} - -/*-------------------------------------------------------------------------*\ -* Marks the operation start time in structure -* Input -* tm: timeout control structure -\*-------------------------------------------------------------------------*/ -p_timeout timeout_markstart(p_timeout tm) { - tm->start = timeout_gettime(); - return tm; -} - -/*-------------------------------------------------------------------------*\ -* Gets time in s, relative to January 1, 1970 (UTC) -* Returns -* time in s. -\*-------------------------------------------------------------------------*/ -#ifdef _WIN32 -double timeout_gettime(void) { - FILETIME ft; - double t; - GetSystemTimeAsFileTime(&ft); - /* Windows file time (time since January 1, 1601 (UTC)) */ - t = ft.dwLowDateTime/1.0e7 + ft.dwHighDateTime*(4294967296.0/1.0e7); - /* convert to Unix Epoch time (time since January 1, 1970 (UTC)) */ - return (t - 11644473600.0); -} -#else -double timeout_gettime(void) { - struct timeval v; - gettimeofday(&v, (struct timezone *) NULL); - /* Unix Epoch time (time since January 1, 1970 (UTC)) */ - return v.tv_sec + v.tv_usec/1.0e6; -} -#endif - -/*-------------------------------------------------------------------------*\ -* Initializes module -\*-------------------------------------------------------------------------*/ -int timeout_open(lua_State *L) { - luaL_setfuncs(L, func, 0); - return 0; -} - -/*-------------------------------------------------------------------------*\ -* Sets timeout values for IO operations -* Lua Input: base, time [, mode] -* time: time out value in seconds -* mode: "b" for block timeout, "t" for total timeout. (default: b) -\*-------------------------------------------------------------------------*/ -int timeout_meth_settimeout(lua_State *L, p_timeout tm) { - double t = luaL_optnumber(L, 2, -1); - const char *mode = luaL_optstring(L, 3, "b"); - switch (*mode) { - case 'b': - tm->block = t; - break; - case 'r': case 't': - tm->total = t; - break; - default: - luaL_argcheck(L, 0, 3, "invalid timeout mode"); - break; - } - lua_pushnumber(L, 1); - return 1; -} - -/*-------------------------------------------------------------------------*\ -* Gets timeout values for IO operations -* Lua Output: block, total -\*-------------------------------------------------------------------------*/ -int timeout_meth_gettimeout(lua_State *L, p_timeout tm) { - lua_pushnumber(L, tm->block); - lua_pushnumber(L, tm->total); - return 2; -} - -/*=========================================================================*\ -* Test support functions -\*=========================================================================*/ -/*-------------------------------------------------------------------------*\ -* Returns the time the system has been up, in secconds. -\*-------------------------------------------------------------------------*/ -static int timeout_lua_gettime(lua_State *L) -{ - lua_pushnumber(L, timeout_gettime()); - return 1; -} - -/*-------------------------------------------------------------------------*\ -* Sleep for n seconds. -\*-------------------------------------------------------------------------*/ -#ifdef _WIN32 -int timeout_lua_sleep(lua_State *L) -{ - double n = luaL_checknumber(L, 1); - if (n < 0.0) n = 0.0; - if (n < DBL_MAX/1000.0) n *= 1000.0; - if (n > INT_MAX) n = INT_MAX; - Sleep((int)n); - return 0; -} -#else -int timeout_lua_sleep(lua_State *L) -{ - double n = luaL_checknumber(L, 1); - struct timespec t, r; - if (n < 0.0) n = 0.0; - if (n > INT_MAX) n = INT_MAX; - t.tv_sec = (int) n; - n -= t.tv_sec; - t.tv_nsec = (int) (n * 1000000000); - if (t.tv_nsec >= 1000000000) t.tv_nsec = 999999999; - while (nanosleep(&t, &r) != 0) { - t.tv_sec = r.tv_sec; - t.tv_nsec = r.tv_nsec; - } - return 0; -} -#endif diff --git a/src/lua/luasocket/timeout.h b/src/lua/luasocket/timeout.h deleted file mode 100644 index 9e5250d33..000000000 --- a/src/lua/luasocket/timeout.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef TIMEOUT_H -#define TIMEOUT_H -/*=========================================================================*\ -* Timeout management functions -* LuaSocket toolkit -\*=========================================================================*/ -#include "luasocket.h" - -/* timeout control structure */ -typedef struct t_timeout_ { - double block; /* maximum time for blocking calls */ - double total; /* total number of miliseconds for operation */ - double start; /* time of start of operation */ -} t_timeout; -typedef t_timeout *p_timeout; - -#ifndef _WIN32 -#pragma GCC visibility push(hidden) -#endif - -void timeout_init(p_timeout tm, double block, double total); -double timeout_get(p_timeout tm); -double timeout_getstart(p_timeout tm); -double timeout_getretry(p_timeout tm); -p_timeout timeout_markstart(p_timeout tm); - -double timeout_gettime(void); - -int timeout_open(lua_State *L); - -int timeout_meth_settimeout(lua_State *L, p_timeout tm); -int timeout_meth_gettimeout(lua_State *L, p_timeout tm); - -#ifndef _WIN32 -#pragma GCC visibility pop -#endif - -#define timeout_iszero(tm) ((tm)->block == 0.0) - -#endif /* TIMEOUT_H */ diff --git a/src/lua/luasocket/udp.c b/src/lua/luasocket/udp.c deleted file mode 100644 index 62b6a20dd..000000000 --- a/src/lua/luasocket/udp.c +++ /dev/null @@ -1,488 +0,0 @@ -/*=========================================================================*\ -* UDP object -* LuaSocket toolkit -\*=========================================================================*/ -#include "luasocket.h" - -#include "auxiliar.h" -#include "socket.h" -#include "inet.h" -#include "options.h" -#include "udp.h" - -#include -#include - -/* min and max macros */ -#ifndef MIN -#define MIN(x, y) ((x) < (y) ? x : y) -#endif -#ifndef MAX -#define MAX(x, y) ((x) > (y) ? x : y) -#endif - -/*=========================================================================*\ -* Internal function prototypes -\*=========================================================================*/ -static int global_create(lua_State *L); -static int global_create4(lua_State *L); -static int global_create6(lua_State *L); -static int meth_send(lua_State *L); -static int meth_sendto(lua_State *L); -static int meth_receive(lua_State *L); -static int meth_receivefrom(lua_State *L); -static int meth_getfamily(lua_State *L); -static int meth_getsockname(lua_State *L); -static int meth_getpeername(lua_State *L); -static int meth_gettimeout(lua_State *L); -static int meth_setsockname(lua_State *L); -static int meth_setpeername(lua_State *L); -static int meth_close(lua_State *L); -static int meth_setoption(lua_State *L); -static int meth_getoption(lua_State *L); -static int meth_settimeout(lua_State *L); -static int meth_getfd(lua_State *L); -static int meth_setfd(lua_State *L); -static int meth_dirty(lua_State *L); - -/* udp object methods */ -static luaL_Reg udp_methods[] = { - {"__gc", meth_close}, - {"__tostring", auxiliar_tostring}, - {"close", meth_close}, - {"dirty", meth_dirty}, - {"getfamily", meth_getfamily}, - {"getfd", meth_getfd}, - {"getpeername", meth_getpeername}, - {"getsockname", meth_getsockname}, - {"receive", meth_receive}, - {"receivefrom", meth_receivefrom}, - {"send", meth_send}, - {"sendto", meth_sendto}, - {"setfd", meth_setfd}, - {"setoption", meth_setoption}, - {"getoption", meth_getoption}, - {"setpeername", meth_setpeername}, - {"setsockname", meth_setsockname}, - {"settimeout", meth_settimeout}, - {"gettimeout", meth_gettimeout}, - {NULL, NULL} -}; - -/* socket options for setoption */ -static t_opt optset[] = { - {"dontroute", opt_set_dontroute}, - {"broadcast", opt_set_broadcast}, - {"reuseaddr", opt_set_reuseaddr}, - {"reuseport", opt_set_reuseport}, - {"ip-multicast-if", opt_set_ip_multicast_if}, - {"ip-multicast-ttl", opt_set_ip_multicast_ttl}, - {"ip-multicast-loop", opt_set_ip_multicast_loop}, - {"ip-add-membership", opt_set_ip_add_membership}, - {"ip-drop-membership", opt_set_ip_drop_membersip}, - {"ipv6-unicast-hops", opt_set_ip6_unicast_hops}, - {"ipv6-multicast-hops", opt_set_ip6_unicast_hops}, - {"ipv6-multicast-loop", opt_set_ip6_multicast_loop}, - {"ipv6-add-membership", opt_set_ip6_add_membership}, - {"ipv6-drop-membership", opt_set_ip6_drop_membersip}, - {"ipv6-v6only", opt_set_ip6_v6only}, - {"recv-buffer-size", opt_set_recv_buf_size}, - {"send-buffer-size", opt_set_send_buf_size}, - {NULL, NULL} -}; - -/* socket options for getoption */ -static t_opt optget[] = { - {"dontroute", opt_get_dontroute}, - {"broadcast", opt_get_broadcast}, - {"reuseaddr", opt_get_reuseaddr}, - {"reuseport", opt_get_reuseport}, - {"ip-multicast-if", opt_get_ip_multicast_if}, - {"ip-multicast-loop", opt_get_ip_multicast_loop}, - {"error", opt_get_error}, - {"ipv6-unicast-hops", opt_get_ip6_unicast_hops}, - {"ipv6-multicast-hops", opt_get_ip6_unicast_hops}, - {"ipv6-multicast-loop", opt_get_ip6_multicast_loop}, - {"ipv6-v6only", opt_get_ip6_v6only}, - {"recv-buffer-size", opt_get_recv_buf_size}, - {"send-buffer-size", opt_get_send_buf_size}, - {NULL, NULL} -}; - -/* functions in library namespace */ -static luaL_Reg func[] = { - {"udp", global_create}, - {"udp4", global_create4}, - {"udp6", global_create6}, - {NULL, NULL} -}; - -/*-------------------------------------------------------------------------*\ -* Initializes module -\*-------------------------------------------------------------------------*/ -int udp_open(lua_State *L) { - /* create classes */ - auxiliar_newclass(L, "udp{connected}", udp_methods); - auxiliar_newclass(L, "udp{unconnected}", udp_methods); - /* create class groups */ - auxiliar_add2group(L, "udp{connected}", "udp{any}"); - auxiliar_add2group(L, "udp{unconnected}", "udp{any}"); - auxiliar_add2group(L, "udp{connected}", "select{able}"); - auxiliar_add2group(L, "udp{unconnected}", "select{able}"); - /* define library functions */ - luaL_setfuncs(L, func, 0); - /* export default UDP size */ - lua_pushliteral(L, "_DATAGRAMSIZE"); - lua_pushinteger(L, UDP_DATAGRAMSIZE); - lua_rawset(L, -3); - return 0; -} - -/*=========================================================================*\ -* Lua methods -\*=========================================================================*/ -static const char *udp_strerror(int err) { - /* a 'closed' error on an unconnected means the target address was not - * accepted by the transport layer */ - if (err == IO_CLOSED) return "refused"; - else return socket_strerror(err); -} - -/*-------------------------------------------------------------------------*\ -* Send data through connected udp socket -\*-------------------------------------------------------------------------*/ -static int meth_send(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{connected}", 1); - p_timeout tm = &udp->tm; - size_t count, sent = 0; - int err; - const char *data = luaL_checklstring(L, 2, &count); - timeout_markstart(tm); - err = socket_send(&udp->sock, data, count, &sent, tm); - if (err != IO_DONE) { - lua_pushnil(L); - lua_pushstring(L, udp_strerror(err)); - return 2; - } - lua_pushnumber(L, (lua_Number) sent); - return 1; -} - -/*-------------------------------------------------------------------------*\ -* Send data through unconnected udp socket -\*-------------------------------------------------------------------------*/ -static int meth_sendto(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); - size_t count, sent = 0; - const char *data = luaL_checklstring(L, 2, &count); - const char *ip = luaL_checkstring(L, 3); - const char *port = luaL_checkstring(L, 4); - p_timeout tm = &udp->tm; - int err; - struct addrinfo aihint; - struct addrinfo *ai; - memset(&aihint, 0, sizeof(aihint)); - aihint.ai_family = udp->family; - aihint.ai_socktype = SOCK_DGRAM; - aihint.ai_flags = AI_NUMERICHOST; -#ifdef AI_NUMERICSERV - aihint.ai_flags |= AI_NUMERICSERV; -#endif - err = getaddrinfo(ip, port, &aihint, &ai); - if (err) { - lua_pushnil(L); - lua_pushstring(L, gai_strerror(err)); - return 2; - } - - /* create socket if on first sendto if AF_UNSPEC was set */ - if (udp->family == AF_UNSPEC && udp->sock == SOCKET_INVALID) { - struct addrinfo *ap; - const char *errstr = NULL; - for (ap = ai; ap != NULL; ap = ap->ai_next) { - errstr = inet_trycreate(&udp->sock, ap->ai_family, SOCK_DGRAM, 0); - if (errstr == NULL) { - socket_setnonblocking(&udp->sock); - udp->family = ap->ai_family; - break; - } - } - if (errstr != NULL) { - lua_pushnil(L); - lua_pushstring(L, errstr); - freeaddrinfo(ai); - return 2; - } - } - - timeout_markstart(tm); - err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr, - (socklen_t) ai->ai_addrlen, tm); - freeaddrinfo(ai); - if (err != IO_DONE) { - lua_pushnil(L); - lua_pushstring(L, udp_strerror(err)); - return 2; - } - lua_pushnumber(L, (lua_Number) sent); - return 1; -} - -/*-------------------------------------------------------------------------*\ -* Receives data from a UDP socket -\*-------------------------------------------------------------------------*/ -static int meth_receive(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - char buf[UDP_DATAGRAMSIZE]; - size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf)); - char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf; - int err; - p_timeout tm = &udp->tm; - timeout_markstart(tm); - if (!dgram) { - lua_pushnil(L); - lua_pushliteral(L, "out of memory"); - return 2; - } - err = socket_recv(&udp->sock, dgram, wanted, &got, tm); - /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ - if (err != IO_DONE && err != IO_CLOSED) { - lua_pushnil(L); - lua_pushstring(L, udp_strerror(err)); - if (wanted > sizeof(buf)) free(dgram); - return 2; - } - lua_pushlstring(L, dgram, got); - if (wanted > sizeof(buf)) free(dgram); - return 1; -} - -/*-------------------------------------------------------------------------*\ -* Receives data and sender from a UDP socket -\*-------------------------------------------------------------------------*/ -static int meth_receivefrom(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); - char buf[UDP_DATAGRAMSIZE]; - size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf)); - char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf; - struct sockaddr_storage addr; - socklen_t addr_len = sizeof(addr); - char addrstr[INET6_ADDRSTRLEN]; - char portstr[6]; - int err; - p_timeout tm = &udp->tm; - timeout_markstart(tm); - if (!dgram) { - lua_pushnil(L); - lua_pushliteral(L, "out of memory"); - return 2; - } - err = socket_recvfrom(&udp->sock, dgram, wanted, &got, (SA *) &addr, - &addr_len, tm); - /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ - if (err != IO_DONE && err != IO_CLOSED) { - lua_pushnil(L); - lua_pushstring(L, udp_strerror(err)); - if (wanted > sizeof(buf)) free(dgram); - return 2; - } - err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr, - INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV); - if (err) { - lua_pushnil(L); - lua_pushstring(L, gai_strerror(err)); - if (wanted > sizeof(buf)) free(dgram); - return 2; - } - lua_pushlstring(L, dgram, got); - lua_pushstring(L, addrstr); - lua_pushinteger(L, (int) strtol(portstr, (char **) NULL, 10)); - if (wanted > sizeof(buf)) free(dgram); - return 3; -} - -/*-------------------------------------------------------------------------*\ -* Returns family as string -\*-------------------------------------------------------------------------*/ -static int meth_getfamily(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - if (udp->family == AF_INET6) { - lua_pushliteral(L, "inet6"); - return 1; - } else { - lua_pushliteral(L, "inet4"); - return 1; - } -} - -/*-------------------------------------------------------------------------*\ -* Select support methods -\*-------------------------------------------------------------------------*/ -static int meth_getfd(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - lua_pushnumber(L, (int) udp->sock); - return 1; -} - -/* this is very dangerous, but can be handy for those that are brave enough */ -static int meth_setfd(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - udp->sock = (t_socket) luaL_checknumber(L, 2); - return 0; -} - -static int meth_dirty(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - (void) udp; - lua_pushboolean(L, 0); - return 1; -} - -/*-------------------------------------------------------------------------*\ -* Just call inet methods -\*-------------------------------------------------------------------------*/ -static int meth_getpeername(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{connected}", 1); - return inet_meth_getpeername(L, &udp->sock, udp->family); -} - -static int meth_getsockname(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - return inet_meth_getsockname(L, &udp->sock, udp->family); -} - -/*-------------------------------------------------------------------------*\ -* Just call option handler -\*-------------------------------------------------------------------------*/ -static int meth_setoption(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - return opt_meth_setoption(L, optset, &udp->sock); -} - -/*-------------------------------------------------------------------------*\ -* Just call option handler -\*-------------------------------------------------------------------------*/ -static int meth_getoption(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - return opt_meth_getoption(L, optget, &udp->sock); -} - -/*-------------------------------------------------------------------------*\ -* Just call tm methods -\*-------------------------------------------------------------------------*/ -static int meth_settimeout(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - return timeout_meth_settimeout(L, &udp->tm); -} - -static int meth_gettimeout(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - return timeout_meth_gettimeout(L, &udp->tm); -} - -/*-------------------------------------------------------------------------*\ -* Turns a master udp object into a client object. -\*-------------------------------------------------------------------------*/ -static int meth_setpeername(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - p_timeout tm = &udp->tm; - const char *address = luaL_checkstring(L, 2); - int connecting = strcmp(address, "*"); - const char *port = connecting? luaL_checkstring(L, 3): "0"; - struct addrinfo connecthints; - const char *err; - memset(&connecthints, 0, sizeof(connecthints)); - connecthints.ai_socktype = SOCK_DGRAM; - /* make sure we try to connect only to the same family */ - connecthints.ai_family = udp->family; - if (connecting) { - err = inet_tryconnect(&udp->sock, &udp->family, address, - port, tm, &connecthints); - if (err) { - lua_pushnil(L); - lua_pushstring(L, err); - return 2; - } - auxiliar_setclass(L, "udp{connected}", 1); - } else { - /* we ignore possible errors because Mac OS X always - * returns EAFNOSUPPORT */ - inet_trydisconnect(&udp->sock, udp->family, tm); - auxiliar_setclass(L, "udp{unconnected}", 1); - } - lua_pushnumber(L, 1); - return 1; -} - -/*-------------------------------------------------------------------------*\ -* Closes socket used by object -\*-------------------------------------------------------------------------*/ -static int meth_close(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - socket_destroy(&udp->sock); - lua_pushnumber(L, 1); - return 1; -} - -/*-------------------------------------------------------------------------*\ -* Turns a master object into a server object -\*-------------------------------------------------------------------------*/ -static int meth_setsockname(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); - const char *address = luaL_checkstring(L, 2); - const char *port = luaL_checkstring(L, 3); - const char *err; - struct addrinfo bindhints; - memset(&bindhints, 0, sizeof(bindhints)); - bindhints.ai_socktype = SOCK_DGRAM; - bindhints.ai_family = udp->family; - bindhints.ai_flags = AI_PASSIVE; - err = inet_trybind(&udp->sock, &udp->family, address, port, &bindhints); - if (err) { - lua_pushnil(L); - lua_pushstring(L, err); - return 2; - } - lua_pushnumber(L, 1); - return 1; -} - -/*=========================================================================*\ -* Library functions -\*=========================================================================*/ -/*-------------------------------------------------------------------------*\ -* Creates a master udp object -\*-------------------------------------------------------------------------*/ -static int udp_create(lua_State *L, int family) { - /* allocate udp object */ - p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); - auxiliar_setclass(L, "udp{unconnected}", -1); - /* if family is AF_UNSPEC, we leave the socket invalid and - * store AF_UNSPEC into family. This will allow it to later be - * replaced with an AF_INET6 or AF_INET socket upon first use. */ - udp->sock = SOCKET_INVALID; - timeout_init(&udp->tm, -1, -1); - udp->family = family; - if (family != AF_UNSPEC) { - const char *err = inet_trycreate(&udp->sock, family, SOCK_DGRAM, 0); - if (err != NULL) { - lua_pushnil(L); - lua_pushstring(L, err); - return 2; - } - socket_setnonblocking(&udp->sock); - } - return 1; -} - -static int global_create(lua_State *L) { - return udp_create(L, AF_UNSPEC); -} - -static int global_create4(lua_State *L) { - return udp_create(L, AF_INET); -} - -static int global_create6(lua_State *L) { - return udp_create(L, AF_INET6); -} diff --git a/src/lua/luasocket/udp.h b/src/lua/luasocket/udp.h deleted file mode 100644 index 07d5247fc..000000000 --- a/src/lua/luasocket/udp.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef UDP_H -#define UDP_H -/*=========================================================================*\ -* UDP object -* LuaSocket toolkit -* -* The udp.h module provides LuaSocket with support for UDP protocol -* (AF_INET, SOCK_DGRAM). -* -* Two classes are defined: connected and unconnected. UDP objects are -* originally unconnected. They can be "connected" to a given address -* with a call to the setpeername function. The same function can be used to -* break the connection. -\*=========================================================================*/ -#include "luasocket.h" - -#include "timeout.h" -#include "socket.h" - -#define UDP_DATAGRAMSIZE 8192 - -typedef struct t_udp_ { - t_socket sock; - t_timeout tm; - int family; -} t_udp; -typedef t_udp *p_udp; - -#ifndef _WIN32 -#pragma GCC visibility push(hidden) -#endif - -int udp_open(lua_State *L); - -#ifndef _WIN32 -#pragma GCC visibility pop -#endif - -#endif /* UDP_H */ diff --git a/src/lua/luasocket/usocket.c b/src/lua/luasocket/usocket.c deleted file mode 100644 index acfe186c8..000000000 --- a/src/lua/luasocket/usocket.c +++ /dev/null @@ -1,454 +0,0 @@ -/*=========================================================================*\ -* Socket compatibilization module for Unix -* LuaSocket toolkit -* -* The code is now interrupt-safe. -* The penalty of calling select to avoid busy-wait is only paid when -* the I/O call fail in the first place. -\*=========================================================================*/ -#include "luasocket.h" - -#include "socket.h" -#include "pierror.h" - -#include -#include - -/*-------------------------------------------------------------------------*\ -* Wait for readable/writable/connected socket with timeout -\*-------------------------------------------------------------------------*/ -#ifndef SOCKET_SELECT -#include - -#define WAITFD_R POLLIN -#define WAITFD_W POLLOUT -#define WAITFD_C (POLLIN|POLLOUT) -int socket_waitfd(p_socket ps, int sw, p_timeout tm) { - int ret; - struct pollfd pfd; - pfd.fd = *ps; - pfd.events = sw; - pfd.revents = 0; - if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ - do { - int t = (int)(timeout_getretry(tm)*1e3); - ret = poll(&pfd, 1, t >= 0? t: -1); - } while (ret == -1 && errno == EINTR); - if (ret == -1) return errno; - if (ret == 0) return IO_TIMEOUT; - if (sw == WAITFD_C && (pfd.revents & (POLLIN|POLLERR))) return IO_CLOSED; - return IO_DONE; -} -#else - -#define WAITFD_R 1 -#define WAITFD_W 2 -#define WAITFD_C (WAITFD_R|WAITFD_W) - -int socket_waitfd(p_socket ps, int sw, p_timeout tm) { - int ret; - fd_set rfds, wfds, *rp, *wp; - struct timeval tv, *tp; - double t; - if (*ps >= FD_SETSIZE) return EINVAL; - if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ - do { - /* must set bits within loop, because select may have modifed them */ - rp = wp = NULL; - if (sw & WAITFD_R) { FD_ZERO(&rfds); FD_SET(*ps, &rfds); rp = &rfds; } - if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; } - t = timeout_getretry(tm); - tp = NULL; - if (t >= 0.0) { - tv.tv_sec = (int)t; - tv.tv_usec = (int)((t-tv.tv_sec)*1.0e6); - tp = &tv; - } - ret = select(*ps+1, rp, wp, NULL, tp); - } while (ret == -1 && errno == EINTR); - if (ret == -1) return errno; - if (ret == 0) return IO_TIMEOUT; - if (sw == WAITFD_C && FD_ISSET(*ps, &rfds)) return IO_CLOSED; - return IO_DONE; -} -#endif - - -/*-------------------------------------------------------------------------*\ -* Initializes module -\*-------------------------------------------------------------------------*/ -int socket_open(void) { - /* installs a handler to ignore sigpipe or it will crash us */ - signal(SIGPIPE, SIG_IGN); - return 1; -} - -/*-------------------------------------------------------------------------*\ -* Close module -\*-------------------------------------------------------------------------*/ -int socket_close(void) { - return 1; -} - -/*-------------------------------------------------------------------------*\ -* Close and inutilize socket -\*-------------------------------------------------------------------------*/ -void socket_destroy(p_socket ps) { - if (*ps != SOCKET_INVALID) { - close(*ps); - *ps = SOCKET_INVALID; - } -} - -/*-------------------------------------------------------------------------*\ -* Select with timeout control -\*-------------------------------------------------------------------------*/ -int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, - p_timeout tm) { - int ret; - do { - struct timeval tv; - double t = timeout_getretry(tm); - tv.tv_sec = (int) t; - tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6); - /* timeout = 0 means no wait */ - ret = select(n, rfds, wfds, efds, t >= 0.0 ? &tv: NULL); - } while (ret < 0 && errno == EINTR); - return ret; -} - -/*-------------------------------------------------------------------------*\ -* Creates and sets up a socket -\*-------------------------------------------------------------------------*/ -int socket_create(p_socket ps, int domain, int type, int protocol) { - *ps = socket(domain, type, protocol); - if (*ps != SOCKET_INVALID) return IO_DONE; - else return errno; -} - -/*-------------------------------------------------------------------------*\ -* Binds or returns error message -\*-------------------------------------------------------------------------*/ -int socket_bind(p_socket ps, SA *addr, socklen_t len) { - int err = IO_DONE; - socket_setblocking(ps); - if (bind(*ps, addr, len) < 0) err = errno; - socket_setnonblocking(ps); - return err; -} - -/*-------------------------------------------------------------------------*\ -* -\*-------------------------------------------------------------------------*/ -int socket_listen(p_socket ps, int backlog) { - int err = IO_DONE; - if (listen(*ps, backlog)) err = errno; - return err; -} - -/*-------------------------------------------------------------------------*\ -* -\*-------------------------------------------------------------------------*/ -void socket_shutdown(p_socket ps, int how) { - shutdown(*ps, how); -} - -/*-------------------------------------------------------------------------*\ -* Connects or returns error message -\*-------------------------------------------------------------------------*/ -int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) { - int err; - /* avoid calling on closed sockets */ - if (*ps == SOCKET_INVALID) return IO_CLOSED; - /* call connect until done or failed without being interrupted */ - do if (connect(*ps, addr, len) == 0) return IO_DONE; - while ((err = errno) == EINTR); - /* if connection failed immediately, return error code */ - if (err != EINPROGRESS && err != EAGAIN) return err; - /* zero timeout case optimization */ - if (timeout_iszero(tm)) return IO_TIMEOUT; - /* wait until we have the result of the connection attempt or timeout */ - err = socket_waitfd(ps, WAITFD_C, tm); - if (err == IO_CLOSED) { - if (recv(*ps, (char *) &err, 0, 0) == 0) return IO_DONE; - else return errno; - } else return err; -} - -/*-------------------------------------------------------------------------*\ -* Accept with timeout -\*-------------------------------------------------------------------------*/ -int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, p_timeout tm) { - if (*ps == SOCKET_INVALID) return IO_CLOSED; - for ( ;; ) { - int err; - if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE; - err = errno; - if (err == EINTR) continue; - if (err != EAGAIN && err != ECONNABORTED) return err; - if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; - } - /* can't reach here */ - return IO_UNKNOWN; -} - -/*-------------------------------------------------------------------------*\ -* Send with timeout -\*-------------------------------------------------------------------------*/ -int socket_send(p_socket ps, const char *data, size_t count, - size_t *sent, p_timeout tm) -{ - int err; - *sent = 0; - /* avoid making system calls on closed sockets */ - if (*ps == SOCKET_INVALID) return IO_CLOSED; - /* loop until we send something or we give up on error */ - for ( ;; ) { - long put = (long) send(*ps, data, count, 0); - /* if we sent anything, we are done */ - if (put >= 0) { - *sent = put; - return IO_DONE; - } - err = errno; - /* EPIPE means the connection was closed */ - if (err == EPIPE) return IO_CLOSED; - /* EPROTOTYPE means the connection is being closed (on Yosemite!)*/ - if (err == EPROTOTYPE) continue; - /* we call was interrupted, just try again */ - if (err == EINTR) continue; - /* if failed fatal reason, report error */ - if (err != EAGAIN) return err; - /* wait until we can send something or we timeout */ - if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; - } - /* can't reach here */ - return IO_UNKNOWN; -} - -/*-------------------------------------------------------------------------*\ -* Sendto with timeout -\*-------------------------------------------------------------------------*/ -int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, - SA *addr, socklen_t len, p_timeout tm) -{ - int err; - *sent = 0; - if (*ps == SOCKET_INVALID) return IO_CLOSED; - for ( ;; ) { - long put = (long) sendto(*ps, data, count, 0, addr, len); - if (put >= 0) { - *sent = put; - return IO_DONE; - } - err = errno; - if (err == EPIPE) return IO_CLOSED; - if (err == EPROTOTYPE) continue; - if (err == EINTR) continue; - if (err != EAGAIN) return err; - if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; - } - return IO_UNKNOWN; -} - -/*-------------------------------------------------------------------------*\ -* Receive with timeout -\*-------------------------------------------------------------------------*/ -int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm) { - int err; - *got = 0; - if (*ps == SOCKET_INVALID) return IO_CLOSED; - for ( ;; ) { - long taken = (long) recv(*ps, data, count, 0); - if (taken > 0) { - *got = taken; - return IO_DONE; - } - err = errno; - if (taken == 0) return IO_CLOSED; - if (err == EINTR) continue; - if (err != EAGAIN) return err; - if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; - } - return IO_UNKNOWN; -} - -/*-------------------------------------------------------------------------*\ -* Recvfrom with timeout -\*-------------------------------------------------------------------------*/ -int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, - SA *addr, socklen_t *len, p_timeout tm) { - int err; - *got = 0; - if (*ps == SOCKET_INVALID) return IO_CLOSED; - for ( ;; ) { - long taken = (long) recvfrom(*ps, data, count, 0, addr, len); - if (taken > 0) { - *got = taken; - return IO_DONE; - } - err = errno; - if (taken == 0) return IO_CLOSED; - if (err == EINTR) continue; - if (err != EAGAIN) return err; - if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; - } - return IO_UNKNOWN; -} - - -/*-------------------------------------------------------------------------*\ -* Write with timeout -* -* socket_read and socket_write are cut-n-paste of socket_send and socket_recv, -* with send/recv replaced with write/read. We can't just use write/read -* in the socket version, because behaviour when size is zero is different. -\*-------------------------------------------------------------------------*/ -int socket_write(p_socket ps, const char *data, size_t count, - size_t *sent, p_timeout tm) -{ - int err; - *sent = 0; - /* avoid making system calls on closed sockets */ - if (*ps == SOCKET_INVALID) return IO_CLOSED; - /* loop until we send something or we give up on error */ - for ( ;; ) { - long put = (long) write(*ps, data, count); - /* if we sent anything, we are done */ - if (put >= 0) { - *sent = put; - return IO_DONE; - } - err = errno; - /* EPIPE means the connection was closed */ - if (err == EPIPE) return IO_CLOSED; - /* EPROTOTYPE means the connection is being closed (on Yosemite!)*/ - if (err == EPROTOTYPE) continue; - /* we call was interrupted, just try again */ - if (err == EINTR) continue; - /* if failed fatal reason, report error */ - if (err != EAGAIN) return err; - /* wait until we can send something or we timeout */ - if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; - } - /* can't reach here */ - return IO_UNKNOWN; -} - -/*-------------------------------------------------------------------------*\ -* Read with timeout -* See note for socket_write -\*-------------------------------------------------------------------------*/ -int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm) { - int err; - *got = 0; - if (*ps == SOCKET_INVALID) return IO_CLOSED; - for ( ;; ) { - long taken = (long) read(*ps, data, count); - if (taken > 0) { - *got = taken; - return IO_DONE; - } - err = errno; - if (taken == 0) return IO_CLOSED; - if (err == EINTR) continue; - if (err != EAGAIN) return err; - if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; - } - return IO_UNKNOWN; -} - -/*-------------------------------------------------------------------------*\ -* Put socket into blocking mode -\*-------------------------------------------------------------------------*/ -void socket_setblocking(p_socket ps) { - int flags = fcntl(*ps, F_GETFL, 0); - flags &= (~(O_NONBLOCK)); - fcntl(*ps, F_SETFL, flags); -} - -/*-------------------------------------------------------------------------*\ -* Put socket into non-blocking mode -\*-------------------------------------------------------------------------*/ -void socket_setnonblocking(p_socket ps) { - int flags = fcntl(*ps, F_GETFL, 0); - flags |= O_NONBLOCK; - fcntl(*ps, F_SETFL, flags); -} - -/*-------------------------------------------------------------------------*\ -* DNS helpers -\*-------------------------------------------------------------------------*/ -int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) { - *hp = gethostbyaddr(addr, len, AF_INET); - if (*hp) return IO_DONE; - else if (h_errno) return h_errno; - else if (errno) return errno; - else return IO_UNKNOWN; -} - -int socket_gethostbyname(const char *addr, struct hostent **hp) { - *hp = gethostbyname(addr); - if (*hp) return IO_DONE; - else if (h_errno) return h_errno; - else if (errno) return errno; - else return IO_UNKNOWN; -} - -/*-------------------------------------------------------------------------*\ -* Error translation functions -* Make sure important error messages are standard -\*-------------------------------------------------------------------------*/ -const char *socket_hoststrerror(int err) { - if (err <= 0) return io_strerror(err); - switch (err) { - case HOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; - default: return hstrerror(err); - } -} - -const char *socket_strerror(int err) { - if (err <= 0) return io_strerror(err); - switch (err) { - case EADDRINUSE: return PIE_ADDRINUSE; - case EISCONN: return PIE_ISCONN; - case EACCES: return PIE_ACCESS; - case ECONNREFUSED: return PIE_CONNREFUSED; - case ECONNABORTED: return PIE_CONNABORTED; - case ECONNRESET: return PIE_CONNRESET; - case ETIMEDOUT: return PIE_TIMEDOUT; - default: { - return strerror(err); - } - } -} - -const char *socket_ioerror(p_socket ps, int err) { - (void) ps; - return socket_strerror(err); -} - -const char *socket_gaistrerror(int err) { - if (err == 0) return NULL; - switch (err) { - case EAI_AGAIN: return PIE_AGAIN; - case EAI_BADFLAGS: return PIE_BADFLAGS; -#ifdef EAI_BADHINTS - case EAI_BADHINTS: return PIE_BADHINTS; -#endif - case EAI_FAIL: return PIE_FAIL; - case EAI_FAMILY: return PIE_FAMILY; - case EAI_MEMORY: return PIE_MEMORY; - case EAI_NONAME: return PIE_NONAME; -#ifdef EAI_OVERFLOW - case EAI_OVERFLOW: return PIE_OVERFLOW; -#endif -#ifdef EAI_PROTOCOL - case EAI_PROTOCOL: return PIE_PROTOCOL; -#endif - case EAI_SERVICE: return PIE_SERVICE; - case EAI_SOCKTYPE: return PIE_SOCKTYPE; - case EAI_SYSTEM: return strerror(errno); - default: return gai_strerror(err); - } -} diff --git a/src/lua/luasocket/usocket.h b/src/lua/luasocket/usocket.h deleted file mode 100644 index 45f2f99f7..000000000 --- a/src/lua/luasocket/usocket.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef USOCKET_H -#define USOCKET_H -/*=========================================================================*\ -* Socket compatibilization module for Unix -* LuaSocket toolkit -\*=========================================================================*/ - -/*=========================================================================*\ -* BSD include files -\*=========================================================================*/ -/* error codes */ -#include -/* close function */ -#include -/* fnctnl function and associated constants */ -#include -/* struct sockaddr */ -#include -/* socket function */ -#include -/* struct timeval */ -#include -/* gethostbyname and gethostbyaddr functions */ -#include -/* sigpipe handling */ -#include -/* IP stuff*/ -#include -#include -/* TCP options (nagle algorithm disable) */ -#include -#include - -#ifndef SO_REUSEPORT -#define SO_REUSEPORT SO_REUSEADDR -#endif - -/* Some platforms use IPV6_JOIN_GROUP instead if - * IPV6_ADD_MEMBERSHIP. The semantics are same, though. */ -#ifndef IPV6_ADD_MEMBERSHIP -#ifdef IPV6_JOIN_GROUP -#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP -#endif /* IPV6_JOIN_GROUP */ -#endif /* !IPV6_ADD_MEMBERSHIP */ - -/* Same with IPV6_DROP_MEMBERSHIP / IPV6_LEAVE_GROUP. */ -#ifndef IPV6_DROP_MEMBERSHIP -#ifdef IPV6_LEAVE_GROUP -#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP -#endif /* IPV6_LEAVE_GROUP */ -#endif /* !IPV6_DROP_MEMBERSHIP */ - -typedef int t_socket; -typedef t_socket *p_socket; -typedef struct sockaddr_storage t_sockaddr_storage; - -#define SOCKET_INVALID (-1) - -#endif /* USOCKET_H */ diff --git a/src/lua/luasocket/wsocket.c b/src/lua/luasocket/wsocket.c deleted file mode 100644 index 20da330b5..000000000 --- a/src/lua/luasocket/wsocket.c +++ /dev/null @@ -1,434 +0,0 @@ -/*=========================================================================*\ -* Socket compatibilization module for Win32 -* LuaSocket toolkit -* -* The penalty of calling select to avoid busy-wait is only paid when -* the I/O call fail in the first place. -\*=========================================================================*/ -#include "luasocket.h" - -#include - -#include "socket.h" -#include "pierror.h" - -/* WinSock doesn't have a strerror... */ -static const char *wstrerror(int err); - -/*-------------------------------------------------------------------------*\ -* Initializes module -\*-------------------------------------------------------------------------*/ -int socket_open(void) { - WSADATA wsaData; - WORD wVersionRequested = MAKEWORD(2, 0); - int err = WSAStartup(wVersionRequested, &wsaData ); - if (err != 0) return 0; - if ((LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) && - (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)) { - WSACleanup(); - return 0; - } - return 1; -} - -/*-------------------------------------------------------------------------*\ -* Close module -\*-------------------------------------------------------------------------*/ -int socket_close(void) { - WSACleanup(); - return 1; -} - -/*-------------------------------------------------------------------------*\ -* Wait for readable/writable/connected socket with timeout -\*-------------------------------------------------------------------------*/ -#define WAITFD_R 1 -#define WAITFD_W 2 -#define WAITFD_E 4 -#define WAITFD_C (WAITFD_E|WAITFD_W) - -int socket_waitfd(p_socket ps, int sw, p_timeout tm) { - int ret; - fd_set rfds, wfds, efds, *rp = NULL, *wp = NULL, *ep = NULL; - struct timeval tv, *tp = NULL; - double t; - if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ - if (sw & WAITFD_R) { - FD_ZERO(&rfds); - FD_SET(*ps, &rfds); - rp = &rfds; - } - if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; } - if (sw & WAITFD_C) { FD_ZERO(&efds); FD_SET(*ps, &efds); ep = &efds; } - if ((t = timeout_get(tm)) >= 0.0) { - tv.tv_sec = (int) t; - tv.tv_usec = (int) ((t-tv.tv_sec)*1.0e6); - tp = &tv; - } - ret = select(0, rp, wp, ep, tp); - if (ret == -1) return WSAGetLastError(); - if (ret == 0) return IO_TIMEOUT; - if (sw == WAITFD_C && FD_ISSET(*ps, &efds)) return IO_CLOSED; - return IO_DONE; -} - -/*-------------------------------------------------------------------------*\ -* Select with int timeout in ms -\*-------------------------------------------------------------------------*/ -int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, - p_timeout tm) { - struct timeval tv; - double t = timeout_get(tm); - tv.tv_sec = (int) t; - tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6); - if (n <= 0) { - Sleep((DWORD) (1000*t)); - return 0; - } else return select(0, rfds, wfds, efds, t >= 0.0? &tv: NULL); -} - -/*-------------------------------------------------------------------------*\ -* Close and inutilize socket -\*-------------------------------------------------------------------------*/ -void socket_destroy(p_socket ps) { - if (*ps != SOCKET_INVALID) { - socket_setblocking(ps); /* close can take a long time on WIN32 */ - closesocket(*ps); - *ps = SOCKET_INVALID; - } -} - -/*-------------------------------------------------------------------------*\ -* -\*-------------------------------------------------------------------------*/ -void socket_shutdown(p_socket ps, int how) { - socket_setblocking(ps); - shutdown(*ps, how); - socket_setnonblocking(ps); -} - -/*-------------------------------------------------------------------------*\ -* Creates and sets up a socket -\*-------------------------------------------------------------------------*/ -int socket_create(p_socket ps, int domain, int type, int protocol) { - *ps = socket(domain, type, protocol); - if (*ps != SOCKET_INVALID) return IO_DONE; - else return WSAGetLastError(); -} - -/*-------------------------------------------------------------------------*\ -* Connects or returns error message -\*-------------------------------------------------------------------------*/ -int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) { - int err; - /* don't call on closed socket */ - if (*ps == SOCKET_INVALID) return IO_CLOSED; - /* ask system to connect */ - if (connect(*ps, addr, len) == 0) return IO_DONE; - /* make sure the system is trying to connect */ - err = WSAGetLastError(); - if (err != WSAEWOULDBLOCK && err != WSAEINPROGRESS) return err; - /* zero timeout case optimization */ - if (timeout_iszero(tm)) return IO_TIMEOUT; - /* we wait until something happens */ - err = socket_waitfd(ps, WAITFD_C, tm); - if (err == IO_CLOSED) { - int elen = sizeof(err); - /* give windows time to set the error (yes, disgusting) */ - Sleep(10); - /* find out why we failed */ - getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &elen); - /* we KNOW there was an error. if 'why' is 0, we will return - * "unknown error", but it's not really our fault */ - return err > 0? err: IO_UNKNOWN; - } else return err; - -} - -/*-------------------------------------------------------------------------*\ -* Binds or returns error message -\*-------------------------------------------------------------------------*/ -int socket_bind(p_socket ps, SA *addr, socklen_t len) { - int err = IO_DONE; - socket_setblocking(ps); - if (bind(*ps, addr, len) < 0) err = WSAGetLastError(); - socket_setnonblocking(ps); - return err; -} - -/*-------------------------------------------------------------------------*\ -* -\*-------------------------------------------------------------------------*/ -int socket_listen(p_socket ps, int backlog) { - int err = IO_DONE; - socket_setblocking(ps); - if (listen(*ps, backlog) < 0) err = WSAGetLastError(); - socket_setnonblocking(ps); - return err; -} - -/*-------------------------------------------------------------------------*\ -* Accept with timeout -\*-------------------------------------------------------------------------*/ -int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, - p_timeout tm) { - if (*ps == SOCKET_INVALID) return IO_CLOSED; - for ( ;; ) { - int err; - /* try to get client socket */ - if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE; - /* find out why we failed */ - err = WSAGetLastError(); - /* if we failed because there was no connectoin, keep trying */ - if (err != WSAEWOULDBLOCK && err != WSAECONNABORTED) return err; - /* call select to avoid busy wait */ - if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; - } -} - -/*-------------------------------------------------------------------------*\ -* Send with timeout -* On windows, if you try to send 10MB, the OS will buffer EVERYTHING -* this can take an awful lot of time and we will end up blocked. -* Therefore, whoever calls this function should not pass a huge buffer. -\*-------------------------------------------------------------------------*/ -int socket_send(p_socket ps, const char *data, size_t count, - size_t *sent, p_timeout tm) -{ - int err; - *sent = 0; - /* avoid making system calls on closed sockets */ - if (*ps == SOCKET_INVALID) return IO_CLOSED; - /* loop until we send something or we give up on error */ - for ( ;; ) { - /* try to send something */ - int put = send(*ps, data, (int) count, 0); - /* if we sent something, we are done */ - if (put > 0) { - *sent = put; - return IO_DONE; - } - /* deal with failure */ - err = WSAGetLastError(); - /* we can only proceed if there was no serious error */ - if (err != WSAEWOULDBLOCK) return err; - /* avoid busy wait */ - if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; - } -} - -/*-------------------------------------------------------------------------*\ -* Sendto with timeout -\*-------------------------------------------------------------------------*/ -int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, - SA *addr, socklen_t len, p_timeout tm) -{ - int err; - *sent = 0; - if (*ps == SOCKET_INVALID) return IO_CLOSED; - for ( ;; ) { - int put = sendto(*ps, data, (int) count, 0, addr, len); - if (put > 0) { - *sent = put; - return IO_DONE; - } - err = WSAGetLastError(); - if (err != WSAEWOULDBLOCK) return err; - if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; - } -} - -/*-------------------------------------------------------------------------*\ -* Receive with timeout -\*-------------------------------------------------------------------------*/ -int socket_recv(p_socket ps, char *data, size_t count, size_t *got, - p_timeout tm) -{ - int err, prev = IO_DONE; - *got = 0; - if (*ps == SOCKET_INVALID) return IO_CLOSED; - for ( ;; ) { - int taken = recv(*ps, data, (int) count, 0); - if (taken > 0) { - *got = taken; - return IO_DONE; - } - if (taken == 0) return IO_CLOSED; - err = WSAGetLastError(); - /* On UDP, a connreset simply means the previous send failed. - * So we try again. - * On TCP, it means our socket is now useless, so the error passes. - * (We will loop again, exiting because the same error will happen) */ - if (err != WSAEWOULDBLOCK) { - if (err != WSAECONNRESET || prev == WSAECONNRESET) return err; - prev = err; - } - if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; - } -} - -/*-------------------------------------------------------------------------*\ -* Recvfrom with timeout -\*-------------------------------------------------------------------------*/ -int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, - SA *addr, socklen_t *len, p_timeout tm) -{ - int err, prev = IO_DONE; - *got = 0; - if (*ps == SOCKET_INVALID) return IO_CLOSED; - for ( ;; ) { - int taken = recvfrom(*ps, data, (int) count, 0, addr, len); - if (taken > 0) { - *got = taken; - return IO_DONE; - } - if (taken == 0) return IO_CLOSED; - err = WSAGetLastError(); - /* On UDP, a connreset simply means the previous send failed. - * So we try again. - * On TCP, it means our socket is now useless, so the error passes. - * (We will loop again, exiting because the same error will happen) */ - if (err != WSAEWOULDBLOCK) { - if (err != WSAECONNRESET || prev == WSAECONNRESET) return err; - prev = err; - } - if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; - } -} - -/*-------------------------------------------------------------------------*\ -* Put socket into blocking mode -\*-------------------------------------------------------------------------*/ -void socket_setblocking(p_socket ps) { - u_long argp = 0; - ioctlsocket(*ps, FIONBIO, &argp); -} - -/*-------------------------------------------------------------------------*\ -* Put socket into non-blocking mode -\*-------------------------------------------------------------------------*/ -void socket_setnonblocking(p_socket ps) { - u_long argp = 1; - ioctlsocket(*ps, FIONBIO, &argp); -} - -/*-------------------------------------------------------------------------*\ -* DNS helpers -\*-------------------------------------------------------------------------*/ -int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) { - *hp = gethostbyaddr(addr, len, AF_INET); - if (*hp) return IO_DONE; - else return WSAGetLastError(); -} - -int socket_gethostbyname(const char *addr, struct hostent **hp) { - *hp = gethostbyname(addr); - if (*hp) return IO_DONE; - else return WSAGetLastError(); -} - -/*-------------------------------------------------------------------------*\ -* Error translation functions -\*-------------------------------------------------------------------------*/ -const char *socket_hoststrerror(int err) { - if (err <= 0) return io_strerror(err); - switch (err) { - case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; - default: return wstrerror(err); - } -} - -const char *socket_strerror(int err) { - if (err <= 0) return io_strerror(err); - switch (err) { - case WSAEADDRINUSE: return PIE_ADDRINUSE; - case WSAECONNREFUSED : return PIE_CONNREFUSED; - case WSAEISCONN: return PIE_ISCONN; - case WSAEACCES: return PIE_ACCESS; - case WSAECONNABORTED: return PIE_CONNABORTED; - case WSAECONNRESET: return PIE_CONNRESET; - case WSAETIMEDOUT: return PIE_TIMEDOUT; - default: return wstrerror(err); - } -} - -const char *socket_ioerror(p_socket ps, int err) { - (void) ps; - return socket_strerror(err); -} - -static const char *wstrerror(int err) { - switch (err) { - case WSAEINTR: return "Interrupted function call"; - case WSAEACCES: return PIE_ACCESS; // "Permission denied"; - case WSAEFAULT: return "Bad address"; - case WSAEINVAL: return "Invalid argument"; - case WSAEMFILE: return "Too many open files"; - case WSAEWOULDBLOCK: return "Resource temporarily unavailable"; - case WSAEINPROGRESS: return "Operation now in progress"; - case WSAEALREADY: return "Operation already in progress"; - case WSAENOTSOCK: return "Socket operation on nonsocket"; - case WSAEDESTADDRREQ: return "Destination address required"; - case WSAEMSGSIZE: return "Message too long"; - case WSAEPROTOTYPE: return "Protocol wrong type for socket"; - case WSAENOPROTOOPT: return "Bad protocol option"; - case WSAEPROTONOSUPPORT: return "Protocol not supported"; - case WSAESOCKTNOSUPPORT: return PIE_SOCKTYPE; // "Socket type not supported"; - case WSAEOPNOTSUPP: return "Operation not supported"; - case WSAEPFNOSUPPORT: return "Protocol family not supported"; - case WSAEAFNOSUPPORT: return PIE_FAMILY; // "Address family not supported by protocol family"; - case WSAEADDRINUSE: return PIE_ADDRINUSE; // "Address already in use"; - case WSAEADDRNOTAVAIL: return "Cannot assign requested address"; - case WSAENETDOWN: return "Network is down"; - case WSAENETUNREACH: return "Network is unreachable"; - case WSAENETRESET: return "Network dropped connection on reset"; - case WSAECONNABORTED: return "Software caused connection abort"; - case WSAECONNRESET: return PIE_CONNRESET; // "Connection reset by peer"; - case WSAENOBUFS: return "No buffer space available"; - case WSAEISCONN: return PIE_ISCONN; // "Socket is already connected"; - case WSAENOTCONN: return "Socket is not connected"; - case WSAESHUTDOWN: return "Cannot send after socket shutdown"; - case WSAETIMEDOUT: return PIE_TIMEDOUT; // "Connection timed out"; - case WSAECONNREFUSED: return PIE_CONNREFUSED; // "Connection refused"; - case WSAEHOSTDOWN: return "Host is down"; - case WSAEHOSTUNREACH: return "No route to host"; - case WSAEPROCLIM: return "Too many processes"; - case WSASYSNOTREADY: return "Network subsystem is unavailable"; - case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range"; - case WSANOTINITIALISED: - return "Successful WSAStartup not yet performed"; - case WSAEDISCON: return "Graceful shutdown in progress"; - case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; // "Host not found"; - case WSATRY_AGAIN: return "Nonauthoritative host not found"; - case WSANO_RECOVERY: return PIE_FAIL; // "Nonrecoverable name lookup error"; - case WSANO_DATA: return "Valid name, no data record of requested type"; - default: return "Unknown error"; - } -} - -const char *socket_gaistrerror(int err) { - if (err == 0) return NULL; - switch (err) { - case EAI_AGAIN: return PIE_AGAIN; - case EAI_BADFLAGS: return PIE_BADFLAGS; -#ifdef EAI_BADHINTS - case EAI_BADHINTS: return PIE_BADHINTS; -#endif - case EAI_FAIL: return PIE_FAIL; - case EAI_FAMILY: return PIE_FAMILY; - case EAI_MEMORY: return PIE_MEMORY; - case EAI_NONAME: return PIE_NONAME; -#ifdef EAI_OVERFLOW - case EAI_OVERFLOW: return PIE_OVERFLOW; -#endif -#ifdef EAI_PROTOCOL - case EAI_PROTOCOL: return PIE_PROTOCOL; -#endif - case EAI_SERVICE: return PIE_SERVICE; - case EAI_SOCKTYPE: return PIE_SOCKTYPE; -#ifdef EAI_SYSTEM - case EAI_SYSTEM: return strerror(errno); -#endif - default: return gai_strerror(err); - } -} diff --git a/src/lua/luasocket/wsocket.h b/src/lua/luasocket/wsocket.h deleted file mode 100644 index 398664026..000000000 --- a/src/lua/luasocket/wsocket.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef WSOCKET_H -#define WSOCKET_H -/*=========================================================================*\ -* Socket compatibilization module for Win32 -* LuaSocket toolkit -\*=========================================================================*/ - -/*=========================================================================*\ -* WinSock include files -\*=========================================================================*/ -#include -#include - -typedef int socklen_t; -typedef SOCKADDR_STORAGE t_sockaddr_storage; -typedef SOCKET t_socket; -typedef t_socket *p_socket; - -#ifndef IPV6_V6ONLY -#define IPV6_V6ONLY 27 -#endif - -#define SOCKET_INVALID (INVALID_SOCKET) - -#ifndef SO_REUSEPORT -#define SO_REUSEPORT SO_REUSEADDR -#endif - -#ifndef AI_NUMERICSERV -#define AI_NUMERICSERV (0) -#endif - -#endif /* WSOCKET_H */ diff --git a/src/lua/meson.build b/src/lua/meson.build index f9baadfa9..a868322f2 100644 --- a/src/lua/meson.build +++ b/src/lua/meson.build @@ -10,11 +10,11 @@ luaconsole_files = files( 'LuaScriptInterface.cpp', 'LuaSlider.cpp', 'LuaSmartRef.cpp', + 'LuaTCPSocket.cpp', 'LuaTextbox.cpp', 'LuaWindow.cpp', ) -subdir('luasocket') subdir('luascripts') powder_files += luaconsole_files