diff --git a/NEW b/NEW index 0191ccd..6c6b095 100644 --- a/NEW +++ b/NEW @@ -2,13 +2,19 @@ What's New This is just a bug-fix/update release. - * Improved: http.request() now supports deprecated HTTP/0.9 - servers (Florian Berger) - * Fixed: could return "timedout" instead of "timeout" (Leo Leo) - * Fixed: crash when reading '*a' on closed socket (Paul Ducklin); - * Fixed: return values are consistent when reading from closed sockets; - * Fixed: case sensitivity in headers of multipart messages in - smtp.message() (Graham Henstridge); - * Fixed a couple instances of error() being called instead of base.error(). These would cause an error when an error was reported. :) (Ketmar Dark); - * Fixed: test script now uses pairs() iterator instead of the old - Lua syntax (Robert Dodier). + * Fixed: manual links to home.html changed to index.html (Robert Hahn) + * Fixed: mime.unb64() returns empty string on results that start + with a null character (Robert Raschke) + * Fixed: HTTP now automatically redirecting on 303 and 307 (Jonathan Gray) + * Fixed: sleep(-1) could sleep 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); + + * Fixed: multicast didn't work on Windows (Herbert Leuwer, Adrian Sietsma) + * Fixed: select() reports an error when called with more + sockets than FD_SETSIZE (Lorenzo Leonini) diff --git a/config b/config deleted file mode 100644 index 49958eb..0000000 --- a/config +++ /dev/null @@ -1,60 +0,0 @@ -#------ -# LuaSocket makefile configuration -# - -#------ -# Output file names -# -EXT=so -SOCKET_V=2.0.2 -MIME_V=1.0.2 -SOCKET_SO=socket.$(EXT).$(SOCKET_V) -MIME_SO=mime.$(EXT).$(MIME_V) -UNIX_SO=unix.$(EXT) - -#------ -# Lua includes and libraries -# -#LUAINC=-I/usr/local/include/lua50 -#LUAINC=-I/usr/local/include/lua5.1 -#LUAINC=-Ilua-5.1.1/src - -#------ -# Compat-5.1 directory -# -#COMPAT=compat-5.1r5 - -#------ -# Top of your Lua installation -# Relative paths will be inside the src tree -# -#INSTALL_TOP_SHARE=/usr/local/share/lua/5.0 -#INSTALL_TOP_LIB=/usr/local/lib/lua/5.0 -INSTALL_TOP_SHARE=/usr/local/share/lua/5.1 -INSTALL_TOP_LIB=/usr/local/lib/lua/5.1 - -INSTALL_DATA=cp -INSTALL_EXEC=cp - -#------ -# Compiler and linker settings -# for Mac OS X -# -#CC=gcc -#DEF= -DLUASOCKET_DEBUG -DUNIX_HAS_SUN_LEN -#CFLAGS= $(LUAINC) -I$(COMPAT) $(DEF) -pedantic -Wall -O2 -fno-common -#LDFLAGS=-bundle -undefined dynamic_lookup -#LD=export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc - -#------ -# Compiler and linker settings -# for Linux -CC=gcc -DEF=-DLUASOCKET_DEBUG -CFLAGS= $(LUAINC) $(DEF) -pedantic -Wall -O2 -fpic -LDFLAGS=-O -shared -fpic -LD=gcc - -#------ -# End of makefile configuration -# diff --git a/doc/dns.html b/doc/dns.html index f4c3b07..a38e368 100644 --- a/doc/dns.html +++ b/doc/dns.html @@ -24,8 +24,8 @@

-home · -download · +home · +download · installation · introduction · reference @@ -113,8 +113,8 @@ message.


-home · -download · +home · +download · installation · introduction · reference diff --git a/doc/ftp.html b/doc/ftp.html index 9884f31..1f6335e 100644 --- a/doc/ftp.html +++ b/doc/ftp.html @@ -24,8 +24,8 @@

-home · -download · +home · +download · installation · introduction · reference @@ -270,8 +270,8 @@ f, e = ftp.put{


-home · -download · +home · +download · installation · introduction · reference diff --git a/doc/http.html b/doc/http.html index 0acac13..a274aef 100644 --- a/doc/http.html +++ b/doc/http.html @@ -24,8 +24,8 @@

-home · -download · +home · +download · introduction · introduction · reference @@ -314,8 +314,8 @@ r, c = http.request {


-home · -download · +home · +download · installation · introduction · reference diff --git a/doc/index.html b/doc/index.html index 57a7907..5b54c59 100644 --- a/doc/index.html +++ b/doc/index.html @@ -24,8 +24,8 @@

-home · -download · +home · +download · installation · introduction · reference @@ -87,7 +87,7 @@ Author: Diego Nehab

Download

-LuaSocket version 2.0.2 is now available for download! It is +LuaSocket version 2.0.3 is now available for download! It is compatible with Lua 5.1, and has been tested on Windows XP, Linux, and Mac OS X. Chances are it works well on most UNIX distributions and Windows flavors. @@ -118,14 +118,15 @@ manual to find out how to properly install the library.

Special thanks

-Throughout LuaSocket's history, many people gave suggestions that helped -improve it. For that, I thank the Lua community. -Special thanks go to -David Burgess, who has helped push the library to a new level of quality and -from whom I have learned a lot of stuff that doesn't show up in RFCs. -Special thanks also to Carlos Cassino, who played a big part in the -extensible design seen in the C core of LuaSocket 2.0. Mike Pall -has been helping a lot too! Thanks to you all! +Throughout LuaSocket's history, many people gave suggestions +that helped improve it. For that, I thank the Lua community. +Special thanks go to David Burgess, who has helped push the +library to a new level of quality and from whom I have +learned a lot of stuff that doesn't show up in RFCs. +Special thanks also to Carlos Cassino, who played a big part +in the extensible design seen in the C core of LuaSocket +2.0. Mike Pall has been helping a lot too! Thanks to you +all!

@@ -133,44 +134,26 @@ has been helping a lot too! Thanks to you all!

What's New

-2.0.2 is just a bug-fix/update release. +2.0.3 is just a bug-fix/update release.

    -
  • Improved: http.request() now supports deprecated -HTTP/0.9 servers (Florian Berger); -
  • Fixed: could return "timedout" instead of "timeout" (Leo Leo); -
  • Fixed: crash when reading '*a' on closed socket (Paul Ducklin); -
  • Fixed: return values are consistent when reading from closed sockets; -
  • Fixed: case sensitivity in headers of multipart -messages in smtp.message() (Graham Henstridge); -
  • Fixed a couple instances of error() being called instead of -base.error(). These would cause an error when an error was -reported :) (Ketmar Dark); -
  • Fixed: test script now uses pairs() iterator instead -of the old Lua syntax (Robert Dodier). -
- -

-2.0.1 is just a bug-fix/update release. -

- -
    -
  • Updated: now using compat-5.1r5; -
  • Improved: http.request is more robust to -malformed URLs (Adrian Sietsma); -
  • Improved: the simple http.request interface sends a -"Content-type: application/x-www-form-urlencoded" -header (William Trenker); -
  • Improved: http.request is robust to evil -servers that send inappropriate 100-continue messages -(David Burgess); -
  • Fixed: http.request was using the old host header during -redirects (Florian Berger); -
  • Fixed: sample unix.c had fallen through the -cracks during development (Matthew Percival); -
  • Fixed: error code was not being propagated correctly in -ftp.lua (David Burgess). +
  • 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).
@@ -190,7 +173,7 @@ still available for those that have compatibility issues.

-download · +download · installation · introduction · reference diff --git a/doc/installation.html b/doc/installation.html index 0288f4a..bb9a5bb 100644 --- a/doc/installation.html +++ b/doc/installation.html @@ -25,8 +25,8 @@ Installation">

-home · -download · +home · +download · installation · introduction · reference @@ -144,8 +144,8 @@ Lua 5.1.2 Copyright (C) 1994-2007 Lua.org, PUC-Rio


-home · -download · +home · +download · installation · introduction · reference diff --git a/doc/introduction.html b/doc/introduction.html index eff6367..fd22f48 100644 --- a/doc/introduction.html +++ b/doc/introduction.html @@ -25,8 +25,8 @@ Library, Support">

-home · -download · +home · +download · installation · introduction · reference @@ -314,8 +314,8 @@ and many others are covered by the reference manual.


