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;