moonbridge

diff moonbridge.c @ 88:fca51922b708

Extended I/O library; Integrated new I/O library into moonbridge.c and moonbridge_http.lua
author jbe
date Tue Apr 07 02:15:17 2015 +0200 (2015-04-07)
parents 22dbb9d09f02
children c4fd976d9537
line diff
     1.1 --- a/moonbridge.c	Tue Apr 07 01:17:55 2015 +0200
     1.2 +++ b/moonbridge.c	Tue Apr 07 02:15:17 2015 +0200
     1.3 @@ -277,12 +277,6 @@
     1.4  /* Variable set to nonzero value to disallow further calls of 'listen' function */
     1.5  static int moonbr_booted = 0;
     1.6  
     1.7 -/* Global variables to store information on connection socket in child process */
     1.8 -static int moonbr_child_peersocket_type;                   /* type of socket by MOONBR_SOCKETTYPE constant */
     1.9 -static int moonbr_child_peersocket_fd;                     /* Original file descriptor of peer socket */
    1.10 -static luaL_Stream *moonbr_child_peersocket_inputstream;   /* Lua input stream of socket */
    1.11 -static luaL_Stream *moonbr_child_peersocket_outputstream;  /* Lua output stream of socket */
    1.12 -
    1.13  /* Verbosity settings */
    1.14  static int moonbr_debug = 0;
    1.15  static int moonbr_stat = 0;
    1.16 @@ -817,249 +811,10 @@
    1.17    }
    1.18  }
    1.19  
    1.20 -/* Closes the input stream from peer unless it has already been closed */
    1.21 -static int moonbr_child_close_peersocket_inputstream(
    1.22 -  int cleanshut,  /* nonzero = use shutdown() if applicable */
    1.23 -  int mark        /* nonzero = mark the stream as closed for Lua */
    1.24 -) {
    1.25 -  int err = 0;  /* nonzero = error occurred */
    1.26 -  int errno2;   /* stores previous errno values that take precedence */
    1.27 -  if (moonbr_child_peersocket_inputstream->f) {
    1.28 -    /* NOTE: shutdown() with SHUT_RD shows different behavior on different
    1.29 -     * operating systems and particularly causes problems with Linux. Hence it
    1.30 -     * is disabled here. */
    1.31 -    /*
    1.32 -    if (cleanshut && moonbr_child_peersocket_type == MOONBR_SOCKETTYPE_NETWORK) {
    1.33 -      if (shutdown(moonbr_child_peersocket_fd, SHUT_RD)) {
    1.34 -        errno2 = errno;
    1.35 -        err = -1;
    1.36 -      }
    1.37 -    }
    1.38 -    */
    1.39 -    if (fclose(moonbr_child_peersocket_inputstream->f)) {
    1.40 -      if (!err) errno2 = errno;
    1.41 -      err = -1;
    1.42 -    }
    1.43 -    moonbr_child_peersocket_inputstream->f = NULL;
    1.44 -  }
    1.45 -  if (mark) moonbr_child_peersocket_inputstream->closef = NULL;
    1.46 -  if (err) errno = errno2;
    1.47 -  return err;
    1.48 -}
    1.49 -
    1.50 -/* Closes the output stream to peer unless it has already been closed */
    1.51 -static int moonbr_child_close_peersocket_outputstream(
    1.52 -  int cleanshut,  /* nonzero = use fflush() and shutdown() if applicable */
    1.53 -  int mark        /* nonzero = mark the stream as closed for Lua */
    1.54 -) {
    1.55 -  int err = 0;  /* nonzero = error occurred */
    1.56 -  int errno2;   /* stores previous errno values that take precedence */
    1.57 -  if (moonbr_child_peersocket_outputstream->f) {
    1.58 -    if (moonbr_child_peersocket_type == MOONBR_SOCKETTYPE_NETWORK) {
    1.59 -      if (cleanshut) {
    1.60 -        if (fflush(moonbr_child_peersocket_outputstream->f)) {
    1.61 -          errno2 = errno;
    1.62 -          err = -1;
    1.63 -        } else {
    1.64 -          if (shutdown(moonbr_child_peersocket_fd, SHUT_WR)) {
    1.65 -            errno2 = errno;
    1.66 -            err = -1;
    1.67 -          }
    1.68 -        }
    1.69 -      } else {
    1.70 -        fpurge(moonbr_child_peersocket_outputstream->f);
    1.71 -      }
    1.72 -    }
    1.73 -    if (fclose(moonbr_child_peersocket_outputstream->f)) {
    1.74 -      if (!err) errno2 = errno;
    1.75 -      err = -1;
    1.76 -    }
    1.77 -    moonbr_child_peersocket_outputstream->f = NULL;
    1.78 -  }
    1.79 -  if (mark) moonbr_child_peersocket_outputstream->closef = NULL;
    1.80 -  if (err) errno = errno2;
    1.81 -  return err;
    1.82 -}
    1.83 -
    1.84 -/* Perform a clean shutdown of input and output stream (may be called multiple times) */
    1.85 -static int moonbr_child_close_peersocket(int timeout) {
    1.86 -  int errprio = 0;
    1.87 -  int errno2;
    1.88 -  if (moonbr_child_peersocket_fd == -1) return 0;
    1.89 -  if (moonbr_child_close_peersocket_inputstream(1, 1)) {
    1.90 -    errprio = 1;
    1.91 -    errno2 = errno;
    1.92 -  }
    1.93 -  if (moonbr_child_close_peersocket_outputstream(1, 1)) {
    1.94 -    errprio = 4;
    1.95 -    errno2 = errno;
    1.96 -  }
    1.97 -  if (moonbr_child_peersocket_type == MOONBR_SOCKETTYPE_NETWORK) {
    1.98 -    struct linger lingerval = { 0, };
    1.99 -    if (timeout && !errprio) {
   1.100 -      lingerval.l_onoff = 1;
   1.101 -      lingerval.l_linger = timeout;
   1.102 -    }
   1.103 -    if (setsockopt(moonbr_child_peersocket_fd, SOL_SOCKET, SO_LINGER, &lingerval, sizeof(lingerval))) {
   1.104 -      if (errprio < 2) {
   1.105 -        errprio = 2;
   1.106 -        errno2 = errno;
   1.107 -      }
   1.108 -    }
   1.109 -  }
   1.110 -  if (close(moonbr_child_peersocket_fd)) {
   1.111 -    if (errprio < 3) {
   1.112 -      errprio = 3;
   1.113 -      errno2 = errno;
   1.114 -    }
   1.115 -  }
   1.116 -  moonbr_child_peersocket_fd = -1;
   1.117 -  if (errprio) {
   1.118 -    errno = errno2;
   1.119 -    return -1;
   1.120 -  }
   1.121 -  return 0;
   1.122 -}
   1.123 -
   1.124 -/* Close socket and cause reset of TCP connection (TCP RST aka "Connection reset by peer") if possible */
   1.125 -static int moonbr_child_cancel_peersocket() {
   1.126 -  int err = 0;
   1.127 -  if (moonbr_child_close_peersocket_inputstream(0, 1)) err = -1;
   1.128 -  if (moonbr_child_close_peersocket_outputstream(0, 1)) err = -1;
   1.129 -  if (close(moonbr_child_peersocket_fd)) err = -1;
   1.130 -  moonbr_child_peersocket_fd = -1;
   1.131 -  return err;
   1.132 -}
   1.133 -
   1.134 -/* Lua method for socket object to read from input stream */
   1.135 -static int moonbr_child_lua_read_stream(lua_State *L) {
   1.136 -  lua_getfield(L, 1, "input");
   1.137 -  lua_getfield(L, -1, "read");
   1.138 -  lua_insert(L, 1);
   1.139 -  lua_replace(L, 2);
   1.140 -  lua_call(L, lua_gettop(L) - 1, LUA_MULTRET);
   1.141 -  return lua_gettop(L);
   1.142 -}
   1.143 -
   1.144 -/* Lua method for socket object to read from input stream until terminator */
   1.145 -static int moonbr_child_lua_readuntil_stream(lua_State *L) {
   1.146 -  lua_getfield(L, 1, "input");
   1.147 -  lua_getfield(L, -1, "readuntil");
   1.148 -  lua_insert(L, 1);
   1.149 -  lua_replace(L, 2);
   1.150 -  lua_call(L, lua_gettop(L) - 1, LUA_MULTRET);
   1.151 -  return lua_gettop(L);
   1.152 -}
   1.153 -
   1.154 -/* Lua method for socket object to iterate over input stream */
   1.155 -static int moonbr_child_lua_lines_stream(lua_State *L) {
   1.156 -  lua_getfield(L, 1, "input");
   1.157 -  lua_getfield(L, -1, "lines");
   1.158 -  lua_insert(L, 1);
   1.159 -  lua_replace(L, 2);
   1.160 -  lua_call(L, lua_gettop(L) - 1, LUA_MULTRET);
   1.161 -  return lua_gettop(L);
   1.162 -}
   1.163 -
   1.164 -/* Lua method for socket object to write to output stream */
   1.165 -static int moonbr_child_lua_write_stream(lua_State *L) {
   1.166 -  lua_getfield(L, 1, "output");
   1.167 -  lua_getfield(L, -1, "write");
   1.168 -  lua_insert(L, 1);
   1.169 -  lua_replace(L, 2);
   1.170 -  lua_call(L, lua_gettop(L) - 1, LUA_MULTRET);
   1.171 -  return lua_gettop(L);
   1.172 -}
   1.173 -
   1.174 -/* Lua method for socket object to flush the output stream */
   1.175 -static int moonbr_child_lua_flush_stream(lua_State *L) {
   1.176 -  lua_getfield(L, 1, "output");
   1.177 -  lua_getfield(L, -1, "flush");
   1.178 -  lua_insert(L, 1);
   1.179 -  lua_replace(L, 2);
   1.180 -  lua_call(L, lua_gettop(L) - 1, LUA_MULTRET);
   1.181 -  return lua_gettop(L);
   1.182 -}
   1.183 -
   1.184 -/* Lua function to close a single stream (input or output) from/to peer */
   1.185 -static int moonbr_child_lua_close_stream(lua_State *L) {
   1.186 -  luaL_Stream *stream = lua_touserdata(L, 1);
   1.187 -  if (stream == moonbr_child_peersocket_inputstream) {
   1.188 -    if (moonbr_child_close_peersocket_inputstream(1, 0)) {  /* don't mark as closed as it's done by Lua */
   1.189 -      char errmsg[MOONBR_MAXSTRERRORLEN];
   1.190 -      strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN);  /* use thread-safe call in case child created threads */
   1.191 -      lua_pushnil(L);
   1.192 -      lua_pushfstring(L, "Could not close input stream from peer: %s", errmsg);
   1.193 -      return 2;
   1.194 -    }
   1.195 -  } else if (stream == moonbr_child_peersocket_outputstream) {
   1.196 -    if (moonbr_child_close_peersocket_outputstream(1, 0)) {  /* don't mark as closed as it's done by Lua */
   1.197 -      char errmsg[MOONBR_MAXSTRERRORLEN];
   1.198 -      strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN);  /* use thread-safe call in case child created threads */
   1.199 -      lua_pushnil(L);
   1.200 -      lua_pushfstring(L, "Could not close output stream to peer: %s", errmsg);
   1.201 -      return 2;
   1.202 -    }
   1.203 -  } else {
   1.204 -    luaL_argerror(L, 1, "Not a connection socket");
   1.205 -  }
   1.206 -  lua_pushboolean(L, 1);
   1.207 -  return 1;
   1.208 -}
   1.209 -
   1.210 -/* Lua function to close both input and output stream from/to peer */
   1.211 -static int moonbr_child_lua_close_both_streams(lua_State *L) {
   1.212 -  int timeout = 0;
   1.213 -  if (!lua_isnoneornil(L, 2)) {
   1.214 -    lua_Integer n = luaL_checkinteger(L, 2);
   1.215 -    luaL_argcheck(L, n >= 0 && n <= INT_MAX, 2, "out of range");
   1.216 -    timeout = n;
   1.217 -  }
   1.218 -  if (moonbr_child_peersocket_fd == -1) {
   1.219 -    luaL_error(L, "Connection with peer has already been explicitly closed");
   1.220 -  }
   1.221 -  if (moonbr_child_close_peersocket(timeout)) {
   1.222 -    char errmsg[MOONBR_MAXSTRERRORLEN];
   1.223 -    strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN);  /* use thread-safe call in case child created threads */
   1.224 -    lua_pushnil(L);
   1.225 -    lua_pushfstring(L, "Could not close socket connection with peer: %s", errmsg);
   1.226 -    return 2;
   1.227 -  }
   1.228 -  lua_pushboolean(L, 1);
   1.229 -  return 1;
   1.230 -}
   1.231 -
   1.232 -/* Lua function to close both input and output stream from/to peer */
   1.233 -static int moonbr_child_lua_cancel_both_streams(lua_State *L) {
   1.234 -  if (moonbr_child_peersocket_fd == -1) {
   1.235 -    luaL_error(L, "Connection with peer has already been explicitly closed");
   1.236 -  }
   1.237 -  if (moonbr_child_cancel_peersocket()) {
   1.238 -    char errmsg[MOONBR_MAXSTRERRORLEN];
   1.239 -    strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN);  /* use thread-safe call in case child created threads */
   1.240 -    lua_pushnil(L);
   1.241 -    lua_pushfstring(L, "Could not cancel socket connection with peer: %s", errmsg);
   1.242 -    return 2;
   1.243 -  }
   1.244 -  lua_pushboolean(L, 1);
   1.245 -  return 1;
   1.246 -}
   1.247 -
   1.248 -/* Methods of (bidirectional) socket object passed to handler */
   1.249 -static luaL_Reg moonbr_child_lua_socket_functions[] = {
   1.250 -  {"read", moonbr_child_lua_read_stream},
   1.251 -  {"readuntil", moonbr_child_lua_readuntil_stream},
   1.252 -  {"lines", moonbr_child_lua_lines_stream},
   1.253 -  {"write", moonbr_child_lua_write_stream},
   1.254 -  {"flush", moonbr_child_lua_flush_stream},
   1.255 -  {"close", moonbr_child_lua_close_both_streams},
   1.256 -  {"cancel", moonbr_child_lua_cancel_both_streams},
   1.257 -  {NULL, NULL}
   1.258 -};
   1.259 -
   1.260  /* Main function of child process to be called after fork() and file descriptor rearrangement */
   1.261  void moonbr_child_run(struct moonbr_pool *pool, lua_State *L) {
   1.262    char controlmsg;
   1.263 +  int fd;
   1.264    struct itimerval notimer = { { 0, }, { 0, } };
   1.265    lua_rawgetp(L, LUA_REGISTRYINDEX, moonbr_luakey_prepare_func(pool));
   1.266    if (lua_isnil(L, -1)) lua_pop(L, 1);
   1.267 @@ -1076,66 +831,20 @@
   1.268      if (write(MOONBR_FD_CONTROL, &controlmsg, 1) <= 0) {
   1.269        moonbr_child_log_errno_fatal("Error while sending ready message to parent process");
   1.270      }
   1.271 -    moonbr_child_receive_control_message(
   1.272 -      MOONBR_FD_CONTROL,
   1.273 -      &controlmsg,
   1.274 -      &moonbr_child_peersocket_fd
   1.275 -    );
   1.276 +    moonbr_child_receive_control_message(MOONBR_FD_CONTROL, &controlmsg, &fd);
   1.277      if (!(
   1.278 -      (controlmsg == MOONBR_COMMAND_TERMINATE   && moonbr_child_peersocket_fd == -1) ||
   1.279 -      (controlmsg == MOONBR_SOCKETTYPE_INTERVAL && moonbr_child_peersocket_fd == -1) ||
   1.280 -      (controlmsg == MOONBR_SOCKETTYPE_LOCAL    && moonbr_child_peersocket_fd != -1) ||
   1.281 -      (controlmsg == MOONBR_SOCKETTYPE_NETWORK  && moonbr_child_peersocket_fd != -1)
   1.282 +      (controlmsg == MOONBR_COMMAND_TERMINATE   && fd == -1) ||
   1.283 +      (controlmsg == MOONBR_SOCKETTYPE_INTERVAL && fd == -1) ||
   1.284 +      (controlmsg == MOONBR_SOCKETTYPE_LOCAL    && fd != -1) ||
   1.285 +      (controlmsg == MOONBR_SOCKETTYPE_NETWORK  && fd != -1)
   1.286      )) {
   1.287        moonbr_child_log_fatal("Received illegal control message from parent process");
   1.288      }
   1.289      if (controlmsg == MOONBR_COMMAND_TERMINATE) break;
   1.290      listener = moonbr_child_receive_pointer(MOONBR_FD_CONTROL);
   1.291 -    moonbr_child_peersocket_type = controlmsg;
   1.292 -    if (moonbr_child_peersocket_fd != -1) {
   1.293 -      {
   1.294 -        int clonedfd;
   1.295 -        clonedfd = dup(moonbr_child_peersocket_fd);
   1.296 -        if (!clonedfd) {
   1.297 -          moonbr_child_log_errno_fatal("Could not duplicate file descriptor for input stream");
   1.298 -        }
   1.299 -        moonbr_child_peersocket_inputstream = lua_newuserdata(L, sizeof(luaL_Stream));
   1.300 -        if (!moonbr_child_peersocket_inputstream) {
   1.301 -          moonbr_child_log_fatal("Memory allocation error");
   1.302 -        }
   1.303 -        moonbr_child_peersocket_inputstream->f = fdopen(clonedfd, "rb");
   1.304 -        if (!moonbr_child_peersocket_inputstream->f) {
   1.305 -          moonbr_child_log_errno_fatal("Could not open input stream for remote connection");
   1.306 -        }
   1.307 -        moonbr_child_peersocket_inputstream->closef = moonbr_child_lua_close_stream;
   1.308 -        if (luaL_newmetatable(L, LUA_FILEHANDLE)) {
   1.309 -          moonbr_child_log_fatal("Lua metatable LUA_FILEHANDLE does not exist");
   1.310 -        }
   1.311 -        lua_setmetatable(L, -2);
   1.312 -      }
   1.313 -      {
   1.314 -        int clonedfd;
   1.315 -        clonedfd = dup(moonbr_child_peersocket_fd);
   1.316 -        if (!clonedfd) {
   1.317 -          moonbr_child_log_errno_fatal("Could not duplicate file descriptor for output stream");
   1.318 -        }
   1.319 -        moonbr_child_peersocket_outputstream = lua_newuserdata(L, sizeof(luaL_Stream));
   1.320 -        if (!moonbr_child_peersocket_outputstream) {
   1.321 -          moonbr_child_log_fatal("Memory allocation error");
   1.322 -        }
   1.323 -        moonbr_child_peersocket_outputstream->f = fdopen(clonedfd, "wb");
   1.324 -        if (!moonbr_child_peersocket_outputstream->f) {
   1.325 -          moonbr_child_log_errno_fatal("Could not open output stream for remote connection");
   1.326 -        }
   1.327 -        moonbr_child_peersocket_outputstream->closef = moonbr_child_lua_close_stream;
   1.328 -        if (luaL_newmetatable(L, LUA_FILEHANDLE)) {
   1.329 -          moonbr_child_log_fatal("Lua metatable LUA_FILEHANDLE does not exist");
   1.330 -        }
   1.331 -        lua_setmetatable(L, -2);
   1.332 -      }
   1.333 -    }
   1.334 +    if (fd) moonbr_io_pushhandle(L, fd, 1, controlmsg == MOONBR_SOCKETTYPE_NETWORK);
   1.335      lua_rawgetp(L, LUA_REGISTRYINDEX, moonbr_luakey_connect_func(pool));
   1.336 -    if (listener->proto == MOONBR_PROTO_INTERVAL) {
   1.337 +    if (!fd) {
   1.338        lua_newtable(L);
   1.339        lua_pushstring(L,
   1.340          listener->proto_specific.interval.name ?
   1.341 @@ -1143,16 +852,11 @@
   1.342        );
   1.343        lua_setfield(L, -2, "interval");
   1.344      } else {
   1.345 -      lua_newtable(L);
   1.346 -      lua_pushvalue(L, -4);
   1.347 -      lua_setfield(L, -2, "input");
   1.348 -      lua_pushvalue(L, -3);
   1.349 -      lua_setfield(L, -2, "output");
   1.350 -      luaL_setfuncs(L, moonbr_child_lua_socket_functions, 0);
   1.351 +      lua_pushvalue(L, -2);
   1.352        if (listener->proto == MOONBR_PROTO_TCP6) {
   1.353          struct sockaddr_in6 addr;
   1.354          socklen_t addr_len = sizeof(struct sockaddr_in6);
   1.355 -        if (getsockname(moonbr_child_peersocket_fd, (struct sockaddr *)&addr, &addr_len)) {
   1.356 +        if (getsockname(fd, (struct sockaddr *)&addr, &addr_len)) {
   1.357            moonbr_child_log_errno("Could not get local IP address/port");
   1.358          } else {
   1.359            lua_pushlstring(L, (char *)addr.sin6_addr.s6_addr, 16);
   1.360 @@ -1160,7 +864,7 @@
   1.361            lua_pushinteger(L, ntohs(addr.sin6_port));
   1.362            lua_setfield(L, -2, "local_tcpport");
   1.363          }
   1.364 -        if (getpeername(moonbr_child_peersocket_fd, (struct sockaddr *)&addr, &addr_len)) {
   1.365 +        if (getpeername(fd, (struct sockaddr *)&addr, &addr_len)) {
   1.366            moonbr_child_log_errno("Could not get remote IP address/port");
   1.367          } else {
   1.368            lua_pushlstring(L, (char *)addr.sin6_addr.s6_addr, 16);
   1.369 @@ -1171,7 +875,7 @@
   1.370        } else if (listener->proto == MOONBR_PROTO_TCP4) {
   1.371          struct sockaddr_in addr;
   1.372          socklen_t addr_len = sizeof(struct sockaddr_in);
   1.373 -        if (getsockname(moonbr_child_peersocket_fd, (struct sockaddr *)&addr, &addr_len)) {
   1.374 +        if (getsockname(fd, (struct sockaddr *)&addr, &addr_len)) {
   1.375            moonbr_child_log_errno("Could not get local IP address/port");
   1.376          } else {
   1.377            lua_pushlstring(L, (char *)&addr.sin_addr.s_addr, 4);
   1.378 @@ -1179,7 +883,7 @@
   1.379            lua_pushinteger(L, ntohs(addr.sin_port));
   1.380            lua_setfield(L, -2, "local_tcpport");
   1.381          }
   1.382 -        if (getpeername(moonbr_child_peersocket_fd, (struct sockaddr *)&addr, &addr_len)) {
   1.383 +        if (getpeername(fd, (struct sockaddr *)&addr, &addr_len)) {
   1.384            moonbr_child_log_errno("Could not get remote IP address/port");
   1.385          } else {
   1.386            lua_pushlstring(L, (char *)&addr.sin_addr.s_addr, 4);
   1.387 @@ -1193,9 +897,7 @@
   1.388        fprintf(stderr, "Error in \"connect\" function: %s\n", lua_tostring(L, -1));
   1.389        exit(1);
   1.390      }
   1.391 -    if (moonbr_child_close_peersocket(0)) {
   1.392 -      moonbr_child_log_errno("Could not close socket connection with peer");
   1.393 -    }
   1.394 +    if (fd) moonbr_io_closehandle(L, -2, -1);  /* attemt clean close */
   1.395      if (lua_type(L, -1) != LUA_TBOOLEAN || !lua_toboolean(L, -1)) break;
   1.396  #ifdef MOONBR_LUA_PANIC_BUG_WORKAROUND
   1.397      lua_settop(L, 2);

Impressum / About Us