Browse Source

[mod_proxy]: fix delayed connect

git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@2773 152afb58-edef-0310-8abb-c4023f1b3aa9
svn/tags/lighttpd-1.4.29
Stefan Bühler 12 years ago
parent
commit
abf07f3a02
  1. 107
      src/mod_proxy.c

107
src/mod_proxy.c

@ -750,7 +750,6 @@ static int proxy_demux_response(server *srv, handler_ctx *hctx) {
static handler_t proxy_write_request(server *srv, handler_ctx *hctx) {
data_proxy *host= hctx->host;
plugin_data *p = hctx->plugin_data;
connection *con = hctx->remote_conn;
int ret;
@ -759,6 +758,17 @@ static handler_t proxy_write_request(server *srv, handler_ctx *hctx) {
(!host->host->used || !host->port)) return -1;
switch(hctx->state) {
case PROXY_STATE_CONNECT:
/* wait for the connect() to finish */
/* connect failed ? */
if (-1 == hctx->fde_ndx) return HANDLER_ERROR;
/* wait */
return HANDLER_WAIT_FOR_EVENT;
break;
case PROXY_STATE_INIT:
#if defined(HAVE_IPV6) && defined(HAVE_INET_PTON)
if (strstr(host->host->ptr,":")) {
@ -786,58 +796,28 @@ static handler_t proxy_write_request(server *srv, handler_ctx *hctx) {
return HANDLER_ERROR;
}
/* fall through */
case PROXY_STATE_CONNECT:
/* try to finish the connect() */
if (hctx->state == PROXY_STATE_INIT) {
/* first round */
switch (proxy_establish_connection(srv, hctx)) {
case 1:
proxy_set_state(srv, hctx, PROXY_STATE_CONNECT);
/* connection is in progress, wait for an event and call getsockopt() below */
fdevent_event_set(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
return HANDLER_WAIT_FOR_EVENT;
case -1:
/* if ECONNREFUSED choose another connection -> FIXME */
hctx->fde_ndx = -1;
return HANDLER_ERROR;
default:
/* everything is ok, go on */
break;
}
} else {
int socket_error;
socklen_t socket_error_len = sizeof(socket_error);
switch (proxy_establish_connection(srv, hctx)) {
case 1:
proxy_set_state(srv, hctx, PROXY_STATE_CONNECT);
/* we don't need it anymore */
fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
/* connection is in progress, wait for an event and call getsockopt() below */
/* try to finish the connect() */
if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
log_error_write(srv, __FILE__, __LINE__, "ss",
"getsockopt failed:", strerror(errno));
fdevent_event_set(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
return HANDLER_ERROR;
}
if (socket_error != 0) {
log_error_write(srv, __FILE__, __LINE__, "ss",
"establishing connection failed:", strerror(socket_error),
"port:", hctx->host->port);
return HANDLER_WAIT_FOR_EVENT;
case -1:
/* if ECONNREFUSED choose another connection -> FIXME */
hctx->fde_ndx = -1;
return HANDLER_ERROR;
}
if (p->conf.debug) {
log_error_write(srv, __FILE__, __LINE__, "s", "proxy - connect - delayed success");
}
return HANDLER_ERROR;
default:
/* everything is ok, go on */
proxy_set_state(srv, hctx, PROXY_STATE_PREPARE_WRITE);
break;
}
proxy_set_state(srv, hctx, PROXY_STATE_PREPARE_WRITE);
/* fall through */
case PROXY_STATE_PREPARE_WRITE:
proxy_create_env(srv, hctx);
@ -1019,11 +999,42 @@ static handler_t proxy_handle_fdevent(server *srv, void *ctx, int revents) {
"proxy: fdevent-out", hctx->state);
}
if (hctx->state == PROXY_STATE_CONNECT ||
if (hctx->state == PROXY_STATE_CONNECT) {
int socket_error;
socklen_t socket_error_len = sizeof(socket_error);
/* we don't need it anymore */
fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
hctx->fde_ndx = -1;
/* try to finish the connect() */
if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
log_error_write(srv, __FILE__, __LINE__, "ss",
"getsockopt failed:", strerror(errno));
joblist_append(srv, con);
return HANDLER_FINISHED;
}
if (socket_error != 0) {
log_error_write(srv, __FILE__, __LINE__, "ss",
"establishing connection failed:", strerror(socket_error),
"port:", hctx->host->port);
joblist_append(srv, con);
return HANDLER_FINISHED;
}
if (p->conf.debug) {
log_error_write(srv, __FILE__, __LINE__, "s", "proxy - connect - delayed success");
}
proxy_set_state(srv, hctx, PROXY_STATE_PREPARE_WRITE);
}
if (hctx->state == PROXY_STATE_PREPARE_WRITE ||
hctx->state == PROXY_STATE_WRITE) {
/* we are allowed to send something out
*
* 1. in a unfinished connect() call
* 1. after a just finished connect() call
* 2. in a unfinished write() call (long POST request)
*/
return mod_proxy_handle_subrequest(srv, con, p);

Loading…
Cancel
Save