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

Impressum / About Us