View | Details | Raw Unified | Return to bug 39673
Collapse All | Expand All

(-)modules/proxy/mod_proxy.h (+40 lines)
Lines 234-239 typedef struct { Link Here
234
    apr_array_header_t* cookie_domains;
234
    apr_array_header_t* cookie_domains;
235
} proxy_req_conf;
235
} proxy_req_conf;
236
236
237
/* Opaque aside connection record */
238
typedef struct ap_proxy_aside_rec ap_proxy_aside_rec;
239
237
typedef struct {
240
typedef struct {
238
    conn_rec     *connection;
241
    conn_rec     *connection;
239
    request_rec  *r;           /* Request record of the backend request
242
    request_rec  *r;           /* Request record of the backend request
Lines 255-260 typedef struct { Link Here
255
    unsigned int inreslist:1;  /* connection in apr_reslist? */
258
    unsigned int inreslist:1;  /* connection in apr_reslist? */
256
    const char   *uds_path;    /* Unix domain socket path */
259
    const char   *uds_path;    /* Unix domain socket path */
257
    const char   *ssl_hostname;/* Hostname (SNI) in use by SSL connection */
260
    const char   *ssl_hostname;/* Hostname (SNI) in use by SSL connection */
261
    ap_proxy_aside_rec *aside; /* Aside context */
258
} proxy_conn_rec;
262
} proxy_conn_rec;
259
263
260
typedef struct {
264
typedef struct {
Lines 840-846 PROXY_DECLARE(int) ap_proxy_acquire_connection(con Link Here
840
                                               proxy_conn_rec **conn,
844
                                               proxy_conn_rec **conn,
841
                                               proxy_worker *worker,
845
                                               proxy_worker *worker,
842
                                               server_rec *s);
846
                                               server_rec *s);
847
843
/**
848
/**
849
 * Function types usable by ap_proxy_acquire_connection_ex().
850
 */
851
typedef apr_status_t (*ap_proxy_acquire_fn)(void *baton, proxy_conn_rec **conn,
852
                                            proxy_worker *worker,
853
                                            server_rec *s);
854
typedef apr_status_t (*ap_proxy_release_fn)(void *baton, proxy_conn_rec *conn);
855
856
/**
857
 * Acquire a connection using the given @acquire function and register
858
 * a @release callback for it on cleanup, or use the worker connection
859
 * pool if the associated @baton is NULL.
860
 * @param proxy_function calling proxy scheme (http, ajp, ...)
861
 * @param conn    acquired connection
862
 * @param worker  worker used for obtaining connection
863
 * @param s       current server record
864
 * @param baton   associated baton (or conn_rec if @acquire is NULL)
865
 * @param acquire function (if not NULL) used to acquire aside connections,
866
 *                given @baton, @conn, @worker, and @s
867
 * @param release function (if not NULL) used to release acquired connection,
868
 *                given @baton, @conn, @worker, and @s, as callback
869
 * @return        OK or HTTP_XXX error
870
 * @note If the connection limit has been reached, the function will
871
 * block until a connection becomes available or the timeout has
872
 * elapsed.
873
 * @note If the given @baton is not NULL and @acquire is NULL, the baton is
874
 * considered to be a conn_rec to which the connection is attached (by worker).
875
 */
876
PROXY_DECLARE(int) ap_proxy_acquire_connection_ex(const char *proxy_function,
877
                                                  proxy_conn_rec **conn,
878
                                                  proxy_worker *worker,
879
                                                  server_rec *s, void *baton,
880
                                                  ap_proxy_acquire_fn acquire,
881
                                                  ap_proxy_release_fn release);
882
883
/**
844
 * Release a connection back to worker connection pool
884
 * Release a connection back to worker connection pool
845
 * @param proxy_function calling proxy scheme (http, ajp, ...)
885
 * @param proxy_function calling proxy scheme (http, ajp, ...)
846
 * @param conn    acquired connection
886
 * @param conn    acquired connection
(-)modules/proxy/mod_proxy_http.c (-2 / +10 lines)
Lines 1924-1931 static int proxy_http_handler(request_rec *r, prox Link Here
1924
1924
1925
1925
1926
    /* create space for state information */
1926
    /* create space for state information */
1927
    if ((status = ap_proxy_acquire_connection(proxy_function, &backend,
1927
    if (apr_table_get(r->subprocess_env, "proxy-aside-c")) {
1928
                                              worker, r->server)) != OK)
1928
        status = ap_proxy_acquire_connection_ex(proxy_function, &backend,
1929
                                                worker, r->server, c,
1930
                                                NULL, NULL);
1931
    }
1932
    else {
1933
        status = ap_proxy_acquire_connection(proxy_function, &backend,
1934
                                             worker, r->server);
1935
    }
1936
    if (status != OK)
1929
        goto cleanup;
1937
        goto cleanup;
1930
1938
1931
1939
(-)modules/proxy/mod_proxy_ajp.c (+6 lines)
Lines 718-723 static int proxy_ajp_handler(request_rec *r, proxy Link Here
718
    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00895) "serving URL %s", url);
