mirror of
https://github.com/lunarmodules/luasocket.git
synced 2024-12-26 12:28:21 +01:00
2.0 alpha RELEASED!
This commit is contained in:
parent
ac4aac0909
commit
7ed89c97f7
2
NEW
2
NEW
@ -56,7 +56,7 @@ the changes that made it into version 2.0:
|
|||||||
LUASOCKET_DEBUG was defined, but it turns out they might be useful for
|
LUASOCKET_DEBUG was defined, but it turns out they might be useful for
|
||||||
applications;
|
applications;
|
||||||
|
|
||||||
<> 'socket.try' and 'socket.protect' provide a simple
|
<> 'socket.newtry' and 'socket.protect' provide a simple
|
||||||
interface to exceptions that proved very in the implementation of
|
interface to exceptions that proved very in the implementation of
|
||||||
high-level modules;
|
high-level modules;
|
||||||
|
|
||||||
|
157
TODO
157
TODO
@ -1,163 +1,12 @@
|
|||||||
|
make select interrupt safe
|
||||||
|
adicionar exemplos de expansão: pipe, local, named pipe
|
||||||
ajeitar os README.*
|
|
||||||
ajeitar as referencias a RFCS e LTNS em todos os arquivos.
|
|
||||||
|
|
||||||
make sure sockets are closed when exceptions are raised
|
|
||||||
|
|
||||||
check garbage collection in test*.lua
|
|
||||||
|
|
||||||
|
|
||||||
manual
|
|
||||||
socket.newtry
|
|
||||||
*socket.skip
|
|
||||||
*send return convention changed.
|
|
||||||
* compatibility: select sets are associative
|
|
||||||
* add socket.connect and socket.bind to the manual
|
|
||||||
* add shutdown
|
|
||||||
* add gethostname
|
|
||||||
check all occurences of it's
|
|
||||||
* 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.
|
|
||||||
|
|
||||||
tests
|
|
||||||
checar todos os metodos
|
|
||||||
checar todas as globais
|
|
||||||
checar garbage collection
|
|
||||||
check for interrupts
|
|
||||||
|
|
||||||
wrp can't break lines in the middle of a line break.
|
|
||||||
|
|
||||||
add comments into each C module.
|
|
||||||
testar os options!
|
|
||||||
|
|
||||||
|
|
||||||
Read about
|
|
||||||
250-ENHANCEDSTATUSCODES
|
|
||||||
250-PIPELINING
|
|
||||||
250-8BITMIME
|
|
||||||
250-SIZE
|
|
||||||
250-DSN
|
|
||||||
250-ETRN
|
|
||||||
250-AUTH GSSAPI
|
|
||||||
250-DELIVERBY
|
|
||||||
250 HELP
|
|
||||||
|
|
||||||
Change return of send and receive callbacks to allow for
|
|
||||||
new functions. "" signals end of transmission. Pass total
|
|
||||||
number of bytes in request table for HTTP. Callback has nothing
|
|
||||||
to do with it.
|
|
||||||
|
|
||||||
Make sure nobody can fuck up with the metatables...
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Adjust dates in all files
|
|
||||||
|
|
||||||
Test the library on every system possible
|
|
||||||
|
|
||||||
Add service name translation.
|
Add service name translation.
|
||||||
Ajeitar o protocolo da luaopen_socket()... sei lá qual é.
|
testar os options!
|
||||||
|
|
||||||
|
|
||||||
- adicionar exemplos de expansão: pipe, local, named pipe
|
|
||||||
|
|
||||||
|
|
||||||
- Fazer compilar com g++
|
- Fazer compilar com g++
|
||||||
- Thread-safe
|
- Thread-safe
|
||||||
- proteger get*by*.* com um mutex GLOBAL!
|
- proteger get*by*.* com um mutex GLOBAL!
|
||||||
- proteger ou atomizar o conjunto (timedout, receive), (timedout, send)
|
- proteger ou atomizar o conjunto (timedout, receive), (timedout, send)
|
||||||
- inet_ntoa também é uma merda.
|
- inet_ntoa também é uma merda.
|
||||||
- SSL
|
- SSL
|
||||||
|
|
||||||
- unix 92 bytes maximo no endereço, incluindo o zero
|
- unix 92 bytes maximo no endereço, incluindo o zero
|
||||||
- unix 9216 maximo de datagram size
|
- unix 9216 maximo de datagram size
|
||||||
|
|
||||||
--------------
|
|
||||||
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)
|
|
||||||
* new socket options (many)
|
|
||||||
* only allocate in case of success
|
|
||||||
* optimize for success (only call select if fails)
|
|
||||||
* add proxy support to http
|
|
||||||
* add gethostname
|
|
||||||
* local connect
|
|
||||||
* connect with timeout
|
|
||||||
* change code to mime
|
|
||||||
* change stay to redirect
|
|
||||||
* add shutdown
|
|
||||||
* change send/recv to avoid using select
|
|
||||||
* O location do "redirect" pode ser relativo ao servidor atual (não pode,
|
|
||||||
mas os servidores fazem merda...)
|
|
||||||
* Ajeitar para Lua 5.0
|
|
||||||
* Padronizar os retornos de funccao
|
|
||||||
* Separar as classes em arquivos
|
|
||||||
* Retorno de sendto em datagram sockets pode ser refused
|
|
||||||
* select sets are now associative
|
|
||||||
* colocar pump.all, pump.step
|
|
||||||
* mudar ltn12.html e usar o exemplo source.cat que está muito melhor.
|
|
||||||
* break smtp.send into c = smtp.open, c:send() c:close()
|
|
||||||
* fazer com que a socket.source e socket.sink sejam "selectable".
|
|
||||||
* change mime.eol to output marker on detection of first candidate, instead
|
|
||||||
of on the second. that way it works in one pass for strings that end with
|
|
||||||
one candidate.
|
|
||||||
* unify backbone of smtp and ftp
|
|
||||||
* unify filter and send/receive callback. new sink/source/pump idea.
|
|
||||||
* get rid of aux_optlstring
|
|
||||||
* get rid of unpack in mime.lua
|
|
||||||
* create socket.(sink|source).simplify
|
|
||||||
* break chain into a simpler binary chain and a complex (recursive) one.
|
|
||||||
* Create a passive mode option for the FTP (good for firewall).
|
|
||||||
* Modules should return their namespace table in the end of the chunk.
|
|
||||||
* get.lua precisa de ftp.get com url e sink
|
|
||||||
* conjunto associativo
|
|
||||||
* colocar um userdata com gc metamethod pra chamar sock_close (WSAClose);
|
|
||||||
* call select before accept, not after, dumbass!
|
|
||||||
* get rid of setnonblocking/setblocking in the bind function
|
|
||||||
* close has to block...
|
|
||||||
* fmt is not a good name
|
|
||||||
* change wrap() to accept a number and default to "character"
|
|
||||||
* move gethostname to dns table
|
|
||||||
* get rid of _cb in name of functions?
|
|
||||||
* trust character constants in mime.c? yup.
|
|
||||||
* smtp.lua needs stuff filter
|
|
||||||
* new option.c module to put all options (TCP and UDP share...)?
|
|
||||||
* add _tostring methods!
|
|
||||||
* 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
|
|
||||||
* smtp.o goes to mime.dll
|
|
||||||
|
20
etc/README
20
etc/README
@ -1,24 +1,10 @@
|
|||||||
This directory contains code that is more useful than the examples. This code
|
This directory contains code that is more useful than the examples. This code
|
||||||
*is* supported.
|
*is* supported.
|
||||||
|
|
||||||
lua.lua
|
lua.lua -- new require and requirelib implementations
|
||||||
|
|
||||||
These are modules to suport dynamic loading of LuaSocket by the stand alone
|
This is to support dynamic loading of LuaSocket. Check the INSTALL
|
||||||
Lua Interpreter with the use of new "require" and "requirelib" functions.
|
file for more information.
|
||||||
For my Mac OS X box, for instance, I place all files in
|
|
||||||
/Users/diego/tec/luasocket and set the following environment variables:
|
|
||||||
|
|
||||||
LUA_INIT=@/Users/diego/tec/luasocket/lua.lua
|
|
||||||
LUA_PATH=/Users/diego/tec/luasocket/?.lua;?.lua
|
|
||||||
LUA_PATHLIB=/Users/diego/tec/luasocket/?.dylib;?.dylib
|
|
||||||
|
|
||||||
With that, I can run any luasocket application with the command line:
|
|
||||||
|
|
||||||
lua <script>
|
|
||||||
|
|
||||||
as long as the script uses "require" to load the needed namespaces.
|
|
||||||
Much nicer than having to build a new executable just to initialize
|
|
||||||
LuaSocket!
|
|
||||||
|
|
||||||
tftp.lua -- Trivial FTP client
|
tftp.lua -- Trivial FTP client
|
||||||
|
|
||||||
|
402
etc/lp.lua
Normal file
402
etc/lp.lua
Normal file
@ -0,0 +1,402 @@
|
|||||||
|
-- make sure LuaSocket is loaded
|
||||||
|
local socket = require("socket")
|
||||||
|
local ltn12 = require("ltn12")
|
||||||
|
local lp = {}
|
||||||
|
--socket.lp = lp
|
||||||
|
-- make all module globals fall into lp namespace
|
||||||
|
setmetatable(lp, { __index = _G })
|
||||||
|
setfenv(1, lp)
|
||||||
|
|
||||||
|
-- default port
|
||||||
|
PORT = 515
|
||||||
|
SERVER = os.getenv("SERVER_NAME") or os.getenv("COMPUTERNAME") or "localhost"
|
||||||
|
PRINTER = os.getenv("PRINTER") or "printer"
|
||||||
|
|
||||||
|
|
||||||
|
--[[
|
||||||
|
RFC 1179
|
||||||
|
5.3 03 - Send queue state (short)
|
||||||
|
|
||||||
|
+----+-------+----+------+----+
|
||||||
|
| 03 | Queue | SP | List | LF |
|
||||||
|
+----+-------+----+------+----+
|
||||||
|
Command code - 3
|
||||||
|
Operand 1 - Printer queue name
|
||||||
|
Other operands - User names or job numbers
|
||||||
|
|
||||||
|
If the user names or job numbers or both are supplied then only those
|
||||||
|
jobs for those users or with those numbers will be sent.
|
||||||
|
|
||||||
|
The response is an ASCII stream which describes the printer queue.
|
||||||
|
The stream continues until the connection closes. Ends of lines are
|
||||||
|
indicated with ASCII LF control characters. The lines may also
|
||||||
|
contain ASCII HT control characters.
|
||||||
|
|
||||||
|
5.4 04 - Send queue state (long)
|
||||||
|
|
||||||
|
+----+-------+----+------+----+
|
||||||
|
| 04 | Queue | SP | List | LF |
|
||||||
|
+----+-------+----+------+----+
|
||||||
|
Command code - 4
|
||||||
|
Operand 1 - Printer queue name
|
||||||
|
Other operands - User names or job numbers
|
||||||
|
|
||||||
|
If the user names or job numbers or both are supplied then only those
|
||||||
|
jobs for those users or with those numbers will be sent.
|
||||||
|
|
||||||
|
The response is an ASCII stream which describes the printer queue.
|
||||||
|
The stream continues until the connection closes. Ends of lines are
|
||||||
|
indicated with ASCII LF control characters. The lines may also
|
||||||
|
contain ASCII HT control characters.
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
-- gets server acknowledement
|
||||||
|
local function recv_ack(connection)
|
||||||
|
local code, current, separator, _
|
||||||
|
local ack = socket.try(connection:receive(1))
|
||||||
|
if string.char(0) ~= ack then
|
||||||
|
connection:close(); error"failed to receive server acknowledement"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- sends client acknowledement
|
||||||
|
local function send_ack(connection)
|
||||||
|
local sent = socket.try(connection:send(string.char(0)))
|
||||||
|
if not sent or sent ~= 1 then
|
||||||
|
connection:close();
|
||||||
|
error"failed to send acknowledgement"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- sends queue request
|
||||||
|
-- 5.2 02 - Receive a printer job
|
||||||
|
--
|
||||||
|
-- +----+-------+----+
|
||||||
|
-- | 02 | Queue | LF |
|
||||||
|
-- +----+-------+----+
|
||||||
|
-- Command code - 2
|
||||||
|
-- Operand - Printer queue name
|
||||||
|
--
|
||||||
|
-- Receiving a job is controlled by a second level of commands. The
|
||||||
|
-- daemon is given commands by sending them over the same connection.
|
||||||
|
-- The commands are described in the next section (6).
|
||||||
|
--
|
||||||
|
-- After this command is sent, the client must read an acknowledgement
|
||||||
|
-- octet from the daemon. A positive acknowledgement is an octet of
|
||||||
|
-- zero bits. A negative acknowledgement is an octet of any other
|
||||||
|
-- pattern.
|
||||||
|
local function send_queue(connection,queue)
|
||||||
|
if not queue then queue=PRINTER end
|
||||||
|
local str = string.format("\2%s\10",queue)
|
||||||
|
local sent = socket.try(connection:send(str))
|
||||||
|
if not sent or sent ~= string.len(str) then
|
||||||
|
error "failed to send print request"
|
||||||
|
end
|
||||||
|
recv_ack(connection)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- sends control file
|
||||||
|
-- 6.2 02 - Receive control file
|
||||||
|
--
|
||||||
|
-- +----+-------+----+------+----+
|
||||||
|
-- | 02 | Count | SP | Name | LF |
|
||||||
|
-- +----+-------+----+------+----+
|
||||||
|
-- Command code - 2
|
||||||
|
-- Operand 1 - Number of bytes in control file
|
||||||
|
-- Operand 2 - Name of control file
|
||||||
|
--
|
||||||
|
-- The control file must be an ASCII stream with the ends of lines
|
||||||
|
-- indicated by ASCII LF. The total number of bytes in the stream is
|
||||||
|
-- sent as the first operand. The name of the control file is sent as
|
||||||
|
-- the second. It should start with ASCII "cfA", followed by a three
|
||||||
|
-- digit job number, followed by the host name which has constructed the
|
||||||
|
-- control file. Acknowledgement processing must occur as usual after
|
||||||
|
-- the command is sent.
|
||||||
|
--
|
||||||
|
-- The next "Operand 1" octets over the same TCP connection are the
|
||||||
|
-- intended contents of the control file. Once all of the contents have
|
||||||
|
-- been delivered, an octet of zero bits is sent as an indication that
|
||||||
|
-- the file being sent is complete. A second level of acknowledgement
|
||||||
|
-- processing must occur at this point.
|
||||||
|
|
||||||
|
-- sends data file
|
||||||
|
-- 6.3 03 - Receive data file
|
||||||
|
--
|
||||||
|
-- +----+-------+----+------+----+
|
||||||
|
-- | 03 | Count | SP | Name | LF |
|
||||||
|
-- +----+-------+----+------+----+
|
||||||
|
-- Command code - 3
|
||||||
|
-- Operand 1 - Number of bytes in data file
|
||||||
|
-- Operand 2 - Name of data file
|
||||||
|
--
|
||||||
|
-- The data file may contain any 8 bit values at all. The total number
|
||||||
|
-- of bytes in the stream may be sent as the first operand, otherwise
|
||||||
|
-- the field should be cleared to 0. The name of the data file should
|
||||||
|
-- start with ASCII "dfA". This should be followed by a three digit job
|
||||||
|
-- number. The job number should be followed by the host name which has
|
||||||
|
-- constructed the data file. Interpretation of the contents of the
|
||||||
|
-- data file is determined by the contents of the corresponding control
|
||||||
|
-- file. If a data file length has been specified, the next "Operand 1"
|
||||||
|
-- octets over the same TCP connection are the intended contents of the
|
||||||
|
-- data file. In this case, once all of the contents have been
|
||||||
|
-- delivered, an octet of zero bits is sent as an indication that the
|
||||||
|
-- file being sent is complete. A second level of acknowledgement
|
||||||
|
-- processing must occur at this point.
|
||||||
|
|
||||||
|
|
||||||
|
local function send_hdr(connection,control)
|
||||||
|
local sent = socket.try(connection:send(control))
|
||||||
|
if not sent or sent < 1 then
|
||||||
|
error "failed to send file"
|
||||||
|
end
|
||||||
|
recv_ack(connection)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function send_control(connection,control)
|
||||||
|
local sent = socket.try(connection:send(control))
|
||||||
|
if not sent or sent < 1 then
|
||||||
|
error "failed to send file"
|
||||||
|
end
|
||||||
|
send_ack(connection)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function send_data(connection,fh,size)
|
||||||
|
-- local sink = socket.sink("keep-open", connection)
|
||||||
|
-- ltn12.pump.all(source, sink)
|
||||||
|
local buf, st, message
|
||||||
|
st = true
|
||||||
|
while size > 0 do
|
||||||
|
buf,message = fh:read(8192)
|
||||||
|
if buf then
|
||||||
|
st = socket.try(connection:send(buf))
|
||||||
|
size = size - st
|
||||||
|
else
|
||||||
|
if size ~= 0 then
|
||||||
|
connection:close()
|
||||||
|
return nil, "file size mismatch"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
send_ack(connection)
|
||||||
|
recv_ack(connection)
|
||||||
|
return size,nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--[[
|
||||||
|
|
||||||
|
local control_dflt = {
|
||||||
|
"H"..string.sub(socket.hostname,1,31).."\10", -- host
|
||||||
|
"C"..string.sub(socket.hostname,1,31).."\10", -- class
|
||||||
|
"J"..string.sub(filename,1,99).."\10", -- jobname
|
||||||
|
"L"..string.sub(user,1,31).."\10", -- print banner page
|
||||||
|
"I"..tonumber(indent).."\10", -- indent column count ('f' only)
|
||||||
|
"M"..string.sub(mail,1,128).."\10", -- mail when printed user@host
|
||||||
|
"N"..string.sub(filename,1,131).."\10", -- name of source file
|
||||||
|
"P"..string.sub(user,1,31).."\10", -- user name
|
||||||
|
"T"..string.sub(title,1,79).."\10", -- title for banner ('p' only)
|
||||||
|
"W"..tonumber(width or 132).."\10", -- width of print f,l,p only
|
||||||
|
|
||||||
|
"f"..file.."\10", -- formatted print (remove control chars)
|
||||||
|
"l"..file.."\10", -- print
|
||||||
|
"o"..file.."\10", -- postscript
|
||||||
|
"p"..file.."\10", -- pr format - requires T, L
|
||||||
|
"r"..file.."\10", -- fortran format
|
||||||
|
"U"..file.."\10", -- Unlink (data file only)
|
||||||
|
}
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
-- generate a varying job number
|
||||||
|
local function getjobno(connection)
|
||||||
|
-- print(math.mod(socket.time() * 1000, port)) -- ok for windows
|
||||||
|
-- print(os.time() / port,math.random(0,999))
|
||||||
|
return math.random(0,999)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getcon(localhost,option)
|
||||||
|
local skt, st, message
|
||||||
|
local localport = 721
|
||||||
|
if not option then
|
||||||
|
error('no options',0)
|
||||||
|
end
|
||||||
|
if option.localbind then
|
||||||
|
repeat
|
||||||
|
-- bind to a local port (if we can)
|
||||||
|
skt = socket.try(socket.tcp())
|
||||||
|
skt:settimeout(30)
|
||||||
|
|
||||||
|
st, message = skt:bind(localhost,localport,-1);
|
||||||
|
-- print("bind",st,message)
|
||||||
|
if st then
|
||||||
|
st,message = skt:connect(option.host or SERVER, option.port or PORT)
|
||||||
|
-- print("connect",st,message)
|
||||||
|
end
|
||||||
|
-- print(st,localport,message)
|
||||||
|
if not st then
|
||||||
|
localport = localport + 1
|
||||||
|
skt:close()
|
||||||
|
end
|
||||||
|
until st or localport > 731 or (not st and message ~= "local address already in use")
|
||||||
|
if st then return skt end
|
||||||
|
end
|
||||||
|
return socket.try(socket.connect(option.host or SERVER, option.port or PORT))
|
||||||
|
end
|
||||||
|
|
||||||
|
local format_codes = {
|
||||||
|
binary = 'l',
|
||||||
|
text = 'f',
|
||||||
|
ps = 'o',
|
||||||
|
pr = 'p',
|
||||||
|
fortran = 'r',
|
||||||
|
l = 'l',
|
||||||
|
r = 'r',
|
||||||
|
o = 'o',
|
||||||
|
p = 'p',
|
||||||
|
f = 'f'
|
||||||
|
}
|
||||||
|
|
||||||
|
lp.send = socket.protect(function(file, option)
|
||||||
|
if not file then error "invalid file name" end
|
||||||
|
if not option or type(option) ~= "table" then error "invalid options" end
|
||||||
|
local fh = socket.try(io.open(file,"rb"))
|
||||||
|
-- get total size
|
||||||
|
local datafile_size = fh:seek("end")
|
||||||
|
-- go back to start of file
|
||||||
|
fh:seek("set")
|
||||||
|
math.randomseed(socket.time() * 1000)
|
||||||
|
local localhost = socket.dns.gethostname() or os.getenv("COMPUTERNAME") or "localhost"
|
||||||
|
|
||||||
|
-- local connection, message = skt:connect(option.host or SERVER, option.port or PORT)
|
||||||
|
|
||||||
|
local connection = getcon(localhost,option)
|
||||||
|
|
||||||
|
-- format the control file
|
||||||
|
local jobno = getjobno(connection)
|
||||||
|
local localip = socket.dns.toip(localhost)
|
||||||
|
localhost = string.sub(localhost,1,31)
|
||||||
|
|
||||||
|
local user = string.sub(option.user or os.getenv("LPRUSER") or os.getenv("USERNAME")
|
||||||
|
or os.getenv("USER") or "anonymous",1,31)
|
||||||
|
|
||||||
|
local lpfile = string.format("dfA%3.3d%-s", jobno, localhost);
|
||||||
|
|
||||||
|
local fmt = format_codes[option.format] or 'l'
|
||||||
|
|
||||||
|
local class = string.sub(option.class or localip or localhost,1,31)
|
||||||
|
|
||||||
|
local _,_,ctlfn = string.find(file,".*[%/%\\](.*)")
|
||||||
|
ctlfn = string.sub(ctlfn or file,1,131)
|
||||||
|
|
||||||
|
local cfile =
|
||||||
|
string.format("H%-s\nC%-s\nJ%-s\nP%-s\n%.1s%-s\nU%-s\nN%-s\n",
|
||||||
|
localhost,
|
||||||
|
class,
|
||||||
|
option.job or ctlfn,
|
||||||
|
user,
|
||||||
|
fmt, lpfile,
|
||||||
|
lpfile,
|
||||||
|
ctlfn); -- mandatory part of ctl file
|
||||||
|
if (option.banner) then cfile = cfile .. 'L'..user..'\10' end
|
||||||
|
if (option.indent) then cfile = cfile .. 'I'..tonumber(option.indent)..'\10' end
|
||||||
|
if (option.mail) then cfile = cfile .. 'M'..string.sub((option.mail),1,128)..'\10' end
|
||||||
|
if (fmt == 'p' and option.title) then cfile = cfile .. 'T'..string.sub((option.title),1,79)..'\10' end
|
||||||
|
if ((fmt == 'p' or fmt == 'l' or fmt == 'f') and option.width) then
|
||||||
|
cfile = cfile .. 'W'..tonumber(option,width)..'\10'
|
||||||
|
end
|
||||||
|
|
||||||
|
connection:settimeout(option.timeout or 65)
|
||||||
|
|
||||||
|
-- send the queue header
|
||||||
|
send_queue(connection,option.queue)
|
||||||
|
|
||||||
|
-- send the control file header
|
||||||
|
local cfilecmd = string.format("\2%d cfA%3.3d%-s\n",string.len(cfile), jobno, localhost);
|
||||||
|
send_hdr(connection,cfilecmd)
|
||||||
|
|
||||||
|
-- send the control file
|
||||||
|
send_control(connection,cfile)
|
||||||
|
|
||||||
|
-- send the data file header
|
||||||
|
local dfilecmd = string.format("\3%d dfA%3.3d%-s\n",datafile_size, jobno, localhost);
|
||||||
|
send_hdr(connection,dfilecmd)
|
||||||
|
|
||||||
|
-- send the data file
|
||||||
|
send_data(connection,fh,datafile_size)
|
||||||
|
fh:close()
|
||||||
|
connection:close();
|
||||||
|
return datafile_size
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
--socket.lpq({host=,queue=printer|'*', format='l'|'s', list=})
|
||||||
|
lp.query = socket.protect(function(p)
|
||||||
|
if not p then p={} end
|
||||||
|
local localhost = socket.dns.gethostname() or os.getenv("COMPUTERNAME") or "localhost"
|
||||||
|
local connection = getcon(localhost,p)
|
||||||
|
local fmt,data
|
||||||
|
if string.sub(p.format or 's',1,1) == 's' then fmt = 3 else fmt = 4 end
|
||||||
|
local sent = socket.try(connection:send(string.format("%c%s %s\n", fmt, p.queue or "*", p.list or "")))
|
||||||
|
local data = socket.try(connection:receive("*a"))
|
||||||
|
io.write(data)
|
||||||
|
connection:close()
|
||||||
|
return tostring(string.len(data))
|
||||||
|
end)
|
||||||
|
|
||||||
|
--for k,v in arg do print(k,v) end
|
||||||
|
local function usage()
|
||||||
|
print('\nUsage: lp filename [keyword=val...]\n')
|
||||||
|
print('Valid keywords are :')
|
||||||
|
print(
|
||||||
|
' host=remote host or IP address (default "localhost")\n' ..
|
||||||
|
' queue=remote queue or printer name (default "printer")\n' ..
|
||||||
|
' port=remote port number (default 515)\n' ..
|
||||||
|
' user=sending user name\n' ..
|
||||||
|
' format=["binary" | "text" | "ps" | "pr" | "fortran"] (default "binary")\n' ..
|
||||||
|
' banner=true|false\n' ..
|
||||||
|
' indent=number of columns to indent\n' ..
|
||||||
|
' mail=email of address to notify when print is complete\n' ..
|
||||||
|
' title=title to use for "pr" format\n' ..
|
||||||
|
' width=width for "text" or "pr" formats\n' ..
|
||||||
|
' class=\n' ..
|
||||||
|
' job=\n' ..
|
||||||
|
' name=\n' ..
|
||||||
|
' localbind=true|false\n'
|
||||||
|
)
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if not arg or not arg[1] then
|
||||||
|
return usage()
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local s="opt = {"
|
||||||
|
for i = 2 , table.getn(arg), 1 do
|
||||||
|
s = s .. string.gsub(arg[i],"[%s%c%p]*([%w]*)=([\"]?[%w%s_!@#$%%^&*()<>:;]+[\"]\?\.?)","%1%=\"%2\",\n")
|
||||||
|
end
|
||||||
|
s = s .. "};\n"
|
||||||
|
assert(loadstring(s))();
|
||||||
|
if not arg[2] then
|
||||||
|
return usage()
|
||||||
|
end
|
||||||
|
if arg[1] ~= "query" then
|
||||||
|
r,e=lp.send(arg[1],opt)
|
||||||
|
io.stderr:write(tostring(r or e),'\n')
|
||||||
|
else
|
||||||
|
r,e=lp.query(opt)
|
||||||
|
io.stderr:write(tostring(r or e),'\n')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- trivial tests
|
||||||
|
--lua lp.lua lp.lua queue=default host=localhost
|
||||||
|
--lua lp.lua lp.lua queue=default host=localhost format=binary localbind=1
|
||||||
|
--lua lp.lua query queue=default host=localhost
|
||||||
|
collectgarbage()
|
||||||
|
collectgarbage()
|
||||||
|
--print(socket.lp.query{host='localhost', queue="default"})
|
||||||
|
|
||||||
|
return nil
|
@ -29,6 +29,7 @@ EXAMPLES = \
|
|||||||
eol.lua \
|
eol.lua \
|
||||||
listener.lua \
|
listener.lua \
|
||||||
qp.lua \
|
qp.lua \
|
||||||
|
lp.lua \
|
||||||
talker.lua \
|
talker.lua \
|
||||||
tinyirc.lua
|
tinyirc.lua
|
||||||
|
|
||||||
@ -101,14 +102,13 @@ dist:
|
|||||||
mkdir -p $(DIST)/tests
|
mkdir -p $(DIST)/tests
|
||||||
mkdir -p $(DIST)/etc
|
mkdir -p $(DIST)/etc
|
||||||
mkdir -p $(DIST)/lua
|
mkdir -p $(DIST)/lua
|
||||||
mkdir -p $(DIST)/make
|
|
||||||
mkdir -p $(DIST)/manual
|
mkdir -p $(DIST)/manual
|
||||||
cp -vf $(CORE) $(DIST)
|
cp -vf $(CORE) $(DIST)
|
||||||
cp -vf README $(DIST)
|
cp -vf README $(DIST)
|
||||||
cp -vf NEW $(DIST)
|
cp -vf NEW $(DIST)
|
||||||
cp -vf LICENSE $(DIST)
|
cp -vf LICENSE $(DIST)
|
||||||
cp -vf $(MAKE) $(DIST)/make
|
cp -vf $(MAKE) $(DIST)
|
||||||
cp -vf make.README $(DIST)/make/README
|
cp -vf make.README $(DIST)/INSTALL
|
||||||
cp -vf $(LUA) $(DIST)/lua
|
cp -vf $(LUA) $(DIST)/lua
|
||||||
cp -vf lua.README $(DIST)/lua/README
|
cp -vf lua.README $(DIST)/lua/README
|
||||||
cp -vf $(EXAMPLES) $(DIST)/examples
|
cp -vf $(EXAMPLES) $(DIST)/examples
|
||||||
|
@ -19,6 +19,12 @@ printed by listen.lua.
|
|||||||
These are tiny programs that perform Base64, Quoted-Printable and
|
These are tiny programs that perform Base64, Quoted-Printable and
|
||||||
end-of-line marker conversions.
|
end-of-line marker conversions.
|
||||||
|
|
||||||
|
lp.lua -- lp client
|
||||||
|
|
||||||
|
This is a cool program written by David Burgess to print files using the
|
||||||
|
Line Printer Daemon protocol, widely used in Unix machines.
|
||||||
|
Just run 'lua lp.lua <filename> queue=<printername>' and the file will print!
|
||||||
|
|
||||||
cddb.lua -- CDDB client
|
cddb.lua -- CDDB client
|
||||||
|
|
||||||
This is the first try on a simple CDDB client. Not really useful, but one
|
This is the first try on a simple CDDB client. Not really useful, but one
|
||||||
@ -26,7 +32,6 @@ day it might become a module.
|
|||||||
|
|
||||||
daytimeclnt.lua -- day time client
|
daytimeclnt.lua -- day time client
|
||||||
|
|
||||||
|
|
||||||
Just run the program to retrieve the hour and date in readable form from
|
Just run the program to retrieve the hour and date in readable form from
|
||||||
any server running an UDP daytime daemon.
|
any server running an UDP daytime daemon.
|
||||||
|
|
||||||
|
23
src/except.c
23
src/except.c
@ -12,33 +12,21 @@
|
|||||||
/*=========================================================================*\
|
/*=========================================================================*\
|
||||||
* Internal function prototypes.
|
* Internal function prototypes.
|
||||||
\*=========================================================================*/
|
\*=========================================================================*/
|
||||||
static int global_try(lua_State *L);
|
|
||||||
static int global_protect(lua_State *L);
|
static int global_protect(lua_State *L);
|
||||||
static int global_newtry(lua_State *L);
|
static int global_newtry(lua_State *L);
|
||||||
static int protected(lua_State *L);
|
static int protected(lua_State *L);
|
||||||
static int finalize(lua_State *L);
|
static int finalize(lua_State *L);
|
||||||
|
static int do_nothing(lua_State *L);
|
||||||
|
|
||||||
/* except functions */
|
/* except functions */
|
||||||
static luaL_reg func[] = {
|
static luaL_reg func[] = {
|
||||||
{"try", global_try},
|
|
||||||
{"newtry", global_newtry},
|
{"newtry", global_newtry},
|
||||||
{"protect", global_protect},
|
{"protect", global_protect},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*\
|
/*-------------------------------------------------------------------------*\
|
||||||
* Try method
|
* Try factory
|
||||||
\*-------------------------------------------------------------------------*/
|
|
||||||
static int global_try(lua_State *L) {
|
|
||||||
if (lua_isnil(L, 1) || (lua_isboolean(L, 1) && !lua_toboolean(L, 1))) {
|
|
||||||
lua_settop(L, 2);
|
|
||||||
lua_error(L);
|
|
||||||
return 0;
|
|
||||||
} else return lua_gettop(L);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*\
|
|
||||||
* Finalizer factory
|
|
||||||
\*-------------------------------------------------------------------------*/
|
\*-------------------------------------------------------------------------*/
|
||||||
static int finalize(lua_State *L) {
|
static int finalize(lua_State *L) {
|
||||||
if (lua_isnil(L, 1) || (lua_isboolean(L, 1) && !lua_toboolean(L, 1))) {
|
if (lua_isnil(L, 1) || (lua_isboolean(L, 1) && !lua_toboolean(L, 1))) {
|
||||||
@ -50,7 +38,14 @@ static int finalize(lua_State *L) {
|
|||||||
} else return lua_gettop(L);
|
} else return lua_gettop(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_nothing(lua_State *L) {
|
||||||
|
(void) L;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int global_newtry(lua_State *L) {
|
static int global_newtry(lua_State *L) {
|
||||||
|
lua_settop(L, 1);
|
||||||
|
if (lua_isnil(L, 1)) lua_pushcfunction(L, do_nothing);
|
||||||
lua_pushcclosure(L, finalize, 1);
|
lua_pushcclosure(L, finalize, 1);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
16
src/ftp.lua
16
src/ftp.lua
@ -32,14 +32,10 @@ local metat = { __index = {} }
|
|||||||
|
|
||||||
function open(server, port)
|
function open(server, port)
|
||||||
local tp = socket.try(tp.connect(server, port or PORT, TIMEOUT))
|
local tp = socket.try(tp.connect(server, port or PORT, TIMEOUT))
|
||||||
local f = { tp = tp }
|
local f = setmetat({ tp = tp }, metat)
|
||||||
-- make sure everything gets closed in an exception
|
-- make sure everything gets closed in an exception
|
||||||
f.try = socket.newtry(function()
|
f.try = socket.newtry(function() f:close() end)
|
||||||
tp:close()
|
return f
|
||||||
if f.data then f.data:close() end
|
|
||||||
if f.server then f.server:close() end
|
|
||||||
end)
|
|
||||||
return setmetatable(f, metat)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function metat.__index:portconnect()
|
function metat.__index:portconnect()
|
||||||
@ -173,13 +169,9 @@ function metat.__index:quit()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function metat.__index:close()
|
function metat.__index:close()
|
||||||
self.tp:close()
|
|
||||||
if self.data then self.data:close() end
|
if self.data then self.data:close() end
|
||||||
if self.server then self.server:close() end
|
if self.server then self.server:close() end
|
||||||
self.tp = nil
|
return self.tp:close()
|
||||||
self.data = nil
|
|
||||||
self.server = nil
|
|
||||||
return 1
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
23
src/http.lua
23
src/http.lua
@ -32,11 +32,12 @@ local metat = { __index = {} }
|
|||||||
|
|
||||||
function open(host, port)
|
function open(host, port)
|
||||||
local c = socket.try(socket.tcp())
|
local c = socket.try(socket.tcp())
|
||||||
|
local h = setmetatable({ c = c }, metat)
|
||||||
-- make sure the connection gets closed on exception
|
-- make sure the connection gets closed on exception
|
||||||
local try = socket.newtry(function() c:close() end)
|
h.try = socket.newtry(function() h:close() end)
|
||||||
try(c:settimeout(TIMEOUT))
|
h.try(c:settimeout(TIMEOUT))
|
||||||
try(c:connect(host, port or PORT))
|
h.try(c:connect(host, port or PORT))
|
||||||
return setmetatable({ c = c, try = try }, metat)
|
return h
|
||||||
end
|
end
|
||||||
|
|
||||||
function metat.__index:sendrequestline(method, uri)
|
function metat.__index:sendrequestline(method, uri)
|
||||||
@ -57,9 +58,8 @@ function metat.__index:sendbody(headers, source, step)
|
|||||||
source = source or ltn12.source.empty()
|
source = source or ltn12.source.empty()
|
||||||
step = step or ltn12.pump.step
|
step = step or ltn12.pump.step
|
||||||
-- if we don't know the size in advance, send chunked and hope for the best
|
-- if we don't know the size in advance, send chunked and hope for the best
|
||||||
local mode
|
local mode = "http-chunked"
|
||||||
if headers["content-length"] then mode = "keep-open"
|
if headers["content-length"] then mode = "keep-open" end
|
||||||
else mode = "http-chunked" end
|
|
||||||
return self.try(ltn12.pump.all(source, socket.sink(mode, self.c), step))
|
return self.try(ltn12.pump.all(source, socket.sink(mode, self.c), step))
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -99,10 +99,9 @@ function metat.__index:receivebody(headers, sink, step)
|
|||||||
step = step or ltn12.pump.step
|
step = step or ltn12.pump.step
|
||||||
local length = tonumber(headers["content-length"])
|
local length = tonumber(headers["content-length"])
|
||||||
local TE = headers["transfer-encoding"]
|
local TE = headers["transfer-encoding"]
|
||||||
local mode
|
local mode = "default" -- connection close
|
||||||
if TE and TE ~= "identity" then mode = "http-chunked"
|
if TE and TE ~= "identity" then mode = "http-chunked"
|
||||||
elseif tonumber(headers["content-length"]) then mode = "by-length"
|
elseif tonumber(headers["content-length"]) then mode = "by-length" end
|
||||||
else mode = "default" end
|
|
||||||
return self.try(ltn12.pump.all(socket.source(mode, self.c, length),
|
return self.try(ltn12.pump.all(socket.source(mode, self.c, length),
|
||||||
sink, step))
|
sink, step))
|
||||||
end
|
end
|
||||||
@ -191,9 +190,9 @@ function tauthorize(reqt)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function tredirect(reqt, headers)
|
function tredirect(reqt, headers)
|
||||||
-- the RFC says the redirect URL has to be absolute, but some
|
|
||||||
-- servers do not respect that
|
|
||||||
return trequest {
|
return trequest {
|
||||||
|
-- the RFC says the redirect URL has to be absolute, but some
|
||||||
|
-- servers do not respect that
|
||||||
url = url.absolute(reqt, headers["location"]),
|
url = url.absolute(reqt, headers["location"]),
|
||||||
source = reqt.source,
|
source = reqt.source,
|
||||||
sink = reqt.sink,
|
sink = reqt.sink,
|
||||||
|
@ -60,7 +60,7 @@ function metat.__index:quit()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function metat.__index:close()
|
function metat.__index:close()
|
||||||
return self.try(self.tp:close())
|
return self.tp:close()
|
||||||
end
|
end
|
||||||
|
|
||||||
function metat.__index:login(user, password)
|
function metat.__index:login(user, password)
|
||||||
@ -104,9 +104,10 @@ end
|
|||||||
|
|
||||||
function open(server, port)
|
function open(server, port)
|
||||||
local tp = socket.try(tp.connect(server or SERVER, port or PORT, TIMEOUT))
|
local tp = socket.try(tp.connect(server or SERVER, port or PORT, TIMEOUT))
|
||||||
|
local s = setmetatable({tp = tp}, metat)
|
||||||
-- make sure tp is closed if we get an exception
|
-- make sure tp is closed if we get an exception
|
||||||
local try = socket.newtry(function() tp:close() end)
|
local try = socket.newtry(function() s:close() end)
|
||||||
return setmetatable({ tp = tp, try = try}, metat)
|
return s
|
||||||
end
|
end
|
||||||
|
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
|
@ -37,6 +37,8 @@ function socket.bind(host, port, backlog)
|
|||||||
return sock
|
return sock
|
||||||
end
|
end
|
||||||
|
|
||||||
|
socket.try = socket.newtry()
|
||||||
|
|
||||||
function socket.choose(table)
|
function socket.choose(table)
|
||||||
return function(name, opt1, opt2)
|
return function(name, opt1, opt2)
|
||||||
if type(name) ~= "string" then
|
if type(name) ~= "string" then
|
||||||
|
49
src/tp.lua
49
src/tp.lua
@ -20,16 +20,16 @@ TIMEOUT = 60
|
|||||||
-- Implementation
|
-- Implementation
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
-- gets server reply (works for SMTP and FTP)
|
-- gets server reply (works for SMTP and FTP)
|
||||||
local function get_reply(control)
|
local function get_reply(c)
|
||||||
local code, current, sep
|
local code, current, sep
|
||||||
local line, err = control:receive()
|
local line, err = c:receive()
|
||||||
local reply = line
|
local reply = line
|
||||||
if err then return nil, err end
|
if err then return nil, err end
|
||||||
code, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
|
code, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
|
||||||
if not code then return nil, "invalid server reply" end
|
if not code then return nil, "invalid server reply" end
|
||||||
if sep == "-" then -- reply is multiline
|
if sep == "-" then -- reply is multiline
|
||||||
repeat
|
repeat
|
||||||
line, err = control:receive()
|
line, err = c:receive()
|
||||||
if err then return nil, err end
|
if err then return nil, err end
|
||||||
current, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
|
current, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
|
||||||
reply = reply .. "\n" .. line
|
reply = reply .. "\n" .. line
|
||||||
@ -43,7 +43,7 @@ end
|
|||||||
local metat = { __index = {} }
|
local metat = { __index = {} }
|
||||||
|
|
||||||
function metat.__index:check(ok)
|
function metat.__index:check(ok)
|
||||||
local code, reply = get_reply(self.control)
|
local code, reply = get_reply(self.c)
|
||||||
if not code then return nil, reply end
|
if not code then return nil, reply end
|
||||||
if type(ok) ~= "function" then
|
if type(ok) ~= "function" then
|
||||||
if type(ok) == "table" then
|
if type(ok) == "table" then
|
||||||
@ -59,50 +59,55 @@ function metat.__index:check(ok)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function metat.__index:command(cmd, arg)
|
function metat.__index:command(cmd, arg)
|
||||||
if arg then return self.control:send(cmd .. " " .. arg.. "\r\n")
|
if arg then return self.c:send(cmd .. " " .. arg.. "\r\n")
|
||||||
else return self.control:send(cmd .. "\r\n") end
|
else return self.c:send(cmd .. "\r\n") end
|
||||||
end
|
end
|
||||||
|
|
||||||
function metat.__index:sink(snk, pat)
|
function metat.__index:sink(snk, pat)
|
||||||
local chunk, err = control:receive(pat)
|
local chunk, err = c:receive(pat)
|
||||||
return snk(chunk, err)
|
return snk(chunk, err)
|
||||||
end
|
end
|
||||||
|
|
||||||
function metat.__index:send(data)
|
function metat.__index:send(data)
|
||||||
return self.control:send(data)
|
return self.c:send(data)
|
||||||
end
|
end
|
||||||
|
|
||||||
function metat.__index:receive(pat)
|
function metat.__index:receive(pat)
|
||||||
return self.control:receive(pat)
|
return self.c:receive(pat)
|
||||||
end
|
end
|
||||||
|
|
||||||
function metat.__index:getfd()
|
function metat.__index:getfd()
|
||||||
return self.control:getfd()
|
return self.c:getfd()
|
||||||
end
|
end
|
||||||
|
|
||||||
function metat.__index:dirty()
|
function metat.__index:dirty()
|
||||||
return self.control:dirty()
|
return self.c:dirty()
|
||||||
end
|
end
|
||||||
|
|
||||||
function metat.__index:getcontrol()
|
function metat.__index:getcontrol()
|
||||||
return self.control
|
return self.c
|
||||||
end
|
end
|
||||||
|
|
||||||
function metat.__index:source(source, step)
|
function metat.__index:source(source, step)
|
||||||
local sink = socket.sink("keep-open", self.control)
|
local sink = socket.sink("keep-open", self.c)
|
||||||
return ltn12.pump.all(source, sink, step or ltn12.pump.step)
|
return ltn12.pump.all(source, sink, step or ltn12.pump.step)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- closes the underlying control
|
-- closes the underlying c
|
||||||
function metat.__index:close()
|
function metat.__index:close()
|
||||||
self.control:close()
|
self.c:close()
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- connect with server and return control object
|
-- connect with server and return c object
|
||||||
connect = socket.protect(function(host, port, timeout)
|
function connect(host, port, timeout)
|
||||||
local control = socket.try(socket.tcp())
|
local c, e = socket.tcp()
|
||||||
socket.try(control:settimeout(timeout or TIMEOUT))
|
if not c then return nil, e end
|
||||||
socket.try(control:connect(host, port))
|
c:settimeout(timeout or TIMEOUT)
|
||||||
return setmetatable({control = control}, metat)
|
local r, e = c:connect(host, port)
|
||||||
end)
|
if not r then
|
||||||
|
c:close()
|
||||||
|
return nil, e
|
||||||
|
end
|
||||||
|
return setmetatable({c = c}, metat)
|
||||||
|
end
|
||||||
|
@ -155,14 +155,15 @@ check_request(request, expect, ignore)
|
|||||||
io.write("testing simple post function: ")
|
io.write("testing simple post function: ")
|
||||||
back = http.request("http://" .. host .. cgiprefix .. "/cat", index)
|
back = http.request("http://" .. host .. cgiprefix .. "/cat", index)
|
||||||
assert(back == index)
|
assert(back == index)
|
||||||
|
print("ok")
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
io.write("testing ltn12.(sink|source).file: ")
|
io.write("testing ltn12.(sink|source).file: ")
|
||||||
request = {
|
request = {
|
||||||
url = "http://" .. host .. cgiprefix .. "/cat",
|
url = "http://" .. host .. cgiprefix .. "/cat",
|
||||||
method = "POST",
|
method = "POST",
|
||||||
source = ltn12.source.file(io.open(index_file, "r")),
|
source = ltn12.source.file(io.open(index_file, "rb")),
|
||||||
sink = ltn12.sink.file(io.open(index_file .. "-back", "w")),
|
sink = ltn12.sink.file(io.open(index_file .. "-back", "wb")),
|
||||||
headers = { ["content-length"] = string.len(index) }
|
headers = { ["content-length"] = string.len(index) }
|
||||||
}
|
}
|
||||||
expect = {
|
expect = {
|
||||||
@ -187,7 +188,7 @@ local function b64length(len)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local source = ltn12.source.chain(
|
local source = ltn12.source.chain(
|
||||||
ltn12.source.file(io.open(index_file, "r")),
|
ltn12.source.file(io.open(index_file, "rb")),
|
||||||
ltn12.filter.chain(
|
ltn12.filter.chain(
|
||||||
mime.encode("base64"),
|
mime.encode("base64"),
|
||||||
mime.wrap("base64")
|
mime.wrap("base64")
|
||||||
@ -196,7 +197,7 @@ local source = ltn12.source.chain(
|
|||||||
|
|
||||||
local sink = ltn12.sink.chain(
|
local sink = ltn12.sink.chain(
|
||||||
mime.decode("base64"),
|
mime.decode("base64"),
|
||||||
ltn12.sink.file(io.open(index_file .. "-back", "w"))
|
ltn12.sink.file(io.open(index_file .. "-back", "wb"))
|
||||||
)
|
)
|
||||||
|
|
||||||
request = {
|
request = {
|
||||||
|
@ -13,7 +13,6 @@ while 1 do
|
|||||||
-- control:setoption("nodelay", true)
|
-- control:setoption("nodelay", true)
|
||||||
while 1 do
|
while 1 do
|
||||||
command, error = control:receive()
|
command, error = control:receive()
|
||||||
print(error)
|
|
||||||
if error then
|
if error then
|
||||||
control:close()
|
control:close()
|
||||||
print("server: closing connection...")
|
print("server: closing connection...")
|
||||||
|
Loading…
Reference in New Issue
Block a user