aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/auxiliar.c2
-rw-r--r--src/compat.c18
-rw-r--r--src/compat.h3
-rw-r--r--src/http.lua25
-rw-r--r--src/ltn12.lua10
-rwxr-xr-x[-rw-r--r--]src/luasocket.c2
-rw-r--r--src/makefile30
-rwxr-xr-x[-rw-r--r--]src/mime.c3
-rw-r--r--src/options.c36
-rw-r--r--src/options.h18
-rw-r--r--src/tcp.c18
-rw-r--r--src/unixdgram.c27
-rw-r--r--src/url.lua64
-rwxr-xr-x[-rw-r--r--]src/wsocket.c4
14 files changed, 197 insertions, 63 deletions
diff --git a/src/auxiliar.c b/src/auxiliar.c
index 18fa8e4..5251549 100644
--- a/src/auxiliar.c
+++ b/src/auxiliar.c
@@ -143,7 +143,7 @@ void *auxiliar_getgroupudata(lua_State *L, const char *groupname, int objidx) {
143* otherwise 143* otherwise
144\*-------------------------------------------------------------------------*/ 144\*-------------------------------------------------------------------------*/
145void *auxiliar_getclassudata(lua_State *L, const char *classname, int objidx) { 145void *auxiliar_getclassudata(lua_State *L, const char *classname, int objidx) {
146 return luaL_checkudata(L, objidx, classname); 146 return luaL_testudata(L, objidx, classname);
147} 147}
148 148
149/*-------------------------------------------------------------------------*\ 149/*-------------------------------------------------------------------------*\
diff --git a/src/compat.c b/src/compat.c
index c2d99cb..988fa68 100644
--- a/src/compat.c
+++ b/src/compat.c
@@ -16,4 +16,22 @@ void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
16 } 16 }
17 lua_pop(L, nup); /* remove upvalues */ 17 lua_pop(L, nup); /* remove upvalues */
18} 18}
19
20/*
21** Duplicated from Lua 5.2
22*/
23void *luaL_testudata (lua_State *L, int ud, const char *tname) {
24 void *p = lua_touserdata(L, ud);
25 if (p != NULL) { /* value is a userdata? */
26 if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
27 luaL_getmetatable(L, tname); /* get correct metatable */
28 if (!lua_rawequal(L, -1, -2)) /* not the same? */
29 p = NULL; /* value is a userdata with wrong metatable */
30 lua_pop(L, 2); /* remove both metatables */
31 return p;
32 }
33 }
34 return NULL; /* value is not a userdata with a metatable */
35}
36
19#endif 37#endif
diff --git a/src/compat.h b/src/compat.h
index 7bf8010..49e83f9 100644
--- a/src/compat.h
+++ b/src/compat.h
@@ -5,7 +5,10 @@
5#include "lauxlib.h" 5#include "lauxlib.h"
6 6
7#if LUA_VERSION_NUM==501 7#if LUA_VERSION_NUM==501
8#define luaL_setfuncs socket_setfuncs
9#define luaL_testudata socket_testudata
8void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup); 10void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup);
11void *luaL_testudata ( lua_State *L, int arg, const char *tname);
9#endif 12#endif
10 13
11#endif 14#endif
diff --git a/src/http.lua b/src/http.lua
index a386165..fb729b2 100644
--- a/src/http.lua
+++ b/src/http.lua
@@ -27,9 +27,13 @@ _M.TIMEOUT = 60
27_M.USERAGENT = socket._VERSION 27_M.USERAGENT = socket._VERSION
28 28
29-- supported schemes 29-- supported schemes
30local SCHEMES = { ["http"] = true } 30local SCHEMES = {
31-- default port for document retrieval 31 http = { port = 80 }
32local PORT = 80 32 , https = { port = 443 }}
33
34-- default scheme and port for document retrieval
35local SCHEME = 'http'
36local PORT = SCHEMES[SCHEME].port
33 37
34----------------------------------------------------------------------------- 38-----------------------------------------------------------------------------
35-- Reads MIME headers from a connection, unfolding where needed 39-- Reads MIME headers from a connection, unfolding where needed
@@ -212,10 +216,14 @@ end
212 216
213local function adjustheaders(reqt) 217local function adjustheaders(reqt)
214 -- default headers 218 -- default headers
215 local host = string.gsub(reqt.authority, "^.-@", "") 219 local headhost = reqt.host
220 local headport = tostring(reqt.port)
221 local schemeport = tostring(SCHEMES[reqt.scheme].port)
222 if headport ~= schemeport then
223 headhost = headhost .. ':' .. headport end
216 local lower = { 224 local lower = {
217 ["user-agent"] = _M.USERAGENT, 225 ["user-agent"] = _M.USERAGENT,
218 ["host"] = host, 226 ["host"] = headhost,
219 ["connection"] = "close, TE", 227 ["connection"] = "close, TE",
220 ["te"] = "trailers" 228 ["te"] = "trailers"
221 } 229 }
@@ -246,7 +254,7 @@ local default = {
246 host = "", 254 host = "",
247 port = PORT, 255 port = PORT,
248 path ="/", 256 path ="/",
249 scheme = "http" 257 scheme = SCHEME
250} 258}
251 259
252local function adjustrequest(reqt) 260local function adjustrequest(reqt)
@@ -277,7 +285,9 @@ local function shouldredirect(reqt, code, headers)
277 return (reqt.redirect ~= false) and 285 return (reqt.redirect ~= false) and
278 (code == 301 or code == 302 or code == 303 or code == 307) and 286 (code == 301 or code == 302 or code == 303 or code == 307) and
279 (not reqt.method or reqt.method == "GET" or reqt.method == "HEAD") 287 (not reqt.method or reqt.method == "GET" or reqt.method == "HEAD")
280 and (not reqt.nredirects or reqt.nredirects < 5) 288 and ((false == reqt.maxredirects)
289 or ((reqt.nredirects or 0)
290 < (reqt.maxredirects or 5)))
281end 291end
282 292
283local function shouldreceivebody(reqt, code) 293local function shouldreceivebody(reqt, code)
@@ -299,6 +309,7 @@ local trequest, tredirect
299 sink = reqt.sink, 309 sink = reqt.sink,
300 headers = reqt.headers, 310 headers = reqt.headers,
301 proxy = reqt.proxy, 311 proxy = reqt.proxy,
312 maxredirects = reqt.maxredirects,
302 nredirects = (reqt.nredirects or 0) + 1, 313 nredirects = (reqt.nredirects or 0) + 1,
303 create = reqt.create 314 create = reqt.create
304 } 315 }
diff --git a/src/ltn12.lua b/src/ltn12.lua
index 575c5a7..afa735d 100644
--- a/src/ltn12.lua
+++ b/src/ltn12.lua
@@ -128,6 +128,16 @@ function source.string(s)
128 else return source.empty() end 128 else return source.empty() end
129end 129end
130 130
131-- creates table source
132function source.table(t)
133 base.assert('table' == type(t))
134 local i = 0
135 return function()
136 i = i + 1
137 return t[i]
138 end
139end
140
131-- creates rewindable source 141-- creates rewindable source
132function source.rewind(src) 142function source.rewind(src)
133 base.assert(src) 143 base.assert(src)
diff --git a/src/luasocket.c b/src/luasocket.c
index 7d9c802..d2752a7 100644..100755
--- a/src/luasocket.c
+++ b/src/luasocket.c
@@ -64,7 +64,7 @@ static luaL_Reg func[] = {
64* Skip a few arguments 64* Skip a few arguments
65\*-------------------------------------------------------------------------*/ 65\*-------------------------------------------------------------------------*/
66static int global_skip(lua_State *L) { 66static int global_skip(lua_State *L) {
67 int amount = luaL_checkinteger(L, 1); 67 int amount = (int) luaL_checkinteger(L, 1);
68 int ret = lua_gettop(L) - amount - 1; 68 int ret = lua_gettop(L) - amount - 1;
69 return ret >= 0 ? ret : 0; 69 return ret >= 0 ? ret : 0;
70} 70}
diff --git a/src/makefile b/src/makefile
index 494baab..cc1ec7e 100644
--- a/src/makefile
+++ b/src/makefile
@@ -35,7 +35,7 @@ DEBUG?=NODEBUG
35# LUAINC_macosx: 35# LUAINC_macosx:
36# /opt/local/include 36# /opt/local/include
37LUAINC_macosx_base?=/opt/local/include 37LUAINC_macosx_base?=/opt/local/include
38LUAINC_macosx?=$(LUAINC_macosx_base)/lua/$(LUAV) 38LUAINC_macosx?=$(LUAINC_macosx_base)/lua/$(LUAV) $(LUAINC_macosx_base)/lua$(LUAV)
39# FIXME default should this default to fink or to macports? 39# FIXME default should this default to fink or to macports?
40# What happens when more than one Lua version is installed? 40# What happens when more than one Lua version is installed?
41LUAPREFIX_macosx?=/opt/local 41LUAPREFIX_macosx?=/opt/local
@@ -48,7 +48,7 @@ LDIR_macosx?=share/lua/$(LUAV)
48# /usr/local/include/lua$(LUAV) 48# /usr/local/include/lua$(LUAV)
49# where lua headers are found for linux builds 49# where lua headers are found for linux builds
50LUAINC_linux_base?=/usr/include 50LUAINC_linux_base?=/usr/include
51LUAINC_linux?=$(LUAINC_linux_base)/lua/$(LUAV) 51LUAINC_linux?=$(LUAINC_linux_base)/lua/$(LUAV) $(LUAINC_linux_base)/lua$(LUAV)
52LUAPREFIX_linux?=/usr/local 52LUAPREFIX_linux?=/usr/local
53CDIR_linux?=lib/lua/$(LUAV) 53CDIR_linux?=lib/lua/$(LUAV)
54LDIR_linux?=share/lua/$(LUAV) 54LDIR_linux?=share/lua/$(LUAV)
@@ -57,7 +57,7 @@ LDIR_linux?=share/lua/$(LUAV)
57# /usr/local/include/lua$(LUAV) 57# /usr/local/include/lua$(LUAV)
58# where lua headers are found for freebsd builds 58# where lua headers are found for freebsd builds
59LUAINC_freebsd_base?=/usr/local/include/ 59LUAINC_freebsd_base?=/usr/local/include/
60LUAINC_freebsd?=$(LUAINC_freebsd_base)/lua$(LUAV) 60LUAINC_freebsd?=$(LUAINC_freebsd_base)/lua/$(LUAV) $(LUAINC_freebsd_base)/lua$(LUAV)
61LUAPREFIX_freebsd?=/usr/local/ 61LUAPREFIX_freebsd?=/usr/local/
62CDIR_freebsd?=lib/lua/$(LUAV) 62CDIR_freebsd?=lib/lua/$(LUAV)
63LDIR_freebsd?=share/lua/$(LUAV) 63LDIR_freebsd?=share/lua/$(LUAV)
@@ -66,7 +66,7 @@ LDIR_freebsd?=share/lua/$(LUAV)
66# LUAINC_mingw: 66# LUAINC_mingw:
67# /opt/local/include 67# /opt/local/include
68LUAINC_mingw_base?=/usr/include 68LUAINC_mingw_base?=/usr/include
69LUAINC_mingw?=$(LUAINC_mingw_base)/lua/$(LUAV) 69LUAINC_mingw?=$(LUAINC_mingw_base)/lua/$(LUAV) $(LUAINC_mingw_base)/lua$(LUAV)
70LUALIB_mingw_base?=/usr/bin 70LUALIB_mingw_base?=/usr/bin
71LUALIB_mingw?=$(LUALIB_mingw_base)/lua/$(LUAV)/lua$(subst .,,$(LUAV)).dll 71LUALIB_mingw?=$(LUALIB_mingw_base)/lua/$(LUAV)/lua$(subst .,,$(LUAV)).dll
72LUAPREFIX_mingw?=/usr 72LUAPREFIX_mingw?=/usr
@@ -78,7 +78,7 @@ LDIR_mingw?=lua/$(LUAV)/lua
78# LUALIB_win32: 78# LUALIB_win32:
79# where lua headers and libraries are found for win32 builds 79# where lua headers and libraries are found for win32 builds
80LUAPREFIX_win32?= 80LUAPREFIX_win32?=
81LUAINC_win32?=$(LUAPREFIX_win32)/include/lua/$(LUAV) 81LUAINC_win32?=$(LUAPREFIX_win32)/include/lua/$(LUAV) $(LUAPREFIX_win32)/include/lua$(LUAV)
82PLATFORM_win32?=Release 82PLATFORM_win32?=Release
83CDIR_win32?=bin/lua/$(LUAV)/$(PLATFORM_win32) 83CDIR_win32?=bin/lua/$(LUAV)/$(PLATFORM_win32)
84LDIR_win32?=bin/lua/$(LUAV)/$(PLATFORM_win32)/lua 84LDIR_win32?=bin/lua/$(LUAV)/$(PLATFORM_win32)/lua
@@ -88,7 +88,7 @@ LUALIBNAME_win32?=lua$(subst .,,$(LUAV)).lib
88 88
89# LUAINC_solaris: 89# LUAINC_solaris:
90LUAINC_solaris_base?=/usr/include 90LUAINC_solaris_base?=/usr/include
91LUAINC_solaris?=$(LUAINC_solaris_base)/lua/$(LUAV) 91LUAINC_solaris?=$(LUAINC_solaris_base)/lua/$(LUAV) $(LUAINC_solaris_base)/lua$(LUAV)
92LUAPREFIX_solaris?=/usr/local 92LUAPREFIX_solaris?=/usr/local
93CDIR_solaris?=lib/lua/$(LUAV) 93CDIR_solaris?=lib/lua/$(LUAV)
94LDIR_solaris?=share/lua/$(LUAV) 94LDIR_solaris?=share/lua/$(LUAV)
@@ -153,7 +153,7 @@ DEF_macosx= -DLUASOCKET_$(DEBUG) -DUNIX_HAS_SUN_LEN \
153 -DLUASOCKET_API='__attribute__((visibility("default")))' \ 153 -DLUASOCKET_API='__attribute__((visibility("default")))' \
154 -DUNIX_API='__attribute__((visibility("default")))' \ 154 -DUNIX_API='__attribute__((visibility("default")))' \
155 -DMIME_API='__attribute__((visibility("default")))' 155 -DMIME_API='__attribute__((visibility("default")))'
156CFLAGS_macosx= -I$(LUAINC) $(DEF) -Wall -O2 -fno-common \ 156CFLAGS_macosx=$(LUAINC:%=-I%) $(DEF) -Wall -O2 -fno-common \
157 -fvisibility=hidden 157 -fvisibility=hidden
158LDFLAGS_macosx= -bundle -undefined dynamic_lookup -o 158LDFLAGS_macosx= -bundle -undefined dynamic_lookup -o
159LD_macosx= export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc 159LD_macosx= export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc
@@ -169,7 +169,7 @@ DEF_linux=-DLUASOCKET_$(DEBUG) \
169 -DLUASOCKET_API='__attribute__((visibility("default")))' \ 169 -DLUASOCKET_API='__attribute__((visibility("default")))' \
170 -DUNIX_API='__attribute__((visibility("default")))' \ 170 -DUNIX_API='__attribute__((visibility("default")))' \
171 -DMIME_API='__attribute__((visibility("default")))' 171 -DMIME_API='__attribute__((visibility("default")))'
172CFLAGS_linux= -I$(LUAINC) $(DEF) -Wall -Wshadow -Wextra \ 172CFLAGS_linux=$(LUAINC:%=-I%) $(DEF) -Wall -Wshadow -Wextra \
173 -Wimplicit -O2 -ggdb3 -fpic -fvisibility=hidden 173 -Wimplicit -O2 -ggdb3 -fpic -fvisibility=hidden
174LDFLAGS_linux=-O -shared -fpic -o 174LDFLAGS_linux=-O -shared -fpic -o
175LD_linux=gcc 175LD_linux=gcc
@@ -181,11 +181,11 @@ SOCKET_linux=usocket.o
181SO_freebsd=so 181SO_freebsd=so
182O_freebsd=o 182O_freebsd=o
183CC_freebsd=gcc 183CC_freebsd=gcc
184DEF_freebsd=-DLUASOCKET_$(DEBUG) \ 184DEF_freebsd=-DLUASOCKET_$(DEBUG) -DUNIX_HAS_SUN_LEN \
185 -DLUASOCKET_API='__attribute__((visibility("default")))' \ 185 -DLUASOCKET_API='__attribute__((visibility("default")))' \
186 -DUNIX_API='__attribute__((visibility("default")))' \ 186 -DUNIX_API='__attribute__((visibility("default")))' \
187 -DMIME_API='__attribute__((visibility("default")))' 187 -DMIME_API='__attribute__((visibility("default")))'
188CFLAGS_freebsd= -I$(LUAINC) $(DEF) -Wall -Wshadow -Wextra \ 188CFLAGS_freebsd=$(LUAINC:%=-I%) $(DEF) -Wall -Wshadow -Wextra \
189 -Wimplicit -O2 -ggdb3 -fpic -fvisibility=hidden 189 -Wimplicit -O2 -ggdb3 -fpic -fvisibility=hidden
190LDFLAGS_freebsd=-O -shared -fpic -o 190LDFLAGS_freebsd=-O -shared -fpic -o
191LD_freebsd=gcc 191LD_freebsd=gcc
@@ -201,7 +201,7 @@ DEF_solaris=-DLUASOCKET_$(DEBUG) \
201 -DLUASOCKET_API='__attribute__((visibility("default")))' \ 201 -DLUASOCKET_API='__attribute__((visibility("default")))' \
202 -DUNIX_API='__attribute__((visibility("default")))' \ 202 -DUNIX_API='__attribute__((visibility("default")))' \
203 -DMIME_API='__attribute__((visibility("default")))' 203 -DMIME_API='__attribute__((visibility("default")))'
204CFLAGS_solaris=-I$(LUAINC) $(DEF) -Wall -Wshadow -Wextra \ 204CFLAGS_solaris=$(LUAINC:%=-I%) $(DEF) -Wall -Wshadow -Wextra \
205 -Wimplicit -O2 -ggdb3 -fpic -fvisibility=hidden 205 -Wimplicit -O2 -ggdb3 -fpic -fvisibility=hidden
206LDFLAGS_solaris=-lnsl -lsocket -lresolv -O -shared -fpic -o 206LDFLAGS_solaris=-lnsl -lsocket -lresolv -O -shared -fpic -o
207LD_solaris=gcc 207LD_solaris=gcc
@@ -216,7 +216,7 @@ CC_mingw=gcc
216DEF_mingw= -DLUASOCKET_INET_PTON -DLUASOCKET_$(DEBUG) \ 216DEF_mingw= -DLUASOCKET_INET_PTON -DLUASOCKET_$(DEBUG) \
217 -DWINVER=0x0501 -DLUASOCKET_API='__declspec(dllexport)' \ 217 -DWINVER=0x0501 -DLUASOCKET_API='__declspec(dllexport)' \
218 -DMIME_API='__declspec(dllexport)' 218 -DMIME_API='__declspec(dllexport)'
219CFLAGS_mingw= -I$(LUAINC) $(DEF) -Wall -O2 -fno-common \ 219CFLAGS_mingw=$(LUAINC:%=-I%) $(DEF) -Wall -O2 -fno-common \
220 -fvisibility=hidden 220 -fvisibility=hidden
221LDFLAGS_mingw= $(LUALIB) -shared -Wl,-s -lws2_32 -o 221LDFLAGS_mingw= $(LUALIB) -shared -Wl,-s -lws2_32 -o
222LD_mingw=gcc 222LD_mingw=gcc
@@ -233,7 +233,7 @@ DEF_win32= //D "WIN32" //D "NDEBUG" //D "_WINDOWS" //D "_USRDLL" \
233 //D "LUASOCKET_API=__declspec(dllexport)" //D "_CRT_SECURE_NO_WARNINGS" \ 233 //D "LUASOCKET_API=__declspec(dllexport)" //D "_CRT_SECURE_NO_WARNINGS" \
234 //D "_WINDLL" //D "MIME_API=__declspec(dllexport)" \ 234 //D "_WINDLL" //D "MIME_API=__declspec(dllexport)" \
235 //D "LUASOCKET_$(DEBUG)" 235 //D "LUASOCKET_$(DEBUG)"
236CFLAGS_win32=//I "$(LUAINC)" $(DEF) //O2 //Ot //MD //W3 //nologo 236CFLAGS_win32=$(LUAINC:%=//I "%") $(DEF) //O2 //Ot //MD //W3 //nologo
237LDFLAGS_win32= //nologo //link //NOLOGO //DLL //INCREMENTAL:NO \ 237LDFLAGS_win32= //nologo //link //NOLOGO //DLL //INCREMENTAL:NO \
238 //MANIFEST //MANIFESTFILE:"intermediate.manifest" \ 238 //MANIFEST //MANIFESTFILE:"intermediate.manifest" \
239 //MANIFESTUAC:"level='asInvoker' uiAccess='false'" \ 239 //MANIFESTUAC:"level='asInvoker' uiAccess='false'" \
@@ -360,7 +360,7 @@ linux:
360 360
361mingw: 361mingw:
362 $(MAKE) all PLAT=mingw 362 $(MAKE) all PLAT=mingw
363 363
364solaris: 364solaris:
365 $(MAKE) all-unix PLAT=solaris 365 $(MAKE) all-unix PLAT=solaris
366 366
@@ -386,7 +386,7 @@ $(UNIX_SO): $(UNIX_OBJS)
386$(SERIAL_SO): $(SERIAL_OBJS) 386$(SERIAL_SO): $(SERIAL_OBJS)
387 $(LD) $(SERIAL_OBJS) $(LDFLAGS)$@ 387 $(LD) $(SERIAL_OBJS) $(LDFLAGS)$@
388 388
389install: 389install:
390 $(INSTALL_DIR) $(INSTALL_TOP_LDIR) 390 $(INSTALL_DIR) $(INSTALL_TOP_LDIR)
391 $(INSTALL_DATA) $(TO_TOP_LDIR) $(INSTALL_TOP_LDIR) 391 $(INSTALL_DATA) $(TO_TOP_LDIR) $(INSTALL_TOP_LDIR)
392 $(INSTALL_DIR) $(INSTALL_SOCKET_LDIR) 392 $(INSTALL_DIR) $(INSTALL_SOCKET_LDIR)
diff --git a/src/mime.c b/src/mime.c
index ed44104..338ecd4 100644..100755
--- a/src/mime.c
+++ b/src/mime.c
@@ -654,7 +654,7 @@ static int eolprocess(int c, int last, const char *marker,
654\*-------------------------------------------------------------------------*/ 654\*-------------------------------------------------------------------------*/
655static int mime_global_eol(lua_State *L) 655static int mime_global_eol(lua_State *L)
656{ 656{
657 int ctx = luaL_checkinteger(L, 1); 657 int ctx = (int) luaL_checkinteger(L, 1);
658 size_t isize = 0; 658 size_t isize = 0;
659 const char *input = luaL_optlstring(L, 2, NULL, &isize); 659 const char *input = luaL_optlstring(L, 2, NULL, &isize);
660 const char *last = input + isize; 660 const char *last = input + isize;
@@ -689,6 +689,7 @@ static size_t dot(int c, size_t state, luaL_Buffer *buffer)
689 case '.': 689 case '.':
690 if (state == 2) 690 if (state == 2)
691 luaL_addchar(buffer, '.'); 691 luaL_addchar(buffer, '.');
692 /* Falls through. */
692 default: 693 default:
693 return 0; 694 return 0;
694 } 695 }
diff --git a/src/options.c b/src/options.c
index fe4e9bb..bbadec3 100644
--- a/src/options.c
+++ b/src/options.c
@@ -90,6 +90,42 @@ int opt_get_tcp_nodelay(lua_State *L, p_socket ps)
90 return opt_getboolean(L, ps, IPPROTO_TCP, TCP_NODELAY); 90 return opt_getboolean(L, ps, IPPROTO_TCP, TCP_NODELAY);
91} 91}
92 92
93#ifdef TCP_KEEPIDLE
94int opt_get_tcp_keepidle(lua_State *L, p_socket ps)
95{
96 return opt_getint(L, ps, IPPROTO_TCP, TCP_KEEPIDLE);
97}
98
99int opt_set_tcp_keepidle(lua_State *L, p_socket ps)
100{
101 return opt_setint(L, ps, IPPROTO_TCP, TCP_KEEPIDLE);
102}
103#endif
104
105#ifdef TCP_KEEPCNT
106int opt_get_tcp_keepcnt(lua_State *L, p_socket ps)
107{
108 return opt_getint(L, ps, IPPROTO_TCP, TCP_KEEPCNT);
109}
110
111int opt_set_tcp_keepcnt(lua_State *L, p_socket ps)
112{
113 return opt_setint(L, ps, IPPROTO_TCP, TCP_KEEPCNT);
114}
115#endif
116
117#ifdef TCP_KEEPINTVL
118int opt_get_tcp_keepintvl(lua_State *L, p_socket ps)
119{
120 return opt_getint(L, ps, IPPROTO_TCP, TCP_KEEPINTVL);
121}
122
123int opt_set_tcp_keepintvl(lua_State *L, p_socket ps)
124{
125 return opt_setint(L, ps, IPPROTO_TCP, TCP_KEEPINTVL);
126}
127#endif
128
93int opt_set_keepalive(lua_State *L, p_socket ps) 129int opt_set_keepalive(lua_State *L, p_socket ps)
94{ 130{
95 return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE); 131 return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE);
diff --git a/src/options.h b/src/options.h
index 4530389..fb82c4d 100644
--- a/src/options.h
+++ b/src/options.h
@@ -22,6 +22,15 @@ typedef t_opt *p_opt;
22int opt_set_dontroute(lua_State *L, p_socket ps); 22int opt_set_dontroute(lua_State *L, p_socket ps);
23int opt_set_broadcast(lua_State *L, p_socket ps); 23int opt_set_broadcast(lua_State *L, p_socket ps);
24int opt_set_tcp_nodelay(lua_State *L, p_socket ps); 24int opt_set_tcp_nodelay(lua_State *L, p_socket ps);
25#ifdef TCP_KEEPIDLE
26int opt_set_tcp_keepidle(lua_State *L, p_socket ps);
27#endif
28#ifdef TCP_KEEPCNT
29int opt_set_tcp_keepcnt(lua_State *L, p_socket ps);
30#endif
31#ifdef TCP_KEEPINTVL
32int opt_set_tcp_keepintvl(lua_State *L, p_socket ps);
33#endif
25int opt_set_keepalive(lua_State *L, p_socket ps); 34int opt_set_keepalive(lua_State *L, p_socket ps);
26int opt_set_linger(lua_State *L, p_socket ps); 35int opt_set_linger(lua_State *L, p_socket ps);
27int opt_set_reuseaddr(lua_State *L, p_socket ps); 36int opt_set_reuseaddr(lua_State *L, p_socket ps);
@@ -46,6 +55,15 @@ int opt_get_broadcast(lua_State *L, p_socket ps);
46int opt_get_reuseaddr(lua_State *L, p_socket ps); 55int opt_get_reuseaddr(lua_State *L, p_socket ps);
47int opt_get_reuseport(lua_State *L, p_socket ps); 56int opt_get_reuseport(lua_State *L, p_socket ps);
48int opt_get_tcp_nodelay(lua_State *L, p_socket ps); 57int opt_get_tcp_nodelay(lua_State *L, p_socket ps);
58#ifdef TCP_KEEPIDLE
59int opt_get_tcp_keepidle(lua_State *L, p_socket ps);
60#endif
61#ifdef TCP_KEEPCNT
62int opt_get_tcp_keepcnt(lua_State *L, p_socket ps);
63#endif
64#ifdef TCP_KEEPINTVL
65int opt_get_tcp_keepintvl(lua_State *L, p_socket ps);
66#endif
49int opt_get_keepalive(lua_State *L, p_socket ps); 67int opt_get_keepalive(lua_State *L, p_socket ps);
50int opt_get_linger(lua_State *L, p_socket ps); 68int opt_get_linger(lua_State *L, p_socket ps);
51int opt_get_ip_multicast_loop(lua_State *L, p_socket ps); 69int opt_get_ip_multicast_loop(lua_State *L, p_socket ps);
diff --git a/src/tcp.c b/src/tcp.c
index f64cb10..c7384b4 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -77,6 +77,15 @@ static t_opt optget[] = {
77 {"reuseaddr", opt_get_reuseaddr}, 77 {"reuseaddr", opt_get_reuseaddr},
78 {"reuseport", opt_get_reuseport}, 78 {"reuseport", opt_get_reuseport},
79 {"tcp-nodelay", opt_get_tcp_nodelay}, 79 {"tcp-nodelay", opt_get_tcp_nodelay},
80#ifdef TCP_KEEPIDLE
81 {"tcp-keepidle", opt_get_tcp_keepidle},
82#endif
83#ifdef TCP_KEEPCNT
84 {"tcp-keepcnt", opt_get_tcp_keepcnt},
85#endif
86#ifdef TCP_KEEPINTVL
87 {"tcp-keepintvl", opt_get_tcp_keepintvl},
88#endif
80 {"linger", opt_get_linger}, 89 {"linger", opt_get_linger},
81 {"error", opt_get_error}, 90 {"error", opt_get_error},
82 {"recv-buffer-size", opt_get_recv_buf_size}, 91 {"recv-buffer-size", opt_get_recv_buf_size},
@@ -89,6 +98,15 @@ static t_opt optset[] = {
89 {"reuseaddr", opt_set_reuseaddr}, 98 {"reuseaddr", opt_set_reuseaddr},
90 {"reuseport", opt_set_reuseport}, 99 {"reuseport", opt_set_reuseport},
91 {"tcp-nodelay", opt_set_tcp_nodelay}, 100 {"tcp-nodelay", opt_set_tcp_nodelay},
101#ifdef TCP_KEEPIDLE
102 {"tcp-keepidle", opt_set_tcp_keepidle},
103#endif
104#ifdef TCP_KEEPCNT
105 {"tcp-keepcnt", opt_set_tcp_keepcnt},
106#endif
107#ifdef TCP_KEEPINTVL
108 {"tcp-keepintvl", opt_set_tcp_keepintvl},
109#endif
92 {"ipv6-v6only", opt_set_ip6_v6only}, 110 {"ipv6-v6only", opt_set_ip6_v6only},
93 {"linger", opt_set_linger}, 111 {"linger", opt_set_linger},
94 {"recv-buffer-size", opt_set_recv_buf_size}, 112 {"recv-buffer-size", opt_set_recv_buf_size},
diff --git a/src/unixdgram.c b/src/unixdgram.c
index 4645892..0d6f18c 100644
--- a/src/unixdgram.c
+++ b/src/unixdgram.c
@@ -17,6 +17,12 @@
17 17
18#define UNIXDGRAM_DATAGRAMSIZE 8192 18#define UNIXDGRAM_DATAGRAMSIZE 8192
19 19
20// provide a SUN_LEN macro if sys/un.h doesn't (e.g. Android)
21#ifndef SUN_LEN
22#define SUN_LEN(ptr) \
23 ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
24 + strlen ((ptr)->sun_path))
25#endif
20/*=========================================================================*\ 26/*=========================================================================*\
21* Internal function prototypes 27* Internal function prototypes
22\*=========================================================================*/ 28\*=========================================================================*/
@@ -261,20 +267,15 @@ static int meth_dirty(lua_State *L) {
261static const char *unixdgram_trybind(p_unix un, const char *path) { 267static const char *unixdgram_trybind(p_unix un, const char *path) {
262 struct sockaddr_un local; 268 struct sockaddr_un local;
263 size_t len = strlen(path); 269 size_t len = strlen(path);
264 int err;
265 if (len >= sizeof(local.sun_path)) return "path too long"; 270 if (len >= sizeof(local.sun_path)) return "path too long";
266 memset(&local, 0, sizeof(local)); 271 memset(&local, 0, sizeof(local));
267 strcpy(local.sun_path, path); 272 strcpy(local.sun_path, path);
268 local.sun_family = AF_UNIX; 273 local.sun_family = AF_UNIX;
274 size_t addrlen = SUN_LEN(&local);
269#ifdef UNIX_HAS_SUN_LEN 275#ifdef UNIX_HAS_SUN_LEN
270 local.sun_len = sizeof(local.sun_family) + sizeof(local.sun_len) 276 local.sun_len = addrlen + 1;
271 + len + 1;
272 err = socket_bind(&un->sock, (SA *) &local, local.sun_len);
273
274#else
275 err = socket_bind(&un->sock, (SA *) &local,
276 sizeof(local.sun_family) + len);
277#endif 277#endif
278 int err = socket_bind(&un->sock, (SA *) &local, addrlen);
278 if (err != IO_DONE) socket_destroy(&un->sock); 279 if (err != IO_DONE) socket_destroy(&un->sock);
279 return socket_strerror(err); 280 return socket_strerror(err);
280} 281}
@@ -315,21 +316,17 @@ static int meth_getsockname(lua_State *L)
315static const char *unixdgram_tryconnect(p_unix un, const char *path) 316static const char *unixdgram_tryconnect(p_unix un, const char *path)
316{ 317{
317 struct sockaddr_un remote; 318 struct sockaddr_un remote;
318 int err;
319 size_t len = strlen(path); 319 size_t len = strlen(path);
320 if (len >= sizeof(remote.sun_path)) return "path too long"; 320 if (len >= sizeof(remote.sun_path)) return "path too long";
321 memset(&remote, 0, sizeof(remote)); 321 memset(&remote, 0, sizeof(remote));
322 strcpy(remote.sun_path, path); 322 strcpy(remote.sun_path, path);
323 remote.sun_family = AF_UNIX; 323 remote.sun_family = AF_UNIX;
324 timeout_markstart(&un->tm); 324 timeout_markstart(&un->tm);
325 size_t addrlen = SUN_LEN(&remote);
325#ifdef UNIX_HAS_SUN_LEN 326#ifdef UNIX_HAS_SUN_LEN
326 remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len) 327 remote.sun_len = addrlen + 1;
327 + len + 1;
328 err = socket_connect(&un->sock, (SA *) &remote, remote.sun_len, &un->tm);
329#else
330 err = socket_connect(&un->sock, (SA *) &remote,
331 sizeof(remote.sun_family) + len, &un->tm);
332#endif 328#endif
329 int err = socket_connect(&un->sock, (SA *) &remote, addrlen, &un->tm);
333 if (err != IO_DONE) socket_destroy(&un->sock); 330 if (err != IO_DONE) socket_destroy(&un->sock);
334 return socket_strerror(err); 331 return socket_strerror(err);
335} 332}
diff --git a/src/url.lua b/src/url.lua
index 110ea94..0a3a80a 100644
--- a/src/url.lua
+++ b/src/url.lua
@@ -77,6 +77,34 @@ function _M.unescape(s)
77end 77end
78 78
79----------------------------------------------------------------------------- 79-----------------------------------------------------------------------------
80-- Removes '..' and '.' components appropriately from a path.
81-- Input
82-- path
83-- Returns
84-- dot-normalized path
85local function remove_dot_components(path)
86 local marker = string.char(1)
87 repeat
88 local was = path
89 path = path:gsub('//', '/'..marker..'/', 1)
90 until path == was
91 repeat
92 local was = path
93 path = path:gsub('/%./', '/', 1)
94 until path == was
95 repeat
96 local was = path
97 path = path:gsub('[^/]+/%.%./([^/]+)', '%1', 1)
98 until path == was
99 path = path:gsub('[^/]+/%.%./*$', '')
100 path = path:gsub('/%.%.$', '/')
101 path = path:gsub('/%.$', '/')
102 path = path:gsub('^/%.%./', '/')
103 path = path:gsub(marker, '')
104 return path
105end
106
107-----------------------------------------------------------------------------
80-- Builds a path from a base path and a relative path 108-- Builds a path from a base path and a relative path
81-- Input 109-- Input
82-- base_path 110-- base_path
@@ -85,23 +113,12 @@ end
85-- corresponding absolute path 113-- corresponding absolute path
86----------------------------------------------------------------------------- 114-----------------------------------------------------------------------------
87local function absolute_path(base_path, relative_path) 115local function absolute_path(base_path, relative_path)
88 if string.sub(relative_path, 1, 1) == "/" then return relative_path end 116 if string.sub(relative_path, 1, 1) == "/" then
89 local path = string.gsub(base_path, "[^/]*$", "") 117 return remove_dot_components(relative_path) end
90 path = path .. relative_path 118 base_path = base_path:gsub("[^/]*$", "")
91 path = string.gsub(path, "([^/]*%./)", function (s) 119 if not base_path:find'/$' then base_path = base_path .. '/' end
92 if s ~= "./" then return s else return "" end 120 local path = base_path .. relative_path
93 end) 121 path = remove_dot_components(path)
94 path = string.gsub(path, "/%.$", "/")
95 local reduced
96 while reduced ~= path do
97 reduced = path
98 path = string.gsub(reduced, "([^/]*/%.%./)", function (s)
99 if s ~= "../../" then return "" else return s end
100 end)
101 end
102 path = string.gsub(reduced, "([^/]*/%.%.)$", function (s)
103 if s ~= "../.." then return "" else return s end
104 end)
105 return path 122 return path
106end 123end
107 124
@@ -227,10 +244,14 @@ function _M.absolute(base_url, relative_url)
227 else 244 else
228 base_parsed = _M.parse(base_url) 245 base_parsed = _M.parse(base_url)
229 end 246 end
247 local result
230 local relative_parsed = _M.parse(relative_url) 248 local relative_parsed = _M.parse(relative_url)
231 if not base_parsed then return relative_url 249 if not base_parsed then
232 elseif not relative_parsed then return base_url 250 result = relative_url
233 elseif relative_parsed.scheme then return relative_url 251 elseif not relative_parsed then
252 result = base_url
253 elseif relative_parsed.scheme then
254 result = relative_url
234 else 255 else
235 relative_parsed.scheme = base_parsed.scheme 256 relative_parsed.scheme = base_parsed.scheme
236 if not relative_parsed.authority then 257 if not relative_parsed.authority then
@@ -248,8 +269,9 @@ function _M.absolute(base_url, relative_url)
248 relative_parsed.path) 269 relative_parsed.path)
249 end 270 end
250 end 271 end
251 return _M.build(relative_parsed) 272 result = _M.build(relative_parsed)
252 end 273 end
274 return remove_dot_components(result)
253end 275end
254 276
255----------------------------------------------------------------------------- 277-----------------------------------------------------------------------------
diff --git a/src/wsocket.c b/src/wsocket.c
index 8ecb0fc..ac8411f 100644..100755
--- a/src/wsocket.c
+++ b/src/wsocket.c
@@ -131,11 +131,11 @@ int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) {
131 /* we wait until something happens */ 131 /* we wait until something happens */
132 err = socket_waitfd(ps, WAITFD_C, tm); 132 err = socket_waitfd(ps, WAITFD_C, tm);
133 if (err == IO_CLOSED) { 133 if (err == IO_CLOSED) {
134 int len = sizeof(err); 134 int elen = sizeof(err);
135 /* give windows time to set the error (yes, disgusting) */ 135 /* give windows time to set the error (yes, disgusting) */
136 Sleep(10); 136 Sleep(10);
137 /* find out why we failed */ 137 /* find out why we failed */
138 getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &len); 138 getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &elen);
139 /* we KNOW there was an error. if 'why' is 0, we will return 139 /* we KNOW there was an error. if 'why' is 0, we will return
140 * "unknown error", but it's not really our fault */ 140 * "unknown error", but it's not really our fault */
141 return err > 0? err: IO_UNKNOWN; 141 return err > 0? err: IO_UNKNOWN;