Saving before big changes to support IPv6.

This commit is contained in:
Diego Nehab 2011-05-25 20:57:22 +00:00
parent bce60be30f
commit 3a8ba90dfb
30 changed files with 948 additions and 850 deletions

13
FIX
View File

@ -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.

40
NEW
View File

@ -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 * Improved: FTP commands are now sent in upper case to
help buggy servers (Anders Eurenius) help buggy servers (Anders Eurenius);
* Improved: known headers now sent in canonic * Improved: known headers now sent in canonic
capitalization to help buggy servers (Joseph Stewart); capitalization to help buggy servers (Joseph Stewart);
* Improved: Clarified tcp:receive() in the manual (MPB); * Improved: Clarified tcp:receive() in the manual (MPB);
* Improved: Decent makefiles (LHF).
* Fixed: RFC links in documentation now point to IETF (Cosmin Apreutesei).
* Fixed: multicast didn't work on Windows (Herbert Leuwer, Adrian Sietsma)
* Fixed: select() reports an error when called with more Yuri's bug?
sockets than FD_SETSIZE (Lorenzo Leonini) Dahlberg
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"))
)

View File

@ -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>

View File

@ -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&nbsp;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>

View File

@ -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);

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -124,7 +124,13 @@ int buffer_meth_receive(lua_State *L, p_buffer buf) {
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

View File

@ -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);
} }

View File

@ -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

View File

@ -195,7 +195,13 @@ function build(parsed)
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)

View File

@ -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 [[
@ -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()