aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2004-01-17 00:17:46 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2004-01-17 00:17:46 +0000
commit076451c75336b30e6152bd5c02f355db39107f7d (patch)
tree785a6c71ca1e5246f2ce09a9b91f98eb902ac2a0
parent89f3ecf7820857f91c4039536d2bbe3cf12d5f95 (diff)
downloadluasocket-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--TODO11
-rw-r--r--luasocket.sln23
-rw-r--r--luasocket.vcproj216
-rw-r--r--src/inet.h4
-rw-r--r--src/luasocket.h2
-rw-r--r--src/tcp.c18
-rw-r--r--src/timeout.c1
-rw-r--r--src/udp.c75
-rw-r--r--src/usocket.c92
-rw-r--r--src/wsocket.c180
-rw-r--r--test/testclnt.lua294
11 files changed, 620 insertions, 296 deletions
diff --git a/TODO b/TODO
index bd8a950..5566d16 100644
--- a/TODO
+++ b/TODO
@@ -1,8 +1,13 @@
1change send/recv to avoid using select
2 1
2
3
4check for interrupt compliance
5add connect with timeout
3add gethostname and use it in HTTP, SMTP etc, and add manual entry. 6add gethostname and use it in HTTP, SMTP etc, and add manual entry.
7
4add local connect, and manual entry 8add local connect, and manual entry
5add shutdown, and manual entry 9
10add shutdown manual entry
6 11
7only allocate in case of success 12only allocate in case of success
8only call select if io fails... 13only 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 @@
1Microsoft Visual Studio Solution File, Format Version 8.00
2Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "luasocket", "luasocket.vcproj", "{4FAAB633-F0E7-4D12-B680-D150A0DD7268}"
3 ProjectSection(ProjectDependencies) = postProject
4 EndProjectSection
5EndProject
6Global
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
23EndGlobal
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>
diff --git a/src/inet.h b/src/inet.h
index 244a310..b69e82d 100644
--- a/src/inet.h
+++ b/src/inet.h
@@ -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
22void inet_open(lua_State *L); 26void inet_open(lua_State *L);
23const char *inet_tryconnect(p_sock ps, const char *address, 27const 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
diff --git a/src/tcp.c b/src/tcp.c
index afa0477..a67b44a 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -36,6 +36,7 @@ static int meth_dirty(lua_State *L);
36static int opt_tcp_nodelay(lua_State *L); 36static int opt_tcp_nodelay(lua_State *L);
37static int opt_keepalive(lua_State *L); 37static int opt_keepalive(lua_State *L);
38static int opt_linger(lua_State *L); 38static int opt_linger(lua_State *L);
39static int opt_reuseaddr(lua_State *L);
39 40
40/* tcp object methods */ 41/* tcp object methods */
41static luaL_reg tcp[] = { 42static luaL_reg tcp[] = {
@@ -61,6 +62,7 @@ static luaL_reg tcp[] = {
61/* socket option handlers */ 62/* socket option handlers */
62static luaL_reg opt[] = { 63static 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
124static int opt_boolean(lua_State *L, int level, int name) 126static 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 */
140static 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 */
138static int opt_tcp_nodelay(lua_State *L) 146static 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
149static int opt_keepalive(lua_State *L) 151static 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>
diff --git a/src/udp.c b/src/udp.c
index 58119cd..21730ab 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -35,6 +35,11 @@ static int meth_fd(lua_State *L);
35static int meth_dirty(lua_State *L); 35static int meth_dirty(lua_State *L);
36static int opt_dontroute(lua_State *L); 36static int opt_dontroute(lua_State *L);
37static int opt_broadcast(lua_State *L); 37static int opt_broadcast(lua_State *L);
38static int opt_reuseaddr(lua_State *L);
39static int opt_ip_multicast_ttl(lua_State *L);
40static int opt_ip_multicast_loop(lua_State *L);
41static int opt_ip_add_membership(lua_State *L);
42static int opt_ip_drop_membersip(lua_State *L);
38 43
39/* udp object methods */ 44/* udp object methods */
40static luaL_reg udp[] = { 45static luaL_reg udp[] = {
@@ -57,8 +62,13 @@ static luaL_reg udp[] = {
57 62
58/* socket options */ 63/* socket options */
59static luaL_reg opt[] = { 64static 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
257static int opt_reuseaddr(lua_State *L)
258{
259 return opt_boolean(L, SOL_SOCKET, SO_REUSEADDR);
260}
261
247static int opt_broadcast(lua_State *L) 262static 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
267static int opt_ip_multicast_loop(lua_State *L)
268{
269 return opt_boolean(L, IPPROTO_IP, IP_MULTICAST_LOOP);
270}
271
272static 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
286static 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
313static int opt_ip_add_membership(lua_State *L)
314{
315 return opt_membership(L, IPPROTO_IP, IP_ADD_MEMBERSHIP);
316}
317
318static 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,
191int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) 193int 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
99control:setoption("tcp-nodelay", true) 99control:setoption("tcp-nodelay", true)
100 100
101------------------------------------------------------------------------ 101------------------------------------------------------------------------
102test("method registration")
103
104function test_methods(sock, methods) 102function 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")
111end 109end
112 110
113test_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
128test_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------------------------------------------------------------------------
143test("mixed patterns")
144
145function test_mixed(len) 112function 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
164end 131end
165 132
166
167test_mixed(1)
168test_mixed(17)
169test_mixed(200)
170test_mixed(4091)
171test_mixed(80199)
172test_mixed(4091)
173test_mixed(200)
174test_mixed(17)
175test_mixed(1)
176
177------------------------------------------------------------------------ 133------------------------------------------------------------------------
178test("character line")
179reconnect()
180
181function test_asciiline(len) 134function 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
195end 148end
196 149
197test_asciiline(1)
198test_asciiline(17)
199test_asciiline(200)
200test_asciiline(4091)
201test_asciiline(80199)
202test_asciiline(800000)
203test_asciiline(80199)
204test_asciiline(4091)
205test_asciiline(200)
206test_asciiline(17)
207test_asciiline(1)
208
209------------------------------------------------------------------------ 150------------------------------------------------------------------------
210test("binary line")
211reconnect()
212
213function test_rawline(len) 151function 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
228end 166end
229 167
230test_rawline(1)
231test_rawline(17)
232test_rawline(200)
233test_rawline(4091)
234test_rawline(80199)
235test_rawline(800000)
236test_rawline(80199)
237test_rawline(4091)
238test_rawline(200)
239test_rawline(17)
240test_rawline(1)
241
242------------------------------------------------------------------------ 168------------------------------------------------------------------------
243test("raw transfer")
244reconnect()
245
246function test_raw(len) 169function 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
262end 185end
263 186
264test_raw(1)
265test_raw(17)
266test_raw(200)
267test_raw(4091)
268test_raw(80199)
269test_raw(800000)
270test_raw(80199)
271test_raw(4091)
272test_raw(200)
273test_raw(17)
274test_raw(1)
275------------------------------------------------------------------------
276test("non-blocking transfer")
277reconnect()
278
279-- the value is not important, we only want
280-- to test non-blockin I/O anyways
281data:settimeout(200)
282test_raw(1)
283test_raw(17)
284test_raw(200)
285test_raw(4091)
286test_raw(80199)
287test_raw(800000)
288test_raw(80199)
289test_raw(4091)
290test_raw(200)
291test_raw(17)
292test_raw(1)
293
294------------------------------------------------------------------------ 187------------------------------------------------------------------------
295test("total timeout on receive")
296function test_totaltimeoutreceive(len, tm, sl) 188function 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)
313end 205end
314test_totaltimeoutreceive(800091, 1, 3)
315test_totaltimeoutreceive(800091, 2, 3)
316test_totaltimeoutreceive(800091, 3, 2)
317test_totaltimeoutreceive(800091, 3, 1)
318 206
319------------------------------------------------------------------------ 207------------------------------------------------------------------------
320test("total timeout on send")
321function test_totaltimeoutsend(len, tm, sl) 208function 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)
338end 225end
339test_totaltimeoutsend(800091, 1, 3)
340test_totaltimeoutsend(800091, 2, 3)
341test_totaltimeoutsend(800091, 3, 2)
342test_totaltimeoutsend(800091, 3, 1)
343 226
344------------------------------------------------------------------------ 227------------------------------------------------------------------------
345test("blocking timeout on receive")
346function test_blockingtimeoutreceive(len, tm, sl) 228function 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)
363end 245end
364test_blockingtimeoutreceive(800091, 1, 3)
365test_blockingtimeoutreceive(800091, 2, 3)
366test_blockingtimeoutreceive(800091, 3, 2)
367test_blockingtimeoutreceive(800091, 3, 1)
368 246
369------------------------------------------------------------------------ 247------------------------------------------------------------------------
370test("blocking timeout on send")
371function test_blockingtimeoutsend(len, tm, sl) 248function 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)
388end 265end
389test_blockingtimeoutsend(800091, 1, 3)
390test_blockingtimeoutsend(800091, 2, 3)
391test_blockingtimeoutsend(800091, 3, 2)
392test_blockingtimeoutsend(800091, 3, 1)
393 266
394------------------------------------------------------------------------ 267------------------------------------------------------------------------
395test("bugs")
396
397io.write("empty host connect: ")
398function empty_connect() 268function 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
409end 279end
410 280
411empty_connect() 281------------------------------------------------------------------------
282function isclosed(c)
283 return c:fd() == -1 or c:fd() == (2^32-1)
284end
412 285
413-- io.write("active close: ")
414function active_close() 286function 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")
425end 297end
426 298
427-- active_close()
428
429------------------------------------------------------------------------ 299------------------------------------------------------------------------
430test("closed connection detection")
431
432function test_closed() 300function 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
456pass("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
458fail("got '"..err.."' instead of 'closed'.") 326 fail("got '"..err.."' instead of 'closed'.")
459 else 327 else
460pass("graceful 'closed' received after %d bytes were sent", total) 328 pass("graceful 'closed' received after %d bytes were sent", total)
461 end 329 end
462end 330end
463 331
464test_closed()
465
466------------------------------------------------------------------------ 332------------------------------------------------------------------------
467test("select function")
468function test_selectbugs() 333function 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")
482end 347end
483 348
349test("method registration")
350test_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})
364test_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
378test("mixed patterns")
379reconnect()
380test_mixed(1)
381test_mixed(17)
382test_mixed(200)
383test_mixed(4091)
384test_mixed(801990)
385test_mixed(4091)
386test_mixed(200)
387test_mixed(17)
388test_mixed(1)
389
390test("character line")
391reconnect()
392test_asciiline(1)
393test_asciiline(17)
394test_asciiline(200)
395test_asciiline(4091)
396test_asciiline(80199)
397test_asciiline(8000000)
398test_asciiline(80199)
399test_asciiline(4091)
400test_asciiline(200)
401test_asciiline(17)
402test_asciiline(1)
403
404test("binary line")
405reconnect()
406test_rawline(1)
407test_rawline(17)
408test_rawline(200)
409test_rawline(4091)
410test_rawline(80199)
411test_rawline(8000000)
412test_rawline(80199)
413test_rawline(4091)
414test_rawline(200)
415test_rawline(17)
416test_rawline(1)
417
418test("raw transfer")
419reconnect()
420test_raw(1)
421test_raw(17)
422test_raw(200)
423test_raw(4091)
424test_raw(80199)
425test_raw(8000000)
426test_raw(80199)
427test_raw(4091)
428test_raw(200)
429test_raw(17)
430test_raw(1)
431
432test("non-blocking transfer")
433reconnect()
434-- the value is not important, we only want
435-- to test non-blockin I/O anyways
436data:settimeout(200)
437test_raw(1)
438test_raw(17)
439test_raw(200)
440test_raw(4091)
441test_raw(80199)
442test_raw(8000000)
443test_raw(80199)
444test_raw(4091)
445test_raw(200)
446test_raw(17)
447test_raw(1)
448
449test("select function")
484test_selectbugs() 450test_selectbugs()
485 451
452test("empty host connect: ")
453empty_connect()
454
455test("active close: ")
456active_close()
457
458test("closed connection detection: ")
459test_closed()
460
461a = [[
462test("total timeout on send")
463test_totaltimeoutsend(800091, 1, 3)
464test_totaltimeoutsend(800091, 2, 3)
465test_totaltimeoutsend(800091, 3, 2)
466test_totaltimeoutsend(800091, 3, 1)
467
468test("total timeout on receive")
469test_totaltimeoutreceive(800091, 1, 3)
470test_totaltimeoutreceive(800091, 2, 3)
471test_totaltimeoutreceive(800091, 3, 2)
472test_totaltimeoutreceive(800091, 3, 1)
473
474test("blocking timeout on send")
475test_blockingtimeoutsend(800091, 1, 3)
476test_blockingtimeoutsend(800091, 2, 3)
477test_blockingtimeoutsend(800091, 3, 2)
478test_blockingtimeoutsend(800091, 3, 1)
479
480test("blocking timeout on receive")
481test_blockingtimeoutreceive(800091, 1, 3)
482test_blockingtimeoutreceive(800091, 2, 3)
483test_blockingtimeoutreceive(800091, 3, 2)
484test_blockingtimeoutreceive(800091, 3, 1)
485]]
486
487socket.done()
486 488
487test(string.format("done in %.2fs", socket.time() - start)) 489test(string.format("done in %.2fs", socket.time() - start))