Few tweaks in installation, some missing files, etc.

This commit is contained in:
Diego Nehab 2005-11-22 08:33:29 +00:00
parent a2b780bf7a
commit d55a5826e8
26 changed files with 232 additions and 238 deletions

2
config
View File

@ -27,7 +27,7 @@ COMPAT=compat-5.1r4
# Top of your Lua installation # Top of your Lua installation
# Relative paths will be inside the src tree # Relative paths will be inside the src tree
# #
INSTALL_TOP_LUA=share INSTALL_TOP_SHARE=share
INSTALL_TOP_LIB=lib INSTALL_TOP_LIB=lib
INSTALL_DATA=cp INSTALL_DATA=cp

View File

@ -69,22 +69,22 @@ independent files. Let's call these directories <tt>&lt;LIB&gt;</tt>
and <tt>&lt;SHARE&gt;</tt>, respectively. and <tt>&lt;SHARE&gt;</tt>, respectively.
For instance, in my laptop, I use '<tt>/usr/local/lib/lua/5.0</tt>' for For instance, in my laptop, I use '<tt>/usr/local/lib/lua/5.0</tt>' for
<tt>&lt;LIB&gt;</tt> and '<tt>/usr/local/share/lua/5.0</tt>' for <tt>&lt;LIB&gt;</tt> and '<tt>/usr/local/share/lua/5.0</tt>' for
<tt>&lt;SHARE&gt;</tt>. On Windows, only one directory is used, say <tt>&lt;SHARE&gt;</tt>. On Windows, sometimes only one directory is used, say
'<tt>c:\program files\lua\5.0</tt>'. Here is the standard LuaSocket '<tt>c:\program files\lua\5.0</tt>'. Here is the standard LuaSocket
distribution directory structure:</p> 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/mime.lua &lt;SHARE&gt;/socket.lua
&lt;LIB&gt;/mime/core.dll
&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
&lt;SHARE&gt;/socket/ftp.lua &lt;SHARE&gt;/socket/ftp.lua
&lt;SHARE&gt;/socket/smtp.lua &lt;SHARE&gt;/socket/smtp.lua
&lt;SHARE&gt;/socket/url.lua &lt;SHARE&gt;/socket/url.lua
&lt;SHARE&gt;/mime.lua
&lt;LIB&gt;/mime/core.dll
</pre> </pre>
<p> Naturally, on Unix systems, <tt>core.dll</tt> <p> Naturally, on Unix systems, <tt>core.dll</tt>

View File

