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
|
||||
# Relative paths will be inside the src tree
|
||||
#
|
||||
INSTALL_TOP_LUA=share
|
||||
INSTALL_TOP_SHARE=share
|
||||
INSTALL_TOP_LIB=lib
|
||||
|
||||
INSTALL_DATA=cp
|
||||
|
@ -69,22 +69,22 @@ independent files. Let's call these directories <tt><LIB></tt>
|
||||
and <tt><SHARE></tt>, respectively.
|
||||
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><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
|
||||
distribution directory structure:</p>
|
||||
|
||||
<pre class=example>
|
||||
<SHARE>/compat-5.1.lua
|
||||
<SHARE>/ltn12.lua
|
||||
<SHARE>/mime/mime.lua
|
||||
<LIB>/mime/core.dll
|
||||
<SHARE>/socket/socket.lua
|
||||
<SHARE>/socket.lua
|
||||
<LIB>/socket/core.dll
|
||||
<SHARE>/socket/http.lua
|
||||
<SHARE>/socket/tp.lua
|
||||
<SHARE>/socket/ftp.lua
|
||||
<SHARE>/socket/smtp.lua
|
||||
<SHARE>/socket/url.lua
|
||||
<SHARE>/mime.lua
|
||||
<LIB>/mime/core.dll
|
||||
</pre>
|
||||
|
||||
<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.
|
||||
</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 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=sink>
|
||||
|
@ -37,7 +37,7 @@ function getstatus(link)
|
||||
handler:start(function()
|
||||
local r, c, h, s = http.request{
|
||||
method = "HEAD",
|
||||
url = link,
|
||||
url = link,
|
||||
create = handler.tcp
|
||||
}
|
||||
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))
|
||||
end
|
||||
|
||||
while nthreads > 0 do
|
||||
while nthreads > 0 do
|
||||
handler:step()
|
||||
end
|
||||
end
|
||||
|
10
etc/dict.lua
10
etc/dict.lua
@ -17,7 +17,7 @@ local tp = require("socket.tp")
|
||||
module("socket.dict")
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Globals
|
||||
-- Globals
|
||||
-----------------------------------------------------------------------------
|
||||
HOST = "dict.org"
|
||||
PORT = 2628
|
||||
@ -39,7 +39,7 @@ end
|
||||
|
||||
function metat.__index: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*)")))
|
||||
end
|
||||
|
||||
@ -101,7 +101,7 @@ local default = {
|
||||
}
|
||||
|
||||
local function there(f)
|
||||
if f == "" then return nil
|
||||
if f == "" then return nil
|
||||
else return f end
|
||||
end
|
||||
|
||||
@ -116,7 +116,7 @@ local function parse(u)
|
||||
arg = string.gsub(arg, "^:([^:]+)", function(f) t.word = f end)
|
||||
socket.try(t.word, "need at least <word> in URL")
|
||||
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)
|
||||
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)
|
||||
con:quit()
|
||||
con:close()
|
||||
if gett.n then return def[gett.n]
|
||||
if gett.n then return def[gett.n]
|
||||
else return def end
|
||||
elseif gett.command == "m" then
|
||||
local mat = con:match(gett.database, gett.strat, gett.word)
|
||||
|
@ -14,7 +14,7 @@ module("dispatch")
|
||||
TIMEOUT = 60
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- We implement 3 types of dispatchers:
|
||||
-- We implement 3 types of dispatchers:
|
||||
-- sequential
|
||||
-- coroutine
|
||||
-- threaded
|
||||
@ -34,7 +34,7 @@ end
|
||||
|
||||
-- sequential handler simply calls the functions and doesn't wrap I/O
|
||||
function handlert.sequential()
|
||||
return {
|
||||
return {
|
||||
tcp = socket.tcp,
|
||||
start = seqstart
|
||||
}
|
||||
@ -55,7 +55,7 @@ function socket.protect(f)
|
||||
if not status then
|
||||
if type(results[1]) == 'table' then
|
||||
return nil, results[1][1]
|
||||
else error(results[1]) end
|
||||
else error(results[1]) end
|
||||
end
|
||||
if coroutine.status(co) == "suspended" then
|
||||
arg = {coroutine.yield(unpack(results))}
|
||||
@ -84,17 +84,17 @@ local function newset()
|
||||
if index then
|
||||
reverse[value] = nil
|
||||
local top = table.remove(set)
|
||||
if top ~= value then
|
||||
if top ~= value then
|
||||
reverse[top] = index
|
||||
set[index] = top
|
||||
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)
|
||||
if not tcp then return nil, error end
|
||||
@ -102,7 +102,7 @@ local function cowrap(dispatcher, tcp, error)
|
||||
tcp:settimeout(0)
|
||||
-- metatable for wrap produces new methods on demand for those that we
|
||||
-- don't override explicitly.
|
||||
local metat = { __index = function(table, key)
|
||||
local metat = { __index = function(table, key)
|
||||
table[key] = function(...)
|
||||
arg[1] = tcp
|
||||
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?
|
||||
local zero = false
|
||||
-- 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
|
||||
-- the user wants to do his own non-blocking I/O
|
||||
function wrap:settimeout(value, mode)
|
||||
@ -121,19 +121,19 @@ local function cowrap(dispatcher, tcp, error)
|
||||
return 1
|
||||
end
|
||||
-- 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
|
||||
local result, error
|
||||
while true do
|
||||
-- return control to dispatcher and tell it we want to send
|
||||
-- if upon return the dispatcher tells us we timed out,
|
||||
-- return an error to whoever called us
|
||||
if coroutine.yield(dispatcher.sending, tcp) == "timeout" then
|
||||
return nil, "timeout"
|
||||
if coroutine.yield(dispatcher.sending, tcp) == "timeout" then
|
||||
return nil, "timeout"
|
||||
end
|
||||
-- try sending
|
||||
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
|
||||
if error ~= "timeout" then return result, error, first end
|
||||
end
|
||||
@ -143,20 +143,20 @@ local function cowrap(dispatcher, tcp, error)
|
||||
function wrap:receive(pattern, partial)
|
||||
local error = "timeout"
|
||||
local value
|
||||
while true do
|
||||
while true do
|
||||
-- return control to dispatcher and tell it we want to receive
|
||||
-- if upon return the dispatcher tells us we timed out,
|
||||
-- return an error to whoever called us
|
||||
if coroutine.yield(dispatcher.receiving, tcp) == "timeout" then
|
||||
return nil, "timeout"
|
||||
if coroutine.yield(dispatcher.receiving, tcp) == "timeout" then
|
||||
return nil, "timeout"
|
||||
end
|
||||
-- try receiving
|
||||
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
|
||||
-- zero timeout, return all we got
|
||||
if (error ~= "timeout") or zero then
|
||||
return value, error, partial
|
||||
if (error ~= "timeout") or zero then
|
||||
return value, error, partial
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -168,8 +168,8 @@ local function cowrap(dispatcher, tcp, error)
|
||||
-- connection succeeds.
|
||||
-- if upon return the dispatcher tells us we have a
|
||||
-- timeout, just abort
|
||||
if coroutine.yield(dispatcher.sending, tcp) == "timeout" then
|
||||
return nil, "timeout"
|
||||
if coroutine.yield(dispatcher.sending, tcp) == "timeout" then
|
||||
return nil, "timeout"
|
||||
end
|
||||
-- when we come back, check if connection was successful
|
||||
result, error = tcp:connect(host, port)
|
||||
@ -179,27 +179,27 @@ local function cowrap(dispatcher, tcp, error)
|
||||
end
|
||||
-- accept in non-blocking mode and yield on timeout
|
||||
function wrap:accept()
|
||||
while 1 do
|
||||
while 1 do
|
||||
-- return control to dispatcher. we will be readable when a
|
||||
-- connection arrives.
|
||||
-- if upon return the dispatcher tells us we have a
|
||||
-- timeout, just abort
|
||||
if coroutine.yield(dispatcher.receiving, tcp) == "timeout" then
|
||||
return nil, "timeout"
|
||||
if coroutine.yield(dispatcher.receiving, tcp) == "timeout" then
|
||||
return nil, "timeout"
|
||||
end
|
||||
local client, error = tcp:accept()
|
||||
if error ~= "timeout" then
|
||||
return cowrap(dispatcher, client, error)
|
||||
if error ~= "timeout" then
|
||||
return cowrap(dispatcher, client, error)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- remove cortn from context
|
||||
function wrap:close()
|
||||
dispatcher.stamp[tcp] = nil
|
||||
dispatcher.sending.set:remove(tcp)
|
||||
dispatcher.sending.cortn[tcp] = nil
|
||||
dispatcher.sending.cortn[tcp] = nil
|
||||
dispatcher.receiving.set:remove(tcp)
|
||||
dispatcher.receiving.cortn[tcp] = nil
|
||||
dispatcher.receiving.cortn[tcp] = nil
|
||||
return tcp:close()
|
||||
end
|
||||
return setmetatable(wrap, metat)
|
||||
@ -207,12 +207,12 @@ end
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Our coroutine dispatcher
|
||||
-- Our coroutine dispatcher
|
||||
-----------------------------------------------------------------------------
|
||||
local cometat = { __index = {} }
|
||||
|
||||
function schedule(cortn, status, operation, tcp)
|
||||
if status then
|
||||
if status then
|
||||
if cortn and operation then
|
||||
operation.set:insert(tcp)
|
||||
operation.cortn[tcp] = cortn
|
||||
@ -233,7 +233,7 @@ function wakeup(operation, tcp)
|
||||
kick(operation, tcp)
|
||||
return cortn, coroutine.resume(cortn)
|
||||
-- othrewise, just get scheduler not to do anything
|
||||
else
|
||||
else
|
||||
return nil, true
|
||||
end
|
||||
end
|
||||
@ -249,7 +249,7 @@ end
|
||||
-- step through all active cortns
|
||||
function cometat.__index:step()
|
||||
-- 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)
|
||||
-- for all readable connections, resume their cortns and reschedule
|
||||
-- when they yield back to us
|
||||
@ -260,7 +260,7 @@ function cometat.__index:step()
|
||||
for _, tcp in ipairs(writable) do
|
||||
schedule(wakeup(self.sending, tcp))
|
||||
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
|
||||
local now = socket.gettime()
|
||||
for tcp, stamp in pairs(self.stamp) do
|
||||
@ -271,25 +271,25 @@ function cometat.__index:step()
|
||||
end
|
||||
end
|
||||
|
||||
function cometat.__index:start(func)
|
||||
function cometat.__index:start(func)
|
||||
local cortn = coroutine.create(func)
|
||||
schedule(cortn, coroutine.resume(cortn))
|
||||
end
|
||||
|
||||
function handlert.coroutine()
|
||||
local stamp = {}
|
||||
local dispatcher = {
|
||||
local dispatcher = {
|
||||
stamp = stamp,
|
||||
sending = {
|
||||
name = "sending",
|
||||
set = newset(),
|
||||
cortn = {},
|
||||
name = "sending",
|
||||
set = newset(),
|
||||
cortn = {},
|
||||
stamp = stamp
|
||||
},
|
||||
receiving = {
|
||||
name = "receiving",
|
||||
set = newset(),
|
||||
cortn = {},
|
||||
set = newset(),
|
||||
cortn = {},
|
||||
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
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id$
|
||||
|
@ -17,10 +17,10 @@ local function move(foo, bar)
|
||||
live = data or error == "timeout"
|
||||
data = data or partial
|
||||
local result, error = bar:send(data)
|
||||
if not live or not result then
|
||||
foo:close()
|
||||
if not live or not result then
|
||||
foo:close()
|
||||
bar:close()
|
||||
break
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -51,7 +51,7 @@ for i, v in ipairs(arg) do
|
||||
handler:start(function()
|
||||
move(client, peer)
|
||||
end)
|
||||
-- afte starting new handler, enter in loop sending data from
|
||||
-- afte starting new handler, enter in loop sending data from
|
||||
-- peer to client
|
||||
move(peer, client)
|
||||
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)
|
||||
local rate = got / delta
|
||||
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))
|
||||
else
|
||||
return string.format(elapsed_s, nicesize(got),
|
||||
else
|
||||
return string.format(elapsed_s, nicesize(got),
|
||||
nicesize(rate), nicetime(delta))
|
||||
end
|
||||
end
|
||||
@ -68,18 +68,18 @@ function stats(size)
|
||||
local got = 0
|
||||
return function(chunk)
|
||||
-- elapsed time since start
|
||||
local delta = socket.gettime() - start
|
||||
if chunk then
|
||||
local delta = socket.gettime() - start
|
||||
if chunk then
|
||||
-- total bytes received
|
||||
got = got + string.len(chunk)
|
||||
got = got + string.len(chunk)
|
||||
-- not enough time for estimate
|
||||
if delta > 0.1 then
|
||||
io.stderr:write("\r", gauge(got, delta, size))
|
||||
if delta > 0.1 then
|
||||
io.stderr:write("\r", gauge(got, delta, size))
|
||||
io.stderr:flush()
|
||||
end
|
||||
else
|
||||
else
|
||||
-- close up
|
||||
io.stderr:write("\r", gauge(got, delta), "\n")
|
||||
io.stderr:write("\r", gauge(got, delta), "\n")
|
||||
end
|
||||
return chunk
|
||||
end
|
||||
@ -111,11 +111,11 @@ function getbyftp(u, file)
|
||||
local gett = url.parse(u)
|
||||
gett.sink = save
|
||||
gett.type = "i"
|
||||
local ret, err = ftp.get(gett)
|
||||
local ret, err = ftp.get(gett)
|
||||
if err then print(err) end
|
||||
end
|
||||
|
||||
-- determines the scheme
|
||||
-- determines the scheme
|
||||
function getscheme(u)
|
||||
-- this is an heuristic to solve a common invalid url poblem
|
||||
if not string.find(u, "//") then u = "//" .. u end
|
||||
@ -134,7 +134,7 @@ end
|
||||
|
||||
-- main program
|
||||
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")
|
||||
os.exit(1)
|
||||
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
|
||||
low = math.mod(block, 256)
|
||||
high = (block - low)/256
|
||||
return char(0, OP_ACK, high, low)
|
||||
return char(0, OP_ACK, high, low)
|
||||
end
|
||||
|
||||
local function get_OP(dgram)
|
||||
@ -71,7 +71,7 @@ local function get_ERROR(dgram)
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- The real work
|
||||
-- The real work
|
||||
-----------------------------------------------------------------------------
|
||||
local function tget(gett)
|
||||
local retries, dgram, sent, datahost, dataport, code
|
||||
@ -83,15 +83,15 @@ local function tget(gett)
|
||||
gett.host = try(socket.dns.toip(gett.host))
|
||||
con:settimeout(1)
|
||||
-- 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)
|
||||
retries = 0
|
||||
repeat
|
||||
repeat
|
||||
sent = try(con:sendto(RRQ(path, "octet"), gett.host, gett.port))
|
||||
dgram, datahost, dataport = con:receivefrom()
|
||||
retries = retries + 1
|
||||
until dgram or datahost ~= "timeout" or retries > 5
|
||||
try(dgram, datahost)
|
||||
try(dgram, datahost)
|
||||
-- associate socket with data host/port
|
||||
try(con:setpeername(datahost, dataport))
|
||||
-- default sink
|
||||
@ -110,7 +110,7 @@ local function tget(gett)
|
||||
last = block
|
||||
end
|
||||
-- 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:close())
|
||||
try(sink(nil))
|
||||
@ -118,7 +118,7 @@ local function tget(gett)
|
||||
end
|
||||
-- get the next packet
|
||||
retries = 0
|
||||
repeat
|
||||
repeat
|
||||
sent = try(con:send(ACK(last)))
|
||||
dgram, err = con:receive()
|
||||
retries = retries + 1
|
||||
@ -141,7 +141,7 @@ local function parse(u)
|
||||
end
|
||||
|
||||
local function sget(u)
|
||||
local gett = parse(u)
|
||||
local gett = parse(u)
|
||||
local t = {}
|
||||
gett.sink = ltn12.sink.table(t)
|
||||
tget(gett)
|
||||
|
31
makefile
31
makefile
@ -6,9 +6,9 @@ include config
|
||||
#------
|
||||
# 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_MIME_LUA=$(INSTALL_TOP_LUA)/mime
|
||||
INSTALL_MIME_SHARE=$(INSTALL_TOP_SHARE)/mime
|
||||
INSTALL_MIME_LIB=$(INSTALL_TOP_LIB)/mime
|
||||
|
||||
all clean:
|
||||
@ -17,35 +17,34 @@ all clean:
|
||||
#------
|
||||
# Files to install
|
||||
#
|
||||
TO_SOCKET_LUA:= \
|
||||
socket.lua \
|
||||
TO_SOCKET_SHARE:= \
|
||||
http.lua \
|
||||
url.lua \
|
||||
tp.lua \
|
||||
ftp.lua \
|
||||
smtp.lua
|
||||
|
||||
TO_TOP_LUA:= \
|
||||
ltn12.lua
|
||||
|
||||
TO_MIME_LUA:= \
|
||||
TO_TOP_SHARE:= \
|
||||
$(COMPAT)/compat-5.1.lua \
|
||||
ltn12.lua \
|
||||
socket.lua \
|
||||
mime.lua
|
||||
|
||||
TO_MIME_SHARE:=
|
||||
|
||||
#------
|
||||
# Install LuaSocket according to recommendation
|
||||
#
|
||||
install: all
|
||||
cd src; mkdir -p $(INSTALL_TOP_LUA)
|
||||
cd src; mkdir -p $(INSTALL_TOP_LIB)
|
||||
cd src; $(INSTALL_DATA) $(COMPAT)/compat-5.1.lua $(INSTALL_TOP_LUA)
|
||||
cd src; $(INSTALL_DATA) ltn12.lua $(INSTALL_TOP_LUA)
|
||||
cd src; mkdir -p $(INSTALL_SOCKET_LUA)
|
||||
cd src; mkdir -p $(INSTALL_TOP_SHARE)
|
||||
cd src; $(INSTALL_DATA) $(TO_TOP_SHARE) $(INSTALL_TOP_SHARE)
|
||||
cd src; mkdir -p $(INSTALL_SOCKET_SHARE)
|
||||
cd src; $(INSTALL_DATA) $(TO_SOCKET_SHARE) $(INSTALL_SOCKET_SHARE)
|
||||
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; 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; $(INSTALL_DATA) $(TO_MIME_LUA) $(INSTALL_MIME_LUA)
|
||||
cd src; $(INSTALL_EXEC) $(MIME_SO) $(INSTALL_MIME_LIB)/core.$(EXT)
|
||||
|
||||
#------
|
||||
|
@ -1,13 +1,12 @@
|
||||
#--------------------------------------------------------------------------
|
||||
# Distribution makefile
|
||||
#--------------------------------------------------------------------------
|
||||
|
||||
DIST = luasocket-2.0
|
||||
|
||||
COMPAT = src/compat-5.1r4
|
||||
|
||||
|
||||
TEST = \
|
||||
test/README \
|
||||
test/testclnt.lua \
|
||||
test/testsrvr.lua \
|
||||
test/testsupport.lua
|
||||
@ -33,12 +32,12 @@ ETC = \
|
||||
etc/eol.lua \
|
||||
etc/forward.lua \
|
||||
etc/get.lua \
|
||||
etc/links \
|
||||
etc/lp.lua \
|
||||
etc/qp.lua \
|
||||
etc/tftp.lua
|
||||
|
||||
SRC = \
|
||||
src/makefile \
|
||||
src/auxiliar.c \
|
||||
src/auxiliar.h \
|
||||
src/buffer.c \
|
||||
@ -108,6 +107,7 @@ dist:
|
||||
mkdir -p $(DIST)
|
||||
cp -vf NEW $(DIST)
|
||||
cp -vf LICENSE $(DIST)
|
||||
cp -vf README $(DIST)
|
||||
cp -vf $(MAKE) $(DIST)
|
||||
|
||||
mkdir -p $(DIST)/etc
|
||||
|
@ -16,7 +16,7 @@ function parse(body)
|
||||
return nil, code, message
|
||||
end
|
||||
local data = {}
|
||||
for l in lines do
|
||||
for l in lines do
|
||||
local c = string.sub(l, 1, 1)
|
||||
if c ~= '#' and c ~= '.' then
|
||||
local key, value = socket.skip(2, string.find(l, "(.-)=(.*)"))
|
||||
@ -26,7 +26,7 @@ function parse(body)
|
||||
data[key] = value
|
||||
end
|
||||
end
|
||||
return data, code, message
|
||||
return data, code, message
|
||||
end
|
||||
|
||||
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 body, headers, code = http.get(url)
|
||||
|
||||
if code == 200 then
|
||||
if code == 200 then
|
||||
local data, code, error = parse(body)
|
||||
if not data then
|
||||
if not data then
|
||||
print(error or code)
|
||||
else
|
||||
for i,v in pairs(data) do
|
||||
io.write(i, ': ', v, '\n')
|
||||
for i,v in pairs(data) do
|
||||
io.write(i, ': ', v, '\n')
|
||||
end
|
||||
end
|
||||
else print(error) end
|
||||
|
@ -20,10 +20,10 @@ assert(ip, port)
|
||||
print("Waiting packets on " .. ip .. ":" .. port .. "...")
|
||||
while 1 do
|
||||
dgram, ip, port = udp:receivefrom()
|
||||
if dgram then
|
||||
if dgram then
|
||||
print("Echoing '" .. dgram .. "' to " .. ip .. ":" .. port)
|
||||
udp:sendto(dgram, ip, port)
|
||||
else
|
||||
print(ip)
|
||||
else
|
||||
print(ip)
|
||||
end
|
||||
end
|
||||
|
@ -36,7 +36,8 @@ do
|
||||
return usage()
|
||||
end
|
||||
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')
|
||||
else
|
||||
r,e=lp.query(opt)
|
||||
|
@ -62,24 +62,24 @@ while 1 do
|
||||
if input == server1 or input == server2 then
|
||||
io.write("Waiting for clients\n")
|
||||
local new = input:accept()
|
||||
if new then
|
||||
if new then
|
||||
new:settimeout(1)
|
||||
io.write("Inserting client in set\n")
|
||||
set:insert(new)
|
||||
set:insert(new)
|
||||
end
|
||||
-- it is a client socket
|
||||
else
|
||||
local line, error = input:receive()
|
||||
if error then
|
||||
if error then
|
||||
input:close()
|
||||
io.write("Removing client from set\n")
|
||||
set:remove(input)
|
||||
set:remove(input)
|
||||
else
|
||||
io.write("Broadcasting line '", line, "'\n")
|
||||
writable, error = socket.skip(1, socket.select(nil, set, 1))
|
||||
if not error then
|
||||
for __, output in ipairs(writable) do
|
||||
if output ~= input then
|
||||
if output ~= input then
|
||||
output:send(line .. "\n")
|
||||
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)
|
||||
-- make sure everything gets closed in an exception
|
||||
f.try = socket.newtry(function() f:close() end)
|
||||
return f
|
||||
return f
|
||||
end
|
||||
|
||||
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 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.pasvt = {
|
||||
ip = string.format("%d.%d.%d.%d", a, b, c, d),
|
||||
self.pasvt = {
|
||||
ip = string.format("%d.%d.%d.%d", a, b, c, d),
|
||||
port = p1*256 + p2
|
||||
}
|
||||
if self.server then
|
||||
if self.server then
|
||||
self.server:close()
|
||||
self.server = nil
|
||||
end
|
||||
return self.pasvt.ip, self.pasvt.port
|
||||
return self.pasvt.ip, self.pasvt.port
|
||||
end
|
||||
|
||||
function metat.__index:port(ip, port)
|
||||
self.pasvt = nil
|
||||
if not ip then
|
||||
if not ip then
|
||||
ip, port = self.try(self.tp:getcontrol():getsockname())
|
||||
self.server = self.try(socket.bind(ip, 0))
|
||||
ip, port = self.try(self.server:getsockname())
|
||||
@ -100,11 +100,11 @@ end
|
||||
|
||||
function metat.__index:send(sendt)
|
||||
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
|
||||
if self.pasvt then self:pasvconnect() end
|
||||
-- get the transfer argument and command
|
||||
local argument = sendt.argument or
|
||||
-- get the transfer argument and command
|
||||
local argument = sendt.argument or
|
||||
url.unescape(string.gsub(sendt.path or "", "^[/\\]", ""))
|
||||
if argument == "" then argument = nil end
|
||||
local command = sendt.command or "stor"
|
||||
@ -137,7 +137,7 @@ end
|
||||
function metat.__index:receive(recvt)
|
||||
self.try(self.pasvt or self.server, "need port or pasv first")
|
||||
if self.pasvt then self:pasvconnect() end
|
||||
local argument = recvt.argument or
|
||||
local argument = recvt.argument or
|
||||
url.unescape(string.gsub(recvt.path or "", "^[/\\]", ""))
|
||||
if argument == "" then argument = nil end
|
||||
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.host, "missing hostname")
|
||||
local pat = "^type=(.)$"
|
||||
if t.params then
|
||||
if t.params then
|
||||
t.type = socket.skip(2, string.find(t.params, pat))
|
||||
socket.try(t.type == "a" or t.type == "i",
|
||||
"invalid type '" .. t.type .. "'")
|
||||
@ -229,7 +229,7 @@ local function parse(u)
|
||||
end
|
||||
|
||||
local function sput(u, body)
|
||||
local putt = parse(u)
|
||||
local putt = parse(u)
|
||||
putt.source = ltn12.source.string(body)
|
||||
return tput(putt)
|
||||
end
|
||||
@ -253,7 +253,7 @@ local function tget(gett)
|
||||
end
|
||||
|
||||
local function sget(u)
|
||||
local gett = parse(u)
|
||||
local gett = parse(u)
|
||||
local t = {}
|
||||
gett.sink = ltn12.sink.table(t)
|
||||
tget(gett)
|
||||
|
32
src/http.lua
32
src/http.lua
@ -21,7 +21,7 @@ module("socket.http")
|
||||
-- Program constants
|
||||
-----------------------------------------------------------------------------
|
||||
-- connection timeout in seconds
|
||||
TIMEOUT = 60
|
||||
TIMEOUT = 60
|
||||
-- default port for document retrieval
|
||||
PORT = 80
|
||||
-- user agent field sent in request
|
||||
@ -65,18 +65,18 @@ socket.sourcet["http-chunked"] = function(sock, headers)
|
||||
return base.setmetatable({
|
||||
getfd = function() return sock:getfd() end,
|
||||
dirty = function() return sock:dirty() end
|
||||
}, {
|
||||
}, {
|
||||
__call = function()
|
||||
-- get chunk size, skip extention
|
||||
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)
|
||||
if not size then return nil, "invalid chunk size" end
|
||||
-- was it the last chunk?
|
||||
if size > 0 then
|
||||
if size > 0 then
|
||||
-- if not, get chunk and skip terminating CRLF
|
||||
local chunk, err, part = sock:receive(size)
|
||||
if chunk then sock:receive() end
|
||||
if chunk then sock:receive() end
|
||||
return chunk, err
|
||||
else
|
||||
-- if it was, read trailers into headers table
|
||||
@ -91,7 +91,7 @@ socket.sinkt["http-chunked"] = function(sock)
|
||||
return base.setmetatable({
|
||||
getfd = function() return sock:getfd() end,
|
||||
dirty = function() return sock:dirty() end
|
||||
}, {
|
||||
}, {
|
||||
__call = function(self, chunk, err)
|
||||
if not chunk then return sock:send("0\r\n\r\n") end
|
||||
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:connect(host, port or PORT))
|
||||
-- here everything worked
|
||||
return h
|
||||
return h
|
||||
end
|
||||
|
||||
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))
|
||||
end
|
||||
|
||||
@ -133,7 +133,7 @@ function metat.__index:sendheaders(headers)
|
||||
end
|
||||
|
||||
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
|
||||
-- if we don't know the size in advance, send chunked and hope for the best
|
||||
local mode = "http-chunked"
|
||||
@ -159,7 +159,7 @@ function metat.__index:receivebody(headers, sink, step)
|
||||
local mode = "default" -- connection close
|
||||
if t and t ~= "identity" then mode = "http-chunked"
|
||||
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))
|
||||
end
|
||||
|
||||
@ -185,7 +185,7 @@ local function adjusturi(reqt)
|
||||
end
|
||||
|
||||
local function adjustproxy(reqt)
|
||||
local proxy = reqt.proxy or PROXY
|
||||
local proxy = reqt.proxy or PROXY
|
||||
if proxy then
|
||||
proxy = url.parse(proxy)
|
||||
return proxy.host, proxy.port or 3128
|
||||
@ -292,10 +292,10 @@ function trequest(reqt)
|
||||
local code, headers, status
|
||||
code, status = h:receivestatusline()
|
||||
headers = h:receiveheaders()
|
||||
if shouldredirect(reqt, code, headers) then
|
||||
if shouldredirect(reqt, code, headers) then
|
||||
h:close()
|
||||
return tredirect(reqt, headers.location)
|
||||
elseif shouldauthorize(reqt, code) then
|
||||
elseif shouldauthorize(reqt, code) then
|
||||
h:close()
|
||||
return tauthorize(reqt)
|
||||
elseif shouldreceivebody(reqt, code) then
|
||||
@ -307,12 +307,12 @@ end
|
||||
|
||||
local function srequest(u, body)
|
||||
local t = {}
|
||||
local reqt = {
|
||||
local reqt = {
|
||||
url = u,
|
||||
sink = ltn12.sink.table(t)
|
||||
}
|
||||
if body then
|
||||
reqt.source = ltn12.source.string(body)
|
||||
if body then
|
||||
reqt.source = ltn12.source.string(body)
|
||||
reqt.headers = { ["content-length"] = string.len(body) }
|
||||
reqt.method = "POST"
|
||||
end
|
||||
|
@ -36,19 +36,19 @@ end
|
||||
|
||||
-- chains a bunch of filters together
|
||||
-- (thanks to Wim Couwenberg)
|
||||
function filter.chain(...)
|
||||
function filter.chain(...)
|
||||
local n = table.getn(arg)
|
||||
local top, index = 1, 1
|
||||
local retry = ""
|
||||
return function(chunk)
|
||||
retry = chunk and retry
|
||||
while true do
|
||||
while true do
|
||||
if index == top then
|
||||
chunk = arg[index](chunk)
|
||||
if chunk == "" or top == n then return chunk
|
||||
elseif chunk then index = index + 1
|
||||
else
|
||||
top = top+1
|
||||
else
|
||||
top = top+1
|
||||
index = top
|
||||
end
|
||||
else
|
||||
@ -148,9 +148,9 @@ function source.chain(src, f)
|
||||
last_in, err = src()
|
||||
if err then return nil, err end
|
||||
last_out = f(last_in)
|
||||
if not last_out then
|
||||
if not last_out then
|
||||
if last_in then
|
||||
base.error('filter returned inappropriate nil')
|
||||
base.error('filter returned inappropriate nil')
|
||||
else
|
||||
return nil
|
||||
end
|
||||
@ -159,17 +159,17 @@ function source.chain(src, f)
|
||||
if last_in then last_in = "" end
|
||||
return last_out
|
||||
end
|
||||
else
|
||||
else
|
||||
last_out = f(last_in)
|
||||
if last_out == "" then
|
||||
if last_in == "" then
|
||||
if last_out == "" then
|
||||
if last_in == "" then
|
||||
state = "feeding"
|
||||
else
|
||||
base.error('filter returned ""')
|
||||
base.error('filter returned ""')
|
||||
end
|
||||
elseif not last_out then
|
||||
if last_in then
|
||||
base.error('filter returned inappropriate nil')
|
||||
if last_in then
|
||||
base.error('filter returned inappropriate nil')
|
||||
else
|
||||
return nil
|
||||
end
|
||||
@ -224,7 +224,7 @@ end
|
||||
function sink.file(handle, io_err)
|
||||
if handle then
|
||||
return function(chunk, err)
|
||||
if not chunk then
|
||||
if not chunk then
|
||||
handle:close()
|
||||
return 1
|
||||
else return handle:write(chunk) end
|
||||
@ -248,7 +248,7 @@ function sink.error(err)
|
||||
end
|
||||
end
|
||||
|
||||
-- chains a sink with a filter
|
||||
-- chains a sink with a filter
|
||||
function sink.chain(f, snk)
|
||||
base.assert(f and snk)
|
||||
return function(chunk, err)
|
||||
@ -282,7 +282,7 @@ function pump.all(src, snk, step)
|
||||
step = step or pump.step
|
||||
while true do
|
||||
local ret, err = step(src, snk)
|
||||
if not ret then
|
||||
if not ret then
|
||||
if err then return nil, err
|
||||
else return 1 end
|
||||
end
|
||||
|
@ -10,7 +10,7 @@ function Public.split_message(message_s)
|
||||
if not message.body then
|
||||
string.gsub(message_s, "^\n(.*)", function (b) message.body = b end)
|
||||
end
|
||||
if not message.headers and not message.body then
|
||||
if not message.headers and not message.body then
|
||||
message.headers = message_s
|
||||
end
|
||||
return message.headers or "", message.body or ""
|
||||
|
14
src/mime.lua
14
src/mime.lua
@ -20,10 +20,10 @@ encodet = {}
|
||||
decodet = {}
|
||||
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)
|
||||
return function(name, opt1, opt2)
|
||||
if base.type(name) ~= "string" then
|
||||
if base.type(name) ~= "string" then
|
||||
name, opt1, opt2 = "default", name, opt1
|
||||
end
|
||||
local f = table[name or "nil"]
|
||||
@ -38,7 +38,7 @@ encodet['base64'] = function()
|
||||
end
|
||||
|
||||
encodet['quoted-printable'] = function(mode)
|
||||
return ltn12.filter.cycle(qp, "",
|
||||
return ltn12.filter.cycle(qp, "",
|
||||
(mode == "binary") and "=0D=0A" or "\r\n")
|
||||
end
|
||||
|
||||
@ -56,22 +56,22 @@ local function format(chunk)
|
||||
if chunk == "" then return "''"
|
||||
else return string.len(chunk) end
|
||||
else return "nil" end
|
||||
end
|
||||
end
|
||||
|
||||
-- define the line-wrap filters
|
||||
wrapt['text'] = function(length)
|
||||
length = length or 76
|
||||
return ltn12.filter.cycle(wrp, length, length)
|
||||
return ltn12.filter.cycle(wrp, length, length)
|
||||
end
|
||||
wrapt['base64'] = wrapt['text']
|
||||
wrapt['default'] = wrapt['text']
|
||||
|
||||
wrapt['quoted-printable'] = function()
|
||||
return ltn12.filter.cycle(qpwrp, 76, 76)
|
||||
return ltn12.filter.cycle(qpwrp, 76, 76)
|
||||
end
|
||||
|
||||
-- function that choose the encoding, decoding or wrap algorithm
|
||||
encode = choose(encodet)
|
||||
encode = choose(encodet)
|
||||
decode = choose(decodet)
|
||||
wrap = choose(wrapt)
|
||||
|
||||
|
42
src/smtp.lua
42
src/smtp.lua
@ -27,8 +27,8 @@ TIMEOUT = 60
|
||||
-- default server used to send e-mails
|
||||
SERVER = "localhost"
|
||||
-- default port
|
||||
PORT = 25
|
||||
-- domain used in HELO command and default sendmail
|
||||
PORT = 25
|
||||
-- domain used in HELO command and default sendmail
|
||||
-- If we are under a CGI, try to get from environment
|
||||
DOMAIN = os.getenv("SERVER_NAME") or "localhost"
|
||||
-- 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:command("EHLO", domain or DOMAIN))
|
||||
return socket.skip(1, self.try(self.tp:check("2..")))
|
||||
end
|
||||
end
|
||||
|
||||
function metat.__index:mail(from)
|
||||
self.try(self.tp:command("MAIL", "FROM:" .. from))
|
||||
return self.try(self.tp:check("2.."))
|
||||
end
|
||||
end
|
||||
|
||||
function metat.__index:rcpt(to)
|
||||
self.try(self.tp:command("RCPT", "TO:" .. to))
|
||||
@ -99,7 +99,7 @@ function metat.__index:auth(user, password, ext)
|
||||
end
|
||||
|
||||
-- send message or throw an exception
|
||||
function metat.__index:send(mailt)
|
||||
function metat.__index:send(mailt)
|
||||
self:mail(mailt.from)
|
||||
if base.type(mailt.rcpt) == "table" then
|
||||
for i,v in base.ipairs(mailt.rcpt) do
|
||||
@ -112,14 +112,14 @@ function metat.__index:send(mailt)
|
||||
end
|
||||
|
||||
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))
|
||||
local s = base.setmetatable({tp = tp}, metat)
|
||||
-- make sure tp is closed if we get an exception
|
||||
s.try = socket.newtry(function()
|
||||
s.try = socket.newtry(function()
|
||||
s:close()
|
||||
end)
|
||||
return s
|
||||
return s
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
@ -142,7 +142,7 @@ local function send_headers(headers)
|
||||
for i,v in base.pairs(headers) do
|
||||
h = i .. ': ' .. v .. "\r\n" .. h
|
||||
end
|
||||
coroutine.yield(h)
|
||||
coroutine.yield(h)
|
||||
end
|
||||
|
||||
-- yield multipart message body from a multipart message table
|
||||
@ -151,25 +151,25 @@ local function send_multipart(mesgt)
|
||||
local bd = newboundary()
|
||||
local headers = mesgt.headers or {}
|
||||
headers['content-type'] = headers['content-type'] or 'multipart/mixed'
|
||||
headers['content-type'] = headers['content-type'] ..
|
||||
headers['content-type'] = headers['content-type'] ..
|
||||
'; boundary="' .. bd .. '"'
|
||||
send_headers(headers)
|
||||
-- send preamble
|
||||
if mesgt.body.preamble then
|
||||
coroutine.yield(mesgt.body.preamble)
|
||||
coroutine.yield("\r\n")
|
||||
if mesgt.body.preamble then
|
||||
coroutine.yield(mesgt.body.preamble)
|
||||
coroutine.yield("\r\n")
|
||||
end
|
||||
-- send each part separated by a boundary
|
||||
for i, m in base.ipairs(mesgt.body) do
|
||||
coroutine.yield("\r\n--" .. bd .. "\r\n")
|
||||
send_message(m)
|
||||
end
|
||||
-- send last boundary
|
||||
-- send last boundary
|
||||
coroutine.yield("\r\n--" .. bd .. "--\r\n\r\n")
|
||||
-- send epilogue
|
||||
if mesgt.body.epilogue then
|
||||
coroutine.yield(mesgt.body.epilogue)
|
||||
coroutine.yield("\r\n")
|
||||
if mesgt.body.epilogue then
|
||||
coroutine.yield(mesgt.body.epilogue)
|
||||
coroutine.yield("\r\n")
|
||||
end
|
||||
end
|
||||
|
||||
@ -181,7 +181,7 @@ local function send_source(mesgt)
|
||||
'text/plain; charset="iso-8859-1"'
|
||||
send_headers(headers)
|
||||
-- send body from source
|
||||
while true do
|
||||
while true do
|
||||
local chunk, err = mesgt.body()
|
||||
if err then coroutine.yield(nil, err)
|
||||
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
|
||||
lower[string.lower(i)] = v
|
||||
end
|
||||
lower["date"] = lower["date"] or
|
||||
lower["date"] = lower["date"] or
|
||||
os.date("!%a, %d %b %Y %H:%M:%S ") .. (mesgt.zone or ZONE)
|
||||
lower["x-mailer"] = lower["x-mailer"] or socket._VERSION
|
||||
-- this can't be overriden
|
||||
lower["mime-version"] = "1.0"
|
||||
lower["mime-version"] = "1.0"
|
||||
mesgt.headers = lower
|
||||
end
|
||||
|
||||
@ -225,7 +225,7 @@ function message(mesgt)
|
||||
adjust_headers(mesgt)
|
||||
-- create and return message source
|
||||
local co = coroutine.create(function() send_message(mesgt) end)
|
||||
return function()
|
||||
return function()
|
||||
local ret, a, b = coroutine.resume(co)
|
||||
if ret then return a, b
|
||||
else return nil, a end
|
||||
|
@ -19,7 +19,7 @@ module("socket")
|
||||
function connect(address, port, laddress, lport)
|
||||
local sock, err = socket.tcp()
|
||||
if not sock then return nil, err end
|
||||
if laddress then
|
||||
if laddress then
|
||||
local res, err = sock:bind(laddress, lport, -1)
|
||||
if not res then return nil, err end
|
||||
end
|
||||
@ -65,9 +65,9 @@ sinkt["close-when-done"] = function(sock)
|
||||
return base.setmetatable({
|
||||
getfd = function() return sock:getfd() end,
|
||||
dirty = function() return sock:dirty() end
|
||||
}, {
|
||||
}, {
|
||||
__call = function(self, chunk, err)
|
||||
if not chunk then
|
||||
if not chunk then
|
||||
sock:close()
|
||||
return 1
|
||||
else return sock:send(chunk) end
|
||||
@ -79,7 +79,7 @@ sinkt["keep-open"] = function(sock)
|
||||
return base.setmetatable({
|
||||
getfd = function() return sock:getfd() end,
|
||||
dirty = function() return sock:dirty() end
|
||||
}, {
|
||||
}, {
|
||||
__call = function(self, chunk, err)
|
||||
if chunk then return sock:send(chunk)
|
||||
else return 1 end
|
||||
@ -95,7 +95,7 @@ sourcet["by-length"] = function(sock, length)
|
||||
return base.setmetatable({
|
||||
getfd = function() return sock:getfd() end,
|
||||
dirty = function() return sock:dirty() end
|
||||
}, {
|
||||
}, {
|
||||
__call = function()
|
||||
if length <= 0 then return nil end
|
||||
local size = math.min(socket.BLOCKSIZE, length)
|
||||
@ -112,16 +112,16 @@ sourcet["until-closed"] = function(sock)
|
||||
return base.setmetatable({
|
||||
getfd = function() return sock:getfd() end,
|
||||
dirty = function() return sock:dirty() end
|
||||
}, {
|
||||
}, {
|
||||
__call = function()
|
||||
if done then return nil end
|
||||
local chunk, err, partial = sock:receive(socket.BLOCKSIZE)
|
||||
if not err then return chunk
|
||||
elseif err == "closed" then
|
||||
elseif err == "closed" then
|
||||
sock:close()
|
||||
done = 1
|
||||
return partial
|
||||
else return nil, err end
|
||||
else return nil, err 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)(.?)"))
|
||||
reply = reply .. "\n" .. line
|
||||
-- reply ends with same code
|
||||
until code == current and sep == " "
|
||||
until code == current and sep == " "
|
||||
end
|
||||
return code, reply
|
||||
end
|
||||
@ -49,25 +49,25 @@ function metat.__index:check(ok)
|
||||
local code, reply = get_reply(self.c)
|
||||
if not code then return nil, reply end
|
||||
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
|
||||
if string.find(code, v) then
|
||||
return base.tonumber(code), reply
|
||||
if string.find(code, v) then
|
||||
return base.tonumber(code), reply
|
||||
end
|
||||
end
|
||||
return nil, reply
|
||||
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
|
||||
end
|
||||
else return ok(base.tonumber(code), reply) end
|
||||
end
|
||||
|
||||
function metat.__index:command(cmd, arg)
|
||||
if arg then
|
||||
if arg then
|
||||
return self.c:send(cmd .. " " .. arg.. "\r\n")
|
||||
else
|
||||
return self.c:send(cmd .. "\r\n")
|
||||
else
|
||||
return self.c:send(cmd .. "\r\n")
|
||||
end
|
||||
end
|
||||
|
||||
@ -114,8 +114,8 @@ function connect(host, port, create, timeout)
|
||||
if not c then return nil, e end
|
||||
c:settimeout(timeout or TIMEOUT)
|
||||
local r, e = c:connect(host, port)
|
||||
if not r then
|
||||
c:close()
|
||||
if not r then
|
||||
c:close()
|
||||
return nil, e
|
||||
end
|
||||
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
|
||||
-- Input
|
||||
-- Input
|
||||
-- s: binary string to be encoded
|
||||
-- Returns
|
||||
-- escaped representation of string binary
|
||||
@ -33,8 +33,8 @@ end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Protects a path segment, to prevent it from interfering with the
|
||||
-- url parsing.
|
||||
-- Input
|
||||
-- url parsing.
|
||||
-- Input
|
||||
-- s: binary string to be encoded
|
||||
-- Returns
|
||||
-- escaped representation of string binary
|
||||
@ -50,12 +50,12 @@ end
|
||||
-- these are allowed withing a path segment, along with alphanum
|
||||
-- other characters must be escaped
|
||||
local segment_set = make_set {
|
||||
"-", "_", ".", "!", "~", "*", "'", "(",
|
||||
"-", "_", ".", "!", "~", "*", "'", "(",
|
||||
")", ":", "@", "&", "=", "+", "$", ",",
|
||||
}
|
||||
|
||||
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
|
||||
else return string.format("%%%02x", string.byte(c)) end
|
||||
end)
|
||||
@ -63,7 +63,7 @@ end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Encodes a string into its escaped hexadecimal representation
|
||||
-- Input
|
||||
-- Input
|
||||
-- s: binary string to be encoded
|
||||
-- Returns
|
||||
-- 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
|
||||
local path = string.gsub(base_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
|
||||
end)
|
||||
path = string.gsub(path, "/%.$", "/")
|
||||
local reduced
|
||||
local reduced
|
||||
while reduced ~= path do
|
||||
reduced = path
|
||||
path = string.gsub(reduced, "([^/]*/%.%./)", function (s)
|
||||
@ -116,7 +116,7 @@ end
|
||||
-- Returns
|
||||
-- table with the following fields, where RFC naming conventions have
|
||||
-- been preserved:
|
||||
-- scheme, authority, userinfo, user, password, host, port,
|
||||
-- scheme, authority, userinfo, user, password, host, port,
|
||||
-- path, params, query, fragment
|
||||
-- Obs:
|
||||
-- the leading '/' in {/<path>} is considered part of <path>
|
||||
@ -130,26 +130,26 @@ function parse(url, default)
|
||||
-- remove whitespace
|
||||
-- url = string.gsub(url, "%s", "")
|
||||
-- get fragment
|
||||
url = string.gsub(url, "#(.*)$", function(f)
|
||||
parsed.fragment = f
|
||||
url = string.gsub(url, "#(.*)$", function(f)
|
||||
parsed.fragment = f
|
||||
return ""
|
||||
end)
|
||||
-- get scheme
|
||||
url = string.gsub(url, "^([%w][%w%+%-%.]*)%:",
|
||||
url = string.gsub(url, "^([%w][%w%+%-%.]*)%:",
|
||||
function(s) parsed.scheme = s; return "" end)
|
||||
-- get authority
|
||||
url = string.gsub(url, "^//([^/]*)", function(n)
|
||||
parsed.authority = n
|
||||
url = string.gsub(url, "^//([^/]*)", function(n)
|
||||
parsed.authority = n
|
||||
return ""
|
||||
end)
|
||||
-- get query stringing
|
||||
url = string.gsub(url, "%?(.*)", function(q)
|
||||
parsed.query = q
|
||||
url = string.gsub(url, "%?(.*)", function(q)
|
||||
parsed.query = q
|
||||
return ""
|
||||
end)
|
||||
-- get params
|
||||
url = string.gsub(url, "%;(.*)", function(p)
|
||||
parsed.params = p
|
||||
url = string.gsub(url, "%;(.*)", function(p)
|
||||
parsed.params = p
|
||||
return ""
|
||||
end)
|
||||
-- path is whatever was left
|
||||
@ -158,14 +158,14 @@ function parse(url, default)
|
||||
if not authority then return parsed end
|
||||
authority = string.gsub(authority,"^([^@]*)@",
|
||||
function(u) parsed.userinfo = u; return "" end)
|
||||
authority = string.gsub(authority, ":([^:]*)$",
|
||||
authority = string.gsub(authority, ":([^:]*)$",
|
||||
function(p) parsed.port = p; return "" end)
|
||||
if authority ~= "" then parsed.host = authority end
|
||||
local userinfo = parsed.userinfo
|
||||
if not userinfo then return parsed end
|
||||
userinfo = string.gsub(userinfo, ":([^:]*)$",
|
||||
userinfo = string.gsub(userinfo, ":([^:]*)$",
|
||||
function(p) parsed.password = p; return "" end)
|
||||
parsed.user = userinfo
|
||||
parsed.user = userinfo
|
||||
return parsed
|
||||
end
|
||||
|
||||
@ -189,8 +189,8 @@ function build(parsed)
|
||||
local userinfo = parsed.userinfo
|
||||
if parsed.user then
|
||||
userinfo = parsed.user
|
||||
if parsed.password then
|
||||
userinfo = userinfo .. ":" .. parsed.password
|
||||
if parsed.password then
|
||||
userinfo = userinfo .. ":" .. parsed.password
|
||||
end
|
||||
end
|
||||
if userinfo then authority = userinfo .. "@" .. authority end
|
||||
@ -233,8 +233,8 @@ function absolute(base_url, relative_url)
|
||||
relative_parsed.query = base_parsed.query
|
||||
end
|
||||
end
|
||||
else
|
||||
relative_parsed.path = absolute_path(base_parsed.path or "",
|
||||
else
|
||||
relative_parsed.path = absolute_path(base_parsed.path or "",
|
||||
relative_parsed.path)
|
||||
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);
|
||||
tv.tv_sec = (int) t;
|
||||
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);
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user