From: William A. Rowe Jr Date: Wed, 11 Aug 2004 22:34:26 +0000 (+0000) Subject: Add ap_proxy_connect_backend that will replace X-Git-Tag: post_ajp_proxy~35 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5ead791f0ee4f7ad512bca9d6dafef374927746f;p=apache Add ap_proxy_connect_backend that will replace ap_proxy_connect_to_backend. It uses worker params for setting socket options and checks for conection's connect status. It works both on empty and acquired connections. Submitted by: mturk git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@104595 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h index 5ff4508c36..be55b9db6b 100644 --- a/modules/proxy/mod_proxy.h +++ b/modules/proxy/mod_proxy.h @@ -235,6 +235,7 @@ struct proxy_worker { char recv_buffer_size_set; apr_size_t io_buffer_size; char io_buffer_size_set; + char keepalive; proxy_conn_pool *cp; /* Connection pool to use */ void *opaque; /* per scheme worker data */ }; @@ -343,6 +344,7 @@ PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *c PROXY_DECLARE(int) ap_proxy_pre_http_request(conn_rec *c, request_rec *r); PROXY_DECLARE(apr_status_t) ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb, char *buff, size_t bufflen, int *eos); PROXY_DECLARE(void) ap_proxy_table_unmerge(apr_pool_t *p, apr_table_t *t, char *key); +/* DEPRECATED (will be replaced with ap_proxy_connect_backend */ PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr_socket_t **, const char *, apr_sockaddr_t *, const char *, proxy_server_conf *, server_rec *, apr_pool_t *); PROXY_DECLARE(int) ap_proxy_ssl_enable(conn_rec *c); PROXY_DECLARE(int) ap_proxy_ssl_disable(conn_rec *c); @@ -359,7 +361,8 @@ PROXY_DECLARE(apr_status_t) ap_proxy_determine_connection(apr_pool_t *p, request char *server_portstr, int server_portstr_size); PROXY_DECLARE(apr_status_t) ap_proxy_destroy_connection(proxy_conn_rec *conn); PROXY_DECLARE(apr_status_t) ap_proxy_close_connection(proxy_conn_rec *conn); - +PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function, proxy_conn_rec *conn, proxy_worker *worker, + proxy_server_conf *conf, server_rec *s); /* For proxy_util */ extern module PROXY_DECLARE_DATA proxy_module; diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c index 50f73bda08..9cbd1937e2 100644 --- a/modules/proxy/proxy_util.c +++ b/modules/proxy/proxy_util.c @@ -1242,6 +1242,7 @@ PROXY_DECLARE(int) ap_proxy_post_request(proxy_worker *worker, return access_status; } +/* DEPRECATED */ PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr_socket_t **newsock, const char *proxy_function, apr_sockaddr_t *backend_addr, @@ -1536,7 +1537,7 @@ static int is_socket_connected(apr_socket_t *sock) char test_buffer[1]; apr_status_t socket_status; apr_interval_time_t current_timeout; - + /* save timeout */ apr_socket_timeout_get(sock, ¤t_timeout); /* set no timeout */ @@ -1549,3 +1550,95 @@ static int is_socket_connected(apr_socket_t *sock) else return 1; } + +PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function, + proxy_conn_rec *conn, + proxy_worker *worker, + proxy_server_conf *conf, + server_rec *s) +{ + apr_status_t rv; + int connected = 0; + int loglevel; + apr_sockaddr_t *backend_addr = worker->cp->addr; + apr_socket_t *newsock; + + if (conn->sock) { + /* This increases the connection pool size + * but the number of dropped connections is + * relatively small compared to connection lifetime + */ + if (!(connected = is_socket_connected(conn->sock))) { + apr_socket_close(conn->sock); + conn->sock = NULL; + } + } + + while (backend_addr && !connected) { + if ((rv = apr_socket_create(&newsock, backend_addr->family, + SOCK_STREAM, 0, conn->pool)) != APR_SUCCESS) { + loglevel = backend_addr->next ? APLOG_DEBUG : APLOG_ERR; + ap_log_error(APLOG_MARK, loglevel, rv, s, + "proxy: %s: error creating fam %d socket for target %s", + proxy_function, + backend_addr->family, + worker->hostname); + /* this could be an IPv6 address from the DNS but the + * local machine won't give us an IPv6 socket; hopefully the + * DNS returned an additional address to try + */ + backend_addr = backend_addr->next; + continue; + } + +#if !defined(TPF) && !defined(BEOS) + if (conf->recv_buffer_size > 0 && + (rv = apr_socket_opt_set(newsock, APR_SO_RCVBUF, + conf->recv_buffer_size))) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, + "apr_socket_opt_set(SO_RCVBUF): Failed to set " + "ProxyReceiveBufferSize, using default"); + } +#endif + + /* Set a timeout on the socket */ + if (worker->timeout_set == 1) { + apr_socket_timeout_set(newsock, worker->timeout); + } + else { + apr_socket_timeout_set(newsock, s->timeout); + } + /* Set a keepalive option */ + if (worker->keepalive) { + if ((rv = apr_socket_opt_set(newsock, + APR_SO_KEEPALIVE, 1)) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, + "apr_socket_opt_set(SO_KEEPALIVE): Failed to set" + " Keepalive"); + } + } + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + "proxy: %s: fam %d socket created to connect to %s", + proxy_function, backend_addr->family, worker->hostname); + + /* make the connection out of the socket */ + rv = apr_socket_connect(newsock, backend_addr); + + /* if an error occurred, loop round and try again */ + if (rv != APR_SUCCESS) { + apr_socket_close(newsock); + loglevel = backend_addr->next ? APLOG_DEBUG : APLOG_ERR; + ap_log_error(APLOG_MARK, loglevel, rv, s, + "proxy: %s: attempt to connect to %pI (%s) failed", + proxy_function, + backend_addr, + worker->hostname); + backend_addr = backend_addr->next; + continue; + } + conn->sock = newsock; + conn->worker = worker; + connected = 1; + } + return connected ? 0 : 1; +}