@ -210,13 +210,6 @@ Use the <a href=tcp.html#settimeout><tt>settimeout</tt></a>
method or <tt>accept</tt> might block forever. method or <tt>accept</tt> might block forever.
</p> </p>
<p class=note>
Interesting note: as mentioned in some Unix manuals, calling select with both
sets empty and a non-null timeout is a fairly portable way to sleep with
sub-second precision (<b>except it doesn't work on Windows</b>).
</p>
<!-- sink ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> <!-- sink ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<p class=name id=sink> <p class=name id=sink>

View File

@ -37,7 +37,7 @@ function getstatus(link)
handler:start(function() handler:start(function()
local r, c, h, s = http.request{ local r, c, h, s = http.request{
method = "HEAD", method = "HEAD",
url = link, url = link,
create = handler.tcp create = handler.tcp
} }
if r and c == 200 then io.write('\t', link, '\n') if r and c == 200 then io.write('\t', link, '\n')
@ -107,6 +107,6 @@ for _, address in ipairs(arg) do
checklinks(url.absolute("file:", address)) checklinks(url.absolute("file:", address))
end end
while nthreads > 0 do while nthreads > 0 do
handler:step() handler:step()
end end

View File

@ -17,7 +17,7 @@ local tp = require("socket.tp")
module("socket.dict") module("socket.dict")
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- Globals -- Globals
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
HOST = "dict.org" HOST = "dict.org"
PORT = 2628 PORT = 2628
@ -39,7 +39,7 @@ end
function metat.__index:check(ok) function metat.__index:check(ok)
local code, status = socket.try(self.tp:check(ok)) local code, status = socket.try(self.tp:check(ok))
return code, return code,
base.tonumber(socket.skip(2, string.find(status, "^%d%d%d (%d*)"))) base.tonumber(socket.skip(2, string.find(status, "^%d%d%d (%d*)")))
end end
@ -101,7 +101,7 @@ local default = {
} }
local function there(f) local function there(f)
if f == "" then return nil if f == "" then return nil
else return f end else return f end
end end
@ -116,7 +116,7 @@ local function parse(u)
arg = string.gsub(arg, "^:([^:]+)", function(f) t.word = f end) arg = string.gsub(arg, "^:([^:]+)", function(f) t.word = f end)
socket.try(t.word, "need at least <word> in URL") socket.try(t.word, "need at least <word> in URL")
arg = string.gsub(arg, "^:([^:]*)", function(f) t.database = there(f) end) arg = string.gsub(arg, "^:([^:]*)", function(f) t.database = there(f) end)
if cmd == "m" then if cmd == "m" then
arg = string.gsub(arg, "^:([^:]*)", function(f) t.strat = there(f) end) arg = string.gsub(arg, "^:([^:]*)", function(f) t.strat = there(f) end)
end end
string.gsub(arg, ":([^:]*)$", function(f) t.n = base.tonumber(f) end) string.gsub(arg, ":([^:]*)$", function(f) t.n = base.tonumber(f) end)
@ -130,7 +130,7 @@ local function tget(gett)
local def = con:define(gett.database, gett.word) local def = con:define(gett.database, gett.word)
con:quit() con:quit()
con:close() con:close()
if gett.n then return def[gett.n] if gett.n then return def[gett.n]
else return def end else return def end
elseif gett.command == "m" then elseif gett.command == "m" then
local mat = con:match(gett.database, gett.strat, gett.word) local mat = con:match(gett.database, gett.strat, gett.word)

View File

@ -14,7 +14,7 @@ module("dispatch")
TIMEOUT = 60 TIMEOUT = 60
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- We implement 3 types of dispatchers: -- We implement 3 types of dispatchers:
-- sequential -- sequential
-- coroutine -- coroutine
-- threaded -- threaded
@ -34,7 +34,7 @@ end
-- sequential handler simply calls the functions and doesn't wrap I/O -- sequential handler simply calls the functions and doesn't wrap I/O
function handlert.sequential() function handlert.sequential()
return { return {
tcp = socket.tcp, tcp = socket.tcp,
start = seqstart start = seqstart
} }
@ -55,7 +55,7 @@ function socket.protect(f)
if not status then if not status then
if type(results[1]) == 'table' then if type(results[1]) == 'table' then
return nil, results[1][1] return nil, results[1][1]
else error(results[1]) end else error(results[1]) end
end end
if coroutine.status(co) == "suspended" then if coroutine.status(co) == "suspended" then
arg = {coroutine.yield(unpack(results))} arg = {coroutine.yield(unpack(results))}
@ -84,17 +84,17 @@ local function newset()
if index then if index then
reverse[value] = nil reverse[value] = nil
local top = table.remove(set) local top = table.remove(set)
if top ~= value then if top ~= value then
reverse[top] = index reverse[top] = index
set[index] = top set[index] = top
end end
end end
end end
}}) }})
end end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- socket.tcp() wrapper for the coroutine dispatcher -- socket.tcp() wrapper for the coroutine dispatcher
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
local function cowrap(dispatcher, tcp, error) local function cowrap(dispatcher, tcp, error)
if not tcp then return nil, error end if not tcp then return nil, error end
@ -102,7 +102,7 @@ local function cowrap(dispatcher, tcp, error)
tcp:settimeout(0) tcp:settimeout(0)
-- metatable for wrap produces new methods on demand for those that we -- metatable for wrap produces new methods on demand for those that we
-- don't override explicitly. -- don't override explicitly.
local metat = { __index = function(table, key) local metat = { __index = function(table, key)
table[key] = function(...) table[key] = function(...)
arg[1] = tcp arg[1] = tcp
return tcp[key](unpack(arg)) return tcp[key](unpack(arg))
@ -112,7 +112,7 @@ local function cowrap(dispatcher, tcp, error)
-- does our user want to do his own non-blocking I/O? -- does our user want to do his own non-blocking I/O?
local zero = false local zero = false
-- create a wrap object that will behave just like a real socket object -- create a wrap object that will behave just like a real socket object
local wrap = { } local wrap = { }
-- we ignore settimeout to preserve our 0 timeout, but record whether -- we ignore settimeout to preserve our 0 timeout, but record whether
-- the user wants to do his own non-blocking I/O -- the user wants to do his own non-blocking I/O
function wrap:settimeout(value, mode) function wrap:settimeout(value, mode)
@ -121,19 +121,19 @@ local function cowrap(dispatcher, tcp, error)
return 1 return 1
end end
-- send in non-blocking mode and yield on timeout -- send in non-blocking mode and yield on timeout
function wrap:send(data, first, last) function wrap:send(data, first, last)
first = (first or 1) - 1 first = (first or 1) - 1
local result, error local result, error
while true do while true do
-- return control to dispatcher and tell it we want to send -- return control to dispatcher and tell it we want to send
-- if upon return the dispatcher tells us we timed out, -- if upon return the dispatcher tells us we timed out,
-- return an error to whoever called us -- return an error to whoever called us
if coroutine.yield(dispatcher.sending, tcp) == "timeout" then if coroutine.yield(dispatcher.sending, tcp) == "timeout" then
return nil, "timeout" return nil, "timeout"
end end
-- try sending -- try sending
result, error, first = tcp:send(data, first+1, last) result, error, first = tcp:send(data, first+1, last)
-- if we are done, or there was an unexpected error, -- if we are done, or there was an unexpected error,
-- break away from loop -- break away from loop
if error ~= "timeout" then return result, error, first end if error ~= "timeout" then return result, error, first end
end end
@ -143,20 +143,20 @@ local function cowrap(dispatcher, tcp, error)
function wrap:receive(pattern, partial) function wrap:receive(pattern, partial)
local error = "timeout" local error = "timeout"
local value local value
while true do while true do
-- return control to dispatcher and tell it we want to receive -- return control to dispatcher and tell it we want to receive
-- if upon return the dispatcher tells us we timed out, -- if upon return the dispatcher tells us we timed out,
-- return an error to whoever called us -- return an error to whoever called us
if coroutine.yield(dispatcher.receiving, tcp) == "timeout" then if coroutine.yield(dispatcher.receiving, tcp) == "timeout" then
return nil, "timeout" return nil, "timeout"
end end
-- try receiving -- try receiving
value, error, partial = tcp:receive(pattern, partial) value, error, partial = tcp:receive(pattern, partial)
-- if we are done, or there was an unexpected error, -- if we are done, or there was an unexpected error,
-- break away from loop. also, if the user requested -- break away from loop. also, if the user requested
-- zero timeout, return all we got -- zero timeout, return all we got
if (error ~= "timeout") or zero then if (error ~= "timeout") or zero then
return value, error, partial return value, error, partial
end end
end end
end end
@ -168,8 +168,8 @@ local function cowrap(dispatcher, tcp, error)
-- connection succeeds. -- connection succeeds.
-- if upon return the dispatcher tells us we have a -- if upon return the dispatcher tells us we have a
-- timeout, just abort -- timeout, just abort
if coroutine.yield(dispatcher.sending, tcp) == "timeout" then if coroutine.yield(dispatcher.sending, tcp) == "timeout" then
return nil, "timeout" return nil, "timeout"
end end
-- when we come back, check if connection was successful -- when we come back, check if connection was successful
result, error = tcp:connect(host, port) result, error = tcp:connect(host, port)
@ -179,27 +179,27 @@ local function cowrap(dispatcher, tcp, error)
end end
-- accept in non-blocking mode and yield on timeout -- accept in non-blocking mode and yield on timeout
function wrap:accept() function wrap:accept()
while 1 do while 1 do
-- return control to dispatcher. we will be readable when a -- return control to dispatcher. we will be readable when a
-- connection arrives. -- connection arrives.
-- if upon return the dispatcher tells us we have a -- if upon return the dispatcher tells us we have a
-- timeout, just abort -- timeout, just abort
if coroutine.yield(dispatcher.receiving, tcp) == "timeout" then if coroutine.yield(dispatcher.receiving, tcp) == "timeout" then
return nil, "timeout" return nil, "timeout"
end end
local client, error = tcp:accept() local client, error = tcp:accept()
if error ~= "timeout" then if error ~= "timeout" then
return cowrap(dispatcher, client, error) return cowrap(dispatcher, client, error)
end end
end end
end end
-- remove cortn from context -- remove cortn from context
function wrap:close() function wrap:close()
dispatcher.stamp[tcp] = nil dispatcher.stamp[tcp] = nil
dispatcher.sending.set:remove(tcp) dispatcher.sending.set:remove(tcp)
dispatcher.sending.cortn[tcp] = nil dispatcher.sending.cortn[tcp] = nil
dispatcher.receiving.set:remove(tcp) dispatcher.receiving.set:remove(tcp)
dispatcher.receiving.cortn[tcp] = nil dispatcher.receiving.cortn[tcp] = nil
return tcp:close() return tcp:close()
end end
return setmetatable(wrap, metat) return setmetatable(wrap, metat)
@ -207,12 +207,12 @@ end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- Our coroutine dispatcher -- Our coroutine dispatcher
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
local cometat = { __index = {} } local cometat = { __index = {} }
function schedule(cortn, status, operation, tcp) function schedule(cortn, status, operation, tcp)
if status then if status then
if cortn and operation then if cortn and operation then
operation.set:insert(tcp) operation.set:insert(tcp)
operation.cortn[tcp] = cortn operation.cortn[tcp] = cortn
@ -233,7 +233,7 @@ function wakeup(operation, tcp)
kick(operation, tcp) kick(operation, tcp)
return cortn, coroutine.resume(cortn) return cortn, coroutine.resume(cortn)
-- othrewise, just get scheduler not to do anything -- othrewise, just get scheduler not to do anything
else else
return nil, true return nil, true
end end
end end
@ -249,7 +249,7 @@ end
-- step through all active cortns -- step through all active cortns
function cometat.__index:step() function cometat.__index:step()
-- check which sockets are interesting and act on them -- check which sockets are interesting and act on them
local readable, writable = socket.select(self.receiving.set, local readable, writable = socket.select(self.receiving.set,
self.sending.set, 1) self.sending.set, 1)
-- for all readable connections, resume their cortns and reschedule -- for all readable connections, resume their cortns and reschedule
-- when they yield back to us -- when they yield back to us
@ -260,7 +260,7 @@ function cometat.__index:step()
for _, tcp in ipairs(writable) do for _, tcp in ipairs(writable) do
schedule(wakeup(self.sending, tcp)) schedule(wakeup(self.sending, tcp))
end end
-- politely ask replacement I/O functions in idle cortns to -- politely ask replacement I/O functions in idle cortns to
-- return reporting a timeout -- return reporting a timeout
local now = socket.gettime() local now = socket.gettime()
for tcp, stamp in pairs(self.stamp) do for tcp, stamp in pairs(self.stamp) do
@ -271,25 +271,25 @@ function cometat.__index:step()
end end
end end
function cometat.__index:start(func) function cometat.__index:start(func)
local cortn = coroutine.create(func) local cortn = coroutine.create(func)
schedule(cortn, coroutine.resume(cortn)) schedule(cortn, coroutine.resume(cortn))
end end
function handlert.coroutine() function handlert.coroutine()
local stamp = {} local stamp = {}
local dispatcher = { local dispatcher = {
stamp = stamp, stamp = stamp,
sending = { sending = {
name = "sending", name = "sending",
set = newset(), set = newset(),
cortn = {}, cortn = {},
stamp = stamp stamp = stamp
}, },
receiving = { receiving = {
name = "receiving", name = "receiving",
set = newset(), set = newset(),
cortn = {}, cortn = {},
stamp = stamp stamp = stamp
}, },
} }

View File

@ -1,5 +1,5 @@
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- Little program to adjust end of line markers. -- Little program to adjust end of line markers.
-- LuaSocket sample files -- LuaSocket sample files
-- Author: Diego Nehab -- Author: Diego Nehab
-- RCS ID: $Id$ -- RCS ID: $Id$

View File

@ -17,10 +17,10 @@ local function move(foo, bar)
live = data or error == "timeout" live = data or error == "timeout"
data = data or partial data = data or partial
local result, error = bar:send(data) local result, error = bar:send(data)
if not live or not result then if not live or not result then
foo:close() foo:close()
bar:close() bar:close()
break break
end end
end end
end end
@ -51,7 +51,7 @@ for i, v in ipairs(arg) do
handler:start(function() handler:start(function()
move(client, peer) move(client, peer)
end) end)
-- afte starting new handler, enter in loop sending data from -- afte starting new handler, enter in loop sending data from
-- peer to client -- peer to client
move(peer, client) move(peer, client)
end) end)

