⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_proxy_ajp.c

📁 Apache官方在今天放出产品系列2.2的最新版本2.2.11的源码包 最流行的HTTP服务器软件之一
💻 C
📖 第 1 页 / 共 2 页
字号:
     * or not (flush response to client)     */    conn_poll = apr_pcalloc(p, sizeof(apr_pollfd_t));    conn_poll->reqevents = APR_POLLIN;    conn_poll->desc_type = APR_POLL_SOCKET;    conn_poll->desc.s = conn->sock;    bufsiz = maxsize;    for (;;) {        switch (result) {            case CMD_AJP13_GET_BODY_CHUNK:                if (havebody) {                    if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {                        /* This is the end */                        bufsiz = 0;                        havebody = 0;                        ap_log_error(APLOG_MARK, APLOG_DEBUG, status, r->server,                                     "proxy: APR_BUCKET_IS_EOS");                    } else {                        status = ap_get_brigade(r->input_filters, input_brigade,                                                AP_MODE_READBYTES,                                                APR_BLOCK_READ,                                                maxsize - AJP_HEADER_SZ);                        if (status != APR_SUCCESS) {                            ap_log_error(APLOG_MARK, APLOG_DEBUG, status,                                         r->server,                                         "ap_get_brigade failed");                            output_failed = 1;                            break;                        }                        bufsiz = maxsize;                        status = apr_brigade_flatten(input_brigade, buff,                                                     &bufsiz);                        apr_brigade_cleanup(input_brigade);                        if (status != APR_SUCCESS) {                            ap_log_error(APLOG_MARK, APLOG_DEBUG, status,                                         r->server,                                         "apr_brigade_flatten failed");                            output_failed = 1;                            break;                        }                    }                    ajp_msg_reset(msg);                    /* will go in ajp_send_data_msg */                    status = ajp_send_data_msg(conn->sock, msg, bufsiz);                    if (status != APR_SUCCESS) {                        ap_log_error(APLOG_MARK, APLOG_DEBUG, status, r->server,                                     "ajp_send_data_msg failed");                        backend_failed = 1;                        break;                    }                    conn->worker->s->transferred += bufsiz;                } else {                    /*                     * something is wrong TC asks for more body but we are                     * already at the end of the body data                     */                    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                                 "ap_proxy_ajp_request error read after end");                    backend_failed = 1;                }                break;            case CMD_AJP13_SEND_HEADERS:                /* AJP13_SEND_HEADERS: process them */                status = ajp_parse_header(r, conf, conn->data);                if (status != APR_SUCCESS) {                    backend_failed = 1;                }                headers_sent = 1;                break;            case CMD_AJP13_SEND_BODY_CHUNK:                /* AJP13_SEND_BODY_CHUNK: piece of data */                status = ajp_parse_data(r, conn->data, &size, &send_body_chunk_buff);                if (status == APR_SUCCESS) {                    /* AJP13_SEND_BODY_CHUNK with zero length                     * is explicit flush message                     */                    if (size == 0) {                        if (headers_sent) {                            e = apr_bucket_flush_create(r->connection->bucket_alloc);                            APR_BRIGADE_INSERT_TAIL(output_brigade, e);                        }                        else {                            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                                 "Ignoring flush message received before headers");                        }                    }                    else {                        e = apr_bucket_transient_create(send_body_chunk_buff, size,                                                    r->connection->bucket_alloc);                        APR_BRIGADE_INSERT_TAIL(output_brigade, e);                        if ((conn->worker->flush_packets == flush_on) ||                            ((conn->worker->flush_packets == flush_auto) &&                            (apr_poll(conn_poll, 1, &conn_poll_fd,                                      conn->worker->flush_wait)                                        == APR_TIMEUP) ) ) {                            e = apr_bucket_flush_create(r->connection->bucket_alloc);                            APR_BRIGADE_INSERT_TAIL(output_brigade, e);                        }                        apr_brigade_length(output_brigade, 0, &bb_len);                        if (bb_len != -1)                            conn->worker->s->read += bb_len;                    }                    if (ap_pass_brigade(r->output_filters,                                        output_brigade) != APR_SUCCESS) {                        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                                      "proxy: error processing body");                        output_failed = 1;                    }                    data_sent = 1;                    apr_brigade_cleanup(output_brigade);                }                else {                    backend_failed = 1;                }                break;            case CMD_AJP13_END_RESPONSE:                e = apr_bucket_eos_create(r->connection->bucket_alloc);                APR_BRIGADE_INSERT_TAIL(output_brigade, e);                if (ap_pass_brigade(r->output_filters,                                    output_brigade) != APR_SUCCESS) {                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                                  "proxy: error processing end");                    output_failed = 1;                }                /* XXX: what about flush here? See mod_jk */                data_sent = 1;                break;            default:                backend_failed = 1;                break;        }        /*         * If connection has been aborted by client: Stop working.         * Nevertheless, we regard our operation so far as a success:         * So reset output_failed to 0 and set result to CMD_AJP13_END_RESPONSE         * But: Close this connection to the backend.         */        if (r->connection->aborted) {            conn->close++;            output_failed = 0;            result = CMD_AJP13_END_RESPONSE;        }        /*         * We either have finished successfully or we failed.         * So bail out         */        if ((result == CMD_AJP13_END_RESPONSE) || backend_failed            || output_failed)            break;        /* read the response */        status = ajp_read_header(conn->sock, r, maxsize,                                 (ajp_msg_t **)&(conn->data));        if (status != APR_SUCCESS) {            backend_failed = 1;            ap_log_error(APLOG_MARK, APLOG_DEBUG, status, r->server,                         "ajp_read_header failed");            break;        }        result = ajp_parse_type(r, conn->data);    }    apr_brigade_destroy(input_brigade);    /*     * Clear output_brigade to remove possible buckets that remained there     * after an error.     */    apr_brigade_cleanup(output_brigade);    if (backend_failed || output_failed) {        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                     "proxy: Processing of request failed backend: %i, "                     "output: %i", backend_failed, output_failed);        /* We had a failure: Close connection to backend */        conn->close++;        /* Return DONE to avoid error messages being added to the stream */        if (data_sent) {            rv = DONE;        }    }    else {        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                     "proxy: got response from %pI (%s)",                     conn->worker->cp->addr,                     conn->worker->hostname);        rv = OK;    }    if (backend_failed) {        ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,                     "proxy: dialog to %pI (%s) failed",                     conn->worker->cp->addr,                     conn->worker->hostname);        /*         * If we already send data, signal a broken backend connection         * upwards in the chain.         */        if (data_sent) {            ap_proxy_backend_broke(r, output_brigade);        } else            rv = HTTP_SERVICE_UNAVAILABLE;    }    /*     * Ensure that we sent an EOS bucket thru the filter chain, if we already     * have sent some data. Maybe ap_proxy_backend_broke was called and added     * one to the brigade already (no longer making it empty). So we should     * not do this in this case.     */    if (data_sent && !r->eos_sent && APR_BRIGADE_EMPTY(output_brigade)) {        e = apr_bucket_eos_create(r->connection->bucket_alloc);        APR_BRIGADE_INSERT_TAIL(output_brigade, e);    }    /* If we have added something to the brigade above, sent it */    if (!APR_BRIGADE_EMPTY(output_brigade))        ap_pass_brigade(r->output_filters, output_brigade);    apr_brigade_destroy(output_brigade);    return rv;}/* * This handles ajp:// URLs */static int proxy_ajp_handler(request_rec *r, proxy_worker *worker,                             proxy_server_conf *conf,                             char *url, const char *proxyname,                             apr_port_t proxyport){    int status;    char server_portstr[32];    conn_rec *origin = NULL;    proxy_conn_rec *backend = NULL;    const char *scheme = "AJP";    int retry;    proxy_dir_conf *dconf = ap_get_module_config(r->per_dir_config,                                                 &proxy_module);    /*     * Note: Memory pool allocation.     * A downstream keepalive connection is always connected to the existence     * (or not) of an upstream keepalive connection. If this is not done then     * load balancing against multiple backend servers breaks (one backend     * server ends up taking 100% of the load), and the risk is run of     * downstream keepalive connections being kept open unnecessarily. This     * keeps webservers busy and ties up resources.     *     * As a result, we allocate all sockets out of the upstream connection     * pool, and when we want to reuse a socket, we check first whether the     * connection ID of the current upstream connection is the same as that     * of the connection when the socket was opened.     */    apr_pool_t *p = r->connection->pool;    apr_uri_t *uri = apr_palloc(r->connection->pool, sizeof(*uri));    if (strncasecmp(url, "ajp:", 4) != 0) {        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                     "proxy: AJP: declining URL %s", url);        return DECLINED;    }    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                 "proxy: AJP: serving URL %s", url);    /* create space for state information */    if (!backend) {        status = ap_proxy_acquire_connection(scheme, &backend, worker,                                             r->server);        if (status != OK) {            if (backend) {                backend->close_on_recycle = 1;                ap_proxy_release_connection(scheme, backend, r->server);            }            return status;        }    }    backend->is_ssl = 0;    backend->close_on_recycle = 0;    retry = 0;    while (retry < 2) {        char *locurl = url;        /* Step One: Determine Who To Connect To */        status = ap_proxy_determine_connection(p, r, conf, worker, backend,                                               uri, &locurl, proxyname, proxyport,                                               server_portstr,                                               sizeof(server_portstr));        if (status != OK)            break;        /* Step Two: Make the Connection */        if (ap_proxy_connect_backend(scheme, backend, worker, r->server)) {            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,                         "proxy: AJP: failed to make connection to backend: %s",                         backend->hostname);            status = HTTP_SERVICE_UNAVAILABLE;            break;        }        /* Handle CPING/CPONG */        if (worker->ping_timeout_set) {            status = ajp_handle_cping_cpong(backend->sock, r,                                            worker->ping_timeout);            /*             * In case the CPING / CPONG failed for the first time we might be             * just out of luck and got a faulty backend connection, but the             * backend might be healthy nevertheless. So ensure that the backend             * TCP connection gets closed and try it once again.             */            if (status != APR_SUCCESS) {                backend->close++;                ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,                             "proxy: AJP: cping/cpong failed to %pI (%s)",                             worker->cp->addr,                             worker->hostname);                status = HTTP_SERVICE_UNAVAILABLE;                retry++;                continue;            }        }        /* Step Three: Process the Request */        status = ap_proxy_ajp_request(p, r, backend, origin, dconf, uri, locurl,                                      server_portstr);        break;    }    /* Do not close the socket */    ap_proxy_release_connection(scheme, backend, r->server);    return status;}static void ap_proxy_http_register_hook(apr_pool_t *p){    proxy_hook_scheme_handler(proxy_ajp_handler, NULL, NULL, APR_HOOK_FIRST);    proxy_hook_canon_handler(proxy_ajp_canon, NULL, NULL, APR_HOOK_FIRST);}module AP_MODULE_DECLARE_DATA proxy_ajp_module = {    STANDARD20_MODULE_STUFF,    NULL,                       /* create per-directory config structure */    NULL,                       /* merge per-directory config structures */    NULL,                       /* create per-server config structure */    NULL,                       /* merge per-server config structures */    NULL,                       /* command apr_table_t */    ap_proxy_http_register_hook /* register hooks */};

⌨️ 快捷键说明

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