mirror of
https://github.com/lunarmodules/luasocket.git
synced 2024-12-25 12:08:21 +01:00
Saving before big changes to support IPv6.
This commit is contained in:
parent
bce60be30f
commit
3a8ba90dfb
13
FIX
13
FIX
@ -1,15 +1,14 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
http was preserving old host header during redirects
|
http was preserving old host header during redirects
|
||||||
fix smtp.send hang on source error
|
fix smtp.send hang on source error
|
||||||
add create field to FTP and SMTP and fix HTTP ugliness
|
add create field to FTP and SMTP and fix HTTP ugliness
|
||||||
clean timeout argument to open functions in SMTP, HTTP and FTP
|
clean timeout argument to open functions in SMTP, HTTP and FTP
|
||||||
eliminate globals from namespaces created by module().
|
eliminate globals from namespaces created by module().
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
url.absolute was not working when base_url was already parsed
|
url.absolute was not working when base_url was already parsed
|
||||||
http.request was redirecting even when the location header was empty
|
http.request was redirecting even when the location header was empty
|
||||||
tcp{client}:shutdown() was checking for group instead of class.
|
tcp{client}:shutdown() was checking for group instead of class.
|
||||||
|
46
NEW
46
NEW
@ -2,19 +2,37 @@ What's New
|
|||||||
|
|
||||||
This is just a bug-fix/update release.
|
This is just a bug-fix/update release.
|
||||||
|
|
||||||
* Fixed: manual links to home.html changed to index.html (Robert Hahn)
|
* Fixed: manual sample of HTTP authentication now uses correct
|
||||||
* Fixed: mime.unb64() returns empty string on results that start
|
"authorization" header (Alexandre Ittner);
|
||||||
with a null character (Robert Raschke)
|
* Fixed: failure on bind() was destroying the socket (Sam Roberts);
|
||||||
* Fixed: HTTP now automatically redirecting on 303 and 307 (Jonathan Gray)
|
* Fixed: receive() returns immediatelly if prefix can satisfy
|
||||||
* Fixed: sleep(-1) could sleep forever wasting CPU. Now it
|
bytes requested (M Joonas Pihlaja);
|
||||||
returns immediately (MPB);
|
* Fixed: multicast didn't work on Windows, or anywhere
|
||||||
|
else for that matter (Herbert Leuwer, Adrian Sietsma);
|
||||||
|
* Fixed: select() now reports an error when called with more
|
||||||
|
sockets than FD_SETSIZE (Lorenzo Leonini);
|
||||||
|
* Fixed: manual links to home.html changed to index.html (Robert Hahn);
|
||||||
|
* Fixed: mime.unb64() would return an empty string on results that started
|
||||||
|
with a null character (Robert Raschke);
|
||||||
|
* Fixed: HTTP now automatically redirects on 303 and 307 (Jonathan Gray);
|
||||||
|
* Fixed: calling sleep() with negative numbers could
|
||||||
|
block forever, wasting CPU. Now it returns immediately (MPB);
|
||||||
|
* Improved: FTP commands are now sent in upper case to
|
||||||
|
help buggy servers (Anders Eurenius);
|
||||||
|
* Improved: known headers now sent in canonic
|
||||||
|
capitalization to help buggy servers (Joseph Stewart);
|
||||||
|
* Improved: Clarified tcp:receive() in the manual (MPB);
|
||||||
|
* Improved: Decent makefiles (LHF).
|
||||||
|
* Fixed: RFC links in documentation now point to IETF (Cosmin Apreutesei).
|
||||||
|
|
||||||
* Improved: FTP commands are now sent in upper case to
|
|
||||||
help buggy servers (Anders Eurenius)
|
|
||||||
* Improved: known headers now sent in canonic
|
|
||||||
capitalization to help buggy servers (Joseph Stewart);
|
|
||||||
* Improved: Clarified tcp:receive() in the manual (MPB);
|
|
||||||
|
|
||||||
* Fixed: multicast didn't work on Windows (Herbert Leuwer, Adrian Sietsma)
|
Yuri's bug?
|
||||||
* Fixed: select() reports an error when called with more
|
Dahlberg
|
||||||
sockets than FD_SETSIZE (Lorenzo Leonini)
|
Sam Roberts
|
||||||
|
Thomas Harning Jr.
|
||||||
|
Sebastien Perin
|
||||||
|
remove getn in all files
|
||||||
|
ltn12.pump.all(
|
||||||
|
ltn12.source.file(io.open("original.png")),
|
||||||
|
ltn12.sink.file(io.open("copy.png", "wb"))
|
||||||
|
)
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
FTP (File Transfer Protocol) is a protocol used to transfer files
|
FTP (File Transfer Protocol) is a protocol used to transfer files
|
||||||
between hosts. The <tt>ftp</tt> namespace offers thorough support
|
between hosts. The <tt>ftp</tt> namespace offers thorough support
|
||||||
to FTP, under a simple interface. The implementation conforms to
|
to FTP, under a simple interface. The implementation conforms to
|
||||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc0959.txt">RFC 959</a>.
|
<a href="http://www.ietf.org/rfc/rfc959.txt">RFC 959</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -70,8 +70,8 @@ local ftp = require("socket.ftp")
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
URLs MUST conform to
|
URLs MUST conform to
|
||||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc1738.txt">RFC
|
<a href="http://www.ietf.org/rfc/rfc1738.txt">RFC 1738</a>,
|
||||||
1738</a>, that is, an URL is a string in the form:
|
that is, an URL is a string in the form:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
|
@ -45,8 +45,7 @@ namespace offers full support for the client side of the HTTP
|
|||||||
protocol (i.e.,
|
protocol (i.e.,
|
||||||
the facilities that would be used by a web-browser implementation). The
|
the facilities that would be used by a web-browser implementation). The
|
||||||
implementation conforms to the HTTP/1.1 standard,
|
implementation conforms to the HTTP/1.1 standard,
|
||||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2616.txt">RFC
|
<a href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</a>.
|
||||||
2616</a>.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -67,8 +66,7 @@ local http = require("socket.http")
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
URLs must conform to
|
URLs must conform to
|
||||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc1738.txt">RFC
|
<a href="http://www.ietf.org/rfc/rfc1738.txt">RFC 1738</a>,
|
||||||
1738</a>,
|
|
||||||
that is, an URL is a string in the form:
|
that is, an URL is a string in the form:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@ -199,8 +197,7 @@ it usually returns a message body (a web page informing the
|
|||||||
URL was not found or some other useless page). To make sure the
|
URL was not found or some other useless page). To make sure the
|
||||||
operation was successful, check the returned status <tt>code</tt>. For
|
operation was successful, check the returned status <tt>code</tt>. For
|
||||||
a list of the possible values and their meanings, refer to <a
|
a list of the possible values and their meanings, refer to <a
|
||||||
href="http://www.cs.princeton.edu/~diego/rfc/rfc2616.txt">RFC
|
href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</a>.
|
||||||
2616</a>.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class=description>
|
<p class=description>
|
||||||
@ -278,7 +275,7 @@ download and return status "401 Authentication Required".
|
|||||||
The HTTP/1.1 standard defines two authentication methods: the Basic
|
The HTTP/1.1 standard defines two authentication methods: the Basic
|
||||||
Authentication Scheme and the Digest Authentication Scheme, both
|
Authentication Scheme and the Digest Authentication Scheme, both
|
||||||
explained in detail in
|
explained in detail in
|
||||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2068.txt">RFC 2068</a>.
|
<a href="http://www.ietf.org/rfc/rfc2068.txt">RFC 2068</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class=note>The Basic Authentication Scheme sends
|
<p class=note>The Basic Authentication Scheme sends
|
||||||
@ -304,7 +301,7 @@ b, c, h = http.request("http://fulano:silva@www.example.com/private/index.html")
|
|||||||
-- the request directly.
|
-- the request directly.
|
||||||
r, c = http.request {
|
r, c = http.request {
|
||||||
url = "http://www.example.com/private/index.html",
|
url = "http://www.example.com/private/index.html",
|
||||||
headers = { authentication = "Basic " .. (mime.b64("fulano:silva")) }
|
headers = { authorization = "Basic " .. (mime.b64("fulano:silva")) }
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
@ -138,18 +138,22 @@ all!
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
<li> Fixed: manual sample of HTTP authentication now uses correct
|
||||||
|
"authorization" header (Alexandre Ittner);
|
||||||
|
<li> Fixed: receive() returns immediatelly if prefix can satisfy
|
||||||
|
bytes requested (M Joonas Pihlaja);
|
||||||
<li> Fixed: multicast didn't work on Windows, or anywhere
|
<li> Fixed: multicast didn't work on Windows, or anywhere
|
||||||
else for that matter (Herbert Leuwer, Adrian Sietsma)
|
else for that matter (Herbert Leuwer, Adrian Sietsma);
|
||||||
<li> Fixed: select() now reports an error when called with more
|
<li> Fixed: select() now reports an error when called with more
|
||||||
sockets than FD_SETSIZE (Lorenzo Leonini)
|
sockets than FD_SETSIZE (Lorenzo Leonini);
|
||||||
<li> Fixed: manual links to home.html changed to index.html (Robert Hahn)
|
<li> Fixed: manual links to home.html changed to index.html (Robert Hahn);
|
||||||
<li> Fixed: mime.unb64() would return an empty string on results that started
|
<li> Fixed: mime.unb64() would return an empty string on results that started
|
||||||
with a null character (Robert Raschke)
|
with a null character (Robert Raschke);
|
||||||
<li> Fixed: HTTP now automatically redirects on 303 and 307 (Jonathan Gray)
|
<li> Fixed: HTTP now automatically redirects on 303 and 307 (Jonathan Gray);
|
||||||
<li> Fixed: calling sleep() with negative numbers could
|
<li> Fixed: calling sleep() with negative numbers could
|
||||||
block forever, wasting CPU. Now it returns immediately (MPB);
|
block forever, wasting CPU. Now it returns immediately (MPB);
|
||||||
<li> Improved: FTP commands are now sent in upper case to
|
<li> Improved: FTP commands are now sent in upper case to
|
||||||
help buggy servers (Anders Eurenius)
|
help buggy servers (Anders Eurenius);
|
||||||
<li> Improved: known headers now sent in canonic
|
<li> Improved: known headers now sent in canonic
|
||||||
capitalization to help buggy servers (Joseph Stewart);
|
capitalization to help buggy servers (Joseph Stewart);
|
||||||
<li> Improved: Clarified tcp:receive() in the manual (MPB);
|
<li> Improved: Clarified tcp:receive() in the manual (MPB);
|
||||||
|
@ -44,11 +44,11 @@ content transfer encodings, such as Base64 and Quoted-Printable.
|
|||||||
It also provides functions to break text into lines and change
|
It also provides functions to break text into lines and change
|
||||||
the end-of-line convention.
|
the end-of-line convention.
|
||||||
MIME is described mainly in
|
MIME is described mainly in
|
||||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2045.txt">RFC 2045</a>,
|
<a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>,
|
||||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2046.txt">2046</a>,
|
<a href="http://www.ietf.org/rfc/rfc2046.txt">2046</a>,
|
||||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2047.txt">2047</a>,
|
<a href="http://www.ietf.org/rfc/rfc2047.txt">2047</a>,
|
||||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2047.txt">2048</a>, and
|
<a href="http://www.ietf.org/rfc/rfc2047.txt">2048</a>, and
|
||||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2048.txt">2049</a>.
|
<a href="http://www.ietf.org/rfc/rfc2048.txt">2049</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
@ -48,14 +48,13 @@ control (if you bother to read the code).
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>The implementation conforms to the Simple Mail Transfer Protocol,
|
<p>The implementation conforms to the Simple Mail Transfer Protocol,
|
||||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2821.txt">RFC 2821</a>.
|
<a href="http://www.ietf.org/rfc/rfc2821.txt">RFC 2821</a>.
|
||||||
Another RFC of interest is <a
|
Another RFC of interest is <a
|
||||||
href="http://www.cs.princeton.edu/~diego/rfc/rfc2822.txt">RFC 2822</a>,
|
href="http://www.ietf.org/rfc/rfc2822.txt">RFC 2822</a>,
|
||||||
which governs the Internet Message Format.
|
which governs the Internet Message Format.
|
||||||
Multipart messages (those that contain attachments) are part
|
Multipart messages (those that contain attachments) are part
|
||||||
of the MIME standard, but described mainly
|
of the MIME standard, but described mainly
|
||||||
in <a href="http://www.cs.princeton.edu/~diego/rfc/rfc2046.txt">RFC
|
in <a href="http://www.ietf.org/rfc/rfc2046.txt">RFC 2046</a>
|
||||||
2046</a>
|
|
||||||
|
|
||||||
<p> In the description below, good understanding of <a
|
<p> In the description below, good understanding of <a
|
||||||
href="http://lua-users.org/wiki/FiltersSourcesAndSinks"> LTN012, Filters
|
href="http://lua-users.org/wiki/FiltersSourcesAndSinks"> LTN012, Filters
|
||||||
@ -196,7 +195,7 @@ part of the message and will not be sent to anyone.
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class=note>
|
<p class=note>
|
||||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2822.txt">RFC 2822</a>
|
<a href="http://www.ietf.org/rfc/rfc2822.txt">RFC 2822</a>
|
||||||
has two <em>important and short</em> sections, "3.6.3. Destination address
|
has two <em>important and short</em> sections, "3.6.3. Destination address
|
||||||
fields" and "5. Security considerations", explaining the proper
|
fields" and "5. Security considerations", explaining the proper
|
||||||
use of these headers. Here is a summary of what it says:
|
use of these headers. Here is a summary of what it says:
|
||||||
@ -236,9 +235,9 @@ exactly what you <em>don't</em> want to happen!
|
|||||||
|
|
||||||
<p class=note>
|
<p class=note>
|
||||||
I hope this clarifies the issue. Otherwise, please refer to
|
I hope this clarifies the issue. Otherwise, please refer to
|
||||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2821.txt">RFC 2821</a>
|
<a href="http://www.ietf.org/rfc/rfc2821.txt">RFC 2821</a>
|
||||||
and
|
and
|
||||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2822.txt">RFC 2822</a>.
|
<a href="http://www.ietf.org/rfc/rfc2822.txt">RFC 2822</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre class=example>
|
<pre class=example>
|
||||||
|
@ -42,8 +42,7 @@
|
|||||||
The <tt>url</tt> namespace provides functions to parse, protect,
|
The <tt>url</tt> namespace provides functions to parse, protect,
|
||||||
and build URLs, as well as functions to compose absolute URLs
|
and build URLs, as well as functions to compose absolute URLs
|
||||||
from base and relative URLs, according to
|
from base and relative URLs, according to
|
||||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2396.txt">RFC
|
<a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>.
|
||||||
2396</a>.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -91,7 +90,7 @@ The function returns a string with the absolute URL.
|
|||||||
<p class=note>
|
<p class=note>
|
||||||
Note: The rules that
|
Note: The rules that
|
||||||
govern the composition are fairly complex, and are described in detail in
|
govern the composition are fairly complex, and are described in detail in
|
||||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2396.txt">RFC 2396</a>.
|
<a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>.
|
||||||
The example bellow should give an idea of what the rules are.
|
The example bellow should give an idea of what the rules are.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
44
etc/dict.lua
44
etc/dict.lua
@ -44,48 +44,48 @@ function metat.__index:check(ok)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function metat.__index:getdef()
|
function metat.__index:getdef()
|
||||||
local line = socket.try(self.tp:receive())
|
local line = socket.try(self.tp:receive())
|
||||||
local def = {}
|
local def = {}
|
||||||
while line ~= "." do
|
while line ~= "." do
|
||||||
table.insert(def, line)
|
table.insert(def, line)
|
||||||
line = socket.try(self.tp:receive())
|
line = socket.try(self.tp:receive())
|
||||||
end
|
end
|
||||||
return table.concat(def, "\n")
|
return table.concat(def, "\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
function metat.__index:define(database, word)
|
function metat.__index:define(database, word)
|
||||||
database = database or "!"
|
database = database or "!"
|
||||||
socket.try(self.tp:command("DEFINE", database .. " " .. word))
|
socket.try(self.tp:command("DEFINE", database .. " " .. word))
|
||||||
local code, count = self:check(150)
|
local code, count = self:check(150)
|
||||||
local defs = {}
|
local defs = {}
|
||||||
for i = 1, count do
|
for i = 1, count do
|
||||||
self:check(151)
|
self:check(151)
|
||||||
table.insert(defs, self:getdef())
|
table.insert(defs, self:getdef())
|
||||||
end
|
end
|
||||||
self:check(250)
|
self:check(250)
|
||||||
return defs
|
return defs
|
||||||
end
|
end
|
||||||
|
|
||||||
function metat.__index:match(database, strat, word)
|
function metat.__index:match(database, strat, word)
|
||||||
database = database or "!"
|
database = database or "!"
|
||||||
strat = strat or "."
|
strat = strat or "."
|
||||||
socket.try(self.tp:command("MATCH", database .." ".. strat .." ".. word))
|
socket.try(self.tp:command("MATCH", database .." ".. strat .." ".. word))
|
||||||
self:check(152)
|
self:check(152)
|
||||||
local mat = {}
|
local mat = {}
|
||||||
local line = socket.try(self.tp:receive())
|
local line = socket.try(self.tp:receive())
|
||||||
while line ~= '.' do
|
while line ~= '.' do
|
||||||
database, word = socket.skip(2, string.find(line, "(%S+) (.*)"))
|
database, word = socket.skip(2, string.find(line, "(%S+) (.*)"))
|
||||||
if not mat[database] then mat[database] = {} end
|
if not mat[database] then mat[database] = {} end
|
||||||
table.insert(mat[database], word)
|
table.insert(mat[database], word)
|
||||||
line = socket.try(self.tp:receive())
|
line = socket.try(self.tp:receive())
|
||||||
end
|
end
|
||||||
self:check(250)
|
self:check(250)
|
||||||
return mat
|
return mat
|
||||||
end
|
end
|
||||||
|
|
||||||
function metat.__index:quit()
|
function metat.__index:quit()
|
||||||
self.tp:command("QUIT")
|
self.tp:command("QUIT")
|
||||||
return self:check(221)
|
return self:check(221)
|
||||||
end
|
end
|
||||||
|
|
||||||
function metat.__index:close()
|
function metat.__index:close()
|
||||||
|
106
etc/get.lua
106
etc/get.lua
@ -12,53 +12,53 @@ local ltn12 = require("ltn12")
|
|||||||
|
|
||||||
-- formats a number of seconds into human readable form
|
-- formats a number of seconds into human readable form
|
||||||
function nicetime(s)
|
function nicetime(s)
|
||||||
local l = "s"
|
local l = "s"
|
||||||
if s > 60 then
|
if s > 60 then
|
||||||
s = s / 60
|
s = s / 60
|
||||||
l = "m"
|
l = "m"
|
||||||
if s > 60 then
|
if s > 60 then
|
||||||
s = s / 60
|
s = s / 60
|
||||||
l = "h"
|
l = "h"
|
||||||
if s > 24 then
|
if s > 24 then
|
||||||
s = s / 24
|
s = s / 24
|
||||||
l = "d" -- hmmm
|
l = "d" -- hmmm
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if l == "s" then return string.format("%5.0f%s", s, l)
|
if l == "s" then return string.format("%5.0f%s", s, l)
|
||||||
else return string.format("%5.2f%s", s, l) end
|
else return string.format("%5.2f%s", s, l) end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- formats a number of bytes into human readable form
|
-- formats a number of bytes into human readable form
|
||||||
function nicesize(b)
|
function nicesize(b)
|
||||||
local l = "B"
|
local l = "B"
|
||||||
if b > 1024 then
|
if b > 1024 then
|
||||||
b = b / 1024
|
b = b / 1024
|
||||||
l = "KB"
|
l = "KB"
|
||||||
if b > 1024 then
|
if b > 1024 then
|
||||||
b = b / 1024
|
b = b / 1024
|
||||||
l = "MB"
|
l = "MB"
|
||||||
if b > 1024 then
|
if b > 1024 then
|
||||||
b = b / 1024
|
b = b / 1024
|
||||||
l = "GB" -- hmmm
|
l = "GB" -- hmmm
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return string.format("%7.2f%2s", b, l)
|
return string.format("%7.2f%2s", b, l)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- returns a string with the current state of the download
|
-- returns a string with the current state of the download
|
||||||
local remaining_s = "%s received, %s/s throughput, %2.0f%% done, %s remaining"
|
local remaining_s = "%s received, %s/s throughput, %2.0f%% done, %s remaining"
|
||||||
local elapsed_s = "%s received, %s/s throughput, %s elapsed "
|
local elapsed_s = "%s received, %s/s throughput, %s elapsed "
|
||||||
function gauge(got, delta, size)
|
function gauge(got, delta, size)
|
||||||
local rate = got / delta
|
local rate = got / delta
|
||||||
if size and size >= 1 then
|
if size and size >= 1 then
|
||||||
return string.format(remaining_s, nicesize(got), nicesize(rate),
|
return string.format(remaining_s, nicesize(got), nicesize(rate),
|
||||||
100*got/size, nicetime((size-got)/rate))
|
100*got/size, nicetime((size-got)/rate))
|
||||||
else
|
else
|
||||||
return string.format(elapsed_s, nicesize(got),
|
return string.format(elapsed_s, nicesize(got),
|
||||||
nicesize(rate), nicetime(delta))
|
nicesize(rate), nicetime(delta))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- creates a new instance of a receive_cb that saves to disk
|
-- creates a new instance of a receive_cb that saves to disk
|
||||||
@ -89,10 +89,10 @@ end
|
|||||||
|
|
||||||
-- determines the size of a http file
|
-- determines the size of a http file
|
||||||
function gethttpsize(u)
|
function gethttpsize(u)
|
||||||
local r, c, h = http.request {method = "HEAD", url = u}
|
local r, c, h = http.request {method = "HEAD", url = u}
|
||||||
if c == 200 then
|
if c == 200 then
|
||||||
return tonumber(h["content-length"])
|
return tonumber(h["content-length"])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- downloads a file using the http protocol
|
-- downloads a file using the http protocol
|
||||||
@ -101,7 +101,7 @@ function getbyhttp(u, file)
|
|||||||
-- only print feedback if output is not stdout
|
-- only print feedback if output is not stdout
|
||||||
if file then save = ltn12.sink.chain(stats(gethttpsize(u)), save) end
|
if file then save = ltn12.sink.chain(stats(gethttpsize(u)), save) end
|
||||||
local r, c, h, s = http.request {url = u, sink = save }
|
local r, c, h, s = http.request {url = u, sink = save }
|
||||||
if c ~= 200 then io.stderr:write(s or c, "\n") end
|
if c ~= 200 then io.stderr:write(s or c, "\n") end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- downloads a file using the ftp protocol
|
-- downloads a file using the ftp protocol
|
||||||
@ -114,29 +114,29 @@ function getbyftp(u, file)
|
|||||||
gett.sink = save
|
gett.sink = save
|
||||||
gett.type = "i"
|
gett.type = "i"
|
||||||
local ret, err = ftp.get(gett)
|
local ret, err = ftp.get(gett)
|
||||||
if err then print(err) end
|
if err then print(err) end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- determines the scheme
|
-- determines the scheme
|
||||||
function getscheme(u)
|
function getscheme(u)
|
||||||
-- this is an heuristic to solve a common invalid url poblem
|
-- this is an heuristic to solve a common invalid url poblem
|
||||||
if not string.find(u, "//") then u = "//" .. u end
|
if not string.find(u, "//") then u = "//" .. u end
|
||||||
local parsed = url.parse(u, {scheme = "http"})
|
local parsed = url.parse(u, {scheme = "http"})
|
||||||
return parsed.scheme
|
return parsed.scheme
|
||||||
end
|
end
|
||||||
|
|
||||||
-- gets a file either by http or ftp, saving as <name>
|
-- gets a file either by http or ftp, saving as <name>
|
||||||
function get(u, name)
|
function get(u, name)
|
||||||
local fout = name and io.open(name, "wb")
|
local fout = name and io.open(name, "wb")
|
||||||
local scheme = getscheme(u)
|
local scheme = getscheme(u)
|
||||||
if scheme == "ftp" then getbyftp(u, fout)
|
if scheme == "ftp" then getbyftp(u, fout)
|
||||||
elseif scheme == "http" then getbyhttp(u, fout)
|
elseif scheme == "http" then getbyhttp(u, fout)
|
||||||
else print("unknown scheme" .. scheme) end
|
else print("unknown scheme" .. scheme) end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- main program
|
-- main program
|
||||||
arg = arg or {}
|
arg = arg or {}
|
||||||
if table.getn(arg) < 1 then
|
if table.getn(arg) < 1 then
|
||||||
io.write("Usage:\n lua get.lua <remote-url> [<local-file>]\n")
|
io.write("Usage:\n lua get.lua <remote-url> [<local-file>]\n")
|
||||||
os.exit(1)
|
os.exit(1)
|
||||||
else get(arg[1], arg[2]) end
|
else get(arg[1], arg[2]) end
|
||||||
|
@ -268,11 +268,11 @@ send = socket.protect(function(option)
|
|||||||
local class = string.sub(option.class or localip or localhost,1,31)
|
local class = string.sub(option.class or localip or localhost,1,31)
|
||||||
local _,_,ctlfn = string.find(file,".*[%/%\\](.*)")
|
local _,_,ctlfn = string.find(file,".*[%/%\\](.*)")
|
||||||
ctlfn = string.sub(ctlfn or file,1,131)
|
ctlfn = string.sub(ctlfn or file,1,131)
|
||||||
local cfile =
|
local cfile =
|
||||||
string.format("H%-s\nC%-s\nJ%-s\nP%-s\n%.1s%-s\nU%-s\nN%-s\n",
|
string.format("H%-s\nC%-s\nJ%-s\nP%-s\n%.1s%-s\nU%-s\nN%-s\n",
|
||||||
localhost,
|
localhost,
|
||||||
class,
|
class,
|
||||||
option.job or "LuaSocket",
|
option.job or "LuaSocket",
|
||||||
user,
|
user,
|
||||||
fmt, lpfile,
|
fmt, lpfile,
|
||||||
lpfile,
|
lpfile,
|
||||||
|
68
etc/tftp.lua
68
etc/tftp.lua
@ -35,18 +35,18 @@ local OP_INV = {"RRQ", "WRQ", "DATA", "ACK", "ERROR"}
|
|||||||
-- Packet creation functions
|
-- Packet creation functions
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
local function RRQ(source, mode)
|
local function RRQ(source, mode)
|
||||||
return char(0, OP_RRQ) .. source .. char(0) .. mode .. char(0)
|
return char(0, OP_RRQ) .. source .. char(0) .. mode .. char(0)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function WRQ(source, mode)
|
local function WRQ(source, mode)
|
||||||
return char(0, OP_RRQ) .. source .. char(0) .. mode .. char(0)
|
return char(0, OP_RRQ) .. source .. char(0) .. mode .. char(0)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function ACK(block)
|
local function ACK(block)
|
||||||
local low, high
|
local low, high
|
||||||
low = math.mod(block, 256)
|
low = math.mod(block, 256)
|
||||||
high = (block - low)/256
|
high = (block - low)/256
|
||||||
return char(0, OP_ACK, high, low)
|
return char(0, OP_ACK, high, low)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function get_OP(dgram)
|
local function get_OP(dgram)
|
||||||
@ -58,16 +58,16 @@ end
|
|||||||
-- Packet analysis functions
|
-- Packet analysis functions
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
local function split_DATA(dgram)
|
local function split_DATA(dgram)
|
||||||
local block = byte(dgram, 3)*256 + byte(dgram, 4)
|
local block = byte(dgram, 3)*256 + byte(dgram, 4)
|
||||||
local data = string.sub(dgram, 5)
|
local data = string.sub(dgram, 5)
|
||||||
return block, data
|
return block, data
|
||||||
end
|
end
|
||||||
|
|
||||||
local function get_ERROR(dgram)
|
local function get_ERROR(dgram)
|
||||||
local code = byte(dgram, 3)*256 + byte(dgram, 4)
|
local code = byte(dgram, 3)*256 + byte(dgram, 4)
|
||||||
local msg
|
local msg
|
||||||
_,_, msg = string.find(dgram, "(.*)\000", 5)
|
_,_, msg = string.find(dgram, "(.*)\000", 5)
|
||||||
return string.format("error code %d: %s", code, msg)
|
return string.format("error code %d: %s", code, msg)
|
||||||
end
|
end
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
@ -77,40 +77,40 @@ local function tget(gett)
|
|||||||
local retries, dgram, sent, datahost, dataport, code
|
local retries, dgram, sent, datahost, dataport, code
|
||||||
local last = 0
|
local last = 0
|
||||||
socket.try(gett.host, "missing host")
|
socket.try(gett.host, "missing host")
|
||||||
local con = socket.try(socket.udp())
|
local con = socket.try(socket.udp())
|
||||||
local try = socket.newtry(function() con:close() end)
|
local try = socket.newtry(function() con:close() end)
|
||||||
-- convert from name to ip if needed
|
-- convert from name to ip if needed
|
||||||
gett.host = try(socket.dns.toip(gett.host))
|
gett.host = try(socket.dns.toip(gett.host))
|
||||||
con:settimeout(1)
|
con:settimeout(1)
|
||||||
-- first packet gives data host/port to be used for data transfers
|
-- first packet gives data host/port to be used for data transfers
|
||||||
local path = string.gsub(gett.path or "", "^/", "")
|
local path = string.gsub(gett.path or "", "^/", "")
|
||||||
path = url.unescape(path)
|
path = url.unescape(path)
|
||||||
retries = 0
|
retries = 0
|
||||||
repeat
|
repeat
|
||||||
sent = try(con:sendto(RRQ(path, "octet"), gett.host, gett.port))
|
sent = try(con:sendto(RRQ(path, "octet"), gett.host, gett.port))
|
||||||
dgram, datahost, dataport = con:receivefrom()
|
dgram, datahost, dataport = con:receivefrom()
|
||||||
retries = retries + 1
|
retries = retries + 1
|
||||||
until dgram or datahost ~= "timeout" or retries > 5
|
until dgram or datahost ~= "timeout" or retries > 5
|
||||||
try(dgram, datahost)
|
try(dgram, datahost)
|
||||||
-- associate socket with data host/port
|
-- associate socket with data host/port
|
||||||
try(con:setpeername(datahost, dataport))
|
try(con:setpeername(datahost, dataport))
|
||||||
-- default sink
|
-- default sink
|
||||||
local sink = gett.sink or ltn12.sink.null()
|
local sink = gett.sink or ltn12.sink.null()
|
||||||
-- process all data packets
|
-- process all data packets
|
||||||
while 1 do
|
while 1 do
|
||||||
-- decode packet
|
-- decode packet
|
||||||
code = get_OP(dgram)
|
code = get_OP(dgram)
|
||||||
try(code ~= OP_ERROR, get_ERROR(dgram))
|
try(code ~= OP_ERROR, get_ERROR(dgram))
|
||||||
try(code == OP_DATA, "unhandled opcode " .. code)
|
try(code == OP_DATA, "unhandled opcode " .. code)
|
||||||
-- get data packet parts
|
-- get data packet parts
|
||||||
local block, data = split_DATA(dgram)
|
local block, data = split_DATA(dgram)
|
||||||
-- if not repeated, write
|
-- if not repeated, write
|
||||||
if block == last+1 then
|
if block == last+1 then
|
||||||
try(sink(data))
|
try(sink(data))
|
||||||
last = block
|
last = block
|
||||||
end
|
end
|
||||||
-- last packet brings less than 512 bytes of data
|
-- last packet brings less than 512 bytes of data
|
||||||
if string.len(data) < 512 then
|
if string.len(data) < 512 then
|
||||||
try(con:send(ACK(block)))
|
try(con:send(ACK(block)))
|
||||||
try(con:close())
|
try(con:close())
|
||||||
try(sink(nil))
|
try(sink(nil))
|
||||||
@ -118,13 +118,13 @@ local function tget(gett)
|
|||||||
end
|
end
|
||||||
-- get the next packet
|
-- get the next packet
|
||||||
retries = 0
|
retries = 0
|
||||||
repeat
|
repeat
|
||||||
sent = try(con:send(ACK(last)))
|
sent = try(con:send(ACK(last)))
|
||||||
dgram, err = con:receive()
|
dgram, err = con:receive()
|
||||||
retries = retries + 1
|
retries = retries + 1
|
||||||
until dgram or err ~= "timeout" or retries > 5
|
until dgram or err ~= "timeout" or retries > 5
|
||||||
try(dgram, err)
|
try(dgram, err)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local default = {
|
local default = {
|
||||||
|
16
makefile
16
makefile
@ -1,21 +1,13 @@
|
|||||||
PLAT= none
|
PLAT?= macosx
|
||||||
PLATS= macosx linux
|
PLATS= macosx linux win32
|
||||||
|
|
||||||
#------
|
#------
|
||||||
# Hopefully no need to change anything below this line
|
# Hopefully no need to change anything below this line
|
||||||
#
|
#
|
||||||
all: $(PLAT)
|
all: $(PLAT)
|
||||||
|
|
||||||
none:
|
$(PLATS) none install local clean:
|
||||||
@echo "Please run"
|
@cd src; $(MAKE) $@
|
||||||
@echo " make PLATFORM"
|
|
||||||
@echo "where PLATFORM is one of these:"
|
|
||||||
@echo " $(PLATS)"
|
|
||||||
|
|
||||||
$(PLATS) install local clean:
|
|
||||||
cd src; $(MAKE) $@
|
|
||||||
|
|
||||||
dummy:
|
|
||||||
|
|
||||||
test: dummy
|
test: dummy
|
||||||
lua test/hello.lua
|
lua test/hello.lua
|
||||||
|
14
src/buffer.c
14
src/buffer.c
@ -42,7 +42,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) {
|
void buffer_init(p_buffer buf, p_io io, p_timeout tm) {
|
||||||
buf->first = buf->last = 0;
|
buf->first = buf->last = 0;
|
||||||
buf->io = io;
|
buf->io = io;
|
||||||
buf->tm = tm;
|
buf->tm = tm;
|
||||||
buf->received = buf->sent = 0;
|
buf->received = buf->sent = 0;
|
||||||
@ -122,9 +122,15 @@ int buffer_meth_receive(lua_State *L, p_buffer buf) {
|
|||||||
if (p[0] == '*' && p[1] == 'l') err = recvline(buf, &b);
|
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");
|
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) */
|
* received) */
|
||||||
} else err = recvraw(buf, (size_t) lua_tonumber(L, 2)-size, &b);
|
} else {
|
||||||
|
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)
|
||||||
|
err = recvraw(buf, wanted-size, &b);
|
||||||
|
}
|
||||||
/* check if there was an error */
|
/* check if there was an error */
|
||||||
if (err != IO_DONE) {
|
if (err != IO_DONE) {
|
||||||
/* we can't push anyting in the stack before pushing the
|
/* we can't push anyting in the stack before pushing the
|
||||||
|
@ -29,8 +29,8 @@ typedef struct t_buffer_ {
|
|||||||
size_t sent, received; /* bytes sent, and bytes received */
|
size_t sent, received; /* bytes sent, and bytes received */
|
||||||
p_io io; /* IO driver used for this buffer */
|
p_io io; /* IO driver used for this buffer */
|
||||||
p_timeout tm; /* timeout management for this buffer */
|
p_timeout tm; /* timeout management for this buffer */
|
||||||
size_t first, last; /* index of first and last bytes of stored data */
|
size_t first, last; /* index of first and last bytes of stored data */
|
||||||
char data[BUF_SIZE]; /* storage space for buffer data */
|
char data[BUF_SIZE]; /* storage space for buffer data */
|
||||||
} t_buffer;
|
} t_buffer;
|
||||||
typedef t_buffer *p_buffer;
|
typedef t_buffer *p_buffer;
|
||||||
|
|
||||||
|
@ -212,8 +212,8 @@ local function tput(putt)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local default = {
|
local default = {
|
||||||
path = "/",
|
path = "/",
|
||||||
scheme = "ftp"
|
scheme = "ftp"
|
||||||
}
|
}
|
||||||
|
|
||||||
local function parse(u)
|
local function parse(u)
|
||||||
|
@ -213,7 +213,7 @@ const char *inet_tryconnect(p_socket ps, const char *address,
|
|||||||
memset(&remote, 0, sizeof(remote));
|
memset(&remote, 0, sizeof(remote));
|
||||||
remote.sin_family = AF_INET;
|
remote.sin_family = AF_INET;
|
||||||
remote.sin_port = htons(port);
|
remote.sin_port = htons(port);
|
||||||
if (strcmp(address, "*")) {
|
if (strcmp(address, "*")) {
|
||||||
if (!inet_aton(address, &remote.sin_addr)) {
|
if (!inet_aton(address, &remote.sin_addr)) {
|
||||||
struct hostent *hp = NULL;
|
struct hostent *hp = NULL;
|
||||||
struct in_addr **addr;
|
struct in_addr **addr;
|
||||||
@ -248,7 +248,6 @@ const char *inet_trybind(p_socket ps, const char *address, unsigned short port)
|
|||||||
memcpy(&local.sin_addr, *addr, sizeof(struct in_addr));
|
memcpy(&local.sin_addr, *addr, sizeof(struct in_addr));
|
||||||
}
|
}
|
||||||
err = socket_bind(ps, (SA *) &local, sizeof(local));
|
err = socket_bind(ps, (SA *) &local, sizeof(local));
|
||||||
if (err != IO_DONE) socket_destroy(ps);
|
|
||||||
return socket_strerror(err);
|
return socket_strerror(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
173
src/makefile
173
src/makefile
@ -1,8 +1,13 @@
|
|||||||
PLAT = none
|
PLAT?=macosx
|
||||||
|
|
||||||
INSTALL_DATA=cp
|
INSTALL_DATA=cp
|
||||||
INSTALL_EXEC=cp
|
INSTALL_EXEC=cp
|
||||||
INSTALL_TOP= /opt/local
|
INSTALL_TOP=/opt/local
|
||||||
LUAINC= $(LUAINC_$(PLAT))
|
|
||||||
|
LUAINC_macosx=/opt/local/include
|
||||||
|
LUAINC_linux=/usr/include/lua5.1
|
||||||
|
LUAINC_win32="../../lua-5.1.3/src"
|
||||||
|
LUALIB_win32="../../lua-5.1.3"
|
||||||
|
|
||||||
#------
|
#------
|
||||||
# Install directories
|
# Install directories
|
||||||
@ -15,40 +20,76 @@ INSTALL_MIME_SHARE=$(INSTALL_TOP_SHARE)/mime
|
|||||||
INSTALL_MIME_LIB=$(INSTALL_TOP_LIB)/mime
|
INSTALL_MIME_LIB=$(INSTALL_TOP_LIB)/mime
|
||||||
|
|
||||||
#------
|
#------
|
||||||
# Output file names
|
# Supported platforms
|
||||||
#
|
#
|
||||||
EXT=so
|
PLATS= macosx linux win32
|
||||||
SOCKET_V=2.0.3
|
|
||||||
MIME_V=1.0.3
|
|
||||||
SOCKET_SO=socket.$(EXT).$(SOCKET_V)
|
|
||||||
MIME_SO=mime.$(EXT).$(MIME_V)
|
|
||||||
UNIX_SO=unix.$(EXT)
|
|
||||||
|
|
||||||
#------
|
#------
|
||||||
# Compiler and linker settings
|
# Compiler and linker settings
|
||||||
# for Mac OS X
|
# for Mac OS X
|
||||||
LUAINC_macosx= -I/opt/local/include
|
SO_macosx=so
|
||||||
|
O_macosx=o
|
||||||
CC_macosx=gcc
|
CC_macosx=gcc
|
||||||
DEF_macosx= -DLUASOCKET_DEBUG -DUNIX_HAS_SUN_LEN \
|
DEF_macosx= -DLUASOCKET_DEBUG -DUNIX_HAS_SUN_LEN \
|
||||||
-DLUASOCKET_API='__attribute__((visibility("default")))' \
|
-DLUASOCKET_API='__attribute__((visibility("default")))' \
|
||||||
-DMIME_API='__attribute__((visibility("default")))'
|
-DMIME_API='__attribute__((visibility("default")))'
|
||||||
CFLAGS_macosx= $(LUAINC) $(COMPAT) $(DEF) -pedantic -Wall -O2 -fno-common \
|
CFLAGS_macosx= -I$(LUAINC) $(DEF) -pedantic -Wall -O2 -fno-common \
|
||||||
-fvisibility=hidden
|
-fvisibility=hidden
|
||||||
LDFLAGS_macosx= -bundle -undefined dynamic_lookup
|
LDFLAGS_macosx= -bundle -undefined dynamic_lookup -o
|
||||||
LD_macosx= export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc
|
LD_macosx= export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc
|
||||||
|
SOCKET_macosx=usocket.o
|
||||||
|
|
||||||
#------
|
#------
|
||||||
# Compiler and linker settings
|
# Compiler and linker settings
|
||||||
# for Linux
|
# for Linux
|
||||||
LUAINC_linux= -I/usr/local/include/lua5.1
|
SO_linux=so
|
||||||
|
O_linux=o
|
||||||
CC_linux=gcc
|
CC_linux=gcc
|
||||||
DEF_linux=-DLUASOCKET_DEBUG \
|
DEF_linux=-DLUASOCKET_DEBUG \
|
||||||
-DLUASOCKET_API='__attribute__((visibility("default")))' \
|
-DLUASOCKET_API='__attribute__((visibility("default")))' \
|
||||||
-DMIME_API='__attribute__((visibility("default")))'
|
-DMIME_API='__attribute__((visibility("default")))'
|
||||||
CFLAGS_linux= $(LUAINC) $(DEF) -pedantic -Wall -O2 -fpic \
|
CFLAGS_linux= -I$(LUAINC) $(DEF) -pedantic -Wall -O2 -fpic \
|
||||||
-fvisibility=hidden
|
-fvisibility=hidden
|
||||||
LDFLAGS_linux=-O -shared -fpic
|
LDFLAGS_linux=-O -shared -fpic -o
|
||||||
LD_linux= gcc
|
LD_linux=gcc
|
||||||
|
SOCKET_linux=usocket.o
|
||||||
|
|
||||||
|
#------
|
||||||
|
# Compiler and linker settings
|
||||||
|
# for Win32
|
||||||
|
SO_win32=dll
|
||||||
|
O_win32=obj
|
||||||
|
CC_win32=cl
|
||||||
|
DEF_win32= /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" \
|
||||||
|
/D "LUASOCKET_API=__declspec(dllexport)" /D "LUASOCKET_DEBUG" \
|
||||||
|
/D "_CRT_SECURE_NO_WARNINGS" /D "_WINDLL"
|
||||||
|
CFLAGS_win32=/I$(LUAINC) $(DEF) /O2 /Ot /MD /W3 /nologo
|
||||||
|
LDFLAGS_win32= /nologo /link /NOLOGO /DLL /INCREMENTAL:NO \
|
||||||
|
/LIBPATH:$(LUALIB) \
|
||||||
|
/MANIFEST \
|
||||||
|
/MANIFESTFILE:"intermediate.manifest" \
|
||||||
|
/MANIFESTUAC:"level='asInvoker' uiAccess='false'" \
|
||||||
|
/SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF /DYNAMICBASE:NO \
|
||||||
|
/MACHINE:X86 ws2_32.lib lua5.1.lib /OUT:
|
||||||
|
LD_win32=cl
|
||||||
|
SOCKET_win32=wsocket.obj
|
||||||
|
|
||||||
|
.SUFFIXES: .obj
|
||||||
|
|
||||||
|
.c.obj:
|
||||||
|
$(CC) $(CFLAGS) /Fo"$@" /c $<
|
||||||
|
|
||||||
|
#------
|
||||||
|
# Output file names
|
||||||
|
#
|
||||||
|
SO=$(SO_$(PLAT))
|
||||||
|
O=$(O_$(PLAT))
|
||||||
|
SOCKET_V=2.0.3
|
||||||
|
MIME_V=1.0.3
|
||||||
|
SOCKET_SO=socket.$(SO).$(SOCKET_V)
|
||||||
|
MIME_SO=mime.$(SO).$(MIME_V)
|
||||||
|
UNIX_SO=unix.$(SO)
|
||||||
|
SOCKET=$(SOCKET_$(PLAT))
|
||||||
|
|
||||||
#------
|
#------
|
||||||
# Settings selected for platform
|
# Settings selected for platform
|
||||||
@ -58,46 +99,48 @@ DEF=$(DEF_$(PLAT))
|
|||||||
CFLAGS=$(CFLAGS_$(PLAT))
|
CFLAGS=$(CFLAGS_$(PLAT))
|
||||||
LDFLAGS=$(LDFLAGS_$(PLAT))
|
LDFLAGS=$(LDFLAGS_$(PLAT))
|
||||||
LD=$(LD_$(PLAT))
|
LD=$(LD_$(PLAT))
|
||||||
|
LUAINC= $(LUAINC_$(PLAT))
|
||||||
|
LUALIB= $(LUALIB_$(PLAT))
|
||||||
|
|
||||||
#------
|
#------
|
||||||
# Modules belonging to socket-core
|
# Modules belonging to socket-core
|
||||||
#
|
#
|
||||||
SOCKET_OBJS= \
|
SOCKET_OBJS= \
|
||||||
luasocket.o \
|
luasocket.$(O) \
|
||||||
timeout.o \
|
timeout.$(O) \
|
||||||
buffer.o \
|
buffer.$(O) \
|
||||||
io.o \
|
io.$(O) \
|
||||||
auxiliar.o \
|
auxiliar.$(O) \
|
||||||
options.o \
|
options.$(O) \
|
||||||
inet.o \
|
inet.$(O) \
|
||||||
usocket.o \
|
$(SOCKET) \
|
||||||
except.o \
|
except.$(O) \
|
||||||
select.o \
|
select.$(O) \
|
||||||
tcp.o \
|
tcp.$(O) \
|
||||||
udp.o
|
udp.$(O)
|
||||||
|
|
||||||
#------
|
#------
|
||||||
# Modules belonging mime-core
|
# Modules belonging mime-core
|
||||||
#
|
#
|
||||||
MIME_OBJS= \
|
MIME_OBJS= \
|
||||||
mime.o
|
mime.$(O)
|
||||||
|
|
||||||
#------
|
#------
|
||||||
# Modules belonging unix (local domain sockets)
|
# Modules belonging unix (local domain sockets)
|
||||||
#
|
#
|
||||||
UNIX_OBJS:=\
|
UNIX_OBJS=\
|
||||||
buffer.o \
|
buffer.$(O) \
|
||||||
auxiliar.o \
|
auxiliar.$(O) \
|
||||||
options.o \
|
options.$(O) \
|
||||||
timeout.o \
|
timeout.$(O) \
|
||||||
io.o \
|
io.$(O) \
|
||||||
usocket.o \
|
usocket.$(O) \
|
||||||
unix.o
|
unix.$(O)
|
||||||
|
|
||||||
#------
|
#------
|
||||||
# Files to install
|
# Files to install
|
||||||
#
|
#
|
||||||
TO_SOCKET_SHARE:= \
|
TO_SOCKET_SHARE= \
|
||||||
http.lua \
|
http.lua \
|
||||||
url.lua \
|
url.lua \
|
||||||
tp.lua \
|
tp.lua \
|
||||||
@ -105,33 +148,41 @@ TO_SOCKET_SHARE:= \
|
|||||||
headers.lua \
|
headers.lua \
|
||||||
smtp.lua
|
smtp.lua
|
||||||
|
|
||||||
TO_TOP_SHARE:= \
|
TO_TOP_SHARE= \
|
||||||
ltn12.lua \
|
ltn12.lua \
|
||||||
socket.lua \
|
socket.lua \
|
||||||
mime.lua
|
mime.lua
|
||||||
|
|
||||||
|
#------
|
||||||
|
# Targets
|
||||||
|
#
|
||||||
default: $(PLAT)
|
default: $(PLAT)
|
||||||
|
|
||||||
macosx:
|
macosx:
|
||||||
$(MAKE) all PLAT=macosx
|
$(MAKE) all PLAT=macosx
|
||||||
|
|
||||||
|
win32:
|
||||||
|
$(MAKE) all PLAT=win32
|
||||||
|
|
||||||
linux:
|
linux:
|
||||||
$(MAKE) all PLAT=linux
|
$(MAKE) all PLAT=linux
|
||||||
|
|
||||||
none:
|
none:
|
||||||
@echo "Please choose a platform:"
|
@echo "Please run"
|
||||||
|
@echo " make PLATFORM"
|
||||||
|
@echo "where PLATFORM is one of these:"
|
||||||
@echo " $(PLATS)"
|
@echo " $(PLATS)"
|
||||||
|
|
||||||
all: $(SOCKET_SO) $(MIME_SO)
|
all: $(SOCKET_SO) $(MIME_SO)
|
||||||
|
|
||||||
$(SOCKET_SO): $(SOCKET_OBJS)
|
$(SOCKET_SO): $(SOCKET_OBJS)
|
||||||
$(LD) $(LDFLAGS) -o $@ $(SOCKET_OBJS)
|
$(LD) $(SOCKET_OBJS) $(LDFLAGS)$@
|
||||||
|
|
||||||
$(MIME_SO): $(MIME_OBJS)
|
$(MIME_SO): $(MIME_OBJS)
|
||||||
$(LD) $(LDFLAGS) -o $@ $(MIME_OBJS)
|
$(LD) $(MIME_OBJS) $(LDFLAGS)$@
|
||||||
|
|
||||||
$(UNIX_SO): $(UNIX_OBJS)
|
$(UNIX_SO): $(UNIX_OBJS)
|
||||||
$(LD) $(LDFLAGS) -o $@ $(UNIX_OBJS)
|
$(LD) $(UNIX_OBJS) $(LDFLAGS)$@
|
||||||
|
|
||||||
install:
|
install:
|
||||||
mkdir -p $(INSTALL_TOP_SHARE)
|
mkdir -p $(INSTALL_TOP_SHARE)
|
||||||
@ -139,9 +190,9 @@ install:
|
|||||||
mkdir -p $(INSTALL_SOCKET_SHARE)
|
mkdir -p $(INSTALL_SOCKET_SHARE)
|
||||||
$(INSTALL_DATA) $(TO_SOCKET_SHARE) $(INSTALL_SOCKET_SHARE)
|
$(INSTALL_DATA) $(TO_SOCKET_SHARE) $(INSTALL_SOCKET_SHARE)
|
||||||
mkdir -p $(INSTALL_SOCKET_LIB)
|
mkdir -p $(INSTALL_SOCKET_LIB)
|
||||||
$(INSTALL_EXEC) $(SOCKET_SO) $(INSTALL_SOCKET_LIB)/core.$(EXT)
|
$(INSTALL_EXEC) $(SOCKET_SO) $(INSTALL_SOCKET_LIB)/core.$(SO)
|
||||||
mkdir -p $(INSTALL_MIME_LIB)
|
mkdir -p $(INSTALL_MIME_LIB)
|
||||||
$(INSTALL_EXEC) $(MIME_SO) $(INSTALL_MIME_LIB)/core.$(EXT)
|
$(INSTALL_EXEC) $(MIME_SO) $(INSTALL_MIME_LIB)/core.$(SO)
|
||||||
|
|
||||||
local:
|
local:
|
||||||
$(MAKE) install INSTALL_TOP_LIB=.. INSTALL_TOP_SHARE=..
|
$(MAKE) install INSTALL_TOP_LIB=.. INSTALL_TOP_SHARE=..
|
||||||
@ -155,24 +206,24 @@ clean:
|
|||||||
#------
|
#------
|
||||||
# List of dependencies
|
# List of dependencies
|
||||||
#
|
#
|
||||||
auxiliar.o: auxiliar.c auxiliar.h
|
auxiliar.$(O): auxiliar.c auxiliar.h
|
||||||
buffer.o: buffer.c buffer.h io.h timeout.h
|
buffer.$(O): buffer.c buffer.h io.h timeout.h
|
||||||
except.o: except.c except.h
|
except.$(O): except.c except.h
|
||||||
inet.o: inet.c inet.h socket.h io.h timeout.h usocket.h
|
inet.$(O): inet.c inet.h socket.h io.h timeout.h usocket.h
|
||||||
io.o: io.c io.h timeout.h
|
io.$(O): io.c io.h timeout.h
|
||||||
luasocket.o: luasocket.c luasocket.h auxiliar.h except.h \
|
luasocket.$(O): luasocket.c luasocket.h auxiliar.h except.h \
|
||||||
timeout.h buffer.h io.h inet.h socket.h usocket.h tcp.h \
|
timeout.h buffer.h io.h inet.h socket.h usocket.h tcp.h \
|
||||||
udp.h select.h
|
udp.h select.h
|
||||||
mime.o: mime.c mime.h
|
mime.$(O): mime.c mime.h
|
||||||
options.o: options.c auxiliar.h options.h socket.h io.h \
|
options.$(O): options.c auxiliar.h options.h socket.h io.h \
|
||||||
timeout.h usocket.h inet.h
|
timeout.h usocket.h inet.h
|
||||||
select.o: select.c socket.h io.h timeout.h usocket.h select.h
|
select.$(O): select.c socket.h io.h timeout.h usocket.h select.h
|
||||||
tcp.o: tcp.c auxiliar.h socket.h io.h timeout.h usocket.h \
|
tcp.$(O): tcp.c auxiliar.h socket.h io.h timeout.h usocket.h \
|
||||||
inet.h options.h tcp.h buffer.h
|
inet.h options.h tcp.h buffer.h
|
||||||
timeout.o: timeout.c auxiliar.h timeout.h
|
timeout.$(O): timeout.c auxiliar.h timeout.h
|
||||||
udp.o: udp.c auxiliar.h socket.h io.h timeout.h usocket.h \
|
udp.$(O): udp.c auxiliar.h socket.h io.h timeout.h usocket.h \
|
||||||
inet.h options.h udp.h
|
inet.h options.h udp.h
|
||||||
unix.o: unix.c auxiliar.h socket.h io.h timeout.h usocket.h \
|
unix.$(O): unix.c auxiliar.h socket.h io.h timeout.h usocket.h \
|
||||||
options.h unix.h buffer.h
|
options.h unix.h buffer.h
|
||||||
usocket.o: usocket.c socket.h io.h timeout.h usocket.h
|
usocket.$(O): usocket.c socket.h io.h timeout.h usocket.h
|
||||||
wsocket.o: wsocket.c socket.h io.h timeout.h usocket.h
|
wsocket.$(O): wsocket.c socket.h io.h timeout.h usocket.h
|
||||||
|
40
src/mbox.lua
40
src/mbox.lua
@ -5,10 +5,10 @@ mbox = Public
|
|||||||
function Public.split_message(message_s)
|
function Public.split_message(message_s)
|
||||||
local message = {}
|
local message = {}
|
||||||
message_s = string.gsub(message_s, "\r\n", "\n")
|
message_s = string.gsub(message_s, "\r\n", "\n")
|
||||||
string.gsub(message_s, "^(.-\n)\n", function (h) message.headers = h end)
|
string.gsub(message_s, "^(.-\n)\n", function (h) message.headers = h end)
|
||||||
string.gsub(message_s, "^.-\n\n(.*)", function (b) message.body = b end)
|
string.gsub(message_s, "^.-\n\n(.*)", function (b) message.body = b end)
|
||||||
if not message.body then
|
if not message.body then
|
||||||
string.gsub(message_s, "^\n(.*)", function (b) message.body = b end)
|
string.gsub(message_s, "^\n(.*)", function (b) message.body = b end)
|
||||||
end
|
end
|
||||||
if not message.headers and not message.body then
|
if not message.headers and not message.body then
|
||||||
message.headers = message_s
|
message.headers = message_s
|
||||||
@ -54,30 +54,30 @@ function Public.parse_from(from)
|
|||||||
name = name or ""
|
name = name or ""
|
||||||
address = address or ""
|
address = address or ""
|
||||||
if name == "" then name = address end
|
if name == "" then name = address end
|
||||||
name = string.gsub(name, '"', "")
|
name = string.gsub(name, '"', "")
|
||||||
return name, address
|
return name, address
|
||||||
end
|
end
|
||||||
|
|
||||||
function Public.split_mbox(mbox_s)
|
function Public.split_mbox(mbox_s)
|
||||||
mbox = {}
|
mbox = {}
|
||||||
mbox_s = string.gsub(mbox_s, "\r\n", "\n") .."\n\nFrom \n"
|
mbox_s = string.gsub(mbox_s, "\r\n", "\n") .."\n\nFrom \n"
|
||||||
local nj, i, j = 1, 1, 1
|
local nj, i, j = 1, 1, 1
|
||||||
while 1 do
|
while 1 do
|
||||||
i, nj = string.find(mbox_s, "\n\nFrom .-\n", j)
|
i, nj = string.find(mbox_s, "\n\nFrom .-\n", j)
|
||||||
if not i then break end
|
if not i then break end
|
||||||
local message = string.sub(mbox_s, j, i-1)
|
local message = string.sub(mbox_s, j, i-1)
|
||||||
table.insert(mbox, message)
|
table.insert(mbox, message)
|
||||||
j = nj+1
|
j = nj+1
|
||||||
end
|
end
|
||||||
return mbox
|
return mbox
|
||||||
end
|
end
|
||||||
|
|
||||||
function Public.parse(mbox_s)
|
function Public.parse(mbox_s)
|
||||||
local mbox = Public.split_mbox(mbox_s)
|
local mbox = Public.split_mbox(mbox_s)
|
||||||
for i = 1, table.getn(mbox) do
|
for i = 1, table.getn(mbox) do
|
||||||
mbox[i] = Public.parse_message(mbox[i])
|
mbox[i] = Public.parse_message(mbox[i])
|
||||||
end
|
end
|
||||||
return mbox
|
return mbox
|
||||||
end
|
end
|
||||||
|
|
||||||
function Public.parse_message(message_s)
|
function Public.parse_message(message_s)
|
||||||
|
@ -106,7 +106,7 @@ end
|
|||||||
-- closes the underlying c
|
-- closes the underlying c
|
||||||
function metat.__index:close()
|
function metat.__index:close()
|
||||||
self.c:close()
|
self.c:close()
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- connect with server and return c object
|
-- connect with server and return c object
|
||||||
|
122
src/url.lua
122
src/url.lua
@ -40,25 +40,25 @@ end
|
|||||||
-- escaped representation of string binary
|
-- escaped representation of string binary
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
local function make_set(t)
|
local function make_set(t)
|
||||||
local s = {}
|
local s = {}
|
||||||
for i,v in base.ipairs(t) do
|
for i,v in base.ipairs(t) do
|
||||||
s[t[i]] = 1
|
s[t[i]] = 1
|
||||||
end
|
end
|
||||||
return s
|
return s
|
||||||
end
|
end
|
||||||
|
|
||||||
-- these are allowed withing a path segment, along with alphanum
|
-- these are allowed withing a path segment, along with alphanum
|
||||||
-- other characters must be escaped
|
-- other characters must be escaped
|
||||||
local segment_set = make_set {
|
local segment_set = make_set {
|
||||||
"-", "_", ".", "!", "~", "*", "'", "(",
|
"-", "_", ".", "!", "~", "*", "'", "(",
|
||||||
")", ":", "@", "&", "=", "+", "$", ",",
|
")", ":", "@", "&", "=", "+", "$", ",",
|
||||||
}
|
}
|
||||||
|
|
||||||
local function protect_segment(s)
|
local function protect_segment(s)
|
||||||
return string.gsub(s, "([^A-Za-z0-9_])", function (c)
|
return string.gsub(s, "([^A-Za-z0-9_])", function (c)
|
||||||
if segment_set[c] then return c
|
if segment_set[c] then return c
|
||||||
else return string.format("%%%02x", string.byte(c)) end
|
else return string.format("%%%02x", string.byte(c)) end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
@ -182,20 +182,26 @@ function build(parsed)
|
|||||||
local url = build_path(ppath)
|
local url = build_path(ppath)
|
||||||
if parsed.params then url = url .. ";" .. parsed.params end
|
if parsed.params then url = url .. ";" .. parsed.params end
|
||||||
if parsed.query then url = url .. "?" .. parsed.query end
|
if parsed.query then url = url .. "?" .. parsed.query end
|
||||||
local authority = parsed.authority
|
local authority = parsed.authority
|
||||||
if parsed.host then
|
if parsed.host then
|
||||||
authority = parsed.host
|
authority = parsed.host
|
||||||
if parsed.port then authority = authority .. ":" .. parsed.port end
|
if parsed.port then authority = authority .. ":" .. parsed.port end
|
||||||
local userinfo = parsed.userinfo
|
local userinfo = parsed.userinfo
|
||||||
if parsed.user then
|
if parsed.user then
|
||||||
userinfo = parsed.user
|
userinfo = parsed.user
|
||||||
if parsed.password then
|
if parsed.password then
|
||||||
userinfo = userinfo .. ":" .. parsed.password
|
userinfo = userinfo .. ":" .. parsed.password
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if userinfo then authority = userinfo .. "@" .. authority end
|
if userinfo then authority = userinfo .. "@" .. authority end
|
||||||
end
|
end
|
||||||
if authority then url = "//" .. authority .. url end
|
if authority then
|
||||||
|
if string.sub(url, 1, 1) == "/" then
|
||||||
|
url = "//" .. authority .. url
|
||||||
|
else
|
||||||
|
url = "//" .. authority .. "/" .. url
|
||||||
|
end
|
||||||
|
end
|
||||||
if parsed.scheme then url = parsed.scheme .. ":" .. url end
|
if parsed.scheme then url = parsed.scheme .. ":" .. url end
|
||||||
if parsed.fragment then url = url .. "#" .. parsed.fragment end
|
if parsed.fragment then url = url .. "#" .. parsed.fragment end
|
||||||
-- url = string.gsub(url, "%s", "")
|
-- url = string.gsub(url, "%s", "")
|
||||||
@ -211,8 +217,8 @@ end
|
|||||||
-- corresponding absolute url
|
-- corresponding absolute url
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
function absolute(base_url, relative_url)
|
function absolute(base_url, relative_url)
|
||||||
|
local base_parsed = base_url
|
||||||
if base.type(base_url) == "table" then
|
if base.type(base_url) == "table" then
|
||||||
base_parsed = base_url
|
|
||||||
base_url = build(base_parsed)
|
base_url = build(base_parsed)
|
||||||
else
|
else
|
||||||
base_parsed = parse(base_url)
|
base_parsed = parse(base_url)
|
||||||
@ -250,16 +256,16 @@ end
|
|||||||
-- segment: a table with one entry per segment
|
-- segment: a table with one entry per segment
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
function parse_path(path)
|
function parse_path(path)
|
||||||
local parsed = {}
|
local parsed = {}
|
||||||
path = path or ""
|
path = path or ""
|
||||||
--path = string.gsub(path, "%s", "")
|
--path = string.gsub(path, "%s", "")
|
||||||
string.gsub(path, "([^/]+)", function (s) table.insert(parsed, s) end)
|
string.gsub(path, "([^/]+)", function (s) table.insert(parsed, s) end)
|
||||||
for i = 1, table.getn(parsed) do
|
for i = 1, table.getn(parsed) do
|
||||||
parsed[i] = unescape(parsed[i])
|
parsed[i] = unescape(parsed[i])
|
||||||
end
|
end
|
||||||
if string.sub(path, 1, 1) == "/" then parsed.is_absolute = 1 end
|
if string.sub(path, 1, 1) == "/" then parsed.is_absolute = 1 end
|
||||||
if string.sub(path, -1, -1) == "/" then parsed.is_directory = 1 end
|
if string.sub(path, -1, -1) == "/" then parsed.is_directory = 1 end
|
||||||
return parsed
|
return parsed
|
||||||
end
|
end
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
@ -271,27 +277,27 @@ end
|
|||||||
-- path: corresponding path stringing
|
-- path: corresponding path stringing
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
function build_path(parsed, unsafe)
|
function build_path(parsed, unsafe)
|
||||||
local path = ""
|
local path = ""
|
||||||
local n = table.getn(parsed)
|
local n = table.getn(parsed)
|
||||||
if unsafe then
|
if unsafe then
|
||||||
for i = 1, n-1 do
|
for i = 1, n-1 do
|
||||||
path = path .. parsed[i]
|
path = path .. parsed[i]
|
||||||
path = path .. "/"
|
path = path .. "/"
|
||||||
end
|
end
|
||||||
if n > 0 then
|
if n > 0 then
|
||||||
path = path .. parsed[n]
|
path = path .. parsed[n]
|
||||||
if parsed.is_directory then path = path .. "/" end
|
if parsed.is_directory then path = path .. "/" end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
for i = 1, n-1 do
|
for i = 1, n-1 do
|
||||||
path = path .. protect_segment(parsed[i])
|
path = path .. protect_segment(parsed[i])
|
||||||
path = path .. "/"
|
path = path .. "/"
|
||||||
end
|
end
|
||||||
if n > 0 then
|
if n > 0 then
|
||||||
path = path .. protect_segment(parsed[n])
|
path = path .. protect_segment(parsed[n])
|
||||||
if parsed.is_directory then path = path .. "/" end
|
if parsed.is_directory then path = path .. "/" end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if parsed.is_absolute then path = "/" .. path end
|
if parsed.is_absolute then path = "/" .. path end
|
||||||
return path
|
return path
|
||||||
end
|
end
|
||||||
|
@ -30,9 +30,9 @@ int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
|
|||||||
pfd.revents = 0;
|
pfd.revents = 0;
|
||||||
if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */
|
if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */
|
||||||
do {
|
do {
|
||||||
int t = (int)(timeout_getretry(tm)*1e3);
|
int t = (int)(timeout_getretry(tm)*1e3);
|
||||||
ret = poll(&pfd, 1, t >= 0? t: -1);
|
ret = poll(&pfd, 1, t >= 0? t: -1);
|
||||||
} while (ret == -1 && errno == EINTR);
|
} while (ret == -1 && errno == EINTR);
|
||||||
if (ret == -1) return errno;
|
if (ret == -1) return errno;
|
||||||
if (ret == 0) return IO_TIMEOUT;
|
if (ret == 0) return IO_TIMEOUT;
|
||||||
if (sw == WAITFD_C && (pfd.revents & (POLLIN|POLLERR))) return IO_CLOSED;
|
if (sw == WAITFD_C && (pfd.revents & (POLLIN|POLLERR))) return IO_CLOSED;
|
||||||
|
@ -54,7 +54,7 @@ int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
|
|||||||
if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */
|
if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */
|
||||||
if (sw & WAITFD_R) {
|
if (sw & WAITFD_R) {
|
||||||
FD_ZERO(&rfds);
|
FD_ZERO(&rfds);
|
||||||
FD_SET(*ps, &rfds);
|
FD_SET(*ps, &rfds);
|
||||||
rp = &rfds;
|
rp = &rfds;
|
||||||
}
|
}
|
||||||
if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; }
|
if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; }
|
||||||
@ -207,7 +207,7 @@ int socket_send(p_socket ps, const char *data, size_t count,
|
|||||||
/* loop until we send something or we give up on error */
|
/* loop until we send something or we give up on error */
|
||||||
for ( ;; ) {
|
for ( ;; ) {
|
||||||
/* try to send something */
|
/* try to send something */
|
||||||
int put = send(*ps, data, (int) count, 0);
|
int put = send(*ps, data, (int) count, 0);
|
||||||
/* if we sent something, we are done */
|
/* if we sent something, we are done */
|
||||||
if (put > 0) {
|
if (put > 0) {
|
||||||
*sent = put;
|
*sent = put;
|
||||||
@ -346,8 +346,8 @@ const char *socket_strerror(int err) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char *socket_ioerror(p_socket ps, int err) {
|
const char *socket_ioerror(p_socket ps, int err) {
|
||||||
(void) ps;
|
(void) ps;
|
||||||
return socket_strerror(err);
|
return socket_strerror(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *wstrerror(int err) {
|
static const char *wstrerror(int err) {
|
||||||
|
@ -82,10 +82,10 @@ print("ok")
|
|||||||
io.write("testing parameter overriding: ")
|
io.write("testing parameter overriding: ")
|
||||||
local back = {}
|
local back = {}
|
||||||
ret, err = ftp.get{
|
ret, err = ftp.get{
|
||||||
url = "//stupid:mistake@" .. host .. "/index.html",
|
url = "//stupid:mistake@" .. host .. "/index.html",
|
||||||
user = "luasocket",
|
user = "luasocket",
|
||||||
password = "pedrovian",
|
password = "pedrovian",
|
||||||
type = "i",
|
type = "i",
|
||||||
sink = ltn12.sink.table(back)
|
sink = ltn12.sink.table(back)
|
||||||
}
|
}
|
||||||
assert(ret and not err and table.concat(back) == index, err)
|
assert(ret and not err and table.concat(back) == index, err)
|
||||||
|
@ -34,28 +34,28 @@ index_file = "index.html"
|
|||||||
index = readfile(index_file)
|
index = readfile(index_file)
|
||||||
|
|
||||||
local check_result = function(response, expect, ignore)
|
local check_result = function(response, expect, ignore)
|
||||||
for i,v in pairs(response) do
|
for i,v in pairs(response) do
|
||||||
if not ignore[i] then
|
if not ignore[i] then
|
||||||
if v ~= expect[i] then
|
if v ~= expect[i] then
|
||||||
local f = io.open("err", "w")
|
local f = io.open("err", "w")
|
||||||
f:write(tostring(v), "\n\n versus\n\n", tostring(expect[i]))
|
f:write(tostring(v), "\n\n versus\n\n", tostring(expect[i]))
|
||||||
f:close()
|
f:close()
|
||||||
fail(i .. " differs!")
|
fail(i .. " differs!")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
for i,v in pairs(expect) do
|
for i,v in pairs(expect) do
|
||||||
if not ignore[i] then
|
if not ignore[i] then
|
||||||
if v ~= response[i] then
|
if v ~= response[i] then
|
||||||
local f = io.open("err", "w")
|
local f = io.open("err", "w")
|
||||||
f:write(tostring(response[i]), "\n\n versus\n\n", tostring(v))
|
f:write(tostring(response[i]), "\n\n versus\n\n", tostring(v))
|
||||||
v = string.sub(type(v) == "string" and v or "", 1, 70)
|
v = string.sub(type(v) == "string" and v or "", 1, 70)
|
||||||
f:close()
|
f:close()
|
||||||
fail(i .. " differs!")
|
fail(i .. " differs!")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
print("ok")
|
print("ok")
|
||||||
end
|
end
|
||||||
|
|
||||||
local check_request = function(request, expect, ignore)
|
local check_request = function(request, expect, ignore)
|
||||||
@ -63,7 +63,7 @@ local check_request = function(request, expect, ignore)
|
|||||||
if not request.sink then request.sink, t = ltn12.sink.table() end
|
if not request.sink then request.sink, t = ltn12.sink.table() end
|
||||||
request.source = request.source or
|
request.source = request.source or
|
||||||
(request.body and ltn12.source.string(request.body))
|
(request.body and ltn12.source.string(request.body))
|
||||||
local response = {}
|
local response = {}
|
||||||
response.code, response.headers, response.status =
|
response.code, response.headers, response.status =
|
||||||
socket.skip(1, http.request(request))
|
socket.skip(1, http.request(request))
|
||||||
if t and table.getn(t) > 0 then response.body = table.concat(t) end
|
if t and table.getn(t) > 0 then response.body = table.concat(t) end
|
||||||
@ -90,15 +90,15 @@ else fail("failed!") end
|
|||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
io.write("testing document retrieval: ")
|
io.write("testing document retrieval: ")
|
||||||
request = {
|
request = {
|
||||||
url = "http://" .. host .. prefix .. "/index.html"
|
url = "http://" .. host .. prefix .. "/index.html"
|
||||||
}
|
}
|
||||||
expect = {
|
expect = {
|
||||||
body = index,
|
body = index,
|
||||||
code = 200
|
code = 200
|
||||||
}
|
}
|
||||||
ignore = {
|
ignore = {
|
||||||
status = 1,
|
status = 1,
|
||||||
headers = 1
|
headers = 1
|
||||||
}
|
}
|
||||||
check_request(request, expect, ignore)
|
check_request(request, expect, ignore)
|
||||||
|
|
||||||
@ -111,9 +111,9 @@ expect = {
|
|||||||
code = 302
|
code = 302
|
||||||
}
|
}
|
||||||
ignore = {
|
ignore = {
|
||||||
status = 1,
|
status = 1,
|
||||||
headers = 1,
|
headers = 1,
|
||||||
body = 1
|
body = 1
|
||||||
}
|
}
|
||||||
check_request(request, expect, ignore)
|
check_request(request, expect, ignore)
|
||||||
|
|
||||||
@ -144,19 +144,19 @@ check_request(request, expect, ignore)
|
|||||||
io.write("testing post method: ")
|
io.write("testing post method: ")
|
||||||
-- wanted to test chunked post, but apache doesn't support it...
|
-- wanted to test chunked post, but apache doesn't support it...
|
||||||
request = {
|
request = {
|
||||||
url = "http://" .. host .. cgiprefix .. "/cat",
|
url = "http://" .. host .. cgiprefix .. "/cat",
|
||||||
method = "POST",
|
method = "POST",
|
||||||
body = index,
|
body = index,
|
||||||
-- remove content-length header to send chunked body
|
-- remove content-length header to send chunked body
|
||||||
headers = { ["content-length"] = string.len(index) }
|
headers = { ["content-length"] = string.len(index) }
|
||||||
}
|
}
|
||||||
expect = {
|
expect = {
|
||||||
body = index,
|
body = index,
|
||||||
code = 200
|
code = 200
|
||||||
}
|
}
|
||||||
ignore = {
|
ignore = {
|
||||||
status = 1,
|
status = 1,
|
||||||
headers = 1
|
headers = 1
|
||||||
}
|
}
|
||||||
check_request(request, expect, ignore)
|
check_request(request, expect, ignore)
|
||||||
|
|
||||||
@ -164,19 +164,19 @@ check_request(request, expect, ignore)
|
|||||||
--[[
|
--[[
|
||||||
io.write("testing proxy with post method: ")
|
io.write("testing proxy with post method: ")
|
||||||
request = {
|
request = {
|
||||||
url = "http://" .. host .. cgiprefix .. "/cat",
|
url = "http://" .. host .. cgiprefix .. "/cat",
|
||||||
method = "POST",
|
method = "POST",
|
||||||
body = index,
|
body = index,
|
||||||
headers = { ["content-length"] = string.len(index) },
|
headers = { ["content-length"] = string.len(index) },
|
||||||
proxy= proxy
|
proxy= proxy
|
||||||
}
|
}
|
||||||
expect = {
|
expect = {
|
||||||
body = index,
|
body = index,
|
||||||
code = 200
|
code = 200
|
||||||
}
|
}
|
||||||
ignore = {
|
ignore = {
|
||||||
status = 1,
|
status = 1,
|
||||||
headers = 1
|
headers = 1
|
||||||
}
|
}
|
||||||
check_request(request, expect, ignore)
|
check_request(request, expect, ignore)
|
||||||
]]
|
]]
|
||||||
@ -190,18 +190,18 @@ print("ok")
|
|||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
io.write("testing ltn12.(sink|source).file: ")
|
io.write("testing ltn12.(sink|source).file: ")
|
||||||
request = {
|
request = {
|
||||||
url = "http://" .. host .. cgiprefix .. "/cat",
|
url = "http://" .. host .. cgiprefix .. "/cat",
|
||||||
method = "POST",
|
method = "POST",
|
||||||
source = ltn12.source.file(io.open(index_file, "rb")),
|
source = ltn12.source.file(io.open(index_file, "rb")),
|
||||||
sink = ltn12.sink.file(io.open(index_file .. "-back", "wb")),
|
sink = ltn12.sink.file(io.open(index_file .. "-back", "wb")),
|
||||||
headers = { ["content-length"] = string.len(index) }
|
headers = { ["content-length"] = string.len(index) }
|
||||||
}
|
}
|
||||||
expect = {
|
expect = {
|
||||||
code = 200
|
code = 200
|
||||||
}
|
}
|
||||||
ignore = {
|
ignore = {
|
||||||
status = 1,
|
status = 1,
|
||||||
headers = 1
|
headers = 1
|
||||||
}
|
}
|
||||||
check_request(request, expect, ignore)
|
check_request(request, expect, ignore)
|
||||||
back = readfile(index_file .. "-back")
|
back = readfile(index_file .. "-back")
|
||||||
@ -231,19 +231,19 @@ local sink = ltn12.sink.chain(
|
|||||||
)
|
)
|
||||||
|
|
||||||
request = {
|
request = {
|
||||||
url = "http://" .. host .. cgiprefix .. "/cat",
|
url = "http://" .. host .. cgiprefix .. "/cat",
|
||||||
method = "POST",
|
method = "POST",
|
||||||
source = source,
|
source = source,
|
||||||
sink = sink,
|
sink = sink,
|
||||||
headers = { ["content-length"] = b64length(string.len(index)) }
|
headers = { ["content-length"] = b64length(string.len(index)) }
|
||||||
}
|
}
|
||||||
expect = {
|
expect = {
|
||||||
code = 200
|
code = 200
|
||||||
}
|
}
|
||||||
ignore = {
|
ignore = {
|
||||||
body_cb = 1,
|
body_cb = 1,
|
||||||
status = 1,
|
status = 1,
|
||||||
headers = 1
|
headers = 1
|
||||||
}
|
}
|
||||||
check_request(request, expect, ignore)
|
check_request(request, expect, ignore)
|
||||||
back = readfile(index_file .. "-back")
|
back = readfile(index_file .. "-back")
|
||||||
@ -253,15 +253,15 @@ os.remove(index_file .. "-back")
|
|||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
io.write("testing http redirection: ")
|
io.write("testing http redirection: ")
|
||||||
request = {
|
request = {
|
||||||
url = "http://" .. host .. prefix
|
url = "http://" .. host .. prefix
|
||||||
}
|
}
|
||||||
expect = {
|
expect = {
|
||||||
body = index,
|
body = index,
|
||||||
code = 200
|
code = 200
|
||||||
}
|
}
|
||||||
ignore = {
|
ignore = {
|
||||||
status = 1,
|
status = 1,
|
||||||
headers = 1
|
headers = 1
|
||||||
}
|
}
|
||||||
check_request(request, expect, ignore)
|
check_request(request, expect, ignore)
|
||||||
|
|
||||||
@ -269,16 +269,16 @@ check_request(request, expect, ignore)
|
|||||||
--[[
|
--[[
|
||||||
io.write("testing proxy with redirection: ")
|
io.write("testing proxy with redirection: ")
|
||||||
request = {
|
request = {
|
||||||
url = "http://" .. host .. prefix,
|
url = "http://" .. host .. prefix,
|
||||||
proxy = proxy
|
proxy = proxy
|
||||||
}
|
}
|
||||||
expect = {
|
expect = {
|
||||||
body = index,
|
body = index,
|
||||||
code = 200
|
code = 200
|
||||||
}
|
}
|
||||||
ignore = {
|
ignore = {
|
||||||
status = 1,
|
status = 1,
|
||||||
headers = 1
|
headers = 1
|
||||||
}
|
}
|
||||||
check_request(request, expect, ignore)
|
check_request(request, expect, ignore)
|
||||||
]]
|
]]
|
||||||
@ -293,104 +293,104 @@ expect = {
|
|||||||
}
|
}
|
||||||
ignore = {
|
ignore = {
|
||||||
body = 1,
|
body = 1,
|
||||||
status = 1,
|
status = 1,
|
||||||
headers = 1
|
headers = 1
|
||||||
}
|
}
|
||||||
check_request(request, expect, ignore)
|
check_request(request, expect, ignore)
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
io.write("testing http redirection failure: ")
|
io.write("testing http redirection failure: ")
|
||||||
request = {
|
request = {
|
||||||
url = "http://" .. host .. prefix,
|
url = "http://" .. host .. prefix,
|
||||||
redirect = false
|
redirect = false
|
||||||
}
|
}
|
||||||
expect = {
|
expect = {
|
||||||
code = 301
|
code = 301
|
||||||
}
|
}
|
||||||
ignore = {
|
ignore = {
|
||||||
body = 1,
|
body = 1,
|
||||||
status = 1,
|
status = 1,
|
||||||
headers = 1
|
headers = 1
|
||||||
}
|
}
|
||||||
check_request(request, expect, ignore)
|
check_request(request, expect, ignore)
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
io.write("testing document not found: ")
|
io.write("testing document not found: ")
|
||||||
request = {
|
request = {
|
||||||
url = "http://" .. host .. "/wrongdocument.html"
|
url = "http://" .. host .. "/wrongdocument.html"
|
||||||
}
|
}
|
||||||
expect = {
|
expect = {
|
||||||
code = 404
|
code = 404
|
||||||
}
|
}
|
||||||
ignore = {
|
ignore = {
|
||||||
body = 1,
|
body = 1,
|
||||||
status = 1,
|
status = 1,
|
||||||
headers = 1
|
headers = 1
|
||||||
}
|
}
|
||||||
check_request(request, expect, ignore)
|
check_request(request, expect, ignore)
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
io.write("testing auth failure: ")
|
io.write("testing auth failure: ")
|
||||||
request = {
|
request = {
|
||||||
url = "http://" .. host .. prefix .. "/auth/index.html"
|
url = "http://" .. host .. prefix .. "/auth/index.html"
|
||||||
}
|
}
|
||||||
expect = {
|
expect = {
|
||||||
code = 401
|
code = 401
|
||||||
}
|
}
|
||||||
ignore = {
|
ignore = {
|
||||||
body = 1,
|
body = 1,
|
||||||
status = 1,
|
status = 1,
|
||||||
headers = 1
|
headers = 1
|
||||||
}
|
}
|
||||||
check_request(request, expect, ignore)
|
check_request(request, expect, ignore)
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
io.write("testing manual basic auth: ")
|
io.write("testing manual basic auth: ")
|
||||||
request = {
|
request = {
|
||||||
url = "http://" .. host .. prefix .. "/auth/index.html",
|
url = "http://" .. host .. prefix .. "/auth/index.html",
|
||||||
headers = {
|
headers = {
|
||||||
authorization = "Basic " .. (mime.b64("luasocket:password"))
|
authorization = "Basic " .. (mime.b64("luasocket:password"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect = {
|
expect = {
|
||||||
code = 200,
|
code = 200,
|
||||||
body = index
|
body = index
|
||||||
}
|
}
|
||||||
ignore = {
|
ignore = {
|
||||||
status = 1,
|
status = 1,
|
||||||
headers = 1
|
headers = 1
|
||||||
}
|
}
|
||||||
check_request(request, expect, ignore)
|
check_request(request, expect, ignore)
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
io.write("testing automatic basic auth: ")
|
io.write("testing automatic basic auth: ")
|
||||||
request = {
|
request = {
|
||||||
url = "http://luasocket:password@" .. host .. prefix .. "/auth/index.html"
|
url = "http://luasocket:password@" .. host .. prefix .. "/auth/index.html"
|
||||||
}
|
}
|
||||||
expect = {
|
expect = {
|
||||||
code = 200,
|
code = 200,
|
||||||
body = index
|
body = index
|
||||||
}
|
}
|
||||||
ignore = {
|
ignore = {
|
||||||
status = 1,
|
status = 1,
|
||||||
headers = 1
|
headers = 1
|
||||||
}
|
}
|
||||||
check_request(request, expect, ignore)
|
check_request(request, expect, ignore)
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
io.write("testing auth info overriding: ")
|
io.write("testing auth info overriding: ")
|
||||||
request = {
|
request = {
|
||||||
url = "http://really:wrong@" .. host .. prefix .. "/auth/index.html",
|
url = "http://really:wrong@" .. host .. prefix .. "/auth/index.html",
|
||||||
user = "luasocket",
|
user = "luasocket",
|
||||||
password = "password"
|
password = "password"
|
||||||
}
|
}
|
||||||
expect = {
|
expect = {
|
||||||
code = 200,
|
code = 200,
|
||||||
body = index
|
body = index
|
||||||
}
|
}
|
||||||
ignore = {
|
ignore = {
|
||||||
status = 1,
|
status = 1,
|
||||||
headers = 1
|
headers = 1
|
||||||
}
|
}
|
||||||
check_request(request, expect, ignore)
|
check_request(request, expect, ignore)
|
||||||
|
|
||||||
@ -400,12 +400,12 @@ request = {
|
|||||||
url = "http://" .. host .. cgiprefix .. "/cat-index-html"
|
url = "http://" .. host .. cgiprefix .. "/cat-index-html"
|
||||||
}
|
}
|
||||||
expect = {
|
expect = {
|
||||||
body = index,
|
body = index,
|
||||||
code = 200
|
code = 200
|
||||||
}
|
}
|
||||||
ignore = {
|
ignore = {
|
||||||
status = 1,
|
status = 1,
|
||||||
headers = 1
|
headers = 1
|
||||||
}
|
}
|
||||||
check_request(request, expect, ignore)
|
check_request(request, expect, ignore)
|
||||||
|
|
||||||
|
@ -19,11 +19,11 @@ local parse = mbox.parse
|
|||||||
dofile("testsupport.lua")
|
dofile("testsupport.lua")
|
||||||
|
|
||||||
local total = function()
|
local total = function()
|
||||||
local t = 0
|
local t = 0
|
||||||
for i = 1, table.getn(sent) do
|
for i = 1, table.getn(sent) do
|
||||||
t = t + sent[i].count
|
t = t + sent[i].count
|
||||||
end
|
end
|
||||||
return t
|
return t
|
||||||
end
|
end
|
||||||
|
|
||||||
local similar = function(s1, s2)
|
local similar = function(s1, s2)
|
||||||
@ -39,14 +39,14 @@ local fail = function(s)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local readfile = function(name)
|
local readfile = function(name)
|
||||||
local f = io.open(name, "r")
|
local f = io.open(name, "r")
|
||||||
if not f then
|
if not f then
|
||||||
fail("unable to open file!")
|
fail("unable to open file!")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
local s = f:read("*a")
|
local s = f:read("*a")
|
||||||
f:close()
|
f:close()
|
||||||
return s
|
return s
|
||||||
end
|
end
|
||||||
|
|
||||||
local empty = function()
|
local empty = function()
|
||||||
@ -62,7 +62,7 @@ end
|
|||||||
local get = function()
|
local get = function()
|
||||||
local s = ""
|
local s = ""
|
||||||
for i,v in ipairs(files) do
|
for i,v in ipairs(files) do
|
||||||
s = s .. "\n" .. readfile(v)
|
s = s .. "\n" .. readfile(v)
|
||||||
end
|
end
|
||||||
return s
|
return s
|
||||||
end
|
end
|
||||||
@ -82,40 +82,40 @@ local check_body = function(sent, got)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local check = function(sent, m)
|
local check = function(sent, m)
|
||||||
io.write("checking ", m.headers.title, ": ")
|
io.write("checking ", m.headers.title, ": ")
|
||||||
for i = 1, table.getn(sent) do
|
for i = 1, table.getn(sent) do
|
||||||
local s = sent[i]
|
local s = sent[i]
|
||||||
if s.title == m.headers.title and s.count > 0 then
|
if s.title == m.headers.title and s.count > 0 then
|
||||||
check_headers(s.headers, m.headers)
|
check_headers(s.headers, m.headers)
|
||||||
check_body(s.body, m.body)
|
check_body(s.body, m.body)
|
||||||
s.count = s.count - 1
|
s.count = s.count - 1
|
||||||
print("ok")
|
print("ok")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
fail("not found")
|
fail("not found")
|
||||||
end
|
end
|
||||||
|
|
||||||
local insert = function(sent, message)
|
local insert = function(sent, message)
|
||||||
if type(message.rcpt) == "table" then
|
if type(message.rcpt) == "table" then
|
||||||
message.count = table.getn(message.rcpt)
|
message.count = table.getn(message.rcpt)
|
||||||
else message.count = 1 end
|
else message.count = 1 end
|
||||||
message.headers = message.headers or {}
|
message.headers = message.headers or {}
|
||||||
message.headers.title = message.title
|
message.headers.title = message.title
|
||||||
table.insert(sent, message)
|
table.insert(sent, message)
|
||||||
end
|
end
|
||||||
|
|
||||||
local mark = function()
|
local mark = function()
|
||||||
local time = socket.time()
|
local time = socket.time()
|
||||||
return { time = time }
|
return { time = time }
|
||||||
end
|
end
|
||||||
|
|
||||||
local wait = function(sentinel, n)
|
local wait = function(sentinel, n)
|
||||||
local to
|
local to
|
||||||
io.write("waiting for ", n, " messages: ")
|
io.write("waiting for ", n, " messages: ")
|
||||||
while 1 do
|
while 1 do
|
||||||
local mbox = parse(get())
|
local mbox = parse(get())
|
||||||
if n == table.getn(mbox) then break end
|
if n == table.getn(mbox) then break end
|
||||||
if socket.time() - sentinel.time > 50 then
|
if socket.time() - sentinel.time > 50 then
|
||||||
to = 1
|
to = 1
|
||||||
break
|
break
|
||||||
@ -124,8 +124,8 @@ local wait = function(sentinel, n)
|
|||||||
io.write(".")
|
io.write(".")
|
||||||
io.stdout:flush()
|
io.stdout:flush()
|
||||||
end
|
end
|
||||||
if to then fail("timeout")
|
if to then fail("timeout")
|
||||||
else print("ok") end
|
else print("ok") end
|
||||||
end
|
end
|
||||||
|
|
||||||
local stuffed_body = [[
|
local stuffed_body = [[
|
||||||
@ -144,21 +144,21 @@ a lot of trouble.
|
|||||||
insert(sent, {
|
insert(sent, {
|
||||||
from = from,
|
from = from,
|
||||||
rcpt = {
|
rcpt = {
|
||||||
"luasocket@localhost",
|
"luasocket@localhost",
|
||||||
"luasock3@dell-diego.cs.princeton.edu",
|
"luasock3@dell-diego.cs.princeton.edu",
|
||||||
"luasock1@dell-diego.cs.princeton.edu"
|
"luasock1@dell-diego.cs.princeton.edu"
|
||||||
},
|
},
|
||||||
body = "multiple rcpt body",
|
body = "multiple rcpt body",
|
||||||
title = "multiple rcpt",
|
title = "multiple rcpt",
|
||||||
})
|
})
|
||||||
|
|
||||||
insert(sent, {
|
insert(sent, {
|
||||||
from = from,
|
from = from,
|
||||||
rcpt = {
|
rcpt = {
|
||||||
"luasock2@localhost",
|
"luasock2@localhost",
|
||||||
"luasock3",
|
"luasock3",
|
||||||
"luasock1"
|
"luasock1"
|
||||||
},
|
},
|
||||||
headers = {
|
headers = {
|
||||||
header1 = "header 1",
|
header1 = "header 1",
|
||||||
header2 = "header 2",
|
header2 = "header 2",
|
||||||
@ -210,24 +210,24 @@ insert(sent, {
|
|||||||
io.write("testing host not found: ")
|
io.write("testing host not found: ")
|
||||||
local c, e = socket.connect("wrong.host", 25)
|
local c, e = socket.connect("wrong.host", 25)
|
||||||
local ret, err = socket.smtp.mail{
|
local ret, err = socket.smtp.mail{
|
||||||
from = from,
|
from = from,
|
||||||
rcpt = rcpt,
|
rcpt = rcpt,
|
||||||
server = "wrong.host"
|
server = "wrong.host"
|
||||||
}
|
}
|
||||||
if ret or e ~= err then fail("wrong error message")
|
if ret or e ~= err then fail("wrong error message")
|
||||||
else print("ok") end
|
else print("ok") end
|
||||||
|
|
||||||
io.write("testing invalid from: ")
|
io.write("testing invalid from: ")
|
||||||
local ret, err = socket.smtp.mail{
|
local ret, err = socket.smtp.mail{
|
||||||
from = ' " " (( _ * ',
|
from = ' " " (( _ * ',
|
||||||
rcpt = rcpt,
|
rcpt = rcpt,
|
||||||
}
|
}
|
||||||
if ret or not err then fail("wrong error message")
|
if ret or not err then fail("wrong error message")
|
||||||
else print(err) end
|
else print(err) end
|
||||||
|
|
||||||
io.write("testing no rcpt: ")
|
io.write("testing no rcpt: ")
|
||||||
local ret, err = socket.smtp.mail{
|
local ret, err = socket.smtp.mail{
|
||||||
from = from,
|
from = from,
|
||||||
}
|
}
|
||||||
if ret or not err then fail("wrong error message")
|
if ret or not err then fail("wrong error message")
|
||||||
else print(err) end
|
else print(err) end
|
||||||
@ -252,7 +252,7 @@ local mbox = parse(get())
|
|||||||
print(table.getn(mbox) .. " messages found!")
|
print(table.getn(mbox) .. " messages found!")
|
||||||
|
|
||||||
for i = 1, table.getn(mbox) do
|
for i = 1, table.getn(mbox) do
|
||||||
check(sent, mbox[i])
|
check(sent, mbox[i])
|
||||||
end
|
end
|
||||||
|
|
||||||
print("passed all tests")
|
print("passed all tests")
|
||||||
|
@ -3,15 +3,20 @@ local socket = require"socket"
|
|||||||
host = host or "localhost"
|
host = host or "localhost"
|
||||||
port = port or "8383"
|
port = port or "8383"
|
||||||
|
|
||||||
function pass(...)
|
function printf(...)
|
||||||
local s = string.format(unpack(arg))
|
local s = string.format(unpack(arg))
|
||||||
io.stderr:write(s, "\n")
|
io.stderr:write(s)
|
||||||
|
end
|
||||||
|
|
||||||
|
function pass(...)
|
||||||
|
printf(...)
|
||||||
|
io.stderr:write("\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
function fail(...)
|
function fail(...)
|
||||||
local s = string.format(unpack(arg))
|
io.stderr:write("ERROR: ")
|
||||||
io.stderr:write("ERROR: ", s, "!\n")
|
printf(...)
|
||||||
socket.sleep(3)
|
io.stderr:write("!\n")
|
||||||
os.exit()
|
os.exit()
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -80,7 +85,6 @@ io.stderr:write("----------------------------------------------\n",
|
|||||||
start = socket.gettime()
|
start = socket.gettime()
|
||||||
|
|
||||||
function reconnect()
|
function reconnect()
|
||||||
io.stderr:write("attempting data connection... ")
|
|
||||||
if data then data:close() end
|
if data then data:close() end
|
||||||
remote [[
|
remote [[
|
||||||
if data then data:close() data = nil end
|
if data then data:close() data = nil end
|
||||||
@ -88,12 +92,11 @@ function reconnect()
|
|||||||
data:setoption("tcp-nodelay", true)
|
data:setoption("tcp-nodelay", true)
|
||||||
]]
|
]]
|
||||||
data, err = socket.connect(host, port)
|
data, err = socket.connect(host, port)
|
||||||
if not data then fail(err)
|
if not data then fail(err) end
|
||||||
else pass("connected!") end
|
|
||||||
data:setoption("tcp-nodelay", true)
|
data:setoption("tcp-nodelay", true)
|
||||||
end
|
end
|
||||||
|
|
||||||
pass("attempting control connection...")
|
printf("attempting control connection...")
|
||||||
control, err = socket.connect(host, port)
|
control, err = socket.connect(host, port)
|
||||||
if err then fail(err)
|
if err then fail(err)
|
||||||
else pass("connected!") end
|
else pass("connected!") end
|
||||||
@ -112,6 +115,7 @@ end
|
|||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
function test_mixed(len)
|
function test_mixed(len)
|
||||||
reconnect()
|
reconnect()
|
||||||
|
io.stderr:write("length " .. len .. ": ")
|
||||||
local inter = math.ceil(len/4)
|
local inter = math.ceil(len/4)
|
||||||
local p1 = "unix " .. string.rep("x", inter) .. "line\n"
|
local p1 = "unix " .. string.rep("x", inter) .. "line\n"
|
||||||
local p2 = "dos " .. string.rep("y", inter) .. "line\r\n"
|
local p2 = "dos " .. string.rep("y", inter) .. "line\r\n"
|
||||||
@ -139,6 +143,7 @@ end
|
|||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
function test_asciiline(len)
|
function test_asciiline(len)
|
||||||
reconnect()
|
reconnect()
|
||||||
|
io.stderr:write("length " .. len .. ": ")
|
||||||
local str, str10, back, err
|
local str, str10, back, err
|
||||||
str = string.rep("x", math.mod(len, 10))
|
str = string.rep("x", math.mod(len, 10))
|
||||||
str10 = string.rep("aZb.c#dAe?", math.floor(len/10))
|
str10 = string.rep("aZb.c#dAe?", math.floor(len/10))
|
||||||
@ -156,6 +161,7 @@ end
|
|||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
function test_rawline(len)
|
function test_rawline(len)
|
||||||
reconnect()
|
reconnect()
|
||||||
|
io.stderr:write("length " .. len .. ": ")
|
||||||
local str, str10, back, err
|
local str, str10, back, err
|
||||||
str = string.rep(string.char(47), math.mod(len, 10))
|
str = string.rep(string.char(47), math.mod(len, 10))
|
||||||
str10 = string.rep(string.char(120,21,77,4,5,0,7,36,44,100),
|
str10 = string.rep(string.char(120,21,77,4,5,0,7,36,44,100),
|
||||||
@ -174,6 +180,7 @@ end
|
|||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
function test_raw(len)
|
function test_raw(len)
|
||||||
reconnect()
|
reconnect()
|
||||||
|
io.stderr:write("length " .. len .. ": ")
|
||||||
local half = math.floor(len/2)
|
local half = math.floor(len/2)
|
||||||
local s1, s2, back, err
|
local s1, s2, back, err
|
||||||
s1 = string.rep("x", half)
|
s1 = string.rep("x", half)
|
||||||
@ -194,7 +201,7 @@ end
|
|||||||
function test_totaltimeoutreceive(len, tm, sl)
|
function test_totaltimeoutreceive(len, tm, sl)
|
||||||
reconnect()
|
reconnect()
|
||||||
local str, err, partial
|
local str, err, partial
|
||||||
pass("%d bytes, %ds total timeout, %ds pause", len, tm, sl)
|
printf("%d bytes, %ds total timeout, %ds pause: ", len, tm, sl)
|
||||||
remote (string.format ([[
|
remote (string.format ([[
|
||||||
data:settimeout(%d)
|
data:settimeout(%d)
|
||||||
str = string.rep('a', %d)
|
str = string.rep('a', %d)
|
||||||
@ -215,7 +222,7 @@ end
|
|||||||
function test_totaltimeoutsend(len, tm, sl)
|
function test_totaltimeoutsend(len, tm, sl)
|
||||||
reconnect()
|
reconnect()
|
||||||
local str, err, total
|
local str, err, total
|
||||||
pass("%d bytes, %ds total timeout, %ds pause", len, tm, sl)
|
printf("%d bytes, %ds total timeout, %ds pause: ", len, tm, sl)
|
||||||
remote (string.format ([[
|
remote (string.format ([[
|
||||||
data:settimeout(%d)
|
data:settimeout(%d)
|
||||||
str = data:receive(%d)
|
str = data:receive(%d)
|
||||||
@ -235,7 +242,7 @@ end
|
|||||||
function test_blockingtimeoutreceive(len, tm, sl)
|
function test_blockingtimeoutreceive(len, tm, sl)
|
||||||
reconnect()
|
reconnect()
|
||||||
local str, err, partial
|
local str, err, partial
|
||||||
pass("%d bytes, %ds blocking timeout, %ds pause", len, tm, sl)
|
printf("%d bytes, %ds blocking timeout, %ds pause: ", len, tm, sl)
|
||||||
remote (string.format ([[
|
remote (string.format ([[
|
||||||
data:settimeout(%d)
|
data:settimeout(%d)
|
||||||
str = string.rep('a', %d)
|
str = string.rep('a', %d)
|
||||||
@ -255,7 +262,7 @@ end
|
|||||||
function test_blockingtimeoutsend(len, tm, sl)
|
function test_blockingtimeoutsend(len, tm, sl)
|
||||||
reconnect()
|
reconnect()
|
||||||
local str, err, total
|
local str, err, total
|
||||||
pass("%d bytes, %ds blocking timeout, %ds pause", len, tm, sl)
|
printf("%d bytes, %ds blocking timeout, %ds pause: ", len, tm, sl)
|
||||||
remote (string.format ([[
|
remote (string.format ([[
|
||||||
data:settimeout(%d)
|
data:settimeout(%d)
|
||||||
str = data:receive(%d)
|
str = data:receive(%d)
|
||||||
@ -273,6 +280,7 @@ end
|
|||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
function empty_connect()
|
function empty_connect()
|
||||||
|
printf("empty connect: ")
|
||||||
reconnect()
|
reconnect()
|
||||||
if data then data:close() data = nil end
|
if data then data:close() data = nil end
|
||||||
remote [[
|
remote [[
|
||||||
@ -284,7 +292,7 @@ function empty_connect()
|
|||||||
pass("ok")
|
pass("ok")
|
||||||
data = socket.connect(host, port)
|
data = socket.connect(host, port)
|
||||||
else
|
else
|
||||||
pass("gethostbyname returns localhost on empty string...")
|
pass("gethostbyname returns localhost on empty string...")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -311,7 +319,7 @@ function test_closed()
|
|||||||
local back, partial, err
|
local back, partial, err
|
||||||
local str = 'little string'
|
local str = 'little string'
|
||||||
reconnect()
|
reconnect()
|
||||||
pass("trying read detection")
|
printf("trying read detection: ")
|
||||||
remote (string.format ([[
|
remote (string.format ([[
|
||||||
data:send('%s')
|
data:send('%s')
|
||||||
data:close()
|
data:close()
|
||||||
@ -324,7 +332,7 @@ function test_closed()
|
|||||||
elseif str ~= partial then fail("didn't receive partial result.")
|
elseif str ~= partial then fail("didn't receive partial result.")
|
||||||
else pass("graceful 'closed' received") end
|
else pass("graceful 'closed' received") end
|
||||||
reconnect()
|
reconnect()
|
||||||
pass("trying write detection")
|
printf("trying write detection: ")
|
||||||
remote [[
|
remote [[
|
||||||
data:close()
|
data:close()
|
||||||
data = nil
|
data = nil
|
||||||
@ -342,7 +350,6 @@ end
|
|||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
function test_selectbugs()
|
function test_selectbugs()
|
||||||
local r, s, e = socket.select(nil, nil, 0.1)
|
local r, s, e = socket.select(nil, nil, 0.1)
|
||||||
print(r, s, e)
|
|
||||||
assert(type(r) == "table" and type(s) == "table" and
|
assert(type(r) == "table" and type(s) == "table" and
|
||||||
(e == "timeout" or e == "error"))
|
(e == "timeout" or e == "error"))
|
||||||
pass("both nil: ok")
|
pass("both nil: ok")
|
||||||
@ -374,7 +381,7 @@ end
|
|||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
function accept_timeout()
|
function accept_timeout()
|
||||||
io.stderr:write("accept with timeout (if it hangs, it failed): ")
|
printf("accept with timeout (if it hangs, it failed): ")
|
||||||
local s, e = socket.bind("*", 0, 0)
|
local s, e = socket.bind("*", 0, 0)
|
||||||
assert(s, e)
|
assert(s, e)
|
||||||
local t = socket.gettime()
|
local t = socket.gettime()
|
||||||
@ -390,23 +397,22 @@ end
|
|||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
function connect_timeout()
|
function connect_timeout()
|
||||||
io.stderr:write("connect with timeout (if it hangs, it failed!): ")
|
printf("connect with timeout (if it hangs, it failed!): ")
|
||||||
local t = socket.gettime()
|
local t = socket.gettime()
|
||||||
local c, e = socket.tcp()
|
local c, e = socket.tcp()
|
||||||
assert(c, e)
|
assert(c, e)
|
||||||
c:settimeout(0.1)
|
c:settimeout(0.1)
|
||||||
local t = socket.gettime()
|
local t = socket.gettime()
|
||||||
local r, e = c:connect("10.0.0.1", 81)
|
local r, e = c:connect("10.0.0.1", 81)
|
||||||
print(r, e)
|
|
||||||
assert(not r, "should not connect")
|
assert(not r, "should not connect")
|
||||||
assert(socket.gettime() - t < 2, "took too long to give up.")
|
assert(socket.gettime() - t < 2, "took too long to give up.")
|
||||||
c:close()
|
c:close()
|
||||||
print("ok")
|
pass("ok")
|
||||||
end
|
end
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
function accept_errors()
|
function accept_errors()
|
||||||
io.stderr:write("not listening: ")
|
printf("not listening: ")
|
||||||
local d, e = socket.bind("*", 0)
|
local d, e = socket.bind("*", 0)
|
||||||
assert(d, e);
|
assert(d, e);
|
||||||
local c, e = socket.tcp();
|
local c, e = socket.tcp();
|
||||||
@ -415,26 +421,26 @@ function accept_errors()
|
|||||||
d:settimeout(2)
|
d:settimeout(2)
|
||||||
local r, e = d:accept()
|
local r, e = d:accept()
|
||||||
assert(not r and e)
|
assert(not r and e)
|
||||||
print("ok: ", e)
|
pass("ok")
|
||||||
io.stderr:write("not supported: ")
|
printf("not supported: ")
|
||||||
local c, e = socket.udp()
|
local c, e = socket.udp()
|
||||||
assert(c, e);
|
assert(c, e);
|
||||||
d:setfd(c:getfd())
|
d:setfd(c:getfd())
|
||||||
local r, e = d:accept()
|
local r, e = d:accept()
|
||||||
assert(not r and e)
|
assert(not r and e)
|
||||||
print("ok: ", e)
|
pass("ok")
|
||||||
end
|
end
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
function connect_errors()
|
function connect_errors()
|
||||||
io.stderr:write("connection refused: ")
|
printf("connection refused: ")
|
||||||
local c, e = socket.connect("localhost", 1);
|
local c, e = socket.connect("localhost", 1);
|
||||||
assert(not c and e)
|
assert(not c and e)
|
||||||
print("ok: ", e)
|
pass("ok")
|
||||||
io.stderr:write("host not found: ")
|
printf("host not found: ")
|
||||||
local c, e = socket.connect("host.is.invalid", 1);
|
local c, e = socket.connect("host.is.invalid", 1);
|
||||||
assert(not c and e, e)
|
assert(not c and e, e)
|
||||||
print("ok: ", e)
|
pass("ok")
|
||||||
end
|
end
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
@ -447,7 +453,7 @@ function rebind_test()
|
|||||||
r, e = s:bind("localhost", p)
|
r, e = s:bind("localhost", p)
|
||||||
assert(not r, "managed to rebind!")
|
assert(not r, "managed to rebind!")
|
||||||
assert(e)
|
assert(e)
|
||||||
print("ok: ", e)
|
pass("ok")
|
||||||
end
|
end
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
@ -469,14 +475,14 @@ function getstats_test()
|
|||||||
assert(s == t, "sent count failed" .. tostring(s)
|
assert(s == t, "sent count failed" .. tostring(s)
|
||||||
.. "/" .. tostring(t))
|
.. "/" .. tostring(t))
|
||||||
end
|
end
|
||||||
print("ok")
|
pass("ok")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
function test_nonblocking(size)
|
function test_nonblocking(size)
|
||||||
reconnect()
|
reconnect()
|
||||||
print("Testing " .. 2*size .. " bytes")
|
printf("testing " .. 2*size .. " bytes: ")
|
||||||
remote(string.format([[
|
remote(string.format([[
|
||||||
data:send(string.rep("a", %d))
|
data:send(string.rep("a", %d))
|
||||||
socket.sleep(0.5)
|
socket.sleep(0.5)
|
||||||
@ -508,7 +514,7 @@ remote(string.format([[
|
|||||||
data:settimeout(-1)
|
data:settimeout(-1)
|
||||||
local back = data:receive(2*size)
|
local back = data:receive(2*size)
|
||||||
assert(back == str, "'" .. back .. "' vs '" .. str .. "'")
|
assert(back == str, "'" .. back .. "' vs '" .. str .. "'")
|
||||||
print("ok")
|
pass("ok")
|
||||||
end
|
end
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
@ -516,7 +522,7 @@ function test_readafterclose()
|
|||||||
local back, partial, err
|
local back, partial, err
|
||||||
local str = 'little string'
|
local str = 'little string'
|
||||||
reconnect()
|
reconnect()
|
||||||
pass("trying repeated '*a' pattern")
|
printf("trying repeated '*a' pattern")
|
||||||
remote (string.format ([[
|
remote (string.format ([[
|
||||||
data:send('%s')
|
data:send('%s')
|
||||||
data:close()
|
data:close()
|
||||||
@ -526,9 +532,9 @@ function test_readafterclose()
|
|||||||
assert(back == str, "unexpected data read")
|
assert(back == str, "unexpected data read")
|
||||||
back, err, partial = data:receive("*a")
|
back, err, partial = data:receive("*a")
|
||||||
assert(back == nil and err == "closed", "should have returned 'closed'")
|
assert(back == nil and err == "closed", "should have returned 'closed'")
|
||||||
print("ok")
|
pass("ok")
|
||||||
reconnect()
|
reconnect()
|
||||||
pass("trying active close before '*a'")
|
printf("trying active close before '*a'")
|
||||||
remote (string.format ([[
|
remote (string.format ([[
|
||||||
data:close()
|
data:close()
|
||||||
data = nil
|
data = nil
|
||||||
@ -536,9 +542,9 @@ function test_readafterclose()
|
|||||||
data:close()
|
data:close()
|
||||||
back, err, partial = data:receive("*a")
|
back, err, partial = data:receive("*a")
|
||||||
assert(back == nil and err == "closed", "should have returned 'closed'")
|
assert(back == nil and err == "closed", "should have returned 'closed'")
|
||||||
print("ok")
|
pass("ok")
|
||||||
reconnect()
|
reconnect()
|
||||||
pass("trying active close before '*l'")
|
printf("trying active close before '*l'")
|
||||||
remote (string.format ([[
|
remote (string.format ([[
|
||||||
data:close()
|
data:close()
|
||||||
data = nil
|
data = nil
|
||||||
@ -546,9 +552,9 @@ function test_readafterclose()
|
|||||||
data:close()
|
data:close()
|
||||||
back, err, partial = data:receive()
|
back, err, partial = data:receive()
|
||||||
assert(back == nil and err == "closed", "should have returned 'closed'")
|
assert(back == nil and err == "closed", "should have returned 'closed'")
|
||||||
print("ok")
|
pass("ok")
|
||||||
reconnect()
|
reconnect()
|
||||||
pass("trying active close before raw 1")
|
printf("trying active close before raw 1")
|
||||||
remote (string.format ([[
|
remote (string.format ([[
|
||||||
data:close()
|
data:close()
|
||||||
data = nil
|
data = nil
|
||||||
@ -556,9 +562,9 @@ function test_readafterclose()
|
|||||||
data:close()
|
data:close()
|
||||||
back, err, partial = data:receive(1)
|
back, err, partial = data:receive(1)
|
||||||
assert(back == nil and err == "closed", "should have returned 'closed'")
|
assert(back == nil and err == "closed", "should have returned 'closed'")
|
||||||
print("ok")
|
pass("ok")
|
||||||
reconnect()
|
reconnect()
|
||||||
pass("trying active close before raw 0")
|
printf("trying active close before raw 0")
|
||||||
remote (string.format ([[
|
remote (string.format ([[
|
||||||
data:close()
|
data:close()
|
||||||
data = nil
|
data = nil
|
||||||
@ -566,7 +572,7 @@ function test_readafterclose()
|
|||||||
data:close()
|
data:close()
|
||||||
back, err, partial = data:receive(0)
|
back, err, partial = data:receive(0)
|
||||||
assert(back == nil and err == "closed", "should have returned 'closed'")
|
assert(back == nil and err == "closed", "should have returned 'closed'")
|
||||||
print("ok")
|
pass("ok")
|
||||||
end
|
end
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
@ -581,13 +587,29 @@ function test_writeafterclose()
|
|||||||
while not err do
|
while not err do
|
||||||
sent, err, errsent, time = data:send(str)
|
sent, err, errsent, time = data:send(str)
|
||||||
end
|
end
|
||||||
print(sent, err, errsent, time)
|
assert(err == "closed", "should have returned 'closed'")
|
||||||
print("ok")
|
pass("ok")
|
||||||
end
|
end
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
--test_writeafterclose()
|
|
||||||
|
|
||||||
|
function test_partialrecv()
|
||||||
|
local str = 'little string'
|
||||||
|
reconnect()
|
||||||
|
remote([[
|
||||||
|
data:send("7890")
|
||||||
|
]])
|
||||||
|
data:settimeout(1)
|
||||||
|
back, err = data:receive(10, "123456")
|
||||||
|
assert(back == "1234567890", "failed on exact mixed length")
|
||||||
|
back, err = data:receive(8, "87654321")
|
||||||
|
assert(back == "87654321", "failed on exact length")
|
||||||
|
back, err = data:receive(4, "87654321")
|
||||||
|
assert(back == "87654321", "failed on smaller length")
|
||||||
|
pass("ok")
|
||||||
|
end
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
test("method registration")
|
test("method registration")
|
||||||
test_methods(socket.tcp(), {
|
test_methods(socket.tcp(), {
|
||||||
"accept",
|
"accept",
|
||||||
@ -629,12 +651,18 @@ test_methods(socket.udp(), {
|
|||||||
"settimeout"
|
"settimeout"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("partial receive")
|
||||||
|
test_partialrecv()
|
||||||
|
|
||||||
test("select function")
|
test("select function")
|
||||||
test_selectbugs()
|
test_selectbugs()
|
||||||
|
|
||||||
test("testing read after close")
|
test("read after close")
|
||||||
test_readafterclose()
|
test_readafterclose()
|
||||||
|
|
||||||
|
test("write after close")
|
||||||
|
test_writeafterclose()
|
||||||
|
|
||||||
test("connect function")
|
test("connect function")
|
||||||
connect_timeout()
|
connect_timeout()
|
||||||
empty_connect()
|
empty_connect()
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
function readfile(name)
|
function readfile(name)
|
||||||
local f = io.open(name, "rb")
|
local f = io.open(name, "rb")
|
||||||
if not f then return nil end
|
if not f then return nil end
|
||||||
local s = f:read("*a")
|
local s = f:read("*a")
|
||||||
f:close()
|
f:close()
|
||||||
return s
|
return s
|
||||||
end
|
end
|
||||||
|
|
||||||
function similar(s1, s2)
|
function similar(s1, s2)
|
||||||
return string.lower(string.gsub(s1 or "", "%s", "")) ==
|
return string.lower(string.gsub(s1 or "", "%s", "")) ==
|
||||||
string.lower(string.gsub(s2 or "", "%s", ""))
|
string.lower(string.gsub(s2 or "", "%s", ""))
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ local set = rawset
|
|||||||
local warn = print
|
local warn = print
|
||||||
|
|
||||||
local setglobal = function(table, key, value)
|
local setglobal = function(table, key, value)
|
||||||
warn("changed " .. key)
|
warn("changed " .. key)
|
||||||
set(table, key, value)
|
set(table, key, value)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
620
test/urltest.lua
620
test/urltest.lua
@ -3,439 +3,439 @@ socket.url = require("socket.url")
|
|||||||
dofile("testsupport.lua")
|
dofile("testsupport.lua")
|
||||||
|
|
||||||
local check_build_url = function(parsed)
|
local check_build_url = function(parsed)
|
||||||
local built = socket.url.build(parsed)
|
local built = socket.url.build(parsed)
|
||||||
if built ~= parsed.url then
|
if built ~= parsed.url then
|
||||||
print("built is different from expected")
|
print("built is different from expected")
|
||||||
print(built)
|
print(built)
|
||||||
print(expected)
|
print(expected)
|
||||||
exit()
|
exit()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local check_protect = function(parsed, path, unsafe)
|
local check_protect = function(parsed, path, unsafe)
|
||||||
local built = socket.url.build_path(parsed, unsafe)
|
local built = socket.url.build_path(parsed, unsafe)
|
||||||
if built ~= path then
|
if built ~= path then
|
||||||
print(built, path)
|
print(built, path)
|
||||||
print("path composition failed.")
|
print("path composition failed.")
|
||||||
exit()
|
exit()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local check_invert = function(url)
|
local check_invert = function(url)
|
||||||
local parsed = socket.url.parse(url)
|
local parsed = socket.url.parse(url)
|
||||||
parsed.path = socket.url.build_path(socket.url.parse_path(parsed.path))
|
parsed.path = socket.url.build_path(socket.url.parse_path(parsed.path))
|
||||||
local rebuilt = socket.url.build(parsed)
|
local rebuilt = socket.url.build(parsed)
|
||||||
if rebuilt ~= url then
|
if rebuilt ~= url then
|
||||||
print(url, rebuilt)
|
print(url, rebuilt)
|
||||||
print("original and rebuilt are different")
|
print("original and rebuilt are different")
|
||||||
exit()
|
exit()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local check_parse_path = function(path, expect)
|
local check_parse_path = function(path, expect)
|
||||||
local parsed = socket.url.parse_path(path)
|
local parsed = socket.url.parse_path(path)
|
||||||
for i = 1, math.max(table.getn(parsed), table.getn(expect)) do
|
for i = 1, math.max(table.getn(parsed), table.getn(expect)) do
|
||||||
if parsed[i] ~= expect[i] then
|
if parsed[i] ~= expect[i] then
|
||||||
print(path)
|
print(path)
|
||||||
exit()
|
exit()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if expect.is_directory ~= parsed.is_directory then
|
if expect.is_directory ~= parsed.is_directory then
|
||||||
print(path)
|
print(path)
|
||||||
print("is_directory mismatch")
|
print("is_directory mismatch")
|
||||||
exit()
|
exit()
|
||||||
end
|
end
|
||||||
if expect.is_absolute ~= parsed.is_absolute then
|
if expect.is_absolute ~= parsed.is_absolute then
|
||||||
print(path)
|
print(path)
|
||||||
print("is_absolute mismatch")
|
print("is_absolute mismatch")
|
||||||
exit()
|
exit()
|
||||||
end
|
end
|
||||||
local built = socket.url.build_path(expect)
|
local built = socket.url.build_path(expect)
|
||||||
if built ~= path then
|
if built ~= path then
|
||||||
print(built, path)
|
print(built, path)
|
||||||
print("path composition failed.")
|
print("path composition failed.")
|
||||||
exit()
|
exit()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local check_absolute_url = function(base, relative, absolute)
|
local check_absolute_url = function(base, relative, absolute)
|
||||||
local res = socket.url.absolute(base, relative)
|
local res = socket.url.absolute(base, relative)
|
||||||
if res ~= absolute then
|
if res ~= absolute then
|
||||||
io.write("absolute: In test for '", relative, "' expected '",
|
io.write("absolute: In test for '", relative, "' expected '",
|
||||||
absolute, "' but got '", res, "'\n")
|
absolute, "' but got '", res, "'\n")
|
||||||
exit()
|
exit()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local check_parse_url = function(gaba)
|
local check_parse_url = function(gaba)
|
||||||
local url = gaba.url
|
local url = gaba.url
|
||||||
gaba.url = nil
|
gaba.url = nil
|
||||||
local parsed = socket.url.parse(url)
|
local parsed = socket.url.parse(url)
|
||||||
for i, v in pairs(gaba) do
|
for i, v in pairs(gaba) do
|
||||||
if v ~= parsed[i] then
|
if v ~= parsed[i] then
|
||||||
io.write("parse: In test for '", url, "' expected ", i, " = '",
|
io.write("parse: In test for '", url, "' expected ", i, " = '",
|
||||||
v, "' but got '", tostring(parsed[i]), "'\n")
|
v, "' but got '", tostring(parsed[i]), "'\n")
|
||||||
for i,v in pairs(parsed) do print(i,v) end
|
for i,v in pairs(parsed) do print(i,v) end
|
||||||
exit()
|
exit()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
for i, v in pairs(parsed) do
|
for i, v in pairs(parsed) do
|
||||||
if v ~= gaba[i] then
|
if v ~= gaba[i] then
|
||||||
io.write("parse: In test for '", url, "' expected ", i, " = '",
|
io.write("parse: In test for '", url, "' expected ", i, " = '",
|
||||||
tostring(gaba[i]), "' but got '", v, "'\n")
|
tostring(gaba[i]), "' but got '", v, "'\n")
|
||||||
for i,v in pairs(parsed) do print(i,v) end
|
for i,v in pairs(parsed) do print(i,v) end
|
||||||
exit()
|
exit()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
print("testing URL parsing")
|
print("testing URL parsing")
|
||||||
check_parse_url{
|
check_parse_url{
|
||||||
url = "scheme://userinfo@host:port/path;params?query#fragment",
|
url = "scheme://userinfo@host:port/path;params?query#fragment",
|
||||||
scheme = "scheme",
|
scheme = "scheme",
|
||||||
authority = "userinfo@host:port",
|
authority = "userinfo@host:port",
|
||||||
host = "host",
|
host = "host",
|
||||||
port = "port",
|
port = "port",
|
||||||
userinfo = "userinfo",
|
userinfo = "userinfo",
|
||||||
user = "userinfo",
|
user = "userinfo",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
params = "params",
|
params = "params",
|
||||||
query = "query",
|
query = "query",
|
||||||
fragment = "fragment"
|
fragment = "fragment"
|
||||||
}
|
}
|
||||||
|
|
||||||
check_parse_url{
|
check_parse_url{
|
||||||
url = "scheme://user:password@host:port/path;params?query#fragment",
|
url = "scheme://user:password@host:port/path;params?query#fragment",
|
||||||
scheme = "scheme",
|
scheme = "scheme",
|
||||||
authority = "user:password@host:port",
|
authority = "user:password@host:port",
|
||||||
host = "host",
|
host = "host",
|
||||||
port = "port",
|
port = "port",
|
||||||
userinfo = "user:password",
|
userinfo = "user:password",
|
||||||
user = "user",
|
user = "user",
|
||||||
password = "password",
|
password = "password",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
params = "params",
|
params = "params",
|
||||||
query = "query",
|
query = "query",
|
||||||
fragment = "fragment",
|
fragment = "fragment",
|
||||||
}
|
}
|
||||||
|
|
||||||
check_parse_url{
|
check_parse_url{
|
||||||
url = "scheme://userinfo@host:port/path;params?query#",
|
url = "scheme://userinfo@host:port/path;params?query#",
|
||||||
scheme = "scheme",
|
scheme = "scheme",
|
||||||
authority = "userinfo@host:port",
|
authority = "userinfo@host:port",
|
||||||
host = "host",
|
host = "host",
|
||||||
port = "port",
|
port = "port",
|
||||||
userinfo = "userinfo",
|
userinfo = "userinfo",
|
||||||
user = "userinfo",
|
user = "userinfo",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
params = "params",
|
params = "params",
|
||||||
query = "query",
|
query = "query",
|
||||||
fragment = ""
|
fragment = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
check_parse_url{
|
check_parse_url{
|
||||||
url = "scheme://userinfo@host:port/path;params?#fragment",
|
url = "scheme://userinfo@host:port/path;params?#fragment",
|
||||||
scheme = "scheme",
|
scheme = "scheme",
|
||||||
authority = "userinfo@host:port",
|
authority = "userinfo@host:port",
|
||||||
host = "host",
|
host = "host",
|
||||||
port = "port",
|
port = "port",
|
||||||
userinfo = "userinfo",
|
userinfo = "userinfo",
|
||||||
user = "userinfo",
|
user = "userinfo",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
params = "params",
|
params = "params",
|
||||||
query = "",
|
query = "",
|
||||||
fragment = "fragment"
|
fragment = "fragment"
|
||||||
}
|
}
|
||||||
|
|
||||||
check_parse_url{
|
check_parse_url{
|
||||||
url = "scheme://userinfo@host:port/path;params#fragment",
|
url = "scheme://userinfo@host:port/path;params#fragment",
|
||||||
scheme = "scheme",
|
scheme = "scheme",
|
||||||
authority = "userinfo@host:port",
|
authority = "userinfo@host:port",
|
||||||
host = "host",
|
host = "host",
|
||||||
port = "port",
|
port = "port",
|
||||||
userinfo = "userinfo",
|
userinfo = "userinfo",
|
||||||
user = "userinfo",
|
user = "userinfo",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
params = "params",
|
params = "params",
|
||||||
fragment = "fragment"
|
fragment = "fragment"
|
||||||
}
|
}
|
||||||
|
|
||||||
check_parse_url{
|
check_parse_url{
|
||||||
url = "scheme://userinfo@host:port/path;?query#fragment",
|
url = "scheme://userinfo@host:port/path;?query#fragment",
|
||||||
scheme = "scheme",
|
scheme = "scheme",
|
||||||
authority = "userinfo@host:port",
|
authority = "userinfo@host:port",
|
||||||
host = "host",
|
host = "host",
|
||||||
port = "port",
|
port = "port",
|
||||||
userinfo = "userinfo",
|
userinfo = "userinfo",
|
||||||
user = "userinfo",
|
user = "userinfo",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
params = "",
|
params = "",
|
||||||
query = "query",
|
query = "query",
|
||||||
fragment = "fragment"
|
fragment = "fragment"
|
||||||
}
|
}
|
||||||
|
|
||||||
check_parse_url{
|
check_parse_url{
|
||||||
url = "scheme://userinfo@host:port/path?query#fragment",
|
url = "scheme://userinfo@host:port/path?query#fragment",
|
||||||
scheme = "scheme",
|
scheme = "scheme",
|
||||||
authority = "userinfo@host:port",
|
authority = "userinfo@host:port",
|
||||||
host = "host",
|
host = "host",
|
||||||
port = "port",
|
port = "port",
|
||||||
userinfo = "userinfo",
|
userinfo = "userinfo",
|
||||||
user = "userinfo",
|
user = "userinfo",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
query = "query",
|
query = "query",
|
||||||
fragment = "fragment"
|
fragment = "fragment"
|
||||||
}
|
}
|
||||||
|
|
||||||
check_parse_url{
|
check_parse_url{
|
||||||
url = "scheme://userinfo@host:port/;params?query#fragment",
|
url = "scheme://userinfo@host:port/;params?query#fragment",
|
||||||
scheme = "scheme",
|
scheme = "scheme",
|
||||||
authority = "userinfo@host:port",
|
authority = "userinfo@host:port",
|
||||||
host = "host",
|
host = "host",
|
||||||
port = "port",
|
port = "port",
|
||||||
userinfo = "userinfo",
|
userinfo = "userinfo",
|
||||||
user = "userinfo",
|
user = "userinfo",
|
||||||
path = "/",
|
path = "/",
|
||||||
params = "params",
|
params = "params",
|
||||||
query = "query",
|
query = "query",
|
||||||
fragment = "fragment"
|
fragment = "fragment"
|
||||||
}
|
}
|
||||||
|
|
||||||
check_parse_url{
|
check_parse_url{
|
||||||
url = "scheme://userinfo@host:port",
|
url = "scheme://userinfo@host:port",
|
||||||
scheme = "scheme",
|
scheme = "scheme",
|
||||||
authority = "userinfo@host:port",
|
authority = "userinfo@host:port",
|
||||||
host = "host",
|
host = "host",
|
||||||
port = "port",
|
port = "port",
|
||||||
userinfo = "userinfo",
|
userinfo = "userinfo",
|
||||||
user = "userinfo",
|
user = "userinfo",
|
||||||
}
|
}
|
||||||
|
|
||||||
check_parse_url{
|
check_parse_url{
|
||||||
url = "//userinfo@host:port/path;params?query#fragment",
|
url = "//userinfo@host:port/path;params?query#fragment",
|
||||||
authority = "userinfo@host:port",
|
authority = "userinfo@host:port",
|
||||||
host = "host",
|
host = "host",
|
||||||
port = "port",
|
port = "port",
|
||||||
userinfo = "userinfo",
|
userinfo = "userinfo",
|
||||||
user = "userinfo",
|
user = "userinfo",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
params = "params",
|
params = "params",
|
||||||
query = "query",
|
query = "query",
|
||||||
fragment = "fragment"
|
fragment = "fragment"
|
||||||
}
|
}
|
||||||
|
|
||||||
check_parse_url{
|
check_parse_url{
|
||||||
url = "//userinfo@host:port/path",
|
url = "//userinfo@host:port/path",
|
||||||
authority = "userinfo@host:port",
|
authority = "userinfo@host:port",
|
||||||
host = "host",
|
host = "host",
|
||||||
port = "port",
|
port = "port",
|
||||||
userinfo = "userinfo",
|
userinfo = "userinfo",
|
||||||
user = "userinfo",
|
user = "userinfo",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
}
|
}
|
||||||
|
|
||||||
check_parse_url{
|
check_parse_url{
|
||||||
url = "//userinfo@host/path",
|
url = "//userinfo@host/path",
|
||||||
authority = "userinfo@host",
|
authority = "userinfo@host",
|
||||||
host = "host",
|
host = "host",
|
||||||
userinfo = "userinfo",
|
userinfo = "userinfo",
|
||||||
user = "userinfo",
|
user = "userinfo",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
}
|
}
|
||||||
|
|
||||||
check_parse_url{
|
check_parse_url{
|
||||||
url = "//user:password@host/path",
|
url = "//user:password@host/path",
|
||||||
authority = "user:password@host",
|
authority = "user:password@host",
|
||||||
host = "host",
|
host = "host",
|
||||||
userinfo = "user:password",
|
userinfo = "user:password",
|
||||||
password = "password",
|
password = "password",
|
||||||
user = "user",
|
user = "user",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
}
|
}
|
||||||
|
|
||||||
check_parse_url{
|
check_parse_url{
|
||||||
url = "//user:@host/path",
|
url = "//user:@host/path",
|
||||||
authority = "user:@host",
|
authority = "user:@host",
|
||||||
host = "host",
|
host = "host",
|
||||||
userinfo = "user:",
|
userinfo = "user:",
|
||||||
password = "",
|
password = "",
|
||||||
user = "user",
|
user = "user",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
}
|
}
|
||||||
|
|
||||||
check_parse_url{
|
check_parse_url{
|
||||||
url = "//user@host:port/path",
|
url = "//user@host:port/path",
|
||||||
authority = "user@host:port",
|
authority = "user@host:port",
|
||||||
host = "host",
|
host = "host",
|
||||||
userinfo = "user",
|
userinfo = "user",
|
||||||
user = "user",
|
user = "user",
|
||||||
port = "port",
|
port = "port",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
}
|
}
|
||||||
|
|
||||||
check_parse_url{
|
check_parse_url{
|
||||||
url = "//host:port/path",
|
url = "//host:port/path",
|
||||||
authority = "host:port",
|
authority = "host:port",
|
||||||
port = "port",
|
port = "port",
|
||||||
host = "host",
|
host = "host",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
}
|
}
|
||||||
|
|
||||||
check_parse_url{
|
check_parse_url{
|
||||||
url = "//host/path",
|
url = "//host/path",
|
||||||
authority = "host",
|
authority = "host",
|
||||||
host = "host",
|
host = "host",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
}
|
}
|
||||||
|
|
||||||
check_parse_url{
|
check_parse_url{
|
||||||
url = "//host",
|
url = "//host",
|
||||||
authority = "host",
|
authority = "host",
|
||||||
host = "host",
|
host = "host",
|
||||||
}
|
}
|
||||||
|
|
||||||
check_parse_url{
|
check_parse_url{
|
||||||
url = "/path",
|
url = "/path",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
}
|
}
|
||||||
|
|
||||||
check_parse_url{
|
check_parse_url{
|
||||||
url = "path",
|
url = "path",
|
||||||
path = "path",
|
path = "path",
|
||||||
}
|
}
|
||||||
|
|
||||||
print("testing URL building")
|
print("testing URL building")
|
||||||
check_build_url {
|
check_build_url {
|
||||||
url = "scheme://user:password@host:port/path;params?query#fragment",
|
url = "scheme://user:password@host:port/path;params?query#fragment",
|
||||||
scheme = "scheme",
|
scheme = "scheme",
|
||||||
host = "host",
|
host = "host",
|
||||||
port = "port",
|
port = "port",
|
||||||
user = "user",
|
user = "user",
|
||||||
password = "password",
|
password = "password",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
params = "params",
|
params = "params",
|
||||||
query = "query",
|
query = "query",
|
||||||
fragment = "fragment"
|
fragment = "fragment"
|
||||||
}
|
}
|
||||||
|
|
||||||
check_build_url {
|
check_build_url {
|
||||||
url = "scheme://user:password@host/path;params?query#fragment",
|
url = "scheme://user:password@host/path;params?query#fragment",
|
||||||
scheme = "scheme",
|
scheme = "scheme",
|
||||||
host = "host",
|
host = "host",
|
||||||
user = "user",
|
user = "user",
|
||||||
password = "password",
|
password = "password",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
params = "params",
|
params = "params",
|
||||||
query = "query",
|
query = "query",
|
||||||
fragment = "fragment"
|
fragment = "fragment"
|
||||||
}
|
}
|
||||||
|
|
||||||
check_build_url {
|
check_build_url {
|
||||||
url = "scheme://user@host/path;params?query#fragment",
|
url = "scheme://user@host/path;params?query#fragment",
|
||||||
scheme = "scheme",
|
scheme = "scheme",
|
||||||
host = "host",
|
host = "host",
|
||||||
user = "user",
|
user = "user",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
params = "params",
|
params = "params",
|
||||||
query = "query",
|
query = "query",
|
||||||
fragment = "fragment"
|
fragment = "fragment"
|
||||||
}
|
}
|
||||||
|
|
||||||
check_build_url {
|
check_build_url {
|
||||||
url = "scheme://host/path;params?query#fragment",
|
url = "scheme://host/path;params?query#fragment",
|
||||||
scheme = "scheme",
|
scheme = "scheme",
|
||||||
host = "host",
|
host = "host",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
params = "params",
|
params = "params",
|
||||||
query = "query",
|
query = "query",
|
||||||
fragment = "fragment"
|
fragment = "fragment"
|
||||||
}
|
}
|
||||||
|
|
||||||
check_build_url {
|
check_build_url {
|
||||||
url = "scheme://host/path;params#fragment",
|
url = "scheme://host/path;params#fragment",
|
||||||
scheme = "scheme",
|
scheme = "scheme",
|
||||||
host = "host",
|
host = "host",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
params = "params",
|
params = "params",
|
||||||
fragment = "fragment"
|
fragment = "fragment"
|
||||||
}
|
}
|
||||||
|
|
||||||
check_build_url {
|
check_build_url {
|
||||||
url = "scheme://host/path#fragment",
|
url = "scheme://host/path#fragment",
|
||||||
scheme = "scheme",
|
scheme = "scheme",
|
||||||
host = "host",
|
host = "host",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
fragment = "fragment"
|
fragment = "fragment"
|
||||||
}
|
}
|
||||||
|
|
||||||
check_build_url {
|
check_build_url {
|
||||||
url = "scheme://host/path",
|
url = "scheme://host/path",
|
||||||
scheme = "scheme",
|
scheme = "scheme",
|
||||||
host = "host",
|
host = "host",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
}
|
}
|
||||||
|
|
||||||
check_build_url {
|
check_build_url {
|
||||||
url = "//host/path",
|
url = "//host/path",
|
||||||
host = "host",
|
host = "host",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
}
|
}
|
||||||
|
|
||||||
check_build_url {
|
check_build_url {
|
||||||
url = "/path",
|
url = "/path",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
}
|
}
|
||||||
|
|
||||||
check_build_url {
|
check_build_url {
|
||||||
url = "scheme://user:password@host:port/path;params?query#fragment",
|
url = "scheme://user:password@host:port/path;params?query#fragment",
|
||||||
scheme = "scheme",
|
scheme = "scheme",
|
||||||
host = "host",
|
host = "host",
|
||||||
port = "port",
|
port = "port",
|
||||||
user = "user",
|
user = "user",
|
||||||
userinfo = "not used",
|
userinfo = "not used",
|
||||||
password = "password",
|
password = "password",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
params = "params",
|
params = "params",
|
||||||
query = "query",
|
query = "query",
|
||||||
fragment = "fragment"
|
fragment = "fragment"
|
||||||
}
|
}
|
||||||
|
|
||||||
check_build_url {
|
check_build_url {
|
||||||
url = "scheme://user:password@host:port/path;params?query#fragment",
|
url = "scheme://user:password@host:port/path;params?query#fragment",
|
||||||
scheme = "scheme",
|
scheme = "scheme",
|
||||||
host = "host",
|
host = "host",
|
||||||
port = "port",
|
port = "port",
|
||||||
user = "user",
|
user = "user",
|
||||||
userinfo = "not used",
|
userinfo = "not used",
|
||||||
authority = "not used",
|
authority = "not used",
|
||||||
password = "password",
|
password = "password",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
params = "params",
|
params = "params",
|
||||||
query = "query",
|
query = "query",
|
||||||
fragment = "fragment"
|
fragment = "fragment"
|
||||||
}
|
}
|
||||||
|
|
||||||
check_build_url {
|
check_build_url {
|
||||||
url = "scheme://user:password@host:port/path;params?query#fragment",
|
url = "scheme://user:password@host:port/path;params?query#fragment",
|
||||||
scheme = "scheme",
|
scheme = "scheme",
|
||||||
host = "host",
|
host = "host",
|
||||||
port = "port",
|
port = "port",
|
||||||
userinfo = "user:password",
|
userinfo = "user:password",
|
||||||
authority = "not used",
|
authority = "not used",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
params = "params",
|
params = "params",
|
||||||
query = "query",
|
query = "query",
|
||||||
fragment = "fragment"
|
fragment = "fragment"
|
||||||
}
|
}
|
||||||
|
|
||||||
check_build_url {
|
check_build_url {
|
||||||
url = "scheme://user:password@host:port/path;params?query#fragment",
|
url = "scheme://user:password@host:port/path;params?query#fragment",
|
||||||
scheme = "scheme",
|
scheme = "scheme",
|
||||||
authority = "user:password@host:port",
|
authority = "user:password@host:port",
|
||||||
path = "/path",
|
path = "/path",
|
||||||
params = "params",
|
params = "params",
|
||||||
query = "query",
|
query = "query",
|
||||||
fragment = "fragment"
|
fragment = "fragment"
|
||||||
}
|
}
|
||||||
|
|
||||||
-- standard RFC tests
|
-- standard RFC tests
|
||||||
@ -488,11 +488,11 @@ print("testing path parsing and composition")
|
|||||||
check_parse_path("/eu/tu/ele", { "eu", "tu", "ele"; is_absolute = 1 })
|
check_parse_path("/eu/tu/ele", { "eu", "tu", "ele"; is_absolute = 1 })
|
||||||
check_parse_path("/eu/", { "eu"; is_absolute = 1, is_directory = 1 })
|
check_parse_path("/eu/", { "eu"; is_absolute = 1, is_directory = 1 })
|
||||||
check_parse_path("eu/tu/ele/nos/vos/eles/",
|
check_parse_path("eu/tu/ele/nos/vos/eles/",
|
||||||
{ "eu", "tu", "ele", "nos", "vos", "eles"; is_directory = 1})
|
{ "eu", "tu", "ele", "nos", "vos", "eles"; is_directory = 1})
|
||||||
check_parse_path("/", { is_absolute = 1, is_directory = 1})
|
check_parse_path("/", { is_absolute = 1, is_directory = 1})
|
||||||
check_parse_path("", { })
|
check_parse_path("", { })
|
||||||
check_parse_path("eu%01/%02tu/e%03l%04e/nos/vos%05/e%12les/",
|
check_parse_path("eu%01/%02tu/e%03l%04e/nos/vos%05/e%12les/",
|
||||||
{ "eu\1", "\2tu", "e\3l\4e", "nos", "vos\5", "e\18les"; is_directory = 1})
|
{ "eu\1", "\2tu", "e\3l\4e", "nos", "vos\5", "e\18les"; is_directory = 1})
|
||||||
check_parse_path("eu/tu", { "eu", "tu" })
|
check_parse_path("eu/tu", { "eu", "tu" })
|
||||||
|
|
||||||
print("testing path protection")
|
print("testing path protection")
|
||||||
|
@ -298,7 +298,7 @@ function empty_connect()
|
|||||||
pass("ok")
|
pass("ok")
|
||||||
data = socket.connect(host, port)
|
data = socket.connect(host, port)
|
||||||
else
|
else
|
||||||
pass("gethostbyname returns localhost on empty string...")
|
pass("gethostbyname returns localhost on empty string...")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user