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

(-)modules/proxy/mod_proxy.h (+40 lines)
Lines 234-239 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 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 868-874 Link Here
868
                                               proxy_conn_rec **conn,
872
                                               proxy_conn_rec **conn,
869
                                               proxy_worker *worker,
873
                                               proxy_worker *worker,
870
                                               server_rec *s);
874
                                               server_rec *s);
875
871
/**
876
/**
877
 * Function types usable by ap_proxy_acquire_connection_ex().
878
 */
879
typedef apr_status_t (*ap_proxy_acquire_fn)(void *baton, proxy_conn_rec **conn,
880
                                            proxy_worker *worker,
881
                                            server_rec *s);
882
typedef apr_status_t (*ap_proxy_release_fn)(void *baton, proxy_conn_rec *conn);
883
884
/**
885
 * Acquire a connection using the given @acquire function and register
886
 * a @release callback for it on cleanup, or use the worker connection
887
 * pool if the associated @baton is NULL.
888
 * @param proxy_function calling proxy scheme (http, ajp, ...)
889
 * @param conn    acquired connection
890
 * @param worker  worker used for obtaining connection
891
 * @param s       current server record
892
 * @param baton   associated baton (or conn_rec if @acquire is NULL)
893
 * @param acquire function (if not NULL) used to acquire aside connections,
894
 *                given @baton, @conn, @worker, and @s
895
 * @param release function (if not NULL) used to release acquired connection,
896
 *                given @baton, @conn, @worker, and @s, as callback
897
 * @return        OK or HTTP_XXX error
898
 * @note If the connection limit has been reached, the function will
899
 * block until a connection becomes available or the timeout has
900
 * elapsed.
901
 * @note If the given @baton is not NULL and @acquire is NULL, the baton is
902
 * considered to be a conn_rec to which the connection is attached (by worker).
903
 */
904
PROXY_DECLARE(int) ap_proxy_acquire_connection_ex(const char *proxy_function,
905
                                                  proxy_conn_rec **conn,
906
                                                  proxy_worker *worker,
907
                                                  server_rec *s, void *baton,
908
                                                  ap_proxy_acquire_fn acquire,
909
                                                  ap_proxy_release_fn release);
910
911
/**
872
 * Release a connection back to worker connection pool
912
 * Release a connection back to worker connection pool
873
 * @param proxy_function calling proxy scheme (http, ajp, ...)
913
 * @param proxy_function calling proxy scheme (http, ajp, ...)
874
 * @param conn    acquired connection
914
 * @param conn    acquired connection
(-)modules/proxy/mod_proxy_ajp.c (+6 lines)
Lines 730-735 Link Here
730
    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00895) "serving URL %s", url);
730
    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00895) "serving URL %s", url);
731
731
732
    /* create space for state information */
732
    /* create space for state information */
733
    if (apr_table_get(r->subprocess_env, "proxy-aside-c")) {
734
        status = ap_proxy_acquire_connection_ex(scheme, &backend, worker,
735
                                                r->server, r->connection,
736
                                                NULL, NULL);
737
    }
738
    else
733
    status = ap_proxy_acquire_connection(scheme, &backend, worker,
739
    status = ap_proxy_acquire_connection(scheme, &backend, worker,
734
                                         r->server);
740
                                         r->server);
