diff --git a/doc/code.html b/doc/code.html new file mode 100644 index 0000000..45fd21a --- /dev/null +++ b/doc/code.html @@ -0,0 +1,202 @@ + + + +
++The code.lua module offers routines to convert back and forth +some common types of content encoding, including Base 64 and URL +escaping. Base 64 is described in +RFC +2045, +URL escaping is described in +RFC +2396. +
+ + + ++socket.code.base64(content, single) +
+ ++Applies the Base 64 content coding to a string. +
+ ++Content is the string to be encoded. +If single is set to anything +but nil, the output is returned as a single +line, otherwise the function splits the content into 76 character long +lines after encoding. +
+ ++The function returns the encoded string. +
+ ++code = socket.code.base64("diego:password") +-- code = "ZGllZ286cGFzc3dvcmQ=" ++ + + +
+socket.code.unbase64(content) +
+ ++Removes the Base 64 content coding from a string. +
+ ++Content is the string to be decoded. +
+ ++The function returns the decoded string. +
+ + + ++socket.code.escape(content) +
+ ++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. +
+ ++Content is the string to be encoded. +
+ ++The function returns the encoded string. +
+ ++code = socket.code.escape("/#?;") +-- code = "%2f%23%3f%3b" ++ + + +
+socket.code.unescape(content) +
+ ++Removes the URL escaping content coding from a string. +
+ ++Content is the string to be decoded. +
+ ++The function returns the decoded string. +
+ + + ++socket.code.hexa(content) +
+ ++Applies the hexadecimal content coding to a string. +Each byte is encoded as the byte hexadecimal +representation of its integer value.
+
+ ++Content is the string to be encoded. +
+ ++The function returns the encoded string. +
+ ++code = socket.code.hexa("\16\32\255") +-- code = "1020ff" ++ + + +
+socket.code.unhexa(content) +
+ ++Removes the hexadecimal content coding from a string. +
+ ++Content is the string to be decoded. +
+ ++The function returns the decoded string. +
+ + + + + + + diff --git a/doc/dns.html b/doc/dns.html new file mode 100644 index 0000000..6abf341 --- /dev/null +++ b/doc/dns.html @@ -0,0 +1,120 @@ + + + + ++The following functions can be used to convert between host names and IP +addresses. Both functions return all information returned by the +resolver in a table of the form: +
+ ++resolved = {+ +
+ name = canonic-name,
+ alias = alias-list,
+ ip = ip-address-list
+} +
+Note that the alias list can be empty. +
+ + + ++socket.dns.tohostname() +
+ ++Converts from IP address to host name. +
+ ++Address can be an IP address or host name. +
+ ++The function a string with the canonic host name of the given +address, followed by a table with all information returned by +the resolver. In case of error, the function returns nil +followed by an error message. +
+ + + + ++socket.dns.toip() +
+ ++Converts from host name to IP address. +
+ ++Address can be an IP address or host name. +
+ ++Returns a string with the first IP address found for address, +followed by a table with all information returned by the resolver. +In case of error, the function returns nil followed by an error +message. +
+ + + + + + + diff --git a/doc/ftp.html b/doc/ftp.html new file mode 100644 index 0000000..8072afe --- /dev/null +++ b/doc/ftp.html @@ -0,0 +1,243 @@ + + + ++FTP (File Transfer Protocol) is a protocol used to transfer files +between hosts. The module ftp.lua offers simple FTP support, +allowing applications to download and upload files, and list directory +contents. The implementation conforms to +RFC 959. +
+ ++URLs MUST conform to +RFC +1738, that is, an URL is a string in the form: +
+ ++ +[ftp://][<user>[:<password>]@]<host>[:<port>][/<path>][type=a|i|d] ++ + + +
+socket.ftp.get(url)
+socket.ftp.get{
+ url = string,
+ type = string,
+ user = string,
+ password = string
+}
+
+Downloads an URL from a FTP server. +
+ ++The function can be called either directly with a url +or with a request table. +Fields passed explicitly in the request table override those +present in the url. +
+ ++The parameter type accepts values 'a' (ASCII, the +default), 'i' (binary) or 'd' (directory listing) and +determines the transfer type. If <path> ends with a +'/' or type is 'd', a directory listing of +<path> is returned. If no user is provided in the +url or explicitly, the function tries to log in as user +'anonymous'. +
+ ++If successful, the function returns +the file content as a string. In case of error, the function returns +nil and an error message describing the error. +
+ ++-- Log as user "anonymous" on server "ftp.tecgraf.puc-rio.br", +-- go to directory "pub/lua" and get file "lua.tar.gz" as binary. +f, e = socket.ftp.get("ftp://ftp.tecgraf.puc-rio.br/pub/lua/lua.tar.gz;type=i") + +-- Log as user "anonymous" on server "ftp.tecgraf.puc-rio.br", +-- go to director "pub" and retrieve directory listing of directory "lua" +f, e = socket.ftp.get("ftp://ftp.tecgraf.puc-rio.br/pub/lua;type=d") + +-- Log as user "diego", password "nehab", on server "ftp.tecgraf.puc-rio.br", +-- go to directory "tec/luasocket/bin" and retrieve file "luasocket.exe" +-- (actually, fails because of wrong password, of course) +f, e = socket.ftp.get{ + url = "ftp://ftp.tecgraf.puc-rio.br/tec/luasocket/bin/luasocket.exe", + user = "diego", + password = "nehab", + type = "i" +} +-- f returns nil, and e returns an appropriate error message ++ + + +
+socket.ftp.get_cb{
+ url = string,
+ type = string,
+ content_cb = receive-callback,
+ user = string,
+ password = string
+}
+
+Same as get, but the library returns +the content of the downloaded file to the receive callback +content_cb. +
+ ++Note: for more information on callbacks, refer to +Streaming with callbacks. +
+ + + +
+socket.ftp.put(url, content)
+socket.ftp.put{
+ url = string,
+ content = string,
+ type = string,
+ user = string,
+ password = string
+}
+
+Upload a file to a FTP server. +
+ ++The function can be called directly with a +url and content parameters, or with a +request table. +Values passed explicitly in the request table override those present in +the url. The parameter type accept values +'a' (ASCII, the default) or 'i' (binary) and +determines the transfer type. If no user is provided, the +function tries to log in as 'anonymous'. +
+ ++If successful, the function returns 1. In case of error, the +function returns nil followed by a string describing the error. +
+ ++-- Log as user "anonymous" on server "ftp.free.org" and store file +-- "hello" with contents "hello world!", using binary mode for the transfer +r, e = socket.ftp.put("ftp://ftp.free.org/hello;type=i", "hello world!\n") + +-- Does exactly the same, but logging in as diego +r, e = socket.ftp.put{ + url = "ftp://ftp.free.org/hello", + type = "i", + user = "diego", + password = "nehab", + content = "hello world\n" +} ++ + + + +
+socket.ftp.put_cb{
+ url = string,
+ type = string,
+ content_cb = send-callback,
+ user = string,
+ password = string
+}
+
+Same as put, but the +library obtains the contents of the file to be uploaded using the send +callback content_cb. +
+ ++Note: for more information on callbacks, refer to +Streaming with callbacks. +
+ ++-- Log as user "anonymous" on server "ftp.free.org" and store file +-- "hello" with contents of the same file in the current directory, +-- using binary mode for the transfer +r, e = socket.ftp.put_cb{ + url = "ftp://ftp.free.org/hello", + type = "i", + content_cb = socket.callback.send_file(io.open("hello", "r")) +} ++ + + + + + + + diff --git a/doc/http.html b/doc/http.html new file mode 100644 index 0000000..b7469a4 --- /dev/null +++ b/doc/http.html @@ -0,0 +1,388 @@ + + + + +
+HTTP (Hyper Text Transfer Protocol) is the protocol used to exchange +information between web-browsers and servers. The http.lua +module offers support for the client side of the HTTP protocol (i.e., +the facilities that would be used by a web-browser implementation). The +implementation conforms to the HTTP/1.1 standard, +RFC +2616. +
+ ++The module exports functions that provide HTTP functionality in different +levels of abstraction, from a simple get, to the generic, stream oriented + request_cb. +
+ ++URLs must conform to +RFC +1738, +that is, an URL is a string in the form: +
+ +++ ++[http://][<user>[:<password>]@]<host>[:<port>][/<path>] ++
+MIME headers are represented as a Lua table in the form: +
+ +++ ++
++ +headers = {
+ field-1-name = field-1-value,
+ field-2-name = field-2-value,
+ field-3-name = field-3-value, ++ + ... + + + field-n-name = field-n-value
+} +
+Field names are case insensitive (as specified by the standard) and all +functions work with lowercase field names. +Field values are left unmodified. +
+ ++Note: MIME headers are independent of order. Therefore, there is no problem +in representing them in a Lua table. +
+ + + +
+socket.http.get(url)
+socket.http.get{
+ url = string,
+ headers = header-table,
+ user = string,
+ password = string,
+ stay = bool,
+}
+
+Performs the HTTP method GET. +
+ ++The function can be +called either directly with a url or with a request table. +The use of a request table allows complete control over the components of +the request. Values passed explicitly as fields of the request table +override those given by the url. For a description of the fields, +see the request function. +
+ ++The function returns the response message body, the mime headers, the +status code and an error message (if any). In case of failure, the +function returns all information it managed to gather. +
+ ++Note: The function is trivially implemented with the use of the +request function. +
+ ++-- connect to server "www.tecgraf.puc-rio.br" and retrieves this manual +-- file from "/luasocket/http.html" +b, h, c, e = socket.http.get("http://www.tecgraf.puc-rio.br/luasocket/http.html") + +-- connect to server "www.tecgraf.puc-rio.br" and tries to retrieve +-- "~diego/auth/index.html". Fails because authentication is needed. +b, h, c, e = socket.http.get("http://www.tecgraf.puc-rio.br/~diego/auth/index.html") +-- b returns some useless page telling about the denied access, +-- h returns authentication information +-- and c returns with value 401 (Authentication Required) + +-- tries to connect to server "wrong.host" to retrieve "/" +-- and fails because the host does not exist. +b, h, c, e = socket.http.get("http://wrong.host/") +-- b, h, c are nil, and e returns with value "host not found" ++ + + +
+socket.http.post(url, body)
+socket.http.post{
+ url = string,
+ headers = header-table,
+ body = string,
+ user = string,
+ password = string,
+ stay = bool,
+}
+
+Same as get, except +that the POST method is used and the request +message body is sent along with the request. +
+ ++Note: This function is also trivially implemented with the use of the +request function. +
+ + + +
+socket.http.request{
+ method = string,
+ url = string,
+ headers = header-table,
+ body = string,
+ user = string,
+ password = string,
+ stay = string,
+}
+
+Performs the generic HTTP request using. +
+ ++The request uses method on url +sending the request headers and request body in the +request message. If authentication information is provided, the function +uses the Basic Authentication Scheme (see note) +to retrieve the document. User and password provided +explicitly override those given by the url. The stay +parameter, when set to anything but nil, prevents the function +from automatically following 301 or 302 server redirect messages. +
+ ++The function returns a table with all components of the response message +it managed to retrieve. The response table has the following form: +
+ ++response = {+ +
+ body = string,
+ headers = header-table,
+ status = string,
+ code = number,
+ error = string
+} +
+Even when there was failure (URL not found, for example), the +function may succeed retrieving a message body (a web page informing the +URL was not found or some other useless page). To make sure the +operation was successful, check the returned status code. For +a list of the possible values and their meanings, refer to RFC +2616. +
+ ++-- Requests information about a document, without downloading it. +-- Useful, for example, if you want to display a download gauge and need +-- to know the size of the document in advance +response = socket.http.request { + method = "HEAD", + url = "http://www.tecgraf.puc-rio.br/~diego" +} +-- Would return the following headers: +-- response.headers = { +-- date = "Tue, 18 Sep 2001 20:42:21 GMT", +-- server = "Apache/1.3.12 (Unix) (Red Hat/Linux)", +-- ["last-modified"] = "Wed, 05 Sep 2001 06:11:20 GMT", +-- ["content-length"] = 15652, +-- ["connection"] = "close", +-- ["content-Type"] = "text/html" +-- } ++ + +
+Note: Some URLs are protected by their +servers from anonymous download. For those URLs, the server must receive +some sort of authentication along with the request or it will deny +download and return status "401 Authentication Required". +
+ ++The HTTP/1.1 standard defines two authentication methods: the Basic +Authentication Scheme and the Digest Authentication Scheme, both +explained in detail in +RFC 2068. +
+ +The Basic Authentication Scheme sends +<user> and +<password> unencrypted to the server and is therefore +considered unsafe. Unfortunately, by the time of this implementation, +the wide majority of servers and browsers support the Basic Scheme only. +Therefore, this is the method used by the toolkit whenever +authentication is required. +
+ ++-- Connect to server "www.tecgraf.puc-rio.br" and tries to retrieve +-- "~diego/auth/index.html", using the provided name and password to +-- authenticate the request +response = socket.http.request{ + url = "http://www.tecgraf.puc-rio.br/~diego/auth/index.html", + user = "diego", + password = "password" +} + +-- Alternatively, one could fill the appropriate header and authenticate +-- the request directly. +headers = { + authentication = "Basic " .. socket.code.base64("diego:password") +} +response = socket.http.request { + url = "http://www.tecgraf.puc-rio.br/~diego/auth/index.html", + headers = headers +} ++ + + +
+socket.http.request_cb(request, response) +
+ ++Performs the generic HTTP request. +
+ ++The function receives two tables as parameters. The request table +provides information about the request: +
+ ++request = {+ +
+ method = string,
+ url = string,
+ headers = header-table,
+ body_cb = send-callback,
+ user = string,
+ password = string,
+ stay = string,
+} +
+The function uses the HTTP method specified in +request.method on the URL request.url, +sending request.headers along with the request. The request +message body is sent via the send callback request.body_cb. +If authentication information is provided, the function uses the Basic +Authentication Scheme (see note) to +retrieve the document. Request.user and +request.password override those given by the +request.url. The request.stay parameter, when set to +anything but nil, prevents the function from automatically +following 301 or 302 server redirect messages. +
+ ++The response table specifies information about the desired +response: +
+ ++response = {+ +
+ body_cb = receive-callback
+} +
+The function returns the same response table as that returned by the +socket.http.request function, except the response message body is +returned to the receive callback given by the +response.body_cb field. +
+ ++Note: For more information on callbacks, please refer to +Streaming with callbacks. +
+ ++Note: Method names are case sensitive +
+ + + + + + + diff --git a/doc/index.html b/doc/index.html new file mode 100644 index 0000000..46642d2 --- /dev/null +++ b/doc/index.html @@ -0,0 +1,212 @@ + + + + ++LuaSocket is a Lua 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. +
+ ++Network support has been implemented so that it is both efficient and +simple to use. LuaSocket can be used by any Lua application once it has +been properly linked with and initialized by the interpreter running the +Lua application. The code has been tested and runs well on several Windows +and Unix platforms. +
+ ++The library is available under the same + +terms and conditions as the Lua language, the MIT license. The idea is +that if you can use Lua in a project, you should also be able to use +LuaSocket. +
+ +
+Copyright © 1999-2003 Tecgraf/PUC-Rio. All rights reserved.
+Author: Diego Nehab
+
+LuaSocket version 2.0 alpha is now available for download! It is +compatible with Lua 5.0 and has been tested on +Windows XP, Linux, and Mac OS X. +
+ ++The library can be downloaded in source code from the following links: +
+ ++ ++ +
+Besides the full C and Lua source code for the library, the distribution +contains several examples, this user's manual and the test procedures. +
+ ++I am also providing a Windows binary for those that want to give +LuaSocket a quick try: +
+ ++ ++ +
+This binary has been compiled with the LUASOCKET_DEBUG +option, and should be able to run the automatic test procedures. +
+ + + ++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 +and greatly improved. There have also been some API changes +that made the interface simpler and more consistent. Here are some of +the changes that made it into version 2.0: +
+ ++All previous versions of the LuaSocket library can be downloaded +here. Although +these versions are no longer supported, they are still available for +those that have compatibility issues. +
+ + + + + + + diff --git a/doc/introduction.html b/doc/introduction.html new file mode 100644 index 0000000..7adf45b --- /dev/null +++ b/doc/introduction.html @@ -0,0 +1,328 @@ + + + + ++Communication in LuaSocket is performed via I/O objects. These can +represent different network domains. Currently, support is +provided for TCP and UDP, but there is work in progress to implement SSL, +Local Domain, Pipes, File Descriptors etc. I/O objects provide a standard +interface to I/O across different domains and operating systems. +LuaSocket 2.0 has been rewritten from scratch to simplify the future +addition new domains. +
+ ++The LuaSocket API was designed with two goals in mind. First, users +experienced with the C API to sockets should feel comfortable using LuaSocket. +Second, the simplicity and the feel of the Lua language should be +preserved. To achieve these goals, the LuaSocket API keeps the function names and semantics the C API whenever possible, but their usage in Lua has been greatly simplified. +
+ ++One of the simplifications is the timeout control +mechanism. As in C, all I/O operations are blocking by default. For +example, the send, +receive and +accept methods +of the TCP domain will block the caller application until +the operation is completed (if ever!). However, with a call to the +settimeout +method, an application can specify upper limits on +the time it can be blocked by LuaSocket (the "total" timeout), on +the time LuaSocket can internally be blocked by any OS call (the +"block" timeout) or a combination of the two. Each LuaSocket +call might perform several OS calls, so that the two timeout values are +not equivalent. +
+ ++Another important difference is the receive pattern capability. +Applications can read data from stream domains (such as TCP) +line by line, block by block, or until the connection is closed. +All I/O reads are buffered and the performance differences between +different receive patterns are negligible. +
+ ++Finally, the host name resolution is transparent, meaning that most +functions and methods accept both IP addresses and host names. In case a +host name is given, the library queries the system's resolver and +tries the main returned IP address. Note that direct use of IP addresses +is more efficient, of course. The +toip +and tohostname +functions from the DNS module are provided to convert between host names and IP addresses. +
+ ++Previous versions of LuaSocket provided global functions for operating on +I/O objects. To give the library a Lua 5.0 feel, these have been eliminated +from LuaSocket 2.0. I/O operations are only available as methods of the +corresponding I/O objects. Naturally, different I/O objects accept +different operations. The core functionality for TCP and UDP objects is +introduced in the following sections, following a few words about +initialization. +
+ + + ++Beginning with version 2.0 and following the Lua 5.0 trend, all LuaSocket +functionality is defined inside a table (or rather a namespace) stored with +the global name socket. To have this table created and its +contents made available to a Lua script, the interpreter running the script +must be linked to the LuaSocket library, and to whatever libraries the +host OS requires for network access (Windows requires ws2_32.lib, for +instance). LuaSocket is initialized in the +Lua state given as the argument to the function +luaopen_socket, the only C function exported by the library. +After initialization, the scripts are free to use all LuaSocket API. +
+ + + ++TCP (Transfer Control Protocol) is reliable stream protocol. In other +words, applications communicating through TCP can send and receive data as +an error free stream of bytes. Data is split in one end and +reassembled transparently on the other end. There are no boundaries in +the data transfers. The library allows users to read data from the +sockets in several different granularity: patterns are available for +lines, arbitrary sized blocks or "read up to connection closed", all with +good performance. +
+ ++The library distinguishes three types of TCP sockets: master, client and server sockets. +
+ ++Master sockets are newly created TCP sockets returned by the function +socket.tcp. A master socket is +transformed into a server socket +after it is associated with a local address by a call to the +bind method. Conversely, it +can be changed into a client socket with the method +connect, +that associates it with a remote address. +
+ ++On server sockets, applications can use the +accept method +to wait for a client connection. Once a connection is established, a +client socket object is returned representing this connection. The +other methods available for server socket objects are +getsockname, +setoption, +settimeout and +close. +
+ ++Client sockets are used to exchange data between two applications over +the Internet. Applications can call the methods +send and +receive +to send and receive data. The other methods +available for client socket objects are +getsockname, +getpeername, +setoption, +settimeout and +close. +
+ ++Example: +
+++ + + ++A simple echo server, using LuaSocket. The program binds to an ephemeral +port (one that is chosen by the operating system) on the local host and +awaits client connections on that port. When a connection is established, +the program reads a line from the remote end and sends it back, closing +the connection immediately after. You can test it using the telnet +program. +
+ ++-- create a new TCP object +server, err = socket.tcp() +assert(server, err) +-- bind it to the local host, at any port +ret, err = server:bind("*", 0) +assert(ret, err) +-- find out which port the OS chose for us +ip, port = server:getsockname() +-- print a message informing what's up +print("Please telnet to localhost on port " .. port) +print("After connecting, you have 10s to enter a line to be echoed") +-- loop forever waiting for clients +while 1 do + -- wait for a conection from any client + client, err = server:accept() + -- make sure we don't block waiting for this client's line + client:settimeout(10) + -- receive the line + line, err = client:receive() + -- if there was no error, send it back to the client + if not err then + client:send(line .. "\n") + end + -- done with client, close the object + client:close() +end ++
+UDP (User Datagram Protocol) is a non-reliable datagram protocol. In +other words, applications communicating through UDP send and receive +data as independent blocks, which are not guaranteed to reach the other +end. Even when they do reach the other end, they are not guaranteed to be +error free. Data transfers are atomic, one datagram at a time. Reading +only part of a datagram discards the rest, so that the following read +operation will act on the next datagram. The advantages are in +simplicity (no connection setup) and performance (no error checking or +error correction). +
+ ++An UDP socket object is created by the +socket.udp function. UDP +sockets do not need to be connected before use. The method +sendto +can be used immediately after creation to +send a datagram to IP address and port. Host names are not allowed +because performing name resolution for each packet would be forbiddingly +slow. Methods +receive and +receivefrom +can be used to retrieve datagrams, the latter returning the IP and port of +the sender as extra return values (thus being slightly less +efficient). +
+ ++When communication is performed repeatedly with a single peer, an +application should call the +setpeername method to specify a +permanent partner. Methods +sendto and +receivefrom +can no longer be used, but the method +send can be used to send data +directly to the peer, and the method +receive +will only return datagrams originating +from that peer. There is about 30% performance gain due to this practice. +
+ ++To associate an UDP socket with a local address, an application calls the +setsockname +method before sending any datagrams. Otherwise, the socket is +automatically bound to an ephemeral address before the first data +transmission and once bound the local address cannot be changed. +The other methods available for UDP sockets are +getpeername, +getsockname, +settimeout, +setoption and +close. +
+ ++Example: +
+++ + + + + + + diff --git a/doc/luasocket.png b/doc/luasocket.png new file mode 100644 index 0000000..d24a954 Binary files /dev/null and b/doc/luasocket.png differ diff --git a/doc/reference.css b/doc/reference.css new file mode 100644 index 0000000..4f17046 --- /dev/null +++ b/doc/reference.css @@ -0,0 +1,40 @@ +body { + margin-left: 1em; + margin-right: 1em; +} + +body > * { margin-left: 1em; } + +div.header, div.footer { margin-left: 0em; } +hr, h1, h2, h3, h4 { margin-left: 0em; } +p.name { margin-left: 0em; } + +h2:first-letter, h2:first-letter, h3:first-letter { color: #00007f; } + +blockquote { margin-left: 3em; } + +a[href] { color: #00007f; } + +p.name { + font-size: large; + font-family: monospace; + padding-top: 1em; +} + +pre.example { + background: #ccc; + font-size: small; + padding: 1em; +} + +hr { + background: #00007f; + border: 0px; + height: 1px; +} + +ul { list-style-type: disc; } + +table.index { border: 1px #00007f; } +table.index td { text-align: left; vertical-align: top; } +table.index ul { padding-top: 0em; margin-top: 0em; } diff --git a/doc/reference.html b/doc/reference.html new file mode 100644 index 0000000..39f6437 --- /dev/null +++ b/doc/reference.html @@ -0,0 +1,209 @@ + + + + ++A simple daytime client, using LuaSocket. The program connects to a remote +server and tries to retrieve the daytime, printing the answer it got or an +error message. +
+ ++host = "localhost" -- change here to the host you want to contact +port = port or 13 +-- convert host name to ip address +ip, err = socket.toip(host) +assert(ip, err) +-- create a new UDP object +udp = socket.udp() +-- contact daytime host +nsent, err = udp:sendto("anything", ip, port) +assert(not err, err) +-- retrieve the answer +dgram, err = udp:receive() +assert(dgram, err) +-- display to user +print(dgram) ++
|
+
|
+
|
+
|
+
|
+
|
+
|
|
+
|
+
|
++ |
+The module smtp.lua provides functionality to send e-mail +messages. The implementation conforms to the Simple Mail Transfer Protocol, +RFC 2821. +The other RFC of interest in this implementation is +RFC 2822, +which governs the Internet Message Format. + +
+ ++MIME headers are represented as a Lua table in the form: +
+ +++ ++
++ +headers = {
+ field-1-name = field-1-value,
+ field-2-name = field-2-value,
+ field-3-name = field-3-value, ++ + ... + + + field-n-name = field-n-value
+} +
+Field names are case insensitive (as specified by the standard) and all +functions work with lowercase field names. +Field values are left unmodified. +
+ ++Note: MIME headers are independent of order. Therefore, there is no problem +in representing them in a Lua table. +
+ + + +
+socket.smtp.mail{
+ from = string,
+ rcpt = string or string-table,
+ body = string,
+ headers = headers-table,
+ server = string
+}
+
+Sends a message to a recipient list. +
+ ++Rcpt is a Lua table with one entry for each recipient, or a string +in case there is just one recipient. +The sender is given by the e-mail address from. +The message is composed by the optional MIME Headers headers +and text body. The message is sent using the server +server. +
+ ++If successful, the function returns 1. Otherwise, the function returns +nil followed by an error message. +
+ ++Big note: There is a good deal of misconception with the use of the +destination address field headers, i.e., the 'To', 'Cc', +and, more importantly, the 'Bcc' headers. Do not add a +'Bcc' header to your messages because it will probably do the +exact opposite of what you expect. +
+ ++Only recipients specified in the recipient list will receive a copy of the +message. Each recipient of an SMTP mail message receives a copy of the +message body along with the headers, and nothing more. The headers are +considered as part of the message. The list of recipients is not +part of the message. +
+ ++RFC 2822 +has two important and short sections, "3.6.3. Destination address +fields" and "5. Security considerations", explaining the proper +use of these headers. Here is a summary of what it says: +
+ ++The LuaSocket mail function does not interpret the headers you +pass to, but it gives you full control over what is sent and to whom +it is sent: +
++I hope this clarifies the issue. Otherwise, please refer to +RFC 2821 +and +RFC 2822. +
+ ++-- Connects to server "localhost" and sends a message to users +-- "fulano@tecgraf.puc-rio.br", "beltrano@tecgraf.puc-rio.br", +-- and "sicrano@tecgraf.puc-rio.br". +-- Note that "fulano" is the primary recipient, "beltrano" receives a +-- carbon copy and neither of them knows that "sicrano" received a blind +-- carbon copy of the message. +headers = { + to = "fulano@tecgraf.puc-rio.br", + cc = "beltrano@tecgraf.puc-rio.br", + subject = "LuaSocket test message" +} + +from = "luasocket@tecgraf.puc-rio.br" + +rcpt = { + "fulano@tecgraf.puc-rio.br", + "beltrano@tecgraf.puc-rio.br", + "sicrano@tecgraf.puc-rio.br" +} + +body = "This is a test message. Please ignore." + +server = "localhost" + +r, e = socket.smtp.mail{ + from = from, + rcpt = rcpt, + headers = headers, + body = body, + server = server +} ++ + + + + + + diff --git a/doc/stream.html b/doc/stream.html new file mode 100644 index 0000000..296ca2e --- /dev/null +++ b/doc/stream.html @@ -0,0 +1,173 @@ + + + + +
+HTTP and FTP 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 message bodies and FTP +file contents to be received or sent through the callback mechanism +outlined below. +
+ ++Instead of returning the entire contents of a FTP file or HTTP message +body as strings to the Lua application, the library allows the user to +provide a receive callback that will be called with successive +chunks of data, as the data becomes available. Conversely, the send +callbacks should be used when data needed by LuaSocket +is generated incrementally by the application. +
+ + + ++receive_cb(chunk, err) +
+ ++The callback provided by the user will be repeatedly called by the +library whenever new data is available. Each time it is called, the +callback receives successive chunks of downloaded data. +
+ ++Chunk contains the current chunk of data. +When the transmission is over, the function is called with an +empty string (i.e. "") as the chunk. If an error occurs, the +function receives nil as chunk and an error message as +err. +
+ ++The callback can abort transmission by returning +nil as its first return value. In that case, it can also return +an error message. Any non-nil return value proceeds with the +transmission. +
+ ++-- The implementation of socket.callback.receive_concat +function Public.receive_concat(concat) + concat = concat or socket.concat.create() + local callback = function(chunk, err) + -- if not finished, add chunk + if chunk and chunk ~= "" then + concat:addstring(chunk) + return 1 + end + end + return callback, concat +end ++ + + +
+send_cb() +
+ ++The callback provided by the user will be repeatedly called whenever the +library needs more data to be sent. +
+ ++Each time the callback is called, it +should return the next part of the information the library is expecting, +followed by the total number of bytes to be sent. +The callback can abort +the process at any time by returning nil followed by an +optional error message. +
+ + ++Note: The need for the second return value comes from the fact that, with +the HTTP protocol for instance, the library needs to know in advance the +total number of bytes that will be sent. +
+ ++-- The implementation of socket.callback.send_file +function Public.send_file(file) + local callback + -- if successfull, return the callback that reads from the file + if file then + -- get total size + local size = file:seek("end") + -- go back to start of file + file:seek("set") + callback = function() + -- send next block of data + local chunk = file:read(Public.BLOCKSIZE) + if not chunk then file:close() end + return chunk, size + end + -- else, return a callback that just aborts the transfer + else + callback = function() + -- just abort + return nil, "unable to open file" + end + end + return callback, file +end ++ + + + + + + diff --git a/doc/tcp.html b/doc/tcp.html new file mode 100644 index 0000000..ecbedaa --- /dev/null +++ b/doc/tcp.html @@ -0,0 +1,415 @@ + + + + +
+socket.tcp() +
+ ++Creates and returns a TCP master object. A master object can +be transformed into a server object with the method +bind or into a client object with the method +connect. The only other method +supported by a master object is the close +method.
+ ++In case of success, a new master object is returned. In case of error, +nil is returned, followed by an error message. +
+ + + ++server:accept() +
+ ++Waits for a remote connection on the server +object and returns a client object representing that connection. +
+ ++If a connection is successfully initiated, a client object is returned. +If a timeout condition is met, the method returns nil followed +by the error string 'timeout'. +
+ ++Note: calling socket.select +with a server object in +the receive parameter before a call to accept does +not guarantee accept will return immediately. Use the settimeout method or accept +might block until another client shows up. +
+ + + ++master:bind(address, port [, backlog]) +
+ ++Binds a master object to address and port on the +local host, transforming it into a server object. Server +objects support the +accept, +getsockname, +setoption, +settimeout, +and close methods. +
+ ++Address can be an IP address or a host name. +Port must be an integer number in the range [0..64K]. +If address +is '*', the system binds to all local interfaces +using the INADDR_ANY constant. If port is 0, the system automatically +chooses an ephemeral port. The optional parameter backlog, 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. +
+ ++In case of success, the method returns 1. In case of error, the +method returns nil followed by an error message. +
+ ++Note: The function socket.bind is available and is a short +for socket.tcp followed by the bind method. +
+ + + +
+master:close()
+client:close()
+server:close()
+
+Closes a TCP object. The internal socket used by the object is closed +and the local address to which the object was +bound is made available to other applications. No further operations +(except for further calls to the close method) are allowed on +a closed socket. +
+ ++Note: It is important to close all used sockets once they are not +needed, since, in many systems, each socket uses a file descriptor, +which are limited system resources. Garbage-collected objects are +automatically closed before destruction, though. +
+ + + ++master:connect(address, port) +
+ ++Attempts to connect a master object to a remote host, transforming it into a +client object. Client objects support methods +send, +receive, +getsockname, +getpeername, +settimeout, +and close. +
+ ++Address can be an IP address or a host name. +Port must be an integer number in the range [1..64K]. +
+ ++In case of error, the method returns nil followed by a string +describing the error. In case of success, the method returns 1. +
+ ++Note: The function socket.connect is available and is a short +for socket.tcp followed by the connect method. +
+ + + ++client:getpeername() +
+ ++Returns information about the remote side of a connected client object. +
+ ++Returns a string with the IP address of the peer, followed by the +port number that peer is using for the connection. +In case of error, the method returns nil. +
+ ++Note: It makes no sense to call this method on server objects. +
+ + + +
+client:getsockname()
+server:getsockname()
+
+Returns the local address information associated to the object. +
+ ++The method returns a string with local IP address and a number with +the port. In case of error, the method returns nil. +
+ ++Note: Naturally, for a server object, the address and port returned are +those passed to the bind 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. +
+ + + ++client:receive([pattern1, pattern2, +... patternN]) +
+ ++Reads data from a client object, according to the specified read +patterns. Patterns follow the Lua file I/O format, and the difference in performance between all patterns is negligible. +
+ ++The parameters pattern1, pattern2, ... +patternN can be any of the following: +
+ ++The method returns one value for each pattern, followed by a single +error code that can be nil in case of success, the string +'closed' in case the connection was closed before the +transmission was completed or the string 'timeout' in case +there was a timeout during the operation. +
+ ++Note: In case of error, the method always return everything it managed +to download before the error condition was met. +
+ + + ++client:send(string1 [, +string2, ... stringN]) +
+ ++Sends data through client object. +
+ ++All parameters should be strings. For small strings, it is always better to +concatenate them in Lua (with the '..' operator) and pass the +result to LuaSocket instead of passing several independent strings. +
+ ++The method returns the number of bytes accepted by the transport layer, +followed by an error code. The error code is nil if the operation +completed with no errors, the string 'closed' in case +the connection was closed before the transmission was completed or the +string 'timeout' in case there was a timeout during the +operation. +
+ ++Note: The return values for the send method have been changed in +LuaSocket 2.0! In previous versions, the method returned only the +error message. Since returning nil in case of success goes +against all other LuaSocket methods and functions, the +send method been changed for the sake of uniformity. +
+ + + +
+client:setoption(option [, value])
+server:setoption(option [, value])
+
+Sets options for the TCP object. Options are only needed by low-level or +time-critical applications. You should only modify a an option if you +are sure you need it. +
+ ++Option is a string with the option name, and value +depends on the option being set: + +
+The method returns 1 in case of success, or nil otherwise. +
+ ++Note: The descriptions above come from the man pages. +
+ + + +
+client:settimeout(value [, mode])
+server:settimeout(value [, mode])
+
+Changes the timeout values for the object. By default, +all I/O operations are blocking. That is, any call to the methods +send, +receive, and +accept +will block indefinitely, until the operation completes. The +settimeout method defines a limit on the amount of time the +I/O methods can block. When a timeout is set and the specified amount of +time has elapsed, the affected methods give up and fail with an error code. +
+ ++The amount of time to wait is specified as the +value parameter, in seconds. There are two timeout modes and +both can be used together for fine tuning: +
+ ++The nil timeout value allows operations to block +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. +
+ ++Note: The old timeout method is deprecated. The name has been +changed for sake of uniformity, since all other method names already +contained verbs making their imperative nature obvious. +
+ + + + + + + diff --git a/doc/udp.html b/doc/udp.html new file mode 100644 index 0000000..235c0c5 --- /dev/null +++ b/doc/udp.html @@ -0,0 +1,400 @@ + + + ++socket.udp() +
+ ++Creates and returns an unconnected UDP object. Unconnected objects support the +sendto, +receive, +receivefrom, +getsockname, +setoption, +settimeout, +setpeername, +setsockname, and +close. +The setpeername +is used to connect the object. +
+ ++In case of success, a new unconnected UDP object +returned. In case of error, nil is returned, followed by +an error message. +
+ + + +
+connected:close()
+unconnected:close()
+
+Closes a UDP object. The internal socket +used by the object is closed and the local address to which the +object was bound is made available to other applications. No +further operations (except for further calls to the close +method) are allowed on a closed socket. +
+ ++Note: It is important to close all used sockets +once they are not needed, since, in many systems, each socket uses +a file descriptor, which are limited system resources. +Garbage-collected objects are automatically closed before +destruction, though. +
+ + + ++connected:getpeername() +
+ ++Retrieves information about the peer +associated with a connected UDP object. +
+ ++Returns the IP address and port number of the peer. +
+ ++Note: It makes no sense to call this method on unconnected objects. +
+ + + +
+connected:getsockname()
+unconnected:getsockname()
+
+Returns the local address information associated to the object. +
+ ++The method returns a string with local IP +address and a number with the port. In case of error, the method +returns nil. +
+ ++Note: UDP sockets are not bound to any address +until the setsockname or the +sendto method is called for the +first time (in which case it is bound to an ephemeral port and the +wild-card address). +
+ + + +
+connected:receive([size])
+unconnected:receive([size])
+
+Receives a datagram from the UDP object. If +the UDP object is connected, only datagrams coming from the peer +are accepted. Otherwise, the returned datagram can come from any +host. +
+ ++The optional size parameter +specifies the maximum size of the datagram to be retrieved. If +there are more than size bytes available in the datagram, +the excess bytes are discarded. If there are less then +size bytes available in the current datagram, the +available bytes are returned. If size is omitted, the +maximum datagram size is used. +
+ ++In case of success, the method return the +received datagram. In case of timeout, the method returns +nil followed by the string 'timeout'. +
+ + + ++unconnected:receivefrom([size]) +
+ ++Works exactly as the receive +method, except it returns the IP +address and port as extra return values (and is therefore slightly less +efficient). +
+ + + ++connected:send(datagram) +
+ ++Sends a datagram to the UDP peer of a connected object. +
+ ++Datagram is a string with the datagram contents. +Beware that the maximum datagram size for UDP is 576 bytes. +
+ ++If successful, the method returns 1. In case of +error, the method returns nil followed by the +'refused' message. +
+ ++Note: In UDP, the send method never blocks +and the only way it can fail is if the underlying transport layer +refuses to send a message to the specified address (i.e. no +interface accepts the address). +
+ + + ++unconnected:sendto(datagram, ip, port) +
+ ++Sends a datagram to the specified IP address and port number. +
+ ++Datagram is a string with the +datagram contents. Beware that the maximum datagram size for UDP is +576 bytes. Ip is the IP address of the recipient. Host +names are not allowed for performance reasons. +Port is the port number at the recipient. +
+ ++If successful, the method returns 1. In case of +error, the method returns nil followed by the +'refused' message. +
+ ++Note: In UDP, the send method never blocks +and the only way it can fail is if the underlying transport layer +refuses to send a message to the specified address (i.e. no +interface accepts the address). +
+ + + +
+connected:setpeername('*')
+unconnected:setpeername(address, port)
+
+Changes the peer of a UDP object. This +method turns an unconnected UDP object into a connected UDP +object or vice-versa. +
+ ++For connected objects, outgoing datagrams +will be sent to the specified peer, and datagrams received from +other peers will be discarded by the OS. Connected UDP objects must +use the send and +receive methods instead of +sendto and +receivefrom. +
+ ++Address can be an IP address or a +host name. Port is the port number. If address is +'*' and the object is connected, the peer association is +removed and the object becomes an unconnected object again. In that +case, the port argument is ignored. +
+ ++In case of error the method returns +nil followed by an error message. In case of success, the +method returns 1. +
+ ++Note: Since the address of the peer does not have +to be passed to and from the OS, the use of connected UDP objects +is recommended when the same peer is used for several transmissions +and can result in up to 30% performance gains. +
+ + + ++unconnected:setsockname(address, port) +
+ ++Binds the UDP object to a local address. +
+ ++Address can be an IP address or a +host name. If address is '*' the system binds to +all local interfaces using the constant INADDR_ANY. If +port is 0, the system chooses an ephemeral port. +
+ ++If successful, the method returns 1. In case of +error, the method returns nil followed by an error +message. +
+ ++Note: This method can only be called before any +datagram is sent through the UDP object, and only once. Otherwise, +the system automatically binds the object to all local interfaces +and chooses an ephemeral port as soon as the first datagram is +sent. After the local address is set, either automatically by the +system or explicitly by setsockname, it cannot be +changed. +
+ + + +
+connected:setoption(option [, value])
+unconnected:setoption(option [, value])
+
+Sets options for the UDP object. Options are +only needed by low-level or time-critical applications. You should +only modify a an option if you are sure you need it.
+Option is a string with the option +name, and value depends on the option being set: +
+ ++The method returns 1 in case of success, or +nil followed by an error message otherwise. +
+ ++Note: The descriptions above come from the man +pages. +
+ + + +
+connected:settimeout(value)
+unconnected:settimeout(value)
+
+Changes the timeout values for the object. By default, the +receive and +receivefrom +operations are blocking. That is, any call to the methods will block +indefinitely, until data arrives. The settimeout function defines +a limit on the amount of time the functions can block. When a timeout is +set and the specified amount of time has elapsed, the affected methods +give up and fail with an error code. +
+ ++The amount of time to wait is specified as +the value parameter, in seconds. The nil timeout +value allows operations to block indefinitely. Negative +timeout values have the same effect. +
+ ++Note: In UDP, the send +and sendto methods never block (the +datagram is just passed to the OS and the call returns +immediately). Therefore, the settimeout method has no +effect on them. +
+ ++Note: The old timeout method is +deprecated. The name has been changed for sake of uniformity, since +all other method names already contained verbs making their +imperative nature obvious. +
+ + + + + + + diff --git a/doc/url.html b/doc/url.html new file mode 100644 index 0000000..e67ea13 --- /dev/null +++ b/doc/url.html @@ -0,0 +1,265 @@ + + + + ++The module url.lua provides functions to parse, protect, +and build URLs, as well as functions to compose absolute URLs +from base and relative URLs, according to +RFC +2396. +
+ ++An URL is defined by the following grammar: +
+ ++ +<url> ::= [<scheme>:][//<authority>][/<path>][;<params>][?<query>][#<fragment>]+ + + +
+<authority> ::= [<userinfo>@]<host>[:<port>]
+<userinfo> ::= <user>[:<password>]
+<path> ::= {<segment>/}<segment>
+ +
+socket.url.absolute(base, relative) +
+ ++Builds an absolute URL from a base URL and a relative URL. +
+ ++Base is a string with the base URL and relative is a +string with the relative URL. +
+ ++The function returns a string with the absolute URL. +
+ ++Note: The rules that +govern the composition are fairly complex, and are described in detail in +RFC 2396. +The example bellow should give an idea of what are the rules. +
+ ++http://a/b/c/d;p?q + ++ + +g:h = g:h +g = http://a/b/c/g +./g = http://a/b/c/g +g/ = http://a/b/c/g/ +/g = http://a/g +//g = http://g +?y = http://a/b/c/?y +g?y = http://a/b/c/g?y +#s = http://a/b/c/d;p?q#s +g#s = http://a/b/c/g#s +g?y#s = http://a/b/c/g?y#s +;x = http://a/b/c/;x +g;x = http://a/b/c/g;x +g;x?y#s = http://a/b/c/g;x?y#s +. = http://a/b/c/ +./ = http://a/b/c/ +.. = http://a/b/ +../ = http://a/b/ +../g = http://a/b/g +../.. = http://a/ +../../ = http://a/ +../../g = http://a/g ++ + + +
+socket.url.build(parsed_url) +
+ ++Rebuilds an URL from its parts. +
+ ++Parsed_url is a table with same components returned by +parse. +Lower level components, if specified, +take precedence over hight level components of the URL grammar. +
+ ++The function returns a string with the built URL. +
+ + + ++socket.url.build_path(segments, unsafe) +
+ ++Builds a <path> component from a list of +<segment> parts. +Before composition, any reserved characters found in a segment are escaped into +their protected form, so that the resulting path is a valid URL path +component. +
+ ++Segments is a list of strings with the <segment> +parts. If unsafe is anything but nil, reserved +characters are left untouched. +
+ ++The function returns a string with the +built <path> component. +
+ + + ++socket.url.parse(url, default) +
+ ++Parses an URL given as a string into a Lua table with its components. +
+ ++Url is the URL to be parsed. If the default table is +present, it is used to store the parsed fields. Only fields present in the +URL are overwritten. Therefore, this table can be used to pass default +values for each field. +
+ ++The function returns a table with all the URL components: +
+ ++parsed_url = {+ +
+ url = string,
+ scheme = string,
+ authority = string,
+ path = string,
+ params = string,
+ query = string,
+ fragment = string,
+ userinfo = string,
+ host = string,
+ port = string,
+ user = string,
+ password = string
+} +
+parsed_url = socket.url.parse("http://www.puc-rio.br/~diego/index.lua?a=2#there") +-- parsed_url = { +-- scheme = "http", +-- authority = "www.puc-rio.br", +-- path = "/~diego/index.lua" +-- query = "a=2", +-- fragment = "there", +-- host = "www.puc-rio.br", +-- } + +parsed_url = socket.url.parse("ftp://root:passwd@unsafe.org/pub/virus.exe;type=i") +-- parsed_url = { +-- scheme = "ftp", +-- authority = "root:passwd@unsafe.org", +-- path = "/pub/virus.exe", +-- params = "type=i", +-- userinfo = "root:passwd", +-- host = "unsafe.org", +-- user = "root", +-- password = "passwd", +-- } ++ + + +
+socket.url.parse_path(path) +
+ ++Breaks a <path> URL component into all its +<segment> parts. +
+ ++Path is a string with the path to be parsed. +
+ ++Since some characters are reserved in URLs, they must be escaped +whenever present in a <path> component. Therefore, before +returning a list with all the parsed segments, the function unescapes all +of them. +
+ + + + + + +