mirror of
https://github.com/lunarmodules/luasocket.git
synced 2024-12-26 04:28:20 +01:00
Few tweaks in installation, some missing files, etc.
This commit is contained in:
parent
a2b780bf7a
commit
d55a5826e8
2
config
2
config
@ -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
|
||||||
|
@ -69,22 +69,22 @@ independent files. Let's call these directories <tt><LIB></tt>
|
|||||||
and <tt><SHARE></tt>, respectively.
|
and <tt><SHARE></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><LIB></tt> and '<tt>/usr/local/share/lua/5.0</tt>' for
|
<tt><LIB></tt> and '<tt>/usr/local/share/lua/5.0</tt>' for
|
||||||
<tt><SHARE></tt>. On Windows, only one directory is used, say
|
<tt><SHARE></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>
|
||||||
<SHARE>/compat-5.1.lua
|
<SHARE>/compat-5.1.lua
|
||||||
<SHARE>/ltn12.lua
|
<SHARE>/ltn12.lua
|
||||||
<SHARE>/mime/mime.lua
|
<SHARE>/socket.lua
|
||||||
<LIB>/mime/core.dll
|
|
||||||
<SHARE>/socket/socket.lua
|
|
||||||
<LIB>/socket/core.dll
|
<LIB>/socket/core.dll
|
||||||
<SHARE>/socket/http.lua
|
<SHARE>/socket/http.lua
|
||||||
<SHARE>/socket/tp.lua
|
<SHARE>/socket/tp.lua
|
||||||
<SHARE>/socket/ftp.lua
|
<SHARE>/socket/ftp.lua
|
||||||
<SHARE>/socket/smtp.lua
|
<SHARE>/socket/smtp.lua
|
||||||
<SHARE>/socket/url.lua
|
<SHARE>/socket/url.lua
|
||||||
|
<SHARE>/mime.lua
|
||||||
|
<LIB>/mime/core.dll
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p> Naturally, on Unix systems, <tt>core.dll</tt>
|
<p> Naturally, on Unix systems, <tt>core.dll</tt>
|
||||||
|
@ -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>
|
||||||
|
@ -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
|
||||||
|
10
etc/dict.lua
10
etc/dict.lua
@ -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)
|
||||||
|
@ -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
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -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$
|
||||||
|
@ -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)
|
||||||
|
26
etc/get.lua
26
etc/get.lua
@ -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
|
||||||
|
16
etc/tftp.lua
16
etc/tftp.lua
@ -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)
|
||||||
|
31
makefile
31
makefile
@ -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)
|
||||||
|
|
||||||
#------
|
#------
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
26
src/ftp.lua
26
src/ftp.lua
@ -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)
|
||||||
|
32
src/http.lua
32
src/http.lua
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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 ""
|
||||||
|
14
src/mime.lua
14
src/mime.lua
@ -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)
|
||||||
|
|
||||||
|
42
src/smtp.lua
42
src/smtp.lua
@ -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
|
||||||
|
@ -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
|
||||||
|
20
src/tp.lua
20
src/tp.lua
@ -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)
|
||||||
|
50
src/url.lua
50
src/url.lua
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user