-home · -download · +home · +download · installation · introduction · reference diff --git a/doc/ltn12.html b/doc/ltn12.html index 0013950..7e2f49a 100644 --- a/doc/ltn12.html +++ b/doc/ltn12.html @@ -25,8 +25,8 @@ Pump, Support, Library">

-home · -download · +home · +download · installation · introduction · reference @@ -411,8 +411,8 @@ Creates and returns a source that produces the contents of a


-home · -download · +home · +download · installation · introduction · reference diff --git a/doc/mime.html b/doc/mime.html index d7faf52..9844744 100644 --- a/doc/mime.html +++ b/doc/mime.html @@ -24,8 +24,8 @@

-home · -download · +home · +download · installation · introduction · reference @@ -457,8 +457,8 @@ marker.


-home · -download · +home · +download · installation · introduction · reference diff --git a/doc/reference.html b/doc/reference.html index b329f57..31f6ecf 100644 --- a/doc/reference.html +++ b/doc/reference.html @@ -25,8 +25,8 @@ Support, Manual">

-home · -download · +home · +download · installation · introduction · reference @@ -151,6 +151,7 @@ Support, Manual"> sink, skip, sleep, +_SETSIZE, source, tcp, try, @@ -220,8 +221,8 @@ Support, Manual">


-home · -download · +home · +download · installation · introduction · reference diff --git a/doc/smtp.html b/doc/smtp.html index 27dd473..980b821 100644 --- a/doc/smtp.html +++ b/doc/smtp.html @@ -25,8 +25,8 @@ Library, Support">