View File

@ -53,10 +53,10 @@ local elapsed_s = "%s received, %s/s throughput, %s elapsed "
function gauge(got, delta, size) function gauge(got, delta, size)
local rate = got / delta local rate = got / delta
if size and size >= 1 then if size and size >= 1 then
return string.format(remaining_s, nicesize(got), nicesize(rate), return string.format(remaining_s, nicesize(got), nicesize(rate),
100*got/size, nicetime((size-got)/rate)) 100*got/size, nicetime((size-got)/rate))
else else
return string.format(elapsed_s, nicesize(got), return string.format(elapsed_s, nicesize(got),
nicesize(rate), nicetime(delta)) nicesize(rate), nicetime(delta))
end end
end end
@ -68,18 +68,18 @@ function stats(size)
local got = 0 local got = 0
return function(chunk) return function(chunk)
-- elapsed time since start -- elapsed time since start
local delta = socket.gettime() - start local delta = socket.gettime() - start
if chunk then if chunk then
-- total bytes received -- total bytes received
got = got + string.len(chunk) got = got + string.len(chunk)
-- not enough time for estimate -- not enough time for estimate
if delta > 0.1 then if delta > 0.1 then
io.stderr:write("\r", gauge(got, delta, size)) io.stderr:write("\r", gauge(got, delta, size))
io.stderr:flush() io.stderr:flush()
end end
else else
-- close up -- close up
io.stderr:write("\r", gauge(got, delta), "\n") io.stderr:write("\r", gauge(got, delta), "\n")
end end
return chunk return chunk
end end
@ -111,11 +111,11 @@ function getbyftp(u, file)
local gett = url.parse(u) local gett = url.parse(u)
gett.sink = save gett.sink = save
gett.type = "i" gett.type = "i"
local ret, err = ftp.get(gett) local ret, err = ftp.get(gett)
if err then print(err) end if err then print(err) end
end end
-- determines the scheme -- determines the scheme
function getscheme(u) function getscheme(u)
-- this is an heuristic to solve a common invalid url poblem -- this is an heuristic to solve a common invalid url poblem
if not string.find(u, "//") then u = "//" .. u end if not string.find(u, "//") then u = "//" .. u end
@ -134,7 +134,7 @@ end
-- main program -- main program
arg = arg or {} arg = arg or {}
if table.getn(arg) < 1 then if table.getn(arg) < 1 then
io.write("Usage:\n lua get.lua <remote-url> [<local-file>]\n") io.write("Usage:\n lua get.lua <remote-url> [<local-file>]\n")
os.exit(1) os.exit(1)
else get(arg[1], arg[2]) end else get(arg[1], arg[2]) end

View File

@ -46,7 +46,7 @@ local function ACK(block)
local low, high local low, high
low = math.mod(block, 256) low = math.mod(block, 256)
high = (block - low)/256 high = (block - low)/256
return char(0, OP_ACK, high, low) return char(0, OP_ACK, high, low)
end end
local function get_OP(dgram) local function get_OP(dgram)
@ -71,7 +71,7 @@ local function get_ERROR(dgram)
end end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- The real work -- The real work
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
local function tget(gett) local function tget(gett)
local retries, dgram, sent, datahost, dataport, code local retries, dgram, sent, datahost, dataport, code
@ -83,15 +83,15 @@ local function tget(gett)
gett.host = try(socket.dns.toip(gett.host)) gett.host = try(socket.dns.toip(gett.host))
con:settimeout(1) con:settimeout(1)
-- first packet gives data host/port to be used for data transfers -- first packet gives data host/port to be used for data transfers
local path = string.gsub(gett.path or "", "^/", "") local path = string.gsub(gett.path or "", "^/", "")
path = url.unescape(path) path = url.unescape(path)
retries = 0 retries = 0
repeat repeat
sent = try(con:sendto(RRQ(path, "octet"), gett.host, gett.port)) sent = try(con:sendto(RRQ(path, "octet"), gett.host, gett.port))
dgram, datahost, dataport = con:receivefrom() dgram, datahost, dataport = con:receivefrom()
retries = retries + 1 retries = retries + 1
until dgram or datahost ~= "timeout" or retries > 5 until dgram or datahost ~= "timeout" or retries > 5
try(dgram, datahost) try(dgram, datahost)
-- associate socket with data host/port -- associate socket with data host/port
try(con:setpeername(datahost, dataport)) try(con:setpeername(datahost, dataport))
-- default sink -- default sink
@ -110,7 +110,7 @@ local function tget(gett)
last = block last = block
end end
-- last packet brings less than 512 bytes of data -- last packet brings less than 512 bytes of data
if string.len(data) < 512 then if string.len(data) < 512 then
try(con:send(ACK(block))) try(con:send(ACK(block)))
try(con:close()) try(con:close())
try(sink(nil)) try(sink(nil))
@ -118,7 +118,7 @@ local function tget(gett)
end end
-- get the next packet -- get the next packet
retries = 0 retries = 0
repeat repeat
sent = try(con:send(ACK(last))) sent = try(con:send(ACK(last)))
dgram, err = con:receive() dgram, err = con:receive()
retries = retries + 1 retries = retries + 1
@ -141,7 +141,7 @@ local function parse(u)
end end
local function sget(u) local function sget(u)
local gett = parse(u) local gett = parse(u)
local t = {} local t = {}
gett.sink = ltn12.sink.table(t) gett.sink = ltn12.sink.table(t)
tget(gett) tget(gett)

View File

@ -6,9 +6,9 @@ include config
#------ #------
# Hopefully no need to change anything below this line # Hopefully no need to change anything below this line
# #
INSTALL_SOCKET_LUA=$(INSTALL_TOP_LUA)/socket INSTALL_SOCKET_SHARE=$(INSTALL_TOP_SHARE)/socket
INSTALL_SOCKET_LIB=$(INSTALL_TOP_LIB)/socket INSTALL_SOCKET_LIB=$(INSTALL_TOP_LIB)/socket
INSTALL_MIME_LUA=$(INSTALL_TOP_LUA)/mime INSTALL_MIME_SHARE=$(INSTALL_TOP_SHARE)/mime
INSTALL_MIME_LIB=$(INSTALL_TOP_LIB)/mime INSTALL_MIME_LIB=$(INSTALL_TOP_LIB)/mime
all clean: all clean:
@ -17,35 +17,34 @@ all clean:
#------ #------
# Files to install # Files to install
# #
TO_SOCKET_LUA:= \ TO_SOCKET_SHARE:= \
socket.lua \
http.lua \ http.lua \
url.lua \ url.lua \
tp.lua \ tp.lua \
ftp.lua \ ftp.lua \
smtp.lua smtp.lua
TO_TOP_LUA:= \ TO_TOP_SHARE:= \
ltn12.lua $(COMPAT)/compat-5.1.lua \
ltn12.lua \
TO_MIME_LUA:= \ socket.lua \
mime.lua mime.lua
TO_MIME_SHARE:=
#------ #------
# Install LuaSocket according to recommendation # Install LuaSocket according to recommendation
# #
install: all install: all
cd src; mkdir -p $(INSTALL_TOP_LUA) cd src; mkdir -p $(INSTALL_TOP_SHARE)
cd src; mkdir -p $(INSTALL_TOP_LIB) cd src; $(INSTALL_DATA) $(TO_TOP_SHARE) $(INSTALL_TOP_SHARE)
cd src; $(INSTALL_DATA) $(COMPAT)/compat-5.1.lua $(INSTALL_TOP_LUA) cd src; mkdir -p $(INSTALL_SOCKET_SHARE)
cd src; $(INSTALL_DATA) ltn12.lua $(INSTALL_TOP_LUA) cd src; $(INSTALL_DATA) $(TO_SOCKET_SHARE) $(INSTALL_SOCKET_SHARE)
cd src; mkdir -p $(INSTALL_SOCKET_LUA)
cd src; mkdir -p $(INSTALL_SOCKET_LIB) cd src; mkdir -p $(INSTALL_SOCKET_LIB)
cd src; $(INSTALL_DATA) $(TO_SOCKET_LUA) $(INSTALL_SOCKET_LUA)
cd src; $(INSTALL_EXEC) $(SOCKET_SO) $(INSTALL_SOCKET_LIB)/core.$(EXT) cd src; $(INSTALL_EXEC) $(SOCKET_SO) $(INSTALL_SOCKET_LIB)/core.$(EXT)
cd src; mkdir -p $(INSTALL_MIME_LUA) #cd src; mkdir -p $(INSTALL_MIME_SHARE)
#cd src; $(INSTALL_DATA) $(TO_MIME_SHARE) $(INSTALL_MIME_SHARE)
cd src; mkdir -p $(INSTALL_MIME_LIB) cd src; mkdir -p $(INSTALL_MIME_LIB)
cd src; $(INSTALL_DATA) $(TO_MIME_LUA) $(INSTALL_MIME_LUA)
cd src; $(INSTALL_EXEC) $(MIME_SO) $(INSTALL_MIME_LIB)/core.$(EXT) cd src; $(INSTALL_EXEC) $(MIME_SO) $(INSTALL_MIME_LIB)/core.$(EXT)
#------ #------

