mod_proxy_ajp.c

来自「linux网络服务器工具」· C语言 代码 · 共 656 行 · 第 1/2 页

C
656
字号
                                     "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, &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(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";    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;    /* Step One: Determine Who To Connect To */    status = ap_proxy_determine_connection(p, r, conf, worker, backend,                                           uri, &url, proxyname, proxyport,                                           server_portstr,                                           sizeof(server_portstr));    if (status != OK)        goto cleanup;    /* 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;        goto cleanup;    }    /* Handle CPING/CPONG */    if (worker->ping_timeout_set) {        status = ajp_handle_cping_cpong(backend->sock, r,                                        worker->ping_timeout);        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;            goto cleanup;        }    }    /* Step Three: Process the Request */    status = ap_proxy_ajp_request(p, r, backend, origin, dconf, uri, url,                                  server_portstr);cleanup:    /* 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 + =
减小字号Ctrl + -
显示快捷键?