Fixed smtp.lua loading.

Adjusted tftp module.
Added some comments.
master
Diego Nehab 2004-06-16 01:02:07 +00:00
parent 843a431ef9
commit d46f7a09a7
20 changed files with 162 additions and 139 deletions

76
TODO
View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -1,12 +1,22 @@
/*=========================================================================*\
* Simple exception support
* LuaSocket toolkit
*
* RCS ID: $Id$
\*=========================================================================*/
#include <lauxlib.h>
#include <stdio.h>
#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},

View File

@ -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

View File

@ -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

View File

@ -254,5 +254,3 @@ function pump.all(src, snk, step)
if not ret then return not err, err end
end
end
return ltn12

View File

@ -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);

View File

@ -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

View File

@ -73,5 +73,3 @@ wrap = choose(wrapt)
function normalize(marker)
return ltn12.filter.cycle(eol, 0, marker)
end
return mime

View File

@ -1,3 +1,9 @@
/*=========================================================================*\
* Common option interface
* LuaSocket toolkit
*
* RCS ID: $Id$
\*=========================================================================*/
#include <lauxlib.h>
#include <string.h>
@ -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,

View File

@ -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 <lua.h>
#include "socket.h"

View File

@ -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$
\*=========================================================================*/

View File

@ -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

View File

@ -166,5 +166,3 @@ end
socket.sourcet["default"] = socket.sourcet["until-closed"]
socket.source = socket.choose(socket.sourcet)
return socket

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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!")