View File

@ -1,13 +1,12 @@
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
# Distribution makefile # Distribution makefile
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
DIST = luasocket-2.0 DIST = luasocket-2.0
COMPAT = src/compat-5.1r4 COMPAT = src/compat-5.1r4
TEST = \ TEST = \
test/README \
test/testclnt.lua \ test/testclnt.lua \
test/testsrvr.lua \ test/testsrvr.lua \
test/testsupport.lua test/testsupport.lua
@ -33,12 +32,12 @@ ETC = \
etc/eol.lua \ etc/eol.lua \
etc/forward.lua \ etc/forward.lua \
etc/get.lua \ etc/get.lua \
etc/links \
etc/lp.lua \ etc/lp.lua \
etc/qp.lua \ etc/qp.lua \
etc/tftp.lua etc/tftp.lua
SRC = \ SRC = \
src/makefile \
src/auxiliar.c \ src/auxiliar.c \
src/auxiliar.h \ src/auxiliar.h \
src/buffer.c \ src/buffer.c \
@ -108,6 +107,7 @@ dist:
mkdir -p $(DIST) mkdir -p $(DIST)
cp -vf NEW $(DIST) cp -vf NEW $(DIST)
cp -vf LICENSE $(DIST) cp -vf LICENSE $(DIST)
cp -vf README $(DIST)
cp -vf $(MAKE) $(DIST) cp -vf $(MAKE) $(DIST)
mkdir -p $(DIST)/etc mkdir -p $(DIST)/etc

View File

@ -16,7 +16,7 @@ function parse(body)
return nil, code, message return nil, code, message
end end
local data = {} local data = {}
for l in lines do for l in lines do
local c = string.sub(l, 1, 1) local c = string.sub(l, 1, 1)
if c ~= '#' and c ~= '.' then if c ~= '#' and c ~= '.' then
local key, value = socket.skip(2, string.find(l, "(.-)=(.*)")) local key, value = socket.skip(2, string.find(l, "(.-)=(.*)"))
@ -26,7 +26,7 @@ function parse(body)
data[key] = value data[key] = value
end end
end end
return data, code, message return data, code, message
end end
local host = socket.dns.gethostname() local host = socket.dns.gethostname()
@ -34,13 +34,13 @@ local query = "%s?cmd=cddb+read+%s+%s&hello=LuaSocket+%s+LuaSocket+2.0&proto=6"
local url = string.format(query, server, arg[1], arg[2], host) local url = string.format(query, server, arg[1], arg[2], host)
local body, headers, code = http.get(url) local body, headers, code = http.get(url)
if code == 200 then if code == 200 then
local data, code, error = parse(body) local data, code, error = parse(body)
if not data then if not data then
print(error or code) print(error or code)
else else
for i,v in pairs(data) do for i,v in pairs(data) do
io.write(i, ': ', v, '\n') io.write(i, ': ', v, '\n')
end end
end end
else print(error) end else print(error) end

View File

@ -20,10 +20,10 @@ assert(ip, port)
print("Waiting packets on " .. ip .. ":" .. port .. "...") print("Waiting packets on " .. ip .. ":" .. port .. "...")
while 1 do while 1 do
dgram, ip, port = udp:receivefrom() dgram, ip, port = udp:receivefrom()
if dgram then if dgram then
print("Echoing '" .. dgram .. "' to " .. ip .. ":" .. port) print("Echoing '" .. dgram .. "' to " .. ip .. ":" .. port)
udp:sendto(dgram, ip, port) udp:sendto(dgram, ip, port)
else else
print(ip) print(ip)
end end
end end

View File

@ -36,7 +36,8 @@ do
return usage() return usage()
end end
if arg[1] ~= "query" then if arg[1] ~= "query" then
r,e=lp.send(arg[1],opt) opt.file = arg[1]
r,e=lp.send(opt)
io.stdout:write(tostring(r or e),'\n') io.stdout:write(tostring(r or e),'\n')
else else
r,e=lp.query(opt) r,e=lp.query(opt)

View File

@ -62,24 +62,24 @@ while 1 do
if input == server1 or input == server2 then if input == server1 or input == server2 then
io.write("Waiting for clients\n") io.write("Waiting for clients\n")
local new = input:accept() local new = input:accept()
if new then if new then
new:settimeout(1) new:settimeout(1)
io.write("Inserting client in set\n") io.write("Inserting client in set\n")
set:insert(new) set:insert(new)
end end
-- it is a client socket -- it is a client socket
else else
local line, error = input:receive() local line, error = input:receive()
if error then if error then
input:close() input:close()
io.write("Removing client from set\n") io.write("Removing client from set\n")
set:remove(input) set:remove(input)
else else
io.write("Broadcasting line '", line, "'\n") io.write("Broadcasting line '", line, "'\n")
writable, error = socket.skip(1, socket.select(nil, set, 1)) writable, error = socket.skip(1, socket.select(nil, set, 1))
if not error then if not error then
for __, output in ipairs(writable) do for __, output in ipairs(writable) do
if output ~= input then if output ~= input then
output:send(line .. "\n") output:send(line .. "\n")
end end
end end

View File

