|
|
|
@ -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); |
|
|
|
|