735
    if (status != OK) {
741
    if (status != OK) {
(-)modules/proxy/mod_proxy_http.c (-2 / +10 lines)
Lines 1962-1969 Link Here
1962
1962
1963
1963
1964
    /* create space for state information */
1964
    /* create space for state information */
1965
    if ((status = ap_proxy_acquire_connection(proxy_function, &backend,
1965
    if (apr_table_get(r->subprocess_env, "proxy-aside-c")) {
1966
                                              worker, r->server)) != OK)
1966
        status = ap_proxy_acquire_connection_ex(proxy_function, &backend,
1967
                                                worker, r->server, c,
1968
                                                NULL, NULL);
1969
    }
1970
    else {
1971
        status = ap_proxy_acquire_connection(proxy_function, &backend,
1972
                                             worker, r->server);
1973
    }
1974
    if (status != OK)
1967
        goto cleanup;
1975
        goto cleanup;
1968
1976
1969
1977
(-)modules/proxy/proxy_util.c (-17 / +130 lines)
Lines 72-77 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 Link Here
1351
    return ! (conn->close || !worker->s->is_address_reusable || worker->s->disablereuse);
1358
    return ! (conn->close || !worker->s->is_address_reusable || worker->s->disablereuse);
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 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 (!ap_proxy_connection_reusable(conn)) {
1412
    if (!ap_proxy_connection_reusable(conn)) {
1383
        apr_pool_t *p = conn->pool;
1413
        apr_pool_t *p = conn->pool;
Lines 1402-1415 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 2151-2161 Link Here
2151
    return connected ? 0 : 1;
2173
    return connected ? 0 : 1;
2152
}
2174
}
2153
2175
2154
PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
2176
/* For the given conn_rec (baton), handle a connection per worker */
2155
                                               proxy_conn_rec **conn,
2177
static apr_status_t proxy_acquire_from_c(void *baton, proxy_conn_rec **conn,
2156
                                               proxy_worker *worker,
2178
                                         proxy_worker *worker, server_rec *s)
2157
                                               server_rec *s)
2158
{
2179
{
2180
    apr_hash_t *conns;
2181
    ap_proxy_aside_rec *aside;
2182
    conn_rec *c = baton;
2183
2184
    conns = ap_get_module_config(c->conn_config, &proxy_module);
2185
    if (!conns) {
2186
        conns = apr_hash_make(c->pool);
2187
        ap_set_module_config(c->conn_config, &proxy_module, conns);
2188
        *conn = NULL;
2189
    }
2190
    else {
2191
        *conn = apr_hash_get(conns, &worker->s, sizeof worker->s);
2192
    }
2193
    if (!*conn) {
2194
        connection_constructor((void **)conn, worker, c->pool);
2195
        apr_hash_set(conns, &worker->s, sizeof worker->s, *conn);
2196
        aside = apr_pcalloc((*conn)->pool, sizeof *aside);
2197
        (*conn)->aside = aside;
2198
    }
2199
    else {
2200
        aside = (*conn)->aside;
2201
        if (aside->expiry) {
2202
            if (apr_time_now() >= aside->expiry) {
2203
                socket_cleanup(*conn);
2204
            }
2205
            aside->expiry = 0;
2206
        }
2207
    }
2208
2209
    return APR_SUCCESS;
2210
}
2211
2212
static apr_status_t proxy_release_to_c(void *baton, proxy_conn_rec *conn)
2213
{
2214
    if (conn->worker->s->ttl) {
2215
        conn->aside->expiry = apr_time_now() +
2216
                              apr_time_from_sec(conn->worker->s->ttl);
2217
    }
2218
    else {
2219
        conn->aside->expiry = 0;
2220
    }
2221
    return APR_SUCCESS;
2222
}
2223
2224
PROXY_DECLARE(int) ap_proxy_acquire_connection_ex(const char *proxy_function,
2225
                                                  proxy_conn_rec **conn,
2226
                                                  proxy_worker *worker,
2227
                                                  server_rec *s, void *baton,
2228
                                                  ap_proxy_acquire_fn acquire,
2229
                                                  ap_proxy_release_fn release)
2230
{
2159
    apr_status_t rv;
2231
    apr_status_t rv;
2160
2232
2161
    if (!PROXY_WORKER_IS_USABLE(worker)) {
2233
    if (!PROXY_WORKER_IS_USABLE(worker)) {
Lines 2170-2176 Link Here
2170
        }
2242
        }
2171
    }
2243
    }
2172
2244
2173
    if (worker->s->hmax && worker->cp->res) {
2245
    /* Aside connection case, use the given functions.
2246
     * When a baton is given with no acquire function, it is
2247
     * assumed to be a conn_rec (to acquire from), hence the
2248
     * corresponding functions are installed.
2249
     */
2250
    if (acquire || (baton && (acquire = proxy_acquire_from_c)
2251
                          && (release = proxy_release_to_c))) {
2252
        rv = acquire(baton, conn, worker, s);
2253
        if (rv == APR_SUCCESS) {
2254
            if (!(*conn)->aside) {
2255
                (*conn)->aside = apr_pcalloc((*conn)->pool,
2256
                                             sizeof *(*conn)->aside);
2257
            }
2258
            (*conn)->aside->release = release;
2259
            (*conn)->aside->baton = baton;
2260
        }
2261
        else if (rv != APR_NOTFOUND) {
2262
            ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO()
2263
                         "%s: failed to acquire aside connection for (%s)",
2264
                         proxy_function, worker->s->hostname);
2265
            return HTTP_SERVICE_UNAVAILABLE;
2266
        }
2267
    }
2268
    else {
2269
        rv = APR_NOTFOUND;
2270
    }
2271
2272
    if (rv == APR_SUCCESS) {
2273
        /* got/use aside connection */
2274
    }
2275
    else if (worker->s->hmax && worker->cp->res) {
2174
        rv = apr_reslist_acquire(worker->cp->res, (void **)conn);
2276
        rv = apr_reslist_acquire(worker->cp->res, (void **)conn);
2175
    }
2277
    }
2176
    else {
2278
    else {
Lines 2192-2199 Link Here
2192
        return HTTP_SERVICE_UNAVAILABLE;
2294
        return HTTP_SERVICE_UNAVAILABLE;
2193
    }
2295
    }
2194
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00942)
2296
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00942)
2195
                 "%s: has acquired connection for (%s)",
2297
                 "%s: has acquired %sconnection for (%s)",
2196
                 proxy_function, worker->s->hostname);
2298
                 proxy_function, (*conn)->aside ? "aside " : "",
2299
                 worker->s->hostname);
2197
2300
2198
    (*conn)->worker = worker;
2301
    (*conn)->worker = worker;
2199
    (*conn)->close  = 0;
2302
    (*conn)->close  = 0;
Lines 2202-2214 Link Here
2202
    return OK;
2305
    return OK;
2203
}
2306
}
2204
2307
2308
PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
2309
                                               proxy_conn_rec **conn,
2310
                                               proxy_worker *worker,
2311
                                               server_rec *s)
2312
{
2313
    return ap_proxy_acquire_connection_ex(proxy_function, conn,
2314
                                          worker, s, NULL, NULL, NULL);
2315
}
2316
2205
PROXY_DECLARE(int) ap_proxy_release_connection(const char *proxy_function,
2317
PROXY_DECLARE(int) ap_proxy_release_connection(const char *proxy_function,
2206
                                               proxy_conn_rec *conn,
2318
                                               proxy_conn_rec *conn,
2207
                                               server_rec *s)
2319
                                               server_rec *s)
2208
{
2320
{
2209
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00943)
2321
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00943)
2210
                "%s: has released connection for (%s)",
2322
                 "%s: has released %sconnection for (%s)",
2211
                proxy_function, conn->worker->s->hostname);
2323
                 proxy_function, conn->aside ? "aside " : "",
2324
                 conn->worker->s->hostname);
2212
    connection_cleanup(conn);
2325
    connection_cleanup(conn);
2213
2326
2214
    return OK;
2327
    return OK;

Return to bug 39673