]> granicus.if.org Git - apache/commitdiff
Add ap_proxy_connect_backend that will replace
authorWilliam A. Rowe Jr <wrowe@apache.org>
Wed, 11 Aug 2004 22:34:26 +0000 (22:34 +0000)
committerWilliam A. Rowe Jr <wrowe@apache.org>
Wed, 11 Aug 2004 22:34:26 +0000 (22:34 +0000)
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

modules/proxy/mod_proxy.h
modules/proxy/proxy_util.c

index 5ff4508c3664c0cf1929d5861ce402553b52a6fe..be55b9db6b63ab5f96c48baaa28d0ad9f85fdb9a 100644 (file)
@@ -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;
index 50f73bda0855822341a7fb8f4d97bfa53c75a53d..9cbd1937e2e7c521a15848c65444ce4bf5a4f0c8 100644 (file)
@@ -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, &current_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;
+}