718
    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00895) "serving URL %s", url);
719
719
720
    /* create space for state information */
720
    /* create space for state information */
721
    if (apr_table_get(r->subprocess_env, "proxy-aside-c")) {
722
        status = ap_proxy_acquire_connection_ex(scheme, &backend, worker,
723
                                                r->server, r->connection,
724
                                                NULL, NULL);
725
    }
726
    else
721
    status = ap_proxy_acquire_connection(scheme, &backend, worker,
727
    status = ap_proxy_acquire_connection(scheme, &backend, worker,
722
                                         r->server);
728
                                         r->server);
723
    if (status != OK) {
729
    if (status != OK) {
(-)modules/proxy/proxy_util.c (-17 / +129 lines)
Lines 72-77 static struct wstat { Link Here
72
    {0x0, '\0', NULL}
72
    {0x0, '\0', NULL}
73
};
73
};
74
74
75
/* Opaque aside connection record */
76
struct ap_proxy_aside_rec {
77
    void *baton;
78
    ap_proxy_release_fn release;
79
    apr_time_t expiry; /* idle connection expiry */
80
};
81
75
/* Global balancer counter */
82
/* Global balancer counter */
76
int PROXY_DECLARE_DATA proxy_lb_workers = 0;
83
int PROXY_DECLARE_DATA proxy_lb_workers = 0;
77
static int lb_workers_limit = 0;
84
static int lb_workers_limit = 0;
Lines 1351-1356 static void init_conn_pool(apr_pool_t *p, proxy_wo Link Here
1351
    worker->cp = cp;
1358
    worker->cp = cp;
1352
}
1359
}
1353
1360
1361
static void socket_cleanup(proxy_conn_rec *conn)
1362
{
1363
    conn->sock = NULL;
1364
    conn->connection = NULL;
1365
    conn->ssl_hostname = NULL;
1366
    apr_pool_clear(conn->scpool);
1367
}
1368
1354
static apr_status_t connection_cleanup(void *theconn)
1369
static apr_status_t connection_cleanup(void *theconn)
1355
{
1370
{
1356
    proxy_conn_rec *conn = (proxy_conn_rec *)theconn;
1371
    proxy_conn_rec *conn = (proxy_conn_rec *)theconn;
Lines 1378-1383 static apr_status_t connection_cleanup(void *theco Link Here
1378
        return APR_SUCCESS;
1393
        return APR_SUCCESS;
1379
    }
1394
    }
1380
1395
1396
    /* If the connection is aside (not acquired from the reslist),
1397
     * let it be released by the callback if any, or live with its
1398
     * parent pool otherwise (still ensuring it is closed if asked to).
1399
     */
1400
    if (conn->aside) {
1401
        if (conn->close) {
1402
            socket_cleanup(conn);
1403
            conn->close = 0;
1404
        }
1405
        if (conn->aside->release) {
1406
            conn->aside->release(conn->aside->baton, conn);
1407
        }
1408
        return APR_SUCCESS;
1409
    }
1410
1381
    /* determine if the connection need to be closed */
1411
    /* determine if the connection need to be closed */
1382
    if (conn->close || !worker->s->is_address_reusable || worker->s->disablereuse) {
1412
    if (conn->close || !worker->s->is_address_reusable || worker->s->disablereuse) {
1383
        apr_pool_t *p = conn->pool;
1413
        apr_pool_t *p = conn->pool;
Lines 1402-1415 static apr_status_t connection_cleanup(void *theco Link Here
1402
    return APR_SUCCESS;
1432
    return APR_SUCCESS;
1403
}
1433
}
1404
1434
1405
static void socket_cleanup(proxy_conn_rec *conn)
1406
{
1407
    conn->sock = NULL;
1408
    conn->connection = NULL;
1409
    conn->ssl_hostname = NULL;
1410
    apr_pool_clear(conn->scpool);
1411
}
1412
1413
PROXY_DECLARE(apr_status_t) ap_proxy_ssl_connection_cleanup(proxy_conn_rec *conn,
1435
PROXY_DECLARE(apr_status_t) ap_proxy_ssl_connection_cleanup(proxy_conn_rec *conn,
1414
                                                            request_rec *r)
1436
                                                            request_rec *r)
1415
{
1437
{
Lines 2086-2096 PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr Link Here
2086
    return connected ? 0 : 1;
2108
    return connected ? 0 : 1;
2087
}
2109
}
2088
2110
2089
PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
2111
/* For the given conn_rec (baton), handle a connection per worker */
2090
                                               proxy_conn_rec **conn,
2112
static apr_status_t proxy_acquire_from_c(void *baton, proxy_conn_rec **conn,
2091
                                               proxy_worker *worker,
2113
                                         proxy_worker *worker, server_rec *s)
2092
                                               server_rec *s)
2093
{
2114
{
2115
    apr_hash_t *conns;
2116
    ap_proxy_aside_rec *aside;
2117
    conn_rec *c = baton;
2118
2119
    conns = ap_get_module_config(c->conn_config, &proxy_module);
2120
    if (!conns) {
2121
        conns = apr_hash_make(c->pool);
2122
        ap_set_module_config(c->conn_config, &proxy_module, conns);
2123
        *conn = NULL;
2124
    }
2125
    else {
2126
        *conn = apr_hash_get(conns, &worker->s, sizeof worker->s);
2127
    }
2128
    if (!*conn) {
2129
        connection_constructor((void **)conn, worker, c->pool);
2130
        aside = apr_pcalloc((*conn)->pool, sizeof *aside);
2131
        (*conn)->aside = aside;
2132
    }
2133
    else {
2134
        aside = (*conn)->aside;
2135
        if (aside->expiry) {
2136
            if (apr_time_now() >= aside->expiry) {
2137
                socket_cleanup(*conn);
2138
            }
2139
            aside->expiry = 0;
2140
        }
2141
    }
2142
2143
    return APR_SUCCESS;
2144
}
2145
2146
static apr_status_t proxy_release_to_c(void *baton, proxy_conn_rec *conn)
2147
{
2148
    if (conn->worker->s->ttl) {
2149
        conn->aside->expiry = apr_time_now() +
2150
                              apr_time_from_sec(conn->worker->s->ttl);
2151
    }
2152
    else {
2153
        conn->aside->expiry = 0;
2154
    }
2155
    return APR_SUCCESS;
2156
}
2157
2158
PROXY_DECLARE(int) ap_proxy_acquire_connection_ex(const char *proxy_function,
2159
                                                  proxy_conn_rec **conn,
2160
                                                  proxy_worker *worker,
2161
                                                  server_rec *s, void *baton,
2162
                                                  ap_proxy_acquire_fn acquire,
2163
                                                  ap_proxy_release_fn release)
2164
{
2094
    apr_status_t rv;
2165
    apr_status_t rv;
2095
2166
2096
    if (!PROXY_WORKER_IS_USABLE(worker)) {
2167
    if (!PROXY_WORKER_IS_USABLE(worker)) {
Lines 2105-2111 PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr Link Here
2105
        }
2176
        }
2106
    }
2177
    }
2107
2178
2108
    if (worker->s->hmax && worker->cp->res) {
2179
    /* Aside connection case, use the given functions.
2180
     * When a baton is given with no acquire function, it is
2181
     * assumed to be a conn_rec (to acquire from), hence the
2182
     * corresponding functions are installed.
2183
     */
2184
    if (acquire || (baton && (acquire = proxy_acquire_from_c)
2185
                          && (release = proxy_release_to_c))) {
2186
        rv = acquire(baton, conn, worker, s);
2187
        if (rv == APR_SUCCESS) {
2188
            if (!(*conn)->aside) {
2189
                (*conn)->aside = apr_pcalloc((*conn)->pool,
2190
                                             sizeof *(*conn)->aside);
2191
            }
2192
            (*conn)->aside->release = release;
2193
            (*conn)->aside->baton = baton;
2194
        }
2195
        else if (rv != APR_NOTFOUND) {
2196
            ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO()
2197
                         "%s: failed to acquire aside connection for (%s)",
2198
                         proxy_function, worker->s->hostname);
2199
            return HTTP_SERVICE_UNAVAILABLE;
2200
        }
2201
    }
2202
    else {
2203
        rv = APR_NOTFOUND;
2204
    }
2205
2206
    if (rv == APR_SUCCESS) {
2207
        /* got/use aside connection */
2208
    }
2209
    else if (worker->s->hmax && worker->cp->res) {
2109
        rv = apr_reslist_acquire(worker->cp->res, (void **)conn);
2210
        rv = apr_reslist_acquire(worker->cp->res, (void **)conn);
2110
    }
2211
    }
