In pre release mode!

This commit is contained in:
Diego Nehab 2005-11-20 08:56:19 +00:00
parent f20f4889bf
commit 5e09779c7f
13 changed files with 279 additions and 407 deletions

69
NEW
View File

@ -1,21 +1,54 @@
What's New What's New
The big change for the 2.0 (beta3) release was the adoption of the Lua There is no big change for the 2.0 (final) release. It is
5.1 package proposal. There were several bug fixes too (a beta is a basically a bug fix release. The main improvement is in the
beta, is a beta). non-blocking support.
* New compat-5.1 distribution: * New: sample module dispatch.lua implements a coroutine
- Instalation uses new directory structure; based dispatcher;
- Namespace hierarchy is in now back in use (ex. socket.url instead of url); * New: sample check-links.lua works both in blocking and
- All modules call require even for standard libraries; non-blocking mode using coroutines (using the new
* LTN12 avoids coroutines (so you can go wild on the C side); dispatcher);
* socket.select wasn't calling tm_markstart; * New: sample forward.lua implements a coroutine based
* Kludge on wsocket.c:sock_send for Windows timeout issue moved to forward server (using the new dispatcher);
buffer.c:sendraw so it's not a kludge anymore; * Improved: tcp:send(data, i, j) to return (i+sent-1). This
* socket.protect only catches errors thrown by socket.try; is great for non-blocking I/O, but might break some code;
* Fixed udp:sendto to call sock_sendto instead of sock_send; * Improved: HTTP, SMTP, and FTP functions to accept a new
* close wasn't returning 1! field create that overrides the function used to create
* socket.gettime returns time since Unix Epoch 1/1/1970 (UTC) socket objects;
* socket.sleep is robust to interrupts; * Improved: smtp.message now supports multipart/alternative
* http.PROXY wasn't working. (for the HTML messages we all love so much);
* fixed some of the examples * Fixed: smtp.send was hanging on errors returned by LTN12
sources;
* Fixed: url.absolute() to work when base_url is in parsed
form;
* Fixed: http.request() not to redirect when the location
header is empty (naughty servers...);
* Fixed: tcp{client}:shutdown() to check for class instead
of group;
* Fixed: The manual to stop using socket.try() in place of
assert(), since it can't;
* Improved: Got rid of package.loaded.base = _G kludge;
* Fixed: Parts of the manual referred to require("http")
instead of require("socket.http");
* Improved: Socket and MIME binaries are called 'core' each
inside their directory (ex. "socket/core.dll"). The 'l'
prefix was just a bad idea;
* Improved: Using bundles in Mac OS X, instead of dylibs;
* Fixed: luasocket.h to export luaopen_socket_core;
* Fixed: udp:setpeername() so you can "disconnect" an UDP
socket;
* Fixed: A weird bug in HTTP support that caused some
requests to fail (Florian Berger);
* Fixed: Bug in socket.select() that caused sockets with
descriptor 0 to be ignored (Renato Maia);
* Fixed: "Bug" that caused dns.toip() to crash under uLinux
(William Trenker);
* Fixed: "Bug" that caused gethostbyname to crash under VMS
(Renato Maia);
* Fixed: tcp:send("") to return 0 bytes sent (Alexander
Marinov);
* Improved: socket.DEBUG and socket.VERSION became
socket._DEBUGs and socket._VERSION for uniformity with other
libraries;
* Improved: socket.select now works on empty sets on Windows.

20
config
View File

