mirror of
https://github.com/lunarmodules/luasocket.git
synced 2024-12-26 04:28:20 +01:00
Worked on the manual.
Implemented stuffing (needs test) Added cddb and qp examples.
This commit is contained in:
parent
f67864f86c
commit
0b2542d1a6
62
TODO
62
TODO
@ -1,7 +1,36 @@
|
||||
* 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
|
||||
|
||||
|
||||
check garbage collection in test*.lua
|
||||
pop3???
|
||||
|
||||
add socket.TIMEOUT to be default timeout?
|
||||
|
||||
manual
|
||||
add socket.connect and socket.bind to the manual
|
||||
say what a nil callback does for http
|
||||
check all occurences of it's
|
||||
add shutdown
|
||||
add gethostname
|
||||
- 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.
|
||||
@ -9,11 +38,11 @@ manual
|
||||
add timeout and proxy to request table
|
||||
change stay to redirect
|
||||
socket.time and socket.sleep
|
||||
connect with timeout
|
||||
- connect with timeout
|
||||
local connect
|
||||
add thanks to 'carlos cassino' and 'david burgess'
|
||||
add new ip- options and reuseaddr option
|
||||
add listen to manual
|
||||
- add listen to manual
|
||||
bind method doesn't do listen anymore
|
||||
bind doesn't turn an object into a server object: listen does.
|
||||
|
||||
@ -23,6 +52,9 @@ tests
|
||||
checar garbage collection
|
||||
check for interrupts
|
||||
|
||||
wrp can't break lines in the middle of a line break.
|
||||
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"
|
||||
@ -76,30 +108,10 @@ Ajeitar o protocolo da luaopen_socket()... sei l
|
||||
|
||||
- adicionar exemplos de expansão: pipe, local, named pipe
|
||||
|
||||
* 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
|
||||
|
||||
- Fazer compilar com g++
|
||||
- Thread-safe
|
||||
- proteger gethostby*.* com um mutex GLOBAL!
|
||||
- proteger get*by*.* com um mutex GLOBAL!
|
||||
- proteger ou atomizar o conjunto (timedout, receive), (timedout, send)
|
||||
- inet_ntoa também é uma merda.
|
||||
- SSL
|
||||
|
@ -31,16 +31,16 @@
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<!-- stream ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<!-- stream ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h2 id=stream>Streaming with Callbacks</h2>
|
||||
<h2 id=stream>Callbacks</h2>
|
||||
|
||||
<p>
|
||||
HTTP, FTP, and SMTP transfers sometimes involve large amounts of
|
||||
information. Sometimes an application needs to generate outgoing data
|
||||
in real time, or needs to process incoming information as it is being
|
||||
received. To address these problems, LuaSocket allows HTTP and SMTP message
|
||||
bodies and FTP file contents to be received or sent through the
|
||||
bodies and FTP file contents to be streamed through the
|
||||
callback mechanism outlined below.
|
||||
</p>
|
||||
|
||||
@ -52,7 +52,7 @@ chunks of data, as the data becomes available. Conversely, the <em>send
|
||||
callback</em> mechanism can be used when the application wants to incrementally provide LuaSocket with the data to be sent.
|
||||
</p>
|
||||
|
||||
<!-- tohostname +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<!-- receive +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=receive>
|
||||
<b>receive_cb(</b>chunk, err<b>)</b>
|
||||
@ -60,7 +60,7 @@ callback</em> mechanism can be used when the application wants to incrementally
|
||||
|
||||
<p class=description>
|
||||
A receive callback will be repeatedly called by
|
||||
LuaSocket wheneve new data is available. Each time it is called, the
|
||||
LuaSocket whenever new data is available. Each time it is called, the
|
||||
callback receives successive chunks of downloaded data.
|
||||
</p>
|
||||
|
||||
@ -113,10 +113,129 @@ Together, these two modules provide a powerful interface to send and
|
||||
receive information.
|
||||
</p>
|
||||
|
||||
<!-- done +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=done>
|
||||
socket.callback.<b>done()</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
This function creates and returns a callback that successfully terminates
|
||||
the transmission.
|
||||
</p>
|
||||
|
||||
<!-- fail +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=fail>
|
||||
socket.callback.<b>fail(</b>message<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
This function creates and returns a callback that aborts the
|
||||
transmission with a given error <tt>message</tt>.
|
||||
</p>
|
||||
|
||||
<!-- receive.concat +++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=receive.concat>
|
||||
socket.callback.<b>receive.concat(</b>cat<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
This function creates a receive callback that stores whatever it receives
|
||||
into a concat object. When done, the application can get the contents
|
||||
received as a single string, directly from the concat object.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Cat</tt> is the target concat object, or <b><tt>nil</tt></b>.
|
||||
If <tt>cat</tt> is <b><tt>nil</tt></b>, the function creates its own
|
||||
concat object.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns a receive callback for the file, and the concat object
|
||||
that will be used to store the received contents.
|
||||
</p>
|
||||
|
||||
<!-- receive.file +++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=receive.file>
|
||||
socket.callback.<b>receive.file(</b>file, io_err<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
This function creates a receive callback that stores whatever it receives
|
||||
into a file. When done, the callback closes the file.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>File</tt> is a file handle opened for writing. If <tt>file</tt> is
|
||||
<b><tt>nil</tt></b>, <tt>io_err</tt> can contain an error message. In this
|
||||
case, the function returns a callback that just aborts
|
||||
transmission with the error message.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns a receive callback for the file.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: This function is designed so that it directly accepts the return
|
||||
values of Lua's IO <tt>io.open</tt> library function.
|
||||
</p>
|
||||
|
||||
<!-- receive.chain ++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=receive.chain>
|
||||
socket.callback.<b>receive.chain(</b>filter, receive_cb<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
This function creates a receive callback that passes all received data
|
||||
through a filter, before handing it to a given receive callback.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Cat</tt> is the target concat object, or <b><tt>nil</tt></b>.
|
||||
If <tt>cat</tt> is <b><tt>nil</tt></b>, the function creates its own
|
||||
concat object.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns a receive callback for the file, and the concat object
|
||||
that will be used to store the received contents.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: Several filters are defined in the <a href=mime.html>MIME</a>
|
||||
module. Below is an example that creates a receive callback that
|
||||
creates a string from the received contents, after decoding the
|
||||
Quoted-Printable transfer content encoding.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
string_cb, concat = socket.callback.receive.concat()
|
||||
receive_cb = socket.callback.receive.chain(
|
||||
socket.mime.decode("quoted-printable"),
|
||||
string_cb
|
||||
)
|
||||
</pre>
|
||||
|
||||
<p class=note>
|
||||
The call to <tt>callback.chain</tt> creates a chained
|
||||
receive callback that decodes data using the
|
||||
<tt><a href=mime.html#decode>mime.decode</a></tt>
|
||||
Quoted-Printable MIME filter and
|
||||
hands the decoded data to a concat receive callback.
|
||||
The concatenated decoded data can be retrieved later
|
||||
from the associated concat object.
|
||||
</p>
|
||||
|
||||
<!-- send.file ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=send.file>
|
||||
<b>send.file</b>(file, io_err<b>)</b>
|
||||
socket.callback.<b>send.file(</b>file, io_err<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
@ -126,25 +245,25 @@ When done, the callback closes the file.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>File</tt> is a file opened for reading. If <tt>file</tt> is
|
||||
<tt>File</tt> is a file handle opened for reading. If <tt>file</tt> is
|
||||
<b><tt>nil</tt></b>, <tt>io_err</tt> can contain an error message. In this
|
||||
case, the function returns a callback that just aborts
|
||||
transmission with the error message.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
Returns a send callback for the file.
|
||||
The function returns a send callback for the file.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: This function is designed so that it directly accepts the return
|
||||
values of the <tt>io.open</tt> function.
|
||||
values of Lua's IO <tt>io.open</tt> library function.
|
||||
</p>
|
||||
|
||||
<!-- send.string ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=send.string>
|
||||
<b>send.string(</b>str, err<b>)</b>
|
||||
socket.callback.<b>send.string(</b>str, err<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
@ -154,26 +273,17 @@ the contents of a string.
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Str</tt> is the string to be sent.
|
||||
<!--
|
||||
If <tt>str</tt> is
|
||||
<b><tt>nil</tt></b>, <tt>err</tt> can optionally contain an error message.
|
||||
-->
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
Returns a send callback for the string, or <b><tt>nil</tt></b> if the string is
|
||||
<b><tt>nil</tt></b>.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: A <tt>nil</tt></b>
|
||||
send callback is equivalent to a callback that returns the empty string.
|
||||
It returns a send callback for the string,
|
||||
or <b><tt>nil</tt></b> if <tt>str</tt> is <b><tt>nil</tt></b>.
|
||||
</p>
|
||||
|
||||
<!-- send.chain ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=send.chain>
|
||||
<b>send.chain(</b>send_cb, filter<b>)</b>
|
||||
socket.callback.<b>send.chain(</b>send_cb, filter<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
@ -207,9 +317,9 @@ send_cb = socket.callback.send.chain(
|
||||
</pre>
|
||||
|
||||
<p class=note>
|
||||
The call to <a href=mime.html#chain><tt>socket.mime.chain</tt></a>
|
||||
The call to <a href=mime.html#chain><tt>mime.chain</tt></a>
|
||||
creates a chained filter that encodes it's input and then breaks it
|
||||
into lines. The call to <tt>socket.callback.chain</tt> creates a chained
|
||||
into lines. The call to <tt>callback.chain</tt> creates a chained
|
||||
send callback that reads the file from disk and passes it through the
|
||||
filter before sending it.
|
||||
</p>
|
||||
|
19
doc/dns.html
19
doc/dns.html
@ -36,8 +36,7 @@
|
||||
<h2 id=dns>DNS</h2>
|
||||
|
||||
<p>
|
||||
The following functions can be used to convert between host names and IP
|
||||
addresses. Both functions return <em>all</em> information returned by the
|
||||
Name resolution function return <em>all</em> information returned by the
|
||||
resolver in a table of the form:
|
||||
</p>
|
||||
|
||||
@ -53,6 +52,21 @@ resolved = {<br>
|
||||
Note that the <tt>alias</tt> list can be empty.
|
||||
</p>
|
||||
|
||||
<!-- gethostname ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=gethostname>
|
||||
socket.dns.<b>gethostname()</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Returns the standard host name for the machine.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns a string with the host name.
|
||||
</p>
|
||||
|
||||
|
||||
<!-- tohostname +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=tohostname>
|
||||
@ -74,7 +88,6 @@ the resolver. In case of error, the function returns <b><tt>nil</tt></b>
|
||||
followed by an error message.
|
||||
</p>
|
||||
|
||||
|
||||
<!-- toip +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=toip>
|
||||
|
@ -49,7 +49,7 @@ implementation conforms to the HTTP/1.1 standard,
|
||||
The module exports functions that provide HTTP functionality in different
|
||||
levels of abstraction, from a simple <a
|
||||
href="#get"><tt>get</tt></a>, to the generic, stream oriented
|
||||
<a href="#request_cb"> <tt>request_cb</tt></a>.
|
||||
<a href="#request_cb"><tt>request_cb</tt></a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
@ -40,7 +40,8 @@ LuaSocket is a <a href="http://www.lua.org">Lua</a> extension library
|
||||
that is composed by two parts: a C layer that provides support for the TCP
|
||||
and UDP transport layers, and a set of Lua modules that add support for
|
||||
the SMTP (sending e-mails), HTTP (WWW access) and FTP (uploading and
|
||||
downloading files) protocols.
|
||||
downloading files) protocols and other functionality commonly needed by
|
||||
applications that deal with the Internet.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@ -106,10 +107,25 @@ This binary has been compiled with the <tt>LUASOCKET_DEBUG</tt>
|
||||
option, and should be able to run the automatic test procedures.
|
||||
</p>
|
||||
|
||||
<!-- thanks +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h2 id=thanks>Special thanks</h2>
|
||||
|
||||
<p>
|
||||
Throughout LuaSocket its history, many people gave sugestions that helped
|
||||
improve it. For that, I thank the Lua comunity.
|
||||
Special thanks go to
|
||||
David Burgess, who has pushed the library to a new level of quality and
|
||||
from whom I have learned a lot stuff that doesn't show up in RFCs.
|
||||
Special thanks also to Carlos Cassino, who played a big part in the
|
||||
extensible design seen in the C core of LuaSocket 2.0.
|
||||
</p>
|
||||
|
||||
<!-- whatsnew +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h2 id=new>What's New</h2>
|
||||
|
||||
|
||||
<p>
|
||||
Most of the changes for 2.0 happened in the C layer, which
|
||||
has been almost completely rewritten. The code has been ported to Lua 5.0
|
||||
|
@ -40,6 +40,10 @@
|
||||
<blockquote>
|
||||
<a href="callback.html">Callbacks (socket.callback)</a>
|
||||
<blockquote>
|
||||
<a href="callback.html#done">done</a>,
|
||||
<a href="callback.html#fail">fail</a>.
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<a href="callback.html#send">send</a>:
|
||||
<a href="callback.html#send.chain">chain</a>,
|
||||
<a href="callback.html#send.file">file</a>,
|
||||
@ -121,7 +125,7 @@
|
||||
<blockquote>
|
||||
<a href="mime.html">MIME (socket.mime) </a>
|
||||
<blockquote>
|
||||
<a href="mime.html#filters">filters</a>:
|
||||
<a href="mime.html#high">high-level</a>:
|
||||
<a href="mime.html#decode">canonic</a>,
|
||||
<a href="mime.html#chain">chain</a>,
|
||||
<a href="mime.html#decode">decode</a>,
|
||||
@ -129,7 +133,7 @@
|
||||
<a href="mime.html#wrap">wrap</a>.
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<a href="mime.html#low-level">low-level</a>:
|
||||
<a href="mime.html#low">low-level</a>:
|
||||
<a href="mime.html#b64">b64</a>,
|
||||
<a href="mime.html#unb64">unb64</a>,
|
||||
<a href="mime.html#eol">eol</a>,
|
||||
|
148
doc/tcp.html
148
doc/tcp.html
@ -44,10 +44,11 @@ socket.<b>tcp()</b>
|
||||
<p class=description>
|
||||
Creates and returns a TCP master object. A master object can
|
||||
be transformed into a server object with the method
|
||||
<a href=#bind><tt>bind</tt></a> or into a client object with the method
|
||||
<a href=#connect><tt>connect</tt></a>. The only other method
|
||||
supported by a master object is the <a href=#close><tt>close</tt></a>
|
||||
method.</p>
|
||||
<a href=#listen><tt>listen</tt></a> (after a call to <a
|
||||
href=#bind><tt>bind</tt></a>) or into a client object with
|
||||
the method <a href=#connect><tt>connect</tt></a>. The only other
|
||||
method supported by a master object is the
|
||||
<a href=#close><tt>close</tt></a> method.</p>
|
||||
|
||||
<p class=return>
|
||||
In case of success, a new master object is returned. In case of error,
|
||||
@ -67,8 +68,9 @@ object and returns a client object representing that connection.
|
||||
|
||||
<p class=return>
|
||||
If a connection is successfully initiated, a client object is returned.
|
||||
If a timeout condition is met, the method returns <b><tt>nil</tt></b> followed
|
||||
by the error string '<tt>timeout</tt>'.
|
||||
If a timeout condition is met, the method returns <b><tt>nil</tt></b>
|
||||
followed by the error string '<tt>timeout</tt>'. Other errors are
|
||||
reported by <b><tt>nil</tt></b> followed by a message describing the error.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
@ -77,25 +79,18 @@ with a server object in
|
||||
the <tt>receive</tt> parameter before a call to <tt>accept</tt> does
|
||||
<em>not</em> guarantee <tt>accept</tt> will return immediately. Use the <a
|
||||
href=#settimeout><tt>settimeout</tt></a> method or <tt>accept</tt>
|
||||
might block until <em>another</em> client shows up.
|
||||
might block until <em>another</em> client shows up.
|
||||
</p>
|
||||
|
||||
<!-- bind +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=bind>
|
||||
master:<b>bind(</b>address, port [, backlog]<b>)</b>
|
||||
master:<b>bind(</b>address, port<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Binds a master object to <tt>address</tt> and <tt>port</tt> on the
|
||||
local host, transforming it into a server object. Server
|
||||
objects support the
|
||||
<a href=#accept><tt>accept</tt></a>,
|
||||
<a href=#getsockname><tt>getsockname</tt></a>,
|
||||
<a href=#setoption><tt>setoption</tt></a>,
|
||||
<a href=#settimeout><tt>settimeout</tt></a>,
|
||||
and <a href=#close><tt>close</tt></a> methods.
|
||||
</p>
|
||||
local host.
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Address</tt> can be an IP address or a host name.
|
||||
@ -103,10 +98,7 @@ and <a href=#close><tt>close</tt></a> methods.
|
||||
If <tt>address</tt>
|
||||
is '<tt>*</tt>', the system binds to all local interfaces
|
||||
using the <tt>INADDR_ANY</tt> constant. If <tt>port</tt> is 0, the system automatically
|
||||
chooses an ephemeral port. The optional parameter <tt>backlog</tt>, which
|
||||
defaults to 1, specifies the number of client connections that can
|
||||
be queued waiting for service. If the queue is full and another client
|
||||
attempts connection, the connection is refused.
|
||||
chooses an ephemeral port.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
@ -115,8 +107,8 @@ method returns <b><tt>nil</tt></b> followed by an error message.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: The function <tt>socket.bind</tt> is available and is a short
|
||||
for <a href=#socket.tcp><tt>socket.tcp</tt></a> followed by the <tt>bind</tt> method.
|
||||
Note: The function <a href=#socket.bind><tt>socket.bind</tt></a>
|
||||
is available and is a shortcut for the creation server sockets.
|
||||
</p>
|
||||
|
||||
<!-- close ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
@ -150,7 +142,8 @@ master:<b>connect(</b>address, port<b>)</b>
|
||||
|
||||
<p class=description>
|
||||
Attempts to connect a master object to a remote host, transforming it into a
|
||||
client object. Client objects support methods
|
||||
client object.
|
||||
Client objects support methods
|
||||
<a href=#send><tt>send</tt></a>,
|
||||
<a href=#receive><tt>receive</tt></a>,
|
||||
<a href=#getsockname><tt>getsockname</tt></a>,
|
||||
@ -170,8 +163,15 @@ describing the error. In case of success, the method returns 1.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: The function <tt>socket.connect</tt> is available and is a short
|
||||
for <a href=#socket.tcp><tt>socket.tcp</tt></a> followed by the <tt>connect</tt> method.
|
||||
Note: The function <a href=#socket.connect><tt>socket.connect</tt></a>
|
||||
is available and is a shortcut for the creation of client sockets.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: Starting with LuaSocket 2.0,
|
||||
the <a href=#settimeout><tt>settimeout</tt></a>
|
||||
function affects the behavior of connect, causing it to return in case of
|
||||
a timeout error.
|
||||
</p>
|
||||
|
||||
<!-- getpeername ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
@ -210,12 +210,32 @@ The method returns a string with local IP address and a number with
|
||||
the port. In case of error, the method returns <b><tt>nil</tt></b>.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: Naturally, for a server object, the address and port returned are
|
||||
those passed to the <a href=#bind>bind</a> method. If the port value
|
||||
passed to bind was 0, the OS assigned ephemeral port is returned. For
|
||||
client objects, both the address and port are ephemeral and these are the
|
||||
values returned.
|
||||
<!-- listen ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=listen>
|
||||
master:<b>listen(</b>backlog<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Specifies the socket is willing to receive connections, transforming the
|
||||
object into a server object. Server objects support the
|
||||
<a href=#accept><tt>accept</tt></a>,
|
||||
<a href=#getsockname><tt>getsockname</tt></a>,
|
||||
<a href=#setoption><tt>setoption</tt></a>,
|
||||
<a href=#settimeout><tt>settimeout</tt></a>,
|
||||
and <a href=#close><tt>close</tt></a> methods.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
The parameter <tt>backlog</tt> specifies the number of client
|
||||
connections that can
|
||||
be queued waiting for service. If the queue is full and another client
|
||||
attempts connection, the connection is refused.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
In case of success, the method returns 1. In case of error, the
|
||||
method returns <b><tt>nil</tt></b> followed by an error message.
|
||||
</p>
|
||||
|
||||
<!-- receive ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
@ -242,8 +262,8 @@ closed. No end-of-line translation is performed;
|
||||
terminated by a LF character (ASCII 10), optionally preceded by a
|
||||
CR character (ASCII 13). The CR and LF characters are not included in
|
||||
the returned line. This is the default pattern;
|
||||
<li> <tt>number</tt>: causes the method to read <tt>number</tt> raw
|
||||
bytes from the socket.
|
||||
<li> <tt>number</tt>: causes the method to read a specified <tt>number</tt>
|
||||
of bytes from the socket.
|
||||
</ul>
|
||||
|
||||
<p class=return>
|
||||
@ -311,22 +331,30 @@ are sure you need it.
|
||||
depends on the option being set:
|
||||
|
||||
<ul>
|
||||
<li> '<tt>tcp-nodelay</tt>': Setting this option to <tt>true</tt> disables the
|
||||
Nagle's algorithm for the connection;
|
||||
|
||||
<li> '<tt>keepalive</tt>': Setting this option to <tt>true</tt> enables
|
||||
the periodic transmission of messages on a connected socket. Should the
|
||||
connected party fail to respond to these messages, the connection is
|
||||
considered broken and processes using the socket are notified;
|
||||
|
||||
<li> '<tt>linger</tt>': Controls the action taken when unsent data are
|
||||
queued on a socket and a close is performed. The value is a table with a
|
||||
boolean entry '<tt>on</tt>' and a numeric entry for the time interval
|
||||
'<tt>timeout</tt>' in seconds.
|
||||
If the '<tt>on</tt>' field is set to <tt>true</tt>,
|
||||
the system will block the process on the close attempt until it is able to
|
||||
transmit the data or until '<tt>timeout</tt>' has passed. If '<tt>on</tt>'
|
||||
is <tt>false</tt> and a close is issued, the system will process the close
|
||||
in a manner that allows the process to continue as quickly as possible. I
|
||||
do not advise you to set this to anything other than zero.
|
||||
<li> '<tt>keepalive</tt>': Setting this option to <tt>true</tt> enables
|
||||
the periodic transmission of messages on a connected socket. Should the
|
||||
connected party fail to respond to these messages, the connection is
|
||||
considered broken and processes using the socket are notified.
|
||||
'<tt>timeout</tt>' in seconds. If the '<tt>on</tt>' field is set to
|
||||
<tt>true</tt>, the system will block the process on the close attempt until
|
||||
it is able to transmit the data or until '<tt>timeout</tt>' has passed. If
|
||||
'<tt>on</tt>' is <tt>false</tt> and a close is issued, the system will
|
||||
process the close in a manner that allows the process to continue as
|
||||
quickly as possible. I do not advise you to set this to anything other than
|
||||
zero;
|
||||
|
||||
<li> '<tt>reuseaddr</tt>': Setting this option indicates that the rules
|
||||
used in validating addresses supplied in a call to
|
||||
<a href=#bind><tt>bind</tt></a> should allow reuse of local addresses;
|
||||
|
||||
<li> '<tt>tcp-nodelay</tt>': Setting this option to <tt>true</tt>
|
||||
disables the Nagle's algorithm for the connection.
|
||||
|
||||
</ul>
|
||||
|
||||
<p class=return>
|
||||
@ -382,7 +410,9 @@ indefinitely. Negative timeout values have the same effect.
|
||||
Note: although timeout values have millisecond precision in LuaSocket,
|
||||
large blocks can cause I/O functions not to respect timeout values due
|
||||
to the time the library takes to transfer blocks to and from the OS
|
||||
and to and from the Lua interpreter.
|
||||
and to and from the Lua interpreter. Also, function that accept host names
|
||||
and perform automatic name resolution might be blocked by the resolver for
|
||||
longer than the specified timeout value.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
@ -391,6 +421,30 @@ changed for sake of uniformity, since all other method names already
|
||||
contained verbs making their imperative nature obvious.
|
||||
</p>
|
||||
|
||||
<!-- shutdown +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=shutdown>
|
||||
client:<b>shutdown(</b>mode<b>)</b><br>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Shuts down part of a full duplex connection.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
Mode tells which way of the connection should be shut down and can
|
||||
take the value:
|
||||
<ul>
|
||||
<li>"<tt>both</tt>": disallow further sends and receives on the object.
|
||||
This is the default mode;
|
||||
<li>"<tt>send</tt>": disallow further sends on the object;
|
||||
<li>"<tt>receive</tt>": disallow further receives on the object.
|
||||
</ul>
|
||||
|
||||
<p class=return>
|
||||
This function returns 1.
|
||||
</p>
|
||||
|
||||
<!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=footer>
|
||||
|
44
doc/url.html
44
doc/url.html
@ -241,6 +241,50 @@ returning a list with all the parsed segments, the function unescapes all
|
||||
of them.
|
||||
</p>
|
||||
|
||||
<!-- escape +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="escape">
|
||||
socket.url.<b>escape(</b>content<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Applies the URL escaping content coding to a string
|
||||
Each byte is encoded as a percent character followed
|
||||
by the two byte hexadecimal representation of its integer
|
||||
value.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Content</tt> is the string to be encoded.
|
||||
</p>
|
||||
|
||||
<p class=result>
|
||||
The function returns the encoded string.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
code = socket.url.escape("/#?;")
|
||||
-- code = "%2f%23%3f%3b"
|
||||
</pre>
|
||||
|
||||
<!-- unescape +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="unescape">
|
||||
socket.url.<b>unescape(</b>content<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Removes the URL escaping content coding from a string.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Content</tt> is the string to be decoded.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns the decoded string.
|
||||
</p>
|
||||
|
||||
<!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=footer>
|
||||
|
18
etc/qp.lua
Normal file
18
etc/qp.lua
Normal file
@ -0,0 +1,18 @@
|
||||
local convert
|
||||
arg = arg or {}
|
||||
local mode = arg and arg[1] or "-et"
|
||||
if mode == "-et" then
|
||||
local canonic = socket.mime.canonic()
|
||||
local qp = socket.mime.encode("quoted-printable")
|
||||
local wrap = socket.mime.wrap("quoted-printable")
|
||||
convert = socket.mime.chain(canonic, qp, wrap)
|
||||
elseif mode == "-eb" then
|
||||
local qp = socket.mime.encode("quoted-printable", "binary")
|
||||
local wrap = socket.mime.wrap("quoted-printable")
|
||||
convert = socket.mime.chain(qp, wrap)
|
||||
else convert = socket.mime.decode("quoted-printable") end
|
||||
while 1 do
|
||||
local chunk = io.read(4096)
|
||||
io.write(convert(chunk))
|
||||
if not chunk then break end
|
||||
end
|
43
samples/cddb.lua
Normal file
43
samples/cddb.lua
Normal file
@ -0,0 +1,43 @@
|
||||
if not arg or not arg[1] or not arg[2] then
|
||||
print("luasocket cddb.lua <category> <disc-id> [<server>]")
|
||||
os.exit(1)
|
||||
end
|
||||
|
||||
local server = arg[3] or "http://freedb.freedb.org/~cddb/cddb.cgi"
|
||||
|
||||
function parse(body)
|
||||
local lines = string.gfind(body, "(.-)\r\n")
|
||||
local status = lines()
|
||||
local _, _, code, message = string.find(status, "(%d%d%d) (.*)")
|
||||
if tonumber(code) ~= 210 then
|
||||
return nil, code, message
|
||||
end
|
||||
local data = {}
|
||||
for l in lines do
|
||||
local c = string.sub(l, 1, 1)
|
||||
if c ~= '#' and c ~= '.' then
|
||||
local _, _, key, value = string.find(l, "(.-)=(.*)")
|
||||
value = string.gsub(value, "\\n", "\n")
|
||||
value = string.gsub(value, "\\\\", "\\")
|
||||
value = string.gsub(value, "\\t", "\t")
|
||||
data[key] = value
|
||||
end
|
||||
end
|
||||
return data, code, message
|
||||
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 = socket.http.get(url)
|
||||
|
||||
if code == 200 then
|
||||
local data, code, error = parse(body)
|
||||
if not data then
|
||||
print(error or code)
|
||||
else
|
||||
for i,v in data do
|
||||
io.write(i, ': ', v, '\n')
|
||||
end
|
||||
end
|
||||
else print(error) end
|
@ -37,9 +37,9 @@ error:
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Initializes the module
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void aux_open(lua_State *L)
|
||||
int aux_open(lua_State *L)
|
||||
{
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
@ -159,3 +159,13 @@ void *aux_getclassudata(lua_State *L, const char *classname, int objidx)
|
||||
return luaL_checkudata(L, objidx, classname);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Accept "false" as nil
|
||||
\*-------------------------------------------------------------------------*/
|
||||
const char *aux_optlstring(lua_State *L, int n, const char *v, size_t *l)
|
||||
{
|
||||
if (lua_isnil(L, n) || (lua_isboolean(L, n) && !lua_toboolean(L, n))) {
|
||||
*l = 0;
|
||||
return NULL;
|
||||
} else return luaL_optlstring(L, n, v, l);
|
||||
}
|
||||
|
@ -40,7 +40,7 @@
|
||||
#define MAX(x, y) ((x) > (y) ? x : y)
|
||||
#endif
|
||||
|
||||
void aux_open(lua_State *L);
|
||||
int aux_open(lua_State *L);
|
||||
void aux_newclass(lua_State *L, const char *classname, luaL_reg *func);
|
||||
void aux_add2group(lua_State *L, const char *classname, const char *group);
|
||||
void aux_setclass(lua_State *L, const char *classname, int objidx);
|
||||
@ -49,5 +49,6 @@ void *aux_checkgroup(lua_State *L, const char *groupname, int objidx);
|
||||
void *aux_getclassudata(lua_State *L, const char *groupname, int objidx);
|
||||
void *aux_getgroupudata(lua_State *L, const char *groupname, int objidx);
|
||||
int aux_checkboolean(lua_State *L, int objidx);
|
||||
const char *aux_optlstring(lua_State *L, int n, const char *v, size_t *l);
|
||||
|
||||
#endif /* AUX_H */
|
||||
|
@ -26,9 +26,10 @@ static int sendraw(p_buf buf, const char *data, size_t count, size_t *sent);
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Initializes module
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void buf_open(lua_State *L)
|
||||
int buf_open(lua_State *L)
|
||||
{
|
||||
(void) L;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
|
@ -34,7 +34,7 @@ typedef struct t_buf_ {
|
||||
} t_buf;
|
||||
typedef t_buf *p_buf;
|
||||
|
||||
void buf_open(lua_State *L);
|
||||
int buf_open(lua_State *L);
|
||||
void buf_init(p_buf buf, p_io io, p_tm tm);
|
||||
int buf_meth_send(lua_State *L, p_buf buf);
|
||||
int buf_meth_receive(lua_State *L, p_buf buf);
|
||||
|
@ -649,3 +649,5 @@ function Public.get(url_or_request)
|
||||
local err = Public.get_cb(request)
|
||||
return concat:getresult(), err
|
||||
end
|
||||
|
||||
return ftp
|
||||
|
@ -11,7 +11,7 @@ if not LUASOCKET_LIBNAME then error('module requires LuaSocket') end
|
||||
local socket = _G[LUASOCKET_LIBNAME]
|
||||
if not socket then error('module requires LuaSocket') end
|
||||
-- create smtp namespace inside LuaSocket namespace
|
||||
local http = {}
|
||||
local http = socket.http or {}
|
||||
socket.http = http
|
||||
-- make all module globals fall into smtp namespace
|
||||
setmetatable(http, { __index = _G })
|
||||
|
@ -35,17 +35,10 @@ static luaL_reg func[] = {
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Initializes module
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void inet_open(lua_State *L)
|
||||
int inet_open(lua_State *L)
|
||||
{
|
||||
lua_pushstring(L, LUASOCKET_LIBNAME);
|
||||
lua_gettable(L, LUA_GLOBALSINDEX);
|
||||
if (lua_isnil(L, -1)) {
|
||||
lua_pop(L, 1);
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, LUASOCKET_LIBNAME);
|
||||
lua_pushvalue(L, -2);
|
||||
lua_settable(L, LUA_GLOBALSINDEX);
|
||||
}
|
||||
lua_pushstring(L, "dns");
|
||||
lua_newtable(L);
|
||||
luaL_openlib(L, NULL, func, 0);
|
||||
|
@ -24,7 +24,7 @@
|
||||
#define INET_ATON
|
||||
#endif
|
||||
|
||||
void inet_open(lua_State *L);
|
||||
int inet_open(lua_State *L);
|
||||
|
||||
const char *inet_trycreate(p_sock ps, int type);
|
||||
const char *inet_tryconnect(p_sock ps, const char *address,
|
||||
|
@ -33,12 +33,14 @@
|
||||
#include "tcp.h"
|
||||
#include "udp.h"
|
||||
#include "select.h"
|
||||
#include "smtp.h"
|
||||
#include "mime.h"
|
||||
|
||||
/*=========================================================================*\
|
||||
* Declarations
|
||||
\*=========================================================================*/
|
||||
static int base_open(lua_State *L);
|
||||
static int mod_open(lua_State *L, const luaL_reg *mod);
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Setup basic stuff.
|
||||
@ -66,22 +68,9 @@ static int base_open(lua_State *L)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Initializes all library modules.
|
||||
\*-------------------------------------------------------------------------*/
|
||||
LUASOCKET_API int luaopen_socket(lua_State *L)
|
||||
static int mod_open(lua_State *L, const luaL_reg *mod)
|
||||
{
|
||||
if (!sock_open()) return 0;
|
||||
/* initialize all modules */
|
||||
base_open(L);
|
||||
aux_open(L);
|
||||
tm_open(L);
|
||||
buf_open(L);
|
||||
inet_open(L);
|
||||
tcp_open(L);
|
||||
udp_open(L);
|
||||
select_open(L);
|
||||
mime_open(L);
|
||||
for (; mod->name; mod++) mod->func(L);
|
||||
#ifdef LUASOCKET_COMPILED
|
||||
#include "auxiliar.lch"
|
||||
#include "concat.lch"
|
||||
@ -101,5 +90,36 @@ LUASOCKET_API int luaopen_socket(lua_State *L)
|
||||
lua_dofile(L, "ftp.lua");
|
||||
lua_dofile(L, "http.lua");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Modules
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static const luaL_reg mod[] = {
|
||||
{"base", base_open},
|
||||
{"aux", aux_open},
|
||||
{"tm", tm_open},
|
||||
{"buf", buf_open},
|
||||
{"inet", inet_open},
|
||||
{"tcp", tcp_open},
|
||||
{"udp", udp_open},
|
||||
{"select", select_open},
|
||||
{"mime", mime_open},
|
||||
{"smtp", smtp_open},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Initializes all library modules.
|
||||
\*-------------------------------------------------------------------------*/
|
||||
LUASOCKET_API int luaopen_socket(lua_State *L)
|
||||
{
|
||||
if (!sock_open()) {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, "unable to initialize library");
|
||||
return 2;
|
||||
}
|
||||
mod_open(L, mod);
|
||||
return 1;
|
||||
}
|
||||
|
140
src/mime.c
140
src/mime.c
@ -10,6 +10,7 @@
|
||||
#include <lauxlib.h>
|
||||
|
||||
#include "luasocket.h"
|
||||
#include "auxiliar.h"
|
||||
#include "mime.h"
|
||||
|
||||
/*=========================================================================*\
|
||||
@ -45,18 +46,16 @@ static void qpquote(UC c, luaL_Buffer *buffer);
|
||||
static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer);
|
||||
static size_t qpencode(UC c, UC *input, size_t size,
|
||||
const char *marker, luaL_Buffer *buffer);
|
||||
|
||||
static const char *checklstring(lua_State *L, int n, size_t *l);
|
||||
static const char *optlstring(lua_State *L, int n, const char *v, size_t *l);
|
||||
static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer);
|
||||
|
||||
/* code support functions */
|
||||
static luaL_reg func[] = {
|
||||
{ "b64", mime_global_b64 },
|
||||
{ "eol", mime_global_eol },
|
||||
{ "qp", mime_global_qp },
|
||||
{ "unqp", mime_global_unqp },
|
||||
{ "qpwrp", mime_global_qpwrp },
|
||||
{ "b64", mime_global_b64 },
|
||||
{ "unb64", mime_global_unb64 },
|
||||
{ "unqp", mime_global_unqp },
|
||||
{ "wrp", mime_global_wrp },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
@ -82,17 +81,10 @@ static UC b64unbase[256];
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Initializes module
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void mime_open(lua_State *L)
|
||||
int mime_open(lua_State *L)
|
||||
{
|
||||
lua_pushstring(L, LUASOCKET_LIBNAME);
|
||||
lua_gettable(L, LUA_GLOBALSINDEX);
|
||||
if (lua_isnil(L, -1)) {
|
||||
lua_pop(L, 1);
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, LUASOCKET_LIBNAME);
|
||||
lua_pushvalue(L, -2);
|
||||
lua_settable(L, LUA_GLOBALSINDEX);
|
||||
}
|
||||
lua_pushstring(L, "mime");
|
||||
lua_newtable(L);
|
||||
luaL_openlib(L, NULL, func, 0);
|
||||
@ -101,25 +93,7 @@ void mime_open(lua_State *L)
|
||||
/* initialize lookup tables */
|
||||
qpsetup(qpclass, qpunbase);
|
||||
b64setup(b64unbase);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Check if a string was provided. We accept false also.
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static const char *checklstring(lua_State *L, int n, size_t *l)
|
||||
{
|
||||
if (lua_isnil(L, n) || (lua_isboolean(L, n) && !lua_toboolean(L, n))) {
|
||||
*l = 0;
|
||||
return NULL;
|
||||
} else return luaL_checklstring(L, n, l);
|
||||
}
|
||||
|
||||
static const char *optlstring(lua_State *L, int n, const char *v, size_t *l)
|
||||
{
|
||||
if (lua_isnil(L, n) || (lua_isboolean(L, n) && !lua_toboolean(L, n))) {
|
||||
*l = 0;
|
||||
return NULL;
|
||||
} else return luaL_optlstring(L, n, v, l);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*=========================================================================*\
|
||||
@ -127,31 +101,42 @@ static const char *optlstring(lua_State *L, int n, const char *v, size_t *l)
|
||||
\*=========================================================================*/
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Incrementaly breaks a string into lines
|
||||
* A, n = wrp(l, B, length, marker)
|
||||
* A, n = wrp(l, B, length)
|
||||
* A is a copy of B, broken into lines of at most 'length' bytes.
|
||||
* 'l' is how many bytes are left for the first line of B.
|
||||
* 'n' is the number of bytes left in the last line of A.
|
||||
* Marker is the end-of-line marker.
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int mime_global_wrp(lua_State *L)
|
||||
{
|
||||
size_t size = 0;
|
||||
int left = (int) luaL_checknumber(L, 1);
|
||||
const UC *input = (UC *) checklstring(L, 2, &size);
|
||||
const UC *input = (UC *) aux_optlstring(L, 2, NULL, &size);
|
||||
const UC *last = input + size;
|
||||
int length = (int) luaL_optnumber(L, 3, 76);
|
||||
const char *marker = luaL_optstring(L, 4, CRLF);
|
||||
luaL_Buffer buffer;
|
||||
luaL_buffinit(L, &buffer);
|
||||
while (input < last) {
|
||||
luaL_putchar(&buffer, *input++);
|
||||
if (--left <= 0) {
|
||||
luaL_addstring(&buffer, marker);
|
||||
left = length;
|
||||
switch (*input) {
|
||||
case CR:
|
||||
break;
|
||||
case LF:
|
||||
luaL_addstring(&buffer, CRLF);
|
||||
left = length;
|
||||
break;
|
||||
default:
|
||||
if (left <= 0) {
|
||||
left = length;
|
||||
luaL_addstring(&buffer, CRLF);
|
||||
}
|
||||
luaL_putchar(&buffer, *input);
|
||||
left--;
|
||||
break;
|
||||
}
|
||||
input++;
|
||||
}
|
||||
/* if in last chunk and last line wasn't terminated, add a line-break */
|
||||
if (!input && left < length) {
|
||||
luaL_addstring(&buffer, marker);
|
||||
luaL_addstring(&buffer, CRLF);
|
||||
left = length;
|
||||
}
|
||||
luaL_pushresult(&buffer);
|
||||
@ -235,7 +220,6 @@ static size_t b64pad(const UC *input, size_t size,
|
||||
static size_t b64decode(UC c, UC *input, size_t size,
|
||||
luaL_Buffer *buffer)
|
||||
{
|
||||
|
||||
/* ignore invalid characters */
|
||||
if (b64unbase[c] > 64) return size;
|
||||
input[size++] = c;
|
||||
@ -277,7 +261,7 @@ static int mime_global_b64(lua_State *L)
|
||||
luaL_buffinit(L, &buffer);
|
||||
while (input < last)
|
||||
asize = b64encode(*input++, atom, asize, &buffer);
|
||||
input = (UC *) optlstring(L, 2, NULL, &isize);
|
||||
input = (UC *) aux_optlstring(L, 2, NULL, &isize);
|
||||
if (input) {
|
||||
last = input + isize;
|
||||
while (input < last)
|
||||
@ -305,12 +289,14 @@ static int mime_global_unb64(lua_State *L)
|
||||
luaL_buffinit(L, &buffer);
|
||||
while (input < last)
|
||||
asize = b64decode(*input++, atom, asize, &buffer);
|
||||
input = (UC *) optlstring(L, 2, NULL, &isize);
|
||||
input = (UC *) aux_optlstring(L, 2, NULL, &isize);
|
||||
if (input) {
|
||||
last = input + isize;
|
||||
while (input < last)
|
||||
asize = b64decode(*input++, atom, asize, &buffer);
|
||||
}
|
||||
/* if !input we are done. if atom > 0, the remaning is invalid. we just
|
||||
* return it undecoded. */
|
||||
luaL_pushresult(&buffer);
|
||||
lua_pushlstring(L, (char *) atom, asize);
|
||||
return 2;
|
||||
@ -416,7 +402,7 @@ static size_t qpencode(UC c, UC *input, size_t size,
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Deal with the final characters
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static void qppad(UC *input, size_t size, luaL_Buffer *buffer)
|
||||
static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < size; i++) {
|
||||
@ -424,12 +410,13 @@ static void qppad(UC *input, size_t size, luaL_Buffer *buffer)
|
||||
else qpquote(input[i], buffer);
|
||||
}
|
||||
luaL_addstring(buffer, EQCRLF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Incrementally converts a string to quoted-printable
|
||||
* A, B = qp(C, D, marker)
|
||||
* Crlf is the text to be used to replace CRLF sequences found in A.
|
||||
* Marker is the text to be used to replace CRLF sequences found in A.
|
||||
* A is the encoded version of the largest prefix of C .. D that
|
||||
* can be encoded without doubts.
|
||||
* B has the remaining bytes of C .. D, *without* encoding.
|
||||
@ -439,19 +426,20 @@ static int mime_global_qp(lua_State *L)
|
||||
|
||||
size_t asize = 0, isize = 0;
|
||||
UC atom[3];
|
||||
const UC *input = (UC *) checklstring(L, 1, &isize);
|
||||
const UC *input = (UC *) aux_optlstring(L, 1, NULL, &isize);
|
||||
const UC *last = input + isize;
|
||||
const char *marker = luaL_optstring(L, 3, CRLF);
|
||||
luaL_Buffer buffer;
|
||||
luaL_buffinit(L, &buffer);
|
||||
while (input < last)
|
||||
asize = qpencode(*input++, atom, asize, marker, &buffer);
|
||||
input = (UC *) optlstring(L, 2, NULL, &isize);
|
||||
input = (UC *) aux_optlstring(L, 2, NULL, &isize);
|
||||
if (input) {
|
||||
last = input + isize;
|
||||
while (input < last)
|
||||
asize = qpencode(*input++, atom, asize, marker, &buffer);
|
||||
} else qppad(atom, asize, &buffer);
|
||||
} else
|
||||
asize = qppad(atom, asize, &buffer);
|
||||
luaL_pushresult(&buffer);
|
||||
lua_pushlstring(L, (char *) atom, asize);
|
||||
return 2;
|
||||
@ -507,13 +495,13 @@ static int mime_global_unqp(lua_State *L)
|
||||
|
||||
size_t asize = 0, isize = 0;
|
||||
UC atom[3];
|
||||
const UC *input = (UC *) checklstring(L, 1, &isize);
|
||||
const UC *input = (UC *) aux_optlstring(L, 1, NULL, &isize);
|
||||
const UC *last = input + isize;
|
||||
luaL_Buffer buffer;
|
||||
luaL_buffinit(L, &buffer);
|
||||
while (input < last)
|
||||
asize = qpdecode(*input++, atom, asize, &buffer);
|
||||
input = (UC *) optlstring(L, 2, NULL, &isize);
|
||||
input = (UC *) aux_optlstring(L, 2, NULL, &isize);
|
||||
if (input) {
|
||||
last = input + isize;
|
||||
while (input < last)
|
||||
@ -537,38 +525,39 @@ static int mime_global_qpwrp(lua_State *L)
|
||||
{
|
||||
size_t size = 0;
|
||||
int left = (int) luaL_checknumber(L, 1);
|
||||
const UC *input = (UC *) checklstring(L, 2, &size);
|
||||
const UC *input = (UC *) aux_optlstring(L, 2, NULL, &size);
|
||||
const UC *last = input + size;
|
||||
int length = (int) luaL_optnumber(L, 3, 76);
|
||||
luaL_Buffer buffer;
|
||||
luaL_buffinit(L, &buffer);
|
||||
while (input < last) {
|
||||
left--;
|
||||
switch (*input) {
|
||||
case '=':
|
||||
/* if there's no room in this line for the quoted char,
|
||||
* output a soft line break now */
|
||||
if (left <= 3) {
|
||||
luaL_addstring(&buffer, EQCRLF);
|
||||
left = length;
|
||||
}
|
||||
break;
|
||||
/* \r\n starts a new line */
|
||||
case CR:
|
||||
case CR:
|
||||
break;
|
||||
case LF:
|
||||
left = length;
|
||||
luaL_addstring(&buffer, CRLF);
|
||||
break;
|
||||
default:
|
||||
/* if in last column, output a soft line break */
|
||||
if (left <= 1) {
|
||||
luaL_addstring(&buffer, EQCRLF);
|
||||
case '=':
|
||||
if (left <= 3) {
|
||||
left = length;
|
||||
luaL_addstring(&buffer, EQCRLF);
|
||||
}
|
||||
luaL_putchar(&buffer, *input);
|
||||
left--;
|
||||
break;
|
||||
default:
|
||||
if (left <= 1) {
|
||||
left = length;
|
||||
luaL_addstring(&buffer, EQCRLF);
|
||||
}
|
||||
luaL_putchar(&buffer, *input);
|
||||
left--;
|
||||
break;
|
||||
}
|
||||
luaL_putchar(&buffer, *input);
|
||||
input++;
|
||||
}
|
||||
/* if in last chunk and last line wasn't terminated, add a soft-break */
|
||||
if (!input && left < length) {
|
||||
luaL_addstring(&buffer, EQCRLF);
|
||||
left = length;
|
||||
@ -579,10 +568,10 @@ static int mime_global_qpwrp(lua_State *L)
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Here is what we do: \n, \r and \f are considered candidates for line
|
||||
* Here is what we do: \n, and \r are considered candidates for line
|
||||
* break. We issue *one* new line marker if any of them is seen alone, or
|
||||
* followed by a different one. That is, \n\n, \r\r and \f\f will issue two
|
||||
* end of line markers each, but \r\n, \n\r, \r\f etc will only issue *one*
|
||||
* followed by a different one. That is, \n\n and \r\r will issue two
|
||||
* end of line markers each, but \r\n, \n\r etc will only issue *one*
|
||||
* marker. This covers Mac OS, Mac OS X, VMS, Unix and DOS, as well as
|
||||
* probably other more obscure conventions.
|
||||
\*-------------------------------------------------------------------------*/
|
||||
@ -616,21 +605,24 @@ static int mime_global_eol(lua_State *L)
|
||||
{
|
||||
size_t asize = 0, isize = 0;
|
||||
UC atom[2];
|
||||
const UC *input = (UC *) checklstring(L, 1, &isize);
|
||||
const UC *input = (UC *) aux_optlstring(L, 1, NULL, &isize);
|
||||
const UC *last = input + isize;
|
||||
const char *marker = luaL_optstring(L, 3, CRLF);
|
||||
luaL_Buffer buffer;
|
||||
luaL_buffinit(L, &buffer);
|
||||
while (input < last)
|
||||
asize = eolconvert(*input++, atom, asize, marker, &buffer);
|
||||
input = (UC *) optlstring(L, 2, NULL, &isize);
|
||||
input = (UC *) aux_optlstring(L, 2, NULL, &isize);
|
||||
if (input) {
|
||||
last = input + isize;
|
||||
while (input < last)
|
||||
asize = eolconvert(*input++, atom, asize, marker, &buffer);
|
||||
/* if there is something in atom, it's one character, and it
|
||||
* is a candidate. so we output a new line */
|
||||
} else if (asize > 0) luaL_addstring(&buffer, marker);
|
||||
} else if (asize > 0) {
|
||||
luaL_addstring(&buffer, marker);
|
||||
asize = 0;
|
||||
}
|
||||
luaL_pushresult(&buffer);
|
||||
lua_pushlstring(L, (char *) atom, asize);
|
||||
return 2;
|
||||
|
@ -12,6 +12,6 @@
|
||||
\*=========================================================================*/
|
||||
#include <lua.h>
|
||||
|
||||
void mime_open(lua_State *L);
|
||||
int mime_open(lua_State *L);
|
||||
|
||||
#endif /* MIME_H */
|
||||
|
85
src/mime.lua
85
src/mime.lua
@ -15,70 +15,57 @@ local et = {}
|
||||
local dt = {}
|
||||
local wt = {}
|
||||
|
||||
-- creates a function that chooses an algorithm from a given table
|
||||
-- creates a function that chooses a filter from a given table
|
||||
local function choose(table)
|
||||
return function(method, ...)
|
||||
local f = table[method or "nil"]
|
||||
if not f then error("unknown method (" .. tostring(method) .. ")", 3)
|
||||
return function(filter, ...)
|
||||
local f = table[filter or "nil"]
|
||||
if not f then error("unknown filter (" .. tostring(filter) .. ")", 3)
|
||||
else return f(unpack(arg)) end
|
||||
end
|
||||
end
|
||||
|
||||
-- creates a function that cicles a filter with a given initial
|
||||
-- context and extra arguments
|
||||
local function cicle(f, ctx, ...)
|
||||
return function(chunk)
|
||||
local ret
|
||||
ret, ctx = f(ctx, chunk, unpack(arg))
|
||||
return ret
|
||||
end
|
||||
-- define the encoding filters
|
||||
et['base64'] = function()
|
||||
return socket.cicle(b64, "")
|
||||
end
|
||||
|
||||
et['quoted-printable'] = function(mode)
|
||||
return socket.cicle(qp, "", (mode == "binary") and "=0D=0A" or "\13\10")
|
||||
end
|
||||
|
||||
-- define the decoding filters
|
||||
dt['base64'] = function()
|
||||
return socket.cicle(unb64, "")
|
||||
end
|
||||
|
||||
dt['quoted-printable'] = function()
|
||||
return socket.cicle(unqp, "")
|
||||
end
|
||||
|
||||
-- define the line-wrap filters
|
||||
wt['text'] = function(length)
|
||||
length = length or 76
|
||||
return socket.cicle(wrp, length, length)
|
||||
end
|
||||
wt['base64'] = wt['text']
|
||||
|
||||
wt['quoted-printable'] = function()
|
||||
return socket.cicle(qpwrp, 76, 76)
|
||||
end
|
||||
|
||||
-- function that choose the encoding, decoding or wrap algorithm
|
||||
encode = choose(et)
|
||||
decode = choose(dt)
|
||||
|
||||
-- the wrap filter has default parameters
|
||||
-- there is a default wrap filter
|
||||
local cwt = choose(wt)
|
||||
function wrap(...)
|
||||
if not arg[1] or type(arg[1]) ~= "string" then
|
||||
table.insert(arg, 1, "base64")
|
||||
end
|
||||
if type(arg[1]) ~= "string" then table.insert(arg, 1, "text") end
|
||||
return cwt(unpack(arg))
|
||||
end
|
||||
|
||||
-- define the encoding algorithms
|
||||
et['base64'] = function()
|
||||
return cicle(b64, "")
|
||||
end
|
||||
|
||||
et['quoted-printable'] = function(mode)
|
||||
return cicle(qp, "", (mode == "binary") and "=0D=0A" or "\13\10")
|
||||
end
|
||||
|
||||
-- define the decoding algorithms
|
||||
dt['base64'] = function()
|
||||
return cicle(unb64, "")
|
||||
end
|
||||
|
||||
dt['quoted-printable'] = function()
|
||||
return cicle(unqp, "")
|
||||
end
|
||||
|
||||
-- define the wrap algorithms
|
||||
wt['base64'] = function(length, marker)
|
||||
length = length or 76
|
||||
return cicle(wrp, length, length, marker)
|
||||
end
|
||||
|
||||
wt['quoted-printable'] = function(length)
|
||||
length = length or 76
|
||||
return cicle(qpwrp, length, length)
|
||||
end
|
||||
|
||||
-- define the end-of-line translation function
|
||||
-- define the end-of-line translation filter
|
||||
function canonic(marker)
|
||||
return cicle(eol, "", marker)
|
||||
return socket.cicle(eol, "", marker)
|
||||
end
|
||||
|
||||
-- chains several filters together
|
||||
@ -104,4 +91,4 @@ function chain(...)
|
||||
end
|
||||
end
|
||||
|
||||
return code
|
||||
return mime
|
||||
|
@ -42,7 +42,7 @@ static luaL_reg func[] = {
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Initializes module
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void select_open(lua_State *L)
|
||||
int select_open(lua_State *L)
|
||||
{
|
||||
/* get select auxiliar lua function from lua code and register
|
||||
* pass it as an upvalue to global_select */
|
||||
@ -54,6 +54,7 @@ void select_open(lua_State *L)
|
||||
luaL_openlib(L, LUASOCKET_LIBNAME, func, 1);
|
||||
lua_pop(L, 1);
|
||||
aux_newclass(L, "select{fd_set}", set);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*=========================================================================*\
|
||||
|
@ -15,6 +15,6 @@
|
||||
* RCS ID: $Id$
|
||||
\*=========================================================================*/
|
||||
|
||||
void select_open(lua_State *L);
|
||||
int select_open(lua_State *L);
|
||||
|
||||
#endif /* SELECT_H */
|
||||
|
@ -4,7 +4,7 @@ if not LUASOCKET_LIBNAME then error('module requires LuaSocket') end
|
||||
local socket = _G[LUASOCKET_LIBNAME]
|
||||
if not socket then error('module requires LuaSocket') end
|
||||
-- create smtp namespace inside LuaSocket namespace
|
||||
local smtp = {}
|
||||
local smtp = socket.smtp or {}
|
||||
socket.smtp = smtp
|
||||
-- make all module globals fall into smtp namespace
|
||||
setmetatable(smtp, { __index = _G })
|
||||
@ -18,6 +18,10 @@ DOMAIN = os.getenv("SERVER_NAME") or "localhost"
|
||||
-- default server used to send e-mails
|
||||
SERVER = "localhost"
|
||||
|
||||
function stuff()
|
||||
return socket.cicle(dot, 2)
|
||||
end
|
||||
|
||||
-- tries to get a pattern from the server and closes socket on error
|
||||
local function try_receiving(connection, pattern)
|
||||
local data, message = connection:receive(pattern)
|
||||
|
37
src/tcp.c
37
src/tcp.c
@ -39,25 +39,26 @@ static int meth_dirty(lua_State *L);
|
||||
|
||||
/* tcp object methods */
|
||||
static luaL_reg tcp[] = {
|
||||
{"connect", meth_connect},
|
||||
{"send", meth_send},
|
||||
{"receive", meth_receive},
|
||||
{"bind", meth_bind},
|
||||
{"listen", meth_listen},
|
||||
{"__gc", meth_close},
|
||||
{"accept", meth_accept},
|
||||
{"setpeername", meth_connect},
|
||||
{"setsockname", meth_bind},
|
||||
{"bind", meth_bind},
|
||||
{"close", meth_close},
|
||||
{"connect", meth_connect},
|
||||
{"dirty", meth_dirty},
|
||||
{"getfd", meth_getfd},
|
||||
{"getpeername", meth_getpeername},
|
||||
{"getsockname", meth_getsockname},
|
||||
{"settimeout", meth_settimeout},
|
||||
{"close", meth_close},
|
||||
{"shutdown", meth_shutdown},
|
||||
{"setoption", meth_setoption},
|
||||
{"__gc", meth_close},
|
||||
{"getfd", meth_getfd},
|
||||
{"listen", meth_listen},
|
||||
{"receive", meth_receive},
|
||||
{"send", meth_send},
|
||||
{"setfd", meth_setfd},
|
||||
{"dirty", meth_dirty},
|
||||
{"setoption", meth_setoption},
|
||||
{"setpeername", meth_connect},
|
||||
{"setsockname", meth_bind},
|
||||
{"settimeout", meth_settimeout},
|
||||
{"shutdown", meth_shutdown},
|
||||
{NULL, NULL}
|
||||
|
||||
};
|
||||
|
||||
/* socket option handlers */
|
||||
@ -78,7 +79,7 @@ static luaL_reg func[] = {
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Initializes module
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void tcp_open(lua_State *L)
|
||||
int tcp_open(lua_State *L)
|
||||
{
|
||||
/* create classes */
|
||||
aux_newclass(L, "tcp{master}", tcp);
|
||||
@ -96,6 +97,7 @@ void tcp_open(lua_State *L)
|
||||
/* define library functions */
|
||||
luaL_openlib(L, LUASOCKET_LIBNAME, func, 0);
|
||||
lua_pop(L, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*=========================================================================*\
|
||||
@ -250,7 +252,7 @@ static int meth_listen(lua_State *L)
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int meth_shutdown(lua_State *L)
|
||||
{
|
||||
p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1);
|
||||
p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client}", 1);
|
||||
const char *how = luaL_optstring(L, 2, "both");
|
||||
switch (how[0]) {
|
||||
case 'b':
|
||||
@ -266,7 +268,8 @@ static int meth_shutdown(lua_State *L)
|
||||
sock_shutdown(&tcp->sock, 0);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
lua_pushnumber(L, 1);
|
||||
return 1;
|
||||
error:
|
||||
luaL_argerror(L, 2, "invalid shutdown method");
|
||||
return 0;
|
||||
|
@ -31,6 +31,6 @@ typedef struct t_tcp_ {
|
||||
|
||||
typedef t_tcp *p_tcp;
|
||||
|
||||
void tcp_open(lua_State *L);
|
||||
int tcp_open(lua_State *L);
|
||||
|
||||
#endif /* TCP_H */
|
||||
|
@ -141,10 +141,11 @@ int tm_gettime(void)
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Initializes module
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void tm_open(lua_State *L)
|
||||
int tm_open(lua_State *L)
|
||||
{
|
||||
luaL_openlib(L, LUASOCKET_LIBNAME, func, 0);
|
||||
lua_pop(L, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
|
@ -16,7 +16,7 @@ typedef struct t_tm_ {
|
||||
} t_tm;
|
||||
typedef t_tm *p_tm;
|
||||
|
||||
void tm_open(lua_State *L);
|
||||
int tm_open(lua_State *L);
|
||||
void tm_init(p_tm tm, int block, int total);
|
||||
int tm_get(p_tm tm);
|
||||
int tm_getretry(p_tm tm);
|
||||
|
32
src/udp.c
32
src/udp.c
@ -30,7 +30,6 @@ static int meth_getpeername(lua_State *L);
|
||||
static int meth_setsockname(lua_State *L);
|
||||
static int meth_setpeername(lua_State *L);
|
||||
static int meth_close(lua_State *L);
|
||||
static int meth_shutdown(lua_State *L);
|
||||
static int meth_setoption(lua_State *L);
|
||||
static int meth_settimeout(lua_State *L);
|
||||
static int meth_getfd(lua_State *L);
|
||||
@ -49,7 +48,6 @@ static luaL_reg udp[] = {
|
||||
{"receivefrom", meth_receivefrom},
|
||||
{"settimeout", meth_settimeout},
|
||||
{"close", meth_close},
|
||||
{"shutdown", meth_shutdown},
|
||||
{"setoption", meth_setoption},
|
||||
{"__gc", meth_close},
|
||||
{"getfd", meth_getfd},
|
||||
@ -79,7 +77,7 @@ static luaL_reg func[] = {
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Initializes module
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void udp_open(lua_State *L)
|
||||
int udp_open(lua_State *L)
|
||||
{
|
||||
/* create classes */
|
||||
aux_newclass(L, "udp{connected}", udp);
|
||||
@ -92,6 +90,7 @@ void udp_open(lua_State *L)
|
||||
/* define library functions */
|
||||
luaL_openlib(L, LUASOCKET_LIBNAME, func, 0);
|
||||
lua_pop(L, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*=========================================================================*\
|
||||
@ -287,33 +286,6 @@ static int meth_close(lua_State *L)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Shuts the connection down partially
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int meth_shutdown(lua_State *L)
|
||||
{
|
||||
p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
|
||||
const char *how = luaL_optstring(L, 2, "both");
|
||||
switch (how[0]) {
|
||||
case 'b':
|
||||
if (strcmp(how, "both")) goto error;
|
||||
sock_shutdown(&udp->sock, 2);
|
||||
break;
|
||||
case 's':
|
||||
if (strcmp(how, "send")) goto error;
|
||||
sock_shutdown(&udp->sock, 1);
|
||||
break;
|
||||
case 'r':
|
||||
if (strcmp(how, "receive")) goto error;
|
||||
sock_shutdown(&udp->sock, 0);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
error:
|
||||
luaL_argerror(L, 2, "invalid shutdown method");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Turns a master object into a server object
|
||||
\*-------------------------------------------------------------------------*/
|
||||
|
@ -27,6 +27,6 @@ typedef struct t_udp_ {
|
||||
} t_udp;
|
||||
typedef t_udp *p_udp;
|
||||
|
||||
void udp_open(lua_State *L);
|
||||
int udp_open(lua_State *L);
|
||||
|
||||
#endif /* UDP_H */
|
||||
|
@ -12,7 +12,7 @@ if not LUASOCKET_LIBNAME then error('module requires LuaSocket') end
|
||||
local socket = _G[LUASOCKET_LIBNAME]
|
||||
if not socket then error('module requires LuaSocket') end
|
||||
-- create smtp namespace inside LuaSocket namespace
|
||||
local url = {}
|
||||
local url = socket.url or {}
|
||||
socket.url = url
|
||||
-- make all module globals fall into smtp namespace
|
||||
setmetatable(url, { __index = _G })
|
||||
|
@ -70,12 +70,10 @@ int sock_select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, int timeout)
|
||||
\*-------------------------------------------------------------------------*/
|
||||
const char *sock_create(p_sock ps, int domain, int type, int protocol)
|
||||
{
|
||||
int val = 1;
|
||||
t_sock sock = socket(domain, type, protocol);
|
||||
if (sock == SOCK_INVALID) return sock_createstrerror(errno);
|
||||
*ps = sock;
|
||||
sock_setnonblocking(ps);
|
||||
setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -167,13 +165,14 @@ const char *sock_accept(p_sock ps, p_sock pa, SA *addr,
|
||||
for (;;) {
|
||||
int err;
|
||||
fd_set fds;
|
||||
/* try to accept */
|
||||
*pa = accept(sock, addr, addr_len);
|
||||
/* if result is valid, we are done */
|
||||
if (*pa != SOCK_INVALID) return NULL;
|
||||
/* find out if we failed for a fatal reason */
|
||||
if (errno != EWOULDBLOCK && errno != ECONNABORTED)
|
||||
return sock_acceptstrerror(errno);
|
||||
/* call select just to avoid busy-wait. */
|
||||
/* call select to avoid busy-wait. */
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(sock, &fds);
|
||||
do err = sock_select(sock+1, &fds, NULL, NULL, tm_getretry(tm));
|
||||
|
@ -75,12 +75,10 @@ void sock_shutdown(p_sock ps, int how)
|
||||
\*-------------------------------------------------------------------------*/
|
||||
const char *sock_create(p_sock ps, int domain, int type, int protocol)
|
||||
{
|
||||
int val = 1;
|
||||
t_sock sock = socket(domain, type, protocol);
|
||||
if (sock == SOCK_INVALID)
|
||||
return sock_createstrerror(WSAGetLastError());
|
||||
*ps = sock;
|
||||
setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val));
|
||||
sock_setnonblocking(ps);
|
||||
return NULL;
|
||||
}
|
||||
@ -112,8 +110,12 @@ const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, p_tm tm)
|
||||
/* if was in efds, we failed */
|
||||
if (FD_ISSET(sock, &efds)) {
|
||||
int why, len = sizeof(why);
|
||||
/* give windows time to set the error (disgusting) */
|
||||
Sleep(0);
|
||||
/* find out why we failed */
|
||||
getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&why, &len);
|
||||
/* we KNOW there was an error. if why is 0, we will return
|
||||
* "unknown error", but it's not really our fault */
|
||||
return sock_connectstrerror(why);
|
||||
/* otherwise it must be in wfds, so we succeeded */
|
||||
} else return NULL;
|
||||
|
@ -181,6 +181,19 @@ local function compare_b64test()
|
||||
compare(b64test, db64test)
|
||||
end
|
||||
|
||||
local function identity_test()
|
||||
local chain = socket.mime.chain(
|
||||
socket.mime.encode("quoted-printable"),
|
||||
socket.mime.encode("base64"),
|
||||
socket.mime.decode("base64"),
|
||||
socket.mime.decode("quoted-printable")
|
||||
)
|
||||
transform(b64test, eb64test, chain)
|
||||
compare(b64test, eb64test)
|
||||
os.remove(eb64test)
|
||||
end
|
||||
|
||||
|
||||
local function padcheck(original, encoded)
|
||||
local e = (socket.mime.b64(original))
|
||||
local d = (socket.mime.unb64(encoded))
|
||||
@ -233,4 +246,6 @@ compare_b64test()
|
||||
cleanup_b64test()
|
||||
padding_b64test()
|
||||
|
||||
identity_test()
|
||||
|
||||
print(string.format("done in %.2fs", socket.time() - t))
|
||||
|
@ -3,18 +3,18 @@ port = port or "8080"
|
||||
|
||||
function pass(...)
|
||||
local s = string.format(unpack(arg))
|
||||
io.write(s, "\n")
|
||||
io.stderr:write(s, "\n")
|
||||
end
|
||||
|
||||
function fail(...)
|
||||
local s = string.format(unpack(arg))
|
||||
io.write("ERROR: ", s, "!\n")
|
||||
io.stderr:write("ERROR: ", s, "!\n")
|
||||
os.exit()
|
||||
end
|
||||
|
||||
function warn(...)
|
||||
local s = string.format(unpack(arg))
|
||||
io.write("WARNING: ", s, "\n")
|
||||
io.stderr:write("WARNING: ", s, "\n")
|
||||
end
|
||||
|
||||
pad = string.rep(" ", 8192)
|
||||
@ -29,7 +29,7 @@ function remote(...)
|
||||
end
|
||||
|
||||
function test(test)
|
||||
io.write("----------------------------------------------\n",
|
||||
io.stderr:write("----------------------------------------------\n",
|
||||
"testing: ", test, "\n",
|
||||
"----------------------------------------------\n")
|
||||
end
|
||||
@ -72,14 +72,14 @@ if not socket.debug then
|
||||
fail("Please define LUASOCKET_DEBUG and recompile LuaSocket")
|
||||
end
|
||||
|
||||
io.write("----------------------------------------------\n",
|
||||
io.stderr:write("----------------------------------------------\n",
|
||||
"LuaSocket Test Procedures\n",
|
||||
"----------------------------------------------\n")
|
||||
|
||||
start = socket.time()
|
||||
|
||||
function reconnect()
|
||||
io.write("attempting data connection... ")
|
||||
io.stderr:write("attempting data connection... ")
|
||||
if data then data:close() end
|
||||
remote [[
|
||||
if data then data:close() data = nil end
|
||||
@ -348,7 +348,7 @@ end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function accept_timeout()
|
||||
io.write("accept with timeout (if it hangs, it failed): ")
|
||||
io.stderr:write("accept with timeout (if it hangs, it failed): ")
|
||||
local s, e = socket.bind("*", 0, 0)
|
||||
assert(s, e)
|
||||
local t = socket.time()
|
||||
@ -364,7 +364,8 @@ end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function connect_timeout()
|
||||
io.write("connect with timeout (if it hangs, it failed): ")
|
||||
io.stderr:write("connect with timeout (if it hangs, it failed): ")
|
||||
local t = socket.time()
|
||||
local c, e = socket.tcp()
|
||||
assert(c, e)
|
||||
c:settimeout(0.1)
|
||||
@ -380,16 +381,17 @@ end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function accept_errors()
|
||||
io.write("not listening: ")
|
||||
io.stderr:write("not listening: ")
|
||||
local d, e = socket.bind("*", 0)
|
||||
assert(d, e);
|
||||
local c, e = socket.tcp();
|
||||
assert(c, e);
|
||||
d:setfd(c:getfd())
|
||||
d:settimeout(2)
|
||||
local r, e = d:accept()
|
||||
assert(not r and e == "not listening", e)
|
||||
print("ok")
|
||||
io.write("not supported: ")
|
||||
io.stderr:write("not supported: ")
|
||||
local c, e = socket.udp()
|
||||
assert(c, e);
|
||||
d:setfd(c:getfd())
|
||||
@ -400,11 +402,11 @@ end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function connect_errors()
|
||||
io.write("connection refused: ")
|
||||
io.stderr:write("connection refused: ")
|
||||
local c, e = socket.connect("localhost", 1);
|
||||
assert(not c and e == "connection refused", e)
|
||||
print("ok")
|
||||
io.write("host not found: ")
|
||||
io.stderr:write("host not found: ")
|
||||
local c, e = socket.connect("not.exist.com", 1);
|
||||
assert(not c and e == "host not found", e)
|
||||
print("ok")
|
||||
@ -534,7 +536,7 @@ test_raw(1)
|
||||
test("non-blocking transfer")
|
||||
reconnect()
|
||||
-- the value is not important, we only want
|
||||
-- to test non-blockin I/O anyways
|
||||
-- to test non-blocking I/O anyways
|
||||
data:settimeout(200)
|
||||
test_raw(1)
|
||||
test_raw(17)
|
||||
|
@ -35,8 +35,6 @@ local check_parse_path = function(path, expect)
|
||||
for i = 1, math.max(table.getn(parsed), table.getn(expect)) do
|
||||
if parsed[i] ~= expect[i] then
|
||||
print(path)
|
||||
write("segment: ", i, " = '", Code.hexa(tostring(parsed[i])),
|
||||
"' but expected '", Code.hexa(tostring(expect[i])), "'\n")
|
||||
exit()
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user