@ -40,7 +40,7 @@ function open(server, port, create)
local f = base.setmetatable({ tp = tp }, metat) local f = base.setmetatable({ tp = tp }, metat)
-- make sure everything gets closed in an exception -- make sure everything gets closed in an exception
f.try = socket.newtry(function() f:close() end) f.try = socket.newtry(function() f:close() end)
return f return f
end end
function metat.__index:portconnect() function metat.__index:portconnect()
@ -71,20 +71,20 @@ function metat.__index:pasv()
local pattern = "(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)" local pattern = "(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)"
local a, b, c, d, p1, p2 = socket.skip(2, string.find(reply, pattern)) local a, b, c, d, p1, p2 = socket.skip(2, string.find(reply, pattern))
self.try(a and b and c and d and p1 and p2, reply) self.try(a and b and c and d and p1 and p2, reply)
self.pasvt = { self.pasvt = {
ip = string.format("%d.%d.%d.%d", a, b, c, d), ip = string.format("%d.%d.%d.%d", a, b, c, d),
port = p1*256 + p2 port = p1*256 + p2
} }
if self.server then if self.server then
self.server:close() self.server:close()
self.server = nil self.server = nil
end end
return self.pasvt.ip, self.pasvt.port return self.pasvt.ip, self.pasvt.port
end end
function metat.__index:port(ip, port) function metat.__index:port(ip, port)
self.pasvt = nil self.pasvt = nil
if not ip then if not ip then
ip, port = self.try(self.tp:getcontrol():getsockname()) ip, port = self.try(self.tp:getcontrol():getsockname())
self.server = self.try(socket.bind(ip, 0)) self.server = self.try(socket.bind(ip, 0))
ip, port = self.try(self.server:getsockname()) ip, port = self.try(self.server:getsockname())
@ -100,11 +100,11 @@ end
function metat.__index:send(sendt) function metat.__index:send(sendt)
self.try(self.pasvt or self.server, "need port or pasv first") self.try(self.pasvt or self.server, "need port or pasv first")
-- if there is a pasvt table, we already sent a PASV command -- if there is a pasvt table, we already sent a PASV command
-- we just get the data connection into self.data -- we just get the data connection into self.data
if self.pasvt then self:pasvconnect() end if self.pasvt then self:pasvconnect() end
-- get the transfer argument and command -- get the transfer argument and command
local argument = sendt.argument or local argument = sendt.argument or
url.unescape(string.gsub(sendt.path or "", "^[/\\]", "")) url.unescape(string.gsub(sendt.path or "", "^[/\\]", ""))
if argument == "" then argument = nil end if argument == "" then argument = nil end
local command = sendt.command or "stor" local command = sendt.command or "stor"
@ -137,7 +137,7 @@ end
function metat.__index:receive(recvt) function metat.__index:receive(recvt)
self.try(self.pasvt or self.server, "need port or pasv first") self.try(self.pasvt or self.server, "need port or pasv first")
if self.pasvt then self:pasvconnect() end if self.pasvt then self:pasvconnect() end
local argument = recvt.argument or local argument = recvt.argument or
url.unescape(string.gsub(recvt.path or "", "^[/\\]", "")) url.unescape(string.gsub(recvt.path or "", "^[/\\]", ""))
if argument == "" then argument = nil end if argument == "" then argument = nil end
local command = recvt.command or "retr" local command = recvt.command or "retr"
@ -220,7 +220,7 @@ local function parse(u)
socket.try(t.scheme == "ftp", "wrong scheme '" .. t.scheme .. "'") socket.try(t.scheme == "ftp", "wrong scheme '" .. t.scheme .. "'")
socket.try(t.host, "missing hostname") socket.try(t.host, "missing hostname")
local pat = "^type=(.)$" local pat = "^type=(.)$"
if t.params then if t.params then
t.type = socket.skip(2, string.find(t.params, pat)) t.type = socket.skip(2, string.find(t.params, pat))
socket.try(t.type == "a" or t.type == "i", socket.try(t.type == "a" or t.type == "i",
"invalid type '" .. t.type .. "'") "invalid type '" .. t.type .. "'")
@ -229,7 +229,7 @@ local function parse(u)
end end
local function sput(u, body) local function sput(u, body)
local putt = parse(u) local putt = parse(u)
putt.source = ltn12.source.string(body) putt.source = ltn12.source.string(body)
return tput(putt) return tput(putt)
end end
@ -253,7 +253,7 @@ local function tget(gett)
end end
local function sget(u) local function sget(u)
local gett = parse(u) local gett = parse(u)
local t = {} local t = {}
gett.sink = ltn12.sink.table(t) gett.sink = ltn12.sink.table(t)
tget(gett) tget(gett)

View File

