diff --git a/doc/http.html b/doc/http.html index cd41c0d..3b7a8b1 100644 --- a/doc/http.html +++ b/doc/http.html @@ -112,12 +112,15 @@ the HTTP module:
+Note: These constants are global. Changing them will also +change the behavior other code that might be using LuaSocket. +
diff --git a/doc/mime.html b/doc/mime.html index ae136fd..8cb3507 100644 --- a/doc/mime.html +++ b/doc/mime.html @@ -72,34 +72,6 @@ local mime = require("mime")-mime.normalize([marker]) -
- --Converts most common end-of-line markers to a specific given marker. -
- --Marker is the new marker. It defaults to CRLF, the canonic -end-of-line marker defined by the MIME standard. -
- --The function returns a filter that performs the conversion. -
- --Note: There is no perfect solution to this problem. Different end-of-line -markers are an evil that will probably plague developers forever. -This function, however, will work perfectly for text created with any of -the most common end-of-line markers, i.e. the Mac OS (CR), the Unix (LF), -or the DOS (CRLF) conventions. Even if the data has mixed end-of-line -markers, the function will still work well, although it doesn't -guarantee that the number of empty lines will be correct. -
@@ -159,6 +131,35 @@ base64 = ltn12.filter.chain( ) + + ++mime.normalize([marker]) +
+ ++Converts most common end-of-line markers to a specific given marker. +
+ ++Marker is the new marker. It defaults to CRLF, the canonic +end-of-line marker defined by the MIME standard. +
+ ++The function returns a filter that performs the conversion. +
+ ++Note: There is no perfect solution to this problem. Different end-of-line +markers are an evil that will probably plague developers forever. +This function, however, will work perfectly for text created with any of +the most common end-of-line markers, i.e. the Mac OS (CR), the Unix (LF), +or the DOS (CRLF) conventions. Even if the data has mixed end-of-line +markers, the function will still work well, although it doesn't +guarantee that the number of empty lines will be correct. +
+@@ -466,7 +467,7 @@ marker.
Last modified by Diego Nehab on
-Thu Apr 20 00:25:44 EDT 2006
+Fri Mar 4 15:19:17 BRT 2016
+smtp.message(mesgt) +
+ ++Returns a simple +LTN12 source that sends an SMTP message body, possibly multipart (arbitrarily deep). +
+ ++The only parameter of the function is a table describing the message. +Mesgt has the following form (notice the recursive structure): +
+ +++ ++
++ +mesgt = {
+ headers = header-table,
+ body = LTN12 source or string or +multipart-mesgt
+}
+
+multipart-mesgt = {
+ [preamble = string,]
+ [1] = mesgt,
+ [2] = mesgt,
+ ...
+ [n] = mesgt,
+ [epilogue = string,]
+}
+
+For a simple message, all that is needed is a set of headers +and the body. The message body can be given as a string +or as a simple +LTN12 +source. For multipart messages, the body is a table that +recursively defines each part as an independent message, plus an optional +preamble and epilogue. +
+ ++The function returns a simple +LTN12 +source that produces the +message contents as defined by mesgt, chunk by chunk. +Hopefully, the following +example will make things clear. When in doubt, refer to the appropriate RFC +as listed in the introduction.
+ ++-- load the smtp support and its friends +local smtp = require("socket.smtp") +local mime = require("mime") +local ltn12 = require("ltn12") + +-- creates a source to send a message with two parts. The first part is +-- plain text, the second part is a PNG image, encoded as base64. +source = smtp.message{ + headers = { + -- Remember that headers are *ignored* by smtp.send. + from = "Sicrano de Oliveira <sicrano@example.com>", + to = "Fulano da Silva <fulano@example.com>", + subject = "Here is a message with attachments" + }, + body = { + preamble = "If your client doesn't understand attachments, \r\n" .. + "it will still display the preamble and the epilogue.\r\n" .. + "Preamble will probably appear even in a MIME enabled client.", + -- first part: no headers means plain text, us-ascii. + -- The mime.eol low-level filter normalizes end-of-line markers. + [1] = { + body = mime.eol(0, [[ + Lines in a message body should always end with CRLF. + The smtp module will *NOT* perform translation. However, the + send function *DOES* perform SMTP stuffing, whereas the message + function does *NOT*. + ]]) + }, + -- second part: headers describe content to be a png image, + -- sent under the base64 transfer content encoding. + -- notice that nothing happens until the message is actually sent. + -- small chunks are loaded into memory right before transmission and + -- translation happens on the fly. + [2] = { + headers = { + ["content-type"] = 'image/png; name="image.png"', + ["content-disposition"] = 'attachment; filename="image.png"', + ["content-description"] = 'a beautiful image', + ["content-transfer-encoding"] = "BASE64" + }, + body = ltn12.source.chain( + ltn12.source.file(io.open("image.png", "rb")), + ltn12.filter.chain( + mime.encode("base64"), + mime.wrap() + ) + ) + }, + epilogue = "This might also show up, but after the attachments" + } +} + +-- finally send it +r, e = smtp.send{ + from = "<sicrano@example.com>", + rcpt = "<fulano@example.com>", + source = source, +} ++ +
@@ -275,123 +393,6 @@ r, e = smtp.send{ } - - -
-smtp.message(mesgt) -
- --Returns a simple -LTN12 source that sends an SMTP message body, possibly multipart (arbitrarily deep). -
- --The only parameter of the function is a table describing the message. -Mesgt has the following form (notice the recursive structure): -
- --- --
-- -mesgt = {
- headers = header-table,
- body = LTN12 source or string or -multipart-mesgt
-}
-
-multipart-mesgt = {
- [preamble = string,]
- [1] = mesgt,
- [2] = mesgt,
- ...
- [n] = mesgt,
- [epilogue = string,]
-}
-
-For a simple message, all that is needed is a set of headers -and the body. The message body can be given as a string -or as a simple -LTN12 -source. For multipart messages, the body is a table that -recursively defines each part as an independent message, plus an optional -preamble and epilogue. -
- --The function returns a simple -LTN12 -source that produces the -message contents as defined by mesgt, chunk by chunk. -Hopefully, the following -example will make things clear. When in doubt, refer to the appropriate RFC -as listed in the introduction.
- ---- load the smtp support and its friends -local smtp = require("socket.smtp") -local mime = require("mime") -local ltn12 = require("ltn12") - --- creates a source to send a message with two parts. The first part is --- plain text, the second part is a PNG image, encoded as base64. -source = smtp.message{ - headers = { - -- Remember that headers are *ignored* by smtp.send. - from = "Sicrano de Oliveira <sicrano@example.com>", - to = "Fulano da Silva <fulano@example.com>", - subject = "Here is a message with attachments" - }, - body = { - preamble = "If your client doesn't understand attachments, \r\n" .. - "it will still display the preamble and the epilogue.\r\n" .. - "Preamble will probably appear even in a MIME enabled client.", - -- first part: no headers means plain text, us-ascii. - -- The mime.eol low-level filter normalizes end-of-line markers. - [1] = { - body = mime.eol(0, [[ - Lines in a message body should always end with CRLF. - The smtp module will *NOT* perform translation. However, the - send function *DOES* perform SMTP stuffing, whereas the message - function does *NOT*. - ]]) - }, - -- second part: headers describe content to be a png image, - -- sent under the base64 transfer content encoding. - -- notice that nothing happens until the message is actually sent. - -- small chunks are loaded into memory right before transmission and - -- translation happens on the fly. - [2] = { - headers = { - ["content-type"] = 'image/png; name="image.png"', - ["content-disposition"] = 'attachment; filename="image.png"', - ["content-description"] = 'a beautiful image', - ["content-transfer-encoding"] = "BASE64" - }, - body = ltn12.source.chain( - ltn12.source.file(io.open("image.png", "rb")), - ltn12.filter.chain( - mime.encode("base64"), - mime.wrap() - ) - ) - }, - epilogue = "This might also show up, but after the attachments" - } -} - --- finally send it -r, e = smtp.send{ - from = "<sicrano@example.com>", - rcpt = "<fulano@example.com>", - source = source, -} --
+socket.headers.canonic
+ +The socket.headers.canonic table +is used by the HTTP and SMTP modules to translate from +lowercase field names back into their canonic +capitalization. When a lowercase field name exists as a key +in this table, the associated value is substituted in +whenever the field name is sent out. +
+ ++You can obtain the headers namespace if case run-time +modifications are required by running: +
+ ++-- loads the headers module +local headers = require("headers") ++ +
@@ -90,7 +114,7 @@ of connect are defined as simple helper functions that restrict the -
+
socket._DEBUG
@@ -99,6 +123,19 @@ This constant is set to true if the library was compiled with debug support. + + ++socket._DATAGRAMSIZE +
+ ++Default datagram size used by calls to +receive and +receivefrom. +(Unless changed in compile time, the value is 8192.) +
+@@ -106,8 +143,7 @@ socket.gettime()
-Returns the time in seconds, relative to the origin of the -universe. You should subtract the values returned by this function +Returns the UNIX time in seconds. You should subtract the values returned by this function to get meaningful values.
@@ -117,29 +153,6 @@ t = socket.gettime() print(socket.gettime() - t .. " seconds elapsed") - - --socket.headers.canonic
- -The socket.headers.canonic table -is used by the HTTP and SMTP modules to translate from -lowercase field names back into their canonic -capitalization. When a lowercase field name exists as a key -in this table, the associated value is substituted in -whenever the field name is sent out. -
- --You can obtain the headers namespace if case run-time -modifications are required by running: -
- ---- loads the headers module -local headers = require("headers") --
@@ -155,8 +168,7 @@ is raised.
Finalizer is a function that will be called before -try throws the exception. It will be called -in protected mode. +try throws the exception.
@@ -204,15 +216,9 @@ to throw exceptions.
-Returns an equivalent function that instead of throwing exceptions, -returns nil followed by an error message. -
- --Note: Beware that if your function performs some illegal operation that -raises an error, the protected function will catch the error and return it -as a string. This is because the try function -uses errors as the mechanism to throw exceptions. +Returns an equivalent function that instead of throwing exceptions in case of +a failed try call, returns nil +followed by an error message.
@@ -238,7 +244,9 @@ non-numeric indices) in the arrays will be silently ignored.The function returns a list with the sockets ready for reading, a list with the sockets ready for writing and an error message. -The error message is "timeout" if a timeout condition was met and +The error message is "timeout" if a timeout +condition was met, "select failed" if the call +to select failed, and nil otherwise. The returned tables are doubly keyed both by integers and also by the sockets themselves, to simplify the test if a specific socket has @@ -246,7 +254,7 @@ changed status.
-Note: : select can monitor a limited number +Note: select can monitor a limited number of sockets, as defined by the constant socket._SETSIZE. This number may be as high as 1024 or as low as 64 by default, depending on the system. It is usually possible to change this @@ -276,6 +284,18 @@ it to select, it will be ignored. Using select with non-socket objects: Any object that implements getfd and dirty can be used with select, allowing objects from other libraries to be used within a socket.select driven loop.
+ + ++socket._SETSIZE +
+ ++The maximum number of sockets that the select function can handle. +
+ +@@ -383,15 +403,14 @@ side closes the connection. The function returns a source with the appropriate behavior.
- + --socket._SETSIZE +
+socket._SOCKETINVALID
-The maximum number of sockets that the select function can handle. +The OS value for an invalid socket.
@@ -401,9 +420,9 @@ socket.try(ret1 [, ret2 ... retN])-Throws an exception in case of error. The exception can only be caught -by the protect function. It does not explode -into an error message. +Throws an exception in case ret1 is falsy, using +ret2 as the error message. The exception is supposed to be caught +by a protected function only.
@@ -414,7 +433,10 @@ nested with try.
The function returns ret1 to retN if -ret1 is not nil. Otherwise, it calls error passing ret2. +ret1 is not nil or false. +Otherwise, it calls error passing ret2 wrapped +in a table with metatable used by protect to +distinguish exceptions from runtime errors.
diff --git a/doc/tcp.html b/doc/tcp.html index 4226d78..c6c6eb2 100644 --- a/doc/tcp.html +++ b/doc/tcp.html @@ -1,10 +1,10 @@ - - +LuaSocket: TCP/IP support @@ -28,7 +28,7 @@ download · installation · introduction · -reference +reference
@@ -36,56 +36,11 @@ -TCP
- - - --socket.tcp() -
- --Creates and returns an IPv4 TCP master object. A master object can -be transformed into a server object with the method -listen (after a call to 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. -
- - - --socket.tcp6() -
- --Creates and returns an IPv6 TCP master object. A master object can -be transformed into a server object with the method -listen (after a call to 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. -
- --Note: The TCP object returned will have the option -"ipv6-v6only" set to true. -
+TCP
-+
server:accept()
@@ -95,9 +50,9 @@ object and returns a client object representing that connection.-If a connection is successfully initiated, a client object is returned. +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'. Other errors are +followed by the error string 'timeout'. Other errors are reported by nil followed by a message describing the error.
@@ -107,28 +62,28 @@ with a server object in the recvt 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. +might block until another client shows up. -+
master:bind(address, port)
Binds a master object to address and port on the -local host. +local host.
-Address can be an IP address or a host name. -Port must be an integer number in the range [0..64K). +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 or -IN6ADDR_ANY_INIT, according to the family. +IN6ADDR_ANY_INIT, according to the family. If port is 0, the system automatically -chooses an ephemeral port. +chooses an ephemeral port.
@@ -137,13 +92,13 @@ method returns nil followed by an error message.
-Note: The function socket.bind +Note: The function socket.bind is available and is a shortcut for the creation of server sockets.
-+
master:close()
client:close()
server:close() @@ -154,14 +109,14 @@ 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. +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. +automatically closed before destruction, though.
@@ -172,19 +127,19 @@ master:connect(address, port)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 send, -receive, -getsockname, +receive, +getsockname, getpeername, -settimeout, +settimeout, and close.
-Address can be an IP address or a host name. -Port must be an integer number in the range [1..64K). +Address can be an IP address or a host name. +Port must be an integer number in the range [1..64K).
@@ -193,14 +148,14 @@ describing the error. In case of success, the method returns 1.
-Note: The function socket.connect +Note: The function socket.connect is available and is a shortcut for the creation of client sockets.
-Note: Starting with LuaSocket 2.0, +Note: Starting with LuaSocket 2.0, the settimeout -method affects the behavior of connect, causing it to return +method affects the behavior of connect, causing it to return with an error in case of a timeout. If that happens, you can still call socket.select with the socket in the sendt table. The socket will be writable when the connection is @@ -209,13 +164,88 @@ established.
Note: Starting with LuaSocket 3.0, the host name resolution -depends on whether the socket was created by socket.tcp or socket.tcp6. Addresses from -the appropriate family are tried in succession until the -first success or until the last failure. +depends on whether the socket was created by +socket.tcp, +socket.tcp4 or +socket.tcp6. Addresses from +the appropriate family (or both) are tried in the order +returned by the resolver until the +first success or until the last failure. If the timeout was +set to zero, only the first address is tried. +
+ + + ++master:dirty()
+ +
+client:dirty()
+server:dirty() ++Check the read buffer status. +
+ ++Returns true if there is any data in the read buffer, false otherwise. +
+ ++Note: This is an internal method, use at your own risk. +
+ + + + ++master:getfd()
+ +
+client:getfd()
+server:getfd() ++Returns the underling socket descriptor or handle associated to the object. +
+ ++The descriptor or handle. In case the object has been closed, the return will be -1. +
+ ++Note: This is an internal method. Unlikely to be +portable. Use at your own risk. +
+ + + + ++client:getoption(option)
+ +
+server:getoption(option) ++Gets options for the TCP object. +See setoption for description of the +option names and values. +
+ ++Option is a string with the option name. +
+The method returns the option value in case of success, or +nil followed by an error message otherwise.
+@@ -227,10 +257,10 @@ Returns information about the remote side of a connected client object.
-Returns a string with the IP address of the peer, the -port number that peer is using for the connection, -and a string with the family ("inet" or "inet6"). -In case of error, the method returns nil. +Returns a string with the IP address of the peer, the +port number that peer is using for the connection, +and a string with the family ("inet" or "inet6"). +In case of error, the method returns nil.
@@ -246,13 +276,13 @@ server:getsockname()
-Returns the local address information associated to the object. +Returns the local address information associated to the object.
-The method returns a string with local IP address, a number with -the local port, -and a string with the family ("inet" or "inet6"). +The method returns a string with local IP address, a number with +the local port, +and a string with the family ("inet" or "inet6"). In case of error, the method returns nil.
@@ -266,32 +296,46 @@ server:getstats()Returns accounting information on the socket, useful for throttling -of bandwidth. +of bandwidth.
The method returns the number of bytes received, the number of bytes sent, -and the age of the socket object in seconds. +and the age of the socket object in seconds.
+ + +
+master:gettimeout()
+client:gettimeout()
+server:gettimeout()
+
+Returns the current block timeout followed by the curent +total timeout. +
+ + -+
master:listen(backlog)
Specifies the socket is willing to receive connections, transforming the -object into a server object. Server objects support the -accept, -getsockname, -setoption, -settimeout, -and close methods. +object into a server object. Server objects support the +accept, +getsockname, +setoption, +settimeout, +and close methods.
-The parameter backlog specifies the number of client +The parameter backlog 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. @@ -310,11 +354,11 @@ client:receive([pattern [, prefix]])
Reads data from a client object, according to the specified read -pattern. Patterns follow the Lua file I/O format, and the difference in performance between all patterns is negligible. +pattern. Patterns follow the Lua file I/O format, and the difference in performance between all patterns is negligible.
-Pattern can be any of the following: +Pattern can be any of the following:
Important note: This function was changed severely. It used to support multiple patterns (but I have never seen this feature used) and -now it doesn't anymore. Partial results used to be returned in the same +now it doesn't anymore. Partial results used to be returned in the same way as successful results. This last feature violated the idea that all functions should return nil on error. Thus it was changed -too. +too.
@@ -366,7 +410,7 @@ Sends data through client object.Data is the string to be sent. The optional arguments i and j work exactly like the standard -string.sub Lua function to allow the selection of a +string.sub Lua function to allow the selection of a substring to be sent.
@@ -385,10 +429,10 @@ there was a timeout during the operation.-Note: Output is not buffered. For small strings, -it is always better to concatenate them in Lua -(with the '..' operator) and send the result in one call -instead of calling the method several times. +Note: Output is not buffered. For small strings, +it is always better to concatenate them in Lua +(with the '..' operator) and send the result in one call +instead of calling the method several times.
@@ -400,12 +444,12 @@ 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 an option if you -are sure you need it. +time-critical applications. You should only modify an option if you +are sure you need it.
-Option is a string with the option name, and value +Option is a string with the option name, and value depends on the option being set:
-client:getoption(option)
-server:getoption(option)
-
-Gets options for the TCP object. -See setoption for description of the -option names and values. -
- --Option is a string with the option name. -
-The method returns the option value in case of success, or -nil followed by an error message otherwise. -
-
@@ -485,7 +501,7 @@ server:setstats(received, sent, age)
Resets accounting information on the socket, useful for throttling -of bandwidth. +of bandwidth.
@@ -495,7 +511,7 @@ of bandwidth.
-The method returns 1 in case of success and nil otherwise. +The method returns 1 in case of success and nil otherwise.
@@ -509,8 +525,8 @@ 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 +send, +receive, and accept will block indefinitely, until the operation completes. The settimeout method defines a limit on the amount of time the @@ -521,7 +537,7 @@ 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: +both can be used together for fine tuning:
@@ -562,7 +578,7 @@ client:shutdown(mode)
-Shuts down part of a full-duplex connection. +Shuts down part of a full-duplex connection.
@@ -579,66 +595,107 @@ This is the default mode; This function returns 1.
- + -
-master:dirty()
-client:dirty()
-server:dirty()
+
+master:setfd(fd)
+client:setfd(fd)
+server:setfd(fd)
-Check the read buffer status. +Sets the underling socket descriptor or handle associated to the object. The current one is simply replaced, not closed, and no other change to the object state is made.
-Returns true if there is any data in the read buffer, false otherwise. +No return value.
-Note: This is an internal method, any use is unlikely to be portable. +Note: This is an internal method. Unlikely to be +portable. Use at your own risk.
- + -
-master:getfd()
-client:getfd()
-server:getfd()
+
+socket.tcp()
-Returns the underling socket descriptor or handle associated to the object. -
+Creates and returns an TCP master object. A master object can +be transformed into a server object with the method +listen (after a call to bind) or into a client object with +the method connect. The only other +method supported by a master object is the +close method.-The descriptor or handle. In case the object has been closed, the return will be -1. +In case of success, a new master object is returned. In case of error, +nil is returned, followed by an error message.
-Note: This is an internal method, any use is unlikely to be portable. +Note: The choice between IPv4 and IPv6 happens during a call to +bind or connect, depending on the address +family obtained from the resolver.
- ++Note: Before the choice between IPv4 and IPv6 happens, +the internal socket object is invalid and therefore setoption will fail. +
-
-master:setfd(fd)
-client:setfd(fd)
-server:setfd(fd)
+
+
+
+socket.tcp4()
-Sets the underling socket descriptor or handle associated to the object. The current one is simply replaced, not closed, and no other change to the object state is made. +Creates and returns an IPv4 TCP master object. A master object can +be transformed into a server object with the method +listen (after a call to 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. +
+ + + ++socket.tcp6()
++Creates and returns an IPv6 TCP master object. A master object can +be transformed into a server object with the method +listen (after a call to bind) or into a client object with +the method connect. The only other +method supported by a master object is the +close method.
+-No return value. +In case of success, a new master object is returned. In case of error, +nil is returned, followed by an error message.
-Note: This is an internal method, any use is unlikely to be portable. +Note: The TCP object returned will have the option +"ipv6-v6only" set to true.
+ +-socket.udp() -
- --Creates and returns an unconnected IPv4 UDP object. -Unconnected objects support the -sendto, -receive, -receivefrom, -getoption, -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. -
- - - --socket.udp6() -
- --Creates and returns an unconnected IPv6 UDP object. -Unconnected objects support the -sendto, -receive, -receivefrom, -getoption, -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. -
- --Note: The TCP object returned will have the option -"ipv6-v6only" set to true. -
- - - - +
+connected:getoption()
+unconnected:getoption()
+
+Gets an option value from the UDP object. +See setoption for +description of the option names and values. +
+ +Option is a string with the option name. +
+The method returns the option value in case of +success, or +nil followed by an error message otherwise. +
+@@ -142,10 +109,10 @@ associated with a connected UDP object.
-Returns a string with the IP address of the peer, the -port number that peer is using for the connection, -and a string with the family ("inet" or "inet6"). -In case of error, the method returns nil. +Returns a string with the IP address of the peer, the +port number that peer is using for the connection, +and a string with the family ("inet" or "inet6"). +In case of error, the method returns nil.
@@ -165,9 +132,9 @@ Returns the local address information associated to the object.
-The method returns a string with local IP address, a number with -the local port, -and a string with the family ("inet" or "inet6"). +The method returns a string with local IP address, a number with +the local port, +and a string with the family ("inet" or "inet6"). In case of error, the method returns nil.
@@ -179,6 +146,18 @@ first time (in which case it is bound to an ephemeral port and the wild-card address). + + +
+connected:settimeout(value)
+unconnected:settimeout(value)
+
+Returns the current timeout value. +
+ +@@ -199,9 +178,12 @@ 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 (which is currently limited by the -implementation to 8192 bytes). +available bytes are returned. +If size is omitted, the +compile-time constant socket._DATAGRAMSIZE is used +(it defaults to 8192 bytes). Larger sizes will cause a +temporary buffer to be allocated for the operation.
@@ -217,46 +199,12 @@ unconnected:receivefrom([size])
-Works exactly as the receive +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:getoption()
-unconnected:getoption()
-
-Gets an option value from the UDP object. -See setoption for -description of the option names and values. -
- -Option is a string with the option name. -
-The method returns the option value in case of -success, or -nil followed by an error message otherwise. -
-@@ -268,7 +216,7 @@ Sends a datagram to the UDP peer of a connected object.
-Datagram is a string with the datagram contents. +Datagram is a string with the datagram contents. The maximum datagram size for UDP is 64K minus IP layer overhead. However datagrams larger than the link layer packet size will be fragmented, which may deteriorate performance and/or reliability. @@ -298,11 +246,11 @@ Sends a datagram to the specified IP address and port number.
Datagram is a string with the -datagram contents. +datagram contents. The maximum datagram size for UDP is 64K minus IP layer overhead. However datagrams larger than the link layer packet size will be fragmented, which may deteriorate performance and/or reliability. -Ip is the IP address of the recipient. +Ip is the IP address of the recipient. Host names are not allowed for performance reasons. Port is the port number at the recipient. @@ -320,6 +268,75 @@ refuses to send a message to the specified address (i.e. no interface accepts the address).
+ + +
+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 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. +
+ +@@ -337,9 +354,9 @@ 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 +use the send and +receive methods instead of +sendto and receivefrom.
@@ -406,74 +423,6 @@ 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 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. -
-@@ -482,14 +431,14 @@ unconnected:settimeout(value)
-Changes the timeout values for the object. By default, the -receive and -receivefrom +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. +give up and fail with an error code.
@@ -514,6 +463,114 @@ all other method names already contained verbs making their imperative nature obvious.
+ + ++socket.udp() +
+ ++Creates and returns an unconnected UDP object. +Unconnected objects support the +sendto, +receive, +receivefrom, +getoption, +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. +
+ ++Note: The choice between IPv4 and IPv6 happens during a call to +sendto, setpeername, or sockname, depending on the address +family obtained from the resolver. +
+ ++Note: Before the choice between IPv4 and IPv6 happens, +the internal socket object is invalid and therefore setoption will fail. +
+ + + ++socket.udp4() +
+ ++Creates and returns an unconnected IPv4 UDP object. +Unconnected objects support the +sendto, +receive, +receivefrom, +getoption, +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. +
+ + + ++socket.udp6() +
+ ++Creates and returns an unconnected IPv6 UDP object. +Unconnected objects support the +sendto, +receive, +receivefrom, +getoption, +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. +
+ ++Note: The TCP object returned will have the option +"ipv6-v6only" set to true. +
+ + +
diff --git a/etc/dispatch.lua b/etc/dispatch.lua
index cab7f59..2485415 100644
--- a/etc/dispatch.lua
+++ b/etc/dispatch.lua
@@ -5,6 +5,7 @@
-----------------------------------------------------------------------------
local base = _G
local table = require("table")
+local string = require("string")
local socket = require("socket")
local coroutine = require("coroutine")
module("dispatch")
@@ -43,26 +44,32 @@ end
-----------------------------------------------------------------------------
-- Mega hack. Don't try to do this at home.
-----------------------------------------------------------------------------
--- we can't yield across calls to protect, so we rewrite it with coxpcall
+-- we can't yield across calls to protect on Lua 5.1, so we rewrite it with
+-- coroutines
-- make sure you don't require any module that uses socket.protect before
-- loading our hack
-function socket.protect(f)
- return function(...)
- local co = coroutine.create(f)
- while true do
- local results = {coroutine.resume(co, ...)}
- local status = table.remove(results, 1)
- if not status then
- if base.type(results[1]) == 'table' then
- return nil, results[1][1]
- else base.error(results[1]) end
- end
- if coroutine.status(co) == "suspended" then
- arg = {coroutine.yield(base.unpack(results))}
+if string.sub(base._VERSION, -3) == "5.1" then
+ local function _protect(co, status, ...)
+ if not status then
+ local msg = ...
+ if base.type(msg) == 'table' then
+ return nil, msg[1]
else
- return base.unpack(results)
+ base.error(msg, 0)
end
end
+ if coroutine.status(co) == "suspended" then
+ return _protect(co, coroutine.resume(co, coroutine.yield(...)))
+ else
+ return ...
+ end
+ end
+
+ function socket.protect(f)
+ return function(...)
+ local co = coroutine.create(f)
+ return _protect(co, coroutine.resume(co, ...))
+ end
end
end
diff --git a/linux.cmd b/linux.cmd
index bd59adc..6c6636b 100644
--- a/linux.cmd
+++ b/linux.cmd
@@ -1 +1 @@
-make PLAT=linux DEBUG=DEBUG LUAINC_linux_base=/home/diego/build/linux/include LUAPREFIX_linux=/home/diego/build/linux
+make PLAT=linux DEBUG=DEBUG LUAINC_linux_base=/home/diego/build/ubuntu/include LUAPREFIX_linux=/home/diego/build/ubuntu
diff --git a/luasocket-scm-0.rockspec b/luasocket-scm-0.rockspec
index f86567b..352a497 100644
--- a/luasocket-scm-0.rockspec
+++ b/luasocket-scm-0.rockspec
@@ -50,13 +50,12 @@ local function make_plat(plat)
}
local modules = {
["socket.core"] = {
- sources = { "src/luasocket.c", "src/timeout.c", "src/buffer.c", "src/io.c", "src/auxiliar.c",
- "src/options.c", "src/inet.c", "src/except.c", "src/select.c", "src/tcp.c", "src/udp.c" },
+ sources = { "src/luasocket.c", "src/timeout.c", "src/buffer.c", "src/io.c", "src/auxiliar.c", "src/options.c", "src/inet.c", "src/except.c", "src/select.c", "src/tcp.c", "src/udp.c", "src/compat.c" },
defines = defines[plat],
incdir = "/src"
},
- ["mime.core"] = {
- sources = { "src/mime.c" },
+ ["mime.core"] = {
+ sources = { "src/mime.c", "src/compat.c" },
defines = defines[plat],
incdir = "/src"
},
@@ -73,14 +72,12 @@ local function make_plat(plat)
if plat == "unix" or plat == "macosx" then
modules["socket.core"].sources[#modules["socket.core"].sources+1] = "src/usocket.c"
modules["socket.unix"] = {
- sources = { "src/buffer.c", "src/auxiliar.c", "src/options.c", "src/timeout.c", "src/io.c",
- "src/usocket.c", "src/unix.c" },
+ sources = { "src/buffer.c", "src/auxiliar.c", "src/options.c", "src/timeout.c", "src/io.c", "src/usocket.c", "src/unix.c" },
defines = defines[plat],
incdir = "/src"
}
modules["socket.serial"] = {
- sources = { "src/buffer.c", "src/auxiliar.c", "src/options.c", "src/timeout.c",
- "src/io.c", "src/usocket.c", "src/serial.c" },
+ sources = { "src/buffer.c", "src/auxiliar.c", "src/options.c", "src/timeout.c", "src/io.c", "src/usocket.c", "src/serial.c" },
defines = defines[plat],
incdir = "/src"
}
diff --git a/makefile b/makefile
index 04cd894..cc15b4e 100644
--- a/makefile
+++ b/makefile
@@ -5,12 +5,12 @@
# Targets:
# install install system independent support
# install-unix also install unix-only support
-# install-both install for both lua5.1 and lua5.2
-# install-both-unix also install unix-only
+# install-both install for lua51 lua52 lua53
+# install-both-unix also install unix-only
# print print the build settings
PLAT?= linux
-PLATS= macosx linux win32 mingw
+PLATS= macosx linux win32 mingw freebsd solaris
all: $(PLAT)
@@ -24,20 +24,26 @@ test:
lua test/hello.lua
install-both:
- $(MAKE) clean
+ $(MAKE) clean
@cd src; $(MAKE) $(PLAT) LUAV=5.1
@cd src; $(MAKE) install LUAV=5.1
- $(MAKE) clean
+ $(MAKE) clean
@cd src; $(MAKE) $(PLAT) LUAV=5.2
@cd src; $(MAKE) install LUAV=5.2
+ $(MAKE) clean
+ @cd src; $(MAKE) $(PLAT) LUAV=5.3
+ @cd src; $(MAKE) install LUAV=5.3
install-both-unix:
- $(MAKE) clean
+ $(MAKE) clean
@cd src; $(MAKE) $(PLAT) LUAV=5.1
@cd src; $(MAKE) install-unix LUAV=5.1
- $(MAKE) clean
+ $(MAKE) clean
@cd src; $(MAKE) $(PLAT) LUAV=5.2
@cd src; $(MAKE) install-unix LUAV=5.2
+ $(MAKE) clean
+ @cd src; $(MAKE) $(PLAT) LUAV=5.3
+ @cd src; $(MAKE) install-unix LUAV=5.3
.PHONY: test
diff --git a/src/auxiliar.c b/src/auxiliar.c
index de625e9..18fa8e4 100644
--- a/src/auxiliar.c
+++ b/src/auxiliar.c
@@ -26,7 +26,7 @@ void auxiliar_newclass(lua_State *L, const char *classname, luaL_Reg *func) {
luaL_newmetatable(L, classname); /* mt */
/* create __index table to place methods */
lua_pushstring(L, "__index"); /* mt,"__index" */
- lua_newtable(L); /* mt,"__index",it */
+ lua_newtable(L); /* mt,"__index",it */
/* put class name into class metatable */
lua_pushstring(L, "class"); /* mt,"__index",it,"class" */
lua_pushstring(L, classname); /* mt,"__index",it,"class",classname */
@@ -84,7 +84,7 @@ int auxiliar_checkboolean(lua_State *L, int objidx) {
}
/*-------------------------------------------------------------------------*\
-* Return userdata pointer if object belongs to a given class, abort with
+* Return userdata pointer if object belongs to a given class, abort with
* error otherwise
\*-------------------------------------------------------------------------*/
void *auxiliar_checkclass(lua_State *L, const char *classname, int objidx) {
@@ -98,7 +98,7 @@ void *auxiliar_checkclass(lua_State *L, const char *classname, int objidx) {
}
/*-------------------------------------------------------------------------*\
-* Return userdata pointer if object belongs to a given group, abort with
+* Return userdata pointer if object belongs to a given group, abort with
* error otherwise
\*-------------------------------------------------------------------------*/
void *auxiliar_checkgroup(lua_State *L, const char *groupname, int objidx) {
@@ -121,7 +121,7 @@ void auxiliar_setclass(lua_State *L, const char *classname, int objidx) {
}
/*-------------------------------------------------------------------------*\
-* Get a userdata pointer if object belongs to a given group. Return NULL
+* Get a userdata pointer if object belongs to a given group. Return NULL
* otherwise
\*-------------------------------------------------------------------------*/
void *auxiliar_getgroupudata(lua_State *L, const char *groupname, int objidx) {
@@ -139,7 +139,7 @@ void *auxiliar_getgroupudata(lua_State *L, const char *groupname, int objidx) {
}
/*-------------------------------------------------------------------------*\
-* Get a userdata pointer if object belongs to a given class. Return NULL
+* Get a userdata pointer if object belongs to a given class. Return NULL
* otherwise
\*-------------------------------------------------------------------------*/
void *auxiliar_getclassudata(lua_State *L, const char *classname, int objidx) {
@@ -151,7 +151,7 @@ void *auxiliar_getclassudata(lua_State *L, const char *classname, int objidx) {
* Used to be part of lauxlib in Lua 5.1, was dropped from 5.2.
\*-------------------------------------------------------------------------*/
int auxiliar_typeerror (lua_State *L, int narg, const char *tname) {
- const char *msg = lua_pushfstring(L, "%s expected, got %s", tname,
+ const char *msg = lua_pushfstring(L, "%s expected, got %s", tname,
luaL_typename(L, narg));
return luaL_argerror(L, narg, msg);
}
diff --git a/src/auxiliar.h b/src/auxiliar.h
index ea99013..65511d4 100644
--- a/src/auxiliar.h
+++ b/src/auxiliar.h
@@ -4,12 +4,12 @@
* Auxiliar routines for class hierarchy manipulation
* LuaSocket toolkit (but completely independent of other LuaSocket modules)
*
-* A LuaSocket class is a name associated with Lua metatables. A LuaSocket
-* group is a name associated with a class. A class can belong to any number
+* A LuaSocket class is a name associated with Lua metatables. A LuaSocket
+* group is a name associated with a class. A class can belong to any number
* of groups. This module provides the functionality to:
*
-* - create new classes
-* - add classes to groups
+* - create new classes
+* - add classes to groups
* - set the class of objects
* - check if an object belongs to a given class or group
* - get the userdata associated to objects
@@ -26,11 +26,12 @@
* "class" with the class name.
*
* The mapping from class name to the corresponding metatable and the
-* reverse mapping are done using lauxlib.
+* reverse mapping are done using lauxlib.
\*=========================================================================*/
#include "lua.h"
#include "lauxlib.h"
+#include "compat.h"
int auxiliar_open(lua_State *L);
void auxiliar_newclass(lua_State *L, const char *classname, luaL_Reg *func);
diff --git a/src/buffer.c b/src/buffer.c
index 4ef4e8e..fff1634 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -4,6 +4,7 @@
\*=========================================================================*/
#include "lua.h"
#include "lauxlib.h"
+#include "compat.h"
#include "buffer.h"
@@ -37,7 +38,7 @@ int buffer_open(lua_State *L) {
}
/*-------------------------------------------------------------------------*\
-* Initializes C structure
+* Initializes C structure
\*-------------------------------------------------------------------------*/
void buffer_init(p_buffer buf, p_io io, p_timeout tm) {
buf->first = buf->last = 0;
@@ -61,8 +62,8 @@ int buffer_meth_getstats(lua_State *L, p_buffer buf) {
* object:setstats() interface
\*-------------------------------------------------------------------------*/
int buffer_meth_setstats(lua_State *L, p_buffer buf) {
- buf->received = (long) luaL_optnumber(L, 2, (lua_Number) buf->received);
- buf->sent = (long) luaL_optnumber(L, 3, (lua_Number) buf->sent);
+ buf->received = (long) luaL_optnumber(L, 2, (lua_Number) buf->received);
+ buf->sent = (long) luaL_optnumber(L, 3, (lua_Number) buf->sent);
if (lua_isnumber(L, 4)) buf->birthday = timeout_gettime() - lua_tonumber(L, 4);
lua_pushnumber(L, 1);
return 1;
@@ -78,9 +79,7 @@ int buffer_meth_send(lua_State *L, p_buffer buf) {
const char *data = luaL_checklstring(L, 2, &size);
long start = (long) luaL_optnumber(L, 3, 1);
long end = (long) luaL_optnumber(L, 4, -1);
-#ifdef LUASOCKET_DEBUG
- p_timeout tm = timeout_markstart(buf->tm);
-#endif
+ timeout_markstart(buf->tm);
if (start < 0) start = (long) (size+start+1);
if (end < 0) end = (long) (size+end+1);
if (start < 1) start = (long) 1;
@@ -89,7 +88,7 @@ int buffer_meth_send(lua_State *L, p_buffer buf) {
/* check if there was an error */
if (err != IO_DONE) {
lua_pushnil(L);
- lua_pushstring(L, buf->io->error(buf->io->ctx, err));
+ lua_pushstring(L, buf->io->error(buf->io->ctx, err));
lua_pushnumber(L, (lua_Number) (sent+start-1));
} else {
lua_pushnumber(L, (lua_Number) (sent+start-1));
@@ -98,7 +97,7 @@ int buffer_meth_send(lua_State *L, p_buffer buf) {
}
#ifdef LUASOCKET_DEBUG
/* push time elapsed during operation as the last return value */
- lua_pushnumber(L, timeout_gettime() - timeout_getstart(tm));
+ lua_pushnumber(L, timeout_gettime() - timeout_getstart(buf->tm));
#endif
return lua_gettop(L) - top;
}
@@ -111,10 +110,8 @@ int buffer_meth_receive(lua_State *L, p_buffer buf) {
luaL_Buffer b;
size_t size;
const char *part = luaL_optlstring(L, 3, "", &size);
-#ifdef LUASOCKET_DEBUG
- p_timeout tm = timeout_markstart(buf->tm);
-#endif
- /* initialize buffer with optional extra prefix
+ timeout_markstart(buf->tm);
+ /* initialize buffer with optional extra prefix
* (useful for concatenating previous partial results) */
luaL_buffinit(L, &b);
luaL_addlstring(&b, part, size);
@@ -122,12 +119,12 @@ int buffer_meth_receive(lua_State *L, p_buffer buf) {
if (!lua_isnumber(L, 2)) {
const char *p= luaL_optstring(L, 2, "*l");
if (p[0] == '*' && p[1] == 'l') err = recvline(buf, &b);
- else if (p[0] == '*' && p[1] == 'a') err = recvall(buf, &b);
+ else if (p[0] == '*' && p[1] == 'a') err = recvall(buf, &b);
else luaL_argcheck(L, 0, 2, "invalid receive pattern");
- /* get a fixed number of bytes (minus what was already partially
+ /* get a fixed number of bytes (minus what was already partially
* received) */
} else {
- double n = lua_tonumber(L, 2);
+ double n = lua_tonumber(L, 2);
size_t wanted = (size_t) n;
luaL_argcheck(L, n >= 0, 2, "invalid receive pattern");
if (size == 0 || wanted > size)
@@ -138,8 +135,8 @@ int buffer_meth_receive(lua_State *L, p_buffer buf) {
/* we can't push anyting in the stack before pushing the
* contents of the buffer. this is the reason for the complication */
luaL_pushresult(&b);
- lua_pushstring(L, buf->io->error(buf->io->ctx, err));
- lua_pushvalue(L, -2);
+ lua_pushstring(L, buf->io->error(buf->io->ctx, err));
+ lua_pushvalue(L, -2);
lua_pushnil(L);
lua_replace(L, -4);
} else {
@@ -149,7 +146,7 @@ int buffer_meth_receive(lua_State *L, p_buffer buf) {
}
#ifdef LUASOCKET_DEBUG
/* push time elapsed during operation as the last return value */
- lua_pushnumber(L, timeout_gettime() - timeout_getstart(tm));
+ lua_pushnumber(L, timeout_gettime() - timeout_getstart(buf->tm));
#endif
return lua_gettop(L) - top;
}
@@ -222,7 +219,7 @@ static int recvall(p_buffer buf, luaL_Buffer *b) {
}
/*-------------------------------------------------------------------------*\
-* Reads a line terminated by a CR LF pair or just by a LF. The CR and LF
+* Reads a line terminated by a CR LF pair or just by a LF. The CR and LF
* are not returned by the function and are discarded from the buffer
\*-------------------------------------------------------------------------*/
static int recvline(p_buffer buf, luaL_Buffer *b) {
@@ -252,7 +249,7 @@ static int recvline(p_buffer buf, luaL_Buffer *b) {
static void buffer_skip(p_buffer buf, size_t count) {
buf->received += count;
buf->first += count;
- if (buffer_isempty(buf))
+ if (buffer_isempty(buf))
buf->first = buf->last = 0;
}
diff --git a/src/compat.c b/src/compat.c
new file mode 100644
index 0000000..c2d99cb
--- /dev/null
+++ b/src/compat.c
@@ -0,0 +1,19 @@
+#include "compat.h"
+
+#if LUA_VERSION_NUM==501
+/*
+** Adapted from Lua 5.2
+*/
+void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
+ luaL_checkstack(L, nup+1, "too many upvalues");
+ for (; l->name != NULL; l++) { /* fill the table with given functions */
+ int i;
+ lua_pushstring(L, l->name);
+ for (i = 0; i < nup; i++) /* copy upvalues to the top */
+ lua_pushvalue(L, -(nup+1));
+ lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */
+ lua_settable(L, -(nup + 3));
+ }
+ lua_pop(L, nup); /* remove upvalues */
+}
+#endif
diff --git a/src/compat.h b/src/compat.h
new file mode 100644
index 0000000..7bf8010
--- /dev/null
+++ b/src/compat.h
@@ -0,0 +1,11 @@
+#ifndef COMPAT_H
+#define COMPAT_H
+
+#include "lua.h"
+#include "lauxlib.h"
+
+#if LUA_VERSION_NUM==501
+void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup);
+#endif
+
+#endif
diff --git a/src/except.c b/src/except.c
index 002e701..60b5005 100644
--- a/src/except.c
+++ b/src/except.c
@@ -6,9 +6,19 @@
#include "lua.h"
#include "lauxlib.h"
+#include "compat.h"
#include "except.h"
+#if LUA_VERSION_NUM < 502
+#define lua_pcallk(L, na, nr, err, ctx, cont) \
+ (((void)ctx),((void)cont),lua_pcall(L, na, nr, err))
+#endif
+
+#if LUA_VERSION_NUM < 503
+typedef int lua_KContext;
+#endif
+
/*=========================================================================*\
* Internal function prototypes.
\*=========================================================================*/
@@ -29,18 +39,17 @@ static luaL_Reg func[] = {
* Try factory
\*-------------------------------------------------------------------------*/
static void wrap(lua_State *L) {
- lua_newtable(L);
- lua_pushnumber(L, 1);
- lua_pushvalue(L, -3);
- lua_settable(L, -3);
- lua_insert(L, -2);
- lua_pop(L, 1);
+ lua_createtable(L, 1, 0);
+ lua_pushvalue(L, -2);
+ lua_rawseti(L, -2, 1);
+ lua_pushvalue(L, lua_upvalueindex(1));
+ lua_setmetatable(L, -2);
}
static int finalize(lua_State *L) {
if (!lua_toboolean(L, 1)) {
- lua_pushvalue(L, lua_upvalueindex(1));
- lua_pcall(L, 0, 0, 0);
+ lua_pushvalue(L, lua_upvalueindex(2));
+ lua_call(L, 0, 0);
lua_settop(L, 2);
wrap(L);
lua_error(L);
@@ -48,15 +57,17 @@ static int finalize(lua_State *L) {
} else return lua_gettop(L);
}
-static int do_nothing(lua_State *L) {
+static int do_nothing(lua_State *L) {
(void) L;
- return 0;
+ return 0;
}
static int global_newtry(lua_State *L) {
lua_settop(L, 1);
if (lua_isnil(L, 1)) lua_pushcfunction(L, do_nothing);
- lua_pushcclosure(L, finalize, 1);
+ lua_pushvalue(L, lua_upvalueindex(1));
+ lua_insert(L, -2);
+ lua_pushcclosure(L, finalize, 2);
return 1;
}
@@ -64,27 +75,49 @@ static int global_newtry(lua_State *L) {
* Protect factory
\*-------------------------------------------------------------------------*/
static int unwrap(lua_State *L) {
- if (lua_istable(L, -1)) {
- lua_pushnumber(L, 1);
- lua_gettable(L, -2);
- lua_pushnil(L);
- lua_insert(L, -2);
- return 1;
- } else return 0;
+ if (lua_istable(L, -1) && lua_getmetatable(L, -1)) {
+ int r = lua_rawequal(L, -1, lua_upvalueindex(1));
+ lua_pop(L, 1);
+ if (r) {
+ lua_pushnil(L);
+ lua_rawgeti(L, -2, 1);
+ return 1;
+ }
+ }
+ return 0;
}
-static int protected_(lua_State *L) {
- lua_pushvalue(L, lua_upvalueindex(1));
- lua_insert(L, 1);
- if (lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0) != 0) {
+static int protected_finish(lua_State *L, int status, lua_KContext ctx) {
+ (void)ctx;
+ if (status != 0 && status != LUA_YIELD) {
if (unwrap(L)) return 2;
- else lua_error(L);
- return 0;
+ else return lua_error(L);
} else return lua_gettop(L);
}
+#if LUA_VERSION_NUM == 502
+static int protected_cont(lua_State *L) {
+ int ctx = 0;
+ int status = lua_getctx(L, &ctx);
+ return protected_finish(L, status, ctx);
+}
+#else
+#define protected_cont protected_finish
+#endif
+
+static int protected_(lua_State *L) {
+ int status;
+ lua_pushvalue(L, lua_upvalueindex(2));
+ lua_insert(L, 1);
+ status = lua_pcallk(L, lua_gettop(L) - 1, LUA_MULTRET, 0, 0, protected_cont);
+ return protected_finish(L, status, 0);
+}
+
static int global_protect(lua_State *L) {
- lua_pushcclosure(L, protected_, 1);
+ lua_settop(L, 1);
+ lua_pushvalue(L, lua_upvalueindex(1));
+ lua_insert(L, 1);
+ lua_pushcclosure(L, protected_, 2);
return 1;
}
@@ -92,10 +125,9 @@ static int global_protect(lua_State *L) {
* Init module
\*-------------------------------------------------------------------------*/
int except_open(lua_State *L) {
-#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
- luaL_setfuncs(L, func, 0);
-#else
- luaL_openlib(L, NULL, func, 0);
-#endif
+ lua_newtable(L); /* metatable for wrapped exceptions */
+ lua_pushboolean(L, 0);
+ lua_setfield(L, -2, "__metatable");
+ luaL_setfuncs(L, func, 1);
return 0;
}
diff --git a/src/except.h b/src/except.h
index 1e7a245..2497c05 100644
--- a/src/except.h
+++ b/src/except.h
@@ -9,21 +9,26 @@
* error checking was taking a substantial amount of the coding. These
* function greatly simplify the task of checking errors.
*
-* The main idea is that functions should return nil as its first return
-* value when it finds an error, and return an error message (or value)
+* The main idea is that functions should return nil as their first return
+* values when they find an error, and return an error message (or value)
* following nil. In case of success, as long as the first value is not nil,
* the other values don't matter.
*
* The idea is to nest function calls with the "try" function. This function
-* checks the first value, and calls "error" on the second if the first is
-* nil. Otherwise, it returns all values it received.
+* checks the first value, and, if it's falsy, wraps the second value in a
+* table with metatable and calls "error" on it. Otherwise, it returns all
+* values it received. Basically, it works like the Lua "assert" function,
+* but it creates errors targeted specifically at "protect".
*
-* The protect function returns a new function that behaves exactly like the
-* function it receives, but the new function doesn't throw exceptions: it
-* returns nil followed by the error message instead.
+* The "newtry" function is a factory for "try" functions that call a
+* finalizer in protected mode before calling "error".
*
-* With these two function, it's easy to write functions that throw
-* exceptions on error, but that don't interrupt the user script.
+* The "protect" function returns a new function that behaves exactly like
+* the function it receives, but the new function catches exceptions thrown
+* by "try" functions and returns nil followed by the error message instead.
+*
+* With these three functions, it's easy to write functions that throw
+* exceptions on error, but that don't interrupt the user script.
\*=========================================================================*/
#include "lua.h"
diff --git a/src/ftp.lua b/src/ftp.lua
index ea1145b..e0c3cae 100644
--- a/src/ftp.lua
+++ b/src/ftp.lua
@@ -268,11 +268,20 @@ _M.command = socket.protect(function(cmdt)
cmdt = override(cmdt)
socket.try(cmdt.host, "missing hostname")
socket.try(cmdt.command, "missing command")
- local f = open(cmdt.host, cmdt.port, cmdt.create)
+ local f = _M.open(cmdt.host, cmdt.port, cmdt.create)
f:greet()
f:login(cmdt.user, cmdt.password)
- f.try(f.tp:command(cmdt.command, cmdt.argument))
- if cmdt.check then f.try(f.tp:check(cmdt.check)) end
+ if type(cmdt.command) == "table" then
+ local argument = cmdt.argument or {}
+ local check = cmdt.check or {}
+ for i,cmd in ipairs(cmdt.command) do
+ f.try(f.tp:command(cmd, argument[i]))
+ if check[i] then f.try(f.tp:check(check[i])) end
+ end
+ else
+ f.try(f.tp:command(cmdt.command, cmdt.argument))
+ if cmdt.check then f.try(f.tp:check(cmdt.check)) end
+ end
f:quit()
return f:close()
end)
@@ -282,4 +291,4 @@ _M.get = socket.protect(function(gett)
else return tget(gett) end
end)
-return _M
\ No newline at end of file
+return _M
diff --git a/src/http.lua b/src/http.lua
index ac4b2d6..d6bcc91 100644
--- a/src/http.lua
+++ b/src/http.lua
@@ -22,12 +22,15 @@ local _M = socket.http
-- Program constants
-----------------------------------------------------------------------------
-- connection timeout in seconds
-TIMEOUT = 60
--- default port for document retrieval
-_M.PORT = 80
+_M.TIMEOUT = 60
-- user agent field sent in request
_M.USERAGENT = socket._VERSION
+-- supported schemes
+local SCHEMES = { ["http"] = true }
+-- default port for document retrieval
+local PORT = 80
+
-----------------------------------------------------------------------------
-- Reads MIME headers from a connection, unfolding where needed
-----------------------------------------------------------------------------
@@ -114,7 +117,7 @@ function _M.open(host, port, create)
h.try = socket.newtry(function() h:close() end)
-- set timeout before connecting
h.try(c:settimeout(_M.TIMEOUT))
- h.try(c:connect(host, port or _M.PORT))
+ h.try(c:connect(host, port or PORT))
-- here everything worked
return h
end
@@ -186,7 +189,7 @@ end
local function adjusturi(reqt)
local u = reqt
-- if there is a proxy, we need the full url. otherwise, just a part.
- if not reqt.proxy and not PROXY then
+ if not reqt.proxy and not _M.PROXY then
u = {
path = socket.try(reqt.path, "invalid path 'nil'"),
params = reqt.params,
@@ -198,7 +201,7 @@ local function adjusturi(reqt)
end
local function adjustproxy(reqt)
- local proxy = reqt.proxy or PROXY
+ local proxy = reqt.proxy or _M.PROXY
if proxy then
proxy = url.parse(proxy)
return proxy.host, proxy.port or 3128
@@ -209,17 +212,27 @@ end
local function adjustheaders(reqt)
-- default headers
+ local host = string.gsub(reqt.authority, "^.-@", "")
local lower = {
["user-agent"] = _M.USERAGENT,
- ["host"] = reqt.host,
+ ["host"] = host,
["connection"] = "close, TE",
["te"] = "trailers"
}
-- if we have authentication information, pass it along
if reqt.user and reqt.password then
- lower["authorization"] =
+ lower["authorization"] =
"Basic " .. (mime.b64(reqt.user .. ":" .. reqt.password))
end
+ -- if we have proxy authentication information, pass it along
+ local proxy = reqt.proxy or _M.PROXY
+ if proxy then
+ proxy = url.parse(proxy)
+ if proxy.user and proxy.password then
+ lower["proxy-authorization"] =
+ "Basic " .. (mime.b64(proxy.user .. ":" .. proxy.password))
+ end
+ end
-- override with user headers
for i,v in base.pairs(reqt.headers or lower) do
lower[string.lower(i)] = v
@@ -230,7 +243,7 @@ end
-- default url parts
local default = {
host = "",
- port = _M.PORT,
+ port = PORT,
path ="/",
scheme = "http"
}
@@ -240,22 +253,27 @@ local function adjustrequest(reqt)
local nreqt = reqt.url and url.parse(reqt.url, default) or {}
-- explicit components override url
for i,v in base.pairs(reqt) do nreqt[i] = v end
- if nreqt.port == "" then nreqt.port = 80 end
- socket.try(nreqt.host and nreqt.host ~= "",
- "invalid host '" .. base.tostring(nreqt.host) .. "'")
+ if nreqt.port == "" then nreqt.port = PORT end
+ if not (nreqt.host and nreqt.host ~= "") then
+ socket.try(nil, "invalid host '" .. base.tostring(nreqt.host) .. "'")
+ end
-- compute uri if user hasn't overriden
nreqt.uri = reqt.uri or adjusturi(nreqt)
- -- ajust host and port if there is a proxy
- nreqt.host, nreqt.port = adjustproxy(nreqt)
-- adjust headers in request
nreqt.headers = adjustheaders(nreqt)
+ -- ajust host and port if there is a proxy
+ nreqt.host, nreqt.port = adjustproxy(nreqt)
return nreqt
end
local function shouldredirect(reqt, code, headers)
- return headers.location and
- string.gsub(headers.location, "%s", "") ~= "" and
- (reqt.redirect ~= false) and
+ local location = headers.location
+ if not location then return false end
+ location = string.gsub(location, "%s", "")
+ if location == "" then return false end
+ local scheme = string.match(location, "^([%w][%w%+%-%.]*)%:")
+ if scheme and not SCHEMES[scheme] then return false end
+ return (reqt.redirect ~= false) and
(code == 301 or code == 302 or code == 303 or code == 307) and
(not reqt.method or reqt.method == "GET" or reqt.method == "HEAD")
and (not reqt.nredirects or reqt.nredirects < 5)
@@ -279,10 +297,10 @@ local trequest, tredirect
source = reqt.source,
sink = reqt.sink,
headers = reqt.headers,
- proxy = reqt.proxy,
+ proxy = reqt.proxy,
nredirects = (reqt.nredirects or 0) + 1,
create = reqt.create
- }
+ }
-- pass location header back as a hint we redirected
headers = headers or {}
headers.location = headers.location or location
@@ -299,7 +317,7 @@ end
h:sendheaders(nreqt.headers)
-- if there is a body, send it
if nreqt.source then
- h:sendbody(nreqt.headers, nreqt.source, nreqt.step)
+ h:sendbody(nreqt.headers, nreqt.source, nreqt.step)
end
local code, status = h:receivestatusline()
-- if it is an HTTP/0.9 server, simply get the body and we are done
@@ -309,13 +327,13 @@ end
end
local headers
-- ignore any 100-continue messages
- while code == 100 do
+ while code == 100 do
headers = h:receiveheaders()
code, status = h:receivestatusline()
end
headers = h:receiveheaders()
-- at this point we should have a honest reply from the server
- -- we can't redirect if we already used the source, so we report the error
+ -- we can't redirect if we already used the source, so we report the error
if shouldredirect(nreqt, code, headers) and not nreqt.source then
h:close()
return tredirect(reqt, headers.location)
@@ -351,4 +369,4 @@ _M.request = socket.protect(function(reqt, body)
else return trequest(reqt) end
end)
-return _M
\ No newline at end of file
+return _M
diff --git a/src/inet.c b/src/inet.c
index 1a411f6..f4c8404 100644
--- a/src/inet.c
+++ b/src/inet.c
@@ -8,6 +8,7 @@
#include "lua.h"
#include "lauxlib.h"
+#include "compat.h"
#include "inet.h"
@@ -41,11 +42,7 @@ int inet_open(lua_State *L)
{
lua_pushstring(L, "dns");
lua_newtable(L);
-#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
luaL_setfuncs(L, func, 0);
-#else
- luaL_openlib(L, NULL, func, 0);
-#endif
lua_settable(L, -3);
return 0;
}
@@ -97,7 +94,7 @@ static int inet_global_getnameinfo(lua_State *L) {
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM;
- hints.ai_family = PF_UNSPEC;
+ hints.ai_family = AF_UNSPEC;
ret = getaddrinfo(host, serv, &hints, &resolved);
if (ret != 0) {
@@ -108,8 +105,8 @@ static int inet_global_getnameinfo(lua_State *L) {
lua_newtable(L);
for (i = 1, iter = resolved; iter; i++, iter = iter->ai_next) {
- getnameinfo(iter->ai_addr, (socklen_t) iter->ai_addrlen,
- hbuf, host? (socklen_t) sizeof(hbuf): 0,
+ getnameinfo(iter->ai_addr, (socklen_t) iter->ai_addrlen,
+ hbuf, host? (socklen_t) sizeof(hbuf): 0,
sbuf, serv? (socklen_t) sizeof(sbuf): 0, 0);
if (host) {
lua_pushnumber(L, i);
@@ -149,7 +146,7 @@ static int inet_global_toip(lua_State *L)
int inet_optfamily(lua_State* L, int narg, const char* def)
{
static const char* optname[] = { "unspec", "inet", "inet6", NULL };
- static int optvalue[] = { PF_UNSPEC, PF_INET, PF_INET6, 0 };
+ static int optvalue[] = { AF_UNSPEC, AF_INET, AF_INET6, 0 };
return optvalue[luaL_checkoption(L, narg, def, optname)];
}
@@ -170,7 +167,7 @@ static int inet_global_getaddrinfo(lua_State *L)
int i = 1, ret = 0;
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM;
- hints.ai_family = PF_UNSPEC;
+ hints.ai_family = AF_UNSPEC;
ret = getaddrinfo(hostname, NULL, &hints, &resolved);
if (ret != 0) {
lua_pushnil(L);
@@ -180,9 +177,10 @@ static int inet_global_getaddrinfo(lua_State *L)
lua_newtable(L);
for (iterator = resolved; iterator; iterator = iterator->ai_next) {
char hbuf[NI_MAXHOST];
- ret = getnameinfo(iterator->ai_addr, (socklen_t) iterator->ai_addrlen,
+ ret = getnameinfo(iterator->ai_addr, (socklen_t) iterator->ai_addrlen,
hbuf, (socklen_t) sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
if (ret){
+ freeaddrinfo(resolved);
lua_pushnil(L);
lua_pushstring(L, socket_gaistrerror(ret));
return 2;
@@ -200,6 +198,16 @@ static int inet_global_getaddrinfo(lua_State *L)
lua_pushliteral(L, "inet6");
lua_settable(L, -3);
break;
+ case AF_UNSPEC:
+ lua_pushliteral(L, "family");
+ lua_pushliteral(L, "unspec");
+ lua_settable(L, -3);
+ break;
+ default:
+ lua_pushliteral(L, "family");
+ lua_pushliteral(L, "unknown");
+ lua_settable(L, -3);
+ break;
}
lua_pushliteral(L, "addr");
lua_pushstring(L, hbuf);
@@ -256,12 +264,11 @@ int inet_meth_getpeername(lua_State *L, p_socket ps, int family)
}
lua_pushstring(L, name);
lua_pushinteger(L, (int) strtol(port, (char **) NULL, 10));
- if (family == PF_INET) {
- lua_pushliteral(L, "inet");
- } else if (family == PF_INET6) {
- lua_pushliteral(L, "inet6");
- } else {
- lua_pushliteral(L, "uknown family");
+ switch (family) {
+ case AF_INET: lua_pushliteral(L, "inet"); break;
+ case AF_INET6: lua_pushliteral(L, "inet6"); break;
+ case AF_UNSPEC: lua_pushliteral(L, "unspec"); break;
+ default: lua_pushliteral(L, "unknown"); break;
}
return 3;
}
@@ -281,7 +288,7 @@ int inet_meth_getsockname(lua_State *L, p_socket ps, int family)
lua_pushstring(L, socket_strerror(errno));
return 2;
}
- err=getnameinfo((struct sockaddr *)&peer, peer_len,
+ err=getnameinfo((struct sockaddr *)&peer, peer_len,
name, INET6_ADDRSTRLEN, port, 6, NI_NUMERICHOST | NI_NUMERICSERV);
if (err) {
lua_pushnil(L);
@@ -290,12 +297,11 @@ int inet_meth_getsockname(lua_State *L, p_socket ps, int family)
}
lua_pushstring(L, name);
lua_pushstring(L, port);
- if (family == PF_INET) {
- lua_pushliteral(L, "inet");
- } else if (family == PF_INET6) {
- lua_pushliteral(L, "inet6");
- } else {
- lua_pushliteral(L, "uknown family");
+ switch (family) {
+ case AF_INET: lua_pushliteral(L, "inet"); break;
+ case AF_INET6: lua_pushliteral(L, "inet6"); break;
+ case AF_UNSPEC: lua_pushliteral(L, "unspec"); break;
+ default: lua_pushliteral(L, "unknown"); break;
}
return 3;
}
@@ -346,8 +352,13 @@ static void inet_pushresolved(lua_State *L, struct hostent *hp)
/*-------------------------------------------------------------------------*\
* Tries to create a new inet socket
\*-------------------------------------------------------------------------*/
-const char *inet_trycreate(p_socket ps, int family, int type) {
- return socket_strerror(socket_create(ps, family, type, 0));
+const char *inet_trycreate(p_socket ps, int family, int type, int protocol) {
+ const char *err = socket_strerror(socket_create(ps, family, type, protocol));
+ if (err == NULL && family == AF_INET6) {
+ int yes = 1;
+ setsockopt(*ps, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&yes, sizeof(yes));
+ }
+ return err;
}
/*-------------------------------------------------------------------------*\
@@ -356,21 +367,21 @@ const char *inet_trycreate(p_socket ps, int family, int type) {
const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm)
{
switch (family) {
- case PF_INET: {
+ case AF_INET: {
struct sockaddr_in sin;
memset((char *) &sin, 0, sizeof(sin));
sin.sin_family = AF_UNSPEC;
sin.sin_addr.s_addr = INADDR_ANY;
- return socket_strerror(socket_connect(ps, (SA *) &sin,
+ return socket_strerror(socket_connect(ps, (SA *) &sin,
sizeof(sin), tm));
}
- case PF_INET6: {
+ case AF_INET6: {
struct sockaddr_in6 sin6;
- struct in6_addr addrany = IN6ADDR_ANY_INIT;
+ struct in6_addr addrany = IN6ADDR_ANY_INIT;
memset((char *) &sin6, 0, sizeof(sin6));
sin6.sin6_family = AF_UNSPEC;
sin6.sin6_addr = addrany;
- return socket_strerror(socket_connect(ps, (SA *) &sin6,
+ return socket_strerror(socket_connect(ps, (SA *) &sin6,
sizeof(sin6), tm));
}
}
@@ -385,6 +396,7 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address,
{
struct addrinfo *iterator = NULL, *resolved = NULL;
const char *err = NULL;
+ int current_family = *family;
/* try resolving */
err = socket_gaistrerror(getaddrinfo(address, serv,
connecthints, &resolved));
@@ -399,23 +411,23 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address,
* that shows up while iterating. if there was a
* bind, all families will be the same and we will
* not enter this branch. */
- if (*family != iterator->ai_family) {
+ if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) {
socket_destroy(ps);
- err = socket_strerror(socket_create(ps, iterator->ai_family,
- iterator->ai_socktype, iterator->ai_protocol));
- if (err != NULL) {
- freeaddrinfo(resolved);
- return err;
- }
- *family = iterator->ai_family;
- /* all sockets initially non-blocking */
+ err = inet_trycreate(ps, iterator->ai_family,
+ iterator->ai_socktype, iterator->ai_protocol);
+ if (err) continue;
+ current_family = iterator->ai_family;
+ /* set non-blocking before connect */
socket_setnonblocking(ps);
}
/* try connecting to remote address */
- err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr,
+ err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr,
(socklen_t) iterator->ai_addrlen, tm));
- /* if success, break out of loop */
- if (err == NULL) break;
+ /* if success or timeout is zero, break out of loop */
+ if (err == NULL || timeout_iszero(tm)) {
+ *family = current_family;
+ break;
+ }
}
freeaddrinfo(resolved);
/* here, if err is set, we failed */
@@ -425,29 +437,27 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address,
/*-------------------------------------------------------------------------*\
* Tries to accept a socket
\*-------------------------------------------------------------------------*/
-const char *inet_tryaccept(p_socket server, int family, p_socket client,
- p_timeout tm)
-{
+const char *inet_tryaccept(p_socket server, int family, p_socket client,
+ p_timeout tm) {
socklen_t len;
t_sockaddr_storage addr;
- if (family == PF_INET6) {
- len = sizeof(struct sockaddr_in6);
- } else {
- len = sizeof(struct sockaddr_in);
- }
- return socket_strerror(socket_accept(server, client, (SA *) &addr,
+ switch (family) {
+ case AF_INET6: len = sizeof(struct sockaddr_in6); break;
+ case AF_INET: len = sizeof(struct sockaddr_in); break;
+ default: len = sizeof(addr); break;
+ }
+ return socket_strerror(socket_accept(server, client, (SA *) &addr,
&len, tm));
}
/*-------------------------------------------------------------------------*\
* Tries to bind socket to (address, port)
\*-------------------------------------------------------------------------*/
-const char *inet_trybind(p_socket ps, const char *address, const char *serv,
- struct addrinfo *bindhints)
-{
+const char *inet_trybind(p_socket ps, int *family, const char *address,
+ const char *serv, struct addrinfo *bindhints) {
struct addrinfo *iterator = NULL, *resolved = NULL;
const char *err = NULL;
- t_socket sock = *ps;
+ int current_family = *family;
/* translate luasocket special values to C */
if (strcmp(address, "*") == 0) address = NULL;
if (!serv) serv = "0";
@@ -459,35 +469,32 @@ const char *inet_trybind(p_socket ps, const char *address, const char *serv,
}
/* iterate over resolved addresses until one is good */
for (iterator = resolved; iterator; iterator = iterator->ai_next) {
- if(sock == SOCKET_INVALID) {
- err = socket_strerror(socket_create(&sock, iterator->ai_family,
- iterator->ai_socktype, iterator->ai_protocol));
- if(err)
- continue;
+ if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) {
+ socket_destroy(ps);
+ err = inet_trycreate(ps, iterator->ai_family,
+ iterator->ai_socktype, iterator->ai_protocol);
+ if (err) continue;
+ current_family = iterator->ai_family;
}
/* try binding to local address */
- err = socket_strerror(socket_bind(&sock,
- (SA *) iterator->ai_addr,
+ err = socket_strerror(socket_bind(ps, (SA *) iterator->ai_addr,
(socklen_t) iterator->ai_addrlen));
-
/* keep trying unless bind succeeded */
- if (err) {
- if(sock != *ps)
- socket_destroy(&sock);
- } else {
- /* remember what we connected to, particularly the family */
- *bindhints = *iterator;
+ if (err == NULL) {
+ *family = current_family;
+ /* set to non-blocking after bind */
+ socket_setnonblocking(ps);
break;
}
}
/* cleanup and return error */
freeaddrinfo(resolved);
- *ps = sock;
+ /* here, if err is set, we failed */
return err;
}
/*-------------------------------------------------------------------------*\
-* Some systems do not provide these so that we provide our own.
+* Some systems do not provide these so that we provide our own.
\*-------------------------------------------------------------------------*/
#ifdef LUASOCKET_INET_ATON
int inet_aton(const char *cp, struct in_addr *inp)
@@ -512,7 +519,7 @@ int inet_aton(const char *cp, struct in_addr *inp)
#endif
#ifdef LUASOCKET_INET_PTON
-int inet_pton(int af, const char *src, void *dst)
+int inet_pton(int af, const char *src, void *dst)
{
struct addrinfo hints, *res;
int ret = 1;
@@ -529,7 +536,7 @@ int inet_pton(int af, const char *src, void *dst)
} else {
ret = -1;
}
- freeaddrinfo(res);
+ freeaddrinfo(res);
return ret;
}
diff --git a/src/inet.h b/src/inet.h
index 1f1a96a..feb3541 100644
--- a/src/inet.h
+++ b/src/inet.h
@@ -1,12 +1,12 @@
-#ifndef INET_H
-#define INET_H
+#ifndef INET_H
+#define INET_H
/*=========================================================================*\
* Internet domain functions
* LuaSocket toolkit
*
* This module implements the creation and connection of internet domain
* sockets, on top of the socket.h interface, and the interface of with the
-* resolver.
+* resolver.
*
* The function inet_aton is provided for the platforms where it is not
* available. The module also implements the interface of the internet
@@ -24,11 +24,11 @@
int inet_open(lua_State *L);
-const char *inet_trycreate(p_socket ps, int family, int type);
+const char *inet_trycreate(p_socket ps, int family, int type, int protocol);
const char *inet_tryconnect(p_socket ps, int *family, const char *address,
const char *serv, p_timeout tm, struct addrinfo *connecthints);
-const char *inet_trybind(p_socket ps, const char *address, const char *serv,
- struct addrinfo *bindhints);
+const char *inet_trybind(p_socket ps, int *family, const char *address,
+ const char *serv, struct addrinfo *bindhints);
const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm);
const char *inet_tryaccept(p_socket server, int family, p_socket client, p_timeout tm);
diff --git a/src/io.c b/src/io.c
index 35f46f7..a4230ce 100644
--- a/src/io.c
+++ b/src/io.c
@@ -25,6 +25,6 @@ const char *io_strerror(int err) {
case IO_DONE: return NULL;
case IO_CLOSED: return "closed";
case IO_TIMEOUT: return "timeout";
- default: return "unknown error";
+ default: return "unknown error";
}
}
diff --git a/src/io.h b/src/io.h
index 76a3e58..8cca08a 100644
--- a/src/io.h
+++ b/src/io.h
@@ -22,7 +22,7 @@ enum {
IO_DONE = 0, /* operation completed successfully */
IO_TIMEOUT = -1, /* operation timed out */
IO_CLOSED = -2, /* the connection has been closed */
- IO_UNKNOWN = -3
+ IO_UNKNOWN = -3
};
/* interface to error message function */
diff --git a/src/ltn12.lua b/src/ltn12.lua
index 5b10f56..575c5a7 100644
--- a/src/ltn12.lua
+++ b/src/ltn12.lua
@@ -9,6 +9,7 @@
-----------------------------------------------------------------------------
local string = require("string")
local table = require("table")
+local unpack = unpack or table.unpack
local base = _G
local _M = {}
if module then -- heuristic for exporting a global package table
@@ -21,6 +22,9 @@ _M.source = source
_M.sink = sink
_M.pump = pump
+local unpack = unpack or table.unpack
+local select = base.select
+
-- 2048 seems to be better in windows...
_M.BLOCKSIZE = 2048
_M._VERSION = "LTN12 1.0.3"
@@ -42,7 +46,7 @@ end
-- (thanks to Wim Couwenberg)
function filter.chain(...)
local arg = {...}
- local n = select('#',...)
+ local n = base.select('#',...)
local top, index = 1, 1
local retry = ""
return function(chunk)
@@ -139,7 +143,9 @@ function source.rewind(src)
end
end
-function source.chain(src, f)
+-- chains a source with one or several filter(s)
+function source.chain(src, f, ...)
+ if ... then f=filter.chain(f, ...) end
base.assert(src and f)
local last_in, last_out = "", ""
local state = "feeding"
@@ -254,8 +260,13 @@ function sink.error(err)
end
end
--- chains a sink with a filter
-function sink.chain(f, snk)
+-- chains a sink with one or several filter(s)
+function sink.chain(f, snk, ...)
+ if ... then
+ local args = { f, snk, ... }
+ snk = table.remove(args, #args)
+ f = filter.chain(unpack(args))
+ end
base.assert(f and snk)
return function(chunk, err)
if chunk ~= "" then
diff --git a/src/luasocket.c b/src/luasocket.c
index e6ee747..7d9c802 100644
--- a/src/luasocket.c
+++ b/src/luasocket.c
@@ -17,7 +17,7 @@
\*=========================================================================*/
#include "lua.h"
#include "lauxlib.h"
-
+#include "compat.h"
/*=========================================================================*\
* LuaSocket includes
@@ -64,7 +64,7 @@ static luaL_Reg func[] = {
* Skip a few arguments
\*-------------------------------------------------------------------------*/
static int global_skip(lua_State *L) {
- int amount = luaL_checkint(L, 1);
+ int amount = luaL_checkinteger(L, 1);
int ret = lua_gettop(L) - amount - 1;
return ret >= 0 ? ret : 0;
}
@@ -78,26 +78,14 @@ static int global_unload(lua_State *L) {
return 0;
}
-#if LUA_VERSION_NUM > 501
-int luaL_typerror (lua_State *L, int narg, const char *tname) {
- const char *msg = lua_pushfstring(L, "%s expected, got %s",
- tname, luaL_typename(L, narg));
- return luaL_argerror(L, narg, msg);
-}
-#endif
-
/*-------------------------------------------------------------------------*\
* Setup basic stuff.
\*-------------------------------------------------------------------------*/
static int base_open(lua_State *L) {
if (socket_open()) {
/* export functions (and leave namespace table on top of stack) */
-#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
lua_newtable(L);
luaL_setfuncs(L, func, 0);
-#else
- luaL_openlib(L, "socket", func, 0);
-#endif
#ifdef LUASOCKET_DEBUG
lua_pushstring(L, "_DEBUG");
lua_pushboolean(L, 1);
diff --git a/src/makefile b/src/makefile
index c24e61b..adf687f 100644
--- a/src/makefile
+++ b/src/makefile
@@ -20,15 +20,17 @@ PLAT?=linux
# lua version to build against
LUAV?=5.1
+# MYCFLAGS: to be set by user if needed
+MYCFLAGS=
+
+# MYLDFLAGS: to be set by user if needed
+MYLDFLAGS=
+
# DEBUG: NODEBUG DEBUG
# debug mode causes luasocket to collect and returns timing information useful
# for testing and debugging luasocket itself
DEBUG?=NODEBUG
-# COMPAT: COMPAT NOCOMPAT
-# when compiling for 5.2, use LUA_COMPAT_MODULE
-COMPAT?=NOCOMPAT
-
# where lua headers are found for macosx builds
# LUAINC_macosx:
# /opt/local/include
@@ -40,7 +42,6 @@ LUAPREFIX_macosx?=/opt/local
CDIR_macosx?=lib/lua/$(LUAV)
LDIR_macosx?=share/lua/$(LUAV)
-
# LUAINC_linux:
# /usr/include/lua$(LUAV)
# /usr/local/include
@@ -52,8 +53,17 @@ LUAPREFIX_linux?=/usr/local
CDIR_linux?=lib/lua/$(LUAV)
LDIR_linux?=share/lua/$(LUAV)
+# LUAINC_freebsd:
+# /usr/local/include/lua$(LUAV)
+# where lua headers are found for freebsd builds
+LUAINC_freebsd_base?=/usr/local/include/
+LUAINC_freebsd?=$(LUAINC_freebsd_base)/lua$(LUAV)
+LUAPREFIX_freebsd?=/usr/local/
+CDIR_freebsd?=lib/lua/$(LUAV)
+LDIR_freebsd?=share/lua/$(LUAV)
+
# where lua headers are found for mingw builds
-# LUAINC_mingw:
+# LUAINC_mingw:
# /opt/local/include
LUAINC_mingw_base?=/usr/include
LUAINC_mingw?=$(LUAINC_mingw_base)/lua/$(LUAV)
@@ -67,13 +77,21 @@ LDIR_mingw?=lua/$(LUAV)/lua
# LUAINC_win32:
# LUALIB_win32:
# where lua headers and libraries are found for win32 builds
-LUAINC_win32_base?=
-LUAINC_win32?=$(LUAINC_win32_base)/lua/$(LUAV)
-PLATFORM_win32?=Release
LUAPREFIX_win32?=
-CDIR_win32?=lua/$(LUAV)/$(PLATFORM_win32)
-LDIR_win32?=lua/$(LUAV)/$(PLATFORM_win32)/lua
-LUALIB_win32?=$(LUAPREFIX_win32)/lua/$(LUAV)/$(PLATFORM_win32)
+LUAINC_win32?=$(LUAPREFIX_win32)/include/lua/$(LUAV)
+PLATFORM_win32?=Release
+CDIR_win32?=bin/lua/$(LUAV)/$(PLATFORM_win32)
+LDIR_win32?=bin/lua/$(LUAV)/$(PLATFORM_win32)/lua
+LUALIB_win32?=$(LUAPREFIX_win32)/lib/lua/$(LUAV)/$(PLATFORM_win32)
+LUALIBNAME_win32?=lua$(subst .,,$(LUAV)).lib
+
+
+# LUAINC_solaris:
+LUAINC_solaris_base?=/usr/include
+LUAINC_solaris?=$(LUAINC_solaris_base)/lua/$(LUAV)
+LUAPREFIX_solaris?=/usr/local
+CDIR_solaris?=lib/lua/$(LUAV)
+LDIR_solaris?=share/lua/$(LUAV)
# prefix: /usr/local /usr /opt/local /sw
# the top of the default install tree
@@ -121,7 +139,7 @@ print:
#------
# Supported platforms
#
-PLATS= macosx linux win32 mingw
+PLATS= macosx linux win32 mingw solaris
#------
# Compiler and linker settings
@@ -129,11 +147,11 @@ PLATS= macosx linux win32 mingw
SO_macosx=so
O_macosx=o
CC_macosx=gcc
-DEF_macosx= -DLUASOCKET_$(DEBUG) -DUNIX_HAS_SUN_LEN -DLUA_$(COMPAT)_MODULE \
+DEF_macosx= -DLUASOCKET_$(DEBUG) -DUNIX_HAS_SUN_LEN \
-DLUASOCKET_API='__attribute__((visibility("default")))' \
-DUNIX_API='__attribute__((visibility("default")))' \
-DMIME_API='__attribute__((visibility("default")))'
-CFLAGS_macosx= -I$(LUAINC) $(DEF) -pedantic -Wall -O2 -fno-common \
+CFLAGS_macosx= -I$(LUAINC) $(DEF) -Wall -O2 -fno-common \
-fvisibility=hidden
LDFLAGS_macosx= -bundle -undefined dynamic_lookup -o
LD_macosx= export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc
@@ -145,11 +163,11 @@ SOCKET_macosx=usocket.o
SO_linux=so
O_linux=o
CC_linux=gcc
-DEF_linux=-DLUASOCKET_$(DEBUG) -DLUA_$(COMPAT)_MODULE \
+DEF_linux=-DLUASOCKET_$(DEBUG) \
-DLUASOCKET_API='__attribute__((visibility("default")))' \
-DUNIX_API='__attribute__((visibility("default")))' \
-DMIME_API='__attribute__((visibility("default")))'
-CFLAGS_linux= -I$(LUAINC) $(DEF) -pedantic -Wall -Wshadow -Wextra \
+CFLAGS_linux= -I$(LUAINC) $(DEF) -Wall -Wshadow -Wextra \
-Wimplicit -O2 -ggdb3 -fpic -fvisibility=hidden
LDFLAGS_linux=-O -shared -fpic -o
LD_linux=gcc
@@ -157,14 +175,46 @@ SOCKET_linux=usocket.o
#------
# Compiler and linker settings
+# for FreeBSD
+SO_freebsd=so
+O_freebsd=o
+CC_freebsd=gcc
+DEF_freebsd=-DLUASOCKET_$(DEBUG) \
+ -DLUASOCKET_API='__attribute__((visibility("default")))' \
+ -DUNIX_API='__attribute__((visibility("default")))' \
+ -DMIME_API='__attribute__((visibility("default")))'
+CFLAGS_freebsd= -I$(LUAINC) $(DEF) -Wall -Wshadow -Wextra \
+ -Wimplicit -O2 -ggdb3 -fpic -fvisibility=hidden
+LDFLAGS_freebsd=-O -shared -fpic -o
+LD_freebsd=gcc
+SOCKET_freebsd=usocket.o
+
+#------
+# Compiler and linker settings
+# for Solaris
+SO_solaris=so
+O_solaris=o
+CC_solaris=gcc
+DEF_solaris=-DLUASOCKET_$(DEBUG) \
+ -DLUASOCKET_API='__attribute__((visibility("default")))' \
+ -DUNIX_API='__attribute__((visibility("default")))' \
+ -DMIME_API='__attribute__((visibility("default")))'
+CFLAGS_solaris=-I$(LUAINC) $(DEF) -Wall -Wshadow -Wextra \
+ -Wimplicit -O2 -ggdb3 -fpic -fvisibility=hidden
+LDFLAGS_solaris=-lnsl -lsocket -lresolv -O -shared -fpic -o
+LD_solaris=gcc
+SOCKET_solaris=usocket.o
+
+#------
+# Compiler and linker settings
# for MingW
SO_mingw=dll
O_mingw=o
CC_mingw=gcc
-DEF_mingw= -DLUASOCKET_INET_PTON -DLUASOCKET_$(DEBUG) -DLUA_$(COMPAT)_MODULE \
+DEF_mingw= -DLUASOCKET_INET_PTON -DLUASOCKET_$(DEBUG) \
-DWINVER=0x0501 -DLUASOCKET_API='__declspec(dllexport)' \
-DMIME_API='__declspec(dllexport)'
-CFLAGS_mingw= -I$(LUAINC) $(DEF) -pedantic -Wall -O2 -fno-common \
+CFLAGS_mingw= -I$(LUAINC) $(DEF) -Wall -O2 -fno-common \
-fvisibility=hidden
LDFLAGS_mingw= $(LUALIB) -shared -Wl,-s -lws2_32 -o
LD_mingw=gcc
@@ -179,8 +229,7 @@ O_win32=obj
CC_win32=cl
DEF_win32= //D "WIN32" //D "NDEBUG" //D "_WINDOWS" //D "_USRDLL" \
//D "LUASOCKET_API=__declspec(dllexport)" //D "_CRT_SECURE_NO_WARNINGS" \
- //D "_WINDLL" //D "LUA_$(COMPAT)_MODULE" \
- //D "MIME_API=__declspec(dllexport)" \
+ //D "_WINDLL" //D "MIME_API=__declspec(dllexport)" \
//D "LUASOCKET_$(DEBUG)"
CFLAGS_win32=//I "$(LUAINC)" $(DEF) //O2 //Ot //MD //W3 //nologo
LDFLAGS_win32= //nologo //link //NOLOGO //DLL //INCREMENTAL:NO \
@@ -188,7 +237,7 @@ LDFLAGS_win32= //nologo //link //NOLOGO //DLL //INCREMENTAL:NO \
//MANIFESTUAC:"level='asInvoker' uiAccess='false'" \
//SUBSYSTEM:WINDOWS //OPT:REF //OPT:ICF //DYNAMICBASE:NO \
//MACHINE:X86 /LIBPATH:"$(shell cmd //c echo $(LUALIB))" \
- lua$(subst .,,$(LUAV)).lib ws2_32.lib //OUT:
+ $(LUALIBNAME_win32) ws2_32.lib //OUT:
LD_win32=cl
SOCKET_win32=wsocket.obj
@@ -204,8 +253,8 @@ SO=$(SO_$(PLAT))
O=$(O_$(PLAT))
SOCKET_V=3.0-rc1
MIME_V=1.0.3
-SOCKET_SO=socket.$(SO).$(SOCKET_V)
-MIME_SO=mime.$(SO).$(MIME_V)
+SOCKET_SO=socket-$(SOCKET_V).$(SO)
+MIME_SO=mime-$(MIME_V).$(SO)
UNIX_SO=unix.$(SO)
SERIAL_SO=serial.$(SO)
SOCKET=$(SOCKET_$(PLAT))
@@ -215,8 +264,8 @@ SOCKET=$(SOCKET_$(PLAT))
#
CC=$(CC_$(PLAT))
DEF=$(DEF_$(PLAT))
-CFLAGS=$(CFLAGS_$(PLAT))
-LDFLAGS=$(LDFLAGS_$(PLAT))
+CFLAGS=$(MYCFLAGS) $(CFLAGS_$(PLAT))
+LDFLAGS=$(MYLDFLAGS) $(LDFLAGS_$(PLAT))
LD=$(LD_$(PLAT))
LUAINC= $(LUAINC_$(PLAT))
LUALIB= $(LUALIB_$(PLAT))
@@ -230,6 +279,7 @@ SOCKET_OBJS= \
buffer.$(O) \
io.$(O) \
auxiliar.$(O) \
+ compat.$(O) \
options.$(O) \
inet.$(O) \
$(SOCKET) \
@@ -242,7 +292,8 @@ SOCKET_OBJS= \
# Modules belonging mime-core
#
MIME_OBJS= \
- mime.$(O)
+ mime.$(O) \
+ compat.$(O)
#------
# Modules belonging unix (local domain sockets)
@@ -259,7 +310,7 @@ UNIX_OBJS=\
#------
# Modules belonging to serial (device streams)
#
-SERIAL_OBJS:=\
+SERIAL_OBJS=\
buffer.$(O) \
auxiliar.$(O) \
options.$(O) \
@@ -289,6 +340,10 @@ TO_TOP_LDIR= \
#
default: $(PLAT)
+
+freebsd:
+ $(MAKE) all-unix PLAT=freebsd
+
macosx:
$(MAKE) all-unix PLAT=macosx
@@ -300,6 +355,9 @@ linux:
mingw:
$(MAKE) all PLAT=mingw
+
+solaris:
+ $(MAKE) all-unix PLAT=solaris
none:
@echo "Please run"
@@ -349,6 +407,7 @@ clean:
#------
# List of dependencies
#
+compat.$(O): compat.c compat.h
auxiliar.$(O): auxiliar.c auxiliar.h
buffer.$(O): buffer.c buffer.h io.h timeout.h
except.$(O): except.c except.h
diff --git a/src/mbox.lua b/src/mbox.lua
index 7724ae2..ed9e781 100644
--- a/src/mbox.lua
+++ b/src/mbox.lua
@@ -61,7 +61,7 @@ function _M.parse_from(from)
end
function _M.split_mbox(mbox_s)
- mbox = {}
+ local mbox = {}
mbox_s = string.gsub(mbox_s, "\r\n", "\n") .."\n\nFrom \n"
local nj, i, j = 1, 1, 1
while 1 do
diff --git a/src/mime.c b/src/mime.c
index dd37dcf..ed44104 100644
--- a/src/mime.c
+++ b/src/mime.c
@@ -6,10 +6,7 @@
#include "lua.h"
#include "lauxlib.h"
-
-#if !defined(LUA_VERSION_NUM) || (LUA_VERSION_NUM < 501)
-#include "compat-5.1.h"
-#endif
+#include "compat.h"
#include "mime.h"
@@ -41,7 +38,7 @@ static size_t b64decode(UC c, UC *input, size_t size, luaL_Buffer *buffer);
static void qpsetup(UC *class, UC *unbase);
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,
+static size_t qpencode(UC c, UC *input, size_t size,
const char *marker, luaL_Buffer *buffer);
static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer);
@@ -81,12 +78,8 @@ static UC b64unbase[256];
\*-------------------------------------------------------------------------*/
MIME_API int luaopen_mime_core(lua_State *L)
{
-#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
lua_newtable(L);
luaL_setfuncs(L, func, 0);
-#else
- luaL_openlib(L, "mime", func, 0);
-#endif
/* make version string available to scripts */
lua_pushstring(L, "_VERSION");
lua_pushstring(L, MIME_VERSION);
@@ -103,15 +96,15 @@ MIME_API int luaopen_mime_core(lua_State *L)
/*-------------------------------------------------------------------------*\
* Incrementaly breaks a string into lines. The string can have CRLF breaks.
* 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.
+* 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.
\*-------------------------------------------------------------------------*/
static int mime_global_wrp(lua_State *L)
{
size_t size = 0;
int left = (int) luaL_checknumber(L, 1);
- const UC *input = (UC *) luaL_optlstring(L, 2, NULL, &size);
+ const UC *input = (const UC *) luaL_optlstring(L, 2, NULL, &size);
const UC *last = input + size;
int length = (int) luaL_optnumber(L, 3, 76);
luaL_Buffer buffer;
@@ -123,7 +116,7 @@ static int mime_global_wrp(lua_State *L)
else lua_pushnil(L);
lua_pushnumber(L, length);
return 2;
- }
+ }
luaL_buffinit(L, &buffer);
while (input < last) {
switch (*input) {
@@ -150,9 +143,9 @@ static int mime_global_wrp(lua_State *L)
}
/*-------------------------------------------------------------------------*\
-* Fill base64 decode map.
+* Fill base64 decode map.
\*-------------------------------------------------------------------------*/
-static void b64setup(UC *unbase)
+static void b64setup(UC *unbase)
{
int i;
for (i = 0; i <= 255; i++) unbase[i] = (UC) 255;
@@ -161,11 +154,11 @@ static void b64setup(UC *unbase)
}
/*-------------------------------------------------------------------------*\
-* Acumulates bytes in input buffer until 3 bytes are available.
+* Acumulates bytes in input buffer until 3 bytes are available.
* Translate the 3 bytes into Base64 form and append to buffer.
* Returns new number of bytes in buffer.
\*-------------------------------------------------------------------------*/
-static size_t b64encode(UC c, UC *input, size_t size,
+static size_t b64encode(UC c, UC *input, size_t size,
luaL_Buffer *buffer)
{
input[size++] = c;
@@ -174,7 +167,7 @@ static size_t b64encode(UC c, UC *input, size_t size,
unsigned long value = 0;
value += input[0]; value <<= 8;
value += input[1]; value <<= 8;
- value += input[2];
+ value += input[2];
code[3] = b64base[value & 0x3f]; value >>= 6;
code[2] = b64base[value & 0x3f]; value >>= 6;
code[1] = b64base[value & 0x3f]; value >>= 6;
@@ -186,11 +179,11 @@ static size_t b64encode(UC c, UC *input, size_t size,
}
/*-------------------------------------------------------------------------*\
-* Encodes the Base64 last 1 or 2 bytes and adds padding '='
+* Encodes the Base64 last 1 or 2 bytes and adds padding '='
* Result, if any, is appended to buffer.
* Returns 0.
\*-------------------------------------------------------------------------*/
-static size_t b64pad(const UC *input, size_t size,
+static size_t b64pad(const UC *input, size_t size,
luaL_Buffer *buffer)
{
unsigned long value = 0;
@@ -203,7 +196,7 @@ static size_t b64pad(const UC *input, size_t size,
luaL_addlstring(buffer, (char *) code, 4);
break;
case 2:
- value = input[0]; value <<= 8;
+ value = input[0]; value <<= 8;
value |= input[1]; value <<= 2;
code[2] = b64base[value & 0x3f]; value >>= 6;
code[1] = b64base[value & 0x3f]; value >>= 6;
@@ -217,11 +210,11 @@ static size_t b64pad(const UC *input, size_t size,
}
/*-------------------------------------------------------------------------*\
-* Acumulates bytes in input buffer until 4 bytes are available.
+* Acumulates bytes in input buffer until 4 bytes are available.
* Translate the 4 bytes from Base64 form and append to buffer.
* Returns new number of bytes in buffer.
\*-------------------------------------------------------------------------*/
-static size_t b64decode(UC c, UC *input, size_t size,
+static size_t b64decode(UC c, UC *input, size_t size,
luaL_Buffer *buffer)
{
/* ignore invalid characters */
@@ -239,7 +232,7 @@ static size_t b64decode(UC c, UC *input, size_t size,
decoded[1] = (UC) (value & 0xff); value >>= 8;
decoded[0] = (UC) value;
/* take care of paddding */
- valid = (input[2] == '=') ? 1 : (input[3] == '=') ? 2 : 3;
+ valid = (input[2] == '=') ? 1 : (input[3] == '=') ? 2 : 3;
luaL_addlstring(buffer, (char *) decoded, valid);
return 0;
/* need more data */
@@ -251,7 +244,7 @@ static size_t b64decode(UC c, UC *input, size_t size,
* A, B = b64(C, D)
* A is the encoded version of the largest prefix of C .. D that is
* divisible by 3. B has the remaining bytes of C .. D, *without* encoding.
-* The easiest thing would be to concatenate the two strings and
+* The easiest thing would be to concatenate the two strings and
* encode the result, but we can't afford that or Lua would dupplicate
* every chunk we received.
\*-------------------------------------------------------------------------*/
@@ -259,7 +252,7 @@ static int mime_global_b64(lua_State *L)
{
UC atom[3];
size_t isize = 0, asize = 0;
- const UC *input = (UC *) luaL_optlstring(L, 1, NULL, &isize);
+ const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize);
const UC *last = input + isize;
luaL_Buffer buffer;
/* end-of-input blackhole */
@@ -272,9 +265,9 @@ static int mime_global_b64(lua_State *L)
lua_settop(L, 2);
/* process first part of the input */
luaL_buffinit(L, &buffer);
- while (input < last)
+ while (input < last)
asize = b64encode(*input++, atom, asize, &buffer);
- input = (UC *) luaL_optlstring(L, 2, NULL, &isize);
+ input = (const UC *) luaL_optlstring(L, 2, NULL, &isize);
/* if second part is nil, we are done */
if (!input) {
size_t osize = 0;
@@ -288,7 +281,7 @@ static int mime_global_b64(lua_State *L)
}
/* otherwise process the second part */
last = input + isize;
- while (input < last)
+ while (input < last)
asize = b64encode(*input++, atom, asize, &buffer);
luaL_pushresult(&buffer);
lua_pushlstring(L, (char *) atom, asize);
@@ -305,7 +298,7 @@ static int mime_global_unb64(lua_State *L)
{
UC atom[4];
size_t isize = 0, asize = 0;
- const UC *input = (UC *) luaL_optlstring(L, 1, NULL, &isize);
+ const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize);
const UC *last = input + isize;
luaL_Buffer buffer;
/* end-of-input blackhole */
@@ -318,9 +311,9 @@ static int mime_global_unb64(lua_State *L)
lua_settop(L, 2);
/* process first part of the input */
luaL_buffinit(L, &buffer);
- while (input < last)
+ while (input < last)
asize = b64decode(*input++, atom, asize, &buffer);
- input = (UC *) luaL_optlstring(L, 2, NULL, &isize);
+ input = (const UC *) luaL_optlstring(L, 2, NULL, &isize);
/* if second is nil, we are done */
if (!input) {
size_t osize = 0;
@@ -333,7 +326,7 @@ static int mime_global_unb64(lua_State *L)
}
/* otherwise, process the rest of the input */
last = input + isize;
- while (input < last)
+ while (input < last)
asize = b64decode(*input++, atom, asize, &buffer);
luaL_pushresult(&buffer);
lua_pushlstring(L, (char *) atom, asize);
@@ -349,7 +342,7 @@ static int mime_global_unb64(lua_State *L)
* 9 and 32 can be plain, unless in the end of a line, where must be =XX
* encoded lines must be no longer than 76 not counting CRLF
* soft line-break are =CRLF
-* To encode one byte, we need to see the next two.
+* To encode one byte, we need to see the next two.
* Worst case is when we see a space, and wonder if a CRLF is comming
\*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*\
@@ -362,7 +355,7 @@ static void qpsetup(UC *cl, UC *unbase)
for (i = 0; i < 256; i++) cl[i] = QP_QUOTED;
for (i = 33; i <= 60; i++) cl[i] = QP_PLAIN;
for (i = 62; i <= 126; i++) cl[i] = QP_PLAIN;
- cl['\t'] = QP_IF_LAST;
+ cl['\t'] = QP_IF_LAST;
cl[' '] = QP_IF_LAST;
cl['\r'] = QP_CR;
for (i = 0; i < 256; i++) unbase[i] = 255;
@@ -388,9 +381,9 @@ static void qpquote(UC c, luaL_Buffer *buffer)
/*-------------------------------------------------------------------------*\
* Accumulate characters until we are sure about how to deal with them.
-* Once we are sure, output to the buffer, in the correct form.
+* Once we are sure, output to the buffer, in the correct form.
\*-------------------------------------------------------------------------*/
-static size_t qpencode(UC c, UC *input, size_t size,
+static size_t qpencode(UC c, UC *input, size_t size,
const char *marker, luaL_Buffer *buffer)
{
input[size++] = c;
@@ -431,7 +424,7 @@ static size_t qpencode(UC c, UC *input, size_t size,
}
/*-------------------------------------------------------------------------*\
-* Deal with the final characters
+* Deal with the final characters
\*-------------------------------------------------------------------------*/
static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer)
{
@@ -448,8 +441,8 @@ static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer)
* Incrementally converts a string to quoted-printable
* A, B = qp(C, D, marker)
* 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.
+* 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.
\*-------------------------------------------------------------------------*/
static int mime_global_qp(lua_State *L)
@@ -457,7 +450,7 @@ static int mime_global_qp(lua_State *L)
size_t asize = 0, isize = 0;
UC atom[3];
- const UC *input = (UC *) luaL_optlstring(L, 1, NULL, &isize);
+ const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize);
const UC *last = input + isize;
const char *marker = luaL_optstring(L, 3, CRLF);
luaL_Buffer buffer;
@@ -473,7 +466,7 @@ static int mime_global_qp(lua_State *L)
luaL_buffinit(L, &buffer);
while (input < last)
asize = qpencode(*input++, atom, asize, marker, &buffer);
- input = (UC *) luaL_optlstring(L, 2, NULL, &isize);
+ input = (const UC *) luaL_optlstring(L, 2, NULL, &isize);
/* if second part is nil, we are done */
if (!input) {
asize = qppad(atom, asize, &buffer);
@@ -493,7 +486,7 @@ static int mime_global_qp(lua_State *L)
/*-------------------------------------------------------------------------*\
* Accumulate characters until we are sure about how to deal with them.
-* Once we are sure, output the to the buffer, in the correct form.
+* Once we are sure, output the to the buffer, in the correct form.
\*-------------------------------------------------------------------------*/
static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer) {
int d;
@@ -501,8 +494,8 @@ static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer) {
/* deal with all characters we can deal */
switch (input[0]) {
/* if we have an escape character */
- case '=':
- if (size < 3) return size;
+ case '=':
+ if (size < 3) return size;
/* eliminate soft line break */
if (input[1] == '\r' && input[2] == '\n') return 0;
/* decode quoted representation */
@@ -512,7 +505,7 @@ static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer) {
else luaL_addchar(buffer, (char) ((c << 4) + d));
return 0;
case '\r':
- if (size < 2) return size;
+ if (size < 2) return size;
if (input[1] == '\n') luaL_addlstring(buffer, (char *)input, 2);
return 0;
default:
@@ -525,15 +518,15 @@ static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer) {
/*-------------------------------------------------------------------------*\
* Incrementally decodes a string in quoted-printable
* A, B = qp(C, D)
-* A is the decoded version of the largest prefix of C .. D that
-* can be decoded without doubts.
+* A is the decoded version of the largest prefix of C .. D that
+* can be decoded without doubts.
* B has the remaining bytes of C .. D, *without* decoding.
\*-------------------------------------------------------------------------*/
static int mime_global_unqp(lua_State *L)
{
size_t asize = 0, isize = 0;
UC atom[3];
- const UC *input = (UC *) luaL_optlstring(L, 1, NULL, &isize);
+ const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize);
const UC *last = input + isize;
luaL_Buffer buffer;
/* end-of-input blackhole */
@@ -548,14 +541,14 @@ static int mime_global_unqp(lua_State *L)
luaL_buffinit(L, &buffer);
while (input < last)
asize = qpdecode(*input++, atom, asize, &buffer);
- input = (UC *) luaL_optlstring(L, 2, NULL, &isize);
+ input = (const UC *) luaL_optlstring(L, 2, NULL, &isize);
/* if second part is nil, we are done */
if (!input) {
luaL_pushresult(&buffer);
if (!(*lua_tostring(L, -1))) lua_pushnil(L);
lua_pushnil(L);
return 2;
- }
+ }
/* otherwise process rest of input */
last = input + isize;
while (input < last)
@@ -568,9 +561,9 @@ static int mime_global_unqp(lua_State *L)
/*-------------------------------------------------------------------------*\
* Incrementally breaks a quoted-printed string into lines
* A, n = qpwrp(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.
+* 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.
* There are two complications: lines can't be broken in the middle
* of an encoded =XX, and there might be line breaks already
\*-------------------------------------------------------------------------*/
@@ -578,7 +571,7 @@ static int mime_global_qpwrp(lua_State *L)
{
size_t size = 0;
int left = (int) luaL_checknumber(L, 1);
- const UC *input = (UC *) luaL_optlstring(L, 2, NULL, &size);
+ const UC *input = (const UC *) luaL_optlstring(L, 2, NULL, &size);
const UC *last = input + size;
int length = (int) luaL_optnumber(L, 3, 76);
luaL_Buffer buffer;
@@ -603,11 +596,11 @@ static int mime_global_qpwrp(lua_State *L)
if (left <= 3) {
left = length;
luaL_addstring(&buffer, EQCRLF);
- }
+ }
luaL_addchar(&buffer, *input);
left--;
break;
- default:
+ default:
if (left <= 1) {
left = length;
luaL_addstring(&buffer, EQCRLF);
@@ -635,7 +628,7 @@ static int mime_global_qpwrp(lua_State *L)
* last is the previous character
\*-------------------------------------------------------------------------*/
#define eolcandidate(c) (c == '\r' || c == '\n')
-static int eolprocess(int c, int last, const char *marker,
+static int eolprocess(int c, int last, const char *marker,
luaL_Buffer *buffer)
{
if (eolcandidate(c)) {
@@ -653,15 +646,15 @@ static int eolprocess(int c, int last, const char *marker,
}
/*-------------------------------------------------------------------------*\
-* Converts a string to uniform EOL convention.
+* Converts a string to uniform EOL convention.
* A, n = eol(o, B, marker)
* A is the converted version of the largest prefix of B that can be
-* converted unambiguously. 'o' is the context returned by the previous
+* converted unambiguously. 'o' is the context returned by the previous
* call. 'n' is the new context.
\*-------------------------------------------------------------------------*/
static int mime_global_eol(lua_State *L)
{
- int ctx = luaL_checkint(L, 1);
+ int ctx = luaL_checkinteger(L, 1);
size_t isize = 0;
const char *input = luaL_optlstring(L, 2, NULL, &isize);
const char *last = input + isize;
@@ -683,18 +676,18 @@ static int mime_global_eol(lua_State *L)
}
/*-------------------------------------------------------------------------*\
-* Takes one byte and stuff it if needed.
+* Takes one byte and stuff it if needed.
\*-------------------------------------------------------------------------*/
static size_t dot(int c, size_t state, luaL_Buffer *buffer)
{
luaL_addchar(buffer, (char) c);
switch (c) {
- case '\r':
+ case '\r':
return 1;
- case '\n':
- return (state == 1)? 2: 0;
- case '.':
- if (state == 2)
+ case '\n':
+ return (state == 1)? 2: 0;
+ case '.':
+ if (state == 2)
luaL_addchar(buffer, '.');
default:
return 0;
@@ -719,7 +712,7 @@ static int mime_global_dot(lua_State *L)
}
/* process all input */
luaL_buffinit(L, &buffer);
- while (input < last)
+ while (input < last)
state = dot(*input++, state, &buffer);
luaL_pushresult(&buffer);
lua_pushnumber(L, (lua_Number) state);
diff --git a/src/options.c b/src/options.c
index 8ac2a14..20f4c28 100644
--- a/src/options.c
+++ b/src/options.c
@@ -1,8 +1,8 @@
/*=========================================================================*\
-* Common option interface
+* Common option interface
* LuaSocket toolkit
\*=========================================================================*/
-#include