-home · -download · +home · +download · installation · introduction · reference @@ -398,8 +398,8 @@ r, e = smtp.send{


-home · -download · +home · +download · installation · introduction · reference diff --git a/doc/socket.html b/doc/socket.html index f096e4b..490ab50 100644 --- a/doc/socket.html +++ b/doc/socket.html @@ -24,8 +24,8 @@

-home · -download · +home · +download · installation · introduction · reference @@ -94,6 +94,24 @@ This constant is set to true if the library was compiled with debug support.

+ + +

+socket.gettime() +

+ +

+Returns the time in seconds, relative to the origin of the +universe. You should subtract the values returned by this function +to get meaningful values. +

+ +
+t = socket.gettime()
+-- do stuff
+print(socket.gettime() - t .. " seconds elapsed")
+
+

@@ -199,6 +217,15 @@ themselves, to simplify the test if a specific socket has changed status.

+

+Note: : select can monitor a limited number +of sockets, as defined by the constant socket._SETSIZE. This +number may be as high as 1024 or as low as 64 by default, +depending on the system. It is usually possible to change this +at compile time. Invoking select with a larger +number of sockets will raise an error. +

+

Important note: a known bug in WinSock causes select to fail on non-blocking TCP sockets. The function may return a socket as @@ -288,8 +315,8 @@ Freezes the program execution during a given amount of time.

-Time is the number of seconds to sleep for. -The function truncates time down to the nearest integer. +Time is the number of seconds to sleep for. If +time is negative, the function returns immediately.

@@ -324,24 +351,17 @@ side closes the connection. The function returns a source with the appropriate behavior.

- + -

-socket.gettime() +

+socket._SETSIZE

-Returns the time in seconds, relative to the origin of the -universe. You should subtract the values returned by this function -to get meaningful values. +The maximum number of sockets that the select function can handle.

-
-t = socket.gettime()
--- do stuff
-print(socket.gettime() - t .. " seconds elapsed")
-
-

@@ -386,8 +406,8 @@ This constant has a string describing the current LuaSocket version.


-home · -download · +home · +download · installation · introduction · reference diff --git a/doc/tcp.html b/doc/tcp.html index a16a09e..d1d2154 100644 --- a/doc/tcp.html +++ b/doc/tcp.html @@ -24,8 +24,8 @@

-home · -download · +home · +download · installation · introduction · reference @@ -297,12 +297,12 @@ of any received data before return.

If successful, the method returns the received pattern. In case of error, -the method returns nil followed by an error message which -can be the string 'closed' in case the connection was +the method returns nil followed by an error +message, followed by a (possibly empty) string containing +the partial that was received. The error message can be +the string 'closed' in case the connection was closed before the transmission was completed or the string 'timeout' in case there was a timeout during the operation. -Also, after the error message, the function returns the partial result of -the transmission.

@@ -514,8 +514,8 @@ This function returns 1.


-home · -download · +home · +download · installation · introduction · reference diff --git a/doc/udp.html b/doc/udp.html index 688649d..eca881d 100644 --- a/doc/udp.html +++ b/doc/udp.html @@ -24,8 +24,8 @@

-home · -download · +home · +download · installation · introduction · reference @@ -397,8 +397,8 @@ imperative nature obvious.


-home · -download · +home · +download · installation · introduction · reference diff --git a/doc/url.html b/doc/url.html index e87126f..303e05d 100644 --- a/doc/url.html +++ b/doc/url.html @@ -24,8 +24,8 @@

-home · -download · +home · +download · installation · introduction · reference @@ -310,8 +310,8 @@ The function returns the decoded string.


-home · -download · +home · +download · installation · introduction · reference diff --git a/etc/dispatch.lua b/etc/dispatch.lua index 3ef1e72..5236f3d 100644 --- a/etc/dispatch.lua +++ b/etc/dispatch.lua @@ -54,7 +54,7 @@ function socket.protect(f) local results = {coroutine.resume(co, base.unpack(arg))} local status = table.remove(results, 1) if not status then - if type(results[1]) == 'table' then + if base.type(results[1]) == 'table' then return nil, results[1][1] else base.error(results[1]) end end diff --git a/luasocket.sln b/luasocket.sln index a674c33..76b175b 100644 --- a/luasocket.sln +++ b/luasocket.sln @@ -1,37 +1,25 @@ -Microsoft Visual Studio Solution File, Format Version 8.00 +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "socket", "socket.vcproj", "{66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mime", "mime.vcproj", "{128E8BD0-174A-48F0-8771-92B1E8D18713}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libluasocket", "libluasocket.vcproj", "{599EAD40-60EE-4043-9C14-AE090A8A092D}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection EndProject Global - GlobalSection(SolutionConfiguration) = preSolution - Debug = Debug - Release = Release + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 EndGlobalSection - GlobalSection(ProjectConfiguration) = postSolution - {66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}.Debug.ActiveCfg = Debug|Win32 - {66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}.Debug.Build.0 = Debug|Win32 - {66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}.Release.ActiveCfg = Release|Win32 - {66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}.Release.Build.0 = Release|Win32 - {128E8BD0-174A-48F0-8771-92B1E8D18713}.Debug.ActiveCfg = Debug|Win32 - {128E8BD0-174A-48F0-8771-92B1E8D18713}.Debug.Build.0 = Debug|Win32 - {128E8BD0-174A-48F0-8771-92B1E8D18713}.Release.ActiveCfg = Release|Win32 - {128E8BD0-174A-48F0-8771-92B1E8D18713}.Release.Build.0 = Release|Win32 - {599EAD40-60EE-4043-9C14-AE090A8A092D}.Debug.ActiveCfg = Debug|Win32 - {599EAD40-60EE-4043-9C14-AE090A8A092D}.Debug.Build.0 = Debug|Win32 - {599EAD40-60EE-4043-9C14-AE090A8A092D}.Release.ActiveCfg = Release|Win32 - {599EAD40-60EE-4043-9C14-AE090A8A092D}.Release.Build.0 = Release|Win32 + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}.Debug|Win32.ActiveCfg = Debug|Win32 + {66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}.Debug|Win32.Build.0 = Debug|Win32 + {66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}.Release|Win32.ActiveCfg = Release|Win32 + {66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}.Release|Win32.Build.0 = Release|Win32 + {128E8BD0-174A-48F0-8771-92B1E8D18713}.Debug|Win32.ActiveCfg = Debug|Win32 + {128E8BD0-174A-48F0-8771-92B1E8D18713}.Debug|Win32.Build.0 = Debug|Win32 + {128E8BD0-174A-48F0-8771-92B1E8D18713}.Release|Win32.ActiveCfg = Release|Win32 + {128E8BD0-174A-48F0-8771-92B1E8D18713}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE EndGlobalSection EndGlobal diff --git a/makefile b/makefile index 6d70039..a9ce34d 100644 --- a/makefile +++ b/makefile @@ -1,51 +1,23 @@ -#------ -# Load configuration -# -include config +PLAT= none +PLATS= macosx linux #------ # Hopefully no need to change anything below this line # -INSTALL_SOCKET_SHARE=$(INSTALL_TOP_SHARE)/socket -INSTALL_SOCKET_LIB=$(INSTALL_TOP_LIB)/socket -INSTALL_MIME_SHARE=$(INSTALL_TOP_SHARE)/mime -INSTALL_MIME_LIB=$(INSTALL_TOP_LIB)/mime +all: $(PLAT) -all clean: +none: + @echo "Please run" + @echo " make PLATFORM" + @echo "where PLATFORM is one of these:" + @echo " $(PLATS)" + +$(PLATS) install local clean: cd src; $(MAKE) $@ -#------ -# Files to install -# -TO_SOCKET_SHARE:= \ - http.lua \ - url.lua \ - tp.lua \ - ftp.lua \ - smtp.lua +dummy: -TO_TOP_SHARE:= \ - ltn12.lua \ - socket.lua \ - mime.lua +test: dummy + lua test/hello.lua -TO_MIME_SHARE:= - -#------ -# Install LuaSocket according to recommendation -# -install: all - cd src; mkdir -p $(INSTALL_TOP_SHARE) - cd src; $(INSTALL_DATA) $(TO_TOP_SHARE) $(INSTALL_TOP_SHARE) - cd src; mkdir -p $(INSTALL_SOCKET_SHARE) - cd src; $(INSTALL_DATA) $(TO_SOCKET_SHARE) $(INSTALL_SOCKET_SHARE) - cd src; mkdir -p $(INSTALL_SOCKET_LIB) - cd src; $(INSTALL_EXEC) $(SOCKET_SO) $(INSTALL_SOCKET_LIB)/core.$(EXT) - #cd src; mkdir -p $(INSTALL_MIME_SHARE) - #cd src; $(INSTALL_DATA) $(TO_MIME_SHARE) $(INSTALL_MIME_SHARE) - cd src; mkdir -p $(INSTALL_MIME_LIB) - cd src; $(INSTALL_EXEC) $(MIME_SO) $(INSTALL_MIME_LIB)/core.$(EXT) - -#------ -# End of makefile -# +.PHONY: dummy diff --git a/makefile.dist b/makefile.dist index 876cf18..e4f8da8 100644 --- a/makefile.dist +++ b/makefile.dist @@ -1,10 +1,11 @@ #-------------------------------------------------------------------------- # Distribution makefile #-------------------------------------------------------------------------- -DIST = luasocket-2.0.2 +DIST = luasocket-2.0.3 TEST = \ test/README \ + test/hello.lua \ test/testclnt.lua \ test/testsrvr.lua \ test/testsupport.lua @@ -15,6 +16,8 @@ SAMPLES = \ samples/daytimeclnt.lua \ samples/echoclnt.lua \ samples/echosrvr.lua \ + samples/mclisten.lua \ + samples/mcsend.lua \ samples/listener.lua \ samples/lpr.lua \ samples/talker.lua \ @@ -73,12 +76,12 @@ SRC = \ src/mime.lua \ src/smtp.lua \ src/socket.lua \ + src/headers.lua \ src/tp.lua \ src/url.lua MAKE = \ makefile \ - config \ luasocket.sln \ socket.vcproj \ mime.vcproj diff --git a/mime.vcproj b/mime.vcproj index 8ad7900..313cdb1 100644 --- a/mime.vcproj +++ b/mime.vcproj @@ -1,114 +1,179 @@ + Keyword="Win32Proj" + TargetFrameworkVersion="131072" + > + Name="Win32" + /> + + + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + CharacterSet="2" + > + + + + + + Detect64BitPortabilityProblems="false" + DebugInformationFormat="4" + /> + Name="VCManagedResourceCompilerTool" + /> + + + TargetMachine="1" + /> + Name="VCALinkTool" + /> + Name="VCManifestTool" + /> + Name="VCXDCMakeTool" + /> + Name="VCBscMakeTool" + /> + Name="VCFxCopTool" + /> + Name="VCAppVerifierTool" + /> - - - + Name="VCPostBuildEventTool" + /> + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + CharacterSet="2" + > + + + + + + Detect64BitPortabilityProblems="false" + DebugInformationFormat="0" + /> + Name="VCManagedResourceCompilerTool" + /> + + + TargetMachine="1" + /> + Name="VCALinkTool" + /> + Name="VCManifestTool" + /> + Name="VCXDCMakeTool" + /> + Name="VCBscMakeTool" + /> + Name="VCFxCopTool" + /> + Name="VCAppVerifierTool" + /> - - - + Name="VCPostBuildEventTool" + /> @@ -117,24 +182,25 @@ + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" + > + RelativePath="src\mime.c" + > + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" + > + UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" + > - - diff --git a/samples/cddb.lua b/samples/cddb.lua index 883730c..49a1871 100644 --- a/samples/cddb.lua +++ b/samples/cddb.lua @@ -32,7 +32,7 @@ end local host = socket.dns.gethostname() local query = "%s?cmd=cddb+read+%s+%s&hello=LuaSocket+%s+LuaSocket+2.0&proto=6" local url = string.format(query, server, arg[1], arg[2], host) -local body, headers, code = http.get(url) +local body, headers, code = http.request(url) if code == 200 then local data, code, error = parse(body) diff --git a/socket.vcproj b/socket.vcproj index b7c4a08..195eb09 100644 --- a/socket.vcproj +++ b/socket.vcproj @@ -1,116 +1,179 @@ + Keyword="Win32Proj" + TargetFrameworkVersion="131072" + > + Name="Win32" + /> + + + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + CharacterSet="2" + > + + + + + + Detect64BitPortabilityProblems="false" + DebugInformationFormat="4" + /> + Name="VCManagedResourceCompilerTool" + /> + + + TargetMachine="1" + /> + Name="VCALinkTool" + /> + Name="VCManifestTool" + /> + Name="VCXDCMakeTool" + /> + Name="VCBscMakeTool" + /> + Name="VCFxCopTool" + /> + Name="VCAppVerifierTool" + /> - - - + Name="VCPostBuildEventTool" + /> + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + CharacterSet="2" + > + + + + + + Detect64BitPortabilityProblems="false" + DebugInformationFormat="0" + /> + Name="VCManagedResourceCompilerTool" + /> + + + TargetMachine="1" + /> + Name="VCALinkTool" + /> + Name="VCManifestTool" + /> + Name="VCXDCMakeTool" + /> + Name="VCBscMakeTool" + /> + Name="VCFxCopTool" + /> + Name="VCAppVerifierTool" + /> - - - + Name="VCPostBuildEventTool" + /> @@ -119,63 +182,77 @@ + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" + > + RelativePath="src\auxiliar.c" + > + RelativePath="src\buffer.c" + > + RelativePath="src\except.c" + > + RelativePath="src\inet.c" + > + RelativePath="src\io.c" + > + RelativePath="src\luasocket.c" + > + RelativePath="src\options.c" + > + RelativePath="src\select.c" + > + RelativePath="src\tcp.c" + > + RelativePath="src\timeout.c" + > + RelativePath="src\udp.c" + > + RelativePath="src\wsocket.c" + > + Name="Release|Win32" + > + GeneratePreprocessedFile="0" + /> + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" + > + UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" + > - - diff --git a/src/auxiliar.h b/src/auxiliar.h index 8a18bcf..57a2ecc 100644 --- a/src/auxiliar.h +++ b/src/auxiliar.h @@ -27,8 +27,6 @@ * * The mapping from class name to the corresponding metatable and the * reverse mapping are done using lauxlib. -* -* RCS ID: $Id$ \*=========================================================================*/ #include "lua.h" diff --git a/src/buffer.c b/src/buffer.c index de817b2..363da3d 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -166,7 +166,7 @@ static int sendraw(p_buffer buf, const char *data, size_t count, size_t *sent) { size_t total = 0; int err = IO_DONE; while (total < count && err == IO_DONE) { - size_t done; + size_t done = 0; size_t step = (count-total <= STEPSIZE)? count-total: STEPSIZE; err = io->send(io->ctx, data+total, step, &done, tm); total += done; diff --git a/src/buffer.h b/src/buffer.h index 0a4a335..58838d1 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -14,8 +14,6 @@ * * The module is built on top of the I/O abstraction defined in io.h and the * timeout management is done with the timeout.h interface. -* -* RCS ID: $Id$ \*=========================================================================*/ #include "lua.h" diff --git a/src/except.h b/src/except.h index 03e417d..1e7a245 100644 --- a/src/except.h +++ b/src/except.h @@ -24,8 +24,6 @@ * * With these two function, it's easy to write functions that throw * exceptions on error, but that don't interrupt the user script. -* -* RCS ID: $Id$ \*=========================================================================*/ #include "lua.h" diff --git a/src/http.lua b/src/http.lua index 3a386a6..4c27149 100644 --- a/src/http.lua +++ b/src/http.lua @@ -13,6 +13,7 @@ local url = require("socket.url") local ltn12 = require("ltn12") local mime = require("mime") local string = require("string") +local headers = require("socket.headers") local base = _G local table = require("table") module("socket.http") @@ -123,10 +124,11 @@ function metat.__index:sendrequestline(method, uri) return self.try(self.c:send(reqline)) end -function metat.__index:sendheaders(headers) +function metat.__index:sendheaders(tosend) + local canonic = headers.canonic local h = "\r\n" - for i, v in base.pairs(headers) do - h = i .. ": " .. v .. "\r\n" .. h + for f, v in base.pairs(tosend) do + h = (canonic[f] or f) .. ": " .. v .. "\r\n" .. h end self.try(self.c:send(h)) return 1 @@ -254,7 +256,7 @@ local function shouldredirect(reqt, code, headers) return headers.location and string.gsub(headers.location, "%s", "") ~= "" and (reqt.redirect ~= false) and - (code == 301 or code == 302) and + (code == 301 or code == 302 or code == 303 or code == 307) and (not reqt.method or reqt.method == "GET" or reqt.method == "HEAD") and (not reqt.nredirects or reqt.nredirects < 5) end diff --git a/src/inet.h b/src/inet.h index c6d717d..dbc160c 100644 --- a/src/inet.h +++ b/src/inet.h @@ -13,8 +13,6 @@ * getpeername and getsockname functions as seen by Lua programs. * * The Lua functions toip and tohostname are also implemented here. -* -* RCS ID: $Id$ \*=========================================================================*/ #include "lua.h" #include "socket.h" diff --git a/src/io.h b/src/io.h index bff48a6..8cca08a 100644 --- a/src/io.h +++ b/src/io.h @@ -11,8 +11,6 @@ * * The module socket.h implements this interface, and thus the module tcp.h * is very simple. -* -* RCS ID: $Id$ \*=========================================================================*/ #include #include "lua.h" diff --git a/src/luasocket.c b/src/luasocket.c index 142aa95..3b29e8e 100644 --- a/src/luasocket.c +++ b/src/luasocket.c @@ -10,8 +10,6 @@ * involved in setting up both client and server connections. The provided * IO routines, however, follow the Lua style, being very similar to the * standard Lua read and write functions. -* -* RCS ID: $Id$ \*=========================================================================*/ /*=========================================================================*\ diff --git a/src/luasocket.h b/src/luasocket.h index 13134cf..d7a78bb 100644 --- a/src/luasocket.h +++ b/src/luasocket.h @@ -5,16 +5,14 @@ * Networking support for the Lua language * Diego Nehab * 9/11/1999 -* -* RCS ID: $Id$ \*=========================================================================*/ #include "lua.h" /*-------------------------------------------------------------------------*\ * Current socket library version \*-------------------------------------------------------------------------*/ -#define LUASOCKET_VERSION "LuaSocket 2.0.2" -#define LUASOCKET_COPYRIGHT "Copyright (C) 2004-2007 Diego Nehab" +#define LUASOCKET_VERSION "LuaSocket 2.0.3" +#define LUASOCKET_COPYRIGHT "Copyright (C) 1999-2009 Diego Nehab" #define LUASOCKET_AUTHORS "Diego Nehab" /*-------------------------------------------------------------------------*\ diff --git a/src/makefile b/src/makefile index b614f77..3351997 100644 --- a/src/makefile +++ b/src/makefile @@ -1,39 +1,86 @@ -#------ -# Load configuration -# -include ../config +PLAT = none +INSTALL_DATA=cp +INSTALL_EXEC=cp +INSTALL_TOP= /opt/local +LUAINC= $(LUAINC_$(PLAT)) #------ -# Hopefully no need to change anything below this line +# Install directories # +INSTALL_TOP_SHARE=$(INSTALL_TOP)/share/lua/5.1 +INSTALL_TOP_LIB=$(INSTALL_TOP)/lib/lua/5.1 +INSTALL_SOCKET_SHARE=$(INSTALL_TOP_SHARE)/socket +INSTALL_SOCKET_LIB=$(INSTALL_TOP_LIB)/socket +INSTALL_MIME_SHARE=$(INSTALL_TOP_SHARE)/mime +INSTALL_MIME_LIB=$(INSTALL_TOP_LIB)/mime + +#------ +# Output file names +# +EXT=so +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 +# for Mac OS X +LUAINC_macosx= -I/opt/local/include +CC_macosx=gcc +DEF_macosx= -DLUASOCKET_DEBUG -DUNIX_HAS_SUN_LEN \ + -DLUASOCKET_API='__attribute__((visibility("default")))' \ + -DMIME_API='__attribute__((visibility("default")))' +CFLAGS_macosx= $(LUAINC) $(COMPAT) $(DEF) -pedantic -Wall -O2 -fno-common \ + -fvisibility=hidden +LDFLAGS_macosx= -bundle -undefined dynamic_lookup +LD_macosx= export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc + +#------ +# Compiler and linker settings +# for Linux +LUAINC_linux= -I/usr/local/include/lua5.1 +CC_linux=gcc +DEF_linux=-DLUASOCKET_DEBUG \ + -DLUASOCKET_API='__attribute__((visibility("default")))' \ + -DMIME_API='__attribute__((visibility("default")))' +CFLAGS_linux= $(LUAINC) $(DEF) -pedantic -Wall -O2 -fpic \ + -fvisibility=hidden +LDFLAGS_linux=-O -shared -fpic +LD_linux= gcc + +#------ +# Settings selected for platform +# +CC=$(CC_$(PLAT)) +DEF=$(DEF_$(PLAT)) +CFLAGS=$(CFLAGS_$(PLAT)) +LDFLAGS=$(LDFLAGS_$(PLAT)) +LD=$(LD_$(PLAT)) #------ # Modules belonging to socket-core # - -#$(COMPAT)/compat-5.1.o \ - -SOCKET_OBJS:= \ +SOCKET_OBJS= \ luasocket.o \ timeout.o \ buffer.o \ io.o \ - auxiliar.o \ + auxiliar.o \ options.o \ inet.o \ - tcp.o \ - udp.o \ + usocket.o \ except.o \ select.o \ - usocket.o + tcp.o \ + udp.o #------ # Modules belonging mime-core # -#$(COMPAT)/compat-5.1.o \ - -MIME_OBJS:=\ - mime.o +MIME_OBJS= \ + mime.o #------ # Modules belonging unix (local domain sockets) @@ -47,7 +94,35 @@ UNIX_OBJS:=\ usocket.o \ unix.o -all: $(SOCKET_SO) $(MIME_SO) +#------ +# Files to install +# +TO_SOCKET_SHARE:= \ + http.lua \ + url.lua \ + tp.lua \ + ftp.lua \ + headers.lua \ + smtp.lua + +TO_TOP_SHARE:= \ + ltn12.lua \ + socket.lua \ + mime.lua + +default: $(PLAT) + +macosx: + $(MAKE) all PLAT=macosx + +linux: + $(MAKE) all PLAT=linux + +none: + @echo "Please choose a platform:" + @echo " $(PLATS)" + +all: $(SOCKET_SO) $(MIME_SO) $(SOCKET_SO): $(SOCKET_OBJS) $(LD) $(LDFLAGS) -o $@ $(SOCKET_OBJS) @@ -58,6 +133,25 @@ $(MIME_SO): $(MIME_OBJS) $(UNIX_SO): $(UNIX_OBJS) $(LD) $(LDFLAGS) -o $@ $(UNIX_OBJS) +install: + mkdir -p $(INSTALL_TOP_SHARE) + $(INSTALL_DATA) $(TO_TOP_SHARE) $(INSTALL_TOP_SHARE) + mkdir -p $(INSTALL_SOCKET_SHARE) + $(INSTALL_DATA) $(TO_SOCKET_SHARE) $(INSTALL_SOCKET_SHARE) + mkdir -p $(INSTALL_SOCKET_LIB) + $(INSTALL_EXEC) $(SOCKET_SO) $(INSTALL_SOCKET_LIB)/core.$(EXT) + mkdir -p $(INSTALL_MIME_LIB) + $(INSTALL_EXEC) $(MIME_SO) $(INSTALL_MIME_LIB)/core.$(EXT) + +local: + $(MAKE) install INSTALL_TOP_LIB=.. INSTALL_TOP_SHARE=.. + +clean: + rm -f $(SOCKET_SO) $(SOCKET_OBJS) + rm -f $(MIME_SO) $(UNIX_SO) $(MIME_OBJS) $(UNIX_OBJS) + +.PHONY: all $(PLATS) default clean echo none + #------ # List of dependencies # @@ -66,25 +160,19 @@ buffer.o: buffer.c buffer.h io.h timeout.h except.o: except.c except.h inet.o: inet.c inet.h socket.h io.h timeout.h usocket.h io.o: io.c io.h timeout.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 udp.h select.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 \ + udp.h select.h mime.o: mime.c mime.h -options.o: options.c auxiliar.h options.h socket.h io.h timeout.h \ - usocket.h inet.h +options.o: options.c auxiliar.h options.h socket.h io.h \ + timeout.h usocket.h inet.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 inet.h \ - options.h tcp.h buffer.h +tcp.o: tcp.c auxiliar.h socket.h io.h timeout.h usocket.h \ + inet.h options.h tcp.h buffer.h timeout.o: timeout.c auxiliar.h timeout.h -udp.o: udp.c auxiliar.h socket.h io.h timeout.h usocket.h inet.h \ - options.h udp.h -unix.o: unix.c auxiliar.h socket.h io.h timeout.h usocket.h options.h \ - unix.h buffer.h +udp.o: udp.c auxiliar.h socket.h io.h timeout.h usocket.h \ + inet.h options.h udp.h +unix.o: unix.c auxiliar.h socket.h io.h timeout.h usocket.h \ + options.h unix.h buffer.h usocket.o: usocket.c socket.h io.h timeout.h usocket.h - -clean: - rm -f $(SOCKET_SO) $(SOCKET_OBJS) - rm -f $(MIME_SO) $(UNIX_SO) $(MIME_OBJS) $(UNIX_OBJS) - -#------ -# End of makefile configuration -# +wsocket.o: wsocket.c socket.h io.h timeout.h usocket.h diff --git a/src/mime.c b/src/mime.c index a41bf40..1e8fded 100644 --- a/src/mime.c +++ b/src/mime.c @@ -272,9 +272,12 @@ static int mime_global_b64(lua_State *L) input = (UC *) luaL_optlstring(L, 2, NULL, &isize); /* if second part is nil, we are done */ if (!input) { + size_t osize = 0; asize = b64pad(atom, asize, &buffer); luaL_pushresult(&buffer); - if (!(*lua_tostring(L, -1))) lua_pushnil(L); + /* if the output is empty and the input is nil, return nil */ + lua_tolstring(L, -1, &osize); + if (osize == 0) lua_pushnil(L); lua_pushnil(L); return 2; } @@ -313,8 +316,11 @@ static int mime_global_unb64(lua_State *L) input = (UC *) luaL_optlstring(L, 2, NULL, &isize); /* if second is nil, we are done */ if (!input) { + size_t osize = 0; luaL_pushresult(&buffer); - if (!(*lua_tostring(L, -1))) lua_pushnil(L); + /* if the output is empty and the input is nil, return nil */ + lua_tolstring(L, -1, &osize); + if (osize == 0) lua_pushnil(L); lua_pushnil(L); return 2; } diff --git a/src/mime.h b/src/mime.h index 0fe8000..37f370f 100644 --- a/src/mime.h +++ b/src/mime.h @@ -7,16 +7,14 @@ * This module provides functions to implement transfer content encodings * and formatting conforming to RFC 2045. It is used by mime.lua, which * provide a higher level interface to this functionality. -* -* RCS ID: $Id$ \*=========================================================================*/ #include "lua.h" /*-------------------------------------------------------------------------*\ * Current MIME library version \*-------------------------------------------------------------------------*/ -#define MIME_VERSION "MIME 1.0.2" -#define MIME_COPYRIGHT "Copyright (C) 2004-2007 Diego Nehab" +#define MIME_VERSION "MIME 1.0.3" +#define MIME_COPYRIGHT "Copyright (C) 2004-2009 Diego Nehab" #define MIME_AUTHORS "Diego Nehab" /*-------------------------------------------------------------------------*\ diff --git a/src/options.c b/src/options.c index a464a4b..1d4c950 100644 --- a/src/options.c +++ b/src/options.c @@ -12,12 +12,12 @@ #include "options.h" #include "inet.h" - /*=========================================================================*\ * Internal functions prototypes \*=========================================================================*/ static int opt_setmembership(lua_State *L, p_socket ps, int level, int name); static int opt_setboolean(lua_State *L, p_socket ps, int level, int name); +static int opt_getboolean(lua_State *L, p_socket ps, int level, int name); static int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len); @@ -40,39 +40,63 @@ int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps) return opt->func(L, ps); } +int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps) +{ + const char *name = luaL_checkstring(L, 2); /* obj, name, ... */ + while (opt->name && strcmp(name, opt->name)) + opt++; + if (!opt->func) { + char msg[45]; + sprintf(msg, "unsupported option `%.35s'", name); + luaL_argerror(L, 2, msg); + } + return opt->func(L, ps); +} + /* enables reuse of local address */ -int opt_reuseaddr(lua_State *L, p_socket ps) +int opt_set_reuseaddr(lua_State *L, p_socket ps) { return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEADDR); } +/* enables reuse of local port */ +int opt_set_reuseport(lua_State *L, p_socket ps) +{ + return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEPORT); +} + /* disables the Naggle algorithm */ -int opt_tcp_nodelay(lua_State *L, p_socket ps) +int opt_set_tcp_nodelay(lua_State *L, p_socket ps) { return opt_setboolean(L, ps, IPPROTO_TCP, TCP_NODELAY); } -int opt_keepalive(lua_State *L, p_socket ps) +int opt_set_keepalive(lua_State *L, p_socket ps) { return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE); } -int opt_dontroute(lua_State *L, p_socket ps) +int opt_set_dontroute(lua_State *L, p_socket ps) { return opt_setboolean(L, ps, SOL_SOCKET, SO_DONTROUTE); } -int opt_broadcast(lua_State *L, p_socket ps) +int opt_set_broadcast(lua_State *L, p_socket ps) { return opt_setboolean(L, ps, SOL_SOCKET, SO_BROADCAST); } -int opt_ip_multicast_loop(lua_State *L, p_socket ps) +int opt_set_ip_multicast_loop(lua_State *L, p_socket ps) { return opt_setboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP); } -int opt_linger(lua_State *L, p_socket ps) +int opt_get_ip_multicast_loop(lua_State *L, p_socket ps) +{ + return opt_getboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP); +} + +int opt_set_linger(lua_State *L, p_socket ps) { struct linger li; /* obj, name, table */ if (!lua_istable(L, 3)) luaL_typerror(L, 3, lua_typename(L, LUA_TTABLE)); @@ -89,18 +113,43 @@ int opt_linger(lua_State *L, p_socket ps) return opt_set(L, ps, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof(li)); } -int opt_ip_multicast_ttl(lua_State *L, p_socket ps) +int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps) { int val = (int) luaL_checknumber(L, 3); /* obj, name, int */ - return opt_set(L, ps, SOL_SOCKET, SO_LINGER, (char *) &val, sizeof(val)); + return opt_set(L, ps, IPPROTO_IP, IP_MULTICAST_TTL, + (char *) &val, sizeof(val)); } -int opt_ip_add_membership(lua_State *L, p_socket ps) +int opt_set_ip_multicast_if(lua_State *L, p_socket ps) +{ + const char *address = luaL_checkstring(L, 3); /* obj, name, ip */ + struct in_addr val; + val.s_addr = htonl(INADDR_ANY); + if (strcmp(address, "*") && !inet_aton(address, &val)) + luaL_argerror(L, 3, "ip expected"); + return opt_set(L, ps, IPPROTO_IP, IP_MULTICAST_IF, + (char *) &val, sizeof(val)); +} + +int opt_get_ip_multicast_if(lua_State *L, p_socket ps) +{ + struct in_addr val; + socklen_t len = sizeof(val); + if (getsockopt(*ps, IPPROTO_IP, IP_MULTICAST_IF, (char *) &val, &len) < 0) { + lua_pushnil(L); + lua_pushstring(L, "getsockopt failed"); + return 2; + } + lua_pushstring(L, inet_ntoa(val)); + return 1; +} + +int opt_set_ip_add_membership(lua_State *L, p_socket ps) { return opt_setmembership(L, ps, IPPROTO_IP, IP_ADD_MEMBERSHIP); } -int opt_ip_drop_membersip(lua_State *L, p_socket ps) +int opt_set_ip_drop_membersip(lua_State *L, p_socket ps) { return opt_setmembership(L, ps, IPPROTO_IP, IP_DROP_MEMBERSHIP); } @@ -141,6 +190,19 @@ int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len) return 1; } +static int opt_getboolean(lua_State *L, p_socket ps, int level, int name) +{ + int val = 0; + socklen_t len = sizeof(val); + if (getsockopt(*ps, level, name, (char *) &val, &len) < 0) { + lua_pushnil(L); + lua_pushstring(L, "getsockopt failed"); + return 2; + } + lua_pushboolean(L, val); + return 1; +} + static int opt_setboolean(lua_State *L, p_socket ps, int level, int name) { int val = auxiliar_checkboolean(L, 3); /* obj, name, bool */ diff --git a/src/options.h b/src/options.h index 900761e..aa43cab 100644 --- a/src/options.h +++ b/src/options.h @@ -6,8 +6,6 @@ * * This module provides a common interface to socket options, used mainly by * modules UDP and TCP. -* -* RCS ID: $Id$ \*=========================================================================*/ #include "lua.h" @@ -20,20 +18,28 @@ typedef struct t_opt { } t_opt; typedef t_opt *p_opt; -/* supported options */ -int opt_dontroute(lua_State *L, p_socket ps); -int opt_broadcast(lua_State *L, p_socket ps); -int opt_reuseaddr(lua_State *L, p_socket ps); -int opt_tcp_nodelay(lua_State *L, p_socket ps); -int opt_keepalive(lua_State *L, p_socket ps); -int opt_linger(lua_State *L, p_socket ps); -int opt_reuseaddr(lua_State *L, p_socket ps); -int opt_ip_multicast_ttl(lua_State *L, p_socket ps); -int opt_ip_multicast_loop(lua_State *L, p_socket ps); -int opt_ip_add_membership(lua_State *L, p_socket ps); -int opt_ip_drop_membersip(lua_State *L, p_socket ps); - +/* supported options for setoption */ +int opt_set_dontroute(lua_State *L, p_socket ps); +int opt_set_broadcast(lua_State *L, p_socket ps); +int opt_set_reuseaddr(lua_State *L, p_socket ps); +int opt_set_tcp_nodelay(lua_State *L, p_socket ps); +int opt_set_keepalive(lua_State *L, p_socket ps); +int opt_set_linger(lua_State *L, p_socket ps); +int opt_set_reuseaddr(lua_State *L, p_socket ps); +int opt_set_reuseport(lua_State *L, p_socket ps); +int opt_set_ip_multicast_if(lua_State *L, p_socket ps); +int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps); +int opt_set_ip_multicast_loop(lua_State *L, p_socket ps); +int opt_set_ip_add_membership(lua_State *L, p_socket ps); +int opt_set_ip_drop_membersip(lua_State *L, p_socket ps); /* invokes the appropriate option handler */ int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps); +/* supported options for getoption */ +int opt_get_ip_multicast_loop(lua_State *L, p_socket ps); +int opt_get_ip_multicast_if(lua_State *L, p_socket ps); +/* invokes the appropriate option handler */ +int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps); + + #endif diff --git a/src/select.c b/src/select.c index 99b59f5..8e47d0e 100644 --- a/src/select.c +++ b/src/select.c @@ -18,8 +18,8 @@ \*=========================================================================*/ static t_socket getfd(lua_State *L); static int dirty(lua_State *L); -static t_socket collect_fd(lua_State *L, int tab, t_socket max_fd, - int itab, fd_set *set); +static void collect_fd(lua_State *L, int tab, int itab, + fd_set *set, t_socket *max_fd); static int check_dirty(lua_State *L, int tab, int dtab, fd_set *set); static void return_fd(lua_State *L, fd_set *set, t_socket max_fd, int itab, int tab, int start); @@ -39,6 +39,9 @@ static luaL_reg func[] = { * Initializes module \*-------------------------------------------------------------------------*/ int select_open(lua_State *L) { + lua_pushstring(L, "_SETSIZE"); + lua_pushnumber(L, FD_SETSIZE); + lua_rawset(L, -3); luaL_openlib(L, NULL, func, 0); return 0; } @@ -51,7 +54,7 @@ int select_open(lua_State *L) { \*-------------------------------------------------------------------------*/ static int global_select(lua_State *L) { int rtab, wtab, itab, ret, ndirty; - t_socket max_fd; + t_socket max_fd = SOCKET_INVALID; fd_set rset, wset; t_timeout tm; double t = luaL_optnumber(L, 3, -1); @@ -60,12 +63,12 @@ static int global_select(lua_State *L) { lua_newtable(L); itab = lua_gettop(L); lua_newtable(L); rtab = lua_gettop(L); lua_newtable(L); wtab = lua_gettop(L); - max_fd = collect_fd(L, 1, SOCKET_INVALID, itab, &rset); + collect_fd(L, 1, itab, &rset, &max_fd); + collect_fd(L, 2, itab, &wset, &max_fd); ndirty = check_dirty(L, 1, rtab, &rset); t = ndirty > 0? 0.0: t; timeout_init(&tm, t, -1); timeout_markstart(&tm); - max_fd = collect_fd(L, 2, max_fd, itab, &wset); ret = socket_select(max_fd+1, &rset, &wset, NULL, &tm); if (ret > 0 || ndirty > 0) { return_fd(L, &rset, max_fd+1, itab, rtab, ndirty); @@ -77,7 +80,7 @@ static int global_select(lua_State *L) { lua_pushstring(L, "timeout"); return 3; } else { - lua_pushstring(L, "error"); + luaL_error(L, "select failed"); return 3; } } @@ -112,11 +115,13 @@ static int dirty(lua_State *L) { return is; } -static t_socket collect_fd(lua_State *L, int tab, t_socket max_fd, - int itab, fd_set *set) { - int i = 1; - if (lua_isnil(L, tab)) - return max_fd; +static void collect_fd(lua_State *L, int tab, int itab, + fd_set *set, t_socket *max_fd) { + int i = 1, n = 0; + /* nil is the same as an empty table */ + if (lua_isnil(L, tab)) return; + /* otherwise we need it to be a table */ + luaL_checktype(L, tab, LUA_TTABLE); while (1) { t_socket fd; lua_pushnumber(L, i); @@ -125,11 +130,18 @@ static t_socket collect_fd(lua_State *L, int tab, t_socket max_fd, lua_pop(L, 1); break; } + /* getfd figures out if this is a socket */ fd = getfd(L); if (fd != SOCKET_INVALID) { + /* make sure we don't overflow the fd_set */ + if (n >= FD_SETSIZE) + luaL_argerror(L, tab, "too many sockets"); FD_SET(fd, set); - if (max_fd == SOCKET_INVALID || max_fd < fd) - max_fd = fd; + n++; + /* keep track of the largest descriptor so far */ + if (*max_fd == SOCKET_INVALID || *max_fd < fd) + *max_fd = fd; + /* make sure we can map back from descriptor to the object */ lua_pushnumber(L, fd); lua_pushvalue(L, -2); lua_settable(L, itab); @@ -137,7 +149,6 @@ static t_socket collect_fd(lua_State *L, int tab, t_socket max_fd, lua_pop(L, 1); i = i + 1; } - return max_fd; } static int check_dirty(lua_State *L, int tab, int dtab, fd_set *set) { diff --git a/src/select.h b/src/select.h index f2d2cc2..8750200 100644 --- a/src/select.h +++ b/src/select.h @@ -8,8 +8,6 @@ * method getfd() which returns the descriptor to be passed to the * underlying select function. Another method, dirty(), should return * true if there is data ready for reading (required for buffered input). -* -* RCS ID: $Id$ \*=========================================================================*/ int select_open(lua_State *L); diff --git a/src/smtp.lua b/src/smtp.lua index 9a204d8..b39f5d6 100644 --- a/src/smtp.lua +++ b/src/smtp.lua @@ -16,6 +16,7 @@ local os = require("os") local socket = require("socket") local tp = require("socket.tp") local ltn12 = require("ltn12") +local headers = require("socket.headers") local mime = require("mime") module("socket.smtp") @@ -146,10 +147,11 @@ end local send_message -- yield the headers all at once, it's faster -local function send_headers(headers) +local function send_headers(tosend) + local canonic = headers.canonic local h = "\r\n" - for i,v in base.pairs(headers) do - h = i .. ': ' .. v .. "\r\n" .. h + for f,v in base.pairs(tosend) do + h = (canonic[f] or f) .. ': ' .. v .. "\r\n" .. h end coroutine.yield(h) end diff --git a/src/socket.h b/src/socket.h index de5d79f..425628d 100644 --- a/src/socket.h +++ b/src/socket.h @@ -8,8 +8,6 @@ * differences. Also, not all *nix platforms behave the same. This module * (and the associated usocket.h and wsocket.h) factor these differences and * creates a interface compatible with the io.h module. -* -* RCS ID: $Id$ \*=========================================================================*/ #include "io.h" diff --git a/src/tcp.c b/src/tcp.c index 539ad5e..06d687b 100644 --- a/src/tcp.c +++ b/src/tcp.c @@ -64,11 +64,11 @@ static luaL_reg tcp[] = { }; /* socket option handlers */ -static t_opt opt[] = { - {"keepalive", opt_keepalive}, - {"reuseaddr", opt_reuseaddr}, - {"tcp-nodelay", opt_tcp_nodelay}, - {"linger", opt_linger}, +static t_opt optset[] = { + {"keepalive", opt_set_keepalive}, + {"reuseaddr", opt_set_reuseaddr}, + {"tcp-nodelay", opt_set_tcp_nodelay}, + {"linger", opt_set_linger}, {NULL, NULL} }; @@ -128,7 +128,7 @@ static int meth_setstats(lua_State *L) { static int meth_setoption(lua_State *L) { p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - return opt_meth_setoption(L, opt, &tcp->sock); + return opt_meth_setoption(L, optset, &tcp->sock); } /*-------------------------------------------------------------------------*\ diff --git a/src/tcp.h b/src/tcp.h index 7e98ab6..a536b49 100644 --- a/src/tcp.h +++ b/src/tcp.h @@ -13,8 +13,6 @@ * objects are tcp objects bound to some local address. Client objects are * tcp objects either connected to some address or returned by the accept * method of a server object. -* -* RCS ID: $Id$ \*=========================================================================*/ #include "lua.h" diff --git a/src/timeout.c b/src/timeout.c index 863546e..fb015f9 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -5,6 +5,8 @@ * RCS ID: $Id$ \*=========================================================================*/ #include +#include +#include #include "lua.h" #include "lauxlib.h" @@ -187,13 +189,23 @@ static int timeout_lua_gettime(lua_State *L) /*-------------------------------------------------------------------------*\ * Sleep for n seconds. \*-------------------------------------------------------------------------*/ +#ifdef _WIN32 int timeout_lua_sleep(lua_State *L) { double n = luaL_checknumber(L, 1); -#ifdef _WIN32 - Sleep((int)(n*1000)); + if (n < 0.0) n = 0.0; + if (n < DBL_MAX/1000.0) n *= 1000.0; + if (n > INT_MAX) n = INT_MAX; + Sleep((int)n); + return 0; +} #else +int timeout_lua_sleep(lua_State *L) +{ + double n = luaL_checknumber(L, 1); struct timespec t, r; + if (n < 0.0) n = 0.0; + if (n > INT_MAX) n = INT_MAX; t.tv_sec = (int) n; n -= t.tv_sec; t.tv_nsec = (int) (n * 1000000000); @@ -202,6 +214,6 @@ int timeout_lua_sleep(lua_State *L) t.tv_sec = r.tv_sec; t.tv_nsec = r.tv_nsec; } -#endif return 0; } +#endif diff --git a/src/timeout.h b/src/timeout.h index a328bcc..6715ca7 100644 --- a/src/timeout.h +++ b/src/timeout.h @@ -3,8 +3,6 @@ /*=========================================================================*\ * Timeout management functions * LuaSocket toolkit -* -* RCS ID: $Id$ \*=========================================================================*/ #include "lua.h" diff --git a/src/tp.lua b/src/tp.lua index 2eacdc4..5fd8d22 100644 --- a/src/tp.lua +++ b/src/tp.lua @@ -64,6 +64,7 @@ function metat.__index:check(ok) end function metat.__index:command(cmd, arg) + cmd = string.upper(cmd) if arg then return self.c:send(cmd .. " " .. arg.. "\r\n") else diff --git a/src/udp.c b/src/udp.c index e604bea..db519ca 100644 --- a/src/udp.c +++ b/src/udp.c @@ -37,6 +37,7 @@ static int meth_setsockname(lua_State *L); static int meth_setpeername(lua_State *L); static int meth_close(lua_State *L); static int meth_setoption(lua_State *L); +static int meth_getoption(lua_State *L); static int meth_settimeout(lua_State *L); static int meth_getfd(lua_State *L); static int meth_setfd(lua_State *L); @@ -57,22 +58,32 @@ static luaL_reg udp[] = { {"sendto", meth_sendto}, {"setfd", meth_setfd}, {"setoption", meth_setoption}, + {"getoption", meth_getoption}, {"setpeername", meth_setpeername}, {"setsockname", meth_setsockname}, {"settimeout", meth_settimeout}, {NULL, NULL} }; -/* socket options */ -static t_opt opt[] = { - {"dontroute", opt_dontroute}, - {"broadcast", opt_broadcast}, - {"reuseaddr", opt_reuseaddr}, - {"ip-multicast-ttl", opt_ip_multicast_ttl}, - {"ip-multicast-loop", opt_ip_multicast_loop}, - {"ip-add-membership", opt_ip_add_membership}, - {"ip-drop-membership", opt_ip_drop_membersip}, - {NULL, NULL} +/* socket options for setoption */ +static t_opt optset[] = { + {"dontroute", opt_set_dontroute}, + {"broadcast", opt_set_broadcast}, + {"reuseaddr", opt_set_reuseaddr}, + {"reuseport", opt_set_reuseport}, + {"ip-multicast-if", opt_set_ip_multicast_if}, + {"ip-multicast-ttl", opt_set_ip_multicast_ttl}, + {"ip-multicast-loop", opt_set_ip_multicast_loop}, + {"ip-add-membership", opt_set_ip_add_membership}, + {"ip-drop-membership", opt_set_ip_drop_membersip}, + {NULL, NULL} +}; + +/* socket options for getoption */ +static t_opt optget[] = { + {"ip-multicast-if", opt_get_ip_multicast_if}, + {"ip-multicast-loop", opt_get_ip_multicast_loop}, + {NULL, NULL} }; /* functions in library namespace */ @@ -247,7 +258,15 @@ static int meth_getsockname(lua_State *L) { \*-------------------------------------------------------------------------*/ static int meth_setoption(lua_State *L) { p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - return opt_meth_setoption(L, opt, &udp->sock); + return opt_meth_setoption(L, optset, &udp->sock); +} + +/*-------------------------------------------------------------------------*\ +* Just call option handler +\*-------------------------------------------------------------------------*/ +static int meth_getoption(lua_State *L) { + p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); + return opt_meth_getoption(L, optget, &udp->sock); } /*-------------------------------------------------------------------------*\ diff --git a/src/udp.h b/src/udp.h index d29f833..358d9e1 100644 --- a/src/udp.h +++ b/src/udp.h @@ -11,8 +11,6 @@ * originally unconnected. They can be "connected" to a given address * with a call to the setpeername function. The same function can be used to * break the connection. -* -* RCS ID: $Id$ \*=========================================================================*/ #include "lua.h" diff --git a/src/unix.c b/src/unix.c index 0430086..a309823 100644 --- a/src/unix.c +++ b/src/unix.c @@ -63,10 +63,10 @@ static luaL_reg un[] = { }; /* socket option handlers */ -static t_opt opt[] = { - {"keepalive", opt_keepalive}, - {"reuseaddr", opt_reuseaddr}, - {"linger", opt_linger}, +static t_opt optset[] = { + {"keepalive", opt_set_keepalive}, + {"reuseaddr", opt_set_reuseaddr}, + {"linger", opt_set_linger}, {NULL, NULL} }; @@ -128,7 +128,7 @@ static int meth_setstats(lua_State *L) { \*-------------------------------------------------------------------------*/ static int meth_setoption(lua_State *L) { p_unix un = (p_unix) auxiliar_checkgroup(L, "unix{any}", 1); - return opt_meth_setoption(L, opt, &un->sock); + return opt_meth_setoption(L, optset, &un->sock); } /*-------------------------------------------------------------------------*\ diff --git a/src/unix.h b/src/unix.h index 055b02b..39fa719 100644 --- a/src/unix.h +++ b/src/unix.h @@ -6,8 +6,6 @@ * * This module is just an example of how to extend LuaSocket with a new * domain. -* -* RCS ID: $Id$ \*=========================================================================*/ #include "lua.h" @@ -23,6 +21,6 @@ typedef struct t_unix_ { } t_unix; typedef t_unix *p_unix; -int luaopen_socketunix(lua_State *L); +int luaopen_socket_unix(lua_State *L); #endif /* UNIX_H */ diff --git a/src/usocket.h b/src/usocket.h index e1f7498..75bfe82 100644 --- a/src/usocket.h +++ b/src/usocket.h @@ -3,8 +3,6 @@ /*=========================================================================*\ * Socket compatibilization module for Unix * LuaSocket toolkit -* -* RCS ID: $Id$ \*=========================================================================*/ /*=========================================================================*\ @@ -32,6 +30,10 @@ /* TCP options (nagle algorithm disable) */ #include +#ifndef SO_REUSEPORT +#define SO_REUSEPORT SO_REUSEADDR +#endif + typedef int t_socket; typedef t_socket *p_socket; diff --git a/src/wsocket.h b/src/wsocket.h index e4f0e92..8e0f114 100644 --- a/src/wsocket.h +++ b/src/wsocket.h @@ -3,14 +3,13 @@ /*=========================================================================*\ * Socket compatibilization module for Win32 * LuaSocket toolkit -* -* RCS ID: $Id$ \*=========================================================================*/ /*=========================================================================*\ * WinSock include files \*=========================================================================*/ -#include +#include +#include typedef int socklen_t; typedef SOCKET t_socket; @@ -18,4 +17,8 @@ typedef t_socket *p_socket; #define SOCKET_INVALID (INVALID_SOCKET) +#ifndef SO_REUSEPORT +#define SO_REUSEPORT SO_REUSEADDR +#endif + #endif /* WSOCKET_H */ diff --git a/test/README b/test/README index 180fa27..27837e0 100644 --- a/test/README +++ b/test/README @@ -8,5 +8,7 @@ The files provided are: To run these tests, just run lua on the server and then on the client. + hello.lua -- run to verify if installation worked + Good luck, Diego. diff --git a/test/hello.lua b/test/hello.lua new file mode 100644 index 0000000..cfa5c82 --- /dev/null +++ b/test/hello.lua @@ -0,0 +1,3 @@ +require"socket" +require"mime" +print("Hello from " .. socket._VERSION .. " and " .. mime._VERSION .. "!") diff --git a/test/httptest.lua b/test/httptest.lua index dd53ec3..9d50a14 100644 --- a/test/httptest.lua +++ b/test/httptest.lua @@ -420,17 +420,17 @@ print("ok") io.write("testing HEAD method: ") local r, c, h = http.request { method = "HEAD", - url = "http://www.cs.princeton.edu/~diego/" + url = "http://www.tecgraf.puc-rio.br/~diego/" } assert(r and h and (c == 200), c) print("ok") ------------------------------------------------------------------------ io.write("testing host not found: ") -local c, e = socket.connect("wronghost", 80) -local r, re = http.request{url = "http://wronghost/does/not/exist"} -assert(r == nil and e == re) -r, re = http.request("http://wronghost/does/not/exist") +local c, e = socket.connect("example.invalid", 80) +local r, re = http.request{url = "http://example.invalid/does/not/exist"} +assert(r == nil and e == re, tostring(r) .. " " .. tostring(re)) +r, re = http.request("http://example.invalid/does/not/exist") assert(r == nil and e == re) print("ok") diff --git a/test/mimetest.lua b/test/mimetest.lua index f52a351..11c3f4f 100644 --- a/test/mimetest.lua +++ b/test/mimetest.lua @@ -251,6 +251,28 @@ io.write("testing b64 padding: ") print("ok") end +local function test_b64lowlevel() +io.write("testing b64 low-level: ") + local a, b + a, b = mime.b64("", "") + assert(a == "" and b == "") + a, b = mime.b64(nil, "blablabla") + assert(a == nil and b == nil) + a, b = mime.b64("", nil) + assert(a == nil and b == nil) + a, b = mime.unb64("", "") + assert(a == "" and b == "") + a, b = mime.unb64(nil, "blablabla") + assert(a == nil and b == nil) + a, b = mime.unb64("", nil) + assert(a == nil and b == nil) + local binary=string.char(0x00,0x44,0x1D,0x14,0x0F,0xF4,0xDA,0x11,0xA9,0x78,0x00,0x14,0x38,0x50,0x60,0xCE) + local encoded = mime.b64(binary) + local decoded=mime.unb64(encoded) + assert(binary == decoded) + print("ok") +end + local t = socket.gettime() create_b64test() @@ -260,6 +282,7 @@ decode_b64test() compare_b64test() cleanup_b64test() padding_b64test() +test_b64lowlevel() create_qptest() encode_qptest() @@ -270,4 +293,5 @@ decode_qptest() compare_qptest() cleanup_qptest() + print(string.format("done in %.2fs", socket.gettime() - t)) diff --git a/test/testclnt.lua b/test/testclnt.lua index a7ca1ba..1f03b10 100644 --- a/test/testclnt.lua +++ b/test/testclnt.lua @@ -342,6 +342,7 @@ end ------------------------------------------------------------------------ function test_selectbugs() local r, s, e = socket.select(nil, nil, 0.1) +print(r, s, e) assert(type(r) == "table" and type(s) == "table" and (e == "timeout" or e == "error")) pass("both nil: ok") @@ -352,10 +353,23 @@ function test_selectbugs() (e == "timeout" or e == "error")) pass("closed sockets: ok") e = pcall(socket.select, "wrong", 1, 0.1) - assert(e == false) + assert(e == false, tostring(e)) e = pcall(socket.select, {}, 1, 0.1) - assert(e == false) + assert(e == false, tostring(e)) pass("invalid input: ok") + local toomany = {} + for i = 1, socket._SETSIZE+1 do + toomany[#toomany+1] = socket.udp() + end + if #toomany > socket._SETSIZE then + local e = pcall(socket.select, toomany, nil, 0.1) + assert(e == false, tostring(e)) + pass("too many sockets (" .. #toomany .. "): ok") + else + pass("unable to create enough sockets (max was "..#toomany..")") + pass("try using ulimit") + end + for _, c in ipairs(toomany) do c:close() end end ------------------------------------------------------------------------ @@ -555,6 +569,25 @@ function test_readafterclose() print("ok") end +------------------------------------------------------------------------ +function test_writeafterclose() + local str = 'little string' + reconnect() + remote (string.format ([[ + data:close() + data = nil + ]])) + local sent, err, errsent + while not err do + sent, err, errsent, time = data:send(str) + end + print(sent, err, errsent, time) + print("ok") +end + +------------------------------------------------------------------------ +--test_writeafterclose() + test("method registration") test_methods(socket.tcp(), { "accept", @@ -596,12 +629,12 @@ test_methods(socket.udp(), { "settimeout" }) -test("testing read after close") -test_readafterclose() - test("select function") test_selectbugs() +test("testing read after close") +test_readafterclose() + test("connect function") connect_timeout() empty_connect() diff --git a/test/testmesg.lua b/test/testmesg.lua index 580693b..135a008 100644 --- a/test/testmesg.lua +++ b/test/testmesg.lua @@ -32,6 +32,8 @@ r, e = smtp.send{ port = 2525 } +print(r, e) + -- creates a source to send a message with two parts. The first part is -- plain text, the second part is a PNG image, encoded as base64. source = smtp.message{