moonbridge

changeset 94:de3982f17d05

Removed timeout option from socket:close(); Simulate shutdown for local sockets (Unix Domain Sockets)
author jbe
date Tue Apr 07 22:17:13 2015 +0200 (2015-04-07)
parents de0e69673953
children 719f83c7fea4
files moonbridge.c moonbridge_io.c moonbridge_io.h reference.txt
line diff
     1.1 --- a/moonbridge.c	Tue Apr 07 04:08:41 2015 +0200
     1.2 +++ b/moonbridge.c	Tue Apr 07 22:17:13 2015 +0200
     1.3 @@ -842,7 +842,7 @@
     1.4      }
     1.5      if (controlmsg == MOONBR_COMMAND_TERMINATE) break;
     1.6      listener = moonbr_child_receive_pointer(MOONBR_FD_CONTROL);
     1.7 -    if (fd) moonbr_io_pushhandle(L, fd, 1, controlmsg == MOONBR_SOCKETTYPE_NETWORK);
     1.8 +    if (fd) moonbr_io_pushhandle(L, fd, controlmsg == MOONBR_SOCKETTYPE_NETWORK);
     1.9      lua_rawgetp(L, LUA_REGISTRYINDEX, moonbr_luakey_connect_func(pool));
    1.10      if (!fd) {
    1.11        lua_newtable(L);
     2.1 --- a/moonbridge_io.c	Tue Apr 07 04:08:41 2015 +0200
     2.2 +++ b/moonbridge_io.c	Tue Apr 07 22:17:13 2015 +0200
     2.3 @@ -25,9 +25,9 @@
     2.4  
     2.5  typedef struct {
     2.6    int fd;
     2.7 -  int issocket;
     2.8 -  int canshutdown;
     2.9 -  int shutwr;
    2.10 +  int useshutdown;
    2.11 +  int finished;
    2.12 +  int closed;
    2.13    int nonblocking;
    2.14    int readerr;
    2.15    int readbufcnt;
    2.16 @@ -65,7 +65,7 @@
    2.17  
    2.18  static void moonbr_io_handle_set_linger(lua_State *L, moonbr_io_handle_t *handle, int timeout) {
    2.19    struct linger lingerval = { 0, };
    2.20 -  if (!handle->issocket) return;
    2.21 +  if (!handle->useshutdown) return;
    2.22    if (timeout >= 0) {
    2.23      lingerval.l_onoff = 1;
    2.24      lingerval.l_linger = timeout;
    2.25 @@ -95,7 +95,8 @@
    2.26      terminator = terminatorstr[0];
    2.27    }
    2.28    lua_settop(L, 1);  /* return handle on drain, terminator string may be garbage collected */
    2.29 -  if (handle->fd < 0) luaL_error(L, "Attempt to read from a closed I/O handle");
    2.30 +  if (handle->closed) luaL_error(L, "Attempt to read from a closed I/O handle");
    2.31 +  if (handle->fd < 0) goto moonbr_io_read_impl_eof;  /* fake EOF to simulate shutdown */
    2.32    if (handle->readerr) {
    2.33      lua_pushnil(L);
    2.34      lua_pushliteral(L, "Previous read error");
    2.35 @@ -147,6 +148,7 @@
    2.36    handle->readbufcnt = 0;
    2.37    if (!drain) {
    2.38      if (!luabufcnt && result == 0) {
    2.39 +      moonbr_io_read_impl_eof:
    2.40        lua_pushboolean(L, 0);
    2.41        lua_pushliteral(L, "End of file");
    2.42        return 2;
    2.43 @@ -182,8 +184,8 @@
    2.44    size_t written;
    2.45    ssize_t result;
    2.46    handle = luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY);
    2.47 -  if (handle->fd < 0) luaL_error(L, "Attempt to write to a closed I/O handle");
    2.48 -  if (handle->shutwr) luaL_error(L, "Attempt to write to a finished I/O handle");
    2.49 +  if (handle->closed) luaL_error(L, "Attempt to write to a closed I/O handle");
    2.50 +  if (handle->finished) luaL_error(L, "Attempt to write to a finished I/O handle");
    2.51    if (handle->writeerr) {
    2.52      lua_pushnil(L);
    2.53      lua_pushliteral(L, "Previous write error");
    2.54 @@ -295,34 +297,44 @@
    2.55  static int moonbr_io_finish(lua_State *L) {
    2.56    moonbr_io_handle_t *handle;
    2.57    handle = luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY);
    2.58 -  if (handle->fd < 0) luaL_error(L, "Attempt to finish a closed I/O handle");
    2.59 -  if (handle->shutwr) luaL_error(L, "Attempt to finish a finished I/O handle");
    2.60 -  handle->shutwr = 1;
    2.61 -  if (handle->canshutdown) {
    2.62 -    if (handle->writeleft) {
    2.63 -      lua_pushcfunction(L, moonbr_io_flush);
    2.64 -      lua_pushvalue(L, 1);
    2.65 -      lua_call(L, 1, 2);
    2.66 -      if (!lua_toboolean(L, -2)) return 2;
    2.67 +  if (handle->closed) luaL_error(L, "Attempt to finish a closed I/O handle");
    2.68 +  if (handle->finished) luaL_error(L, "Attempt to finish a finished I/O handle");
    2.69 +  if (handle->writeleft) {
    2.70 +    lua_pushcfunction(L, moonbr_io_flush);
    2.71 +    lua_pushvalue(L, 1);
    2.72 +    lua_call(L, 1, 2);
    2.73 +    if (!lua_toboolean(L, -2)) {
    2.74 +      handle->finished = 1;
    2.75 +      return 2;
    2.76      }
    2.77 +  }
    2.78 +  handle->finished = 1;
    2.79 +  if (handle->useshutdown) {
    2.80      if (shutdown(handle->fd, SHUT_WR)) {
    2.81        moonbr_io_errmsg();
    2.82        lua_pushnil(L);
    2.83        lua_pushstring(L, errmsg);
    2.84        return 2;
    2.85      }
    2.86 +  } else {
    2.87 +    if (close(handle->fd)) {
    2.88 +      moonbr_io_errmsg();
    2.89 +      handle->fd = -1;
    2.90 +      lua_pushnil(L);
    2.91 +      lua_pushstring(L, errmsg);
    2.92 +      return 2;
    2.93 +    }
    2.94 +    handle->fd = -1;  /* fake EOF on read */
    2.95    }
    2.96    lua_pushboolean(L, 1);
    2.97    return 1;
    2.98  }
    2.99  
   2.100 -static int moonbr_io_close(lua_State *L) {
   2.101 +static int moonbr_io_close_impl(lua_State *L, int reset) {
   2.102    moonbr_io_handle_t *handle;
   2.103 -  int timeout;
   2.104    handle = luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY);
   2.105 -  timeout = luaL_optinteger(L, 2, -1);
   2.106 -  if (handle->fd < 0) luaL_error(L, "Attempt to close a closed I/O handle");
   2.107 -  if (timeout != 0) {
   2.108 +  if (handle->closed) luaL_error(L, "Attempt to close a closed I/O handle");
   2.109 +  if (!reset) {
   2.110      if (handle->writeleft) {
   2.111        lua_pushcfunction(L, moonbr_io_flush);
   2.112        lua_pushvalue(L, 1);
   2.113 @@ -333,14 +345,16 @@
   2.114          return 2;
   2.115        }
   2.116      }
   2.117 -    moonbr_io_handle_set_linger(L, handle, timeout);
   2.118 +    moonbr_io_handle_set_linger(L, handle, -1);
   2.119    }
   2.120 -  if (close(handle->fd)) {
   2.121 -    moonbr_io_errmsg();
   2.122 -    handle->fd = -1;
   2.123 -    lua_pushnil(L);
   2.124 -    lua_pushstring(L, errmsg);
   2.125 -    return 2;
   2.126 +  if (handle->fd >= 0) {
   2.127 +    if (close(handle->fd)) {
   2.128 +      moonbr_io_errmsg();
   2.129 +      handle->fd = -1;
   2.130 +      lua_pushnil(L);
   2.131 +      lua_pushstring(L, errmsg);
   2.132 +      return 2;
   2.133 +    }
   2.134    }
   2.135    handle->fd = -1;
   2.136    lua_pushboolean(L, 1);
   2.137 @@ -348,14 +362,12 @@
   2.138  
   2.139  }
   2.140  
   2.141 +static int moonbr_io_close(lua_State *L) {
   2.142 +  return moonbr_io_close_impl(L, 0);
   2.143 +}
   2.144 +
   2.145  static int moonbr_io_reset(lua_State *L) {
   2.146 -  luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY);
   2.147 -  lua_settop(L, 1);
   2.148 -  lua_pushcfunction(L, moonbr_io_close);
   2.149 -  lua_insert(L, 1);
   2.150 -  lua_pushinteger(L, 0);
   2.151 -  lua_call(L, 2, LUA_MULTRET);
   2.152 -  return lua_gettop(L);
   2.153 +  return moonbr_io_close_impl(L, 1);
   2.154  }
   2.155  
   2.156  static int moonbr_io_gc(lua_State *L) {
   2.157 @@ -381,13 +393,13 @@
   2.158    }
   2.159  }
   2.160  
   2.161 -void moonbr_io_pushhandle(lua_State *L, int fd, int issocket, int canshutdown) {
   2.162 +void moonbr_io_pushhandle(lua_State *L, int fd, int useshutdown) {
   2.163    moonbr_io_handle_t *handle;
   2.164    handle = lua_newuserdata(L, sizeof(moonbr_io_handle_t));
   2.165    handle->fd = fd;
   2.166 -  handle->issocket = issocket;
   2.167 -  handle->canshutdown = canshutdown;
   2.168 -  handle->shutwr = 0;
   2.169 +  handle->useshutdown = useshutdown;
   2.170 +  handle->finished = 0;
   2.171 +  handle->closed = 0;
   2.172    handle->nonblocking = -1;
   2.173    handle->readerr = 0;
   2.174    handle->readbufcnt = 0;
     3.1 --- a/moonbridge_io.h	Tue Apr 07 04:08:41 2015 +0200
     3.2 +++ b/moonbridge_io.h	Tue Apr 07 22:17:13 2015 +0200
     3.3 @@ -1,5 +1,5 @@
     3.4  
     3.5 -void moonbr_io_pushhandle(lua_State *L, int fd, int issocket, int canshutdown);
     3.6 +void moonbr_io_pushhandle(lua_State *L, int fd, int useshutdown);
     3.7  void moonbr_io_closehandle(lua_State *L, int idx, int timeout);
     3.8  int luaopen_moonbridge_io(lua_State *L);
     3.9  
     4.1 --- a/reference.txt	Tue Apr 07 04:08:41 2015 +0200
     4.2 +++ b/reference.txt	Tue Apr 07 22:17:13 2015 +0200
     4.3 @@ -52,23 +52,19 @@
     4.4  a single socket object as argument, which is described below:
     4.5  
     4.6  
     4.7 -### socket:close(timeout)
     4.8 +### socket:close()
     4.9  
    4.10  Closes the socket connection (input and output stream) by flushing all data and
    4.11 -sending a TCP FIN packet. If the timeout value is non-nil but zero, a TCP RST
    4.12 -is sent instead. If a positive timeout value is given and if the remote peer
    4.13 -doesn't respond with a TCP FIN within the given time, a TCP RST is sent in
    4.14 -addition to the previously sent TCP FIN packet. If the timeout value is nil or
    4.15 -negative, the call returns immediately and the operating system will wait for
    4.16 -the peer's TCP FIN packet.
    4.17 +sending a TCP FIN packet.
    4.18  
    4.19  Returns true on success, or nil plus error message in case of an I/O error.
    4.20  Using this method on sockets that have already been closed (or reset) will
    4.21  throw an error.
    4.22  
    4.23  Warning: Pending data on the input stream may cause connection aborts (TCP RST)
    4.24 -depending on the particular operating system used. All pending input data
    4.25 -should have been read (or drained) before calling socket:close().
    4.26 +when network connections are used. All pending input data should have been read
    4.27 +(or drained) before calling socket:close(). Use socket:finish() to send a
    4.28 +TCP FIN packet to the peer before waiting for EOF from the peer.
    4.29  
    4.30  
    4.31  ### socket:drain(maxlen, terminator)
    4.32 @@ -91,6 +87,17 @@
    4.33  second result value) are returned.
    4.34  
    4.35  
    4.36 +### socket:finish()
    4.37 +
    4.38 +Sends a TCP FIN packet to indicate EOF on write stream. Subsequent reads are
    4.39 +still possible. When there is no more input data to be read, the connection
    4.40 +should finally be closed with socket:close().
    4.41 +
    4.42 +In case of local sockets (Unix Domain Sockets), socket:finish() simply closes
    4.43 +the underlying socket and emulates EOF on subsequent reads. Also in this case,
    4.44 +the connection should be finally closed with socket:close().
    4.45 +
    4.46 +
    4.47  ### socket:flush(...)
    4.48  
    4.49  Same as socket:write(...) but additionally flushes the socket (i.e. all pending

Impressum / About Us