aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2004-11-27 07:58:04 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2004-11-27 07:58:04 +0000
commit7c97e8e40aaa665226fb54449773dc3134e755b2 (patch)
tree47888d4c924fc24bf3b355bf58120ea3cdc74bc4
parenteb0fc857ddea6f084d338589e2a33d3e7d4eade6 (diff)
downloadluasocket-7c97e8e40aaa665226fb54449773dc3134e755b2.tar.gz
luasocket-7c97e8e40aaa665226fb54449773dc3134e755b2.tar.bz2
luasocket-7c97e8e40aaa665226fb54449773dc3134e755b2.zip
Almost ready for beta3
-rw-r--r--TODO9
-rw-r--r--doc/ftp.html2
-rw-r--r--etc/dict.lua16
-rw-r--r--etc/lp.lua23
-rw-r--r--etc/tftp.lua17
-rw-r--r--luasocket.vcproj16
-rw-r--r--mime.vcproj15
-rw-r--r--src/buffer.c4
-rw-r--r--src/except.c26
-rw-r--r--src/ftp.lua53
-rw-r--r--src/http.lua23
-rw-r--r--src/ltn12.lua22
-rw-r--r--src/mime.lua11
-rw-r--r--src/smtp.lua25
-rw-r--r--src/tcp.c3
-rw-r--r--src/tp.lua29
-rw-r--r--src/udp.c3
-rw-r--r--src/url.lua15
-rw-r--r--src/wsocket.c15
-rw-r--r--test/dicttest.lua2
-rw-r--r--test/ftptest.lua155
-rw-r--r--test/httptest.lua2
-rw-r--r--test/testclnt.lua5
-rw-r--r--test/testmesg.lua7
-rw-r--r--test/testsrvr.lua2
-rw-r--r--test/tftptest.lua2
26 files changed, 311 insertions, 191 deletions
diff --git a/TODO b/TODO
index 7dadfd9..dfb9178 100644
--- a/TODO
+++ b/TODO
@@ -1,14 +1,12 @@
1 1use wim's filter.chain or something better
2make sure standard libraries are "required" by modules before use. 2make sure standard libraries are "required" by modules before use.
3eliminate globals from namespaces created by module(). 3eliminate globals from namespaces created by module().
4ftp.send/recv return bytes transfered? 4ftp.send/recv return bytes transfered?
5new scheme to choose family/protocol of object to create 5new scheme to choose family/protocol of object to create
6change ltn13 to make sure drawbacks are obvious 6change ltn13 to make sure drawbacks are obvious
7 - check discussion 7 - check discussion
8make sure errors not thrown by try() are not caught by protect()
9use mike's "don't set to blocking before closing unless needed" patch? 8use mike's "don't set to blocking before closing unless needed" patch?
10take a look at DB's smtp patch (add "extra argument" table) 9take a look at DB's smtp patch (add "extra argument" table)
11move wsocket.c:sock_send kludge to buffer.c:sendraw (probably)?
12 10
13optmize aux_getgroupudata (Mike idea) 11optmize aux_getgroupudata (Mike idea)
14 make aux_newclass receive upvalues 12 make aux_newclass receive upvalues
@@ -25,7 +23,10 @@ testar os options!
25 - proteger ou atomizar o conjunto (timedout, receive), (timedout, send) 23 - proteger ou atomizar o conjunto (timedout, receive), (timedout, send)
26 - inet_ntoa também é uma merda. 24 - inet_ntoa também é uma merda.
27 25
28*use wim's filter.chain or something better 26*close wasn't returning 1
27*make sure errors not thrown by try() are not caught by protect()
28*move wsocket.c:sock_send kludge to buffer.c:sendraw?
29*bug on UDP sendto.
29*fix PROXY in http.lua 30*fix PROXY in http.lua
30*use new distribution scheme 31*use new distribution scheme
31*create the getstats method. 32*create the getstats method.
diff --git a/doc/ftp.html b/doc/ftp.html
index 158b402..0b52007 100644
--- a/doc/ftp.html
+++ b/doc/ftp.html
@@ -163,7 +163,7 @@ local ltn12 = require("ltn12")
163local url = require("url") 163local url = require("url")
164 164
165-- a function that returns a directory listing 165-- a function that returns a directory listing
166function ls(u) 166function nlst(u)
167 local t = {} 167 local t = {}
168 local p = url.parse(u) 168 local p = url.parse(u)
169 p.command = "nlst" 169 p.command = "nlst"
diff --git a/etc/dict.lua b/etc/dict.lua
index 8c197f5..716b8db 100644
--- a/etc/dict.lua
+++ b/etc/dict.lua
@@ -8,11 +8,14 @@
8----------------------------------------------------------------------------- 8-----------------------------------------------------------------------------
9-- Load required modules 9-- Load required modules
10----------------------------------------------------------------------------- 10-----------------------------------------------------------------------------
11local base = require("base")
12local string = require("string")
13local table = require("table")
11local socket = require("socket") 14local socket = require("socket")
12local url = require("socket.url") 15local url = require("socket.url")
13local tp = require("socket.tp") 16local tp = require("socket.tp")
14 17
15module("socket.dict") 18local dict = module("socket.dict")
16 19
17----------------------------------------------------------------------------- 20-----------------------------------------------------------------------------
18-- Globals 21-- Globals
@@ -28,7 +31,7 @@ local metat = { __index = {} }
28 31
29function open(host, port) 32function open(host, port)
30 local tp = socket.try(tp.connect(host or HOST, port or PORT, TIMEOUT)) 33 local tp = socket.try(tp.connect(host or HOST, port or PORT, TIMEOUT))
31 return setmetatable({tp = tp}, metat) 34 return base.setmetatable({tp = tp}, metat)
32end 35end
33 36
34function metat.__index:greet() 37function metat.__index:greet()
@@ -37,7 +40,8 @@ end
37 40
38function metat.__index:check(ok) 41function metat.__index:check(ok)
39 local code, status = socket.try(self.tp:check(ok)) 42 local code, status = socket.try(self.tp:check(ok))
40 return code, tonumber(socket.skip(2, string.find(status, "^%d%d%d (%d*)"))) 43 return code,
44 base.tonumber(socket.skip(2, string.find(status, "^%d%d%d (%d*)")))
41end 45end
42 46
43function metat.__index:getdef() 47function metat.__index:getdef()
@@ -116,7 +120,7 @@ local function parse(u)
116 if cmd == "m" then 120 if cmd == "m" then
117 arg = string.gsub(arg, "^:([^:]*)", function(f) t.strat = there(f) end) 121 arg = string.gsub(arg, "^:([^:]*)", function(f) t.strat = there(f) end)
118 end 122 end
119 string.gsub(arg, ":([^:]*)$", function(f) t.n = tonumber(f) end) 123 string.gsub(arg, ":([^:]*)$", function(f) t.n = base.tonumber(f) end)
120 return t 124 return t
121end 125end
122 126
@@ -143,6 +147,8 @@ local function sget(u)
143end 147end
144 148
145get = socket.protect(function(gett) 149get = socket.protect(function(gett)
146 if type(gett) == "string" then return sget(gett) 150 if base.type(gett) == "string" then return sget(gett)
147 else return tget(gett) end 151 else return tget(gett) end
148end) 152end)
153
154base.setmetatable(dict, nil)
diff --git a/etc/lp.lua b/etc/lp.lua
index b69cc02..a5327d1 100644
--- a/etc/lp.lua
+++ b/etc/lp.lua
@@ -9,9 +9,12 @@
9 if you have any questions: RFC 1179 9 if you have any questions: RFC 1179
10]] 10]]
11-- make sure LuaSocket is loaded 11-- make sure LuaSocket is loaded
12local io = require("io")
13local base = require("base")
14local string = require("string")
12local socket = require("socket") 15local socket = require("socket")
13local ltn12 = require("ltn12") 16local ltn12 = require("ltn12")
14local test = socket.try 17local lp = module("socket.lp")
15 18
16-- default port 19-- default port
17PORT = 515 20PORT = 515
@@ -28,7 +31,7 @@ local function connect(localhost, option)
28 local localport = 721 31 local localport = 721
29 local done, err 32 local done, err
30 repeat 33 repeat
31 skt = test(socket.tcp()) 34 skt = socket.try(socket.tcp())
32 try(skt:settimeout(30)) 35 try(skt:settimeout(30))
33 done, err = skt:bind(localhost, localport) 36 done, err = skt:bind(localhost, localport)
34 if not done then 37 if not done then
@@ -37,8 +40,8 @@ local function connect(localhost, option)
37 skt = nil 40 skt = nil
38 else break end 41 else break end
39 until localport > 731 42 until localport > 731
40 test(skt, err) 43 socket.try(skt, err)
41 else skt = test(socket.tcp()) end 44 else skt = socket.try(socket.tcp()) end
42 try(skt:connect(host, port)) 45 try(skt:connect(host, port))
43 return { skt = skt, try = try } 46 return { skt = skt, try = try }
44end 47end
@@ -241,9 +244,9 @@ local format_codes = {
241-- lp.send 244-- lp.send
242 245
243send = socket.protect(function(file, option) 246send = socket.protect(function(file, option)
244 test(file, "invalid file name") 247 socket.try(file, "invalid file name")
245 test(option and type(option) == "table", "invalid options") 248 socket.try(option and base.type(option) == "table", "invalid options")
246 local fh = test(io.open(file,"rb")) 249 local fh = socket.try(io.open(file,"rb"))
247 local datafile_size = fh:seek("end") -- get total size 250 local datafile_size = fh:seek("end") -- get total size
248 fh:seek("set") -- go back to start of file 251 fh:seek("set") -- go back to start of file
249 local localhost = socket.dns.gethostname() or os.getenv("COMPUTERNAME") 252 local localhost = socket.dns.gethostname() or os.getenv("COMPUTERNAME")
@@ -270,11 +273,11 @@ send = socket.protect(function(file, option)
270 lpfile, 273 lpfile,
271 ctlfn); -- mandatory part of ctl file 274 ctlfn); -- mandatory part of ctl file
272 if (option.banner) then cfile = cfile .. 'L'..user..'\10' end 275 if (option.banner) then cfile = cfile .. 'L'..user..'\10' end
273 if (option.indent) then cfile = cfile .. 'I'..tonumber(option.indent)..'\10' end 276 if (option.indent) then cfile = cfile .. 'I'..base.tonumber(option.indent)..'\10' end
274 if (option.mail) then cfile = cfile .. 'M'..string.sub((option.mail),1,128)..'\10' end 277 if (option.mail) then cfile = cfile .. 'M'..string.sub((option.mail),1,128)..'\10' end
275 if (fmt == 'p' and option.title) then cfile = cfile .. 'T'..string.sub((option.title),1,79)..'\10' end 278 if (fmt == 'p' and option.title) then cfile = cfile .. 'T'..string.sub((option.title),1,79)..'\10' end
276 if ((fmt == 'p' or fmt == 'l' or fmt == 'f') and option.width) then 279 if ((fmt == 'p' or fmt == 'l' or fmt == 'f') and option.width) then
277 cfile = cfile .. 'W'..tonumber(option,width)..'\10' 280 cfile = cfile .. 'W'..base.tonumber(option,width)..'\10'
278 end 281 end
279 282
280 con.skt:settimeout(option.timeout or 65) 283 con.skt:settimeout(option.timeout or 65)
@@ -314,3 +317,5 @@ query = socket.protect(function(p)
314 con.skt:close() 317 con.skt:close()
315 return data 318 return data
316end) 319end)
320
321base.setmetatable(lp, nil)
diff --git a/etc/tftp.lua b/etc/tftp.lua
index f4af8bc..83a08b9 100644
--- a/etc/tftp.lua
+++ b/etc/tftp.lua
@@ -8,11 +8,14 @@
8----------------------------------------------------------------------------- 8-----------------------------------------------------------------------------
9-- Load required files 9-- Load required files
10----------------------------------------------------------------------------- 10-----------------------------------------------------------------------------
11local base = require("base")
12local table = require("table")
13local math = require("math")
14local string = require("string")
11local socket = require("socket") 15local socket = require("socket")
12local ltn12 = require("ltn12") 16local ltn12 = require("ltn12")
13local url = require("socket.url") 17local url = require("socket.url")
14 18local tftp = module("socket.tftp")
15module("socket.tftp")
16 19
17----------------------------------------------------------------------------- 20-----------------------------------------------------------------------------
18-- Program constants 21-- Program constants
@@ -73,16 +76,18 @@ end
73local function tget(gett) 76local function tget(gett)
74 local retries, dgram, sent, datahost, dataport, code 77 local retries, dgram, sent, datahost, dataport, code
75 local last = 0 78 local last = 0
79 socket.try(gett.host, "missing host")
76 local con = socket.try(socket.udp()) 80 local con = socket.try(socket.udp())
77 local try = socket.newtry(function() con:close() end) 81 local try = socket.newtry(function() con:close() end)
78 -- convert from name to ip if needed 82 -- convert from name to ip if needed
79 gett.host = try(socket.dns.toip(gett.host)) 83 gett.host = try(socket.dns.toip(gett.host))
80 con:settimeout(1) 84 con:settimeout(1)
81 -- first packet gives data host/port to be used for data transfers 85 -- first packet gives data host/port to be used for data transfers
86 local path = string.gsub(gett.path or "", "^/", "")
87 path = url.unescape(path)
82 retries = 0 88 retries = 0
83 repeat 89 repeat
84 sent = try(con:sendto(RRQ(gett.path, "octet"), 90 sent = try(con:sendto(RRQ(path, "octet"), gett.host, gett.port))
85 gett.host, gett.port))
86 dgram, datahost, dataport = con:receivefrom() 91 dgram, datahost, dataport = con:receivefrom()
87 retries = retries + 1 92 retries = retries + 1
88 until dgram or datahost ~= "timeout" or retries > 5 93 until dgram or datahost ~= "timeout" or retries > 5
@@ -144,6 +149,8 @@ local function sget(u)
144end 149end
145 150
146get = socket.protect(function(gett) 151get = socket.protect(function(gett)
147 if type(gett) == "string" then return sget(gett) 152 if base.type(gett) == "string" then return sget(gett)
148 else return tget(gett) end 153 else return tget(gett) end
149end) 154end)
155
156base.setmetatable(tftp, nil)
diff --git a/luasocket.vcproj b/luasocket.vcproj
index 6e2da8a..4699498 100644
--- a/luasocket.vcproj
+++ b/luasocket.vcproj
@@ -12,17 +12,18 @@
12 <Configurations> 12 <Configurations>
13 <Configuration 13 <Configuration
14 Name="Debug|Win32" 14 Name="Debug|Win32"
15 OutputDirectory="Debug" 15 OutputDirectory=".\"
16 IntermediateDirectory="Debug" 16 IntermediateDirectory=".\"
17 ConfigurationType="2" 17 ConfigurationType="2"
18 CharacterSet="2"> 18 CharacterSet="2">
19 <Tool 19 <Tool
20 Name="VCCLCompilerTool" 20 Name="VCCLCompilerTool"
21 Optimization="0" 21 Optimization="0"
22 PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LUASOCKET_EXPORTS" 22 AdditionalIncludeDirectories="h:\include"
23 PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LUASOCKET_EXPORTS;LUASOCKET_API=__declspec(dllexport)"
23 MinimalRebuild="TRUE" 24 MinimalRebuild="TRUE"
24 BasicRuntimeChecks="3" 25 BasicRuntimeChecks="3"
25 RuntimeLibrary="1" 26 RuntimeLibrary="5"
26 UsePrecompiledHeader="0" 27 UsePrecompiledHeader="0"
27 WarningLevel="3" 28 WarningLevel="3"
28 Detect64BitPortabilityProblems="TRUE" 29 Detect64BitPortabilityProblems="TRUE"
@@ -31,6 +32,7 @@
31 Name="VCCustomBuildTool"/> 32 Name="VCCustomBuildTool"/>
32 <Tool 33 <Tool
33 Name="VCLinkerTool" 34 Name="VCLinkerTool"
35 AdditionalDependencies="ws2_32.lib"
34 OutputFile="$(OutDir)/lsocket.dll" 36 OutputFile="$(OutDir)/lsocket.dll"
35 LinkIncremental="2" 37 LinkIncremental="2"
36 GenerateDebugInformation="TRUE" 38 GenerateDebugInformation="TRUE"
@@ -69,7 +71,7 @@
69 Name="VCCLCompilerTool" 71 Name="VCCLCompilerTool"
70 AdditionalIncludeDirectories="../../include" 72 AdditionalIncludeDirectories="../../include"
71 PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LUASOCKET_EXPORTS;LUASOCKET_API=__declspec(dllexport); LUASOCKET_DEBUG" 73 PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LUASOCKET_EXPORTS;LUASOCKET_API=__declspec(dllexport); LUASOCKET_DEBUG"
72 RuntimeLibrary="0" 74 RuntimeLibrary="4"
73 UsePrecompiledHeader="0" 75 UsePrecompiledHeader="0"
74 WarningLevel="3" 76 WarningLevel="3"
75 Detect64BitPortabilityProblems="TRUE" 77 Detect64BitPortabilityProblems="TRUE"
@@ -209,10 +211,10 @@
209 UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"> 211 UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
210 </Filter> 212 </Filter>
211 <File 213 <File
212 RelativePath="..\..\lib\lua.lib"> 214 RelativePath="..\..\lib\liblua.lib">
213 </File> 215 </File>
214 <File 216 <File
215 RelativePath="..\..\lib\lualib.lib"> 217 RelativePath="..\..\lib\liblualib.lib">
216 </File> 218 </File>
217 </Files> 219 </Files>
218 <Globals> 220 <Globals>
diff --git a/mime.vcproj b/mime.vcproj
index 51ce05e..9fe7aa8 100644
--- a/mime.vcproj
+++ b/mime.vcproj
@@ -12,17 +12,18 @@
12 <Configurations> 12 <Configurations>
13 <Configuration 13 <Configuration
14 Name="Debug|Win32" 14 Name="Debug|Win32"
15 OutputDirectory="Debug" 15 OutputDirectory=".\"
16 IntermediateDirectory="Debug" 16 IntermediateDirectory=".\"
17 ConfigurationType="2" 17 ConfigurationType="2"
18 CharacterSet="2"> 18 CharacterSet="2">
19 <Tool 19 <Tool
20 Name="VCCLCompilerTool" 20 Name="VCCLCompilerTool"
21 Optimization="0" 21 Optimization="0"
22 PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MIME_EXPORTS" 22 AdditionalIncludeDirectories="h:\include"
23 PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MIME_EXPORTS;MIME_API=__declspec(dllexport)"
23 MinimalRebuild="TRUE" 24 MinimalRebuild="TRUE"
24 BasicRuntimeChecks="3" 25 BasicRuntimeChecks="3"
25 RuntimeLibrary="1" 26 RuntimeLibrary="5"
26 UsePrecompiledHeader="0" 27 UsePrecompiledHeader="0"
27 WarningLevel="3" 28 WarningLevel="3"
28 Detect64BitPortabilityProblems="TRUE" 29 Detect64BitPortabilityProblems="TRUE"
@@ -69,7 +70,7 @@
69 Name="VCCLCompilerTool" 70 Name="VCCLCompilerTool"
70 AdditionalIncludeDirectories="../../include" 71 AdditionalIncludeDirectories="../../include"
71 PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MIME_EXPORTS; MIME_API=__declspec(dllexport)" 72 PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MIME_EXPORTS; MIME_API=__declspec(dllexport)"
72 RuntimeLibrary="0" 73 RuntimeLibrary="4"
73 UsePrecompiledHeader="0" 74 UsePrecompiledHeader="0"
74 WarningLevel="3" 75 WarningLevel="3"
75 Detect64BitPortabilityProblems="TRUE" 76 Detect64BitPortabilityProblems="TRUE"
@@ -136,10 +137,10 @@
136 UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"> 137 UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
137 </Filter> 138 </Filter>
138 <File 139 <File
139 RelativePath="..\..\lib\lua.lib"> 140 RelativePath="..\..\lib\liblua.lib">
140 </File> 141 </File>
141 <File 142 <File
142 RelativePath="..\..\lib\lualib.lib"> 143 RelativePath="..\..\lib\liblualib.lib">
143 </File> 144 </File>
144 </Files> 145 </Files>
145 <Globals> 146 <Globals>
diff --git a/src/buffer.c b/src/buffer.c
index dbd5d2c..1b1b791 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -158,6 +158,7 @@ int buf_isempty(p_buf buf) {
158/*-------------------------------------------------------------------------*\ 158/*-------------------------------------------------------------------------*\
159* Sends a block of data (unbuffered) 159* Sends a block of data (unbuffered)
160\*-------------------------------------------------------------------------*/ 160\*-------------------------------------------------------------------------*/
161#define STEPSIZE 8192
161static int sendraw(p_buf buf, const char *data, size_t count, size_t *sent) { 162static int sendraw(p_buf buf, const char *data, size_t count, size_t *sent) {
162 p_io io = buf->io; 163 p_io io = buf->io;
163 p_tm tm = buf->tm; 164 p_tm tm = buf->tm;
@@ -165,7 +166,8 @@ static int sendraw(p_buf buf, const char *data, size_t count, size_t *sent) {
165 int err = IO_DONE; 166 int err = IO_DONE;
166 while (total < count && err == IO_DONE) { 167 while (total < count && err == IO_DONE) {
167 size_t done; 168 size_t done;
168 err = io->send(io->ctx, data+total, count-total, &done, tm); 169 size_t step = (count-total <= STEPSIZE)? count-total: STEPSIZE;
170 err = io->send(io->ctx, data+total, step, &done, tm);
169 total += done; 171 total += done;
170 } 172 }
171 *sent = total; 173 *sent = total;
diff --git a/src/except.c b/src/except.c
index 80d7e5d..dabaf19 100644
--- a/src/except.c
+++ b/src/except.c
@@ -29,11 +29,21 @@ static luaL_reg func[] = {
29/*-------------------------------------------------------------------------*\ 29/*-------------------------------------------------------------------------*\
30* Try factory 30* Try factory
31\*-------------------------------------------------------------------------*/ 31\*-------------------------------------------------------------------------*/
32static void wrap(lua_State *L) {
33 lua_newtable(L);
34 lua_pushnumber(L, 1);
35 lua_pushvalue(L, -3);
36 lua_settable(L, -3);
37 lua_insert(L, -2);
38 lua_pop(L, 1);
39}
40
32static int finalize(lua_State *L) { 41static int finalize(lua_State *L) {
33 if (!lua_toboolean(L, 1)) { 42 if (!lua_toboolean(L, 1)) {
34 lua_pushvalue(L, lua_upvalueindex(1)); 43 lua_pushvalue(L, lua_upvalueindex(1));
35 lua_pcall(L, 0, 0, 0); 44 lua_pcall(L, 0, 0, 0);
36 lua_settop(L, 2); 45 lua_settop(L, 2);
46 wrap(L);
37 lua_error(L); 47 lua_error(L);
38 return 0; 48 return 0;
39 } else return lua_gettop(L); 49 } else return lua_gettop(L);
@@ -54,13 +64,23 @@ static int global_newtry(lua_State *L) {
54/*-------------------------------------------------------------------------*\ 64/*-------------------------------------------------------------------------*\
55* Protect factory 65* Protect factory
56\*-------------------------------------------------------------------------*/ 66\*-------------------------------------------------------------------------*/
67static int unwrap(lua_State *L) {
68 if (lua_istable(L, -1)) {
69 lua_pushnumber(L, 1);
70 lua_gettable(L, -2);
71 lua_pushnil(L);
72 lua_insert(L, -2);
73 return 1;
74 } else return 0;
75}
76
57static int protected_(lua_State *L) { 77static int protected_(lua_State *L) {
58 lua_pushvalue(L, lua_upvalueindex(1)); 78 lua_pushvalue(L, lua_upvalueindex(1));
59 lua_insert(L, 1); 79 lua_insert(L, 1);
60 if (lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0) != 0) { 80 if (lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0) != 0) {
61 lua_pushnil(L); 81 if (unwrap(L)) return 2;
62 lua_insert(L, 1); 82 else lua_error(L);
63 return 2; 83 return 0;
64 } else return lua_gettop(L); 84 } else return lua_gettop(L);
65} 85}
66 86
diff --git a/src/ftp.lua b/src/ftp.lua
index 9902c88..4529acd 100644
--- a/src/ftp.lua
+++ b/src/ftp.lua
@@ -8,13 +8,15 @@
8----------------------------------------------------------------------------- 8-----------------------------------------------------------------------------
9-- Declare module and import dependencies 9-- Declare module and import dependencies
10----------------------------------------------------------------------------- 10-----------------------------------------------------------------------------
11local base = require("base")
12local table = require("table")
13local string = require("string")
14local math = require("math")
11local socket = require("socket") 15local socket = require("socket")
12local url = require("socket.url") 16local url = require("socket.url")
13local tp = require("socket.tp") 17local tp = require("socket.tp")
14
15local ltn12 = require("ltn12") 18local ltn12 = require("ltn12")
16 19local ftp = module("socket.ftp")
17module("socket.ftp")
18 20
19----------------------------------------------------------------------------- 21-----------------------------------------------------------------------------
20-- Program constants 22-- Program constants
@@ -35,7 +37,7 @@ local metat = { __index = {} }
35 37
36function open(server, port) 38function open(server, port)
37 local tp = socket.try(tp.connect(server, port or PORT, TIMEOUT)) 39 local tp = socket.try(tp.connect(server, port or PORT, TIMEOUT))
38 local f = setmetatable({ tp = tp }, metat) 40 local f = base.setmetatable({ tp = tp }, metat)
39 -- make sure everything gets closed in an exception 41 -- make sure everything gets closed in an exception
40 f.try = socket.newtry(function() f:close() end) 42 f.try = socket.newtry(function() f:close() end)
41 return f 43 return f
@@ -102,7 +104,8 @@ function metat.__index:send(sendt)
102 -- we just get the data connection into self.data 104 -- we just get the data connection into self.data
103 if self.pasvt then self:pasvconnect() end 105 if self.pasvt then self:pasvconnect() end
104 -- get the transfer argument and command 106 -- get the transfer argument and command
105 local argument = sendt.argument or string.gsub(sendt.path, "^/", "") 107 local argument = sendt.argument or
108 url.unescape(string.gsub(sendt.path or "", "^/", ""))
106 if argument == "" then argument = nil end 109 if argument == "" then argument = nil end
107 local command = sendt.command or "stor" 110 local command = sendt.command or "stor"
108 -- send the transfer command and check the reply 111 -- send the transfer command and check the reply
@@ -134,7 +137,8 @@ end
134function metat.__index:receive(recvt) 137function metat.__index:receive(recvt)
135 self.try(self.pasvt or self.server, "need port or pasv first") 138 self.try(self.pasvt or self.server, "need port or pasv first")
136 if self.pasvt then self:pasvconnect() end 139 if self.pasvt then self:pasvconnect() end
137 local argument = recvt.argument or string.gsub(recvt.path, "^/", "") 140 local argument = recvt.argument or
141 url.unescape(string.gsub(recvt.path or "", "^/", ""))
138 if argument == "" then argument = nil end 142 if argument == "" then argument = nil end
139 local command = recvt.command or "retr" 143 local command = recvt.command or "retr"
140 self.try(self.tp:command(command, argument)) 144 self.try(self.tp:command(command, argument))
@@ -182,7 +186,19 @@ end
182----------------------------------------------------------------------------- 186-----------------------------------------------------------------------------
183-- High level FTP API 187-- High level FTP API
184----------------------------------------------------------------------------- 188-----------------------------------------------------------------------------
189function override(t)
190 if t.url then
191 u = url.parse(t.url)
192 for i,v in base.pairs(t) do
193 u[i] = v
194 end
195 return u
196 else return t end
197end
198
185local function tput(putt) 199local function tput(putt)
200 putt = override(putt)
201 socket.try(putt.host, "missing hostname")
186 local f = open(putt.host, putt.port) 202 local f = open(putt.host, putt.port)
187 f:greet() 203 f:greet()
188 f:login(putt.user, putt.password) 204 f:login(putt.user, putt.password)
@@ -201,8 +217,8 @@ local default = {
201 217
202local function parse(u) 218local function parse(u)
203 local t = socket.try(url.parse(u, default)) 219 local t = socket.try(url.parse(u, default))
204 socket.try(t.scheme == "ftp", "invalid scheme '" .. t.scheme .. "'") 220 socket.try(t.scheme == "ftp", "wrong scheme '" .. t.scheme .. "'")
205 socket.try(t.host, "invalid host") 221 socket.try(t.host, "missing hostname")
206 local pat = "^type=(.)$" 222 local pat = "^type=(.)$"
207 if t.params then 223 if t.params then
208 t.type = socket.skip(2, string.find(t.params, pat)) 224 t.type = socket.skip(2, string.find(t.params, pat))
@@ -219,11 +235,13 @@ local function sput(u, body)
219end 235end
220 236
221put = socket.protect(function(putt, body) 237put = socket.protect(function(putt, body)
222 if type(putt) == "string" then return sput(putt, body) 238 if base.type(putt) == "string" then return sput(putt, body)
223 else return tput(putt) end 239 else return tput(putt) end
224end) 240end)
225 241
226local function tget(gett) 242local function tget(gett)
243 gett = override(gett)
244 socket.try(gett.host, "missing hostname")
227 local f = open(gett.host, gett.port) 245 local f = open(gett.host, gett.port)
228 f:greet() 246 f:greet()
229 f:login(gett.user, gett.password) 247 f:login(gett.user, gett.password)
@@ -242,7 +260,22 @@ local function sget(u)
242 return table.concat(t) 260 return table.concat(t)
243end 261end
244 262
263command = socket.protect(function(cmdt)
264 cmdt = override(cmdt)
265 socket.try(cmdt.host, "missing hostname")
266 socket.try(cmdt.command, "missing command")
267 local f = open(cmdt.host, cmdt.port)
268 f:greet()
269 f:login(cmdt.user, cmdt.password)
270 f.try(f.tp:command(cmdt.command, cmdt.argument))
271 if cmdt.check then f.try(f.tp:check(cmdt.check)) end
272 f:quit()
273 return f:close()
274end)
275
245get = socket.protect(function(gett) 276get = socket.protect(function(gett)
246 if type(gett) == "string" then return sget(gett) 277 if base.type(gett) == "string" then return sget(gett)
247 else return tget(gett) end 278 else return tget(gett) end
248end) 279end)
280
281base.setmetatable(ftp, nil)
diff --git a/src/http.lua b/src/http.lua
index b265650..a15ea69 100644
--- a/src/http.lua
+++ b/src/http.lua
@@ -12,8 +12,10 @@ local socket = require("socket")
12local url = require("socket.url") 12local url = require("socket.url")
13local ltn12 = require("ltn12") 13local ltn12 = require("ltn12")
14local mime = require("mime") 14local mime = require("mime")
15 15local string = require("string")
16module("socket.http") 16local base = require("base")
17local table = require("table")
18local http = module("socket.http")
17 19
18----------------------------------------------------------------------------- 20-----------------------------------------------------------------------------
19-- Program constants 21-- Program constants
@@ -32,7 +34,7 @@ local metat = { __index = {} }
32 34
33function open(host, port) 35function open(host, port)
34 local c = socket.try(socket.tcp()) 36 local c = socket.try(socket.tcp())
35 local h = setmetatable({ c = c }, metat) 37 local h = base.setmetatable({ c = c }, metat)
36 -- make sure the connection gets closed on exception 38 -- make sure the connection gets closed on exception
37 h.try = socket.newtry(function() h:close() end) 39 h.try = socket.newtry(function() h:close() end)
38 h.try(c:settimeout(TIMEOUT)) 40 h.try(c:settimeout(TIMEOUT))
@@ -46,7 +48,7 @@ function metat.__index:sendrequestline(method, uri)
46end 48end
47 49
48function metat.__index:sendheaders(headers) 50function metat.__index:sendheaders(headers)
49 for i, v in pairs(headers) do 51 for i, v in base.pairs(headers) do
50 self.try(self.c:send(i .. ": " .. v .. "\r\n")) 52 self.try(self.c:send(i .. ": " .. v .. "\r\n"))
51 end 53 end
52 -- mark end of request headers 54 -- mark end of request headers
@@ -66,7 +68,7 @@ end
66function metat.__index:receivestatusline() 68function metat.__index:receivestatusline()
67 local status = self.try(self.c:receive()) 69 local status = self.try(self.c:receive())
68 local code = socket.skip(2, string.find(status, "HTTP/%d*%.%d* (%d%d%d)")) 70 local code = socket.skip(2, string.find(status, "HTTP/%d*%.%d* (%d%d%d)"))
69 return self.try(tonumber(code), status) 71 return self.try(base.tonumber(code), status)
70end 72end
71 73
72function metat.__index:receiveheaders() 74function metat.__index:receiveheaders()
@@ -97,11 +99,11 @@ end
97function metat.__index:receivebody(headers, sink, step) 99function metat.__index:receivebody(headers, sink, step)
98 sink = sink or ltn12.sink.null() 100 sink = sink or ltn12.sink.null()
99 step = step or ltn12.pump.step 101 step = step or ltn12.pump.step
100 local length = tonumber(headers["content-length"]) 102 local length = base.tonumber(headers["content-length"])
101 local TE = headers["transfer-encoding"] 103 local TE = headers["transfer-encoding"]
102 local mode = "default" -- connection close 104 local mode = "default" -- connection close
103 if TE and TE ~= "identity" then mode = "http-chunked" 105 if TE and TE ~= "identity" then mode = "http-chunked"
104 elseif tonumber(headers["content-length"]) then mode = "by-length" end 106 elseif base.tonumber(headers["content-length"]) then mode = "by-length" end
105 return self.try(ltn12.pump.all(socket.source(mode, self.c, length), 107 return self.try(ltn12.pump.all(socket.source(mode, self.c, length),
106 sink, step)) 108 sink, step))
107end 109end
@@ -159,9 +161,10 @@ local default = {
159local function adjustrequest(reqt) 161local function adjustrequest(reqt)
160 -- parse url if provided 162 -- parse url if provided
161 local nreqt = reqt.url and url.parse(reqt.url, default) or {} 163 local nreqt = reqt.url and url.parse(reqt.url, default) or {}
164 local t = url.parse(reqt.url, default)
162 -- explicit components override url 165 -- explicit components override url
163 for i,v in reqt do nreqt[i] = reqt[i] end 166 for i,v in reqt do nreqt[i] = reqt[i] end
164 socket.try(nreqt.host, "invalid host '" .. tostring(nreqt.host) .. "'") 167 socket.try(nreqt.host, "invalid host '" .. base.tostring(nreqt.host) .. "'")
165 -- compute uri if user hasn't overriden 168 -- compute uri if user hasn't overriden
166 nreqt.uri = reqt.uri or adjusturi(nreqt) 169 nreqt.uri = reqt.uri or adjusturi(nreqt)
167 -- ajust host and port if there is a proxy 170 -- ajust host and port if there is a proxy
@@ -253,6 +256,8 @@ local function srequest(u, body)
253end 256end
254 257
255request = socket.protect(function(reqt, body) 258request = socket.protect(function(reqt, body)
256 if type(reqt) == "string" then return srequest(reqt, body) 259 if base.type(reqt) == "string" then return srequest(reqt, body)
257 else return trequest(reqt) end 260 else return trequest(reqt) end
258end) 261end)
262
263base.setmetatable(http, nil)
diff --git a/src/ltn12.lua b/src/ltn12.lua
index ed39ec8..43c2755 100644
--- a/src/ltn12.lua
+++ b/src/ltn12.lua
@@ -8,7 +8,11 @@
8----------------------------------------------------------------------------- 8-----------------------------------------------------------------------------
9-- Declare module 9-- Declare module
10----------------------------------------------------------------------------- 10-----------------------------------------------------------------------------
11module("ltn12") 11local string = require("string")
12local table = require("table")
13local base = require("base")
14local coroutine = require("coroutine")
15local ltn12 = module("ltn12")
12 16
13filter = {} 17filter = {}
14source = {} 18source = {}
@@ -23,7 +27,7 @@ BLOCKSIZE = 2048
23----------------------------------------------------------------------------- 27-----------------------------------------------------------------------------
24-- returns a high level filter that cycles a low-level filter 28-- returns a high level filter that cycles a low-level filter
25function filter.cycle(low, ctx, extra) 29function filter.cycle(low, ctx, extra)
26 assert(low) 30 base.assert(low)
27 return function(chunk) 31 return function(chunk)
28 local ret 32 local ret
29 ret, ctx = low(ctx, chunk, extra) 33 ret, ctx = low(ctx, chunk, extra)
@@ -121,7 +125,7 @@ end
121 125
122-- turns a fancy source into a simple source 126-- turns a fancy source into a simple source
123function source.simplify(src) 127function source.simplify(src)
124 assert(src) 128 base.assert(src)
125 return function() 129 return function()
126 local chunk, err_or_new = src() 130 local chunk, err_or_new = src()
127 src = err_or_new or src 131 src = err_or_new or src
@@ -145,7 +149,7 @@ end
145 149
146-- creates rewindable source 150-- creates rewindable source
147function source.rewind(src) 151function source.rewind(src)
148 assert(src) 152 base.assert(src)
149 local t = {} 153 local t = {}
150 return function(chunk) 154 return function(chunk)
151 if not chunk then 155 if not chunk then
@@ -160,7 +164,7 @@ end
160 164
161-- chains a source with a filter 165-- chains a source with a filter
162function source.chain(src, f) 166function source.chain(src, f)
163 assert(src and f) 167 base.assert(src and f)
164 local co = coroutine.create(function() 168 local co = coroutine.create(function()
165 while true do 169 while true do
166 local chunk, err = src() 170 local chunk, err = src()
@@ -215,7 +219,7 @@ end
215 219
216-- turns a fancy sink into a simple sink 220-- turns a fancy sink into a simple sink
217function sink.simplify(snk) 221function sink.simplify(snk)
218 assert(snk) 222 base.assert(snk)
219 return function(chunk, err) 223 return function(chunk, err)
220 local ret, err_or_new = snk(chunk, err) 224 local ret, err_or_new = snk(chunk, err)
221 if not ret then return nil, err_or_new end 225 if not ret then return nil, err_or_new end
@@ -254,7 +258,7 @@ end
254 258
255-- chains a sink with a filter 259-- chains a sink with a filter
256function sink.chain(f, snk) 260function sink.chain(f, snk)
257 assert(f and snk) 261 base.assert(f and snk)
258 return function(chunk, err) 262 return function(chunk, err)
259 local filtered = f(chunk) 263 local filtered = f(chunk)
260 local done = chunk and "" 264 local done = chunk and ""
@@ -279,10 +283,12 @@ end
279 283
280-- pumps all data from a source to a sink, using a step function 284-- pumps all data from a source to a sink, using a step function
281function pump.all(src, snk, step) 285function pump.all(src, snk, step)
282 assert(src and snk) 286 base.assert(src and snk)
283 step = step or pump.step 287 step = step or pump.step
284 while true do 288 while true do
285 local ret, err = step(src, snk) 289 local ret, err = step(src, snk)
286 if not ret then return not err, err end 290 if not ret then return not err, err end
287 end 291 end
288end 292end
293
294base.setmetatable(ltn12, nil)
diff --git a/src/mime.lua b/src/mime.lua
index 3dbcf79..712600c 100644
--- a/src/mime.lua
+++ b/src/mime.lua
@@ -8,9 +8,10 @@
8----------------------------------------------------------------------------- 8-----------------------------------------------------------------------------
9-- Declare module and import dependencies 9-- Declare module and import dependencies
10----------------------------------------------------------------------------- 10-----------------------------------------------------------------------------
11module("mime") 11local base = require("base")
12local mime = require("lmime")
13local ltn12 = require("ltn12") 12local ltn12 = require("ltn12")
13local mime = require("lmime")
14module("mime")
14 15
15-- encode, decode and wrap algorithm tables 16-- encode, decode and wrap algorithm tables
16mime.encodet = {} 17mime.encodet = {}
@@ -20,11 +21,11 @@ mime.wrapt = {}
20-- creates a function that chooses a filter by name from a given table 21-- creates a function that chooses a filter by name from a given table
21local function choose(table) 22local function choose(table)
22 return function(name, opt1, opt2) 23 return function(name, opt1, opt2)
23 if type(name) ~= "string" then 24 if base.type(name) ~= "string" then
24 name, opt1, opt2 = "default", name, opt1 25 name, opt1, opt2 = "default", name, opt1
25 end 26 end
26 local f = table[name or "nil"] 27 local f = table[name or "nil"]
27 if not f then error("unknown key (" .. tostring(name) .. ")", 3) 28 if not f then error("unknown key (" .. base.tostring(name) .. ")", 3)
28 else return f(opt1, opt2) end 29 else return f(opt1, opt2) end
29 end 30 end
30end 31end
@@ -74,3 +75,5 @@ end
74function mime.stuff() 75function mime.stuff()
75 return ltn12.filter.cycle(dot, 2) 76 return ltn12.filter.cycle(dot, 2)
76end 77end
78
79base.setmetatable(mime, nil)
diff --git a/src/smtp.lua b/src/smtp.lua
index 974d222..9d49178 100644
--- a/src/smtp.lua
+++ b/src/smtp.lua
@@ -8,13 +8,16 @@
8----------------------------------------------------------------------------- 8-----------------------------------------------------------------------------
9-- Declare module and import dependencies 9-- Declare module and import dependencies
10----------------------------------------------------------------------------- 10-----------------------------------------------------------------------------
11local base = require("base")
12local coroutine = require("coroutine")
13local string = require("string")
14local math = require("math")
15local os = require("os")
11local socket = require("socket") 16local socket = require("socket")
12local tp = require("socket.tp") 17local tp = require("socket.tp")
13
14local ltn12 = require("ltn12") 18local ltn12 = require("ltn12")
15local mime = require("mime") 19local mime = require("mime")
16 20local smtp = module("socket.smtp")
17module("socket.smtp")
18 21
19----------------------------------------------------------------------------- 22-----------------------------------------------------------------------------
20-- Program constants 23-- Program constants
@@ -98,8 +101,8 @@ end
98-- send message or throw an exception 101-- send message or throw an exception
99function metat.__index:send(mailt) 102function metat.__index:send(mailt)
100 self:mail(mailt.from) 103 self:mail(mailt.from)
101 if type(mailt.rcpt) == "table" then 104 if base.type(mailt.rcpt) == "table" then
102 for i,v in ipairs(mailt.rcpt) do 105 for i,v in base.ipairs(mailt.rcpt) do
103 self:rcpt(v) 106 self:rcpt(v)
104 end 107 end
105 else 108 else
@@ -110,7 +113,7 @@ end
110 113
111function open(server, port) 114function open(server, port)
112 local tp = socket.try(tp.connect(server or SERVER, port or PORT, TIMEOUT)) 115 local tp = socket.try(tp.connect(server or SERVER, port or PORT, TIMEOUT))
113 local s = setmetatable({tp = tp}, metat) 116 local s = base.setmetatable({tp = tp}, metat)
114 -- make sure tp is closed if we get an exception 117 -- make sure tp is closed if we get an exception
115 s.try = socket.newtry(function() 118 s.try = socket.newtry(function()
116 if s.tp:command("QUIT") then s.tp:check("2..") end 119 if s.tp:command("QUIT") then s.tp:check("2..") end
@@ -145,7 +148,7 @@ local function send_multipart(mesgt)
145 coroutine.yield("\r\n") 148 coroutine.yield("\r\n")
146 end 149 end
147 -- send each part separated by a boundary 150 -- send each part separated by a boundary
148 for i, m in ipairs(mesgt.body) do 151 for i, m in base.ipairs(mesgt.body) do
149 coroutine.yield("\r\n--" .. bd .. "\r\n") 152 coroutine.yield("\r\n--" .. bd .. "\r\n")
150 send_message(m) 153 send_message(m)
151 end 154 end
@@ -191,7 +194,7 @@ end
191-- yield the headers one by one 194-- yield the headers one by one
192local function send_headers(mesgt) 195local function send_headers(mesgt)
193 if mesgt.headers then 196 if mesgt.headers then
194 for i,v in pairs(mesgt.headers) do 197 for i,v in base.pairs(mesgt.headers) do
195 coroutine.yield(i .. ':' .. v .. "\r\n") 198 coroutine.yield(i .. ':' .. v .. "\r\n")
196 end 199 end
197 end 200 end
@@ -200,8 +203,8 @@ end
200-- message source 203-- message source
201function send_message(mesgt) 204function send_message(mesgt)
202 send_headers(mesgt) 205 send_headers(mesgt)
203 if type(mesgt.body) == "table" then send_multipart(mesgt) 206 if base.type(mesgt.body) == "table" then send_multipart(mesgt)
204 elseif type(mesgt.body) == "function" then send_source(mesgt) 207 elseif base.type(mesgt.body) == "function" then send_source(mesgt)
205 else send_string(mesgt) end 208 else send_string(mesgt) end
206end 209end
207 210
@@ -241,3 +244,5 @@ send = socket.protect(function(mailt)
241 s:quit() 244 s:quit()
242 return s:close() 245 return s:close()
243end) 246end)
247
248base.setmetatable(smtp, nil)
diff --git a/src/tcp.c b/src/tcp.c
index 746c4b6..618f4ce 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -233,7 +233,8 @@ static int meth_close(lua_State *L)
233{ 233{
234 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1); 234 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1);
235 sock_destroy(&tcp->sock); 235 sock_destroy(&tcp->sock);
236 return 0; 236 lua_pushnumber(L, 1);
237 return 1;
237} 238}
238 239
239/*-------------------------------------------------------------------------*\ 240/*-------------------------------------------------------------------------*\
diff --git a/src/tp.lua b/src/tp.lua
index ada00d2..0a671fb 100644
--- a/src/tp.lua
+++ b/src/tp.lua
@@ -8,10 +8,12 @@
8----------------------------------------------------------------------------- 8-----------------------------------------------------------------------------
9-- Declare module and import dependencies 9-- Declare module and import dependencies
10----------------------------------------------------------------------------- 10-----------------------------------------------------------------------------
11local base = require("base")
12local string = require("string")
11local socket = require("socket") 13local socket = require("socket")
12local ltn12 = require("ltn12") 14local ltn12 = require("ltn12")
13 15
14module("socket.tp") 16local tp = module("socket.tp")
15 17
16----------------------------------------------------------------------------- 18-----------------------------------------------------------------------------
17-- Program constants 19-- Program constants
@@ -47,22 +49,27 @@ local metat = { __index = {} }
47function metat.__index:check(ok) 49function metat.__index:check(ok)
48 local code, reply = get_reply(self.c) 50 local code, reply = get_reply(self.c)
49 if not code then return nil, reply end 51 if not code then return nil, reply end
50 if type(ok) ~= "function" then 52 if base.type(ok) ~= "function" then
51 if type(ok) == "table" then 53 if base.type(ok) == "table" then
52 for i, v in ipairs(ok) do 54 for i, v in base.ipairs(ok) do
53 if string.find(code, v) then return tonumber(code), reply end 55 if string.find(code, v) then
56 return base.tonumber(code), reply
57 end
54 end 58 end
55 return nil, reply 59 return nil, reply
56 else 60 else
57 if string.find(code, ok) then return tonumber(code), reply 61 if string.find(code, ok) then return base.tonumber(code), reply
58 else return nil, reply end 62 else return nil, reply end
59 end 63 end
60 else return ok(tonumber(code), reply) end 64 else return ok(base.tonumber(code), reply) end
61end 65end
62 66
63function metat.__index:command(cmd, arg) 67function metat.__index:command(cmd, arg)
64 if arg then return self.c:send(cmd .. " " .. arg.. "\r\n") 68 if arg then
65 else return self.c:send(cmd .. "\r\n") end 69 return self.c:send(cmd .. " " .. arg.. "\r\n")
70 else
71 return self.c:send(cmd .. "\r\n")
72 end
66end 73end
67 74
68function metat.__index:sink(snk, pat) 75function metat.__index:sink(snk, pat)
@@ -111,5 +118,7 @@ function connect(host, port, timeout)
111 c:close() 118 c:close()
112 return nil, e 119 return nil, e
113 end 120 end
114 return setmetatable({c = c}, metat) 121 return base.setmetatable({c = c}, metat)
115end 122end
123
124base.setmetatable(tp, nil)
diff --git a/src/udp.c b/src/udp.c
index 97a6169..7a60080 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -288,7 +288,8 @@ static int meth_setpeername(lua_State *L) {
288static int meth_close(lua_State *L) { 288static int meth_close(lua_State *L) {
289 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); 289 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
290 sock_destroy(&udp->sock); 290 sock_destroy(&udp->sock);
291 return 0; 291 lua_pushnumber(L, 1);
292 return 1;
292} 293}
293 294
294/*-------------------------------------------------------------------------*\ 295/*-------------------------------------------------------------------------*\
diff --git a/src/url.lua b/src/url.lua
index efe7254..08081f0 100644
--- a/src/url.lua
+++ b/src/url.lua
@@ -8,7 +8,10 @@
8----------------------------------------------------------------------------- 8-----------------------------------------------------------------------------
9-- Declare module 9-- Declare module
10----------------------------------------------------------------------------- 10-----------------------------------------------------------------------------
11module("socket.url") 11local string = require("string")
12local base = require("base")
13local table = require("table")
14local url = module("socket.url")
12 15
13----------------------------------------------------------------------------- 16-----------------------------------------------------------------------------
14-- Encodes a string into its escaped hexadecimal representation 17-- Encodes a string into its escaped hexadecimal representation
@@ -18,7 +21,7 @@ module("socket.url")
18-- escaped representation of string binary 21-- escaped representation of string binary
19----------------------------------------------------------------------------- 22-----------------------------------------------------------------------------
20function escape(s) 23function escape(s)
21 return string.gsub(s, "(.)", function(c) 24 return string.gsub(s, "([^A-Za-z0-9_])", function(c)
22 return string.format("%%%02x", string.byte(c)) 25 return string.format("%%%02x", string.byte(c))
23 end) 26 end)
24end 27end
@@ -33,7 +36,7 @@ end
33----------------------------------------------------------------------------- 36-----------------------------------------------------------------------------
34local function make_set(t) 37local function make_set(t)
35 local s = {} 38 local s = {}
36 for i = 1, table.getn(t) do 39 for i,v in base.ipairs(t) do
37 s[t[i]] = 1 40 s[t[i]] = 1
38 end 41 end
39 return s 42 return s
@@ -62,7 +65,7 @@ end
62----------------------------------------------------------------------------- 65-----------------------------------------------------------------------------
63function unescape(s) 66function unescape(s)
64 return string.gsub(s, "%%(%x%x)", function(hex) 67 return string.gsub(s, "%%(%x%x)", function(hex)
65 return string.char(tonumber(hex, 16)) 68 return string.char(base.tonumber(hex, 16))
66 end) 69 end)
67end 70end
68 71
@@ -191,7 +194,7 @@ end
191-- corresponding absolute url 194-- corresponding absolute url
192----------------------------------------------------------------------------- 195-----------------------------------------------------------------------------
193function absolute(base_url, relative_url) 196function absolute(base_url, relative_url)
194 local base = type(base_url) == "table" and base_url or parse(base_url) 197 local base = base.type(base_url) == "table" and base_url or parse(base_url)
195 local relative = parse(relative_url) 198 local relative = parse(relative_url)
196 if not base then return relative_url 199 if not base then return relative_url
197 elseif not relative then return base_url 200 elseif not relative then return base_url
@@ -269,3 +272,5 @@ function build_path(parsed, unsafe)
269 if parsed.is_absolute then path = "/" .. path end 272 if parsed.is_absolute then path = "/" .. path end
270 return path 273 return path
271end 274end
275
276base.setmetatable(url, nil)
diff --git a/src/wsocket.c b/src/wsocket.c
index 1b169ed..0294dce 100644
--- a/src/wsocket.c
+++ b/src/wsocket.c
@@ -180,9 +180,10 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *len, p_tm tm) {
180 180
181/*-------------------------------------------------------------------------*\ 181/*-------------------------------------------------------------------------*\
182* Send with timeout 182* Send with timeout
183* On windows, if you try to send 10MB, the OS will buffer EVERYTHING
184* this can take an awful lot of time and we will end up blocked.
185* Therefore, whoever calls this function should not pass a huge buffer.
183\*-------------------------------------------------------------------------*/ 186\*-------------------------------------------------------------------------*/
184/* has to be larger than UDP_DATAGRAMSIZE !!!*/
185#define MAXCHUNK (64*1024)
186int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, p_tm tm) 187int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, p_tm tm)
187{ 188{
188 int err; 189 int err;
@@ -192,9 +193,7 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, p_tm tm)
192 *sent = 0; 193 *sent = 0;
193 for ( ;; ) { 194 for ( ;; ) {
194 /* try to send something */ 195 /* try to send something */
195 /* on windows, if you try to send 10MB, the OS will buffer EVERYTHING 196 int put = send(*ps, data, count, 0);
196 * this can take an awful lot of time and we will end up blocked. */
197 int put = send(*ps, data, (count < MAXCHUNK)? (int)count: MAXCHUNK, 0);
198 /* if we sent something, we are done */ 197 /* if we sent something, we are done */
199 if (put > 0) { 198 if (put > 0) {
200 *sent = put; 199 *sent = put;
@@ -221,7 +220,7 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
221 if (*ps == SOCK_INVALID) return IO_CLOSED; 220 if (*ps == SOCK_INVALID) return IO_CLOSED;
222 *sent = 0; 221 *sent = 0;
223 for ( ;; ) { 222 for ( ;; ) {
224 int put = send(*ps, data, (int) count, 0); 223 int put = sendto(*ps, data, (int) count, 0, addr, len);
225 if (put > 0) { 224 if (put > 0) {
226 *sent = put; 225 *sent = put;
227 return IO_DONE; 226 return IO_DONE;
@@ -298,13 +297,13 @@ void sock_setnonblocking(p_sock ps) {
298int sock_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) { 297int sock_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) {
299 *hp = gethostbyaddr(addr, len, AF_INET); 298 *hp = gethostbyaddr(addr, len, AF_INET);
300 if (*hp) return IO_DONE; 299 if (*hp) return IO_DONE;
301 else return h_errno; 300 else return WSAGetLastError();
302} 301}
303 302
304int sock_gethostbyname(const char *addr, struct hostent **hp) { 303int sock_gethostbyname(const char *addr, struct hostent **hp) {
305 *hp = gethostbyname(addr); 304 *hp = gethostbyname(addr);
306 if (*hp) return IO_DONE; 305 if (*hp) return IO_DONE;
307 else return h_errno; 306 else return WSAGetLastError();
308} 307}
309 308
310/*-------------------------------------------------------------------------*\ 309/*-------------------------------------------------------------------------*\
diff --git a/test/dicttest.lua b/test/dicttest.lua
index fcdd61f..a37ec8d 100644
--- a/test/dicttest.lua
+++ b/test/dicttest.lua
@@ -1,3 +1,3 @@
1local dict = require"socket.dict" 1local dict = require"socket.dict"
2 2
3for i,v in dict.get("dict://localhost/d:banana") do print(v) end 3for i,v in dict.get("dict://dell-diego/d:banana") do print(v) end
diff --git a/test/ftptest.lua b/test/ftptest.lua
index f578c82..ef1bf0f 100644
--- a/test/ftptest.lua
+++ b/test/ftptest.lua
@@ -1,103 +1,110 @@
1local similar = function(s1, s2) 1local socket = require("socket")
2 return 2local ftp = require("socket.ftp")
3 string.lower(string.gsub(s1, "%s", "")) == 3local url = require("socket.url")
4 string.lower(string.gsub(s2, "%s", "")) 4local ltn12 = require("ltn12")
5end
6 5
7local readfile = function(name) 6-- override protection to make sure we see all errors
8 local f = io.open(name, "r") 7--socket.protect = function(s) return s end
9 if not f then return nil end
10 local s = f:read("*a")
11 f:close()
12 return s
13end
14 8
15local capture = function(cmd) 9dofile("testsupport.lua")
16 local f = io.popen(cmd)
17 if not f then return nil end
18 local s = f:read("*a")
19 f:close()
20 return s
21end
22 10
23local check = function(v, e, o) 11local host, port, index_file, index, back, err, ret
24 e = e or "failed!"
25 o = o or "ok"
26 if v then print(o)
27 else print(e) os.exit() end
28end
29 12
30-- needs an account luasocket:password 13local t = socket.gettime()
31-- and some directories and files in ~ftp
32 14
33local index, err, saved, back, expected 15host = host or "diego.student.princeton.edu"
16index_file = "test/index.html"
34 17
35local t = socket.time()
36 18
37index = readfile("test/index.html") 19-- a function that returns a directory listing
20local function nlst(u)
21 local t = {}
22 local p = url.parse(u)
23 p.command = "nlst"
24 p.sink = ltn12.sink.table(t)
25 local r, e = ftp.get(p)
26 return r and table.concat(t), e
27end
28
29-- function that removes a remote file
30local function dele(u)
31 local p = url.parse(u)
32 p.command = "dele"
33 p.argument = string.gsub(p.path, "^/", "")
34 if p.argumet == "" then p.argument = nil end
35 p.check = 250
36 return ftp.command(p)
37end
38
39-- read index with CRLF convention
40index = readfile(index_file)
38 41
39io.write("testing wrong scheme: ") 42io.write("testing wrong scheme: ")
40back, err = socket.ftp.get("wrong://banana.com/lixo") 43back, err = ftp.get("wrong://banana.com/lixo")
41check(not back and err == "unknown scheme 'wrong'", err) 44assert(not back and err == "wrong scheme 'wrong'", err)
45print("ok")
42 46
43io.write("testing invalid url: ") 47io.write("testing invalid url: ")
44back, err = socket.ftp.get("localhost/dir1/index.html;type=i") 48back, err = ftp.get("localhost/dir1/index.html;type=i")
45local c, e = socket.connect("", 21) 49assert(not back and err)
46check(not back and err == e, err) 50print("ok")
47
48io.write("testing anonymous file upload: ")
49os.remove("/var/ftp/pub/index.up.html")
50ret, err = socket.ftp.put("ftp://localhost/pub/index.up.html;type=i", index)
51saved = readfile("/var/ftp/pub/index.up.html")
52check(ret and not err and saved == index, err)
53 51
54io.write("testing anonymous file download: ") 52io.write("testing anonymous file download: ")
55back, err = socket.ftp.get("ftp://localhost/pub/index.up.html;type=i") 53back, err = socket.ftp.get("ftp://" .. host .. "/pub/index.html;type=i")
56check(not err and back == index, err) 54assert(not err and back == index, err)
57 55print("ok")
58io.write("testing no directory changes: ") 56
59back, err = socket.ftp.get("ftp://localhost/index.html;type=i") 57io.write("erasing before upload: ")
60check(not err and back == index, err) 58ret, err = dele("ftp://luasocket:password@" .. host .. "/index.up.html")
61 59if not ret then print(err)
62io.write("testing multiple directory changes: ") 60else print("ok") end
63back, err = socket.ftp.get("ftp://localhost/pub/dir1/dir2/dir3/dir4/dir5/index.html;type=i") 61
64check(not err and back == index, err) 62io.write("testing upload: ")
65 63ret, err = ftp.put("ftp://luasocket:password@" .. host .. "/index.up.html;type=i", index)
66io.write("testing authenticated upload: ") 64assert(ret and not err, err)
67os.remove("/home/luasocket/index.up.html") 65print("ok")
68ret, err = socket.ftp.put("ftp://luasocket:password@localhost/index.up.html;type=i", index) 66
69saved = readfile("/home/luasocket/index.up.html") 67io.write("downloading uploaded file: ")
70check(ret and not err and saved == index, err) 68back, err = ftp.get("ftp://luasocket:password@" .. host .. "/index.up.html;type=i")
71 69assert(ret and not err and index == back, err)
72io.write("testing authenticated download: ") 70print("ok")
73back, err = socket.ftp.get("ftp://luasocket:password@localhost/index.up.html;type=i") 71
74check(not err and back == index, err) 72io.write("erasing after upload/download: ")
73ret, err = dele("ftp://luasocket:password@" .. host .. "/index.up.html")
74assert(ret and not err, err)
75print("ok")
75 76
76io.write("testing weird-character translation: ") 77io.write("testing weird-character translation: ")
77back, err = socket.ftp.get("ftp://luasocket:password@localhost/%2fvar/ftp/pub/index.html;type=i") 78back, err = ftp.get("ftp://luasocket:password@" .. host .. "/%23%3f;type=i")
78check(not err and back == index, err) 79assert(not err and back == index, err)
80print("ok")
79 81
80io.write("testing parameter overriding: ") 82io.write("testing parameter overriding: ")
81back, err = socket.ftp.get { 83local back = {}
82 url = "//stupid:mistake@localhost/index.html", 84ret, err = ftp.get{
85 url = "//stupid:mistake@" .. host .. "/index.html",
83 user = "luasocket", 86 user = "luasocket",
84 password = "password", 87 password = "password",
85 type = "i" 88 type = "i",
89 sink = ltn12.sink.table(back)
86} 90}
87check(not err and back == index, err) 91assert(ret and not err and table.concat(back) == index, err)
92print("ok")
88 93
89io.write("testing upload denial: ") 94io.write("testing upload denial: ")
90ret, err = socket.ftp.put("ftp://localhost/index.up.html;type=a", index) 95ret, err = ftp.put("ftp://" .. host .. "/index.up.html;type=a", index)
91check(err, err) 96assert(not ret and err, "should have failed")
97print(err)
92 98
93io.write("testing authentication failure: ") 99io.write("testing authentication failure: ")
94ret, err = socket.ftp.put("ftp://luasocket:wrong@localhost/index.html;type=a", index) 100ret, err = ftp.get("ftp://luasocket:wrong@".. host .. "/index.html;type=a")
101assert(not ret and err, "should have failed")
95print(err) 102print(err)
96check(not ret and err, err)
97 103
98io.write("testing wrong file: ") 104io.write("testing wrong file: ")
99back, err = socket.ftp.get("ftp://localhost/index.wrong.html;type=a") 105back, err = ftp.get("ftp://".. host .. "/index.wrong.html;type=a")
100check(err, err) 106assert(not back and err, "should have failed")
107print(err)
101 108
102print("passed all tests") 109print("passed all tests")
103print(string.format("done in %.2fs", socket.time() - t)) 110print(string.format("done in %.2fs", socket.gettime() - t))
diff --git a/test/httptest.lua b/test/httptest.lua
index 71021a4..cade837 100644
--- a/test/httptest.lua
+++ b/test/httptest.lua
@@ -23,7 +23,7 @@ http.TIMEOUT = 10
23local t = socket.gettime() 23local t = socket.gettime()
24 24
25host = host or "diego.student.princeton.edu" 25host = host or "diego.student.princeton.edu"
26proxy = proxy or "http://localhost:3128" 26proxy = proxy or "http://dell-diego.cs.princeton.edu:3128"
27prefix = prefix or "/luasocket-test" 27prefix = prefix or "/luasocket-test"
28cgiprefix = cgiprefix or "/luasocket-test-cgi" 28cgiprefix = cgiprefix or "/luasocket-test-cgi"
29index_file = "test/index.html" 29index_file = "test/index.html"
diff --git a/test/testclnt.lua b/test/testclnt.lua
index f838533..c2c782c 100644
--- a/test/testclnt.lua
+++ b/test/testclnt.lua
@@ -1,7 +1,7 @@
1local socket = require"socket" 1local socket = require"socket"
2 2
3host = host or "localhost" 3host = host or "localhost"
4port = port or "8080" 4port = port or "8383"
5 5
6function pass(...) 6function pass(...)
7 local s = string.format(unpack(arg)) 7 local s = string.format(unpack(arg))
@@ -590,7 +590,6 @@ test_mixed(200)
590test_mixed(17) 590test_mixed(17)
591test_mixed(1) 591test_mixed(1)
592 592
593
594test("binary line") 593test("binary line")
595test_rawline(1) 594test_rawline(1)
596test_rawline(17) 595test_rawline(17)
@@ -630,14 +629,12 @@ test_nonblocking(200)
630test_nonblocking(17) 629test_nonblocking(17)
631test_nonblocking(1) 630test_nonblocking(1)
632 631
633
634test("total timeout on send") 632test("total timeout on send")
635test_totaltimeoutsend(800091, 1, 3) 633test_totaltimeoutsend(800091, 1, 3)
636test_totaltimeoutsend(800091, 2, 3) 634test_totaltimeoutsend(800091, 2, 3)
637test_totaltimeoutsend(800091, 5, 2) 635test_totaltimeoutsend(800091, 5, 2)
638test_totaltimeoutsend(800091, 3, 1) 636test_totaltimeoutsend(800091, 3, 1)
639 637
640
641test("total timeout on receive") 638test("total timeout on receive")
642test_totaltimeoutreceive(800091, 1, 3) 639test_totaltimeoutreceive(800091, 1, 3)
643test_totaltimeoutreceive(800091, 2, 3) 640test_totaltimeoutreceive(800091, 2, 3)
diff --git a/test/testmesg.lua b/test/testmesg.lua
index e29b3cb..5350921 100644
--- a/test/testmesg.lua
+++ b/test/testmesg.lua
@@ -1,5 +1,5 @@
1-- load the smtp support and its friends 1-- load the smtp support and its friends
2local smtp = require("smtp") 2local smtp = require("socket.smtp")
3local mime = require("mime") 3local mime = require("mime")
4local ltn12 = require("ltn12") 4local ltn12 = require("ltn12")
5 5
@@ -48,6 +48,11 @@ source = smtp.message{
48 } 48 }
49} 49}
50 50
51--[[
52sink = ltn12.sink.file(io.stdout)
53ltn12.pump.all(source, sink)
54]]
55
51-- finally send it 56-- finally send it
52r, e = smtp.send{ 57r, e = smtp.send{
53 rcpt = {"<diego@tecgraf.puc-rio.br>", 58 rcpt = {"<diego@tecgraf.puc-rio.br>",
diff --git a/test/testsrvr.lua b/test/testsrvr.lua
index 23e3850..2408e83 100644
--- a/test/testsrvr.lua
+++ b/test/testsrvr.lua
@@ -1,6 +1,6 @@
1socket = require("socket"); 1socket = require("socket");
2host = host or "localhost"; 2host = host or "localhost";
3port = port or "8080"; 3port = port or "8383";
4server = assert(socket.bind(host, port)); 4server = assert(socket.bind(host, port));
5ack = "\n"; 5ack = "\n";
6while 1 do 6while 1 do
diff --git a/test/tftptest.lua b/test/tftptest.lua
index edb6484..35078e8 100644
--- a/test/tftptest.lua
+++ b/test/tftptest.lua
@@ -12,7 +12,7 @@ function readfile(file)
12 return a 12 return a
13end 13end
14 14
15host = host or "localhost" 15host = host or "diego.student.princeton.edu"
16retrieved, err = tftp.get("tftp://" .. host .."/index.html") 16retrieved, err = tftp.get("tftp://" .. host .."/index.html")
17assert(not err, err) 17assert(not err, err)
18original = readfile("test/index.html") 18original = readfile("test/index.html")