@ -37,20 +37,20 @@ INSTALL_EXEC=cp
# Compiler and linker settings # Compiler and linker settings
# for Mac OS X # for Mac OS X
# #
#CC=gcc CC=gcc
#DEF=-DLUASOCKET_DEBUG -DUNIX_HAS_SUN_LEN DEF=-DLUASOCKET_DEBUG -DUNIX_HAS_SUN_LEN
#CFLAGS= $(LUAINC) -I$(COMPAT) $(DEF) -pedantic -Wall -O2 -fno-common CFLAGS= $(LUAINC) -I$(COMPAT) $(DEF) -pedantic -Wall -O2 -fno-common
#LDFLAGS=-bundle -undefined dynamic_lookup LDFLAGS=-bundle -undefined dynamic_lookup
#LD=export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc LD=export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc
#------ #------
# Compiler and linker settings # Compiler and linker settings
# for Linux # for Linux
CC=gcc #CC=gcc
DEF=-DLUASOCKET_DEBUG #DEF=-DLUASOCKET_DEBUG
CFLAGS= $(LUAINC) -I$(COMPAT) $(DEF) -pedantic -Wall -O2 -fpic #CFLAGS= $(LUAINC) -I$(COMPAT) $(DEF) -pedantic -Wall -O2 -fpic
LDFLAGS=-O -shared #LDFLAGS=-O -shared
LD=gcc #LD=gcc
#------ #------
# End of makefile configuration # End of makefile configuration

View File

@ -209,11 +209,16 @@ Here are a few examples with the simple interface:
<pre class=example> <pre class=example>
-- load the http module -- load the http module
http = require("socket.http") local io = require("io")
local http = require("socket.http")
local ltn12 = require("ltn12")
-- connect to server "www.tecgraf.puc-rio.br" and retrieves this manual -- connect to server "www.cs.princeton.edu" and retrieves this manual
-- file from "/luasocket/http.html" -- file from "~diego/professional/luasocket/http.html" and print it to stdout
b = http.request("http://www.tecgraf.puc-rio.br/luasocket/http.html") http.request{
url = "http://www.cs.princeton.edu/~diego/professional/luasocket/http.html",
sink = ltn12.sink.file(io.stdout)
}
-- connect to server "www.example.com" and tries to retrieve -- connect to server "www.example.com" and tries to retrieve
-- "/private/index.html". Fails because authentication is needed. -- "/private/index.html". Fails because authentication is needed.

View File

@ -165,6 +165,13 @@ support.
</p> </p>
<ul> <ul>
<li> New: sample module <tt>dispatch.lua</tt> implements a
coroutine based dispatcher;
<li> New: sample <tt>check-links.lua</tt> works
both in blocking and non-blocking mode using coroutines
(using the new dispatcher);
<li> New: sample <tt>forward.lua</tt> implements a coroutine
based forward server (using the new dispatcher);
<li> Improved: <tt>tcp:send(data, i, j)</tt> to return <tt>(i+sent-1)</tt>. This is great for non-blocking I/O, but might break some code; <li> Improved: <tt>tcp:send(data, i, j)</tt> to return <tt>(i+sent-1)</tt>. This is great for non-blocking I/O, but might break some code;
<li> Improved: HTTP, SMTP, and FTP functions to accept a new field <li> Improved: HTTP, SMTP, and FTP functions to accept a new field
<tt>create</tt> that overrides the function used to create socket objects; <tt>create</tt> that overrides the function used to create socket objects;

View File

@ -76,9 +76,9 @@ distribution directory structure:</p>
<pre class=example> <pre class=example>
&lt;SHARE&gt;/compat-5.1.lua &lt;SHARE&gt;/compat-5.1.lua
&lt;SHARE&gt;/ltn12.lua &lt;SHARE&gt;/ltn12.lua
&lt;SHARE&gt;/mime/init.lua (originally mime.lua) &lt;SHARE&gt;/mime/mime.lua
&lt;LIB&gt;/mime/core.dll &lt;LIB&gt;/mime/core.dll
&lt;SHARE&gt;/socket/init.lua (originally socket.lua) &lt;SHARE&gt;/socket/socket.lua
&lt;LIB&gt;/socket/core.dll &lt;LIB&gt;/socket/core.dll
&lt;SHARE&gt;/socket/http.lua &lt;SHARE&gt;/socket/http.lua
&lt;SHARE&gt;/socket/tp.lua &lt;SHARE&gt;/socket/tp.lua
@ -88,9 +88,7 @@ distribution directory structure:</p>
</pre> </pre>
<p> Naturally, on Unix systems, <tt>core.dll</tt> <p> Naturally, on Unix systems, <tt>core.dll</tt>
would be replaced by <tt>core.so</tt>. Notice that in the instalation, would be replaced by <tt>core.so</tt>.
<tt>socket.lua</tt> becomes <tt>socket/init.lua</tt>, and the same happens
with <tt>mime.lua</tt>, which becomes <tt>mime/init.lua</tt>.
</p> </p>
<p> In order for the interpreter to find all LuaSocket components, three <p> In order for the interpreter to find all LuaSocket components, three

