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

📄 jk_ajp_common.c

📁 jboss与apache集成的中间件,详情请参看文档说明.
💻 C
📖 第 1 页 / 共 5 页
字号:
            jk_close_socket(ae->sd);            ae->sd = -1;            jk_log(l, JK_LOG_INFO,                   "Error connecting to the Tomcat process.");            JK_TRACE_EXIT(l);            return JK_FALSE;        }    }    /*     * From now on an error means that we have an internal server error     * or Tomcat crashed. In any case we cannot recover this.     */    if (JK_IS_DEBUG_LEVEL(l))        jk_log(l, JK_LOG_DEBUG,               "request body to send %d - request body to resend %d",               ae->left_bytes_to_send, op->reply->len - AJP_HEADER_LEN);    /*     * POST recovery job is done here and will work when data to     * POST are less than 8k, since it's the maximum size of op-post buffer.     * We send here the first part of data which was sent previously to the     * remote Tomcat     */    /* Did we have something to resend (ie the op-post has been feeded previously */    postlen = op->post->len;    if (postlen > AJP_HEADER_LEN) {        if (ajp_connection_tcp_send_message(ae, op->post, l) != JK_TRUE) {            jk_log(l, JK_LOG_ERROR, "Error resending request body (%d)",                   postlen);            JK_TRACE_EXIT(l);            return JK_FALSE;        }        else {            if (JK_IS_DEBUG_LEVEL(l))                jk_log(l, JK_LOG_DEBUG, "Resent the request body (%d)",                       postlen);        }    }    else if (s->reco_status == RECO_FILLED) {        /* Recovery in LB MODE */        postlen = s->reco_buf->len;        if (postlen > AJP_HEADER_LEN) {            if (ajp_connection_tcp_send_message(ae, s->reco_buf, l) != JK_TRUE) {                jk_log(l, JK_LOG_ERROR,                       "Error resending request body (lb mode) (%d)",                       postlen);                JK_TRACE_EXIT(l);                return JK_FALSE;            }        }        else {            if (JK_IS_DEBUG_LEVEL(l))                jk_log(l, JK_LOG_DEBUG,                       "Resent the request body (lb mode) (%d)", postlen);        }    }    else {        /* We never sent any POST data and we check if we have to send at         * least one block of data (max 8k). These data will be kept in reply         * for resend if the remote Tomcat is down, a fact we will learn only         * doing a read (not yet)         */        /* || s->is_chunked - this can't be done here. The original protocol           sends the first chunk of post data ( based on Content-Length ),           and that's what the java side expects.           Sending this data for chunked would break other ajp13 servers.           Note that chunking will continue to work - using the normal read.         */        if (ae->left_bytes_to_send > 0) {            int len = ae->left_bytes_to_send;            if (len > AJP13_MAX_SEND_BODY_SZ) {                len = AJP13_MAX_SEND_BODY_SZ;            }            if ((len = ajp_read_into_msg_buff(ae, s, op->post, len, l)) < 0) {                /* the browser stop sending data, no need to recover */                op->recoverable = JK_FALSE;                JK_TRACE_EXIT(l);                return len;            }            /* If a RECOVERY buffer is available in LB mode, fill it */            if (s->reco_status == RECO_INITED) {                jk_b_copy(op->post, s->reco_buf);                s->reco_status = RECO_FILLED;            }            s->content_read = len;            if (ajp_connection_tcp_send_message(ae, op->post, l) != JK_TRUE) {                jk_log(l, JK_LOG_ERROR, "Error sending request body");                JK_TRACE_EXIT(l);                return JK_FALSE;            }        }    }    JK_TRACE_EXIT(l);    return (JK_TRUE);}/* * What to do with incoming data (dispatcher) */static int ajp_process_callback(jk_msg_buf_t *msg,                                jk_msg_buf_t *pmsg,                                ajp_endpoint_t * ae,                                jk_ws_service_t *r, jk_logger_t *l){    int code = (int)jk_b_get_byte(msg);    JK_TRACE_ENTER(l);    switch (code) {    case JK_AJP13_SEND_HEADERS:        {            jk_res_data_t res;            if (!ajp_unmarshal_response(msg, &res, ae, l)) {                jk_log(l, JK_LOG_ERROR,                       "ajp_unmarshal_response failed");                JK_TRACE_EXIT(l);                return JK_AJP13_ERROR;            }            r->start_response(r, res.status, res.msg,                              (const char *const *)res.header_names,                              (const char *const *)res.header_values,                              res.num_headers);        }        return JK_AJP13_SEND_HEADERS;    case JK_AJP13_SEND_BODY_CHUNK:        {            unsigned int len = (unsigned int)jk_b_get_int(msg);            if (!r->write(r, msg->buf + msg->pos, len)) {                jk_log(l, JK_LOG_INFO,                       "Connection aborted or network problems");                JK_TRACE_EXIT(l);                return JK_CLIENT_ERROR;            }            if (r->flush && r->flush_packets)                r->flush(r);        }        break;    case JK_AJP13_GET_BODY_CHUNK:        {            int len = (int)jk_b_get_int(msg);            if (len < 0) {                len = 0;            }            if (len > AJP13_MAX_SEND_BODY_SZ) {                len = AJP13_MAX_SEND_BODY_SZ;            }            if ((unsigned int)len > ae->left_bytes_to_send) {                len = ae->left_bytes_to_send;            }            /* the right place to add file storage for upload */            if ((len = ajp_read_into_msg_buff(ae, r, pmsg, len, l)) >= 0) {                r->content_read += len;                JK_TRACE_EXIT(l);                return JK_AJP13_HAS_RESPONSE;            }            jk_log(l, JK_LOG_INFO,                   "Connection aborted or network problems");            JK_TRACE_EXIT(l);            return JK_CLIENT_ERROR;        }        break;    case JK_AJP13_END_RESPONSE:        ae->reuse = (int)jk_b_get_byte(msg);        if (!ae->reuse) {            /*                * Strange protocol error.                */            jk_log(l, JK_LOG_INFO, " Protocol error: Reuse is set to false");        }        /* Flush after the last write */        if (r->flush && !r->flush_packets)            r->flush(r);        /* Reuse in all cases */        ae->reuse = JK_TRUE;        JK_TRACE_EXIT(l);        return JK_AJP13_END_RESPONSE;        break;    default:        jk_log(l, JK_LOG_ERROR,               "Invalid code: %d", code);        JK_TRACE_EXIT(l);        return JK_AJP13_ERROR;    }    JK_TRACE_EXIT(l);    return JK_AJP13_NO_RESPONSE;}/* * get replies from Tomcat via Ajp13/Ajp14 * We will know only at read time if the remote host closed * the connection (half-closed state - FIN-WAIT2). In that case * we must close our side of the socket and abort emission. * 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 it 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,                       "Timeout with waiting reply from tomcat. "                       "Tomcat is down, stopped or network problems.");                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;                }                JK_TRACE_EXIT(l);                return JK_FALSE;            }        }        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,                       "Tomcat is down or refused connection. "                       "No response has been sent to the client (yet)");                /*                 * 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 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,                       "Tomcat is down or network problems. "                       "Part of the response has already been sent to the client");                /* 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;                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_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,                       "Tomcat is down or network problems.", rc);                JK_TRACE_EXIT(l);                return JK_FALSE;            }        }        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_ERROR == rc) {            /*             * Client has stop talking to us, so get out.             * We assume this isn't our fault, so just a normal exit.             * In most (all?)  cases, the ajp13_endpoint::reuse will still be             * false here, so this will be functionally the same as an             * un-recoverable error.  We just won't log it as such.             */            JK_TRACE_EXIT(l);            return JK_CLIENT_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, err;    ajp_operation_t oper;    ajp_operation_t *op = &oper;    JK_TRACE_ENTER(l);    if (is_error)        *is_error = JK_HTTP_SERVER_ERROR;    if (e && e->endpoint_private && s && is_error) {        ajp_endpoint_t *p = e->endpoint_private;        op->request = jk_b_new(&(p->pool));        jk_b_set_buffer_size(op->request, DEF_BUFFER_SZ);        jk_b_reset(op->request);        op->reply = jk_b_new(&(p->pool));        jk_b_set_buffer_size(op->reply, DEF_BUFFER_SZ);        jk_b_reset(op->reply);        op->post = jk_b_new(&(p->pool));        jk_b_set_buffer_size(op->post, DEF_BUFFER_SZ);        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)) {

⌨️ 快捷键说明

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