From abf07f3a0288f32b02b203f95c3539bf4201ad75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Thu, 16 Dec 2010 15:04:41 +0000 Subject: [PATCH] [mod_proxy]: fix delayed connect git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@2773 152afb58-edef-0310-8abb-c4023f1b3aa9 --- src/mod_proxy.c | 107 ++++++++++++++++++++++++++---------------------- 1 file changed, 59 insertions(+), 48 deletions(-) diff --git a/src/mod_proxy.c b/src/mod_proxy.c index 0e28c36b..bd826541 100644 --- a/src/mod_proxy.c +++ b/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);