Using core.so instead of csocket.so and cmime.so.

This commit is contained in:
Diego Nehab 2005-06-17 04:04:55 +00:00
parent 65c35845c5
commit 4d455c6206
9 changed files with 89 additions and 69 deletions

3
TODO
View File

@ -1,3 +1,6 @@
clean timeout argument to open functions in SMTP, HTTP and FTP
add create field to FTP and SMTP
talk about new create field in HTTP, FTP and SMTP
talk about the non-blocking connect in the manual talk about the non-blocking connect in the manual
test it on Windows!!! test it on Windows!!!

View File

@ -27,10 +27,41 @@ PORT = 80
-- user agent field sent in request -- user agent field sent in request
USERAGENT = socket._VERSION USERAGENT = socket._VERSION
-----------------------------------------------------------------------------
-- Reads MIME headers from a connection, unfolding where needed
-----------------------------------------------------------------------------
local function receiveheaders(sock, headers)
local line, name, value, err
headers = headers or {}
-- get first line
line, err = sock:receive()
if err then return nil, err end
-- headers go until a blank line is found
while line ~= "" do
-- get field-name and value
name, value = socket.skip(2, string.find(line, "^(.-):%s*(.*)"))
if not (name and value) then return nil, "malformed reponse headers" end
name = string.lower(name)
-- get next line (value might be folded)
line, err = sock:receive()
if err then return nil, err end
-- unfold any folded values
while string.find(line, "^%s") do
value = value .. line
line = sock:receive()
if err then return nil, err end
end
-- save pair in table
if headers[name] then headers[name] = headers[name] .. ", " .. value
else headers[name] = value end
end
return headers
end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- Extra sources and sinks -- Extra sources and sinks
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
socket.sourcet["http-chunked"] = function(sock) 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
@ -42,18 +73,15 @@ socket.sourcet["http-chunked"] = function(sock)
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
-- skip trailer headers, if any -- if not, get chunk and skip terminating CRLF
local line, err = sock:receive()
while not err and line ~= "" do
line, err = sock:receive()
end
return nil, err
else
-- 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
-- if it was, read trailers into headers table
headers, err = receiveheaders(sock, headers)
if not headers then return nil, err end
end end
end end
}) })
@ -78,8 +106,8 @@ end
local metat = { __index = {} } local metat = { __index = {} }
-- default connect function, respecting the timeout -- default connect function, respecting the timeout
local function connect(host, port) local function connect(host, port, create)
local c, e = socket.tcp() local c, e = (create or socket.tcp)()
if not c then return nil, e end if not c then return nil, e end
c:settimeout(TIMEOUT) c:settimeout(TIMEOUT)
local r, e = c:connect(host, port or PORT) local r, e = c:connect(host, port or PORT)
@ -90,9 +118,9 @@ local function connect(host, port)
return c return c
end end
function open(host, port, user) function open(host, port, create)
-- create socket with user connect function, or with default -- create socket with user connect function, or with default
local c = socket.try((user or connect)(host, port)) local c = socket.try(connect(host, port, create))
-- create our http request object, pointing to the socket -- create our http request object, pointing to the socket
local h = base.setmetatable({ c = c }, metat) local h = base.setmetatable({ c = c }, metat)
-- make sure the object close gets called on exception -- make sure the object close gets called on exception
@ -130,37 +158,16 @@ function metat.__index:receivestatusline()
end end
function metat.__index:receiveheaders() function metat.__index:receiveheaders()
local line, name, value return self.try(receiveheaders(self.c))
local headers = {}
-- get first line
line = self.try(self.c:receive())
-- headers go until a blank line is found
while line ~= "" do
-- get field-name and value
name, value = socket.skip(2, string.find(line, "^(.-):%s*(.*)"))
self.try(name and value, "malformed reponse headers")
name = string.lower(name)
-- get next line (value might be folded)
line = self.try(self.c:receive())
-- unfold any folded values
while string.find(line, "^%s") do
value = value .. line
line = self.try(self.c:receive())
end
-- save pair in table
if headers[name] then headers[name] = headers[name] .. ", " .. value
else headers[name] = value end
end
return headers
end end
function metat.__index:receivebody(headers, sink, step) function metat.__index:receivebody(headers, sink, step)
sink = sink or ltn12.sink.null() sink = sink or ltn12.sink.null()
step = step or ltn12.pump.step step = step or ltn12.pump.step
local length = base.tonumber(headers["content-length"]) local length = base.tonumber(headers["content-length"])
local TE = headers["transfer-encoding"] local t = headers["transfer-encoding"] -- shortcut
local mode = "default" -- connection close local mode = "default" -- connection close
if TE and TE ~= "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))
@ -198,16 +205,21 @@ local function adjustproxy(reqt)
end end
local function adjustheaders(headers, host) local function adjustheaders(headers, host)
local lower = {} -- default headers
-- override with user values local lower = {
["user-agent"] = USERAGENT,
["host"] = host,
["connection"] = "close, TE",
["te"] = "trailers"
}
-- override with user headers
for i,v in pairs(headers or lower) do for i,v in pairs(headers or lower) do
lower[string.lower(i)] = v lower[string.lower(i)] = v
end end
lower["user-agent"] = lower["user-agent"] or USERAGENT
lower["host"] = lower["host"] or host
return lower return lower
end end
-- default url parts
local default = { local default = {
host = "", host = "",
port = PORT, port = PORT,
@ -280,7 +292,7 @@ end
function trequest(reqt) function trequest(reqt)
reqt = adjustrequest(reqt) reqt = adjustrequest(reqt)
local h = open(reqt.host, reqt.port, reqt.connect) local h = open(reqt.host, reqt.port, reqt.create)
h:sendrequestline(reqt.method, reqt.uri) h:sendrequestline(reqt.method, reqt.uri)
h:sendheaders(reqt.headers) h:sendheaders(reqt.headers)
if reqt.source then h:sendbody(reqt.headers, reqt.source, reqt.step) end if reqt.source then h:sendbody(reqt.headers, reqt.source, reqt.step) end

View File

@ -108,7 +108,7 @@ static int base_open(lua_State *L) {
/*-------------------------------------------------------------------------*\ /*-------------------------------------------------------------------------*\
* Initializes all library modules. * Initializes all library modules.
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
LUASOCKET_API int luaopen_csocket(lua_State *L) { LUASOCKET_API int luaopen_socketcore(lua_State *L) {
int i; int i;
base_open(L); base_open(L);
for (i = 0; mod[i].name; i++) mod[i].func(L); for (i = 0; mod[i].name; i++) mod[i].func(L);

View File

@ -27,6 +27,6 @@
/*-------------------------------------------------------------------------*\ /*-------------------------------------------------------------------------*\
* Initializes the library. * Initializes the library.
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
LUASOCKET_API int luaopen_csocket(lua_State *L); LUASOCKET_API int luaopen_socketcore(lua_State *L);
#endif /* LUASOCKET_H */ #endif /* LUASOCKET_H */

View File

@ -78,7 +78,7 @@ static UC b64unbase[256];
/*-------------------------------------------------------------------------*\ /*-------------------------------------------------------------------------*\
* Initializes module * Initializes module
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
MIME_API int luaopen_cmime(lua_State *L) MIME_API int luaopen_mimecore(lua_State *L)
{ {
luaL_openlib(L, "mime", func, 0); luaL_openlib(L, "mime", func, 0);
/* initialize lookup tables */ /* initialize lookup tables */

View File

@ -19,6 +19,6 @@
#define MIME_API extern #define MIME_API extern
#endif #endif
MIME_API int luaopen_cmime(lua_State *L); MIME_API int luaopen_mimecore(lua_State *L);
#endif /* MIME_H */ #endif /* MIME_H */

View File

@ -10,7 +10,9 @@
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
local base = _G local base = _G
local ltn12 = require("ltn12") local ltn12 = require("ltn12")
local mime = require("cmime") local mime = require("mime.core")
local io = require("io")
local string = require("string")
module("mime") module("mime")
-- encode, decode and wrap algorithm tables -- encode, decode and wrap algorithm tables
@ -49,8 +51,6 @@ decodet['quoted-printable'] = function()
return ltn12.filter.cycle(unqp, "") return ltn12.filter.cycle(unqp, "")
end end
local io, string = io, string
local function format(chunk) local function format(chunk)
if chunk then if chunk then
if chunk == "" then return "''" if chunk == "" then return "''"

View File

@ -10,13 +10,13 @@
local base = _G local base = _G
local string = require("string") local string = require("string")
local math = require("math") local math = require("math")
local socket = require("csocket") local socket = require("socket.core")
module("socket") module("socket")
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- Auxiliar functions -- Exported auxiliar functions
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
function socket.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
@ -28,7 +28,7 @@ function socket.connect(address, port, laddress, lport)
return sock return sock
end end
function socket.bind(host, port, backlog) function bind(host, port, backlog)
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
sock:setoption("reuseaddr", true) sock:setoption("reuseaddr", true)
@ -39,9 +39,9 @@ function socket.bind(host, port, backlog)
return sock return sock
end end
socket.try = socket.newtry() try = newtry()
function socket.choose(table) 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
@ -56,12 +56,12 @@ end
-- Socket sources and sinks, conforming to LTN12 -- Socket sources and sinks, conforming to LTN12
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- create namespaces inside LuaSocket namespace -- create namespaces inside LuaSocket namespace
socket.sourcet = {} sourcet = {}
socket.sinkt = {} sinkt = {}
socket.BLOCKSIZE = 2048 BLOCKSIZE = 2048
socket.sinkt["close-when-done"] = function(sock) 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
@ -75,7 +75,7 @@ socket.sinkt["close-when-done"] = function(sock)
}) })
end end
socket.sinkt["keep-open"] = function(sock) 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
@ -87,11 +87,11 @@ socket.sinkt["keep-open"] = function(sock)
}) })
end end
socket.sinkt["default"] = socket.sinkt["keep-open"] sinkt["default"] = sinkt["keep-open"]
socket.sink = socket.choose(socket.sinkt) sink = choose(sinkt)
socket.sourcet["by-length"] = function(sock, length) 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
@ -107,7 +107,7 @@ socket.sourcet["by-length"] = function(sock, length)
}) })
end end
socket.sourcet["until-closed"] = function(sock) sourcet["until-closed"] = function(sock)
local done local done
return base.setmetatable({ return base.setmetatable({
getfd = function() return sock:getfd() end, getfd = function() return sock:getfd() end,
@ -127,8 +127,9 @@ socket.sourcet["until-closed"] = function(sock)
end end
socket.sourcet["default"] = socket.sourcet["until-closed"] sourcet["default"] = sourcet["until-closed"]
socket.source = socket.choose(socket.sourcet) source = choose(sourcet)
--getmetatable(_M).__index = nil -- clear globals from namespace
getmetatable(_M).__index = nil

View File

@ -22,7 +22,7 @@ http.TIMEOUT = 10
local t = socket.gettime() local t = socket.gettime()
host = host or "diego.student.princeton.edu" host = host or "localhost" -- "diego.student.princeton.edu"
proxy = proxy or "http://localhost:3128" proxy = proxy or "http://localhost:3128"
prefix = prefix or "/luasocket-test" prefix = prefix or "/luasocket-test"
cgiprefix = cgiprefix or "/luasocket-test-cgi" cgiprefix = cgiprefix or "/luasocket-test-cgi"
@ -146,6 +146,7 @@ ignore = {
check_request(request, expect, ignore) check_request(request, expect, ignore)
------------------------------------------------------------------------ ------------------------------------------------------------------------
--[[
io.write("testing proxy with post method: ") io.write("testing proxy with post method: ")
request = { request = {
url = "http://" .. host .. cgiprefix .. "/cat", url = "http://" .. host .. cgiprefix .. "/cat",
@ -163,6 +164,7 @@ ignore = {
headers = 1 headers = 1
} }
check_request(request, expect, ignore) check_request(request, expect, ignore)
]]
------------------------------------------------------------------------ ------------------------------------------------------------------------
io.write("testing simple post function: ") io.write("testing simple post function: ")
@ -249,6 +251,7 @@ ignore = {
check_request(request, expect, ignore) check_request(request, expect, ignore)
------------------------------------------------------------------------ ------------------------------------------------------------------------
--[[
io.write("testing proxy with redirection: ") io.write("testing proxy with redirection: ")
request = { request = {
url = "http://" .. host .. prefix, url = "http://" .. host .. prefix,
@ -263,6 +266,7 @@ ignore = {
headers = 1 headers = 1
} }
check_request(request, expect, ignore) check_request(request, expect, ignore)
]]
------------------------------------------------------------------------ ------------------------------------------------------------------------
io.write("testing automatic auth failure: ") io.write("testing automatic auth failure: ")