moonbridge

changeset 95:719f83c7fea4

Correctly cache nonblocking status of socket in I/O library; Use TCP_NOPUSH/TCP_CORK when applicable
author jbe
date Wed Apr 08 01:12:03 2015 +0200 (2015-04-08)
parents de3982f17d05
children fdc1bb710544
files moonbridge_io.c
line diff
     1.1 --- a/moonbridge_io.c	Tue Apr 07 22:17:13 2015 +0200
     1.2 +++ b/moonbridge_io.c	Wed Apr 08 01:12:03 2015 +0200
     1.3 @@ -7,6 +7,8 @@
     1.4  #include <sys/socket.h>
     1.5  #include <sys/select.h>
     1.6  #include <fcntl.h>
     1.7 +#include <netinet/in.h>
     1.8 +#include <netinet/tcp.h>
     1.9  
    1.10  #include <lua.h>
    1.11  #include <lauxlib.h>
    1.12 @@ -25,10 +27,11 @@
    1.13  
    1.14  typedef struct {
    1.15    int fd;
    1.16 -  int useshutdown;
    1.17 +  int isnetwork;
    1.18    int finished;
    1.19    int closed;
    1.20    int nonblocking;
    1.21 +  int nopush;
    1.22    int readerr;
    1.23    int readbufcnt;
    1.24    int writeerr;
    1.25 @@ -47,35 +50,55 @@
    1.26  } moonbr_io_handle_t;
    1.27  
    1.28  static void moonbr_io_handle_set_nonblocking(lua_State *L, moonbr_io_handle_t *handle, int nonblocking) {
    1.29 -  if (handle->nonblocking != nonblocking) {
    1.30 -    int flags;
    1.31 -    flags = fcntl(handle->fd, F_GETFL, 0);
    1.32 -    if (flags == -1) {
    1.33 -      moonbr_io_errmsg();
    1.34 -      luaL_error(L, "Unexpected error in fcntl call: %s", errmsg);
    1.35 -    }
    1.36 -    if (nonblocking) flags |= O_NONBLOCK;
    1.37 -    else flags &= ~O_NONBLOCK;
    1.38 -    if (fcntl(handle->fd, F_SETFL, flags) == -1) {
    1.39 -      moonbr_io_errmsg();
    1.40 -      luaL_error(L, "Unexpected error in fcntl call: %s", errmsg);
    1.41 -    }
    1.42 +  int flags;
    1.43 +  if (handle->nonblocking == nonblocking) return;
    1.44 +  flags = fcntl(handle->fd, F_GETFL, 0);
    1.45 +  if (flags == -1) {
    1.46 +    moonbr_io_errmsg();
    1.47 +    handle->nonblocking = -1;
    1.48 +    luaL_error(L, "Unexpected error in fcntl call: %s", errmsg);
    1.49    }
    1.50 +  if (nonblocking) flags |= O_NONBLOCK;
    1.51 +  else flags &= ~O_NONBLOCK;
    1.52 +  if (fcntl(handle->fd, F_SETFL, flags) == -1) {
    1.53 +    moonbr_io_errmsg();
    1.54 +    handle->nonblocking = -1;
    1.55 +    luaL_error(L, "Unexpected error in fcntl call: %s", errmsg);
    1.56 +  }
    1.57 +  handle->nonblocking = nonblocking;
    1.58  }
    1.59  
    1.60  static void moonbr_io_handle_set_linger(lua_State *L, moonbr_io_handle_t *handle, int timeout) {
    1.61    struct linger lingerval = { 0, };
    1.62 -  if (!handle->useshutdown) return;
    1.63 +  if (!handle->isnetwork) return;
    1.64    if (timeout >= 0) {
    1.65      lingerval.l_onoff = 1;
    1.66      lingerval.l_linger = timeout;
    1.67    }
    1.68    if (setsockopt(handle->fd, SOL_SOCKET, SO_LINGER, &lingerval, sizeof(lingerval))) {
    1.69      moonbr_io_errmsg();
    1.70 -    luaL_error(L, "Unexpected error in setsockopt call: %s", errmsg);
    1.71 +    luaL_error(L, "Unexpected error while setting SO_LINGER with setsockopt: %s", errmsg);
    1.72    }
    1.73  }
    1.74  
    1.75 +static void moonbr_io_handle_set_nopush(lua_State *L, moonbr_io_handle_t *handle, int nopush) {
    1.76 +  if (!handle->isnetwork || handle->nopush == nopush) return;
    1.77 +#if defined(TCP_CORK) && !defined(TCP_NOPUSH)
    1.78 +  if (setsockopt(handle->fd, IPPROTO_TCP, TCP_CORK, &nopush, sizeof(nopush))) {
    1.79 +    moonbr_io_errmsg();
    1.80 +    handle->nopush = -1;
    1.81 +    luaL_error(L, "Unexpected error while setting TCP_CORK with setsockopt: %s", errmsg);
    1.82 +  }
    1.83 +#else
    1.84 +  if (setsockopt(handle->fd, IPPROTO_TCP, TCP_NOPUSH, &nopush, sizeof(nopush))) {
    1.85 +    moonbr_io_errmsg();
    1.86 +    handle->nopush = -1;
    1.87 +    luaL_error(L, "Unexpected error while setting TCP_NOPUSH with setsockopt: %s", errmsg);
    1.88 +  }
    1.89 +#endif
    1.90 +  handle->nopush = nopush;
    1.91 +}
    1.92 +
    1.93  static int moonbr_io_read_impl(lua_State *L, int nonblocking, int drain) {
    1.94    moonbr_io_handle_t *handle;
    1.95    lua_Integer maxread;
    1.96 @@ -210,6 +233,10 @@
    1.97          handle->writebufcnt += strlen - handle->writeqoff;
    1.98          break;
    1.99        } else {
   1.100 +        moonbr_io_handle_set_nopush(L, handle,
   1.101 +          (flush || handle->writeleft == MOONBR_IO_WRITEBUFLEN) ?
   1.102 +          0 : 1
   1.103 +        );
   1.104          written = 0;
   1.105          memcpy(handle->writebuf + handle->writebufcnt, str + handle->writeqoff, MOONBR_IO_WRITEBUFLEN - handle->writebufcnt);
   1.106          handle->writeqoff += MOONBR_IO_WRITEBUFLEN - handle->writebufcnt;
   1.107 @@ -309,7 +336,7 @@
   1.108      }
   1.109    }
   1.110    handle->finished = 1;
   1.111 -  if (handle->useshutdown) {
   1.112 +  if (handle->isnetwork) {
   1.113      if (shutdown(handle->fd, SHUT_WR)) {
   1.114        moonbr_io_errmsg();
   1.115        lua_pushnil(L);
   1.116 @@ -393,14 +420,15 @@
   1.117    }
   1.118  }
   1.119  
   1.120 -void moonbr_io_pushhandle(lua_State *L, int fd, int useshutdown) {
   1.121 +void moonbr_io_pushhandle(lua_State *L, int fd, int isnetwork) {
   1.122    moonbr_io_handle_t *handle;
   1.123    handle = lua_newuserdata(L, sizeof(moonbr_io_handle_t));
   1.124    handle->fd = fd;
   1.125 -  handle->useshutdown = useshutdown;
   1.126 +  handle->isnetwork = isnetwork;
   1.127    handle->finished = 0;
   1.128    handle->closed = 0;
   1.129    handle->nonblocking = -1;
   1.130 +  handle->nopush = -1;
   1.131    handle->readerr = 0;
   1.132    handle->readbufcnt = 0;
   1.133    handle->writeerr = 0;

Impressum / About Us