proxy_util.c

来自「apache服务器源代码(版本号:2.2.2)」· C语言 代码 · 共 2,057 行 · 第 1/5 页

C
2,057
字号
    if (c) {        char *pathstart;        pathstart = url_copy + (c - url);        *pathstart = '\0';        ap_str_tolower(url_copy);        *pathstart = '/';    } else {        ap_str_tolower(url_copy);    }    worker = (proxy_worker *)conf->workers->elts;    /*     * Do a "longest match" on the worker name to find the worker that     * fits best to the URL.     */    for (i = 0; i < conf->workers->nelts; i++) {        if ( ((worker_name_length = strlen(worker->name)) <= url_length)           && (worker_name_length > max_match)           && (strncmp(url_copy, worker->name, worker_name_length) == 0) ) {            max_worker = worker;            max_match = worker_name_length;        }        worker++;    }    return max_worker;}#if APR_HAS_THREADSstatic apr_status_t conn_pool_cleanup(void *theworker){    proxy_worker *worker = (proxy_worker *)theworker;    if (worker->cp->res) {        worker->cp->pool = NULL;        apr_reslist_destroy(worker->cp->res);    }    return APR_SUCCESS;}#endifstatic void init_conn_pool(apr_pool_t *p, proxy_worker *worker){    apr_pool_t *pool;    proxy_conn_pool *cp;    /*     * Create a connection pool's subpool.     * This pool is used for connection recycling.     * Once the worker is added it is never removed but     * it can be disabled.     */    apr_pool_create(&pool, p);    /*     * Alloc from the same pool as worker.     * proxy_conn_pool is permanently attached to the worker.     */    cp = (proxy_conn_pool *)apr_pcalloc(p, sizeof(proxy_conn_pool));    cp->pool = pool;    worker->cp = cp;}PROXY_DECLARE(const char *) ap_proxy_add_worker(proxy_worker **worker,                                                apr_pool_t *p,                                                proxy_server_conf *conf,                                                const char *url){    int rv;    apr_uri_t uri;    rv = apr_uri_parse(p, url, &uri);    if (rv != APR_SUCCESS) {        return "Unable to parse URL";    }    if (!uri.hostname || !uri.scheme) {        return "URL must be absolute!";    }    ap_str_tolower(uri.hostname);    ap_str_tolower(uri.scheme);    *worker = apr_array_push(conf->workers);    memset(*worker, 0, sizeof(proxy_worker));    (*worker)->name = apr_uri_unparse(p, &uri, APR_URI_UNP_REVEALPASSWORD);    (*worker)->scheme = uri.scheme;    (*worker)->hostname = uri.hostname;    (*worker)->port = uri.port;    (*worker)->id   = proxy_lb_workers;    (*worker)->flush_packets = flush_off;    (*worker)->flush_wait = PROXY_FLUSH_WAIT;    /* Increase the total worker count */    proxy_lb_workers++;    init_conn_pool(p, *worker);#if APR_HAS_THREADS    if (apr_thread_mutex_create(&((*worker)->mutex),                APR_THREAD_MUTEX_DEFAULT, p) != APR_SUCCESS) {        /* XXX: Do we need to log something here */        return "can not create thread mutex";    }#endif    return NULL;}PROXY_DECLARE(proxy_worker *) ap_proxy_create_worker(apr_pool_t *p){    proxy_worker *worker;    worker = (proxy_worker *)apr_pcalloc(p, sizeof(proxy_worker));    worker->id = proxy_lb_workers;    /* Increase the total worker count */    proxy_lb_workers++;    init_conn_pool(p, worker);    return worker;}PROXY_DECLARE(void)ap_proxy_add_worker_to_balancer(apr_pool_t *pool, proxy_balancer *balancer,                                proxy_worker *worker){    proxy_worker *runtime;    runtime = apr_array_push(balancer->workers);    memcpy(runtime, worker, sizeof(proxy_worker));    runtime->id = proxy_lb_workers;    /* Increase the total runtime count */    proxy_lb_workers++;}PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,                                        proxy_balancer **balancer,                                        request_rec *r,                                        proxy_server_conf *conf, char **url){    int access_status;    access_status = proxy_run_pre_request(worker, balancer, r, conf, url);    if (access_status == DECLINED && *balancer == NULL) {        *worker = ap_proxy_get_worker(r->pool, conf, *url);        if (*worker) {            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,                          "proxy: %s: found worker %s for %s",                           (*worker)->scheme, (*worker)->name, *url);            *balancer = NULL;            access_status = OK;        }        else if (r->proxyreq == PROXYREQ_PROXY) {            if (conf->forward) {                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,                              "proxy: *: found forward proxy worker for %s",                               *url);                *balancer = NULL;                *worker = conf->forward;                access_status = OK;            }        }        else if (r->proxyreq == PROXYREQ_REVERSE) {            if (conf->reverse) {                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,                              "proxy: *: found reverse proxy worker for %s",                               *url);                *balancer = NULL;                *worker = conf->reverse;                access_status = OK;            }        }    }    else if (access_status == DECLINED && *balancer != NULL) {        /* All the workers are busy */        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,          "proxy: all workers are busy.  Unable to serve %s",          *url);        access_status = HTTP_SERVICE_UNAVAILABLE;    }    return access_status;}PROXY_DECLARE(int) ap_proxy_post_request(proxy_worker *worker,                                         proxy_balancer *balancer,                                         request_rec *r,                                         proxy_server_conf *conf){    int access_status;    if (balancer)        access_status = proxy_run_post_request(worker, balancer, r, conf);    else {        access_status = OK;    }    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,                                               const char *backend_name,                                               proxy_server_conf *conf,                                               server_rec *s,                                               apr_pool_t *p){    apr_status_t rv;    int connected = 0;    int loglevel;    while (backend_addr && !connected) {        if ((rv = apr_socket_create(newsock, backend_addr->family,                                    SOCK_STREAM, 0, p)) != 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,                         backend_name);            /*             * 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 (conf->timeout_set == 1) {            apr_socket_timeout_set(*newsock, conf->timeout);        }        else {             apr_socket_timeout_set(*newsock, s->timeout);        }        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,                     "proxy: %s: fam %d socket created to connect to %s",                     proxy_function, backend_addr->family, backend_name);        /* 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,                         backend_name);            backend_addr = backend_addr->next;            continue;        }        connected = 1;    }    return connected ? 0 : 1;}static apr_status_t connection_cleanup(void *theconn){    proxy_conn_rec *conn = (proxy_conn_rec *)theconn;    proxy_worker *worker = conn->worker;    /*     * If the connection pool is NULL the worker     * cleanup has been run. Just return.     */    if (!worker->cp)        return APR_SUCCESS;#if APR_HAS_THREADS    /* Sanity check: Did we already return the pooled connection? */    if (conn->inreslist) {        ap_log_perror(APLOG_MARK, APLOG_ERR, 0, conn->pool,                      "proxy: Pooled connection 0x%pp for worker %s has been"                      " already returned to the connection pool.", conn,                      worker->name);        return APR_SUCCESS;    }#endif    /* determine if the connection need to be closed */    if (conn->close_on_recycle || conn->close) {        apr_pool_t *p = conn->pool;        apr_pool_clear(conn->pool);        memset(conn, 0, sizeof(proxy_conn_rec));        conn->pool = p;        conn->worker = worker;    }#if APR_HAS_THREADS    if (worker->hmax && worker->cp->res) {        conn->inreslist = 1;        apr_reslist_release(worker->cp->res, (void *)conn);    }    else#endif    {        worker->cp->conn = conn;    }    /* Allways return the SUCCESS */    return APR_SUCCESS;}/* reslist constructor */static apr_status_t connection_constructor(void **resource, void *params,                                           apr_pool_t *pool){    apr_pool_t *ctx;    proxy_conn_rec *conn;    proxy_worker *worker = (proxy_worker *)params;    /*     * Create the subpool for each connection     * This keeps the memory consumption constant     * when disconnecting from backend.     */    apr_pool_create(&ctx, pool);    conn = apr_pcalloc(pool, sizeof(proxy_conn_rec));    conn->pool   = ctx;    conn->worker = worker;#if APR_HAS_THREADS    conn->inreslist = 1;#endif    *resource = conn;    return APR_SUCCESS;}#if APR_HAS_THREADS /* only needed when threads are used *//* reslist destructor */static apr_status_t connection_destructor(void *resource, void *params,                                          apr_pool_t *pool){    proxy_conn_rec *conn = (proxy_conn_rec *)resource;    /* Destroy the pool only if not called from reslist_destroy */    if (conn->worker->cp->pool)        apr_pool_destroy(conn->pool);    return APR_SUCCESS;}#endif/* * ap_proxy_initialize_worker_share() concerns itself * with initializing those parts of worker which * are, or could be, shared. Basically worker->s */PROXY_DECLARE(void) ap_proxy_initialize_worker_share(proxy_server_conf *conf,                                                     proxy_worker *worker,                                                     server_rec *s){#if PROXY_HAS_SCOREBOARD    lb_score *score = NULL;#else    void *score = NULL;#endif    if (worker->s && (worker->s->status & PROXY_WORKER_INITIALIZED)) {        /* The worker share is already initialized */        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,              "proxy: worker %s already initialized",              worker->name);        return;    }#if PROXY_HAS_SCOREBOARD        /* Get scoreboard slot */    if (ap_scoreboard_image) {        score = ap_get_scoreboard_lb(worker->id);        if (!score) {            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,                  "proxy: ap_get_scoreboard_lb(%d) failed in child %" APR_PID_T_FMT " for worker %s",                  worker->id, getpid(), worker->name);        }        else {             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,                  "proxy: grabbed scoreboard slot %d in child %" APR_PID_T_FMT " for worker %s",                  worker->id, getpid(), worker->name);        }    }#endif    if (!score) {        score = apr_pcalloc(conf->pool, sizeof(proxy_worker_stat));        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,              "proxy: initialized plain memory in child %" APR_PID_T_FMT " for worker %s",              getpid(), worker->name);    }    worker->s = (proxy_worker_stat *)score;    /*     * recheck to see if we've already been here. Possible     * if proxy is using scoreboard to hold shared stats     */    if (worker->s->status & PROXY_WORKER_INITIALIZED) {        /* The worker share is already initialized */        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,              "proxy: worker %s already initialized",              worker->name);        return;    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?