diff --git a/TODO b/TODO index 69cfc6b..33e9a43 100644 --- a/TODO +++ b/TODO @@ -1,52 +1,31 @@ ajeitar os README.* -ajeitar select. upvalue nao tem nada a ver... -make sure filter.chain fails gracefully. -ajeitar o manual sobre select, mais liberal agora -falar sobre o novo esquema de namespace -tirar socket.url socket.ftp etc do manual. agora os namespaces estao -liberados. ajeitar as referencias a RFCS e LTNS em todos os arquivos. -proxy no ftp -ajeitar < e-mail > no smtp? -ajeitar referencias a LTN12 nos manuais make sure sockets are closed when exceptions are raised -falar sobre encodet/wrapt/decodet no manual sobre mime - -RECEIVE MUDOU!!! (partial stuff) COLOCAR NO MANUAL. -HTTP.lua mudou bastante também. -pump.step usado em todo mundo que recebe source ou sink - -sources ans sinks are always simple in http and ftp and smtp -expose encode/decode tables to provide extensibility for mime module -use coroutines instead of fancy filters - check garbage collection in test*.lua -add socket.TIMEOUT to be default timeout? manual - compatibility: select sets are associative - add socket.connect and socket.bind to the manual - say what a nil callback does for http + * compatibility: select sets are associative + * add socket.connect and socket.bind to the manual + * add shutdown + * add gethostname check all occurences of it's - - add shutdown - - add gethostname - the need of a content-length header in the post method... - notice the change in callback conventions - the callback.lua module and the new mime module. - escape and unescape in url, not in code! - add timeout and proxy to request table - change stay to redirect - socket.time and socket.sleep - - connect with timeout + * the need of a content-length header in the post method... + * notice the change in callback conventions + * the callback.lua module and the new mime module. + * escape and unescape in url, not in code! + * add timeout and proxy to request table + * change stay to redirect + * socket.time and socket.sleep + * - connect with timeout local connect - add thanks to 'carlos cassino' and 'david burgess' - add new ip- options and reuseaddr option - - add listen to manual - bind method doesn't do listen anymore - bind doesn't turn an object into a server object: listen does. + * add thanks to 'carlos cassino' and 'david burgess' + * add new ip- options and reuseaddr option + * - add listen to manual + * bind method doesn't do listen anymore + * bind doesn't turn an object into a server object: listen does. tests checar todos os metodos @@ -59,9 +38,6 @@ wrp can't break lines in the middle of a line break. add comments into each C module. testar os options! -use gethostname it in SMTP - -make sure modules know if their dependencies are there. Read about 250-ENHANCEDSTATUSCODES @@ -108,6 +84,12 @@ Ajeitar o protocolo da luaopen_socket()... sei l these are done -------------- +* tirar socket.url socket.ftp etc do manual. agora os namespaces + estao liberados. +* falar sobre o novo esquema de namespace +* ajeitar o manual sobre select, mais liberal agora +* make sure filter.chain fails gracefully. +* ajeitar select. upvalue nao tem nada a ver... * should be interrupt-safe * notice the change in callback conventions * new mime module replacing old code module (faster, more functionality) @@ -161,3 +143,15 @@ these are done * change all modules to use the new namespace scheme * write some utilities that use the code.lua module and put them * in etc, modify the README.etc file and makefile.dist (eol.lua is done) +* proxy no ftp? no +* ajeitar < e-mail > no smtp? no +* ajeitar referencias a LTN12 nos manuais +* RECEIVE MUDOU!!! (partial stuff) COLOCAR NO MANUAL. +* HTTP.lua mudou bastante também. +* falar sobre encodet/wrapt/decodet no manual sobre mime? no. +* pump.step usado em todo mundo que recebe source ou sink +* sources ans sinks are always simple in http and ftp and smtp +* expose encode/decode tables to provide extensibility for mime module +* use coroutines instead of fancy filters +* add socket.TIMEOUT to be default timeout? no. +* use gethostname it in SMTP diff --git a/etc/tftp.lua b/etc/tftp.lua index 4113034..5238de0 100644 --- a/etc/tftp.lua +++ b/etc/tftp.lua @@ -2,13 +2,20 @@ -- TFTP support for the Lua language -- LuaSocket toolkit. -- Author: Diego Nehab --- Conforming to: RFC 783, LTN7 -- RCS ID: $Id$ ----------------------------------------------------------------------------- -local Public, Private = {}, {} -local socket = _G[LUASOCKET_LIBNAME] -- get LuaSocket namespace -socket.tftp = Public -- create tftp sub namespace +----------------------------------------------------------------------------- +-- Load required files +----------------------------------------------------------------------------- +local socket = require("socket") +local ltn12 = require("ltn12") +local url = require("url") + +----------------------------------------------------------------------------- +-- Setup namespace +----------------------------------------------------------------------------- +_LOADED["tftp"] = getfenv(1) ----------------------------------------------------------------------------- -- Program constants @@ -16,33 +23,33 @@ socket.tftp = Public -- create tftp sub namespace local char = string.char local byte = string.byte -Public.PORT = 69 -Private.OP_RRQ = 1 -Private.OP_WRQ = 2 -Private.OP_DATA = 3 -Private.OP_ACK = 4 -Private.OP_ERROR = 5 -Private.OP_INV = {"RRQ", "WRQ", "DATA", "ACK", "ERROR"} +PORT = 69 +local OP_RRQ = 1 +local OP_WRQ = 2 +local OP_DATA = 3 +local OP_ACK = 4 +local OP_ERROR = 5 +local OP_INV = {"RRQ", "WRQ", "DATA", "ACK", "ERROR"} ----------------------------------------------------------------------------- -- Packet creation functions ----------------------------------------------------------------------------- -function Private.RRQ(source, mode) - return char(0, Private.OP_RRQ) .. source .. char(0) .. mode .. char(0) +local function RRQ(source, mode) + return char(0, OP_RRQ) .. source .. char(0) .. mode .. char(0) end -function Private.WRQ(source, mode) - return char(0, Private.OP_RRQ) .. source .. char(0) .. mode .. char(0) +local function WRQ(source, mode) + return char(0, OP_RRQ) .. source .. char(0) .. mode .. char(0) end -function Private.ACK(block) +local function ACK(block) local low, high low = math.mod(block, 256) high = (block - low)/256 - return char(0, Private.OP_ACK, high, low) + return char(0, OP_ACK, high, low) end -function Private.get_OP(dgram) +local function get_OP(dgram) local op = byte(dgram, 1)*256 + byte(dgram, 2) return op end @@ -50,13 +57,13 @@ end ----------------------------------------------------------------------------- -- Packet analysis functions ----------------------------------------------------------------------------- -function Private.split_DATA(dgram) +local function split_DATA(dgram) local block = byte(dgram, 3)*256 + byte(dgram, 4) local data = string.sub(dgram, 5) return block, data end -function Private.get_ERROR(dgram) +local function get_ERROR(dgram) local code = byte(dgram, 3)*256 + byte(dgram, 4) local msg _,_, msg = string.find(dgram, "(.*)\000", 5) @@ -64,68 +71,81 @@ function Private.get_ERROR(dgram) end ----------------------------------------------------------------------------- --- Downloads and returns a file pointed to by url +-- High level TFTP API ----------------------------------------------------------------------------- -function Public.get(url) - local parsed = socket.url.parse(url, { - host = "", - port = Public.PORT, - path ="/", - scheme = "tftp" - }) - if parsed.scheme ~= "tftp" then - return nil, string.format("unknown scheme '%s'", parsed.scheme) - end +local function tget(gett) local retries, dgram, sent, datahost, dataport, code - local cat = socket.concat.create() local last = 0 - local udp, err = socket.udp() - if not udp then return nil, err end + local con = socket.try(socket.udp()) -- convert from name to ip if needed - parsed.host = socket.dns.toip(parsed.host) - udp:settimeout(1) + gett.host = socket.try(socket.dns.toip(gett.host)) + con:settimeout(1) -- first packet gives data host/port to be used for data transfers retries = 0 repeat - sent, err = udp:sendto(Private.RRQ(parsed.path, "octet"), - parsed.host, parsed.port) - if err then return nil, err end - dgram, datahost, dataport = udp:receivefrom() + sent = socket.try(con:sendto(RRQ(gett.path, "octet"), + gett.host, gett.port)) + dgram, datahost, dataport = con:receivefrom() retries = retries + 1 until dgram or datahost ~= "timeout" or retries > 5 - if not dgram then return nil, datahost end + socket.try(dgram, datahost) -- associate socket with data host/port - udp:setpeername(datahost, dataport) + socket.try(con:setpeername(datahost, dataport)) + -- default sink + local sink = gett.sink or ltn12.sink.null() -- process all data packets while 1 do -- decode packet - code = Private.get_OP(dgram) - if code == Private.OP_ERROR then - return nil, Private.get_ERROR(dgram) - end - if code ~= Private.OP_DATA then - return nil, "unhandled opcode " .. code - end + code = get_OP(dgram) + socket.try(code ~= OP_ERROR, get_ERROR(dgram)) + socket.try(code == OP_DATA, "unhandled opcode " .. code) -- get data packet parts - local block, data = Private.split_DATA(dgram) + local block, data = split_DATA(dgram) -- if not repeated, write if block == last+1 then - cat:addstring(data) + socket.try(sink(data)) last = block end -- last packet brings less than 512 bytes of data if string.len(data) < 512 then - sent, err = udp:send(Private.ACK(block)) - return cat:getresult() + socket.try(con:send(ACK(block))) + socket.try(con:close()) + socket.try(sink(nil)) + return 1 end -- get the next packet retries = 0 repeat - sent, err = udp:send(Private.ACK(last)) - if err then return err end - dgram, err = udp:receive() + sent = socket.try(con:send(ACK(last))) + dgram, err = con:receive() retries = retries + 1 until dgram or err ~= "timeout" or retries > 5 - if not dgram then return err end + socket.try(dgram, err) end end + +local default = { + port = PORT, + path ="/", + scheme = "tftp" +} + +local function parse(u) + local t = socket.try(url.parse(u, default)) + socket.try(t.scheme == "tftp", "invalid scheme '" .. t.scheme .. "'") + socket.try(t.host, "invalid host") + return t +end + +local function sget(u) + local gett = parse(u) + local t = {} + gett.sink = ltn12.sink.table(t) + tget(gett) + return table.concat(t) +end + +get = socket.protect(function(gett) + if type(gett) == "string" then return sget(gett) + else return tget(gett) end +end) diff --git a/samples/cddb.lua b/samples/cddb.lua index 0ceba09..aefa04e 100644 --- a/samples/cddb.lua +++ b/samples/cddb.lua @@ -32,7 +32,7 @@ end local host = socket.dns.gethostname() 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, error = http.get(url) +local body, headers, code = http.get(url) if code == 200 then local data, code, error = parse(body) diff --git a/src/except.c b/src/except.c index c9eb20e..0482e1c 100644 --- a/src/except.c +++ b/src/except.c @@ -1,12 +1,22 @@ +/*=========================================================================*\ +* Simple exception support +* LuaSocket toolkit +* +* RCS ID: $Id$ +\*=========================================================================*/ #include #include #include "except.h" +/*=========================================================================*\ +* Internal function prototypes. +\*=========================================================================*/ static int global_try(lua_State *L); static int global_protect(lua_State *L); static int protected(lua_State *L); +/* except functions */ static luaL_reg func[] = { {"try", global_try}, {"protect", global_protect}, diff --git a/src/ftp.lua b/src/ftp.lua index c130d1a..87a1e4e 100644 --- a/src/ftp.lua +++ b/src/ftp.lua @@ -2,7 +2,6 @@ -- FTP support for the Lua language -- LuaSocket toolkit. -- Author: Diego Nehab --- Conforming to: RFC 959, LTN7 -- RCS ID: $Id$ ----------------------------------------------------------------------------- @@ -244,5 +243,3 @@ get = socket.protect(function(gett) if type(gett) == "string" then return sget(gett) else return tget(gett) end end) - -return ftp diff --git a/src/http.lua b/src/http.lua index 129b562..8f3fdb9 100644 --- a/src/http.lua +++ b/src/http.lua @@ -2,7 +2,6 @@ -- HTTP/1.1 client support for the Lua language. -- LuaSocket toolkit. -- Author: Diego Nehab --- Conforming to RFC 2616 -- RCS ID: $Id$ ----------------------------------------------------------------------------- @@ -23,7 +22,7 @@ _LOADED["http"] = getfenv(1) -- Program constants ----------------------------------------------------------------------------- -- connection timeout in seconds -TIMEOUT = 4 +TIMEOUT = 60 -- default port for document retrieval PORT = 80 -- user agent field sent in request @@ -146,7 +145,7 @@ end local function adjustrequest(reqt) -- parse url with default fields - local parsed = url.parse(reqt.url, { + local parsed = url.parse(reqt.url or "", { host = "", port = PORT, path ="/", @@ -258,5 +257,3 @@ post = socket.protect(function(u, body) return (table.getn(t) > 0 or nil) and table.concat(t), respt.headers, respt.code end) - -return http diff --git a/src/ltn12.lua b/src/ltn12.lua index 6228247..bb527bd 100644 --- a/src/ltn12.lua +++ b/src/ltn12.lua @@ -254,5 +254,3 @@ function pump.all(src, snk, step) if not ret then return not err, err end end end - -return ltn12 diff --git a/src/mime.c b/src/mime.c index 5750714..825b666 100644 --- a/src/mime.c +++ b/src/mime.c @@ -1,5 +1,5 @@ /*=========================================================================*\ -* Encoding support functions +* MIME support functions * LuaSocket toolkit * * RCS ID: $Id$ @@ -653,7 +653,7 @@ static int mime_global_eol(lua_State *L) const char *marker = luaL_optstring(L, 3, CRLF); luaL_Buffer buffer; luaL_buffinit(L, &buffer); - /* if the last character was a candidate, we output a new line */ + /* end of input blackhole */ if (!input) { lua_pushnil(L); lua_pushnumber(L, 0); diff --git a/src/mime.h b/src/mime.h index b82d61a..be16920 100644 --- a/src/mime.h +++ b/src/mime.h @@ -1,7 +1,7 @@ #ifndef MIME_H #define MIME_H /*=========================================================================*\ -* Mime support functions +* MIME support functions * LuaSocket toolkit * * This module provides functions to implement transfer content encodings diff --git a/src/mime.lua b/src/mime.lua index 000404f..4fade3b 100644 --- a/src/mime.lua +++ b/src/mime.lua @@ -73,5 +73,3 @@ wrap = choose(wrapt) function normalize(marker) return ltn12.filter.cycle(eol, 0, marker) end - -return mime diff --git a/src/options.c b/src/options.c index 972844f..c9e69f0 100644 --- a/src/options.c +++ b/src/options.c @@ -1,3 +1,9 @@ +/*=========================================================================*\ +* Common option interface +* LuaSocket toolkit +* +* RCS ID: $Id$ +\*=========================================================================*/ #include #include @@ -5,6 +11,10 @@ #include "options.h" #include "inet.h" + +/*=========================================================================*\ +* Internal functions prototypes +\*=========================================================================*/ static int opt_setmembership(lua_State *L, p_sock ps, int level, int name); static int opt_setboolean(lua_State *L, p_sock ps, int level, int name); static int opt_set(lua_State *L, p_sock ps, int level, int name, diff --git a/src/options.h b/src/options.h index ec75fc0..d57bfaa 100644 --- a/src/options.h +++ b/src/options.h @@ -1,5 +1,14 @@ #ifndef OPTIONS_H #define OPTIONS_H +/*=========================================================================*\ +* Common option interface +* LuaSocket toolkit +* +* This module provides a common interface to socket options, used mainly by +* modules UDP and TCP. +* +* RCS ID: $Id$ +\*=========================================================================*/ #include #include "socket.h" diff --git a/src/select.h b/src/select.h index b58f082..f2d2cc2 100644 --- a/src/select.h +++ b/src/select.h @@ -4,13 +4,10 @@ * Select implementation * LuaSocket toolkit * -* To make the code as simple as possible, the select function is -* implemented int Lua, with a few helper functions written in C. -* -* Each object that can be passed to the select function has to export two -* methods: fd() and dirty(). Fd returns the descriptor to be passed to the -* select function. Dirty() should return true if there is data ready for -* reading (required for buffered input). +* Each object that can be passed to the select function has to export +* method getfd() which returns the descriptor to be passed to the +* underlying select function. Another method, dirty(), should return +* true if there is data ready for reading (required for buffered input). * * RCS ID: $Id$ \*=========================================================================*/ diff --git a/src/smtp.lua b/src/smtp.lua index dc80c35..fb76ea4 100644 --- a/src/smtp.lua +++ b/src/smtp.lua @@ -2,14 +2,13 @@ -- SMTP client support for the Lua language. -- LuaSocket toolkit. -- Author: Diego Nehab --- Conforming to RFC 2821 -- RCS ID: $Id$ ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- -- Load required modules ----------------------------------------------------------------------------- -local smtp = requirelib("smtp") +local smtp = requirelib("smtp", "luaopen_smtp", getfenv(1)) local socket = require("socket") local ltn12 = require("ltn12") local tp = require("tp") @@ -206,6 +205,7 @@ end --------------------------------------------------------------------------- -- High level SMTP API ----------------------------------------------------------------------------- +socket.protect = function(a) return a end send = socket.protect(function(mailt) local con = open(mailt.server, mailt.port) con:greet(mailt.domain) @@ -213,5 +213,3 @@ send = socket.protect(function(mailt) con:quit() return con:close() end) - -return smtp diff --git a/src/socket.lua b/src/socket.lua index 9aa6437..f73d167 100644 --- a/src/socket.lua +++ b/src/socket.lua @@ -166,5 +166,3 @@ end socket.sourcet["default"] = socket.sourcet["until-closed"] socket.source = socket.choose(socket.sourcet) - -return socket diff --git a/src/tp.lua b/src/tp.lua index 56dd8bc..731191e 100644 --- a/src/tp.lua +++ b/src/tp.lua @@ -49,7 +49,6 @@ local metat = { __index = {} } function metat.__index:check(ok) local code, reply = get_reply(self.control) -print(reply) if not code then return nil, reply end if type(ok) ~= "function" then if type(ok) == "table" then @@ -65,7 +64,6 @@ print(reply) end function metat.__index:command(cmd, arg) -print(cmd, arg) if arg then return self.control:send(cmd .. " " .. arg.. "\r\n") else return self.control:send(cmd .. "\r\n") end end @@ -113,5 +111,3 @@ connect = socket.protect(function(host, port, timeout) socket.try(control:connect(host, port)) return setmetatable({control = control}, metat) end) - -return tp diff --git a/src/url.lua b/src/url.lua index aac2a47..960a248 100644 --- a/src/url.lua +++ b/src/url.lua @@ -2,7 +2,6 @@ -- URI parsing, composition and relative URL resolution -- LuaSocket toolkit. -- Author: Diego Nehab --- Conforming to: RFC 2396, LTN7 -- RCS ID: $Id$ ----------------------------------------------------------------------------- @@ -269,5 +268,3 @@ function build_path(parsed, unsafe) if parsed.is_absolute then path = "/" .. path end return path end - -return url diff --git a/test/stufftest.lua b/test/stufftest.lua index 5eb8005..6bd1f91 100644 --- a/test/stufftest.lua +++ b/test/stufftest.lua @@ -1,11 +1,13 @@ +smtp = require("smtp") + function test_dot(original, right) - local result, n = socket.smtp.dot(2, original) + local result, n = smtp.dot(2, original) assert(result == right, "->" .. result .. "<-") print("ok") end function test_stuff(original, right) - local result, n = socket.smtp.dot(2, original) + local result, n = smtp.dot(2, original) assert(result == right, "->" .. result .. "<-") print("ok") end diff --git a/test/testmesg.lua b/test/testmesg.lua index 449f4c2..3e4c28f 100644 --- a/test/testmesg.lua +++ b/test/testmesg.lua @@ -14,7 +14,7 @@ source = smtp.message{ }, body = { preamble = "If your client doesn't understand attachments, \r\n" .. - "it will still display the preamble and the epilogue.\r\n", + "it will still display the preamble and the epilogue.\r\n" .. "Preamble might show up even in a MIME enabled client.", -- first part: No headers means plain text, us-ascii. -- The mime.eol low-level filter normalizes end-of-line markers. @@ -55,3 +55,5 @@ r, e = smtp.send{ source = source, server = "mail.cs.princeton.edu" } + +print(r, e) diff --git a/test/tftptest.lua b/test/tftptest.lua index a478ed8..f0dbd82 100644 --- a/test/tftptest.lua +++ b/test/tftptest.lua @@ -1,5 +1,5 @@ -- load tftpclnt.lua -dofile("tftp.lua") +local tftp = require("tftp") -- needs tftp server running on localhost, with root pointing to -- a directory with index.html in it @@ -13,7 +13,7 @@ function readfile(file) end host = host or "localhost" -retrieved, err = socket.tftp.get("tftp://" .. host .."/index.html") +retrieved, err = tftp.get("tftp://" .. host .."/index.html") assert(not err, err) original = readfile("test/index.html") assert(original == retrieved, "files differ!")