aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2005-02-08 10:01:01 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2005-02-08 10:01:01 +0000
commit8d4e240f6ae50d9b22ddc44f5e207018935da907 (patch)
treed8ca9a51dc35534592f700e42740feac20242ede
parent5d32848674b723521e87836eafa24f5ae8f80a89 (diff)
downloadluasocket-8d4e240f6ae50d9b22ddc44f5e207018935da907.tar.gz
luasocket-8d4e240f6ae50d9b22ddc44f5e207018935da907.tar.bz2
luasocket-8d4e240f6ae50d9b22ddc44f5e207018935da907.zip
Forward server working on Mac OS X...
-rw-r--r--FIX7
-rw-r--r--TODO40
-rw-r--r--doc/ftp.html12
-rw-r--r--doc/http.html8
-rw-r--r--doc/introduction.html10
-rw-r--r--doc/ltn12.html2
-rw-r--r--doc/smtp.html6
-rw-r--r--doc/socket.html9
-rw-r--r--doc/url.html6
-rw-r--r--src/buffer.c2
-rw-r--r--src/inet.c1
-rw-r--r--src/luasocket.c4
-rw-r--r--src/luasocket.h4
-rw-r--r--src/mime.c4
-rw-r--r--src/mime.h2
-rw-r--r--src/mime.lua3
-rw-r--r--src/socket.h4
-rw-r--r--src/socket.lua3
-rw-r--r--src/tcp.c22
-rw-r--r--src/unix.c27
-rw-r--r--src/unix.h2
-rw-r--r--src/usocket.c26
-rw-r--r--src/wsocket.c15
-rw-r--r--test/dicttest.lua2
-rw-r--r--test/httptest.lua2
-rw-r--r--test/testclnt.lua16
-rw-r--r--test/testsrvr.lua1
-rw-r--r--test/utestclnt.lua644
-rw-r--r--test/utestsrvr.lua17
29 files changed, 800 insertions, 101 deletions
diff --git a/FIX b/FIX
index 10a96b0..9d50a66 100644
--- a/FIX
+++ b/FIX
@@ -1,2 +1,9 @@
1tcp{client}:shutdown() was checking for group instead of class. 1tcp{client}:shutdown() was checking for group instead of class.
2tcp{client}:send() now returns i+sent-1... 2tcp{client}:send() now returns i+sent-1...
3get rid of a = socket.try() in the manual, except for protected cases.
4 replace it with assert.
5get rid of "base." kludge
6check all "require("http")" etc in the manual.
7make sure sock_gethostname.* only return success if the hp is not null!
8change 'l' prefix in C libraries to 'l-something'...
9 don't forget the declarations in luasocket.h and mime.h!!!
diff --git a/TODO b/TODO
index 7b74fe2..19c9319 100644
--- a/TODO
+++ b/TODO
@@ -1,6 +1,7 @@
1get rid of a = socket.try() in the manual, except for protected cases.
2 replace it with assert.
3 1
2BUG NO SET DO TINYIRC!!! SINISTRO.
3talk about the non-blocking connect in the manual
4test it on Windows!!!
4 5
5think about a dispatcher. 6think about a dispatcher.
6 - it creates a server and receives a function that will do the work on 7 - it creates a server and receives a function that will do the work on
@@ -13,17 +14,9 @@ functions for non-blocking so they can be used in the context of the
13dispatcher! 14dispatcher!
14 15
15adjust manual for new sock:send returns. 16adjust manual for new sock:send returns.
16check all "require("http")" etc in the manual.
17_VERSION, _DEBUG, etc. 17_VERSION, _DEBUG, etc.
18get rid of "base." kludge
19make sure sock_gethostname.* only return success if the hp is not
20null!
21change 'l' prefix in C libraries to 'l-something'...
22 don't forget the declarations in luasocket.h and mime.h!!!
23leave code for losers that don't have nanosleep
24 18
25"foo.bar.baz" previously had to provide luaopen_foobarbaz() and now 19leave code for losers that don't have nanosleep
26should use luaopen_foo_bar_baz(). Change compat-5.1 and LuaSocket?
27 20
28ftp.send/recv return bytes transfered? 21ftp.send/recv return bytes transfered?
29new scheme to choose family/protocol of object to create 22new scheme to choose family/protocol of object to create
@@ -47,27 +40,4 @@ testar os options!
47 - proteger ou atomizar o conjunto (timedout, receive), (timedout, send) 40 - proteger ou atomizar o conjunto (timedout, receive), (timedout, send)
48 - inet_ntoa também é uma merda. 41 - inet_ntoa também é uma merda.
49 42
50*eliminate globals from namespaces created by module(). 43eliminate globals from namespaces created by module().
51*make sure standard libraries are "required" by modules before use.
52*use wim's filter.chain or something better
53*close wasn't returning 1
54*make sure errors not thrown by try() are not caught by protect()
55*move wsocket.c:sock_send kludge to buffer.c:sendraw?
56*bug on UDP sendto.
57*fix PROXY in http.lua
58*use new distribution scheme
59*create the getstats method.
60*fix local domain socket kludge of name size
61*use TLS
62*sort out the wrap around of gettime...
63 *use doubles all over
64 *sock_send, sock_recv & sock_select use p_tm instead of timeout
65 *make select interrupt safe (will be with tm stuff)
66 *use GetSystemTimeAsFileTime in windows (WinCE will suffer document)
67*add getstats to the manual
68*Fazer compilar com g++
69*test associativity of socket.select
70* fix manual for send and receive
71* add thanks to mike
72* change sock:send to use indices just like string.sub?
73* change sendraw to send by chunks
diff --git a/doc/ftp.html b/doc/ftp.html
index 454d417..7860c27 100644
--- a/doc/ftp.html
+++ b/doc/ftp.html
@@ -65,7 +65,7 @@ To obtain the <tt>ftp</tt> namespace, run:
65 65
66<pre class=example> 66<pre class=example>
67-- loads the FTP module and any libraries it requires 67-- loads the FTP module and any libraries it requires
68local ftp = require("ftp") 68local ftp = require("socket.ftp")
69</pre> 69</pre>
70 70
71<p> 71<p>
@@ -150,7 +150,7 @@ error.
150 150
151<pre class=example> 151<pre class=example>
152-- load the ftp support 152-- load the ftp support
153local ftp = require("ftp") 153local ftp = require("socket.ftp")
154 154
155-- Log as user "anonymous" on server "ftp.tecgraf.puc-rio.br", 155-- Log as user "anonymous" on server "ftp.tecgraf.puc-rio.br",
156-- and get file "lua.tar.gz" from directory "pub/lua" as binary. 156-- and get file "lua.tar.gz" from directory "pub/lua" as binary.
@@ -159,9 +159,9 @@ f, e = ftp.get("ftp://ftp.tecgraf.puc-rio.br/pub/lua/lua.tar.gz;type=i")
159 159
160<pre class=example> 160<pre class=example>
161-- load needed modules 161-- load needed modules
162local ftp = require("ftp") 162local ftp = require("socket.ftp")
163local ltn12 = require("ltn12") 163local ltn12 = require("ltn12")
164local url = require("url") 164local url = require("socket.url")
165 165
166-- a function that returns a directory listing 166-- a function that returns a directory listing
167function nlst(u) 167function nlst(u)
@@ -230,7 +230,7 @@ message describing the reason for failure.
230 230
231<pre class=example> 231<pre class=example>
232-- load the ftp support 232-- load the ftp support
233local ftp = require("ftp") 233local ftp = require("socket.ftp")
234 234
235-- Log as user "fulano" on server "ftp.example.com", 235-- Log as user "fulano" on server "ftp.example.com",
236-- using password "silva", and store a file "README" with contents 236-- using password "silva", and store a file "README" with contents
@@ -241,7 +241,7 @@ f, e = ftp.put("ftp://fulano:silva@ftp.example.com/README",
241 241
242<pre class=example> 242<pre class=example>
243-- load the ftp support 243-- load the ftp support
244local ftp = require("ftp") 244local ftp = require("socket.ftp")
245local ltn12 = require("ltn12") 245local ltn12 = require("ltn12")
246 246
247-- Log as user "fulano" on server "ftp.example.com", 247-- Log as user "fulano" on server "ftp.example.com",
diff --git a/doc/http.html b/doc/http.html
index 4cbbe95..af58571 100644
--- a/doc/http.html
+++ b/doc/http.html
@@ -62,7 +62,7 @@ To obtain the <tt>http</tt> namespace, run:
62 62
63<pre class=example> 63<pre class=example>
64-- loads the HTTP module and any libraries it requires 64-- loads the HTTP module and any libraries it requires
65local http = require("http") 65local http = require("socket.http")
66</pre> 66</pre>
67 67
68<p> 68<p>
@@ -206,7 +206,7 @@ Here are a few examples with the simple interface:
206 206
207<pre class=example> 207<pre class=example>
208-- load the http module 208-- load the http module
209http = require("http") 209http = require("socket.http")
210 210
211-- connect to server "www.tecgraf.puc-rio.br" and retrieves this manual 211-- connect to server "www.tecgraf.puc-rio.br" and retrieves this manual
212-- file from "/luasocket/http.html" 212-- file from "/luasocket/http.html"
@@ -231,7 +231,7 @@ And here is an example using the generic interface:
231 231
232<pre class=example> 232<pre class=example>
233-- load the http module 233-- load the http module
234http = require("http") 234http = require("socket.http")
235 235
236-- Requests information about a document, without downloading it. 236-- Requests information about a document, without downloading it.
237-- Useful, for example, if you want to display a download gauge and need 237-- Useful, for example, if you want to display a download gauge and need
@@ -276,7 +276,7 @@ authentication is required.
276 276
277<pre class=example> 277<pre class=example>
278-- load required modules 278-- load required modules
279http = require("http") 279http = require("socket.http")
280mime = require("mime") 280mime = require("mime")
281 281
282-- Connect to server "www.example.com" and tries to retrieve 282-- Connect to server "www.example.com" and tries to retrieve
diff --git a/doc/introduction.html b/doc/introduction.html
index f8fe078..c88fa40 100644
--- a/doc/introduction.html
+++ b/doc/introduction.html
@@ -182,7 +182,7 @@ program.
182-- load namespace 182-- load namespace
183local socket = require("socket") 183local socket = require("socket")
184-- create a TCP socket and bind it to the local host, at any port 184-- create a TCP socket and bind it to the local host, at any port
185local server = socket.try(socket.bind("*", 0)) 185local server = assert(socket.bind("*", 0))
186-- find out which port the OS chose for us 186-- find out which port the OS chose for us
187local ip, port = server:getsockname() 187local ip, port = server:getsockname()
188-- print a message informing what's up 188-- print a message informing what's up
@@ -287,13 +287,13 @@ local host, port = "localhost", 13
287-- load namespace 287-- load namespace
288local socket = require("socket") 288local socket = require("socket")
289-- convert host name to ip address 289-- convert host name to ip address
290local ip = socket.try(socket.dns.toip(host)) 290local ip = assert(socket.dns.toip(host))
291-- create a new UDP object 291-- create a new UDP object
292local udp = socket.try(socket.udp()) 292local udp = assert(socket.udp())
293-- contact daytime host 293-- contact daytime host
294socket.try(udp:sendto("anything", ip, port)) 294assert(udp:sendto("anything", ip, port))
295-- retrieve the answer and print results 295-- retrieve the answer and print results
296io.write(socket.try((udp:receive()))) 296io.write(assert(udp:receive()))
297</pre> 297</pre>
298</blockquote> 298</blockquote>
299 299
diff --git a/doc/ltn12.html b/doc/ltn12.html
index 44fcbe4..c5a0f59 100644
--- a/doc/ltn12.html
+++ b/doc/ltn12.html
@@ -271,7 +271,7 @@ The function returns the sink and the table used to store the chunks.
271 271
272<pre class=example> 272<pre class=example>
273-- load needed modules 273-- load needed modules
274local http = require("http") 274local http = require("socket.http")
275local ltn12 = require("ltn12") 275local ltn12 = require("ltn12")
276 276
277-- a simplified http.get function 277-- a simplified http.get function
diff --git a/doc/smtp.html b/doc/smtp.html
index 8feae3e..bd18bfa 100644
--- a/doc/smtp.html
+++ b/doc/smtp.html
@@ -69,7 +69,7 @@ To obtain the <tt>smtp</tt> namespace, run:
69 69
70<pre class=example> 70<pre class=example>
71-- loads the SMTP module and everything it requires 71-- loads the SMTP module and everything it requires
72local smtp = require("smtp") 72local smtp = require("socket.smtp")
73</pre> 73</pre>
74 74
75<p> 75<p>
@@ -239,7 +239,7 @@ and
239 239
240<pre class=example> 240<pre class=example>
241-- load the smtp support 241-- load the smtp support
242local smtp = require("smtp") 242local smtp = require("socket.smtp")
243 243
244-- Connects to server "localhost" and sends a message to users 244-- Connects to server "localhost" and sends a message to users
245-- "fulano@example.com", "beltrano@example.com", 245-- "fulano@example.com", "beltrano@example.com",
@@ -329,7 +329,7 @@ as listed in the introduction. </p>
329 329
330<pre class=example> 330<pre class=example>
331-- load the smtp support and its friends 331-- load the smtp support and its friends
332local smtp = require("smtp") 332local smtp = require("socket.smtp")
333local mime = require("mime") 333local mime = require("mime")
334local ltn12 = require("ltn12") 334local ltn12 = require("ltn12")
335 335
diff --git a/doc/socket.html b/doc/socket.html
index f638fd9..18c71d1 100644
--- a/doc/socket.html
+++ b/doc/socket.html
@@ -145,7 +145,10 @@ socket.<b>protect(</b>func<b>)</b>
145</p> 145</p>
146 146
147<p class=description> 147<p class=description>
148Converts a function that throws exceptions into a safe function. 148Converts a function that throws exceptions into a safe function. This
149function only catches exceptions thrown by the <a href=#try><tt>try</tt></a>
150and <a href=#newtry><tt>newtry</tt></a> functions. It does not catch normal
151Lua errors.
149</p> 152</p>
150 153
151<p class=parameters> 154<p class=parameters>
@@ -346,7 +349,9 @@ socket.<b>try(</b>ret<sub>1</sub> [, ret<sub>2</sub> ... ret<sub>N</sub>]<b>)</b
346</p> 349</p>
347 350
348<p class=description> 351<p class=description>
349Throws an exception in case of error. 352Throws an exception in case of error. The exception can only be caught
353by the <a href=#protect><tt>protect</tt></a> function. It does not explode
354into an error message.
350</p> 355</p>
351 356
352<p class=parameters> 357<p class=parameters>
diff --git a/doc/url.html b/doc/url.html
index 56e1ef5..ac84d24 100644
--- a/doc/url.html
+++ b/doc/url.html
@@ -52,7 +52,7 @@ To obtain the <tt>url</tt> namespace, run:
52 52
53<pre class=example> 53<pre class=example>
54-- loads the URL module 54-- loads the URL module
55local url = require("url") 55local url = require("socket.url")
56</pre> 56</pre>
57 57
58<p> 58<p>
@@ -193,7 +193,7 @@ The function returns the encoded string.
193 193
194<pre class=example> 194<pre class=example>
195-- load url module 195-- load url module
196url = require("url") 196url = require("socket.url")
197 197
198code = url.escape("/#?;") 198code = url.escape("/#?;")
199-- code = "%2f%23%3f%3b" 199-- code = "%2f%23%3f%3b"
@@ -239,7 +239,7 @@ parsed_url = {<br>
239 239
240<pre class=example> 240<pre class=example>
241-- load url module 241-- load url module
242url = require("url") 242url = require("socket.url")
243 243
244parsed_url = url.parse("http://www.example.com/cgilua/index.lua?a=2#there") 244parsed_url = url.parse("http://www.example.com/cgilua/index.lua?a=2#there")
245-- parsed_url = { 245-- parsed_url = {
diff --git a/src/buffer.c b/src/buffer.c
index 0ec7b4d..45cd0f2 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -123,7 +123,7 @@ int buf_meth_receive(lua_State *L, p_buf buf) {
123 else if (p[0] == '*' && p[1] == 'a') err = recvall(buf, &b); 123 else if (p[0] == '*' && p[1] == 'a') err = recvall(buf, &b);
124 else luaL_argcheck(L, 0, 2, "invalid receive pattern"); 124 else luaL_argcheck(L, 0, 2, "invalid receive pattern");
125 /* get a fixed number of bytes */ 125 /* get a fixed number of bytes */
126 } else err = recvraw(buf, (size_t) lua_tonumber(L, 2), &b); 126 } else err = recvraw(buf, (size_t) lua_tonumber(L, 2)-size, &b);
127 /* check if there was an error */ 127 /* check if there was an error */
128 if (err != IO_DONE) { 128 if (err != IO_DONE) {
129 /* we can't push anyting in the stack before pushing the 129 /* we can't push anyting in the stack before pushing the
diff --git a/src/inet.c b/src/inet.c
index e2afcdf..d713643 100644
--- a/src/inet.c
+++ b/src/inet.c
@@ -220,7 +220,6 @@ const char *inet_tryconnect(p_sock ps, const char *address,
220 } 220 }
221 } else remote.sin_family = AF_UNSPEC; 221 } else remote.sin_family = AF_UNSPEC;
222 err = sock_connect(ps, (SA *) &remote, sizeof(remote), tm); 222 err = sock_connect(ps, (SA *) &remote, sizeof(remote), tm);
223 if (err != IO_DONE) sock_destroy(ps);
224 return sock_strerror(err); 223 return sock_strerror(err);
225} 224}
226 225
diff --git a/src/luasocket.c b/src/luasocket.c
index 4b829f8..8f13dbc 100644
--- a/src/luasocket.c
+++ b/src/luasocket.c
@@ -87,7 +87,7 @@ static int global_unload(lua_State *L) {
87static int base_open(lua_State *L) { 87static int base_open(lua_State *L) {
88 if (sock_open()) { 88 if (sock_open()) {
89 /* export functions (and leave namespace table on top of stack) */ 89 /* export functions (and leave namespace table on top of stack) */
90 luaL_module(L, "socket", func, 0); 90 luaL_openlib(L, "socket", func, 0);
91#ifdef LUASOCKET_DEBUG 91#ifdef LUASOCKET_DEBUG
92 lua_pushstring(L, "DEBUG"); 92 lua_pushstring(L, "DEBUG");
93 lua_pushboolean(L, 1); 93 lua_pushboolean(L, 1);
@@ -108,7 +108,7 @@ static int base_open(lua_State *L) {
108/*-------------------------------------------------------------------------*\ 108/*-------------------------------------------------------------------------*\
109* Initializes all library modules. 109* Initializes all library modules.
110\*-------------------------------------------------------------------------*/ 110\*-------------------------------------------------------------------------*/
111LUASOCKET_API int luaopen_lsocket(lua_State *L) { 111LUASOCKET_API int luaopen_csocket(lua_State *L) {
112 int i; 112 int i;
113 base_open(L); 113 base_open(L);
114 for (i = 0; mod[i].name; i++) mod[i].func(L); 114 for (i = 0; mod[i].name; i++) mod[i].func(L);
diff --git a/src/luasocket.h b/src/luasocket.h
index db54a18..768e335 100644
--- a/src/luasocket.h
+++ b/src/luasocket.h
@@ -13,7 +13,7 @@
13/*-------------------------------------------------------------------------*\ 13/*-------------------------------------------------------------------------*\
14* Current luasocket version 14* Current luasocket version
15\*-------------------------------------------------------------------------*/ 15\*-------------------------------------------------------------------------*/
16#define LUASOCKET_VERSION "LuaSocket 2.0 (beta3)" 16#define LUASOCKET_VERSION "LuaSocket 2.0"
17#define LUASOCKET_COPYRIGHT "Copyright (C) 2004-2005 Diego Nehab" 17#define LUASOCKET_COPYRIGHT "Copyright (C) 2004-2005 Diego Nehab"
18#define LUASOCKET_AUTHORS "Diego Nehab" 18#define LUASOCKET_AUTHORS "Diego Nehab"
19 19
@@ -27,6 +27,6 @@
27/*-------------------------------------------------------------------------*\ 27/*-------------------------------------------------------------------------*\
28* Initializes the library. 28* Initializes the library.
29\*-------------------------------------------------------------------------*/ 29\*-------------------------------------------------------------------------*/
30LUASOCKET_API int luaopen_socket(lua_State *L); 30LUASOCKET_API int luaopen_csocket(lua_State *L);
31 31
32#endif /* LUASOCKET_H */ 32#endif /* LUASOCKET_H */
diff --git a/src/mime.c b/src/mime.c
index dcc4af3..67f9f5b 100644
--- a/src/mime.c
+++ b/src/mime.c
@@ -78,9 +78,9 @@ static UC b64unbase[256];
78/*-------------------------------------------------------------------------*\ 78/*-------------------------------------------------------------------------*\
79* Initializes module 79* Initializes module
80\*-------------------------------------------------------------------------*/ 80\*-------------------------------------------------------------------------*/
81MIME_API int luaopen_lmime(lua_State *L) 81MIME_API int luaopen_cmime(lua_State *L)
82{ 82{
83 luaL_module(L, "mime", func, 0); 83 luaL_openlib(L, "mime", func, 0);
84 /* initialize lookup tables */ 84 /* initialize lookup tables */
85 qpsetup(qpclass, qpunbase); 85 qpsetup(qpclass, qpunbase);
86 b64setup(b64unbase); 86 b64setup(b64unbase);
diff --git a/src/mime.h b/src/mime.h
index 688d043..d596861 100644
--- a/src/mime.h
+++ b/src/mime.h
@@ -19,6 +19,6 @@
19#define MIME_API extern 19#define MIME_API extern
20#endif 20#endif
21 21
22MIME_API int luaopen_mime(lua_State *L); 22MIME_API int luaopen_cmime(lua_State *L);
23 23
24#endif /* MIME_H */ 24#endif /* MIME_H */
diff --git a/src/mime.lua b/src/mime.lua
index 4d5bdba..6492a96 100644
--- a/src/mime.lua
+++ b/src/mime.lua
@@ -8,9 +8,10 @@
8----------------------------------------------------------------------------- 8-----------------------------------------------------------------------------
9-- Declare module and import dependencies 9-- Declare module and import dependencies
10----------------------------------------------------------------------------- 10-----------------------------------------------------------------------------
11package.loaded.base = _G
11local base = require("base") 12local base = require("base")
12local ltn12 = require("ltn12") 13local ltn12 = require("ltn12")
13local mime = require("lmime") 14local mime = require("cmime")
14module("mime") 15module("mime")
15 16
16-- encode, decode and wrap algorithm tables 17-- encode, decode and wrap algorithm tables
diff --git a/src/socket.h b/src/socket.h
index 368c2b6..639229d 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -45,11 +45,15 @@ int sock_sendto(p_sock ps, const char *data, size_t count,
45 size_t *sent, SA *addr, socklen_t addr_len, p_tm tm); 45 size_t *sent, SA *addr, socklen_t addr_len, p_tm tm);
46int sock_recvfrom(p_sock ps, char *data, size_t count, 46int sock_recvfrom(p_sock ps, char *data, size_t count,
47 size_t *got, SA *addr, socklen_t *addr_len, p_tm tm); 47 size_t *got, SA *addr, socklen_t *addr_len, p_tm tm);
48
48void sock_setnonblocking(p_sock ps); 49void sock_setnonblocking(p_sock ps);
49void sock_setblocking(p_sock ps); 50void sock_setblocking(p_sock ps);
51
52int sock_waitfd(int fd, int sw, p_tm tm);
50int sock_select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, p_tm tm); 53int sock_select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, p_tm tm);
51 54
52int sock_connect(p_sock ps, SA *addr, socklen_t addr_len, p_tm tm); 55int sock_connect(p_sock ps, SA *addr, socklen_t addr_len, p_tm tm);
56int sock_connected(p_sock ps, p_tm tm);
53int sock_create(p_sock ps, int domain, int type, int protocol); 57int sock_create(p_sock ps, int domain, int type, int protocol);
54int sock_bind(p_sock ps, SA *addr, socklen_t addr_len); 58int sock_bind(p_sock ps, SA *addr, socklen_t addr_len);
55int sock_listen(p_sock ps, int backlog); 59int sock_listen(p_sock ps, int backlog);
diff --git a/src/socket.lua b/src/socket.lua
index 1c82750..f3563e7 100644
--- a/src/socket.lua
+++ b/src/socket.lua
@@ -7,10 +7,11 @@
7----------------------------------------------------------------------------- 7-----------------------------------------------------------------------------
8-- Declare module and import dependencies 8-- Declare module and import dependencies
9----------------------------------------------------------------------------- 9-----------------------------------------------------------------------------
10package.loaded.base = _G
10local base = require("base") 11local base = require("base")
11local string = require("string") 12local string = require("string")
12local math = require("math") 13local math = require("math")
13local socket = require("lsocket") 14local socket = require("csocket")
14module("socket") 15module("socket")
15 16
16----------------------------------------------------------------------------- 17-----------------------------------------------------------------------------
diff --git a/src/tcp.c b/src/tcp.c
index 0b3706b..3a84191 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -20,6 +20,7 @@
20\*=========================================================================*/ 20\*=========================================================================*/
21static int global_create(lua_State *L); 21static int global_create(lua_State *L);
22static int meth_connect(lua_State *L); 22static int meth_connect(lua_State *L);
23static int meth_connected(lua_State *L);
23static int meth_listen(lua_State *L); 24static int meth_listen(lua_State *L);
24static int meth_bind(lua_State *L); 25static int meth_bind(lua_State *L);
25static int meth_send(lua_State *L); 26static int meth_send(lua_State *L);
@@ -45,6 +46,7 @@ static luaL_reg tcp[] = {
45 {"bind", meth_bind}, 46 {"bind", meth_bind},
46 {"close", meth_close}, 47 {"close", meth_close},
47 {"connect", meth_connect}, 48 {"connect", meth_connect},
49 {"connected", meth_connected},
48 {"dirty", meth_dirty}, 50 {"dirty", meth_dirty},
49 {"getfd", meth_getfd}, 51 {"getfd", meth_getfd},
50 {"getpeername", meth_getpeername}, 52 {"getpeername", meth_getpeername},
@@ -113,12 +115,12 @@ static int meth_receive(lua_State *L) {
113} 115}
114 116
115static int meth_getstats(lua_State *L) { 117static int meth_getstats(lua_State *L) {
116 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1); 118 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1);
117 return buf_meth_getstats(L, &tcp->buf); 119 return buf_meth_getstats(L, &tcp->buf);
118} 120}
119 121
120static int meth_setstats(lua_State *L) { 122static int meth_setstats(lua_State *L) {
121 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1); 123 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1);
122 return buf_meth_setstats(L, &tcp->buf); 124 return buf_meth_setstats(L, &tcp->buf);
123} 125}
124 126
@@ -224,6 +226,22 @@ static int meth_connect(lua_State *L)
224 return 1; 226 return 1;
225} 227}
226 228
229static int meth_connected(lua_State *L)
230{
231 static t_tm tm = {-1, -1};
232 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1);
233 int err = sock_connected(&tcp->sock, &tm);
234 if (err != IO_DONE) {
235 lua_pushnil(L);
236 lua_pushstring(L, sock_strerror(err));
237 return 2;
238 }
239 /* turn master object into a client object */
240 aux_setclass(L, "tcp{client}", 1);
241 lua_pushnumber(L, 1);
242 return 1;
243}
244
227/*-------------------------------------------------------------------------*\ 245/*-------------------------------------------------------------------------*\
228* Closes socket used by object 246* Closes socket used by object
229\*-------------------------------------------------------------------------*/ 247\*-------------------------------------------------------------------------*/
diff --git a/src/unix.c b/src/unix.c
index 1e0e252..c169268 100644
--- a/src/unix.c
+++ b/src/unix.c
@@ -32,6 +32,8 @@ static int meth_settimeout(lua_State *L);
32static int meth_getfd(lua_State *L); 32static int meth_getfd(lua_State *L);
33static int meth_setfd(lua_State *L); 33static int meth_setfd(lua_State *L);
34static int meth_dirty(lua_State *L); 34static int meth_dirty(lua_State *L);
35static int meth_getstats(lua_State *L);
36static int meth_setstats(lua_State *L);
35 37
36static const char *unix_tryconnect(p_unix un, const char *path); 38static const char *unix_tryconnect(p_unix un, const char *path);
37static const char *unix_trybind(p_unix un, const char *path); 39static const char *unix_trybind(p_unix un, const char *path);
@@ -46,6 +48,8 @@ static luaL_reg un[] = {
46 {"connect", meth_connect}, 48 {"connect", meth_connect},
47 {"dirty", meth_dirty}, 49 {"dirty", meth_dirty},
48 {"getfd", meth_getfd}, 50 {"getfd", meth_getfd},
51 {"getstats", meth_getstats},
52 {"setstats", meth_setstats},
49 {"listen", meth_listen}, 53 {"listen", meth_listen},
50 {"receive", meth_receive}, 54 {"receive", meth_receive},
51 {"send", meth_send}, 55 {"send", meth_send},
@@ -75,7 +79,7 @@ static luaL_reg func[] = {
75/*-------------------------------------------------------------------------*\ 79/*-------------------------------------------------------------------------*\
76* Initializes module 80* Initializes module
77\*-------------------------------------------------------------------------*/ 81\*-------------------------------------------------------------------------*/
78int unix_open(lua_State *L) { 82int luaopen_socketunix(lua_State *L) {
79 /* create classes */ 83 /* create classes */
80 aux_newclass(L, "unix{master}", un); 84 aux_newclass(L, "unix{master}", un);
81 aux_newclass(L, "unix{client}", un); 85 aux_newclass(L, "unix{client}", un);
@@ -84,11 +88,9 @@ int unix_open(lua_State *L) {
84 aux_add2group(L, "unix{master}", "unix{any}"); 88 aux_add2group(L, "unix{master}", "unix{any}");
85 aux_add2group(L, "unix{client}", "unix{any}"); 89 aux_add2group(L, "unix{client}", "unix{any}");
86 aux_add2group(L, "unix{server}", "unix{any}"); 90 aux_add2group(L, "unix{server}", "unix{any}");
87 aux_add2group(L, "unix{client}", "unix{client,server}");
88 aux_add2group(L, "unix{server}", "unix{client,server}");
89 /* define library functions */ 91 /* define library functions */
90 luaL_openlib(L, NULL, func, 0); 92 luaL_openlib(L, "socket", func, 0);
91 return 0; 93 return 1;
92} 94}
93 95
94/*=========================================================================*\ 96/*=========================================================================*\
@@ -107,6 +109,16 @@ static int meth_receive(lua_State *L) {
107 return buf_meth_receive(L, &un->buf); 109 return buf_meth_receive(L, &un->buf);
108} 110}
109 111
112static int meth_getstats(lua_State *L) {
113 p_unix un = (p_unix) aux_checkclass(L, "unix{client}", 1);
114 return buf_meth_getstats(L, &un->buf);
115}
116
117static int meth_setstats(lua_State *L) {
118 p_unix un = (p_unix) aux_checkclass(L, "unix{client}", 1);
119 return buf_meth_setstats(L, &un->buf);
120}
121
110/*-------------------------------------------------------------------------*\ 122/*-------------------------------------------------------------------------*\
111* Just call option handler 123* Just call option handler
112\*-------------------------------------------------------------------------*/ 124\*-------------------------------------------------------------------------*/
@@ -250,7 +262,8 @@ static int meth_close(lua_State *L)
250{ 262{
251 p_unix un = (p_unix) aux_checkgroup(L, "unix{any}", 1); 263 p_unix un = (p_unix) aux_checkgroup(L, "unix{any}", 1);
252 sock_destroy(&un->sock); 264 sock_destroy(&un->sock);
253 return 0; 265 lua_pushnumber(L, 1);
266 return 1;
254} 267}
255 268
256/*-------------------------------------------------------------------------*\ 269/*-------------------------------------------------------------------------*\
@@ -277,7 +290,7 @@ static int meth_listen(lua_State *L)
277\*-------------------------------------------------------------------------*/ 290\*-------------------------------------------------------------------------*/
278static int meth_shutdown(lua_State *L) 291static int meth_shutdown(lua_State *L)
279{ 292{
280 p_unix un = (p_unix) aux_checkgroup(L, "unix{client}", 1); 293 p_unix un = (p_unix) aux_checkclass(L, "unix{client}", 1);
281 const char *how = luaL_optstring(L, 2, "both"); 294 const char *how = luaL_optstring(L, 2, "both");
282 switch (how[0]) { 295 switch (how[0]) {
283 case 'b': 296 case 'b':
diff --git a/src/unix.h b/src/unix.h
index 7b2a5c5..aaaef3d 100644
--- a/src/unix.h
+++ b/src/unix.h
@@ -23,6 +23,6 @@ typedef struct t_unix_ {
23} t_unix; 23} t_unix;
24typedef t_unix *p_unix; 24typedef t_unix *p_unix;
25 25
26int unix_open(lua_State *L); 26int luaopen_socketunix(lua_State *L);
27 27
28#endif /* UNIX_H */ 28#endif /* UNIX_H */
diff --git a/src/usocket.c b/src/usocket.c
index c1ab725..3428a0c 100644
--- a/src/usocket.c
+++ b/src/usocket.c
@@ -22,7 +22,7 @@
22#define WAITFD_R POLLIN 22#define WAITFD_R POLLIN
23#define WAITFD_W POLLOUT 23#define WAITFD_W POLLOUT
24#define WAITFD_C (POLLIN|POLLOUT) 24#define WAITFD_C (POLLIN|POLLOUT)
25static int sock_waitfd(int fd, int sw, p_tm tm) { 25int sock_waitfd(int fd, int sw, p_tm tm) {
26 int ret; 26 int ret;
27 struct pollfd pfd; 27 struct pollfd pfd;
28 pfd.fd = fd; 28 pfd.fd = fd;
@@ -44,7 +44,7 @@ static int sock_waitfd(int fd, int sw, p_tm tm) {
44#define WAITFD_W 2 44#define WAITFD_W 2
45#define WAITFD_C (WAITFD_R|WAITFD_W) 45#define WAITFD_C (WAITFD_R|WAITFD_W)
46 46
47static int sock_waitfd(int fd, int sw, p_tm tm) { 47int sock_waitfd(int fd, int sw, p_tm tm) {
48 int ret; 48 int ret;
49 fd_set rfds, wfds, *rp, *wp; 49 fd_set rfds, wfds, *rp, *wp;
50 struct timeval tv, *tp; 50 struct timeval tv, *tp;
@@ -166,12 +166,20 @@ int sock_connect(p_sock ps, SA *addr, socklen_t len, p_tm tm) {
166 while ((err = errno) == EINTR); 166 while ((err = errno) == EINTR);
167 /* if connection failed immediately, return error code */ 167 /* if connection failed immediately, return error code */
168 if (err != EINPROGRESS && err != EAGAIN) return err; 168 if (err != EINPROGRESS && err != EAGAIN) return err;
169 /* zero timeout case optimization */
170 if (tm_iszero(tm)) return IO_TIMEOUT;
169 /* wait until we have the result of the connection attempt or timeout */ 171 /* wait until we have the result of the connection attempt or timeout */
170 if ((err = sock_waitfd(*ps, WAITFD_C, tm)) == IO_CLOSED) { 172 return sock_connected(ps, tm);
171 /* finaly find out if we succeeded connecting */ 173}
174
175/*-------------------------------------------------------------------------*\
176* Checks if socket is connected, or return reason for failure
177\*-------------------------------------------------------------------------*/
178int sock_connected(p_sock ps, p_tm tm) {
179 int err;
180 if ((err = sock_waitfd(*ps, WAITFD_C, tm) == IO_CLOSED)) {
172 if (recv(*ps, (char *) &err, 0, 0) == 0) return IO_DONE; 181 if (recv(*ps, (char *) &err, 0, 0) == 0) return IO_DONE;
173 else return errno; 182 else return errno;
174 /* timed out or some weirder error */
175 } else return err; 183 } else return err;
176} 184}
177 185
@@ -321,13 +329,17 @@ void sock_setnonblocking(p_sock ps) {
321int sock_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) { 329int sock_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) {
322 *hp = gethostbyaddr(addr, len, AF_INET); 330 *hp = gethostbyaddr(addr, len, AF_INET);
323 if (*hp) return IO_DONE; 331 if (*hp) return IO_DONE;
324 else return h_errno; 332 else if (h_errno) return h_errno;
333 else if (errno) return errno;
334 else return IO_UNKNOWN;
325} 335}
326 336
327int sock_gethostbyname(const char *addr, struct hostent **hp) { 337int sock_gethostbyname(const char *addr, struct hostent **hp) {
328 *hp = gethostbyname(addr); 338 *hp = gethostbyname(addr);
329 if (*hp) return IO_DONE; 339 if (*hp) return IO_DONE;
330 else return h_errno; 340 else if (h_errno) return h_errno;
341 else if (errno) return errno;
342 else return IO_UNKNOWN;
331} 343}
332 344
333/*-------------------------------------------------------------------------*\ 345/*-------------------------------------------------------------------------*\
diff --git a/src/wsocket.c b/src/wsocket.c
index 69fac4d..c0686cd 100644
--- a/src/wsocket.c
+++ b/src/wsocket.c
@@ -45,7 +45,7 @@ int sock_close(void) {
45#define WAITFD_E 4 45#define WAITFD_E 4
46#define WAITFD_C (WAITFD_E|WAITFD_W) 46#define WAITFD_C (WAITFD_E|WAITFD_W)
47 47
48static int sock_waitfd(t_sock fd, int sw, p_tm tm) { 48int sock_waitfd(t_sock fd, int sw, p_tm tm) {
49 int ret; 49 int ret;
50 fd_set rfds, wfds, efds, *rp = NULL, *wp = NULL, *ep = NULL; 50 fd_set rfds, wfds, efds, *rp = NULL, *wp = NULL, *ep = NULL;
51 struct timeval tv, *tp = NULL; 51 struct timeval tv, *tp = NULL;
@@ -118,7 +118,17 @@ int sock_connect(p_sock ps, SA *addr, socklen_t len, p_tm tm) {
118 /* make sure the system is trying to connect */ 118 /* make sure the system is trying to connect */
119 err = WSAGetLastError(); 119 err = WSAGetLastError();
120 if (err != WSAEWOULDBLOCK && err != WSAEINPROGRESS) return err; 120 if (err != WSAEWOULDBLOCK && err != WSAEINPROGRESS) return err;
121 /* zero timeout case optimization */
122 if (tm_iszero(tm)) return IO_TIMEOUT;
121 /* we wait until something happens */ 123 /* we wait until something happens */
124 return sock_connected(ps, tm);
125}
126
127/*-------------------------------------------------------------------------*\
128* Check if socket is connected
129\*-------------------------------------------------------------------------*/
130int sock_connected(p_sock ps) {
131 int err;
122 if ((err = sock_waitfd(*ps, WAITFD_C, tm)) == IO_CLOSED) { 132 if ((err = sock_waitfd(*ps, WAITFD_C, tm)) == IO_CLOSED) {
123 int len = sizeof(err); 133 int len = sizeof(err);
124 /* give windows time to set the error (yes, disgusting) */ 134 /* give windows time to set the error (yes, disgusting) */
@@ -126,9 +136,8 @@ int sock_connect(p_sock ps, SA *addr, socklen_t len, p_tm tm) {
126 /* find out why we failed */ 136 /* find out why we failed */
127 getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &len); 137 getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &len);
128 /* we KNOW there was an error. if why is 0, we will return 138 /* we KNOW there was an error. if why is 0, we will return
129 * "unknown error", but it's not really our fault */ 139 * "unknown error", but it's not really our fault */
130 return err > 0? err: IO_UNKNOWN; 140 return err > 0? err: IO_UNKNOWN;
131 /* here we deal with the case in which it worked, timedout or weird errors */
132 } else return err; 141 } else return err;
133} 142}
134 143
diff --git a/test/dicttest.lua b/test/dicttest.lua
index a37ec8d..7ac7811 100644
--- a/test/dicttest.lua
+++ b/test/dicttest.lua
@@ -1,3 +1,3 @@
1local dict = require"socket.dict" 1local dict = require"socket.dict"
2 2
3for i,v in dict.get("dict://dell-diego/d:banana") do print(v) end 3for i,v in dict.get("dict://localhost/d:teste") do print(v) end
diff --git a/test/httptest.lua b/test/httptest.lua
index 8862ceb..2335fcb 100644
--- a/test/httptest.lua
+++ b/test/httptest.lua
@@ -23,7 +23,7 @@ http.TIMEOUT = 10
23local t = socket.gettime() 23local t = socket.gettime()
24 24
25host = host or "diego.student.princeton.edu" 25host = host or "diego.student.princeton.edu"
26proxy = proxy or "http://dell-diego:3128" 26proxy = proxy or "http://localhost:3128"
27prefix = prefix or "/luasocket-test" 27prefix = prefix or "/luasocket-test"
28cgiprefix = cgiprefix or "/luasocket-test-cgi" 28cgiprefix = cgiprefix or "/luasocket-test-cgi"
29index_file = "test/index.html" 29index_file = "test/index.html"
diff --git a/test/testclnt.lua b/test/testclnt.lua
index c2c782c..e3f2b94 100644
--- a/test/testclnt.lua
+++ b/test/testclnt.lua
@@ -465,16 +465,14 @@ print("Testing " .. 2*size .. " bytes")
465remote(string.format([[ 465remote(string.format([[
466 data:send(string.rep("a", %d)) 466 data:send(string.rep("a", %d))
467 socket.sleep(0.5) 467 socket.sleep(0.5)
468 data:send(string.rep("b", %d)) 468 data:send(string.rep("b", %d) .. "\n")
469]], size, size)) 469]], size, size))
470 local err = "timeout" 470 local err = "timeout"
471 local part = "" 471 local part = ""
472 local str 472 local str
473 data:settimeout(0) 473 data:settimeout(0)
474 while 1 do 474 while 1 do
475 local needed = 2*size - string.len(part) 475 str, err, part = data:receive("*l", part)
476 assert(needed > 0, "weird")
477 str, err, part = data:receive(needed, part)
478 if err ~= "timeout" then break end 476 if err ~= "timeout" then break end
479 end 477 end
480 assert(str == (string.rep("a", size) .. string.rep("b", size))) 478 assert(str == (string.rep("a", size) .. string.rep("b", size)))
@@ -482,15 +480,14 @@ remote(string.format([[
482remote(string.format([[ 480remote(string.format([[
483 str = data:receive(%d) 481 str = data:receive(%d)
484 socket.sleep(0.5) 482 socket.sleep(0.5)
485 str = data:receive(%d, str) 483 str = data:receive(2*%d, str)
486 data:send(str) 484 data:send(str)
487]], size, size)) 485]], size, size))
488 data:settimeout(0) 486 data:settimeout(0)
489 local sofar = 1 487 local start = 0
490 while 1 do 488 while 1 do
491 _, err, part = data:send(str, sofar) 489 ret, err, start = data:send(str, start+1)
492 if err ~= "timeout" then break end 490 if err ~= "timeout" then break end
493 sofar = sofar + part
494 end 491 end
495 data:send("\n") 492 data:send("\n")
496 data:settimeout(-1) 493 data:settimeout(-1)
@@ -501,6 +498,7 @@ end
501 498
502------------------------------------------------------------------------ 499------------------------------------------------------------------------
503 500
501
504test("method registration") 502test("method registration")
505test_methods(socket.tcp(), { 503test_methods(socket.tcp(), {
506 "accept", 504 "accept",
@@ -622,7 +620,7 @@ test_nonblocking(17)
622test_nonblocking(200) 620test_nonblocking(200)
623test_nonblocking(4091) 621test_nonblocking(4091)
624test_nonblocking(80199) 622test_nonblocking(80199)
625test_nonblocking(8000000) 623test_nonblocking(800000)
626test_nonblocking(80199) 624test_nonblocking(80199)
627test_nonblocking(4091) 625test_nonblocking(4091)
628test_nonblocking(200) 626test_nonblocking(200)
diff --git a/test/testsrvr.lua b/test/testsrvr.lua
index 2408e83..f1972c2 100644
--- a/test/testsrvr.lua
+++ b/test/testsrvr.lua
@@ -9,6 +9,7 @@ while 1 do
9 while 1 do 9 while 1 do
10 command = assert(control:receive()); 10 command = assert(control:receive());
11 assert(control:send(ack)); 11 assert(control:send(ack));
12 print(command);
12 (loadstring(command))(); 13 (loadstring(command))();
13 end 14 end
14end 15end
diff --git a/test/utestclnt.lua b/test/utestclnt.lua
new file mode 100644
index 0000000..f002c6e
--- /dev/null
+++ b/test/utestclnt.lua
@@ -0,0 +1,644 @@
1require"socket"
2local socket = require"socket.unix"
3
4host = "luasocket"
5
6function pass(...)
7 local s = string.format(unpack(arg))
8 io.stderr:write(s, "\n")
9end
10
11function fail(...)
12 local s = string.format(unpack(arg))
13 io.stderr:write("ERROR: ", s, "!\n")
14socket.sleep(3)
15 os.exit()
16end
17
18function warn(...)
19 local s = string.format(unpack(arg))
20 io.stderr:write("WARNING: ", s, "\n")
21end
22
23function remote(...)
24 local s = string.format(unpack(arg))
25 s = string.gsub(s, "\n", ";")
26 s = string.gsub(s, "%s+", " ")
27 s = string.gsub(s, "^%s*", "")
28 control:send(s .. "\n")
29 control:receive()
30end
31
32function test(test)
33 io.stderr:write("----------------------------------------------\n",
34 "testing: ", test, "\n",
35 "----------------------------------------------\n")
36end
37
38function uconnect(path)
39 local u = assert(socket.unix())
40 assert(u:connect(path))
41 return u
42end
43
44function ubind(path)
45 local u = assert(socket.unix())
46 assert(u:bind(path))
47 assert(u:listen(5))
48 return u
49end
50
51function check_timeout(tm, sl, elapsed, err, opp, mode, alldone)
52 if tm < sl then
53 if opp == "send" then
54 if not err then warn("must be buffered")
55 elseif err == "timeout" then pass("proper timeout")
56 else fail("unexpected error '%s'", err) end
57 else
58 if err ~= "timeout" then fail("should have timed out")
59 else pass("proper timeout") end
60 end
61 else
62 if mode == "total" then
63 if elapsed > tm then
64 if err ~= "timeout" then fail("should have timed out")
65 else pass("proper timeout") end
66 elseif elapsed < tm then
67 if err then fail(err)
68 else pass("ok") end
69 else
70 if alldone then
71 if err then fail("unexpected error '%s'", err)
72 else pass("ok") end
73 else
74 if err ~= "timeout" then fail(err)
75 else pass("proper timeoutk") end
76 end
77 end
78 else
79 if err then fail(err)
80 else pass("ok") end
81 end
82 end
83end
84
85if not socket.DEBUG then
86 fail("Please define LUASOCKET_DEBUG and recompile LuaSocket")
87end
88
89io.stderr:write("----------------------------------------------\n",
90"LuaSocket Test Procedures\n",
91"----------------------------------------------\n")
92
93start = socket.gettime()
94
95function reconnect()
96 io.stderr:write("attempting data connection... ")
97 if data then data:close() end
98 remote [[
99 i = i or 1
100 if data then data:close() data = nil end
101 print("accepting")
102 data = server:accept()
103 i = i + 1
104 print("done " .. i)
105 ]]
106 data, err = uconnect(host, port)
107 if not data then fail(err)
108 else pass("connected!") end
109end
110
111pass("attempting control connection...")
112control, err = uconnect(host, port)
113if err then fail(err)
114else pass("connected!") end
115
116------------------------------------------------------------------------
117function test_methods(sock, methods)
118 for _, v in methods do
119 if type(sock[v]) ~= "function" then
120 fail(sock.class .. " method '" .. v .. "' not registered")
121 end
122 end
123 pass(sock.class .. " methods are ok")
124end
125
126------------------------------------------------------------------------
127function test_mixed(len)
128 reconnect()
129 local inter = math.ceil(len/4)
130 local p1 = "unix " .. string.rep("x", inter) .. "line\n"
131 local p2 = "dos " .. string.rep("y", inter) .. "line\r\n"
132 local p3 = "raw " .. string.rep("z", inter) .. "bytes"
133 local p4 = "end" .. string.rep("w", inter) .. "bytes"
134 local bp1, bp2, bp3, bp4
135remote (string.format("str = data:receive(%d)",
136 string.len(p1)+string.len(p2)+string.len(p3)+string.len(p4)))
137 sent, err = data:send(p1..p2..p3..p4)
138 if err then fail(err) end
139remote "data:send(str); data:close()"
140 bp1, err = data:receive()
141 if err then fail(err) end
142 bp2, err = data:receive()
143 if err then fail(err) end
144 bp3, err = data:receive(string.len(p3))
145 if err then fail(err) end
146 bp4, err = data:receive("*a")
147 if err then fail(err) end
148 if bp1.."\n" == p1 and bp2.."\r\n" == p2 and bp3 == p3 and bp4 == p4 then
149 pass("patterns match")
150 else fail("patterns don't match") end
151end
152
153------------------------------------------------------------------------
154function test_asciiline(len)
155 reconnect()
156 local str, str10, back, err
157 str = string.rep("x", math.mod(len, 10))
158 str10 = string.rep("aZb.c#dAe?", math.floor(len/10))
159 str = str .. str10
160remote "str = data:receive()"
161 sent, err = data:send(str.."\n")
162 if err then fail(err) end
163remote "data:send(str ..'\\n')"
164 back, err = data:receive()
165 if err then fail(err) end
166 if back == str then pass("lines match")
167 else fail("lines don't match") end
168end
169
170------------------------------------------------------------------------
171function test_rawline(len)
172 reconnect()
173 local str, str10, back, err
174 str = string.rep(string.char(47), math.mod(len, 10))
175 str10 = string.rep(string.char(120,21,77,4,5,0,7,36,44,100),
176 math.floor(len/10))
177 str = str .. str10
178remote "str = data:receive()"
179 sent, err = data:send(str.."\n")
180 if err then fail(err) end
181remote "data:send(str..'\\n')"
182 back, err = data:receive()
183 if err then fail(err) end
184 if back == str then pass("lines match")
185 else fail("lines don't match") end
186end
187
188------------------------------------------------------------------------
189function test_raw(len)
190 reconnect()
191 local half = math.floor(len/2)
192 local s1, s2, back, err
193 s1 = string.rep("x", half)
194 s2 = string.rep("y", len-half)
195remote (string.format("str = data:receive(%d)", len))
196 sent, err = data:send(s1)
197 if err then fail(err) end
198 sent, err = data:send(s2)
199 if err then fail(err) end
200remote "data:send(str)"
201 back, err = data:receive(len)
202 if err then fail(err) end
203 if back == s1..s2 then pass("blocks match")
204 else fail("blocks don't match") end
205end
206
207------------------------------------------------------------------------
208function test_totaltimeoutreceive(len, tm, sl)
209 reconnect()
210 local str, err, partial
211 pass("%d bytes, %ds total timeout, %ds pause", len, tm, sl)
212 remote (string.format ([[
213 data:settimeout(%d)
214 str = string.rep('a', %d)
215 data:send(str)
216 print('server: sleeping for %ds')
217 socket.sleep(%d)
218 print('server: woke up')
219 data:send(str)
220 ]], 2*tm, len, sl, sl))
221 data:settimeout(tm, "total")
222local t = socket.gettime()
223 str, err, partial, elapsed = data:receive(2*len)
224 check_timeout(tm, sl, elapsed, err, "receive", "total",
225 string.len(str or partial) == 2*len)
226end
227
228------------------------------------------------------------------------
229function test_totaltimeoutsend(len, tm, sl)
230 reconnect()
231 local str, err, total
232 pass("%d bytes, %ds total timeout, %ds pause", len, tm, sl)
233 remote (string.format ([[
234 data:settimeout(%d)
235 str = data:receive(%d)
236 print('server: sleeping for %ds')
237 socket.sleep(%d)
238 print('server: woke up')
239 str = data:receive(%d)
240 ]], 2*tm, len, sl, sl, len))
241 data:settimeout(tm, "total")
242 str = string.rep("a", 2*len)
243 total, err, partial, elapsed = data:send(str)
244 check_timeout(tm, sl, elapsed, err, "send", "total",
245 total == 2*len)
246end
247
248------------------------------------------------------------------------
249function test_blockingtimeoutreceive(len, tm, sl)
250 reconnect()
251 local str, err, partial
252 pass("%d bytes, %ds blocking timeout, %ds pause", len, tm, sl)
253 remote (string.format ([[
254 data:settimeout(%d)
255 str = string.rep('a', %d)
256 data:send(str)
257 print('server: sleeping for %ds')
258 socket.sleep(%d)
259 print('server: woke up')
260 data:send(str)
261 ]], 2*tm, len, sl, sl))
262 data:settimeout(tm)
263 str, err, partial, elapsed = data:receive(2*len)
264 check_timeout(tm, sl, elapsed, err, "receive", "blocking",
265 string.len(str or partial) == 2*len)
266end
267
268------------------------------------------------------------------------
269function test_blockingtimeoutsend(len, tm, sl)
270 reconnect()
271 local str, err, total
272 pass("%d bytes, %ds blocking timeout, %ds pause", len, tm, sl)
273 remote (string.format ([[
274 data:settimeout(%d)
275 str = data:receive(%d)
276 print('server: sleeping for %ds')
277 socket.sleep(%d)
278 print('server: woke up')
279 str = data:receive(%d)
280 ]], 2*tm, len, sl, sl, len))
281 data:settimeout(tm)
282 str = string.rep("a", 2*len)
283 total, err, partial, elapsed = data:send(str)
284 check_timeout(tm, sl, elapsed, err, "send", "blocking",
285 total == 2*len)
286end
287
288------------------------------------------------------------------------
289function empty_connect()
290 reconnect()
291 if data then data:close() data = nil end
292 remote [[
293 if data then data:close() data = nil end
294 data = server:accept()
295 ]]
296 data, err = socket.connect("", port)
297 if not data then
298 pass("ok")
299 data = socket.connect(host, port)
300 else
301 pass("gethostbyname returns localhost on empty string...")
302 end
303end
304
305------------------------------------------------------------------------
306function isclosed(c)
307 return c:getfd() == -1 or c:getfd() == (2^32-1)
308end
309
310function active_close()
311 reconnect()
312 if isclosed(data) then fail("should not be closed") end
313 data:close()
314 if not isclosed(data) then fail("should be closed") end
315 data = nil
316 local udp = socket.udp()
317 if isclosed(udp) then fail("should not be closed") end
318 udp:close()
319 if not isclosed(udp) then fail("should be closed") end
320 pass("ok")
321end
322
323------------------------------------------------------------------------
324function test_closed()
325 local back, partial, err
326 local str = 'little string'
327 reconnect()
328 pass("trying read detection")
329 remote (string.format ([[
330 data:send('%s')
331 data:close()
332 data = nil
333 ]], str))
334 -- try to get a line
335 back, err, partial = data:receive()
336 if not err then fail("should have gotten 'closed'.")
337 elseif err ~= "closed" then fail("got '"..err.."' instead of 'closed'.")
338 elseif str ~= partial then fail("didn't receive partial result.")
339 else pass("graceful 'closed' received") end
340 reconnect()
341 pass("trying write detection")
342 remote [[
343 data:close()
344 data = nil
345 ]]
346 total, err, partial = data:send(string.rep("ugauga", 100000))
347 if not err then
348 pass("failed: output buffer is at least %d bytes long!", total)
349 elseif err ~= "closed" then
350 fail("got '"..err.."' instead of 'closed'.")
351 else
352 pass("graceful 'closed' received after %d bytes were sent", partial)
353 end
354end
355
356------------------------------------------------------------------------
357function test_selectbugs()
358 local r, s, e = socket.select(nil, nil, 0.1)
359 assert(type(r) == "table" and type(s) == "table" and
360 (e == "timeout" or e == "error"))
361 pass("both nil: ok")
362 local udp = socket.udp()
363 udp:close()
364 r, s, e = socket.select({ udp }, { udp }, 0.1)
365 assert(type(r) == "table" and type(s) == "table" and
366 (e == "timeout" or e == "error"))
367 pass("closed sockets: ok")
368 e = pcall(socket.select, "wrong", 1, 0.1)
369 assert(e == false)
370 e = pcall(socket.select, {}, 1, 0.1)
371 assert(e == false)
372 pass("invalid input: ok")
373end
374
375------------------------------------------------------------------------
376function accept_timeout()
377 io.stderr:write("accept with timeout (if it hangs, it failed): ")
378 local s, e = socket.bind("*", 0, 0)
379 assert(s, e)
380 local t = socket.gettime()
381 s:settimeout(1)
382 local c, e = s:accept()
383 assert(not c, "should not accept")
384 assert(e == "timeout", string.format("wrong error message (%s)", e))
385 t = socket.gettime() - t
386 assert(t < 2, string.format("took to long to give up (%gs)", t))
387 s:close()
388 pass("good")
389end
390
391------------------------------------------------------------------------
392function connect_timeout()
393 io.stderr:write("connect with timeout (if it hangs, it failed!): ")
394 local t = socket.gettime()
395 local c, e = socket.tcp()
396 assert(c, e)
397 c:settimeout(0.1)
398 local t = socket.gettime()
399 local r, e = c:connect("127.0.0.2", 80)
400 assert(not r, "should not connect")
401 assert(socket.gettime() - t < 2, "took too long to give up.")
402 c:close()
403 print("ok")
404end
405
406------------------------------------------------------------------------
407function accept_errors()
408 io.stderr:write("not listening: ")
409 local d, e = socket.bind("*", 0)
410 assert(d, e);
411 local c, e = socket.tcp();
412 assert(c, e);
413 d:setfd(c:getfd())
414 d:settimeout(2)
415 local r, e = d:accept()
416 assert(not r and e)
417 print("ok: ", e)
418 io.stderr:write("not supported: ")
419 local c, e = socket.udp()
420 assert(c, e);
421 d:setfd(c:getfd())
422 local r, e = d:accept()
423 assert(not r and e)
424 print("ok: ", e)
425end
426
427------------------------------------------------------------------------
428function connect_errors()
429 io.stderr:write("connection refused: ")
430 local c, e = socket.connect("localhost", 1);
431 assert(not c and e)
432 print("ok: ", e)
433 io.stderr:write("host not found: ")
434 local c, e = socket.connect("host.is.invalid", 1);
435 assert(not c and e, e)
436 print("ok: ", e)
437end
438
439------------------------------------------------------------------------
440function rebind_test()
441 local c = socket.bind("localhost", 0)
442 local i, p = c:getsockname()
443 local s, e = socket.tcp()
444 assert(s, e)
445 s:setoption("reuseaddr", false)
446 r, e = s:bind("localhost", p)
447 assert(not r, "managed to rebind!")
448 assert(e)
449 print("ok: ", e)
450end
451
452------------------------------------------------------------------------
453function getstats_test()
454 reconnect()
455 local t = 0
456 for i = 1, 25 do
457 local c = math.random(1, 100)
458 remote (string.format ([[
459 str = data:receive(%d)
460 data:send(str)
461 ]], c))
462 data:send(string.rep("a", c))
463 data:receive(c)
464 t = t + c
465 local r, s, a = data:getstats()
466 assert(r == t, "received count failed" .. tostring(r)
467 .. "/" .. tostring(t))
468 assert(s == t, "sent count failed" .. tostring(s)
469 .. "/" .. tostring(t))
470 end
471 print("ok")
472end
473
474
475------------------------------------------------------------------------
476function test_nonblocking(size)
477 reconnect()
478print("Testing " .. 2*size .. " bytes")
479remote(string.format([[
480 data:send(string.rep("a", %d))
481 socket.sleep(0.5)
482 data:send(string.rep("b", %d) .. "\n")
483]], size, size))
484 local err = "timeout"
485 local part = ""
486 local str
487 data:settimeout(0)
488 while 1 do
489 str, err, part = data:receive("*l", part)
490 if err ~= "timeout" then break end
491 end
492 assert(str == (string.rep("a", size) .. string.rep("b", size)))
493 reconnect()
494remote(string.format([[
495 str = data:receive(%d)
496 socket.sleep(0.5)
497 str = data:receive(%d, str)
498 data:send(str)
499]], size, size))
500 data:settimeout(0)
501 local start = 0
502 while 1 do
503 ret, err, start = data:send(str, start+1)
504 if err ~= "timeout" then break end
505 end
506 data:send("\n")
507 data:settimeout(-1)
508 local back = data:receive(2*size)
509 assert(back == str, "'" .. back .. "' vs '" .. str .. "'")
510 print("ok")
511end
512
513------------------------------------------------------------------------
514
515test("method registration")
516test_methods(socket.unix(), {
517 "accept",
518 "bind",
519 "close",
520 "connect",
521 "dirty",
522 "getfd",
523 "getstats",
524 "setstats",
525 "listen",
526 "receive",
527 "send",
528 "setfd",
529 "setoption",
530 "setpeername",
531 "setsockname",
532 "settimeout",
533 "shutdown",
534})
535
536test("connect function")
537--connect_timeout()
538--empty_connect()
539--connect_errors()
540
541--test("rebinding: ")
542--rebind_test()
543
544test("active close: ")
545active_close()
546
547test("closed connection detection: ")
548test_closed()
549
550test("accept function: ")
551accept_timeout()
552accept_errors()
553
554test("getstats test")
555getstats_test()
556
557test("character line")
558test_asciiline(1)
559test_asciiline(17)
560test_asciiline(200)
561test_asciiline(4091)
562test_asciiline(80199)
563test_asciiline(8000000)
564test_asciiline(80199)
565test_asciiline(4091)
566test_asciiline(200)
567test_asciiline(17)
568test_asciiline(1)
569
570test("mixed patterns")
571test_mixed(1)
572test_mixed(17)
573test_mixed(200)
574test_mixed(4091)
575test_mixed(801990)
576test_mixed(4091)
577test_mixed(200)
578test_mixed(17)
579test_mixed(1)
580
581test("binary line")
582test_rawline(1)
583test_rawline(17)
584test_rawline(200)
585test_rawline(4091)
586test_rawline(80199)
587test_rawline(8000000)
588test_rawline(80199)
589test_rawline(4091)
590test_rawline(200)
591test_rawline(17)
592test_rawline(1)
593
594test("raw transfer")
595test_raw(1)
596test_raw(17)
597test_raw(200)
598test_raw(4091)
599test_raw(80199)
600test_raw(8000000)
601test_raw(80199)
602test_raw(4091)
603test_raw(200)
604test_raw(17)
605test_raw(1)
606
607test("non-blocking transfer")
608test_nonblocking(1)
609test_nonblocking(17)
610test_nonblocking(200)
611test_nonblocking(4091)
612test_nonblocking(80199)
613test_nonblocking(8000000)
614test_nonblocking(80199)
615test_nonblocking(4091)
616test_nonblocking(200)
617test_nonblocking(17)
618test_nonblocking(1)
619
620test("total timeout on send")
621test_totaltimeoutsend(800091, 1, 3)
622test_totaltimeoutsend(800091, 2, 3)
623test_totaltimeoutsend(800091, 5, 2)
624test_totaltimeoutsend(800091, 3, 1)
625
626test("total timeout on receive")
627test_totaltimeoutreceive(800091, 1, 3)
628test_totaltimeoutreceive(800091, 2, 3)
629test_totaltimeoutreceive(800091, 3, 2)
630test_totaltimeoutreceive(800091, 3, 1)
631
632test("blocking timeout on send")
633test_blockingtimeoutsend(800091, 1, 3)
634test_blockingtimeoutsend(800091, 2, 3)
635test_blockingtimeoutsend(800091, 3, 2)
636test_blockingtimeoutsend(800091, 3, 1)
637
638test("blocking timeout on receive")
639test_blockingtimeoutreceive(800091, 1, 3)
640test_blockingtimeoutreceive(800091, 2, 3)
641test_blockingtimeoutreceive(800091, 3, 2)
642test_blockingtimeoutreceive(800091, 3, 1)
643
644test(string.format("done in %.2fs", socket.gettime() - start))
diff --git a/test/utestsrvr.lua b/test/utestsrvr.lua
new file mode 100644
index 0000000..f7be196
--- /dev/null
+++ b/test/utestsrvr.lua
@@ -0,0 +1,17 @@
1require("socket");
2os.remove("/tmp/luasocket")
3socket = require("socket.unix");
4host = "luasocket";
5server = socket.unix()
6print(server:bind(host))
7print(server:listen(5))
8ack = "\n";
9while 1 do
10 print("server: waiting for client connection...");
11 control = assert(server:accept());
12 while 1 do
13 command = assert(control:receive());
14 assert(control:send(ack));
15 (loadstring(command))();
16 end
17end