2111
    else {
2212
    else {
Lines 2127-2134 PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr Link Here
2127
        return HTTP_SERVICE_UNAVAILABLE;
2228
        return HTTP_SERVICE_UNAVAILABLE;
2128
    }
2229
    }
2129
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00942)
2230
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00942)
2130
                 "%s: has acquired connection for (%s)",
2231
                 "%s: has acquired %sconnection for (%s)",
2131
                 proxy_function, worker->s->hostname);
2232
                 proxy_function, (*conn)->aside ? "aside " : "",
2233
                 worker->s->hostname);
2132
2234
2133
    (*conn)->worker = worker;
2235
    (*conn)->worker = worker;
2134
    (*conn)->close  = 0;
2236
    (*conn)->close  = 0;
Lines 2137-2149 PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr Link Here
2137
    return OK;
2239
    return OK;
2138
}
2240
}
2139
2241
2242
PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
2243
                                               proxy_conn_rec **conn,
2244
                                               proxy_worker *worker,
2245
                                               server_rec *s)
2246
{
2247
    return ap_proxy_acquire_connection_ex(proxy_function, conn,
2248
                                          worker, s, NULL, NULL, NULL);
2249
}
2250
2140
PROXY_DECLARE(int) ap_proxy_release_connection(const char *proxy_function,
2251
PROXY_DECLARE(int) ap_proxy_release_connection(const char *proxy_function,
2141
                                               proxy_conn_rec *conn,
2252
                                               proxy_conn_rec *conn,
2142
                                               server_rec *s)
2253
                                               server_rec *s)
2143
{
2254
{
2144
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00943)
2255
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00943)
2145
                "%s: has released connection for (%s)",
2256
                 "%s: has released %sconnection for (%s)",
2146
                proxy_function, conn->worker->s->hostname);
2257
                 proxy_function, conn->aside ? "aside " : "",
2258
                 conn->worker->s->hostname);
2147
    connection_cleanup(conn);
2259
    connection_cleanup(conn);
2148
2260
2149
    return OK;
2261
    return OK;

Return to bug 39673