diff options
| author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-01-17 00:17:46 +0000 |
|---|---|---|
| committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-01-17 00:17:46 +0000 |
| commit | 076451c75336b30e6152bd5c02f355db39107f7d (patch) | |
| tree | 785a6c71ca1e5246f2ce09a9b91f98eb902ac2a0 | |
| parent | 89f3ecf7820857f91c4039536d2bbe3cf12d5f95 (diff) | |
| download | luasocket-076451c75336b30e6152bd5c02f355db39107f7d.tar.gz luasocket-076451c75336b30e6152bd5c02f355db39107f7d.tar.bz2 luasocket-076451c75336b30e6152bd5c02f355db39107f7d.zip | |
Tested in windows. Still needs more testing, but progress has been made.
| -rw-r--r-- | TODO | 11 | ||||
| -rw-r--r-- | luasocket.sln | 23 | ||||
| -rw-r--r-- | luasocket.vcproj | 216 | ||||
| -rw-r--r-- | src/inet.h | 4 | ||||
| -rw-r--r-- | src/luasocket.h | 2 | ||||
| -rw-r--r-- | src/tcp.c | 18 | ||||
| -rw-r--r-- | src/timeout.c | 1 | ||||
| -rw-r--r-- | src/udp.c | 75 | ||||
| -rw-r--r-- | src/usocket.c | 92 | ||||
| -rw-r--r-- | src/wsocket.c | 180 | ||||
| -rw-r--r-- | test/testclnt.lua | 294 |
11 files changed, 620 insertions, 296 deletions
| @@ -1,8 +1,13 @@ | |||
| 1 | change send/recv to avoid using select | ||
| 2 | 1 | ||
| 2 | |||
| 3 | |||
| 4 | check for interrupt compliance | ||
| 5 | add connect with timeout | ||
| 3 | add gethostname and use it in HTTP, SMTP etc, and add manual entry. | 6 | add gethostname and use it in HTTP, SMTP etc, and add manual entry. |
| 7 | |||
| 4 | add local connect, and manual entry | 8 | add local connect, and manual entry |
| 5 | add shutdown, and manual entry | 9 | |
| 10 | add shutdown manual entry | ||
| 6 | 11 | ||
| 7 | only allocate in case of success | 12 | only allocate in case of success |
| 8 | only call select if io fails... | 13 | only call select if io fails... |
| @@ -65,6 +70,8 @@ Ajeitar o protocolo da luaopen_socket()... sei lá qual é. | |||
| 65 | - testar os options! | 70 | - testar os options! |
| 66 | - adicionar exemplos de expansão: pipe, local, named pipe | 71 | - adicionar exemplos de expansão: pipe, local, named pipe |
| 67 | 72 | ||
| 73 | * add shutdown | ||
| 74 | * change send/recv to avoid using select | ||
| 68 | * O location do "redirect" pode ser relativo ao servidor atual (não pode, | 75 | * O location do "redirect" pode ser relativo ao servidor atual (não pode, |
| 69 | mas os servidores fazem merda...) | 76 | mas os servidores fazem merda...) |
| 70 | * Ajeitar para Lua 5.0 | 77 | * Ajeitar para Lua 5.0 |
diff --git a/luasocket.sln b/luasocket.sln new file mode 100644 index 0000000..25fe127 --- /dev/null +++ b/luasocket.sln | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | Microsoft Visual Studio Solution File, Format Version 8.00 | ||
| 2 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "luasocket", "luasocket.vcproj", "{4FAAB633-F0E7-4D12-B680-D150A0DD7268}" | ||
| 3 | ProjectSection(ProjectDependencies) = postProject | ||
| 4 | EndProjectSection | ||
| 5 | EndProject | ||
| 6 | Global | ||
| 7 | GlobalSection(SolutionConfiguration) = preSolution | ||
| 8 | Debug = Debug | ||
| 9 | Release = Release | ||
| 10 | EndGlobalSection | ||
| 11 | GlobalSection(ProjectConfiguration) = postSolution | ||
| 12 | {4FAAB633-F0E7-4D12-B680-D150A0DD7268}.Debug.ActiveCfg = Debug|Win32 | ||
| 13 | {4FAAB633-F0E7-4D12-B680-D150A0DD7268}.Debug.Build.0 = Debug|Win32 | ||
| 14 | {4FAAB633-F0E7-4D12-B680-D150A0DD7268}.Release.ActiveCfg = Release|Win32 | ||
| 15 | {4FAAB633-F0E7-4D12-B680-D150A0DD7268}.Release.Build.0 = Release|Win32 | ||
| 16 | EndGlobalSection | ||
| 17 | GlobalSection(SolutionItems) = postSolution | ||
| 18 | EndGlobalSection | ||
| 19 | GlobalSection(ExtensibilityGlobals) = postSolution | ||
| 20 | EndGlobalSection | ||
| 21 | GlobalSection(ExtensibilityAddIns) = postSolution | ||
| 22 | EndGlobalSection | ||
| 23 | EndGlobal | ||
diff --git a/luasocket.vcproj b/luasocket.vcproj new file mode 100644 index 0000000..b5c4d53 --- /dev/null +++ b/luasocket.vcproj | |||
| @@ -0,0 +1,216 @@ | |||
| 1 | <?xml version="1.0" encoding="Windows-1252"?> | ||
| 2 | <VisualStudioProject | ||
| 3 | ProjectType="Visual C++" | ||
| 4 | Version="7.10" | ||
| 5 | Name="luasocket" | ||
| 6 | ProjectGUID="{4FAAB633-F0E7-4D12-B680-D150A0DD7268}" | ||
| 7 | Keyword="Win32Proj"> | ||
| 8 | <Platforms> | ||
| 9 | <Platform | ||
| 10 | Name="Win32"/> | ||
| 11 | </Platforms> | ||
| 12 | <Configurations> | ||
| 13 | <Configuration | ||
| 14 | Name="Debug|Win32" | ||
| 15 | OutputDirectory="." | ||
| 16 | IntermediateDirectory="." | ||
| 17 | ConfigurationType="1" | ||
| 18 | CharacterSet="2"> | ||
| 19 | <Tool | ||
| 20 | Name="VCCLCompilerTool" | ||
| 21 | Optimization="0" | ||
| 22 | AdditionalIncludeDirectories="net/include" | ||
| 23 | PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE, LUASOCKET_DEBUG" | ||
| 24 | MinimalRebuild="TRUE" | ||
| 25 | BasicRuntimeChecks="3" | ||
| 26 | RuntimeLibrary="5" | ||
| 27 | UsePrecompiledHeader="0" | ||
| 28 | WarningLevel="3" | ||
| 29 | Detect64BitPortabilityProblems="TRUE" | ||
| 30 | DebugInformationFormat="4"/> | ||
| 31 | <Tool | ||
| 32 | Name="VCCustomBuildTool"/> | ||
| 33 | <Tool | ||
| 34 | Name="VCLinkerTool" | ||
| 35 | AdditionalDependencies="lua.lib lualib.lib ws2_32.lib" | ||
| 36 | OutputFile="$(OutDir)/luasocket.exe" | ||
| 37 | LinkIncremental="2" | ||
| 38 | AdditionalLibraryDirectories="net/lib" | ||
| 39 | GenerateDebugInformation="TRUE" | ||
| 40 | ProgramDatabaseFile="$(OutDir)/luasocket.pdb" | ||
| 41 | SubSystem="1" | ||
| 42 | TargetMachine="1"/> | ||
| 43 | <Tool | ||
| 44 | Name="VCMIDLTool"/> | ||
| 45 | <Tool | ||
| 46 | Name="VCPostBuildEventTool"/> | ||
| 47 | <Tool | ||
| 48 | Name="VCPreBuildEventTool"/> | ||
| 49 | <Tool | ||
| 50 | Name="VCPreLinkEventTool"/> | ||
| 51 | <Tool | ||
| 52 | Name="VCResourceCompilerTool"/> | ||
| 53 | <Tool | ||
| 54 | Name="VCWebServiceProxyGeneratorTool"/> | ||
| 55 | <Tool | ||
| 56 | Name="VCXMLDataGeneratorTool"/> | ||
| 57 | <Tool | ||
| 58 | Name="VCWebDeploymentTool"/> | ||
| 59 | <Tool | ||
| 60 | Name="VCManagedWrapperGeneratorTool"/> | ||
| 61 | <Tool | ||
| 62 | Name="VCAuxiliaryManagedWrapperGeneratorTool"/> | ||
| 63 | </Configuration> | ||
| 64 | <Configuration | ||
| 65 | Name="Release|Win32" | ||
| 66 | OutputDirectory="." | ||
| 67 | IntermediateDirectory="." | ||
| 68 | ConfigurationType="1" | ||
| 69 | CharacterSet="2"> | ||
| 70 | <Tool | ||
| 71 | Name="VCCLCompilerTool" | ||
| 72 | AdditionalIncludeDirectories="net/include" | ||
| 73 | PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE, LUASOCKET_DEBUG" | ||
| 74 | RuntimeLibrary="4" | ||
| 75 | UsePrecompiledHeader="0" | ||
| 76 | WarningLevel="3" | ||
| 77 | Detect64BitPortabilityProblems="TRUE" | ||
| 78 | DebugInformationFormat="3"/> | ||
| 79 | <Tool | ||
| 80 | Name="VCCustomBuildTool"/> | ||
| 81 | <Tool | ||
| 82 | Name="VCLinkerTool" | ||
| 83 | AdditionalDependencies="lua.lib lualib.lib ws2_32.lib" | ||
| 84 | OutputFile="$(OutDir)/luasocket.exe" | ||
| 85 | LinkIncremental="1" | ||
| 86 | AdditionalLibraryDirectories="net/lib" | ||
| 87 | GenerateDebugInformation="TRUE" | ||
| 88 | SubSystem="1" | ||
| 89 | OptimizeReferences="2" | ||
| 90 | EnableCOMDATFolding="2" | ||
| 91 | TargetMachine="1"/> | ||
| 92 | <Tool | ||
| 93 | Name="VCMIDLTool"/> | ||
| 94 | <Tool | ||
| 95 | Name="VCPostBuildEventTool"/> | ||
| 96 | <Tool | ||
| 97 | Name="VCPreBuildEventTool"/> | ||
| 98 | <Tool | ||
| 99 | Name="VCPreLinkEventTool"/> | ||
| 100 | <Tool | ||
| 101 | Name="VCResourceCompilerTool"/> | ||
| 102 | <Tool | ||
| 103 | Name="VCWebServiceProxyGeneratorTool"/> | ||
| 104 | <Tool | ||
| 105 | Name="VCXMLDataGeneratorTool"/> | ||
| 106 | <Tool | ||
| 107 | Name="VCWebDeploymentTool"/> | ||
| 108 | <Tool | ||
| 109 | Name="VCManagedWrapperGeneratorTool"/> | ||
| 110 | <Tool | ||
| 111 | Name="VCAuxiliaryManagedWrapperGeneratorTool"/> | ||
| 112 | </Configuration> | ||
| 113 | </Configurations> | ||
| 114 | <References> | ||
| 115 | </References> | ||
| 116 | <Files> | ||
| 117 | <Filter | ||
| 118 | Name="Source Files" | ||
| 119 | Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx" | ||
| 120 | UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"> | ||
| 121 | <File | ||
| 122 | RelativePath=".\auxiliar.c"> | ||
| 123 | </File> | ||
| 124 | <File | ||
| 125 | RelativePath=".\buffer.c"> | ||
| 126 | </File> | ||
| 127 | <File | ||
| 128 | RelativePath=".\code.c"> | ||
| 129 | </File> | ||
| 130 | <File | ||
| 131 | RelativePath=".\error.c"> | ||
| 132 | </File> | ||
| 133 | <File | ||
| 134 | RelativePath=".\inet.c"> | ||
| 135 | </File> | ||
| 136 | <File | ||
| 137 | RelativePath=".\io.c"> | ||
| 138 | </File> | ||
| 139 | <File | ||
| 140 | RelativePath=".\lua.c"> | ||
| 141 | </File> | ||
| 142 | <File | ||
| 143 | RelativePath=".\luasocket.c"> | ||
| 144 | </File> | ||
| 145 | <File | ||
| 146 | RelativePath=".\select.c"> | ||
| 147 | </File> | ||
| 148 | <File | ||
| 149 | RelativePath=".\tcp.c"> | ||
| 150 | </File> | ||
| 151 | <File | ||
| 152 | RelativePath=".\timeout.c"> | ||
| 153 | </File> | ||
| 154 | <File | ||
| 155 | RelativePath=".\udp.c"> | ||
| 156 | </File> | ||
| 157 | <File | ||
| 158 | RelativePath=".\wsocket.c"> | ||
| 159 | </File> | ||
| 160 | </Filter> | ||
| 161 | <Filter | ||
| 162 | Name="Header Files" | ||
| 163 | Filter="h;hpp;hxx;hm;inl;inc;xsd" | ||
| 164 | UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"> | ||
| 165 | <File | ||
| 166 | RelativePath=".\auxiliar.h"> | ||
| 167 | </File> | ||
| 168 | <File | ||
| 169 | RelativePath=".\buffer.h"> | ||
| 170 | </File> | ||
| 171 | <File | ||
| 172 | RelativePath=".\code.h"> | ||
| 173 | </File> | ||
| 174 | <File | ||
| 175 | RelativePath=".\error.h"> | ||
| 176 | </File> | ||
| 177 | <File | ||
| 178 | RelativePath=".\inet.h"> | ||
| 179 | </File> | ||
| 180 | <File | ||
| 181 | RelativePath=".\io.h"> | ||
| 182 | </File> | ||
| 183 | <File | ||
| 184 | RelativePath=".\luasocket.h"> | ||
| 185 | </File> | ||
| 186 | <File | ||
| 187 | RelativePath=".\select.h"> | ||
| 188 | </File> | ||
| 189 | <File | ||
| 190 | RelativePath=".\socket.h"> | ||
| 191 | </File> | ||
| 192 | <File | ||
| 193 | RelativePath=".\stdafx.h"> | ||
| 194 | </File> | ||
| 195 | <File | ||
| 196 | RelativePath=".\tcp.h"> | ||
| 197 | </File> | ||
| 198 | <File | ||
| 199 | RelativePath=".\timeout.h"> | ||
| 200 | </File> | ||
| 201 | <File | ||
| 202 | RelativePath=".\udp.h"> | ||
| 203 | </File> | ||
| 204 | <File | ||
| 205 | RelativePath=".\wsocket.h"> | ||
| 206 | </File> | ||
| 207 | </Filter> | ||
| 208 | <Filter | ||
| 209 | Name="Resource Files" | ||
| 210 | Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx" | ||
| 211 | UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"> | ||
| 212 | </Filter> | ||
| 213 | </Files> | ||
| 214 | <Globals> | ||
| 215 | </Globals> | ||
| 216 | </VisualStudioProject> | ||
| @@ -19,6 +19,10 @@ | |||
| 19 | #include <lua.h> | 19 | #include <lua.h> |
| 20 | #include "socket.h" | 20 | #include "socket.h" |
| 21 | 21 | ||
| 22 | #ifdef WIN32 | ||
| 23 | #define INET_ATON | ||
| 24 | #endif | ||
| 25 | |||
| 22 | void inet_open(lua_State *L); | 26 | void inet_open(lua_State *L); |
| 23 | const char *inet_tryconnect(p_sock ps, const char *address, | 27 | const char *inet_tryconnect(p_sock ps, const char *address, |
| 24 | unsigned short port); | 28 | unsigned short port); |
diff --git a/src/luasocket.h b/src/luasocket.h index 7756605..ac26824 100644 --- a/src/luasocket.h +++ b/src/luasocket.h | |||
| @@ -18,7 +18,9 @@ | |||
| 18 | /*-------------------------------------------------------------------------*\ | 18 | /*-------------------------------------------------------------------------*\ |
| 19 | * Library's namespace | 19 | * Library's namespace |
| 20 | \*-------------------------------------------------------------------------*/ | 20 | \*-------------------------------------------------------------------------*/ |
| 21 | #ifndef LUASOCKET_LIBNAME | ||
| 21 | #define LUASOCKET_LIBNAME "socket" | 22 | #define LUASOCKET_LIBNAME "socket" |
| 23 | #endif | ||
| 22 | 24 | ||
| 23 | /*-------------------------------------------------------------------------*\ | 25 | /*-------------------------------------------------------------------------*\ |
| 24 | * This macro prefixes all exported API functions | 26 | * This macro prefixes all exported API functions |
| @@ -36,6 +36,7 @@ static int meth_dirty(lua_State *L); | |||
| 36 | static int opt_tcp_nodelay(lua_State *L); | 36 | static int opt_tcp_nodelay(lua_State *L); |
| 37 | static int opt_keepalive(lua_State *L); | 37 | static int opt_keepalive(lua_State *L); |
| 38 | static int opt_linger(lua_State *L); | 38 | static int opt_linger(lua_State *L); |
| 39 | static int opt_reuseaddr(lua_State *L); | ||
| 39 | 40 | ||
| 40 | /* tcp object methods */ | 41 | /* tcp object methods */ |
| 41 | static luaL_reg tcp[] = { | 42 | static luaL_reg tcp[] = { |
| @@ -61,6 +62,7 @@ static luaL_reg tcp[] = { | |||
| 61 | /* socket option handlers */ | 62 | /* socket option handlers */ |
| 62 | static luaL_reg opt[] = { | 63 | static luaL_reg opt[] = { |
| 63 | {"keepalive", opt_keepalive}, | 64 | {"keepalive", opt_keepalive}, |
| 65 | {"reuseaddr", opt_reuseaddr}, | ||
| 64 | {"tcp-nodelay", opt_tcp_nodelay}, | 66 | {"tcp-nodelay", opt_tcp_nodelay}, |
| 65 | {"linger", opt_linger}, | 67 | {"linger", opt_linger}, |
| 66 | {NULL, NULL} | 68 | {NULL, NULL} |
| @@ -123,7 +125,7 @@ static int meth_setoption(lua_State *L) | |||
| 123 | 125 | ||
| 124 | static int opt_boolean(lua_State *L, int level, int name) | 126 | static int opt_boolean(lua_State *L, int level, int name) |
| 125 | { | 127 | { |
| 126 | p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client,server}", 1); | 128 | p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1); |
| 127 | int val = aux_checkboolean(L, 2); | 129 | int val = aux_checkboolean(L, 2); |
| 128 | if (setsockopt(tcp->sock, level, name, (char *) &val, sizeof(val)) < 0) { | 130 | if (setsockopt(tcp->sock, level, name, (char *) &val, sizeof(val)) < 0) { |
| 129 | lua_pushnil(L); | 131 | lua_pushnil(L); |
| @@ -134,16 +136,16 @@ static int opt_boolean(lua_State *L, int level, int name) | |||
| 134 | return 1; | 136 | return 1; |
| 135 | } | 137 | } |
| 136 | 138 | ||
| 139 | /* enables reuse of local address */ | ||
| 140 | static int opt_reuseaddr(lua_State *L) | ||
| 141 | { | ||
| 142 | return opt_boolean(L, SOL_SOCKET, SO_REUSEADDR); | ||
| 143 | } | ||
| 144 | |||
| 137 | /* disables the Naggle algorithm */ | 145 | /* disables the Naggle algorithm */ |
| 138 | static int opt_tcp_nodelay(lua_State *L) | 146 | static int opt_tcp_nodelay(lua_State *L) |
| 139 | { | 147 | { |
| 140 | struct protoent *pe = getprotobyname("TCP"); | 148 | return opt_boolean(L, IPPROTO_TCP, TCP_NODELAY); |
| 141 | if (!pe) { | ||
| 142 | lua_pushnil(L); | ||
| 143 | lua_pushstring(L, "getprotobyname"); | ||
| 144 | return 2; | ||
| 145 | } | ||
| 146 | return opt_boolean(L, pe->p_proto, TCP_NODELAY); | ||
| 147 | } | 149 | } |
| 148 | 150 | ||
| 149 | static int opt_keepalive(lua_State *L) | 151 | static int opt_keepalive(lua_State *L) |
diff --git a/src/timeout.c b/src/timeout.c index 5d6de99..2d88ded 100644 --- a/src/timeout.c +++ b/src/timeout.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #ifdef WIN32 | 16 | #ifdef WIN32 |
| 17 | #include <windows.h> | 17 | #include <windows.h> |
| 18 | #else | 18 | #else |
| 19 | #include <time.h> | ||
| 19 | #include <sys/time.h> | 20 | #include <sys/time.h> |
| 20 | #include <sys/times.h> | 21 | #include <sys/times.h> |
| 21 | #include <unistd.h> | 22 | #include <unistd.h> |
| @@ -35,6 +35,11 @@ static int meth_fd(lua_State *L); | |||
| 35 | static int meth_dirty(lua_State *L); | 35 | static int meth_dirty(lua_State *L); |
| 36 | static int opt_dontroute(lua_State *L); | 36 | static int opt_dontroute(lua_State *L); |
| 37 | static int opt_broadcast(lua_State *L); | 37 | static int opt_broadcast(lua_State *L); |
| 38 | static int opt_reuseaddr(lua_State *L); | ||
| 39 | static int opt_ip_multicast_ttl(lua_State *L); | ||
| 40 | static int opt_ip_multicast_loop(lua_State *L); | ||
| 41 | static int opt_ip_add_membership(lua_State *L); | ||
| 42 | static int opt_ip_drop_membersip(lua_State *L); | ||
| 38 | 43 | ||
| 39 | /* udp object methods */ | 44 | /* udp object methods */ |
| 40 | static luaL_reg udp[] = { | 45 | static luaL_reg udp[] = { |
| @@ -57,8 +62,13 @@ static luaL_reg udp[] = { | |||
| 57 | 62 | ||
| 58 | /* socket options */ | 63 | /* socket options */ |
| 59 | static luaL_reg opt[] = { | 64 | static luaL_reg opt[] = { |
| 60 | {"dontroute", opt_dontroute}, | 65 | {"dontroute", opt_dontroute}, |
| 61 | {"broadcast", opt_broadcast}, | 66 | {"broadcast", opt_broadcast}, |
| 67 | {"reuseaddr", opt_reuseaddr}, | ||
| 68 | {"ip-multicast-ttl", opt_ip_multicast_ttl}, | ||
| 69 | {"ip-multicast-loop", opt_ip_multicast_loop}, | ||
| 70 | {"ip-add-membership", opt_ip_add_membership}, | ||
| 71 | {"ip-drop-membership", opt_ip_drop_membersip}, | ||
| 62 | {NULL, NULL} | 72 | {NULL, NULL} |
| 63 | }; | 73 | }; |
| 64 | 74 | ||
| @@ -244,11 +254,72 @@ static int opt_dontroute(lua_State *L) | |||
| 244 | return opt_boolean(L, SOL_SOCKET, SO_DONTROUTE); | 254 | return opt_boolean(L, SOL_SOCKET, SO_DONTROUTE); |
| 245 | } | 255 | } |
| 246 | 256 | ||
| 257 | static int opt_reuseaddr(lua_State *L) | ||
| 258 | { | ||
| 259 | return opt_boolean(L, SOL_SOCKET, SO_REUSEADDR); | ||
| 260 | } | ||
| 261 | |||
| 247 | static int opt_broadcast(lua_State *L) | 262 | static int opt_broadcast(lua_State *L) |
| 248 | { | 263 | { |
| 249 | return opt_boolean(L, SOL_SOCKET, SO_BROADCAST); | 264 | return opt_boolean(L, SOL_SOCKET, SO_BROADCAST); |
| 250 | } | 265 | } |
| 251 | 266 | ||
| 267 | static int opt_ip_multicast_loop(lua_State *L) | ||
| 268 | { | ||
| 269 | return opt_boolean(L, IPPROTO_IP, IP_MULTICAST_LOOP); | ||
| 270 | } | ||
| 271 | |||
| 272 | static int opt_ip_multicast_ttl(lua_State *L) | ||
| 273 | { | ||
| 274 | p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); | ||
| 275 | int val = (int) luaL_checknumber(L, 2); | ||
| 276 | if (setsockopt(udp->sock, IPPROTO_IP, IP_MULTICAST_TTL, | ||
| 277 | (char *) &val, sizeof(val)) < 0) { | ||
| 278 | lua_pushnil(L); | ||
| 279 | lua_pushstring(L, "setsockopt failed"); | ||
| 280 | return 2; | ||
| 281 | } | ||
| 282 | lua_pushnumber(L, 1); | ||
| 283 | return 1; | ||
| 284 | } | ||
| 285 | |||
| 286 | static int opt_membership(lua_State *L, int level, int name) | ||
| 287 | { | ||
| 288 | p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); | ||
| 289 | struct ip_mreq val; | ||
| 290 | if (!lua_istable(L, 2)) | ||
| 291 | luaL_typerror(L, 2, lua_typename(L, LUA_TTABLE)); | ||
| 292 | lua_pushstring(L, "multiaddr"); | ||
| 293 | lua_gettable(L, 2); | ||
| 294 | if (!lua_isstring(L, -1)) luaL_argerror(L, 2, "invalid 'group' field"); | ||
| 295 | if (!inet_aton(lua_tostring(L, -1), &val.imr_multiaddr)) | ||
| 296 | luaL_argerror(L, 3, "invalid 'multiaddr' ip address"); | ||
| 297 | lua_pushstring(L, "interface"); | ||
| 298 | lua_gettable(L, 2); | ||
| 299 | if (!lua_isstring(L, -1)) luaL_argerror(L, 2, "invalid 'interface' field"); | ||
| 300 | val.imr_interface.s_addr = htonl(INADDR_ANY); | ||
| 301 | if (strcmp(lua_tostring(L, -1), "*") && | ||
| 302 | !inet_aton(lua_tostring(L, -1), &val.imr_interface)) | ||
| 303 | luaL_argerror(L, 3, "invalid 'interface' ip address"); | ||
| 304 | if (setsockopt(udp->sock, level, name, (char *) &val, sizeof(val)) < 0) { | ||
| 305 | lua_pushnil(L); | ||
| 306 | lua_pushstring(L, "setsockopt failed"); | ||
| 307 | return 2; | ||
| 308 | } | ||
| 309 | lua_pushnumber(L, 1); | ||
| 310 | return 1; | ||
| 311 | } | ||
| 312 | |||
| 313 | static int opt_ip_add_membership(lua_State *L) | ||
| 314 | { | ||
| 315 | return opt_membership(L, IPPROTO_IP, IP_ADD_MEMBERSHIP); | ||
| 316 | } | ||
| 317 | |||
| 318 | static int opt_ip_drop_membersip(lua_State *L) | ||
| 319 | { | ||
| 320 | return opt_membership(L, IPPROTO_IP, IP_DROP_MEMBERSHIP); | ||
| 321 | } | ||
| 322 | |||
| 252 | /*-------------------------------------------------------------------------*\ | 323 | /*-------------------------------------------------------------------------*\ |
| 253 | * Just call tm methods | 324 | * Just call tm methods |
| 254 | \*-------------------------------------------------------------------------*/ | 325 | \*-------------------------------------------------------------------------*/ |
diff --git a/src/usocket.c b/src/usocket.c index f2d9f01..89be85e 100644 --- a/src/usocket.c +++ b/src/usocket.c | |||
| @@ -145,7 +145,7 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, | |||
| 145 | else return IO_TIMEOUT; | 145 | else return IO_TIMEOUT; |
| 146 | /* here we know the connection has been closed */ | 146 | /* here we know the connection has been closed */ |
| 147 | } else return IO_CLOSED; | 147 | } else return IO_CLOSED; |
| 148 | /* here we sent successfully sent something */ | 148 | /* here we successfully sent something */ |
| 149 | } else { | 149 | } else { |
| 150 | *sent = put; | 150 | *sent = put; |
| 151 | return IO_DONE; | 151 | return IO_DONE; |
| @@ -159,34 +159,36 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, | |||
| 159 | SA *addr, socklen_t addr_len, int timeout) | 159 | SA *addr, socklen_t addr_len, int timeout) |
| 160 | { | 160 | { |
| 161 | t_sock sock = *ps; | 161 | t_sock sock = *ps; |
| 162 | struct timeval tv; | 162 | ssize_t put; |
| 163 | fd_set fds; | ||
| 164 | ssize_t put = 0; | ||
| 165 | int err; | ||
| 166 | int ret; | 163 | int ret; |
| 164 | /* avoid making system calls on closed sockets */ | ||
| 167 | if (sock == SOCK_INVALID) return IO_CLOSED; | 165 | if (sock == SOCK_INVALID) return IO_CLOSED; |
| 168 | tv.tv_sec = timeout / 1000; | 166 | /* make sure we repeat in case the call was interrupted */ |
| 169 | tv.tv_usec = (timeout % 1000) * 1000; | 167 | do put = sendto(sock, data, count, 0, addr, addr_len); |
| 170 | FD_ZERO(&fds); | 168 | while (put <= 0 && errno == EINTR); |
| 171 | FD_SET(sock, &fds); | 169 | /* deal with failure */ |
| 172 | ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL); | 170 | if (put <= 0) { |
| 173 | if (ret > 0) { | 171 | /* in any case, nothing has been sent */ |
| 174 | put = sendto(sock, data, count, 0, addr, addr_len); | ||
| 175 | if (put <= 0) { | ||
| 176 | err = IO_CLOSED; | ||
| 177 | #ifdef __CYGWIN__ | ||
| 178 | /* this is for CYGWIN, which is like Unix but has Win32 bugs */ | ||
| 179 | if (sent < 0 && errno == EWOULDBLOCK) err = IO_DONE; | ||
| 180 | #endif | ||
| 181 | *sent = 0; | ||
| 182 | } else { | ||
| 183 | *sent = put; | ||
| 184 | err = IO_DONE; | ||
| 185 | } | ||
| 186 | return err; | ||
| 187 | } else { | ||
| 188 | *sent = 0; | 172 | *sent = 0; |
| 189 | return IO_TIMEOUT; | 173 | /* run select to avoid busy wait */ |
| 174 | if (errno != EPIPE) { | ||
| 175 | struct timeval tv; | ||
| 176 | fd_set fds; | ||
| 177 | tv.tv_sec = timeout / 1000; | ||
| 178 | tv.tv_usec = (timeout % 1000) * 1000; | ||
| 179 | FD_ZERO(&fds); | ||
| 180 | FD_SET(sock, &fds); | ||
| 181 | ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL); | ||
| 182 | /* tell the caller to call us again because there is more data */ | ||
| 183 | if (ret > 0) return IO_DONE; | ||
| 184 | /* tell the caller there was no data before timeout */ | ||
| 185 | else return IO_TIMEOUT; | ||
| 186 | /* here we know the connection has been closed */ | ||
| 187 | } else return IO_CLOSED; | ||
| 188 | /* here we successfully sent something */ | ||
| 189 | } else { | ||
| 190 | *sent = put; | ||
| 191 | return IO_DONE; | ||
| 190 | } | 192 | } |
| 191 | } | 193 | } |
| 192 | 194 | ||
| @@ -232,28 +234,26 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, | |||
| 232 | SA *addr, socklen_t *addr_len, int timeout) | 234 | SA *addr, socklen_t *addr_len, int timeout) |
| 233 | { | 235 | { |
| 234 | t_sock sock = *ps; | 236 | t_sock sock = *ps; |
| 235 | struct timeval tv; | 237 | ssize_t taken; |
| 236 | fd_set fds; | ||
| 237 | int ret; | ||
| 238 | if (sock == SOCK_INVALID) return IO_CLOSED; | 238 | if (sock == SOCK_INVALID) return IO_CLOSED; |
| 239 | ssize_t taken = 0; | 239 | do taken = recvfrom(sock, data, count, 0, addr, addr_len); |
| 240 | tv.tv_sec = timeout / 1000; | 240 | while (taken <= 0 && errno == EINTR); |
| 241 | tv.tv_usec = (timeout % 1000) * 1000; | 241 | if (taken <= 0) { |
| 242 | FD_ZERO(&fds); | 242 | struct timeval tv; |
| 243 | FD_SET(sock, &fds); | 243 | fd_set fds; |
| 244 | ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); | 244 | int ret; |
| 245 | if (ret > 0) { | ||
| 246 | taken = recvfrom(sock, data, count, 0, addr, addr_len); | ||
| 247 | if (taken <= 0) { | ||
| 248 | *got = 0; | ||
| 249 | return IO_CLOSED; | ||
| 250 | } else { | ||
| 251 | *got = taken; | ||
| 252 | return IO_DONE; | ||
| 253 | } | ||
| 254 | } else { | ||
| 255 | *got = 0; | 245 | *got = 0; |
| 256 | return IO_TIMEOUT; | 246 | if (taken == 0) return IO_CLOSED; |
| 247 | tv.tv_sec = timeout / 1000; | ||
| 248 | tv.tv_usec = (timeout % 1000) * 1000; | ||
| 249 | FD_ZERO(&fds); | ||
| 250 | FD_SET(sock, &fds); | ||
| 251 | ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); | ||
| 252 | if (ret > 0) return IO_DONE; | ||
| 253 | else return IO_TIMEOUT; | ||
| 254 | } else { | ||
| 255 | *got = taken; | ||
| 256 | return IO_DONE; | ||
| 257 | } | 257 | } |
| 258 | } | 258 | } |
| 259 | 259 | ||
diff --git a/src/wsocket.c b/src/wsocket.c index 59d88df..30208b9 100644 --- a/src/wsocket.c +++ b/src/wsocket.c | |||
| @@ -100,7 +100,7 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, | |||
| 100 | FD_ZERO(&fds); | 100 | FD_ZERO(&fds); |
| 101 | FD_SET(sock, &fds); | 101 | FD_SET(sock, &fds); |
| 102 | *pa = SOCK_INVALID; | 102 | *pa = SOCK_INVALID; |
| 103 | if (select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL) <= 0) | 103 | if (select(0, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL) <= 0) |
| 104 | return IO_TIMEOUT; | 104 | return IO_TIMEOUT; |
| 105 | if (!addr) addr = &dummy_addr; | 105 | if (!addr) addr = &dummy_addr; |
| 106 | if (!addr_len) addr_len = &dummy_len; | 106 | if (!addr_len) addr_len = &dummy_len; |
| @@ -116,34 +116,35 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, | |||
| 116 | int timeout) | 116 | int timeout) |
| 117 | { | 117 | { |
| 118 | t_sock sock = *ps; | 118 | t_sock sock = *ps; |
| 119 | struct timeval tv; | 119 | ssize_t put; |
| 120 | fd_set fds; | ||
| 121 | ssize_t put = 0; | ||
| 122 | if (sock == SOCK_INVALID) return IO_CLOSED; | ||
| 123 | int err; | ||
| 124 | int ret; | 120 | int ret; |
| 125 | tv.tv_sec = timeout / 1000; | 121 | /* avoid making system calls on closed sockets */ |
| 126 | tv.tv_usec = (timeout % 1000) * 1000; | 122 | if (sock == SOCK_INVALID) return IO_CLOSED; |
| 127 | FD_ZERO(&fds); | 123 | /* try to send something */ |
| 128 | FD_SET(sock, &fds); | 124 | put = send(sock, data, (int) count, 0); |
| 129 | ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL); | 125 | /* deal with failure */ |
| 130 | if (ret > 0) { | 126 | if (put <= 0) { |
| 131 | put = send(sock, data, count, 0); | 127 | /* in any case, nothing has been sent */ |
| 132 | if (put <= 0) { | ||
| 133 | /* a bug in WinSock forces us to do a busy wait until we manage | ||
| 134 | ** to write, because select returns immediately even though it | ||
| 135 | ** should have blocked us until we could write... */ | ||
| 136 | if (WSAGetLastError() == WSAEWOULDBLOCK) err = IO_DONE; | ||
| 137 | else err = IO_CLOSED; | ||
| 138 | *sent = 0; | ||
| 139 | } else { | ||
| 140 | *sent = put; | ||
| 141 | err = IO_DONE; | ||
| 142 | } | ||
| 143 | return err; | ||
| 144 | } else { | ||
| 145 | *sent = 0; | 128 | *sent = 0; |
| 146 | return IO_TIMEOUT; | 129 | /* run select to avoid busy wait */ |
| 130 | if (WSAGetLastError() == WSAEWOULDBLOCK) { | ||
| 131 | struct timeval tv; | ||
| 132 | fd_set fds; | ||
| 133 | tv.tv_sec = timeout / 1000; | ||
| 134 | tv.tv_usec = (timeout % 1000) * 1000; | ||
| 135 | FD_ZERO(&fds); | ||
| 136 | FD_SET(sock, &fds); | ||
| 137 | ret = select(0, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL); | ||
| 138 | /* tell the caller to call us again because there is more data */ | ||
| 139 | if (ret > 0) return IO_DONE; | ||
| 140 | /* tell the caller there was no data before timeout */ | ||
| 141 | else return IO_TIMEOUT; | ||
| 142 | /* here we know the connection has been closed */ | ||
| 143 | } else return IO_CLOSED; | ||
| 144 | /* here we successfully sent something */ | ||
| 145 | } else { | ||
| 146 | *sent = put; | ||
| 147 | return IO_DONE; | ||
| 147 | } | 148 | } |
| 148 | } | 149 | } |
| 149 | 150 | ||
| @@ -154,34 +155,35 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, | |||
| 154 | SA *addr, socklen_t addr_len, int timeout) | 155 | SA *addr, socklen_t addr_len, int timeout) |
| 155 | { | 156 | { |
| 156 | t_sock sock = *ps; | 157 | t_sock sock = *ps; |
| 157 | struct timeval tv; | 158 | ssize_t put; |
| 158 | fd_set fds; | ||
| 159 | ssize_t put = 0; | ||
| 160 | int err; | ||
| 161 | int ret; | 159 | int ret; |
| 160 | /* avoid making system calls on closed sockets */ | ||
| 162 | if (sock == SOCK_INVALID) return IO_CLOSED; | 161 | if (sock == SOCK_INVALID) return IO_CLOSED; |
| 163 | tv.tv_sec = timeout / 1000; | 162 | /* try to send something */ |
| 164 | tv.tv_usec = (timeout % 1000) * 1000; | 163 | put = sendto(sock, data, (int) count, 0, addr, addr_len); |
| 165 | FD_ZERO(&fds); | 164 | /* deal with failure */ |
| 166 | FD_SET(sock, &fds); | 165 | if (put <= 0) { |
| 167 | ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL); | 166 | /* in any case, nothing has been sent */ |
| 168 | if (ret > 0) { | ||
| 169 | put = sendto(sock, data, count, 0, addr, addr_len); | ||
| 170 | if (put <= 0) { | ||
| 171 | /* a bug in WinSock forces us to do a busy wait until we manage | ||
| 172 | ** to write, because select returns immediately even though it | ||
| 173 | ** should have blocked us until we could write... */ | ||
| 174 | if (WSAGetLastError() == WSAEWOULDBLOCK) err = IO_DONE; | ||
| 175 | else err = IO_CLOSED; | ||
| 176 | *sent = 0; | ||
| 177 | } else { | ||
| 178 | *sent = put; | ||
| 179 | err = IO_DONE; | ||
| 180 | } | ||
| 181 | return err; | ||
| 182 | } else { | ||
| 183 | *sent = 0; | 167 | *sent = 0; |
| 184 | return IO_TIMEOUT; | 168 | /* run select to avoid busy wait */ |
| 169 | if (WSAGetLastError() == WSAEWOULDBLOCK) { | ||
| 170 | struct timeval tv; | ||
| 171 | fd_set fds; | ||
| 172 | tv.tv_sec = timeout / 1000; | ||
| 173 | tv.tv_usec = (timeout % 1000) * 1000; | ||
| 174 | FD_ZERO(&fds); | ||
| 175 | FD_SET(sock, &fds); | ||
| 176 | ret = select(0, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL); | ||
| 177 | /* tell the caller to call us again because there is more data */ | ||
| 178 | if (ret > 0) return IO_DONE; | ||
| 179 | /* tell the caller there was no data before timeout */ | ||
| 180 | else return IO_TIMEOUT; | ||
| 181 | /* here we know the connection has been closed */ | ||
| 182 | } else return IO_CLOSED; | ||
| 183 | /* here we successfully sent something */ | ||
| 184 | } else { | ||
| 185 | *sent = put; | ||
| 186 | return IO_DONE; | ||
| 185 | } | 187 | } |
| 186 | } | 188 | } |
| 187 | 189 | ||
| @@ -191,28 +193,25 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, | |||
| 191 | int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) | 193 | int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) |
| 192 | { | 194 | { |
| 193 | t_sock sock = *ps; | 195 | t_sock sock = *ps; |
| 194 | struct timeval tv; | 196 | ssize_t taken; |
| 195 | fd_set fds; | ||
| 196 | int ret; | ||
| 197 | ssize_t taken = 0; | ||
| 198 | if (sock == SOCK_INVALID) return IO_CLOSED; | 197 | if (sock == SOCK_INVALID) return IO_CLOSED; |
| 199 | tv.tv_sec = timeout / 1000; | 198 | taken = recv(sock, data, (int) count, 0); |
| 200 | tv.tv_usec = (timeout % 1000) * 1000; | 199 | if (taken <= 0) { |
| 201 | FD_ZERO(&fds); | 200 | struct timeval tv; |
| 202 | FD_SET(sock, &fds); | 201 | fd_set fds; |
| 203 | ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); | 202 | int ret; |
| 204 | if (ret > 0) { | ||
| 205 | taken = recv(sock, data, count, 0); | ||
| 206 | if (taken <= 0) { | ||
| 207 | *got = 0; | ||
| 208 | return IO_CLOSED; | ||
| 209 | } else { | ||
| 210 | *got = taken; | ||
| 211 | return IO_DONE; | ||
| 212 | } | ||
| 213 | } else { | ||
| 214 | *got = 0; | 203 | *got = 0; |
| 215 | return IO_TIMEOUT; | 204 | if (taken == 0) return IO_CLOSED; |
| 205 | tv.tv_sec = timeout / 1000; | ||
| 206 | tv.tv_usec = (timeout % 1000) * 1000; | ||
| 207 | FD_ZERO(&fds); | ||
| 208 | FD_SET(sock, &fds); | ||
| 209 | ret = select(0, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); | ||
| 210 | if (ret > 0) return IO_DONE; | ||
| 211 | else return IO_TIMEOUT; | ||
| 212 | } else { | ||
| 213 | *got = taken; | ||
| 214 | return IO_DONE; | ||
| 216 | } | 215 | } |
| 217 | } | 216 | } |
| 218 | 217 | ||
| @@ -223,28 +222,25 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, | |||
| 223 | SA *addr, socklen_t *addr_len, int timeout) | 222 | SA *addr, socklen_t *addr_len, int timeout) |
| 224 | { | 223 | { |
| 225 | t_sock sock = *ps; | 224 | t_sock sock = *ps; |
| 226 | struct timeval tv; | 225 | ssize_t taken; |
| 227 | fd_set fds; | ||
| 228 | int ret; | ||
| 229 | ssize_t taken = 0; | ||
| 230 | if (sock == SOCK_INVALID) return IO_CLOSED; | 226 | if (sock == SOCK_INVALID) return IO_CLOSED; |
| 231 | tv.tv_sec = timeout / 1000; | 227 | taken = recvfrom(sock, data, (int) count, 0, addr, addr_len); |
| 232 | tv.tv_usec = (timeout % 1000) * 1000; | 228 | if (taken <= 0) { |
| 233 | FD_ZERO(&fds); | 229 | struct timeval tv; |
| 234 | FD_SET(sock, &fds); | 230 | fd_set fds; |
| 235 | ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); | 231 | int ret; |
| 236 | if (ret > 0) { | ||
| 237 | taken = recvfrom(sock, data, count, 0, addr, addr_len); | ||
| 238 | if (taken <= 0) { | ||
| 239 | *got = 0; | ||
| 240 | return IO_CLOSED; | ||
| 241 | } else { | ||
| 242 | *got = taken; | ||
| 243 | return IO_DONE; | ||
| 244 | } | ||
| 245 | } else { | ||
| 246 | *got = 0; | 232 | *got = 0; |
| 247 | return IO_TIMEOUT; | 233 | if (taken == 0) return IO_CLOSED; |
| 234 | tv.tv_sec = timeout / 1000; | ||
| 235 | tv.tv_usec = (timeout % 1000) * 1000; | ||
| 236 | FD_ZERO(&fds); | ||
| 237 | FD_SET(sock, &fds); | ||
| 238 | ret = select(0, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); | ||
| 239 | if (ret > 0) return IO_DONE; | ||
| 240 | else return IO_TIMEOUT; | ||
| 241 | } else { | ||
| 242 | *got = taken; | ||
| 243 | return IO_DONE; | ||
| 248 | } | 244 | } |
| 249 | } | 245 | } |
| 250 | 246 | ||
diff --git a/test/testclnt.lua b/test/testclnt.lua index 2420711..6b07dca 100644 --- a/test/testclnt.lua +++ b/test/testclnt.lua | |||
| @@ -99,8 +99,6 @@ else pass("connected!") end | |||
| 99 | control:setoption("tcp-nodelay", true) | 99 | control:setoption("tcp-nodelay", true) |
| 100 | 100 | ||
| 101 | ------------------------------------------------------------------------ | 101 | ------------------------------------------------------------------------ |
| 102 | test("method registration") | ||
| 103 | |||
| 104 | function test_methods(sock, methods) | 102 | function test_methods(sock, methods) |
| 105 | for _, v in methods do | 103 | for _, v in methods do |
| 106 | if type(sock[v]) ~= "function" then | 104 | if type(sock[v]) ~= "function" then |
| @@ -110,38 +108,7 @@ function test_methods(sock, methods) | |||
| 110 | pass(sock.class .. " methods are ok") | 108 | pass(sock.class .. " methods are ok") |
| 111 | end | 109 | end |
| 112 | 110 | ||
| 113 | test_methods(socket.tcp(), { | ||
| 114 | "connect", | ||
| 115 | "send", | ||
| 116 | "receive", | ||
| 117 | "bind", | ||
| 118 | "accept", | ||
| 119 | "setpeername", | ||
| 120 | "setsockname", | ||
| 121 | "getpeername", | ||
| 122 | "getsockname", | ||
| 123 | "setoption", | ||
| 124 | "settimeout", | ||
| 125 | "close", | ||
| 126 | }) | ||
| 127 | |||
| 128 | test_methods(socket.udp(), { | ||
| 129 | "getpeername", | ||
| 130 | "getsockname", | ||
| 131 | "setsockname", | ||
| 132 | "setpeername", | ||
| 133 | "send", | ||
| 134 | "sendto", | ||
| 135 | "receive", | ||
| 136 | "receivefrom", | ||
| 137 | "setoption", | ||
| 138 | "settimeout", | ||
| 139 | "close", | ||
| 140 | }) | ||
| 141 | |||
| 142 | ------------------------------------------------------------------------ | 111 | ------------------------------------------------------------------------ |
| 143 | test("mixed patterns") | ||
| 144 | |||
| 145 | function test_mixed(len) | 112 | function test_mixed(len) |
| 146 | reconnect() | 113 | reconnect() |
| 147 | local inter = math.ceil(len/4) | 114 | local inter = math.ceil(len/4) |
| @@ -163,21 +130,7 @@ remote "data:send(str); data:close()" | |||
| 163 | else fail("patterns don't match") end | 130 | else fail("patterns don't match") end |
| 164 | end | 131 | end |
| 165 | 132 | ||
| 166 | |||
| 167 | test_mixed(1) | ||
| 168 | test_mixed(17) | ||
| 169 | test_mixed(200) | ||
| 170 | test_mixed(4091) | ||
| 171 | test_mixed(80199) | ||
| 172 | test_mixed(4091) | ||
| 173 | test_mixed(200) | ||
| 174 | test_mixed(17) | ||
| 175 | test_mixed(1) | ||
| 176 | |||
| 177 | ------------------------------------------------------------------------ | 133 | ------------------------------------------------------------------------ |
| 178 | test("character line") | ||
| 179 | reconnect() | ||
| 180 | |||
| 181 | function test_asciiline(len) | 134 | function test_asciiline(len) |
| 182 | local str, str10, back, err | 135 | local str, str10, back, err |
| 183 | str = string.rep("x", math.mod(len, 10)) | 136 | str = string.rep("x", math.mod(len, 10)) |
| @@ -194,22 +147,7 @@ remote "data:send(str, '\\n')" | |||
| 194 | else fail("lines don't match") end | 147 | else fail("lines don't match") end |
| 195 | end | 148 | end |
| 196 | 149 | ||
| 197 | test_asciiline(1) | ||
| 198 | test_asciiline(17) | ||
| 199 | test_asciiline(200) | ||
| 200 | test_asciiline(4091) | ||
| 201 | test_asciiline(80199) | ||
| 202 | test_asciiline(800000) | ||
| 203 | test_asciiline(80199) | ||
| 204 | test_asciiline(4091) | ||
| 205 | test_asciiline(200) | ||
| 206 | test_asciiline(17) | ||
| 207 | test_asciiline(1) | ||
| 208 | |||
| 209 | ------------------------------------------------------------------------ | 150 | ------------------------------------------------------------------------ |
| 210 | test("binary line") | ||
| 211 | reconnect() | ||
| 212 | |||
| 213 | function test_rawline(len) | 151 | function test_rawline(len) |
| 214 | local str, str10, back, err | 152 | local str, str10, back, err |
| 215 | str = string.rep(string.char(47), math.mod(len, 10)) | 153 | str = string.rep(string.char(47), math.mod(len, 10)) |
| @@ -227,22 +165,7 @@ remote "data:send(str, '\\n')" | |||
| 227 | else fail("lines don't match") end | 165 | else fail("lines don't match") end |
| 228 | end | 166 | end |
| 229 | 167 | ||
| 230 | test_rawline(1) | ||
| 231 | test_rawline(17) | ||
| 232 | test_rawline(200) | ||
| 233 | test_rawline(4091) | ||
| 234 | test_rawline(80199) | ||
| 235 | test_rawline(800000) | ||
| 236 | test_rawline(80199) | ||
| 237 | test_rawline(4091) | ||
| 238 | test_rawline(200) | ||
| 239 | test_rawline(17) | ||
| 240 | test_rawline(1) | ||
| 241 | |||
| 242 | ------------------------------------------------------------------------ | 168 | ------------------------------------------------------------------------ |
| 243 | test("raw transfer") | ||
| 244 | reconnect() | ||
| 245 | |||
| 246 | function test_raw(len) | 169 | function test_raw(len) |
| 247 | local half = math.floor(len/2) | 170 | local half = math.floor(len/2) |
| 248 | local s1, s2, back, err | 171 | local s1, s2, back, err |
| @@ -261,38 +184,7 @@ remote "data:send(str)" | |||
| 261 | else fail("blocks don't match") end | 184 | else fail("blocks don't match") end |
| 262 | end | 185 | end |
| 263 | 186 | ||
| 264 | test_raw(1) | ||
| 265 | test_raw(17) | ||
| 266 | test_raw(200) | ||
| 267 | test_raw(4091) | ||
| 268 | test_raw(80199) | ||
| 269 | test_raw(800000) | ||
| 270 | test_raw(80199) | ||
| 271 | test_raw(4091) | ||
| 272 | test_raw(200) | ||
| 273 | test_raw(17) | ||
| 274 | test_raw(1) | ||
| 275 | ------------------------------------------------------------------------ | ||
| 276 | test("non-blocking transfer") | ||
| 277 | reconnect() | ||
| 278 | |||
| 279 | -- the value is not important, we only want | ||
| 280 | -- to test non-blockin I/O anyways | ||
| 281 | data:settimeout(200) | ||
| 282 | test_raw(1) | ||
| 283 | test_raw(17) | ||
| 284 | test_raw(200) | ||
| 285 | test_raw(4091) | ||
| 286 | test_raw(80199) | ||
| 287 | test_raw(800000) | ||
| 288 | test_raw(80199) | ||
| 289 | test_raw(4091) | ||
| 290 | test_raw(200) | ||
| 291 | test_raw(17) | ||
| 292 | test_raw(1) | ||
| 293 | |||
| 294 | ------------------------------------------------------------------------ | 187 | ------------------------------------------------------------------------ |
| 295 | test("total timeout on receive") | ||
| 296 | function test_totaltimeoutreceive(len, tm, sl) | 188 | function test_totaltimeoutreceive(len, tm, sl) |
| 297 | local str, err, total | 189 | local str, err, total |
| 298 | reconnect() | 190 | reconnect() |
| @@ -311,13 +203,8 @@ function test_totaltimeoutreceive(len, tm, sl) | |||
| 311 | check_timeout(tm, sl, elapsed, err, "receive", "total", | 203 | check_timeout(tm, sl, elapsed, err, "receive", "total", |
| 312 | string.len(str) == 2*len) | 204 | string.len(str) == 2*len) |
| 313 | end | 205 | end |
| 314 | test_totaltimeoutreceive(800091, 1, 3) | ||
| 315 | test_totaltimeoutreceive(800091, 2, 3) | ||
| 316 | test_totaltimeoutreceive(800091, 3, 2) | ||
| 317 | test_totaltimeoutreceive(800091, 3, 1) | ||
| 318 | 206 | ||
| 319 | ------------------------------------------------------------------------ | 207 | ------------------------------------------------------------------------ |
| 320 | test("total timeout on send") | ||
| 321 | function test_totaltimeoutsend(len, tm, sl) | 208 | function test_totaltimeoutsend(len, tm, sl) |
| 322 | local str, err, total | 209 | local str, err, total |
| 323 | reconnect() | 210 | reconnect() |
| @@ -336,13 +223,8 @@ function test_totaltimeoutsend(len, tm, sl) | |||
| 336 | check_timeout(tm, sl, elapsed, err, "send", "total", | 223 | check_timeout(tm, sl, elapsed, err, "send", "total", |
| 337 | total == 2*len) | 224 | total == 2*len) |
| 338 | end | 225 | end |
| 339 | test_totaltimeoutsend(800091, 1, 3) | ||
| 340 | test_totaltimeoutsend(800091, 2, 3) | ||
| 341 | test_totaltimeoutsend(800091, 3, 2) | ||
| 342 | test_totaltimeoutsend(800091, 3, 1) | ||
| 343 | 226 | ||
| 344 | ------------------------------------------------------------------------ | 227 | ------------------------------------------------------------------------ |
| 345 | test("blocking timeout on receive") | ||
| 346 | function test_blockingtimeoutreceive(len, tm, sl) | 228 | function test_blockingtimeoutreceive(len, tm, sl) |
| 347 | local str, err, total | 229 | local str, err, total |
| 348 | reconnect() | 230 | reconnect() |
| @@ -361,13 +243,8 @@ function test_blockingtimeoutreceive(len, tm, sl) | |||
| 361 | check_timeout(tm, sl, elapsed, err, "receive", "blocking", | 243 | check_timeout(tm, sl, elapsed, err, "receive", "blocking", |
| 362 | string.len(str) == 2*len) | 244 | string.len(str) == 2*len) |
| 363 | end | 245 | end |
| 364 | test_blockingtimeoutreceive(800091, 1, 3) | ||
| 365 | test_blockingtimeoutreceive(800091, 2, 3) | ||
| 366 | test_blockingtimeoutreceive(800091, 3, 2) | ||
| 367 | test_blockingtimeoutreceive(800091, 3, 1) | ||
| 368 | 246 | ||
| 369 | ------------------------------------------------------------------------ | 247 | ------------------------------------------------------------------------ |
| 370 | test("blocking timeout on send") | ||
| 371 | function test_blockingtimeoutsend(len, tm, sl) | 248 | function test_blockingtimeoutsend(len, tm, sl) |
| 372 | local str, err, total | 249 | local str, err, total |
| 373 | reconnect() | 250 | reconnect() |
| @@ -386,15 +263,8 @@ function test_blockingtimeoutsend(len, tm, sl) | |||
| 386 | check_timeout(tm, sl, elapsed, err, "send", "blocking", | 263 | check_timeout(tm, sl, elapsed, err, "send", "blocking", |
| 387 | total == 2*len) | 264 | total == 2*len) |
| 388 | end | 265 | end |
| 389 | test_blockingtimeoutsend(800091, 1, 3) | ||
| 390 | test_blockingtimeoutsend(800091, 2, 3) | ||
| 391 | test_blockingtimeoutsend(800091, 3, 2) | ||
| 392 | test_blockingtimeoutsend(800091, 3, 1) | ||
| 393 | 266 | ||
| 394 | ------------------------------------------------------------------------ | 267 | ------------------------------------------------------------------------ |
| 395 | test("bugs") | ||
| 396 | |||
| 397 | io.write("empty host connect: ") | ||
| 398 | function empty_connect() | 268 | function empty_connect() |
| 399 | if data then data:close() data = nil end | 269 | if data then data:close() data = nil end |
| 400 | remote [[ | 270 | remote [[ |
| @@ -408,27 +278,25 @@ function empty_connect() | |||
| 408 | else fail("should not have connected!") end | 278 | else fail("should not have connected!") end |
| 409 | end | 279 | end |
| 410 | 280 | ||
| 411 | empty_connect() | 281 | ------------------------------------------------------------------------ |
| 282 | function isclosed(c) | ||
| 283 | return c:fd() == -1 or c:fd() == (2^32-1) | ||
| 284 | end | ||
| 412 | 285 | ||
| 413 | -- io.write("active close: ") | ||
| 414 | function active_close() | 286 | function active_close() |
| 415 | reconnect() | 287 | reconnect() |
| 416 | if socket._isclosed(data) then fail("should not be closed") end | 288 | if isclosed(data) then fail("should not be closed") end |
| 417 | data:close() | 289 | data:close() |
| 418 | if not socket._isclosed(data) then fail("should be closed") end | 290 | if not isclosed(data) then fail("should be closed") end |
| 419 | data = nil | 291 | data = nil |
| 420 | local udp = socket.udp() | 292 | local udp = socket.udp() |
| 421 | if socket._isclosed(udp) then fail("should not be closed") end | 293 | if isclosed(udp) then fail("should not be closed") end |
| 422 | udp:close() | 294 | udp:close() |
| 423 | if not socket._isclosed(udp) then fail("should be closed") end | 295 | if not isclosed(udp) then fail("should be closed") end |
| 424 | pass("ok") | 296 | pass("ok") |
| 425 | end | 297 | end |
| 426 | 298 | ||
| 427 | -- active_close() | ||
| 428 | |||
| 429 | ------------------------------------------------------------------------ | 299 | ------------------------------------------------------------------------ |
| 430 | test("closed connection detection") | ||
| 431 | |||
| 432 | function test_closed() | 300 | function test_closed() |
| 433 | local back, err | 301 | local back, err |
| 434 | local str = 'little string' | 302 | local str = 'little string' |
| @@ -453,18 +321,15 @@ function test_closed() | |||
| 453 | ]] | 321 | ]] |
| 454 | total, err = data:send(string.rep("ugauga", 100000)) | 322 | total, err = data:send(string.rep("ugauga", 100000)) |
| 455 | if not err then | 323 | if not err then |
| 456 | pass("failed: output buffer is at least %d bytes long!", total) | 324 | pass("failed: output buffer is at least %d bytes long!", total) |
| 457 | elseif err ~= "closed" then | 325 | elseif err ~= "closed" then |
| 458 | fail("got '"..err.."' instead of 'closed'.") | 326 | fail("got '"..err.."' instead of 'closed'.") |
| 459 | else | 327 | else |
| 460 | pass("graceful 'closed' received after %d bytes were sent", total) | 328 | pass("graceful 'closed' received after %d bytes were sent", total) |
| 461 | end | 329 | end |
| 462 | end | 330 | end |
| 463 | 331 | ||
| 464 | test_closed() | ||
| 465 | |||
| 466 | ------------------------------------------------------------------------ | 332 | ------------------------------------------------------------------------ |
| 467 | test("select function") | ||
| 468 | function test_selectbugs() | 333 | function test_selectbugs() |
| 469 | local r, s, e = socket.select(nil, nil, 0.1) | 334 | local r, s, e = socket.select(nil, nil, 0.1) |
| 470 | assert(type(r) == "table" and type(s) == "table" and e == "timeout") | 335 | assert(type(r) == "table" and type(s) == "table" and e == "timeout") |
| @@ -481,7 +346,144 @@ function test_selectbugs() | |||
| 481 | pass("invalid input: ok") | 346 | pass("invalid input: ok") |
| 482 | end | 347 | end |
| 483 | 348 | ||
| 349 | test("method registration") | ||
| 350 | test_methods(socket.tcp(), { | ||
| 351 | "connect", | ||
| 352 | "send", | ||
| 353 | "receive", | ||
| 354 | "bind", | ||
| 355 | "accept", | ||
| 356 | "setpeername", | ||
| 357 | "setsockname", | ||
| 358 | "getpeername", | ||
| 359 | "getsockname", | ||
| 360 | "setoption", | ||
| 361 | "settimeout", | ||
| 362 | "close", | ||
| 363 | }) | ||
| 364 | test_methods(socket.udp(), { | ||
| 365 | "getpeername", | ||
| 366 | "getsockname", | ||
| 367 | "setsockname", | ||
| 368 | "setpeername", | ||
| 369 | "send", | ||
| 370 | "sendto", | ||
| 371 | "receive", | ||
| 372 | "receivefrom", | ||
| 373 | "setoption", | ||
| 374 | "settimeout", | ||
| 375 | "close", | ||
| 376 | }) | ||
| 377 | |||
| 378 | test("mixed patterns") | ||
| 379 | reconnect() | ||
| 380 | test_mixed(1) | ||
| 381 | test_mixed(17) | ||
| 382 | test_mixed(200) | ||
| 383 | test_mixed(4091) | ||
| 384 | test_mixed(801990) | ||
| 385 | test_mixed(4091) | ||
| 386 | test_mixed(200) | ||
| 387 | test_mixed(17) | ||
| 388 | test_mixed(1) | ||
| 389 | |||
| 390 | test("character line") | ||
| 391 | reconnect() | ||
| 392 | test_asciiline(1) | ||
| 393 | test_asciiline(17) | ||
| 394 | test_asciiline(200) | ||
| 395 | test_asciiline(4091) | ||
| 396 | test_asciiline(80199) | ||
| 397 | test_asciiline(8000000) | ||
| 398 | test_asciiline(80199) | ||
| 399 | test_asciiline(4091) | ||
| 400 | test_asciiline(200) | ||
| 401 | test_asciiline(17) | ||
| 402 | test_asciiline(1) | ||
| 403 | |||
| 404 | test("binary line") | ||
| 405 | reconnect() | ||
| 406 | test_rawline(1) | ||
| 407 | test_rawline(17) | ||
| 408 | test_rawline(200) | ||
| 409 | test_rawline(4091) | ||
| 410 | test_rawline(80199) | ||
| 411 | test_rawline(8000000) | ||
| 412 | test_rawline(80199) | ||
| 413 | test_rawline(4091) | ||
| 414 | test_rawline(200) | ||
| 415 | test_rawline(17) | ||
| 416 | test_rawline(1) | ||
| 417 | |||
| 418 | test("raw transfer") | ||
| 419 | reconnect() | ||
| 420 | test_raw(1) | ||
| 421 | test_raw(17) | ||
| 422 | test_raw(200) | ||
| 423 | test_raw(4091) | ||
| 424 | test_raw(80199) | ||
| 425 | test_raw(8000000) | ||
| 426 | test_raw(80199) | ||
| 427 | test_raw(4091) | ||
| 428 | test_raw(200) | ||
| 429 | test_raw(17) | ||
| 430 | test_raw(1) | ||
| 431 | |||
| 432 | test("non-blocking transfer") | ||
| 433 | reconnect() | ||
| 434 | -- the value is not important, we only want | ||
| 435 | -- to test non-blockin I/O anyways | ||
| 436 | data:settimeout(200) | ||
| 437 | test_raw(1) | ||
| 438 | test_raw(17) | ||
| 439 | test_raw(200) | ||
| 440 | test_raw(4091) | ||
| 441 | test_raw(80199) | ||
| 442 | test_raw(8000000) | ||
| 443 | test_raw(80199) | ||
| 444 | test_raw(4091) | ||
| 445 | test_raw(200) | ||
| 446 | test_raw(17) | ||
| 447 | test_raw(1) | ||
| 448 | |||
| 449 | test("select function") | ||
| 484 | test_selectbugs() | 450 | test_selectbugs() |
| 485 | 451 | ||
| 452 | test("empty host connect: ") | ||
| 453 | empty_connect() | ||
| 454 | |||
| 455 | test("active close: ") | ||
| 456 | active_close() | ||
| 457 | |||
| 458 | test("closed connection detection: ") | ||
| 459 | test_closed() | ||
| 460 | |||
| 461 | a = [[ | ||
| 462 | test("total timeout on send") | ||
| 463 | test_totaltimeoutsend(800091, 1, 3) | ||
| 464 | test_totaltimeoutsend(800091, 2, 3) | ||
| 465 | test_totaltimeoutsend(800091, 3, 2) | ||
| 466 | test_totaltimeoutsend(800091, 3, 1) | ||
| 467 | |||
| 468 | test("total timeout on receive") | ||
| 469 | test_totaltimeoutreceive(800091, 1, 3) | ||
| 470 | test_totaltimeoutreceive(800091, 2, 3) | ||
| 471 | test_totaltimeoutreceive(800091, 3, 2) | ||
| 472 | test_totaltimeoutreceive(800091, 3, 1) | ||
| 473 | |||
| 474 | test("blocking timeout on send") | ||
| 475 | test_blockingtimeoutsend(800091, 1, 3) | ||
| 476 | test_blockingtimeoutsend(800091, 2, 3) | ||
| 477 | test_blockingtimeoutsend(800091, 3, 2) | ||
| 478 | test_blockingtimeoutsend(800091, 3, 1) | ||
| 479 | |||
| 480 | test("blocking timeout on receive") | ||
| 481 | test_blockingtimeoutreceive(800091, 1, 3) | ||
| 482 | test_blockingtimeoutreceive(800091, 2, 3) | ||
| 483 | test_blockingtimeoutreceive(800091, 3, 2) | ||
| 484 | test_blockingtimeoutreceive(800091, 3, 1) | ||
| 485 | ]] | ||
| 486 | |||
| 487 | socket.done() | ||
| 486 | 488 | ||
| 487 | test(string.format("done in %.2fs", socket.time() - start)) | 489 | test(string.format("done in %.2fs", socket.time() - start)) |
