aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2004-07-18 22:56:14 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2004-07-18 22:56:14 +0000
commitc8b402e00442cd249397d4d33d2723a1f08a8108 (patch)
treed72a1ace55b42aa9d41c741fa2f757d92fad6592
parente4e2223cff658a7016724a625ebbd3dacb92a8f9 (diff)
downloadluasocket-c8b402e00442cd249397d4d33d2723a1f08a8108.tar.gz
luasocket-c8b402e00442cd249397d4d33d2723a1f08a8108.tar.bz2
luasocket-c8b402e00442cd249397d4d33d2723a1f08a8108.zip
Changed send function.
-rw-r--r--FIX4
-rw-r--r--TODO3
-rw-r--r--doc/introduction.html2
-rw-r--r--doc/tcp.html35
-rw-r--r--src/buffer.c23
-rw-r--r--src/wsocket.c2
-rw-r--r--test/testclnt.lua86
-rw-r--r--test/testsrvr.lua33
8 files changed, 118 insertions, 70 deletions
diff --git a/FIX b/FIX
index 08f1452..f0ad3aa 100644
--- a/FIX
+++ b/FIX
@@ -1,3 +1,7 @@
1UDP has a reasonable maximum datagram size
2receive accepts the prefix optional argument
3send doesn't support multiple arguments anymore
4send allows the selection of the substring to be sent
1fix bug that caused select return tables not to be associative on windows 5fix bug that caused select return tables not to be associative on windows
2compiles with g++ 6compiles with g++
3new sample unix domain support 7new sample unix domain support
diff --git a/TODO b/TODO
index ec8f25e..23de9d7 100644
--- a/TODO
+++ b/TODO
@@ -1,4 +1,7 @@
1 1
2fix manual for send and receive
3add thanks to mike
4
2change sock:send to use indices just like string.sub? 5change sock:send to use indices just like string.sub?
3use mike's "don't set to blocking before closing unless needed" patch? 6use mike's "don't set to blocking before closing unless needed" patch?
4take a look at DB's smtp patch 7take a look at DB's smtp patch
diff --git a/doc/introduction.html b/doc/introduction.html
index 6468148..20c4d36 100644
--- a/doc/introduction.html
+++ b/doc/introduction.html
@@ -113,7 +113,7 @@ The core LuaSocket is almost entirely implemented in C. It is
113usually available as a dynamic library which the interpreter can load 113usually available as a dynamic library which the interpreter can load
114with the help of a loader module written in Lua. 114with the help of a loader module written in Lua.
115Beginning with version 2.0 and following the Lua 5.0 trend, all LuaSocket 115Beginning with version 2.0 and following the Lua 5.0 trend, all LuaSocket
116functionality is defined inside tables (or rather a namespaces). No global 116functionality is defined inside tables (or rather namespaces). No global
117variables are ever created. 117variables are ever created.
118Namespaces are obtained with the <tt>require</tt> Lua function, which loads 118Namespaces are obtained with the <tt>require</tt> Lua function, which loads
119and initializes any required library and returns the namespace. 119and initializes any required library and returns the namespace.
diff --git a/doc/tcp.html b/doc/tcp.html
index 5f520e9..30e06f4 100644
--- a/doc/tcp.html
+++ b/doc/tcp.html
@@ -260,7 +260,7 @@ method returns <b><tt>nil</tt></b> followed by an error message.
260<!-- receive ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> 260<!-- receive ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
261 261
262<p class=name id=receive> 262<p class=name id=receive>
263client:<b>receive(</b>[pattern]<b>)</b> 263client:<b>receive(</b>[pattern [, prefix]]<b>)</b>
264</p> 264</p>
265 265
266<p class=description> 266<p class=description>
@@ -283,6 +283,11 @@ the returned line. This is the default pattern;
283of bytes from the socket. 283of bytes from the socket.
284</ul> 284</ul>
285 285
286<p class=parameters>
287<tt>Prefix</tt> is an optional string to be concatenated to the beginning
288of any received data before return.
289</p>
290
286<p class=return> 291<p class=return>
287If successful, the method returns the received pattern. In case of error, 292If successful, the method returns the received pattern. In case of error,
288the method returns <tt><b>nil</b></tt> followed by an error message which 293the method returns <tt><b>nil</b></tt> followed by an error message which
@@ -305,18 +310,18 @@ too.
305<!-- send +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> 310<!-- send +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
306 311
307<p class=name id=send> 312<p class=name id=send>
308client:<b>send(</b>string<sub>1</sub> [, 313client:<b>send(</b>data [, i [, j]]<b>)</b>
309string<sub>2</sub>, ... string<sub>N</sub>]<b>)</b>
310</p> 314</p>
311 315
312<p class=description> 316<p class=description>
313Sends data through client object. 317Sends <tt>data</tt> through client object.
314</p> 318</p>
315 319
316<p class=parameters> 320<p class=parameters>
317All parameters should be strings. For small strings, it is always better to 321<tt>Data</tt> is the string to be sent. The optional arguments
318concatenate them in Lua (with the '<tt>..</tt>' operator) and pass the 322<tt>i</tt> and <tt>j</tt> work exactly like the standard
319result to LuaSocket instead of passing several independent strings. 323<tt>string.sub</tt> Lua function to allow the selection of a
324substring to be sent.
320</p> 325</p>
321 326
322<p class=return> 327<p class=return>
@@ -341,6 +346,22 @@ Alas, it wasn't returning <tt><b>nil</b></tt> in case of
341error. So it was changed again in beta. 346error. So it was changed again in beta.
342</p> 347</p>
343 348
349<p class=note>
350<b>Also important</b>:
351In order to better support non-blocking I/O and to discourage
352bad practice, the <tt>send</tt> method now only sends one string
353per call. The other optional arguments allow the user to select
354a substring to be sent in a much more efficient way than
355using <tt>string.sub</tt>.
356</p>
357
358<p class=note>
359Note: Output is <em>not</em> buffered. For small strings,
360it is always better to concatenate them in Lua
361(with the '<tt>..</tt>' operator) and send the result in one call
362instead of calling the method several times.
363</p>
364
344<!-- setoption ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> 365<!-- setoption ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
345 366
346<p class=name id=setoption> 367<p class=name id=setoption>
diff --git a/src/buffer.c b/src/buffer.c
index 33fae84..30be156 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -64,23 +64,24 @@ int buf_meth_getstats(lua_State *L, p_buf buf) {
64\*-------------------------------------------------------------------------*/ 64\*-------------------------------------------------------------------------*/
65int buf_meth_send(lua_State *L, p_buf buf) { 65int buf_meth_send(lua_State *L, p_buf buf) {
66 int top = lua_gettop(L); 66 int top = lua_gettop(L);
67 size_t total = 0;
68 int arg, err = IO_DONE;
69 p_tm tm = tm_markstart(buf->tm); 67 p_tm tm = tm_markstart(buf->tm);
70 for (arg = 2; arg <= top; arg++) { /* first arg is socket object */ 68 int err = IO_DONE;
71 size_t sent, count; 69 size_t size, sent;
72 const char *data = luaL_optlstring(L, arg, NULL, &count); 70 const char *data = luaL_checklstring(L, 2, &size);
73 if (!data || err != IO_DONE) break; 71 ssize_t start = (ssize_t) luaL_optnumber(L, 3, 1);
74 err = sendraw(buf, data, count, &sent); 72 ssize_t end = (ssize_t) luaL_optnumber(L, 4, -1);
75 total += sent; 73 if (start < 0) start = size+start+1;
76 } 74 if (end < 0) end = size+end+1;
75 if (start < 1) start = 1;
76 if (end > size) end = size;
77 if (start <= end) err = sendraw(buf, data+start-1, end-start+1, &sent);
77 /* check if there was an error */ 78 /* check if there was an error */
78 if (err != IO_DONE) { 79 if (err != IO_DONE) {
79 lua_pushnil(L); 80 lua_pushnil(L);
80 lua_pushstring(L, buf->io->error(buf->io->ctx, err)); 81 lua_pushstring(L, buf->io->error(buf->io->ctx, err));
81 lua_pushnumber(L, total); 82 lua_pushnumber(L, sent);
82 } else { 83 } else {
83 lua_pushnumber(L, total); 84 lua_pushnumber(L, sent);
84 lua_pushnil(L); 85 lua_pushnil(L);
85 lua_pushnil(L); 86 lua_pushnil(L);
86 } 87 }
diff --git a/src/wsocket.c b/src/wsocket.c
index d9da6fc..511dbdc 100644
--- a/src/wsocket.c
+++ b/src/wsocket.c
@@ -373,12 +373,10 @@ static const char *wstrerror(int err) {
373 case WSANOTINITIALISED: 373 case WSANOTINITIALISED:
374 return "Successful WSAStartup not yet performed"; 374 return "Successful WSAStartup not yet performed";
375 case WSAEDISCON: return "Graceful shutdown in progress"; 375 case WSAEDISCON: return "Graceful shutdown in progress";
376 case WSATYPE_NOT_FOUND: return "Class type not found";
377 case WSAHOST_NOT_FOUND: return "Host not found"; 376 case WSAHOST_NOT_FOUND: return "Host not found";
378 case WSATRY_AGAIN: return "Nonauthoritative host not found"; 377 case WSATRY_AGAIN: return "Nonauthoritative host not found";
379 case WSANO_RECOVERY: return "Nonrecoverable name lookup error"; 378 case WSANO_RECOVERY: return "Nonrecoverable name lookup error";
380 case WSANO_DATA: return "Valid name, no data record of requested type"; 379 case WSANO_DATA: return "Valid name, no data record of requested type";
381 case WSASYSCALLFAILURE: return "System call failure";
382 default: return "Unknown error"; 380 default: return "Unknown error";
383 } 381 }
384} 382}
diff --git a/test/testclnt.lua b/test/testclnt.lua
index f98a504..356350a 100644
--- a/test/testclnt.lua
+++ b/test/testclnt.lua
@@ -25,7 +25,7 @@ function remote(...)
25 s = string.gsub(s, "\n", ";") 25 s = string.gsub(s, "\n", ";")
26 s = string.gsub(s, "%s+", " ") 26 s = string.gsub(s, "%s+", " ")
27 s = string.gsub(s, "^%s*", "") 27 s = string.gsub(s, "^%s*", "")
28 control:send(s, "\n") 28 control:send(s .. "\n")
29 control:receive() 29 control:receive()
30end 30end
31 31
@@ -120,7 +120,7 @@ function test_mixed(len)
120 local bp1, bp2, bp3, bp4 120 local bp1, bp2, bp3, bp4
121remote (string.format("str = data:receive(%d)", 121remote (string.format("str = data:receive(%d)",
122 string.len(p1)+string.len(p2)+string.len(p3)+string.len(p4))) 122 string.len(p1)+string.len(p2)+string.len(p3)+string.len(p4)))
123 sent, err = data:send(p1, p2, p3, p4) 123 sent, err = data:send(p1..p2..p3..p4)
124 if err then fail(err) end 124 if err then fail(err) end
125remote "data:send(str); data:close()" 125remote "data:send(str); data:close()"
126 bp1, err = data:receive() 126 bp1, err = data:receive()
@@ -144,9 +144,9 @@ function test_asciiline(len)
144 str10 = string.rep("aZb.c#dAe?", math.floor(len/10)) 144 str10 = string.rep("aZb.c#dAe?", math.floor(len/10))
145 str = str .. str10 145 str = str .. str10
146remote "str = data:receive()" 146remote "str = data:receive()"
147 sent, err = data:send(str, "\n") 147 sent, err = data:send(str.."\n")
148 if err then fail(err) end 148 if err then fail(err) end
149remote "data:send(str, '\\n')" 149remote "data:send(str ..'\\n')"
150 back, err = data:receive() 150 back, err = data:receive()
151 if err then fail(err) end 151 if err then fail(err) end
152 if back == str then pass("lines match") 152 if back == str then pass("lines match")
@@ -162,9 +162,9 @@ function test_rawline(len)
162 math.floor(len/10)) 162 math.floor(len/10))
163 str = str .. str10 163 str = str .. str10
164remote "str = data:receive()" 164remote "str = data:receive()"
165 sent, err = data:send(str, "\n") 165 sent, err = data:send(str.."\n")
166 if err then fail(err) end 166 if err then fail(err) end
167remote "data:send(str, '\\n')" 167remote "data:send(str..'\\n')"
168 back, err = data:receive() 168 back, err = data:receive()
169 if err then fail(err) end 169 if err then fail(err) end
170 if back == str then pass("lines match") 170 if back == str then pass("lines match")
@@ -457,7 +457,62 @@ function getstats_test()
457 print("ok") 457 print("ok")
458end 458end
459 459
460
460------------------------------------------------------------------------ 461------------------------------------------------------------------------
462function test_nonblocking(size)
463 reconnect()
464remote(string.format([[
465 data:send(string.rep("a", %d))
466 socket.sleep(0.5)
467 data:send(string.rep("b", %d))
468]], size, size))
469 local err = "timeout"
470 local part = ""
471 local str
472 data:settimeout(0)
473 while 1 do
474 str, err, part = data:receive(2*size - string.len(part), part)
475 if err ~= "timeout" then break end
476 end
477 assert(str == (string.rep("a", size) .. string.rep("b", size)))
478 reconnect()
479remote(string.format([[
480 str = data:receive(%d)
481 socket.sleep(0.5)
482 str = data:receive(%d, str)
483 str = data:receive("*l", str)
484 data:send(str)
485 data:send("\n")
486]], size, size))
487 data:settimeout(0)
488 local sofar = 1
489 while 1 do
490 _, err, part = data:send(str, sofar)
491 if err ~= "timeout" then break end
492 sofar = sofar + part
493 end
494 data:send("\n")
495 data:settimeout(-1)
496 local back = data:receive()
497 assert(back == str)
498 print("ok")
499end
500
501
502------------------------------------------------------------------------
503test("non-blocking transfer")
504test_nonblocking(1)
505test_nonblocking(17)
506test_nonblocking(200)
507test_nonblocking(4091)
508test_nonblocking(80199)
509test_nonblocking(8000000)
510test_nonblocking(80199)
511test_nonblocking(4091)
512test_nonblocking(200)
513test_nonblocking(17)
514test_nonblocking(1)
515
461test("method registration") 516test("method registration")
462test_methods(socket.tcp(), { 517test_methods(socket.tcp(), {
463 "accept", 518 "accept",
@@ -548,7 +603,6 @@ test_mixed(1)
548 603
549 604
550test("binary line") 605test("binary line")
551reconnect()
552test_rawline(1) 606test_rawline(1)
553test_rawline(17) 607test_rawline(17)
554test_rawline(200) 608test_rawline(200)
@@ -562,24 +616,6 @@ test_rawline(17)
562test_rawline(1) 616test_rawline(1)
563 617
564test("raw transfer") 618test("raw transfer")
565reconnect()
566test_raw(1)
567test_raw(17)
568test_raw(200)
569test_raw(4091)
570test_raw(80199)
571test_raw(8000000)
572test_raw(80199)
573test_raw(4091)
574test_raw(200)
575test_raw(17)
576test_raw(1)
577
578test("non-blocking transfer")
579reconnect()
580-- the value is not important, we only want
581-- to test non-blocking I/O anyways
582data:settimeout(200)
583test_raw(1) 619test_raw(1)
584test_raw(17) 620test_raw(17)
585test_raw(200) 621test_raw(200)
diff --git a/test/testsrvr.lua b/test/testsrvr.lua
index 969f95b..23e3850 100644
--- a/test/testsrvr.lua
+++ b/test/testsrvr.lua
@@ -1,29 +1,14 @@
1socket = require"socket" 1socket = require("socket");
2 2host = host or "localhost";
3host = host or "localhost" 3port = port or "8080";
4port = port or "8080" 4server = assert(socket.bind(host, port));
5 5ack = "\n";
6server, error = socket.bind(host, port)
7if not server then print("server: " .. tostring(error)) os.exit() end
8ack = "\n"
9while 1 do 6while 1 do
10 print("server: waiting for client connection..."); 7 print("server: waiting for client connection...");
11 control, error = server:accept() 8 control = assert(server:accept());
12 assert(control, error)
13 -- control:setoption("nodelay", true)
14 while 1 do 9 while 1 do
15 command, error = control:receive() 10 command = assert(control:receive());
16 if error then 11 assert(control:send(ack));
17 control:close() 12 (loadstring(command))();
18 print("server: closing connection...")
19 break
20 end
21 sent, error = control:send(ack)
22 if error then
23 control:close()
24 print("server: closing connection...")
25 break
26 end
27 (loadstring(command))()
28 end 13 end
29end 14end