moonbridge
changeset 78:0ec070d6f5d9
Reverted experimental work on non-blocking I/O with file handles
author | jbe |
---|---|
date | Sun Apr 05 15:15:06 2015 +0200 (2015-04-05) |
parents | 38e7bd13200d |
children | 22dbb9d09f02 |
files | moonbridge.c moonbridge_http.lua reference.txt |
line diff
1.1 --- a/moonbridge.c Sun Apr 05 01:17:06 2015 +0200 1.2 +++ b/moonbridge.c Sun Apr 05 15:15:06 2015 +0200 1.3 @@ -936,20 +936,10 @@ 1.4 return lua_gettop(L); 1.5 } 1.6 1.7 -/* Lua method for socket object to read from input stream using xread */ 1.8 -static int moonbr_child_lua_xread_stream(lua_State *L) { 1.9 +/* Lua method for socket object to read from input stream until terminator */ 1.10 +static int moonbr_child_lua_readuntil_stream(lua_State *L) { 1.11 lua_getfield(L, 1, "input"); 1.12 - lua_getfield(L, -1, "xread"); 1.13 - lua_insert(L, 1); 1.14 - lua_replace(L, 2); 1.15 - lua_call(L, lua_gettop(L) - 1, LUA_MULTRET); 1.16 - return lua_gettop(L); 1.17 -} 1.18 - 1.19 -/* Lua method for socket object to read from input stream using xread_nb */ 1.20 -static int moonbr_child_lua_xread_nb_stream(lua_State *L) { 1.21 - lua_getfield(L, 1, "input"); 1.22 - lua_getfield(L, -1, "xread_nb"); 1.23 + lua_getfield(L, -1, "readuntil"); 1.24 lua_insert(L, 1); 1.25 lua_replace(L, 2); 1.26 lua_call(L, lua_gettop(L) - 1, LUA_MULTRET); 1.27 @@ -976,16 +966,6 @@ 1.28 return lua_gettop(L); 1.29 } 1.30 1.31 -/* Lua method for socket object to write to output stream using write_nb */ 1.32 -static int moonbr_child_lua_write_nb_stream(lua_State *L) { 1.33 - lua_getfield(L, 1, "output"); 1.34 - lua_getfield(L, -1, "write_nb"); 1.35 - lua_insert(L, 1); 1.36 - lua_replace(L, 2); 1.37 - lua_call(L, lua_gettop(L) - 1, LUA_MULTRET); 1.38 - return lua_gettop(L); 1.39 -} 1.40 - 1.41 /* Lua method for socket object to flush the output stream */ 1.42 static int moonbr_child_lua_flush_stream(lua_State *L) { 1.43 lua_getfield(L, 1, "output"); 1.44 @@ -1062,15 +1042,13 @@ 1.45 1.46 /* Methods of (bidirectional) socket object passed to handler */ 1.47 static luaL_Reg moonbr_child_lua_socket_functions[] = { 1.48 - {"read", moonbr_child_lua_read_stream}, 1.49 - {"xread", moonbr_child_lua_xread_stream}, 1.50 - {"xread_nb", moonbr_child_lua_xread_nb_stream}, 1.51 - {"lines", moonbr_child_lua_lines_stream}, 1.52 - {"write", moonbr_child_lua_write_stream}, 1.53 - {"write_nb", moonbr_child_lua_write_nb_stream}, 1.54 - {"flush", moonbr_child_lua_flush_stream}, 1.55 - {"close", moonbr_child_lua_close_both_streams}, 1.56 - {"cancel", moonbr_child_lua_cancel_both_streams}, 1.57 + {"read", moonbr_child_lua_read_stream}, 1.58 + {"readuntil", moonbr_child_lua_readuntil_stream}, 1.59 + {"lines", moonbr_child_lua_lines_stream}, 1.60 + {"write", moonbr_child_lua_write_stream}, 1.61 + {"flush", moonbr_child_lua_flush_stream}, 1.62 + {"close", moonbr_child_lua_close_both_streams}, 1.63 + {"cancel", moonbr_child_lua_cancel_both_streams}, 1.64 {NULL, NULL} 1.65 }; 1.66 1.67 @@ -2258,7 +2236,46 @@ 1.68 return ptr; 1.69 } 1.70 1.71 -/* Helper function to convert a value at the given stack index to a natural number */ 1.72 +/* New method for Lua file objects: read until terminator or length exceeded */ 1.73 +static int moonbr_readuntil(lua_State *L) { 1.74 + luaL_Stream *stream; 1.75 + FILE *file; 1.76 + const char *terminatorstr; 1.77 + size_t terminatorlen; 1.78 + luaL_Buffer buf; 1.79 + lua_Integer maxlen; 1.80 + char terminator; 1.81 + int byte; 1.82 + stream = luaL_checkudata(L, 1, LUA_FILEHANDLE); 1.83 + terminatorstr = luaL_checklstring(L, 2, &terminatorlen); 1.84 + luaL_argcheck(L, terminatorlen == 1, 2, "single byte expected"); 1.85 + maxlen = luaL_optinteger(L, 3, 0); 1.86 + if (!stream->closef) luaL_error(L, "attempt to use a closed file"); 1.87 + file = stream->f; 1.88 + luaL_buffinit(L, &buf); 1.89 + if (!maxlen) maxlen = -1; 1.90 + terminator = terminatorstr[0]; 1.91 + while (maxlen > 0 ? maxlen-- : maxlen) { 1.92 + byte = fgetc(file); 1.93 + if (byte == EOF) { 1.94 + if (ferror(file)) { 1.95 + char errmsg[MOONBR_MAXSTRERRORLEN]; 1.96 + strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN); /* use thread-safe call in case child created threads */ 1.97 + lua_pushnil(L); 1.98 + lua_pushstring(L, errmsg); 1.99 + return 2; 1.100 + } else { 1.101 + break; 1.102 + } 1.103 + } 1.104 + luaL_addchar(&buf, byte); 1.105 + if (byte == terminator) break; 1.106 + } 1.107 + luaL_pushresult(&buf); 1.108 + if (!lua_rawlen(L, -1)) lua_pushnil(L); 1.109 + return 1; 1.110 +} 1.111 + 1.112 static int moonbr_lua_tonatural(lua_State *L, int idx) { 1.113 int isnum; 1.114 lua_Number n; 1.115 @@ -2267,7 +2284,6 @@ 1.116 else return -1; 1.117 } 1.118 1.119 -/* Helper function to convert a value at the given stack index to a timeval struct */ 1.120 static int moonbr_lua_totimeval(lua_State *L, int idx, struct timeval *value) { 1.121 int isnum; 1.122 lua_Number n; 1.123 @@ -2281,275 +2297,6 @@ 1.124 } 1.125 } 1.126 1.127 -/* New function io.poll(...) */ 1.128 -static int moonbr_io_poll(lua_State *L) { 1.129 - int i; 1.130 - luaL_Stream *stream; 1.131 - int fd, isnum; 1.132 - int nfds = 0; 1.133 - fd_set readfds, writefds, exceptfds; 1.134 - struct timeval timeout = {0, }; 1.135 - int status; 1.136 - FD_ZERO(&readfds); 1.137 - FD_ZERO(&writefds); 1.138 - FD_ZERO(&exceptfds); 1.139 - if (!lua_isnoneornil(L, 1)) { 1.140 - luaL_checktype(L, 1, LUA_TTABLE); 1.141 - for (i=1; ; i++) { 1.142 -#if LUA_VERSION_NUM >= 503 1.143 - if (lua_geti(L, 1, i) == LUA_TNIL) break; 1.144 -#else 1.145 - lua_pushinteger(L, i); 1.146 - lua_gettable(L, 1); 1.147 - if (lua_isnil(L, -1)) break; 1.148 -#endif 1.149 - stream = luaL_testudata(L, -1, LUA_FILEHANDLE); 1.150 - if (stream) { 1.151 - /* in case of file handle, check for pending data in buffer */ 1.152 - FILE *file = stream->f; 1.153 - int flags, chr; 1.154 - flockfile(file); 1.155 - fd = fileno_unlocked(file); 1.156 - if (ferror(file) || feof(file)) goto moonbr_io_poll_pending_shortcut1; 1.157 - flags = fcntl(fd, F_GETFL, 0); 1.158 - if (flags == -1) goto moonbr_io_poll_pending_error; 1.159 - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) goto moonbr_io_poll_pending_error; 1.160 - chr = getc_unlocked(file); 1.161 - if (chr == EOF) { 1.162 - if (ferror(file) && errno == EAGAIN) clearerr_unlocked(file); 1.163 - else goto moonbr_io_poll_pending_shortcut2; 1.164 - } else { 1.165 - if (ungetc(chr, file) == EOF) { 1.166 - fcntl(fd, F_SETFL, flags); 1.167 - goto moonbr_io_poll_pending_error; 1.168 - } 1.169 - goto moonbr_io_poll_pending_shortcut2; 1.170 - } 1.171 - if (fcntl(fd, F_SETFL, flags) == -1) goto moonbr_io_poll_pending_error; 1.172 - funlockfile(file); 1.173 - goto moonbr_io_poll_pending_cont; 1.174 - moonbr_io_poll_pending_shortcut2: 1.175 - if (fcntl(fd, F_SETFL, flags) == -1) goto moonbr_io_poll_pending_error; 1.176 - moonbr_io_poll_pending_shortcut1: 1.177 - funlockfile(file); 1.178 - lua_pushboolean(L, 1); 1.179 - return 1; 1.180 - moonbr_io_poll_pending_error: 1.181 - funlockfile(file); 1.182 - { 1.183 - char errmsg[MOONBR_MAXSTRERRORLEN]; 1.184 - strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN); /* use thread-safe call in case child created threads */ 1.185 - return luaL_error(L, "Unexpected error while checking buffer of FILE handle: %s", errmsg); 1.186 - } 1.187 - } 1.188 - fd = lua_tointegerx(L, -1, &isnum); 1.189 - if (!isnum) luaL_error(L, "File descriptor is not an integer"); 1.190 - moonbr_io_poll_pending_cont: 1.191 - FD_SET(fd, &readfds); 1.192 - if (fd+1 > nfds) nfds = fd+1; 1.193 - lua_pop(L, 1); 1.194 - } 1.195 - } 1.196 - if (!lua_isnoneornil(L, 2)) { 1.197 - luaL_checktype(L, 2, LUA_TTABLE); 1.198 - for (i=1; ; i++) { 1.199 -#if LUA_VERSION_NUM >= 503 1.200 - if (lua_geti(L, 2, i) == LUA_TNIL) break; 1.201 -#else 1.202 - lua_pushinteger(L, i); 1.203 - lua_gettable(L, 2); 1.204 - if (lua_isnil(L, -1)) break; 1.205 -#endif 1.206 - stream = luaL_testudata(L, -1, LUA_FILEHANDLE); 1.207 - if (stream) { 1.208 - fd = fileno(stream->f); 1.209 - } else { 1.210 - fd = lua_tointegerx(L, -1, &isnum); 1.211 - if (!isnum) luaL_error(L, "File descriptor is not an integer"); 1.212 - } 1.213 - FD_SET(fd, &writefds); 1.214 - if (fd+1 > nfds) nfds = fd+1; 1.215 - lua_pop(L, 1); 1.216 - } 1.217 - lua_pop(L, 2); 1.218 - } 1.219 - if (!lua_isnoneornil(L, 3)) { 1.220 - luaL_argcheck(L, moonbr_lua_totimeval(L, 3, &timeout), 3, "not a valid timeout"); 1.221 - } 1.222 - status = select(nfds, &readfds, &writefds, &exceptfds, &timeout); 1.223 - if (status == -1) { 1.224 - if (errno == EINTR) { 1.225 - lua_pushboolean(L, 0); 1.226 - lua_pushliteral(L, "Signal received while polling file descriptors"); 1.227 - return 2; 1.228 - } else { 1.229 - char errmsg[MOONBR_MAXSTRERRORLEN]; 1.230 - strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN); /* use thread-safe call in case child created threads */ 1.231 - return luaL_error(L, "Unexpected error during \"select\" system call: %s", errmsg); 1.232 - } 1.233 - } else if (status == 0) { 1.234 - lua_pushboolean(L, 0); 1.235 - lua_pushliteral(L, "Timeout while polling file descriptors"); 1.236 - return 2; 1.237 - } else { 1.238 - lua_pushboolean(L, 1); 1.239 - return 1; 1.240 - } 1.241 -} 1.242 - 1.243 -/* New methods for Lua file objects: read until terminator or length exceeded (blocking and non-blocking) */ 1.244 -static int moonbr_io_xread_impl(lua_State *L, int nonblock) { 1.245 - luaL_Stream *stream; 1.246 - lua_Integer maxlen; 1.247 - const char *terminatorstr; 1.248 - size_t terminatorlen; 1.249 - FILE *file; 1.250 - int chr, terminator; 1.251 - luaL_Buffer buf; 1.252 - int wouldblock = 0; 1.253 - stream = luaL_checkudata(L, 1, LUA_FILEHANDLE); 1.254 - maxlen = luaL_optinteger(L, 2, 0); 1.255 - terminatorstr = luaL_optlstring(L, 3, "", &terminatorlen); 1.256 - luaL_argcheck(L, terminatorlen <= 1, 3, "single byte expected"); 1.257 - if (!stream->closef) luaL_error(L, "attempt to use a closed file"); 1.258 - file = stream->f; 1.259 - if (ferror(file)) { 1.260 - lua_pushnil(L); 1.261 - lua_pushliteral(L, "Previous error condition on file handle"); 1.262 - return 2; 1.263 - } 1.264 - if (!maxlen) maxlen = -1; 1.265 - terminator = terminatorlen ? terminatorstr[0] : -1; 1.266 - luaL_buffinit(L, &buf); 1.267 - while (maxlen > 0 ? maxlen-- : maxlen) { 1.268 - chr = getc(file); 1.269 - if (chr == EOF) { 1.270 - if (ferror(file)) { 1.271 - if (nonblock && errno == EAGAIN) { 1.272 - clearerr(file); 1.273 - wouldblock = 1; 1.274 - } else { 1.275 - char errmsg[MOONBR_MAXSTRERRORLEN]; 1.276 - strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN); /* use thread-safe call in case child created threads */ 1.277 - lua_pushnil(L); 1.278 - lua_pushstring(L, errmsg); 1.279 - return 2; 1.280 - } 1.281 - } 1.282 - break; 1.283 - } 1.284 - luaL_addchar(&buf, chr); 1.285 - if (chr == terminator) break; 1.286 - } 1.287 - luaL_pushresult(&buf); 1.288 - if (wouldblock || lua_rawlen(L, -1)) { 1.289 - return 1; 1.290 - } else { 1.291 - lua_pushboolean(L, 0); 1.292 - lua_pushliteral(L, "End of file"); 1.293 - return 2; 1.294 - } 1.295 -} 1.296 -static int moonbr_io_xread(lua_State *L) { 1.297 - return moonbr_io_xread_impl(L, 0); 1.298 -} 1.299 -static int moonbr_io_xread_nb_impl(lua_State *L) { 1.300 - return moonbr_io_xread_impl(L, 1); 1.301 -} 1.302 -static int moonbr_io_xread_nb(lua_State *L) { 1.303 - luaL_Stream *stream; 1.304 - int fd, flags; 1.305 - stream = luaL_checkudata(L, 1, LUA_FILEHANDLE); 1.306 - if (!stream->closef) luaL_error(L, "attempt to use a closed file"); 1.307 - lua_pushcfunction(L, moonbr_io_xread_nb_impl); 1.308 - lua_insert(L, 1); 1.309 - lua_settop(L, 4); 1.310 - fd = fileno(stream->f); 1.311 - flags = fcntl(fd, F_GETFL, 0); 1.312 - if (flags == -1) goto moonbr_io_xread_nb_error; 1.313 - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) goto moonbr_io_xread_nb_error; 1.314 - if (lua_pcall(L, 3, LUA_MULTRET, 0)) { 1.315 - fcntl(fd, F_SETFL, flags); 1.316 - return lua_error(L); 1.317 - } 1.318 - if (fcntl(fd, F_SETFL, flags) == -1) goto moonbr_io_xread_nb_error; 1.319 - return lua_gettop(L); 1.320 - moonbr_io_xread_nb_error: 1.321 - { 1.322 - char errmsg[MOONBR_MAXSTRERRORLEN]; 1.323 - strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN); /* use thread-safe call in case child created threads */ 1.324 - return luaL_error(L, "Unexpected error in xread_nb method: %s", errmsg); 1.325 - } 1.326 -} 1.327 - 1.328 -/* New methods for Lua file objects: non-blocking writing */ 1.329 -static int moonbr_io_write_nb_impl(lua_State *L) { 1.330 - int fd, argc, i; 1.331 - const char *str; 1.332 - size_t strlen; 1.333 - ssize_t written; 1.334 - luaL_Buffer buf; 1.335 - fd = lua_tointeger(L, 1); 1.336 - argc = lua_gettop(L) - 1; 1.337 - for (i=0; i<argc; i++) { 1.338 - str = luaL_checklstring(L, 2+i, &strlen); 1.339 - written = write(fd, str, strlen); 1.340 - if (written < 0) { 1.341 - if (errno != EAGAIN) { 1.342 - char errmsg[MOONBR_MAXSTRERRORLEN]; 1.343 - strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN); /* use thread-safe call in case child created threads */ 1.344 - lua_pushnil(L); 1.345 - lua_pushstring(L, errmsg); 1.346 - return 2; 1.347 - } 1.348 - written = 0; 1.349 - } 1.350 - if (written < strlen) { 1.351 - luaL_buffinit(L, &buf); 1.352 - luaL_addlstring(&buf, str+written, strlen-written); 1.353 - for (i=i+1; i<argc; i++) { 1.354 - luaL_checkstring(L, 2+i); 1.355 - lua_pushvalue(L, 2+i); 1.356 - luaL_addvalue(&buf); 1.357 - } 1.358 - luaL_pushresult(&buf); 1.359 - return 1; 1.360 - } 1.361 - } 1.362 - lua_pushliteral(L, ""); 1.363 - return 1; 1.364 -} 1.365 -static int moonbr_io_write_nb(lua_State *L) { 1.366 - luaL_Stream *stream; 1.367 - FILE *file; 1.368 - int fd, flags; 1.369 - stream = luaL_checkudata(L, 1, LUA_FILEHANDLE); 1.370 - if (!stream->closef) luaL_error(L, "attempt to use a closed file"); 1.371 - file = stream->f; 1.372 - if (fflush(file)) goto moonbr_io_write_nb_error; 1.373 - lua_pushcfunction(L, moonbr_io_write_nb_impl); 1.374 - lua_insert(L, 2); 1.375 - fd = fileno(file); 1.376 - lua_pushinteger(L, fd); 1.377 - lua_insert(L, 3); 1.378 - flags = fcntl(fd, F_GETFL, 0); 1.379 - if (flags == -1) goto moonbr_io_write_nb_error; 1.380 - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) goto moonbr_io_write_nb_error; 1.381 - if (lua_pcall(L, lua_gettop(L) - 2, LUA_MULTRET, 0)) { 1.382 - fcntl(fd, F_SETFL, flags); 1.383 - return lua_error(L); 1.384 - } 1.385 - if (fcntl(fd, F_SETFL, flags) == -1) goto moonbr_io_write_nb_error; 1.386 - return lua_gettop(L) - 1; 1.387 - moonbr_io_write_nb_error: 1.388 - { 1.389 - char errmsg[MOONBR_MAXSTRERRORLEN]; 1.390 - strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN); /* use thread-safe call in case child created threads */ 1.391 - return luaL_error(L, "Unexpected error in write_nb method: %s", errmsg); 1.392 - } 1.393 -} 1.394 - 1.395 -/* New global function timeout(...) */ 1.396 static int moonbr_timeout(lua_State *L) { 1.397 struct itimerval oldval; 1.398 if (lua_isnoneornil(L, 1) && lua_isnoneornil(L, 2)) { 1.399 @@ -3017,21 +2764,13 @@ 1.400 #ifdef MOONBR_LUA_CPATH 1.401 moonbr_modify_path(L, "cpath", MOONBR_LUA_CPATH); 1.402 #endif 1.403 - lua_getglobal(L, "io"); 1.404 - lua_pushcfunction(L, moonbr_io_poll); 1.405 - lua_setfield(L, -2, "poll"); 1.406 - lua_pop(L, 1); 1.407 if (luaL_newmetatable(L, LUA_FILEHANDLE)) { 1.408 moonbr_log(LOG_CRIT, "Lua metatable LUA_FILEHANDLE does not exist"); 1.409 moonbr_terminate_error(); 1.410 } 1.411 lua_getfield(L, -1, "__index"); 1.412 - lua_pushcfunction(L, moonbr_io_xread); 1.413 - lua_setfield(L, -2, "xread"); 1.414 - lua_pushcfunction(L, moonbr_io_xread_nb); 1.415 - lua_setfield(L, -2, "xread_nb"); 1.416 - lua_pushcfunction(L, moonbr_io_write_nb); 1.417 - lua_setfield(L, -2, "write_nb"); 1.418 + lua_pushcfunction(L, moonbr_readuntil); 1.419 + lua_setfield(L, -2, "readuntil"); 1.420 lua_pop(L, 2); 1.421 lua_pushcfunction(L, moonbr_timeout); 1.422 lua_setglobal(L, "timeout");
2.1 --- a/moonbridge_http.lua Sun Apr 05 01:17:06 2015 +0200 2.2 +++ b/moonbridge_http.lua Sun Apr 05 15:15:06 2015 +0200 2.3 @@ -180,16 +180,13 @@ 2.4 end 2.5 local input_chunk_size = options.maximum_input_chunk_size or options.chunk_size or 16384 2.6 local output_chunk_size = options.minimum_output_chunk_size or options.chunk_size or 1024 2.7 - local request_idle_timeout, request_header_timeout, response_timeout 2.8 - if options.request_idle_timeout ~= nil then 2.9 - request_idle_timeout = options.request_idle_timeout or 0 2.10 + local request_header_timeout, response_timeout 2.11 + if options.request_header_timeout ~= nil then 2.12 + request_header_timeout = options.request_header_timeout 2.13 + elseif options.timeout ~= nil then 2.14 + request_header_timeout = options.timeout or 0 2.15 else 2.16 - request_idle_timeout = 330 2.17 - end 2.18 - if options.request_header_timeout ~= nil then 2.19 - request_header_timeout = options.request_header_timeout or 0 2.20 - else 2.21 - request_header_timeout = 30 2.22 + request_header_timeout = 360 2.23 end 2.24 if options.timeout ~= nil then 2.25 response_timeout = options.timeout or 0 2.26 @@ -200,6 +197,8 @@ 2.27 return function(socket) 2.28 local survive = true -- set to false if process shall be terminated later 2.29 repeat 2.30 + -- (re)set timeout: 2.31 + timeout(request_header_timeout or 0) 2.32 -- process named arguments "request_header_size_limit" and "request_body_size_limit": 2.33 local remaining_header_size_limit = options.request_header_size_limit or 1024*1024 2.34 local remaining_body_size_limit = options.request_body_size_limit or 64*1024*1024 2.35 @@ -833,7 +832,7 @@ 2.36 end 2.37 if request.headers_flags["Transfer-Encoding"]["chunked"] then 2.38 while true do 2.39 - local line = socket:xread(32 + remaining_body_size_limit, "\n") 2.40 + local line = socket:readuntil("\n", 32 + remaining_body_size_limit) 2.41 if not line then 2.42 request_error(true, "400 Bad Request", "Unexpected EOF while reading next chunk of request body") 2.43 end 2.44 @@ -854,13 +853,13 @@ 2.45 end 2.46 if len == 0 then break end 2.47 read_body_bytes(len, callback) 2.48 - local term = socket:xread(2, "\n") 2.49 + local term = socket:readuntil("\n", 2) 2.50 if term ~= "\r\n" and term ~= "\n" then 2.51 request_error(true, "400 Bad Request", "Encoding error while reading chunk of request body") 2.52 end 2.53 end 2.54 while true do 2.55 - local line = socket:xread(2 + remaining_body_size_limit, "\n") 2.56 + local line = socket:readuntil("\n", 2 + remaining_body_size_limit) 2.57 if line == "\r\n" or line == "\n" then break end 2.58 remaining_body_size_limit = remaining_body_size_limit - #line 2.59 if remaining_body_size_limit < 0 then 2.60 @@ -894,14 +893,8 @@ 2.61 end 2.62 end 2.63 }) 2.64 - -- wait for input: 2.65 - if not io.poll({socket.input}, nil, request_idle_timeout) then 2.66 - return request_error(false, "408 Request Timeout") 2.67 - end 2.68 - -- set timeout for request header processing: 2.69 - timeout(request_header_timeout) 2.70 -- read and parse request line: 2.71 - local line = socket:xread(remaining_header_size_limit, "\n") 2.72 + local line = socket:readuntil("\n", remaining_header_size_limit) 2.73 if not line then return survive end 2.74 remaining_header_size_limit = remaining_header_size_limit - #line 2.75 if remaining_header_size_limit == 0 then 2.76 @@ -917,7 +910,7 @@ 2.77 end 2.78 -- read and parse headers: 2.79 while true do 2.80 - local line = socket:xread(remaining_header_size_limit, "\n"); 2.81 + local line = socket:readuntil("\n", remaining_header_size_limit); 2.82 remaining_header_size_limit = remaining_header_size_limit - #line 2.83 if not line then 2.84 return request_error(false, "400 Bad Request") 2.85 @@ -998,14 +991,12 @@ 2.86 request.cookies[decode_uri(rawkey)] = decode_uri(rawvalue) 2.87 end 2.88 end 2.89 - -- (re)set timeout for handler: 2.90 + -- (re)set timeout: 2.91 timeout(response_timeout or 0) 2.92 -- call underlying handler and remember boolean result: 2.93 if handler(request) ~= true then survive = false end 2.94 -- finish request (unless already done by underlying handler): 2.95 request:finish() 2.96 - -- stop timeout timer: 2.97 - timeout(0) 2.98 until connection_close_responded 2.99 return survive 2.100 end
3.1 --- a/reference.txt Sun Apr 05 01:17:06 2015 +0200 3.2 +++ b/reference.txt Sun Apr 05 15:15:06 2015 +0200 3.3 @@ -45,28 +45,6 @@ 3.4 3.5 3.6 3.7 -Function io.poll(read_fds, write_fds, timeout) 3.8 ----------------------------------------------- 3.9 - 3.10 -This function allows to wait for file descriptors to become ready for reading 3.11 -or writing. It accepts the following arguments: 3.12 - 3.13 -1. Table of file descriptors to wait for reading (optional, may be nil) 3.14 -2. Table of file descriptors to wait for writing (optional, may be nil) 3.15 -3. Timeout in seconds (optional, may be nil or zero to disable timeout) 3.16 - 3.17 -Alternatively to file descriptors, the tables may contain file handles, in 3.18 -which case the file descriptor is automatically extracted from the file handle 3.19 -and, in case of waiting for reading, the file handle's buffer is additionally 3.20 -tested for pending data. 3.21 - 3.22 -Please note that support for non-blocking I/O operations is limited if you use 3.23 -ordinary file handles (as Moonbridge does). It is possible, however, to wait 3.24 -until the first byte to read is available at a file handle. For more 3.25 -information, see socket.input:pending(). 3.26 - 3.27 - 3.28 - 3.29 Socket object passed to "connect" handler 3.30 ----------------------------------------- 3.31 3.32 @@ -112,34 +90,6 @@ 3.33 Supports the same methods as io.open()'s return values. 3.34 3.35 3.36 -### socket.input:xread(maxlen, terminator) 3.37 - 3.38 -Reads as many bytes until either the maximum length is reached (first argument) 3.39 -or a terminating character (second argument as string with a length of 1) is 3.40 -encountered. In the latter case, the terminating character will be included in 3.41 -the result. 3.42 - 3.43 -On EOF, false (as first result value) and an error message (as second result 3.44 -value) are returned. In case of an I/O error, nil and an error message are 3.45 -returned. 3.46 - 3.47 -This method is also available for any other Lua file handle. 3.48 - 3.49 - 3.50 -### socket.input:xread_nb(maxlen, terminator) 3.51 - 3.52 -Same as socket.input:xread(maxlen, terminator), but non-blocking. If no more 3.53 -data can be read due to blocking, this method returns a string containing the 3.54 -data which has already been read. If no data could be read due to blocking, 3.55 -then an empty string is returned. 3.56 - 3.57 -On EOF, false (as first result value) and an error message (as second result 3.58 -value) are returned. In case of an I/O error, nil and an error message are 3.59 -returned. 3.60 - 3.61 -This method is also available for any other Lua file handle. 3.62 - 3.63 - 3.64 ### socket.interval 3.65 3.66 Set to the name of an interval timer if the "connect" handler was called due to 3.67 @@ -174,40 +124,23 @@ 3.68 Supports the same methods as io.open()'s return values. 3.69 3.70 3.71 -### socket.output:close() 3.72 - 3.73 -Performs a half-close (i.e. sends a TCP FIN package in case of a TCP socket). 3.74 - 3.75 -Note: In order to shut down a TCP connection properly, it may be necessary to 3.76 -read any pending data from socket.input before closing the socket completely 3.77 -(e.g. with socket:close() or by returning from the connect handler). If there 3.78 -is still incoming data, a TCP RST packet might be sent which can cause loss of 3.79 -transmitted data. 3.80 - 3.81 - 3.82 -### socket.output:write_nb(...) 3.83 - 3.84 -Non-blocking write. This function attempts to write as many bytes as possible, 3.85 -returning a string containing all data that could not be written due to 3.86 -blocking (potentially concatenating some or all remaining arguments to create 3.87 -that string). 3.88 - 3.89 -In case of an I/O error, nil (as first result value) and an error message (as 3.90 -second result value) are returned. 3.91 - 3.92 -Note: Using this method will automatically flush any unflushed data written 3.93 -through previous socket.output:write(...) calls. Thus, if any data was 3.94 -previously written in a blocking fashion and has not been flushed, then the 3.95 -socket.output:write_nb(...) call may block. 3.96 - 3.97 -This method is also available for any other Lua file handle. 3.98 - 3.99 - 3.100 ### socket:read(...) 3.101 3.102 Alias for socket.input:read() 3.103 3.104 3.105 +### socket:readuntil(terminator, maxlen) 3.106 + 3.107 +Reads as many bytes until a byte equal to the terminator value occurs. An 3.108 +optional maximum length may be specified. The terminating byte is included in 3.109 +the return value (unless the maximum length would be exceeded). On EOF, nil is 3.110 +returned. In case of an I/O error, nil (as first result value) plus an error 3.111 +message (as second result value) is returned. 3.112 + 3.113 +This method is also available as :readuntil(...) for any other Lua file handle 3.114 +(including socket.input). 3.115 + 3.116 + 3.117 ### socket.remote_ip4 3.118 3.119 Remote IPv4 address used for the connection. Encoded as 4 raw bytes in form of 3.120 @@ -230,21 +163,6 @@ 3.121 Alias for socket.output:write(...) 3.122 3.123 3.124 -### socket:write_nb(...) 3.125 - 3.126 -Alias for socket.output:write(...) 3.127 - 3.128 - 3.129 -### socket:xread(maxlen, terminator) 3.130 - 3.131 -Alias for socket.input:xread(...) 3.132 - 3.133 - 3.134 -### socket:xread_nb(maxlen, terminator) 3.135 - 3.136 -Alias for socket.input:xread_nb(...) 3.137 - 3.138 - 3.139 3.140 HTTP module 3.141 -----------