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

📄 jk_ajp_common.c

📁 以便Apache与其他服务进行整合 Mod_JK安装
💻 C
📖 第 1 页 / 共 5 页
字号:
 * We will need another connection to send the request * There is need of refactoring here since we mix * reply reception (tomcat -> apache) and request send (apache -> tomcat) * and everything using the same buffer (repmsg) * ajp13/ajp14 is async but handling read/send this way prevent nice recovery * In fact if tomcat link is broken during upload (browser -> apache -> tomcat) * we'll loose data and we'll have to abort the whole request. */static int ajp_get_reply(jk_endpoint_t *e,                         jk_ws_service_t *s,                         jk_logger_t *l,                         ajp_endpoint_t * p, ajp_operation_t * op){    /* Don't get header from tomcat yet */    int headeratclient = JK_FALSE;    JK_TRACE_ENTER(l);    /* Start read all reply message */    while (1) {        int rc = 0;        /* If we set a reply timeout, check if something is available */        if (p->worker->reply_timeout > 0) {            if (ajp_is_input_event(p, p->worker->reply_timeout, l) ==                JK_FALSE) {                jk_log(l, JK_LOG_ERROR,                       "(%s) Timeout with waiting reply from tomcat. "                       "Tomcat is down, stopped or network problems (errno=%d)",                       p->worker->name, p->last_errno);                if (headeratclient == JK_FALSE) {                    if (p->worker->recovery_opts & RECOVER_ABORT_IF_TCGETREQUEST)                        op->recoverable = JK_FALSE;                }                else {                    if (p->worker->recovery_opts & RECOVER_ABORT_IF_TCSENDHEADER)                        op->recoverable = JK_FALSE;                }                /*                 * We revert back to recoverable, if recovery_opts allow it for GET or HEAD                 */                if (op->recoverable == JK_FALSE) {                    if (p->worker->recovery_opts & RECOVER_ALWAYS_HTTP_HEAD) {                        if (!strcmp(s->method, "HEAD"))                            op->recoverable = JK_TRUE;                    }                    else if (p->worker->recovery_opts & RECOVER_ALWAYS_HTTP_GET) {                        if (!strcmp(s->method, "GET"))                            op->recoverable = JK_TRUE;                    }                }                JK_TRACE_EXIT(l);                return JK_REPLY_TIMEOUT;            }        }        if (!ajp_connection_tcp_get_message(p, op->reply, l)) {            /* we just can't recover, unset recover flag */            if (headeratclient == JK_FALSE) {                jk_log(l, JK_LOG_ERROR,                       "(%s) Tomcat is down or refused connection. "                       "No response has been sent to the client (yet)",                       p->worker->name);                /*                 * communication with tomcat has been interrupted BEFORE                 * headers have been sent to the client.                 * DISCUSSION: As we suppose that tomcat has already started                 * to process the query we think it's unrecoverable (and we                 * should not retry or switch to another tomcat in the                 * cluster).                 */                /*                 * We mark it unrecoverable if recovery_opts set to RECOVER_ABORT_IF_TCGETREQUEST                 */                if (p->worker->recovery_opts & RECOVER_ABORT_IF_TCGETREQUEST)                    op->recoverable = JK_FALSE;                /*                 * We revert back to recoverable, if recovery_opts allow it for GET or HEAD                 */                if (op->recoverable == JK_FALSE) {                    if (p->worker->recovery_opts & RECOVER_ALWAYS_HTTP_HEAD) {                        if (!strcmp(s->method, "HEAD"))                            op->recoverable = JK_TRUE;                    }                    else if (p->worker->recovery_opts & RECOVER_ALWAYS_HTTP_GET) {                        if (!strcmp(s->method, "GET"))                            op->recoverable = JK_TRUE;                    }                }                /*                 * we want to display the webservers error page, therefore                 * we return JK_FALSE                 */                JK_TRACE_EXIT(l);                return JK_FALSE;            }            else {                jk_log(l, JK_LOG_ERROR,                       "(%s) Tomcat is down or network problems. "                       "Part of the response has already been sent to the client",                       p->worker->name);                /* communication with tomcat has been interrupted AFTER                 * headers have been sent to the client.                 * headers (and maybe parts of the body) have already been                 * sent, therefore the response is "complete" in a sense                 * that nobody should append any data, especially no 500 error                 * page of the webserver!                 *                 * BUT if you retrun JK_TRUE you have a 200 (OK) code in your                 * in your apache access.log instead of a 500 (Error).                 * Therefore return FALSE/FALSE                 * return JK_TRUE;                 */                /*                 * We mark it unrecoverable if recovery_opts set to RECOVER_ABORT_IF_TCSENDHEADER                 */                if (p->worker->recovery_opts & RECOVER_ABORT_IF_TCSENDHEADER)                    op->recoverable = JK_FALSE;                /*                 * We revert back to recoverable, if recovery_opts allow it for GET or HEAD                 */                if (op->recoverable == JK_FALSE) {                    if (p->worker->recovery_opts & RECOVER_ALWAYS_HTTP_HEAD) {                        if (!strcmp(s->method, "HEAD"))                            op->recoverable = JK_TRUE;                    }                    else if (p->worker->recovery_opts & RECOVER_ALWAYS_HTTP_GET) {                        if (!strcmp(s->method, "GET"))                            op->recoverable = JK_TRUE;                    }                }                JK_TRACE_EXIT(l);                return JK_FALSE;            }        }        rc = ajp_process_callback(op->reply, op->post, p, s, l);        /* no more data to be sent, fine we have finish here */        if (JK_AJP13_END_RESPONSE == rc) {            JK_TRACE_EXIT(l);            return JK_TRUE;        }        else if (JK_AJP13_SEND_HEADERS == rc) {            headeratclient = JK_TRUE;        }        else if (JK_STATUS_ERROR == rc || JK_STATUS_FATAL_ERROR == rc) {            JK_TRACE_EXIT(l);            return rc;        }        else if (JK_AJP13_HAS_RESPONSE == rc) {            /*             * in upload-mode there is no second chance since             * we may have allready sent part of the uploaded data             * to Tomcat.             * In this case if Tomcat connection is broken we must             * abort request and indicate error.             * A possible work-around could be to store the uploaded             * data to file and replay for it             */            op->recoverable = JK_FALSE;            rc = ajp_connection_tcp_send_message(p, op->post, l);            if (rc < 0) {                jk_log(l, JK_LOG_ERROR,                       "(%s) Tomcat is down or network problems",                        p->worker->name);                jk_shutdown_socket(p->sd);                p->sd = JK_INVALID_SOCKET;                JK_TRACE_EXIT(l);                return JK_FALSE;            }        }        else if (JK_AJP13_ERROR == rc) {            /*             * Tomcat has send invalid AJP message.             * Loadbalancer if present will decide if             * failover is possible.             */            JK_TRACE_EXIT(l);            return JK_SERVER_ERROR;        }        else if (JK_FATAL_ERROR == rc) {            /*             * we won't be able to gracefully recover from this so             * set recoverable to false and get out.             */            op->recoverable = JK_FALSE;            JK_TRACE_EXIT(l);            return JK_FALSE;        }        else if (JK_CLIENT_RD_ERROR == rc) {            /*             * Client has stop sending to us, so get out.             * We assume this isn't our fault, so just a normal exit.             */            JK_TRACE_EXIT(l);            return JK_CLIENT_RD_ERROR;        }        else if (JK_CLIENT_WR_ERROR == rc) {            /*             * Client has stop receiving to us, so get out.             * We assume this isn't our fault, so just a normal exit.             */            JK_TRACE_EXIT(l);            return JK_CLIENT_WR_ERROR;        }        else if (JK_SERVER_ERROR == rc) {            /*             * Tomcat has stop talking to us, so get out.             * Loadbalancer if present will decide if             * failover is possible.             */            JK_TRACE_EXIT(l);            return JK_SERVER_ERROR;        }        else if (rc < 0) {            JK_TRACE_EXIT(l);            return (JK_FALSE);  /* XXX error */        }    }    /* XXX: Not reached? */    JK_TRACE_EXIT(l);    return JK_FALSE;}/* * service is now splitted in ajp_send_request and ajp_get_reply * much more easier to do errors recovery * * We serve here the request, using AJP13/AJP14 (e->proto) * */static int JK_METHOD ajp_service(jk_endpoint_t *e,                                 jk_ws_service_t *s,                                 jk_logger_t *l, int *is_error){    int i;    int err = JK_TRUE;    ajp_operation_t oper;    ajp_operation_t *op = &oper;    ajp_endpoint_t *p;    JK_TRACE_ENTER(l);    if (!e || !e->endpoint_private || !s || !is_error) {        JK_LOG_NULL_PARAMS(l);        if (is_error)            *is_error = JK_HTTP_SERVER_ERROR;        JK_TRACE_EXIT(l);        return JK_FALSE;    }    p = e->endpoint_private;    /* Set returned error to OK */    *is_error = JK_HTTP_OK;    op->request = jk_b_new(&(p->pool));    if (!op->request) {        *is_error = JK_HTTP_SERVER_ERROR;        jk_log(l, JK_LOG_ERROR,               "Failed allocating AJP message");        JK_TRACE_EXIT(l);        return JK_SERVER_ERROR;    }    if (jk_b_set_buffer_size(op->request, p->worker->max_packet_size)) {        *is_error = JK_HTTP_SERVER_ERROR;        jk_log(l, JK_LOG_ERROR,               "Failed allocating AJP message buffer");        JK_TRACE_EXIT(l);        return JK_SERVER_ERROR;    }    jk_b_reset(op->request);    op->reply = jk_b_new(&(p->pool));    if (!op->reply) {        *is_error = JK_HTTP_SERVER_ERROR;        jk_log(l, JK_LOG_ERROR,               "Failed allocating AJP message");        JK_TRACE_EXIT(l);        return JK_SERVER_ERROR;    }    if (jk_b_set_buffer_size(op->reply, p->worker->max_packet_size)) {        *is_error = JK_HTTP_SERVER_ERROR;        jk_log(l, JK_LOG_ERROR,               "Failed allocating AJP message buffer");        JK_TRACE_EXIT(l);        return JK_SERVER_ERROR;    }    jk_b_reset(op->reply);    op->post = jk_b_new(&(p->pool));    if (!op->post) {        *is_error = JK_HTTP_SERVER_ERROR;        jk_log(l, JK_LOG_ERROR,               "Failed allocating AJP message");        JK_TRACE_EXIT(l);        return JK_SERVER_ERROR;    }    if (jk_b_set_buffer_size(op->post, p->worker->max_packet_size)) {        *is_error = JK_HTTP_SERVER_ERROR;        jk_log(l, JK_LOG_ERROR,               "Failed allocating AJP message buffer");        JK_TRACE_EXIT(l);        return JK_SERVER_ERROR;    }    jk_b_reset(op->post);    op->recoverable = JK_TRUE;    op->uploadfd = -1;      /* not yet used, later ;) */    p->left_bytes_to_send = s->content_length;    p->reuse = JK_FALSE;    s->secret = p->worker->secret;    /*     * We get here initial request (in reqmsg)     */    if (!ajp_marshal_into_msgb(op->request, s, l, p)) {        *is_error = JK_REQUEST_TOO_LARGE;        jk_log(l, JK_LOG_INFO,                "Creating AJP message failed, "                "without recovery");        JK_TRACE_EXIT(l);        return JK_CLIENT_ERROR;    }    if (JK_IS_DEBUG_LEVEL(l)) {        jk_log(l, JK_LOG_DEBUG, "processing %s with %d retries",               p->worker->name, p->worker->worker.retries);    }    /*     * JK_RETRIES could be replaced by the number of workers in     * a load-balancing configuration     */    for (i = 0; i < p->worker->worker.retries; i++) {        /*         * We're using reqmsg which hold initial request         * if Tomcat is stopped or restarted, we will pass reqmsg         * to next valid tomcat.         */        err = ajp_send_request(e, s, l, p, op);        if (err == JK_TRUE) {            /* If we have an unrecoverable error, it's probably because             * the sender (browser) stopped sending data before the end             * (certainly in a big post)             */            if (!op->recoverable) {                *is_error = JK_HTTP_SERVER_ERROR;                jk_log(l, JK_LOG_ERROR,                       "(%s) sending request to tomcat failed "                       "without recovery in send loop %d",                       p->worker->name, i);                JK_TRACE_EXIT(l);                return JK_FALSE;            }            /* Up to there we can recover */            err = ajp_get_reply(e, s, l, p, op);            if (err == JK_TRUE) {                *is_error = JK_HTTP_OK;                /* Done with the request */                JK_TRACE_EXIT(l);                return JK_TRUE;            }            if (err == JK_CLIENT_RD_ERROR) {                *is_error = JK_HTTP_BAD_REQUEST;                if (p->worker->recovery_opts & RECOVER_ABORT_IF_CLIENTERROR) {                    /* Mark the endpoint for shutdown */                    p->reuse = JK_FALSE;                }                jk_log(l, JK_LOG_INFO,                       "(%s) request failed, "                       "because of client read error "                       "without recovery in send loop attempt=%d",                       p->worker->name, i);                JK_TRACE_EXIT(l);                return JK_CLIENT_ERROR;            }            else if (err == JK_CLIENT_WR_ERROR) {                /* XXX: Is this correct to log this as 200? */                *is_error = JK_HTTP_OK;                if (p->worker->recovery_opts & RECOVER_ABORT_IF_CLIENTERROR) {                    /* Mark the endpoint for shutdown */

⌨️ 快捷键说明

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