@ -21,7 +21,7 @@ module("socket.http")
-- Program constants -- Program constants
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- connection timeout in seconds -- connection timeout in seconds
TIMEOUT = 60 TIMEOUT = 60
-- default port for document retrieval -- default port for document retrieval
PORT = 80 PORT = 80
-- user agent field sent in request -- user agent field sent in request
@ -65,18 +65,18 @@ socket.sourcet["http-chunked"] = function(sock, headers)
return base.setmetatable({ return base.setmetatable({
getfd = function() return sock:getfd() end, getfd = function() return sock:getfd() end,
dirty = function() return sock:dirty() end dirty = function() return sock:dirty() end
}, { }, {
__call = function() __call = function()
-- get chunk size, skip extention -- get chunk size, skip extention
local line, err = sock:receive() local line, err = sock:receive()
if err then return nil, err end if err then return nil, err end
local size = base.tonumber(string.gsub(line, ";.*", ""), 16) local size = base.tonumber(string.gsub(line, ";.*", ""), 16)
if not size then return nil, "invalid chunk size" end if not size then return nil, "invalid chunk size" end
-- was it the last chunk? -- was it the last chunk?
if size > 0 then if size > 0 then
-- if not, get chunk and skip terminating CRLF -- if not, get chunk and skip terminating CRLF
local chunk, err, part = sock:receive(size) local chunk, err, part = sock:receive(size)
if chunk then sock:receive() end if chunk then sock:receive() end
return chunk, err return chunk, err
else else
-- if it was, read trailers into headers table -- if it was, read trailers into headers table
@ -91,7 +91,7 @@ socket.sinkt["http-chunked"] = function(sock)
return base.setmetatable({ return base.setmetatable({
getfd = function() return sock:getfd() end, getfd = function() return sock:getfd() end,
dirty = function() return sock:dirty() end dirty = function() return sock:dirty() end
}, { }, {
__call = function(self, chunk, err) __call = function(self, chunk, err)
if not chunk then return sock:send("0\r\n\r\n") end if not chunk then return sock:send("0\r\n\r\n") end
local size = string.format("%X\r\n", string.len(chunk)) local size = string.format("%X\r\n", string.len(chunk))
@ -115,11 +115,11 @@ function open(host, port, create)
h.try(c:settimeout(TIMEOUT)) h.try(c:settimeout(TIMEOUT))
h.try(c:connect(host, port or PORT)) h.try(c:connect(host, port or PORT))
-- here everything worked -- here everything worked
return h return h
end end
function metat.__index:sendrequestline(method, uri) function metat.__index:sendrequestline(method, uri)
local reqline = string.format("%s %s HTTP/1.1\r\n", method or "GET", uri) local reqline = string.format("%s %s HTTP/1.1\r\n", method or "GET", uri)
return self.try(self.c:send(reqline)) return self.try(self.c:send(reqline))
end end
@ -133,7 +133,7 @@ function metat.__index:sendheaders(headers)
end end
function metat.__index:sendbody(headers, source, step) function metat.__index:sendbody(headers, source, step)
source = source or ltn12.source.empty() source = source or ltn12.source.empty()
step = step or ltn12.pump.step step = step or ltn12.pump.step
-- if we don't know the size in advance, send chunked and hope for the best -- if we don't know the size in advance, send chunked and hope for the best
local mode = "http-chunked" local mode = "http-chunked"
@ -159,7 +159,7 @@ function metat.__index:receivebody(headers, sink, step)
local mode = "default" -- connection close local mode = "default" -- connection close
if t and t ~= "identity" then mode = "http-chunked" if t and t ~= "identity" then mode = "http-chunked"
elseif base.tonumber(headers["content-length"]) then mode = "by-length" end elseif base.tonumber(headers["content-length"]) then mode = "by-length" end
return self.try(ltn12.pump.all(socket.source(mode, self.c, length), return self.try(ltn12.pump.all(socket.source(mode, self.c, length),
sink, step)) sink, step))
end end
@ -185,7 +185,7 @@ local function adjusturi(reqt)
end end
local function adjustproxy(reqt) local function adjustproxy(reqt)
local proxy = reqt.proxy or PROXY local proxy = reqt.proxy or PROXY
if proxy then if proxy then
proxy = url.parse(proxy) proxy = url.parse(proxy)
return proxy.host, proxy.port or 3128 return proxy.host, proxy.port or 3128
@ -292,10 +292,10 @@ function trequest(reqt)
local code, headers, status local code, headers, status
code, status = h:receivestatusline() code, status = h:receivestatusline()
headers = h:receiveheaders() headers = h:receiveheaders()
if shouldredirect(reqt, code, headers) then if shouldredirect(reqt, code, headers) then
h:close() h:close()
return tredirect(reqt, headers.location) return tredirect(reqt, headers.location)
elseif shouldauthorize(reqt, code) then elseif shouldauthorize(reqt, code) then
h:close() h:close()
return tauthorize(reqt) return tauthorize(reqt)
elseif shouldreceivebody(reqt, code) then elseif shouldreceivebody(reqt, code) then
@ -307,12 +307,12 @@ end
local function srequest(u, body) local function srequest(u, body)
local t = {} local t = {}
local reqt = { local reqt = {
url = u, url = u,
sink = ltn12.sink.table(t) sink = ltn12.sink.table(t)
} }
if body then if body then
reqt.source = ltn12.source.string(body) reqt.source = ltn12.source.string(body)
reqt.headers = { ["content-length"] = string.len(body) } reqt.headers = { ["content-length"] = string.len(body) }
reqt.method = "POST" reqt.method = "POST"
end end

View File

@ -36,19 +36,19 @@ end
-- chains a bunch of filters together -- chains a bunch of filters together
-- (thanks to Wim Couwenberg) -- (thanks to Wim Couwenberg)
function filter.chain(...) function filter.chain(...)
local n = table.getn(arg) local n = table.getn(arg)
local top, index = 1, 1 local top, index = 1, 1
local retry = "" local retry = ""
return function(chunk) return function(chunk)
retry = chunk and retry retry = chunk and retry
while true do while true do
if index == top then if index == top then
chunk = arg[index](chunk) chunk = arg[index](chunk)
if chunk == "" or top == n then return chunk if chunk == "" or top == n then return chunk
elseif chunk then index = index + 1 elseif chunk then index = index + 1
else else
top = top+1 top = top+1
index = top index = top
end end
else else
@ -148,9 +148,9 @@ function source.chain(src, f)
last_in, err = src() last_in, err = src()
if err then return nil, err end if err then return nil, err end
last_out = f(last_in) last_out = f(last_in)
if not last_out then if not last_out then
if last_in then if last_in then
base.error('filter returned inappropriate nil') base.error('filter returned inappropriate nil')
else else
return nil return nil
end end
@ -159,17 +159,17 @@ function source.chain(src, f)
if last_in then last_in = "" end if last_in then last_in = "" end
return last_out return last_out
end end
else else
last_out = f(last_in) last_out = f(last_in)
if last_out == "" then if last_out == "" then
if last_in == "" then if last_in == "" then
state = "feeding" state = "feeding"
else else
base.error('filter returned ""') base.error('filter returned ""')
end end
elseif not last_out then elseif not last_out then
if last_in then if last_in then
base.error('filter returned inappropriate nil') base.error('filter returned inappropriate nil')
else else
return nil return nil
end end
@ -224,7 +224,7 @@ end
function sink.file(handle, io_err) function sink.file(handle, io_err)
if handle then if handle then
return function(chunk, err) return function(chunk, err)
if not chunk then if not chunk then
handle:close() handle:close()
return 1 return 1
else return handle:write(chunk) end else return handle:write(chunk) end
@ -248,7 +248,7 @@ function sink.error(err)
end end
end end
-- chains a sink with a filter -- chains a sink with a filter
function sink.chain(f, snk) function sink.chain(f, snk)
base.assert(f and snk) base.assert(f and snk)
return function(chunk, err) return function(chunk, err)
@ -282,7 +282,7 @@ function pump.all(src, snk, step)
step = step or pump.step step = step or pump.step
while true do while true do
local ret, err = step(src, snk) local ret, err = step(src, snk)
if not ret then if not ret then
if err then return nil, err if err then return nil, err
else return 1 end else return 1 end
end end

View File

@ -10,7 +10,7 @@ function Public.split_message(message_s)
if not message.body then if not message.body then
string.gsub(message_s, "^\n(.*)", function (b) message.body = b end) string.gsub(message_s, "^\n(.*)", function (b) message.body = b end)
end end
if not message.headers and not message.body then if not message.headers and not message.body then
message.headers = message_s message.headers = message_s
end end
return message.headers or "", message.body or "" return message.headers or "", message.body or ""

View File

@ -20,10 +20,10 @@ encodet = {}
decodet = {} decodet = {}
wrapt = {} wrapt = {}
-- creates a function that chooses a filter by name from a given table -- creates a function that chooses a filter by name from a given table
local function choose(table) local function choose(table)
return function(name, opt1, opt2) return function(name, opt1, opt2)
if base.type(name) ~= "string" then if base.type(name) ~= "string" then
name, opt1, opt2 = "default", name, opt1 name, opt1, opt2 = "default", name, opt1
end end
local f = table[name or "nil"] local f = table[name or "nil"]
@ -38,7 +38,7 @@ encodet['base64'] = function()
end end
encodet['quoted-printable'] = function(mode) encodet['quoted-printable'] = function(mode)
return ltn12.filter.cycle(qp, "", return ltn12.filter.cycle(qp, "",
(mode == "binary") and "=0D=0A" or "\r\n") (mode == "binary") and "=0D=0A" or "\r\n")
end end
@ -56,22 +56,22 @@ local function format(chunk)
if chunk == "" then return "''" if chunk == "" then return "''"
else return string.len(chunk) end else return string.len(chunk) end
else return "nil" end else return "nil" end
end end
-- define the line-wrap filters -- define the line-wrap filters
wrapt['text'] = function(length) wrapt['text'] = function(length)
length = length or 76 length = length or 76
return ltn12.filter.cycle(wrp, length, length) return ltn12.filter.cycle(wrp, length, length)
end end
wrapt['base64'] = wrapt['text'] wrapt['base64'] = wrapt['text']
wrapt['default'] = wrapt['text'] wrapt['default'] = wrapt['text']
wrapt['quoted-printable'] = function() wrapt['quoted-printable'] = function()
return ltn12.filter.cycle(qpwrp, 76, 76) return ltn12.filter.cycle(qpwrp, 76, 76)
end end
-- function that choose the encoding, decoding or wrap algorithm -- function that choose the encoding, decoding or wrap algorithm
encode = choose(encodet) encode = choose(encodet)
decode = choose(decodet) decode = choose(decodet)
wrap = choose(wrapt) wrap = choose(wrapt)

View File

@ -27,8 +27,8 @@ TIMEOUT = 60
-- default server used to send e-mails -- default server used to send e-mails
SERVER = "localhost" SERVER = "localhost"
-- default port -- default port
PORT = 25 PORT = 25
-- domain used in HELO command and default sendmail -- domain used in HELO command and default sendmail
-- If we are under a CGI, try to get from environment -- If we are under a CGI, try to get from environment
DOMAIN = os.getenv("SERVER_NAME") or "localhost" DOMAIN = os.getenv("SERVER_NAME") or "localhost"
-- default time zone (means we don't know) -- default time zone (means we don't know)
@ -43,12 +43,12 @@ function metat.__index:greet(domain)
self.try(self.tp:check("2..")) self.try(self.tp:check("2.."))
self.try(self.tp:command("EHLO", domain or DOMAIN)) self.try(self.tp:command("EHLO", domain or DOMAIN))
return socket.skip(1, self.try(self.tp:check("2.."))) return socket.skip(1, self.try(self.tp:check("2..")))
end end
function metat.__index:mail(from) function metat.__index:mail(from)
self.try(self.tp:command("MAIL", "FROM:" .. from)) self.try(self.tp:command("MAIL", "FROM:" .. from))
return self.try(self.tp:check("2..")) return self.try(self.tp:check("2.."))
end end
function metat.__index:rcpt(to) function metat.__index:rcpt(to)
self.try(self.tp:command("RCPT", "TO:" .. to)) self.try(self.tp:command("RCPT", "TO:" .. to))
@ -99,7 +99,7 @@ function metat.__index:auth(user, password, ext)
end end
-- send message or throw an exception -- send message or throw an exception
function metat.__index:send(mailt) function metat.__index:send(mailt)
self:mail(mailt.from) self:mail(mailt.from)
if base.type(mailt.rcpt) == "table" then if base.type(mailt.rcpt) == "table" then
for i,v in base.ipairs(mailt.rcpt) do for i,v in base.ipairs(mailt.rcpt) do
@ -112,14 +112,14 @@ function metat.__index:send(mailt)
end end
function open(server, port, create) function open(server, port, create)
local tp = socket.try(tp.connect(server or SERVER, port or PORT, local tp = socket.try(tp.connect(server or SERVER, port or PORT,
create, TIMEOUT)) create, TIMEOUT))
local s = base.setmetatable({tp = tp}, metat) local s = base.setmetatable({tp = tp}, metat)
-- make sure tp is closed if we get an exception -- make sure tp is closed if we get an exception
s.try = socket.newtry(function() s.try = socket.newtry(function()
s:close() s:close()
end) end)
return s return s
end end
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
@ -142,7 +142,7 @@ local function send_headers(headers)
for i,v in base.pairs(headers) do for i,v in base.pairs(headers) do
h = i .. ': ' .. v .. "\r\n" .. h h = i .. ': ' .. v .. "\r\n" .. h
end end
coroutine.yield(h) coroutine.yield(h)
end end
-- yield multipart message body from a multipart message table -- yield multipart message body from a multipart message table
@ -151,25 +151,25 @@ local function send_multipart(mesgt)
local bd = newboundary() local bd = newboundary()
local headers = mesgt.headers or {} local headers = mesgt.headers or {}
headers['content-type'] = headers['content-type'] or 'multipart/mixed' headers['content-type'] = headers['content-type'] or 'multipart/mixed'
headers['content-type'] = headers['content-type'] .. headers['content-type'] = headers['content-type'] ..
'; boundary="' .. bd .. '"' '; boundary="' .. bd .. '"'
send_headers(headers) send_headers(headers)
-- send preamble -- send preamble
if mesgt.body.preamble then if mesgt.body.preamble then
coroutine.yield(mesgt.body.preamble) coroutine.yield(mesgt.body.preamble)
coroutine.yield("\r\n") coroutine.yield("\r\n")
end end
-- send each part separated by a boundary -- send each part separated by a boundary
for i, m in base.ipairs(mesgt.body) do for i, m in base.ipairs(mesgt.body) do
coroutine.yield("\r\n--" .. bd .. "\r\n") coroutine.yield("\r\n--" .. bd .. "\r\n")
send_message(m) send_message(m)
end end
-- send last boundary -- send last boundary
coroutine.yield("\r\n--" .. bd .. "--\r\n\r\n") coroutine.yield("\r\n--" .. bd .. "--\r\n\r\n")
-- send epilogue -- send epilogue
if mesgt.body.epilogue then if mesgt.body.epilogue then
coroutine.yield(mesgt.body.epilogue) coroutine.yield(mesgt.body.epilogue)
coroutine.yield("\r\n") coroutine.yield("\r\n")
end end
end end
@ -181,7 +181,7 @@ local function send_source(mesgt)
'text/plain; charset="iso-8859-1"' 'text/plain; charset="iso-8859-1"'
send_headers(headers) send_headers(headers)
-- send body from source -- send body from source
while true do while true do
local chunk, err = mesgt.body() local chunk, err = mesgt.body()
if err then coroutine.yield(nil, err) if err then coroutine.yield(nil, err)
elseif chunk then coroutine.yield(chunk) elseif chunk then coroutine.yield(chunk)
@ -213,11 +213,11 @@ local function adjust_headers(mesgt)
for i,v in base.pairs(mesgt.headers or lower) do for i,v in base.pairs(mesgt.headers or lower) do
lower[string.lower(i)] = v lower[string.lower(i)] = v
end end
lower["date"] = lower["date"] or lower["date"] = lower["date"] or
os.date("!%a, %d %b %Y %H:%M:%S ") .. (mesgt.zone or ZONE) os.date("!%a, %d %b %Y %H:%M:%S ") .. (mesgt.zone or ZONE)
lower["x-mailer"] = lower["x-mailer"] or socket._VERSION lower["x-mailer"] = lower["x-mailer"] or socket._VERSION
-- this can't be overriden -- this can't be overriden
lower["mime-version"] = "1.0" lower["mime-version"] = "1.0"
mesgt.headers = lower mesgt.headers = lower
end end
@ -225,7 +225,7 @@ function message(mesgt)
adjust_headers(mesgt) adjust_headers(mesgt)
-- create and return message source -- create and return message source
local co = coroutine.create(function() send_message(mesgt) end) local co = coroutine.create(function() send_message(mesgt) end)
return function() return function()
local ret, a, b = coroutine.resume(co) local ret, a, b = coroutine.resume(co)
if ret then return a, b if ret then return a, b
else return nil, a end else return nil, a end

View File

@ -19,7 +19,7 @@ module("socket")
function connect(address, port, laddress, lport) function connect(address, port, laddress, lport)
local sock, err = socket.tcp() local sock, err = socket.tcp()
if not sock then return nil, err end if not sock then return nil, err end
if laddress then if laddress then
local res, err = sock:bind(laddress, lport, -1) local res, err = sock:bind(laddress, lport, -1)
if not res then return nil, err end if not res then return nil, err end
end end
@ -65,9 +65,9 @@ sinkt["close-when-done"] = function(sock)
return base.setmetatable({ return base.setmetatable({
getfd = function() return sock:getfd() end, getfd = function() return sock:getfd() end,
dirty = function() return sock:dirty() end dirty = function() return sock:dirty() end
}, { }, {
__call = function(self, chunk, err) __call = function(self, chunk, err)
if not chunk then if not chunk then
sock:close() sock:close()
return 1 return 1
else return sock:send(chunk) end else return sock:send(chunk) end
@ -79,7 +79,7 @@ sinkt["keep-open"] = function(sock)
return base.setmetatable({ return base.setmetatable({
getfd = function() return sock:getfd() end, getfd = function() return sock:getfd() end,
dirty = function() return sock:dirty() end dirty = function() return sock:dirty() end
}, { }, {
__call = function(self, chunk, err) __call = function(self, chunk, err)
if chunk then return sock:send(chunk) if chunk then return sock:send(chunk)
else return 1 end else return 1 end
@ -95,7 +95,7 @@ sourcet["by-length"] = function(sock, length)
return base.setmetatable({ return base.setmetatable({
getfd = function() return sock:getfd() end, getfd = function() return sock:getfd() end,
dirty = function() return sock:dirty() end dirty = function() return sock:dirty() end
}, { }, {
__call = function() __call = function()
if length <= 0 then return nil end if length <= 0 then return nil end
local size = math.min(socket.BLOCKSIZE, length) local size = math.min(socket.BLOCKSIZE, length)
@ -112,16 +112,16 @@ sourcet["until-closed"] = function(sock)
return base.setmetatable({ return base.setmetatable({
getfd = function() return sock:getfd() end, getfd = function() return sock:getfd() end,
dirty = function() return sock:dirty() end dirty = function() return sock:dirty() end
}, { }, {
__call = function() __call = function()
if done then return nil end if done then return nil end
local chunk, err, partial = sock:receive(socket.BLOCKSIZE) local chunk, err, partial = sock:receive(socket.BLOCKSIZE)
if not err then return chunk if not err then return chunk
elseif err == "closed" then elseif err == "closed" then
sock:close() sock:close()
done = 1 done = 1
return partial return partial
else return nil, err end else return nil, err end
end end
}) })
end end

View File

@ -37,7 +37,7 @@ local function get_reply(c)
current, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)")) current, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
reply = reply .. "\n" .. line reply = reply .. "\n" .. line
-- reply ends with same code -- reply ends with same code
until code == current and sep == " " until code == current and sep == " "
end end
return code, reply return code, reply
end end
@ -49,25 +49,25 @@ function metat.__index:check(ok)
local code, reply = get_reply(self.c) local code, reply = get_reply(self.c)
if not code then return nil, reply end if not code then return nil, reply end
if base.type(ok) ~= "function" then if base.type(ok) ~= "function" then
if base.type(ok) == "table" then if base.type(ok) == "table" then
for i, v in base.ipairs(ok) do for i, v in base.ipairs(ok) do
if string.find(code, v) then if string.find(code, v) then
return base.tonumber(code), reply return base.tonumber(code), reply
end end
end end
return nil, reply return nil, reply
else else
if string.find(code, ok) then return base.tonumber(code), reply if string.find(code, ok) then return base.tonumber(code), reply
else return nil, reply end else return nil, reply end
end end
else return ok(base.tonumber(code), reply) end else return ok(base.tonumber(code), reply) end
end end
function metat.__index:command(cmd, arg) function metat.__index:command(cmd, arg)
if arg then if arg then
return self.c:send(cmd .. " " .. arg.. "\r\n") return self.c:send(cmd .. " " .. arg.. "\r\n")
else else
return self.c:send(cmd .. "\r\n") return self.c:send(cmd .. "\r\n")
end end
end end
@ -114,8 +114,8 @@ function connect(host, port, create, timeout)
if not c then return nil, e end if not c then return nil, e end
c:settimeout(timeout or TIMEOUT) c:settimeout(timeout or TIMEOUT)
local r, e = c:connect(host, port) local r, e = c:connect(host, port)
if not r then if not r then
c:close() c:close()
return nil, e return nil, e
end end
return base.setmetatable({c = c}, metat) return base.setmetatable({c = c}, metat)

View File

@ -20,7 +20,7 @@ _VERSION = "URL 1.0"
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- Encodes a string into its escaped hexadecimal representation -- Encodes a string into its escaped hexadecimal representation
-- Input -- Input
-- s: binary string to be encoded -- s: binary string to be encoded
-- Returns -- Returns
-- escaped representation of string binary -- escaped representation of string binary
@ -33,8 +33,8 @@ end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- Protects a path segment, to prevent it from interfering with the -- Protects a path segment, to prevent it from interfering with the
-- url parsing. -- url parsing.
-- Input -- Input
-- s: binary string to be encoded -- s: binary string to be encoded
-- Returns -- Returns
-- escaped representation of string binary -- escaped representation of string binary
@ -50,12 +50,12 @@ end
-- these are allowed withing a path segment, along with alphanum -- these are allowed withing a path segment, along with alphanum
-- other characters must be escaped -- other characters must be escaped
local segment_set = make_set { local segment_set = make_set {
"-", "_", ".", "!", "~", "*", "'", "(", "-", "_", ".", "!", "~", "*", "'", "(",
")", ":", "@", "&", "=", "+", "$", ",", ")", ":", "@", "&", "=", "+", "$", ",",
} }
local function protect_segment(s) local function protect_segment(s)
return string.gsub(s, "([^A-Za-z0-9_])", function (c) return string.gsub(s, "([^A-Za-z0-9_])", function (c)
if segment_set[c] then return c if segment_set[c] then return c
else return string.format("%%%02x", string.byte(c)) end else return string.format("%%%02x", string.byte(c)) end
end) end)
@ -63,7 +63,7 @@ end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- Encodes a string into its escaped hexadecimal representation -- Encodes a string into its escaped hexadecimal representation
-- Input -- Input
-- s: binary string to be encoded -- s: binary string to be encoded
-- Returns -- Returns
-- escaped representation of string binary -- escaped representation of string binary
@ -86,11 +86,11 @@ local function absolute_path(base_path, relative_path)
if string.sub(relative_path, 1, 1) == "/" then return relative_path end if string.sub(relative_path, 1, 1) == "/" then return relative_path end
local path = string.gsub(base_path, "[^/]*$", "") local path = string.gsub(base_path, "[^/]*$", "")
path = path .. relative_path path = path .. relative_path
path = string.gsub(path, "([^/]*%./)", function (s) path = string.gsub(path, "([^/]*%./)", function (s)
if s ~= "./" then return s else return "" end if s ~= "./" then return s else return "" end
end) end)
path = string.gsub(path, "/%.$", "/") path = string.gsub(path, "/%.$", "/")
local reduced local reduced
while reduced ~= path do while reduced ~= path do
reduced = path reduced = path
path = string.gsub(reduced, "([^/]*/%.%./)", function (s) path = string.gsub(reduced, "([^/]*/%.%./)", function (s)
@ -116,7 +116,7 @@ end
-- Returns -- Returns
-- table with the following fields, where RFC naming conventions have -- table with the following fields, where RFC naming conventions have
-- been preserved: -- been preserved:
-- scheme, authority, userinfo, user, password, host, port, -- scheme, authority, userinfo, user, password, host, port,
-- path, params, query, fragment -- path, params, query, fragment
-- Obs: -- Obs:
-- the leading '/' in {/<path>} is considered part of <path> -- the leading '/' in {/<path>} is considered part of <path>
@ -130,26 +130,26 @@ function parse(url, default)
-- remove whitespace -- remove whitespace
-- url = string.gsub(url, "%s", "") -- url = string.gsub(url, "%s", "")
-- get fragment -- get fragment
url = string.gsub(url, "#(.*)$", function(f) url = string.gsub(url, "#(.*)$", function(f)
parsed.fragment = f parsed.fragment = f
return "" return ""
end) end)
-- get scheme -- get scheme
url = string.gsub(url, "^([%w][%w%+%-%.]*)%:", url = string.gsub(url, "^([%w][%w%+%-%.]*)%:",
function(s) parsed.scheme = s; return "" end) function(s) parsed.scheme = s; return "" end)
-- get authority -- get authority
url = string.gsub(url, "^//([^/]*)", function(n) url = string.gsub(url, "^//([^/]*)", function(n)
parsed.authority = n parsed.authority = n
return "" return ""
end) end)
-- get query stringing -- get query stringing
url = string.gsub(url, "%?(.*)", function(q) url = string.gsub(url, "%?(.*)", function(q)
parsed.query = q parsed.query = q
return "" return ""
end) end)
-- get params -- get params
url = string.gsub(url, "%;(.*)", function(p) url = string.gsub(url, "%;(.*)", function(p)
parsed.params = p parsed.params = p
return "" return ""
end) end)
-- path is whatever was left -- path is whatever was left
@ -158,14 +158,14 @@ function parse(url, default)
if not authority then return parsed end if not authority then return parsed end
authority = string.gsub(authority,"^([^@]*)@", authority = string.gsub(authority,"^([^@]*)@",
function(u) parsed.userinfo = u; return "" end) function(u) parsed.userinfo = u; return "" end)
authority = string.gsub(authority, ":([^:]*)$", authority = string.gsub(authority, ":([^:]*)$",
function(p) parsed.port = p; return "" end) function(p) parsed.port = p; return "" end)
if authority ~= "" then parsed.host = authority end if authority ~= "" then parsed.host = authority end
local userinfo = parsed.userinfo local userinfo = parsed.userinfo
if not userinfo then return parsed end if not userinfo then return parsed end
userinfo = string.gsub(userinfo, ":([^:]*)$", userinfo = string.gsub(userinfo, ":([^:]*)$",
function(p) parsed.password = p; return "" end) function(p) parsed.password = p; return "" end)
parsed.user = userinfo parsed.user = userinfo
return parsed return parsed
end end
@ -189,8 +189,8 @@ function build(parsed)
local userinfo = parsed.userinfo local userinfo = parsed.userinfo
if parsed.user then if parsed.user then
userinfo = parsed.user userinfo = parsed.user
if parsed.password then if parsed.password then
userinfo = userinfo .. ":" .. parsed.password userinfo = userinfo .. ":" .. parsed.password
end end
end end
if userinfo then authority = userinfo .. "@" .. authority end if userinfo then authority = userinfo .. "@" .. authority end
@ -233,8 +233,8 @@ function absolute(base_url, relative_url)
relative_parsed.query = base_parsed.query relative_parsed.query = base_parsed.query
end end
end end
else else
relative_parsed.path = absolute_path(base_parsed.path or "", relative_parsed.path = absolute_path(base_parsed.path or "",
relative_parsed.path) relative_parsed.path)
end end
end end

View File

@ -110,7 +110,8 @@ int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds,
double t = timeout_getretry(tm); double t = timeout_getretry(tm);
tv.tv_sec = (int) t; tv.tv_sec = (int) t;
tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6); tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6);
ret = select(n, rfds, wfds, efds, t >= 0.0? &tv: NULL); /* timeout = 0 means no wait */
ret = select(n, rfds, wfds, efds, t >= 0.0 ? &tv: NULL);
} while (ret < 0 && errno == EINTR); } while (ret < 0 && errno == EINTR);
return ret; return ret;
} }