View File

@ -446,6 +446,7 @@ The method returns 1 in case of success and <tt><b>nil</b></tt> otherwise.
<!-- settimeout +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> <!-- settimeout +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<p class=name id=settimeout> <p class=name id=settimeout>
master:<b>settimeout(</b>value [, mode]<b>)</b><br>
client:<b>settimeout(</b>value [, mode]<b>)</b><br> client:<b>settimeout(</b>value [, mode]<b>)</b><br>
server:<b>settimeout(</b>value [, mode]<b>)</b> server:<b>settimeout(</b>value [, mode]<b>)</b>
</p> </p>

View File

@ -1,48 +1,89 @@
This directory contains code that is more useful than the examples. This code This directory contains code that is more useful than the
*is* supported. samples. This code *is* supported.
tftp.lua -- Trivial FTP client tftp.lua -- Trivial FTP client
This module implements file retrieval by the TFTP protocol. Its main use This module implements file retrieval by the TFTP protocol.
was to test the UDP code, but since someone found it usefull, I turned it Its main use was to test the UDP code, but since someone
into a module that is almost official (no uploads, yet). found it usefull, I turned it into a module that is almost
official (no uploads, yet).
dict.lua -- Dict client dict.lua -- Dict client
The dict.lua module started with a cool simple client for the DICT The dict.lua module started with a cool simple client
protocol, written by Luiz Henrique Figueiredo. This new version has been for the DICT protocol, written by Luiz Henrique Figueiredo.
converted into a library, similar to the HTTP and FTP libraries, that can This new version has been converted into a library, similar
be used from within any luasocket application. Take a look on the source to the HTTP and FTP libraries, that can be used from within
code and you will be able to figure out how to use it. any luasocket application. Take a look on the source code
and you will be able to figure out how to use it.
lp.lua -- LPD client lp.lua -- LPD client library
The lp.lua module implements the client part of the Line Printer Daemon The lp.lua module implements the client part of the Line
protocol, used to print files on Unix machines. It is courtesy of David Printer Daemon protocol, used to print files on Unix
Burgess and I heard he would be the one supporting it, even after I messed machines. It is courtesy of David Burgess! See the source
with it. See the source code and the lpr.lua in the examples directory. code and the lpr.lua in the examples directory.
b64.lua
qp.lua
eol.lua
These are tiny programs that perform Base64,
Quoted-Printable and end-of-line marker conversions.
get.lua -- file retriever get.lua -- file retriever
This little program is a client that uses the FTP and HTTP code to This little program is a client that uses the FTP and
implement a command line file graber. Just run HTTP code to implement a command line file graber. Just
run
lua get.lua <remote-file> [<local-file>] lua get.lua <remote-file> [<local-file>]
to download a remote file (either ftp:// or http://) to the specified to download a remote file (either ftp:// or http://) to
local file. The program also prints the download throughput, elapsed the specified local file. The program also prints the
time, bytes already downloaded etc during download. download throughput, elapsed time, bytes already downloaded
etc during download.
check-memory.lua -- checks memory consumption
This is just to see how much memory each module uses.
dispatch.lua -- coroutine based dispatcher
This is a first try at a coroutine based non-blocking
dispatcher for LuaSocket. Take a look at 'check-links.lua'
and at 'forward.lua' to see how to use it.
check-links.lua -- HTML link checker program check-links.lua -- HTML link checker program
This little program scans a HTML file and checks for broken links. It is This little program scans a HTML file and checks for broken
similar to check-links.pl by Jamie Zawinski, but uses all facilities of links. It is similar to check-links.pl by Jamie Zawinski,
the LuaSocket library and the Lua language. It has not been thoroughly but uses all facilities of the LuaSocket library and the Lua
tested, but it should work. Just run language. It has not been thoroughly tested, but it should
work. Just run
lua check-links.lua {<url>} > output lua check-links.lua [-n] {<url>} > output
and open the result to see a list of broken links. and open the result to see a list of broken links. You can
also use the '-n' switch to run the same program in
non-blocking mode to see how much faster things can get.
forward.lua -- coroutine based forward server
This is a forward server that can accept several connections
and transfers simultaneously using non-blocking I/O and the
coroutine-based dispatcher. You can run, for example
lua forward.lua 8080:proxy.com:3128
to redirect all local conections to port 8080 to the host
'proxy.com' at port 3128.
unix.c and unix.h
This is an implementation of Unix local domain sockets and
demonstrates how to extend LuaSocket with a new type of
transport. It has been tested on Linux and on Mac OS X.
Good luck, Good luck,
Diego. Diego.

View File

@ -7,7 +7,7 @@ function load(s)
print(s .. ":\t " .. (b-a) .. "k") print(s .. ":\t " .. (b-a) .. "k")
end end
load("url") load("socket.url")
load("ltn12") load("ltn12")
load("socket") load("socket")
load("mime") load("mime")

View File

@ -4,125 +4,128 @@
DIST = luasocket-2.0 DIST = luasocket-2.0
COMPAT = compat-5.1r4 COMPAT = src/compat-5.1r4
LUA = \
ftp.lua \
http.lua \
ltn12.lua \
mime.lua \
smtp.lua \
socket.lua \
tp.lua \
url.lua
TESTS = \ TEST = \
testclnt.lua \ test/testclnt.lua \
testsrvr.lua \ test/testsrvr.lua \
testsupport.lua test/testsupport.lua
EXAMPLES = \ SAMPLES = \
check-memory.lua \ samples/README \
b64.lua \ samples/cddb.lua \
cddb.lua \ samples/daytimeclnt.lua \
daytimeclnt.lua \ samples/echoclnt.lua \
echoclnt.lua \ samples/echosrvr.lua \
echosrvr.lua \ samples/listener.lua \
eol.lua \ samples/lpr.lua \
listener.lua \ samples/talker.lua \
qp.lua \ samples/tinyirc.lua
lpr.lua \
talker.lua \
tinyirc.lua
ETC = \ ETC = \
check-links.lua \ etc/README \
check-links-nb.lua \ etc/b64.lua \
dict.lua \ etc/check-links.lua \
get.lua \ etc/check-memory.lua \
unix.c \ etc/dict.lua \
unix.h \ etc/dispatch.lua \
lp.lua \ etc/eol.lua \
tftp.lua etc/forward.lua \
etc/get.lua \
etc/links \
etc/lp.lua \
etc/qp.lua \
etc/tftp.lua
CORE = \ SRC = \
auxiliar.c \ src/auxiliar.c \
auxiliar.h \ src/auxiliar.h \
buffer.c \ src/buffer.c \
buffer.h \ src/buffer.h \
except.c \ src/except.c \
except.h \ src/except.h \
inet.c \ src/inet.c \
inet.h \ src/inet.h \
io.c \ src/io.c \
io.h \ src/io.h \
luasocket.c \ src/luasocket.c \
luasocket.h \ src/luasocket.h \
mime.c \ src/mime.c \
mime.h \ src/mime.h \
options.c \ src/options.c \
options.h \ src/options.h \
select.c \ src/select.c \
select.h \ src/select.h \
socket.h \ src/socket.h \
tcp.c \ src/tcp.c \
tcp.h \ src/tcp.h \
timeout.c \ src/timeout.c \
timeout.h \ src/timeout.h \
udp.c \ src/udp.c \
udp.h \ src/udp.h \
usocket.c \ src/unix.c \
usocket.h \ src/unix.h \
wsocket.c \ src/usocket.c \
wsocket.h src/usocket.h \
src/wsocket.c \
src/wsocket.h \
src/ftp.lua \
src/http.lua \
src/ltn12.lua \
src/mime.lua \
src/smtp.lua \
src/socket.lua \
src/tp.lua \
src/url.lua
MAKE = \ MAKE = \
makefile \ makefile \
config \ config \
luasocket.sln \ luasocket.sln \
luasocket.vcproj \ socket.vcproj \
mime.vcproj mime.vcproj
MANUAL = \ DOC = \
manual/dns.html \ doc/dns.html \
manual/ftp.html \ doc/ftp.html \
manual/home.html \ doc/home.html \
manual/http.html \ doc/http.html \
manual/introduction.html \ doc/installation.html \
manual/ltn12.html \ doc/introduction.html \
manual/luasocket.png \ doc/ltn12.html \
manual/mime.html \ doc/luasocket.png \
manual/installation.html \ doc/mime.html \
manual/reference.css \ doc/reference.css \
manual/reference.html \ doc/reference.html \
manual/smtp.html \ doc/smtp.html \
manual/socket.html \ doc/socket.html \
manual/tcp.html \ doc/tcp.html \
manual/udp.html \ doc/udp.html \
manual/url.html doc/url.html
dist: dist:
mkdir -p $(DIST)/examples mkdir -p $(DIST)
mkdir -p $(DIST)/tests
mkdir -p $(DIST)/etc
mkdir -p $(DIST)/lua
mkdir -p $(DIST)/manual
cp -vfr $(COMPAT) $(DIST)
cp -vf $(CORE) $(DIST)
cp -vf README $(DIST)
cp -vf NEW $(DIST) cp -vf NEW $(DIST)
cp -vf LICENSE $(DIST) cp -vf LICENSE $(DIST)
cp -vf $(MAKE) $(DIST) cp -vf $(MAKE) $(DIST)
cp -vf make.README $(DIST)/INSTALL
cp -vf $(LUA) $(DIST)/lua mkdir -p $(DIST)/etc
cp -vf lua.README $(DIST)/lua/README
cp -vf $(EXAMPLES) $(DIST)/examples
cp -vf examples.README $(DIST)/examples/README
cp -vf $(TESTS) $(DIST)/tests
cp -vf tests.README $(DIST)/tests/README
cp -vf $(ETC) $(DIST)/etc cp -vf $(ETC) $(DIST)/etc
cp -vf etc.README $(DIST)/etc/README
cp -vf $(MANUAL) $(DIST)/manual mkdir -p $(DIST)/src
cp -vf $(SRC) $(DIST)/src
cp -vfr $(COMPAT) $(DIST)/src
mkdir -p $(DIST)/doc
cp -vf $(DOC) $(DIST)/doc
mkdir -p $(DIST)/samples
cp -vf $(SAMPLES) $(DIST)/samples
mkdir -p $(DIST)/test
cp -vf $(TEST) $(DIST)/test
tar -zcvf $(DIST).tar.gz $(DIST) tar -zcvf $(DIST).tar.gz $(DIST)
zip -r $(DIST).zip $(DIST) zip -r $(DIST).zip $(DIST)

View File

@ -1,59 +1,50 @@
This directory contains some sample programs using LuaSocket. This code This directory contains some sample programs using
is not supported. LuaSocket. This code is not supported.
listener.lua -- socket to stdout listener.lua -- socket to stdout
talker.lua -- stdin to socket talker.lua -- stdin to socket
listener.lua and talker.lua are about the simplest applications you can listener.lua and talker.lua are about the simplest
write using LuaSocket. Run applications you can write using LuaSocket. Run
'lua listener.lua' and 'lua talker.lua' 'lua listener.lua' and 'lua talker.lua'
on different terminals. Whatever you type on talk.lua will be on different terminals. Whatever you type on talk.lua will
printed by listen.lua. be printed by listen.lua.
b64.lua
qp.lua
eol.lua
These are tiny programs that perform Base64, Quoted-Printable and
end-of-line marker conversions.
lpr.lua -- lpr client lpr.lua -- lpr client
This is a cool program written by David Burgess to print files using the This is a cool program written by David Burgess to print
Line Printer Daemon protocol, widely used in Unix machines. It uses the files using the Line Printer Daemon protocol, widely used in
lp.lua implementation, in the etc directory. Just run Unix machines. It uses the lp.lua implementation, in the
'lua lpr.lua <filename> queue=<printername>' and the file will print! etc directory. Just run 'lua lpr.lua <filename>
queue=<printername>' and the file will print!
cddb.lua -- CDDB client cddb.lua -- CDDB client
This is the first try on a simple CDDB client. Not really useful, but one This is the first try on a simple CDDB client. Not really
day it might become a module. useful, but one day it might become a module.
daytimeclnt.lua -- day time client daytimeclnt.lua -- day time client
Just run the program to retrieve the hour and date in readable form from Just run the program to retrieve the hour and date in
any server running an UDP daytime daemon. readable form from any server running an UDP daytime daemon.
echoclnt.lua -- UDP echo client echoclnt.lua -- UDP echo client
echosrvr.lua -- UDP echo server echosrvr.lua -- UDP echo server
These are a UDP echo client/server pair. They work with other client and These are a UDP echo client/server pair. They work with
servers as well. other client and servers as well.
tinyirc.lua -- irc like broadcast server tinyirc.lua -- irc like broadcast server
This is a simple server that waits simultaneously on two server sockets This is a simple server that waits simultaneously on two
for telnet connections. Everything it receives from the telnet clients server sockets for telnet connections. Everything it
is broadcasted to every other connected client. It tests the select receives from the telnet clients is broadcasted to every
function and shows how to create a simple server whith LuaSocket. Just other connected client. It tests the select function and
run tinyirc.lua and then open as many telnet connections as you want shows how to create a simple server whith LuaSocket. Just
to ports 8080 and 8081. run tinyirc.lua and then open as many telnet connections
as you want to ports 8080 and 8081.
check-memory.lua -- checks memory consumption
This is just to see how much memory each module uses.
Good luck, Good luck,
Diego. Diego.

View File

@ -1,207 +0,0 @@
-- load our favourite library
local socket = require"socket"
-- creates a new set data structure
function newset()
local reverse = {}
local set = {}
return setmetatable(set, {__index = {
insert = function(set, value)
if not reverse[value] then
table.insert(set, value)
reverse[value] = table.getn(set)
end
end,
remove = function(set, value)
local index = reverse[value]
if index then
reverse[value] = nil
local top = table.remove(set)
if top ~= value then
reverse[top] = index
set[index] = top
end
end
end
}})
end
-- timeout before an inactive thread is kicked
local TIMEOUT = 10
-- set of connections waiting to receive data
local receiving = newset(1)
-- set of sockets waiting to send data
local sending = newset()
-- context for connections and servers
local context = {}
function wait(who, what)
if what == "input" then receiving:insert(who)
else sending:insert(who) end
context[who].last = socket.gettime()
coroutine.yield()
end
-- initializes the forward server
function init()
if table.getn(arg) < 1 then
print("Usage")
print(" lua forward.lua <iport:ohost:oport> ...")
os.exit(1)
end
-- for each tunnel, start a new server socket
for i, v in ipairs(arg) do
-- capture forwarding parameters
local iport, ohost, oport =
socket.skip(2, string.find(v, "([^:]+):([^:]+):([^:]+)"))
assert(iport, "invalid arguments")
-- create our server socket
local server = assert(socket.bind("*", iport))
server:settimeout(0) -- we don't want to be killed by bad luck
-- make sure server is tested for readability
receiving:insert(server)
-- add server context
context[server] = {
thread = coroutine.create(accept),
ohost = ohost,
oport = oport
}
end
end
-- starts a connection in a non-blocking way
function connect(who, host, port)
who:settimeout(0)
local ret, err = who:connect(host, port)
if not ret and err == "timeout" then
wait(who, "output")
ret, err = who:connect(host, port)
if not ret and err ~= "already connected" then
kick(context[who].peer)
kick(who)
return
end
end
return forward(who)
end
-- gets rid of a client
function kick(who)
if who then
sending:remove(who)
receiving:remove(who)
who:close()
context[who] = nil
end
end
-- loops accepting connections and creating new threads to deal with them
function accept(server)
while true do
-- accept a new connection and start a new coroutine to deal with it
local client = server:accept()
if client then
-- create contexts for client and peer.
local peer, err = socket.tcp()
if peer then
context[client] = {
last = socket.gettime(),
-- client goes straight to forwarding loop
thread = coroutine.create(forward),
peer = peer,
}
context[peer] = {
last = socket.gettime(),
peer = client,
-- peer first tries to connect to forwarding address
thread = coroutine.create(connect),
last = socket.gettime()
}
-- resume peer and client so they can do their thing
local ohost = context[server].ohost
local oport = context[server].oport
coroutine.resume(context[peer].thread, peer, ohost, oport)
coroutine.resume(context[client].thread, client)
else
print(err)
client:close()
end
end
-- tell scheduler we are done for now
wait(server, "input")
end
end
-- forwards all data arriving to the appropriate peer
function forward(who)
who:settimeout(0)
while true do
-- wait until we have something to read
wait(who, "input")
-- try to read as much as possible
local data, rec_err, partial = who:receive("*a")
-- if we had an error other than timeout, abort
if rec_err and rec_err ~= "timeout" then return kick(who) end
-- if we got a timeout, we probably have partial results to send
data = data or partial
-- forward what we got right away
local peer = context[who].peer
while true do
-- tell scheduler we need to wait until we can send something
wait(who, "output")
local ret, snd_err
local start = 0
ret, snd_err, start = peer:send(data, start+1)
if ret then break
elseif snd_err ~= "timeout" then return kick(who) end
end
-- if we are done receiving, we are done
if not rec_err then
kick(who)
kick(peer)
break
end
end
end
-- loop waiting until something happens, restarting the thread to deal with
-- what happened, and routing it to wait until something else happens
function go()
while true do
-- check which sockets are interesting and act on them
readable, writable = socket.select(receiving, sending)
-- for all readable connections, resume its thread
for _, who in ipairs(readable) do
if context[who] then
receiving:remove(who)
coroutine.resume(context[who].thread, who)
end
end
-- for all writable connections, do the same
for _, who in ipairs(writable) do
if context[who] then
sending:remove(who)
coroutine.resume(context[who].thread, who)
end
end
-- put all inactive threads in death row
local now = socket.gettime()
local deathrow
for who, data in pairs(context) do
if data.peer then
if now - data.last > TIMEOUT then
-- only create table if at least one is doomed
deathrow = deathrow or {}
deathrow[who] = true
end
end
end
-- finally kick everyone in deathrow
if deathrow then
for who in pairs(deathrow) do kick(who) end
end
end
end
init()
go()

View File

@ -1,7 +1,7 @@
local lp = require("socket.lp") local lp = require("socket.lp")
local function usage() local function usage()
print('\nUsage: lua lptest.lua [filename] [keyword=val...]\n') print('\nUsage: lua lpr.lua [filename] [keyword=val...]\n')
print('Valid keywords are :') print('Valid keywords are :')
print( print(
' host=remote host or IP address (default "localhost")\n' .. ' host=remote host or IP address (default "localhost")\n' ..

View File

@ -22,8 +22,8 @@ http.TIMEOUT = 10
local t = socket.gettime() local t = socket.gettime()
host = host or "dell-diego" -- "diego.student.princeton.edu" host = host or "diego.student.princeton.edu"
proxy = proxy or "http://dell-diego:3128" proxy = proxy or "http://localhost:3128"
prefix = prefix or "/luasocket-test" prefix = prefix or "/luasocket-test"
cgiprefix = cgiprefix or "/luasocket-test-cgi" cgiprefix = cgiprefix or "/luasocket-test-cgi"
index_file = "index.html" index_file = "index.html"