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

📄 jk_ajp_common.c

📁 以便Apache与其他服务进行整合 Mod_JK安装
💻 C
📖 第 1 页 / 共 5 页
字号:
        if (!jk_is_socket_connected(ae->sd)) {            jk_log(l, JK_LOG_DEBUG,                   "(%s) socket %d is not connected any more (errno=%d)",                   ae->worker->name, ae->sd, errno);            jk_shutdown_socket(ae->sd);            ae->sd = JK_INVALID_SOCKET;            err = 1;        }        if (ae->worker->prepost_timeout > 0 && !err) {            /* handle cping/cpong if prepost_timeout is set             * If the socket is disconnected no need to handle             * the cping/cpong             */            if (ajp_handle_cping_cpong(ae,                        ae->worker->prepost_timeout, l) == JK_FALSE) {                /* XXX: Is there any reason to try other                 * connections to the node if one of them fails                 * the cping/cpong heartbeat?                 * Tomcat can be either too busy or simply dead, so                 * there is a chance that all oter connections would                 * fail as well.                 */                err = 2;            }        }        /* If we got an error or can't send data, then try to get a pooled         * connection and try again.  If we are succesful, break out of this         * loop. */        if (err ||            ((rc = ajp_connection_tcp_send_message(ae, op->request, l)) != JK_TRUE)) {            if (rc != JK_FATAL_ERROR) {                if (err == 1) {                    jk_log(l, JK_LOG_DEBUG,                           "(%s) failed sending request. "                           "Will try another pooled connection",                            ae->worker->name);                }                else {                    jk_log(l, JK_LOG_INFO,                           "(%s) error sending request. "                           "Will try another pooled connection",                            ae->worker->name);                }                ajp_next_connection(ae, l);            }            else {                op->recoverable = JK_FALSE;                jk_log(l, JK_LOG_ERROR,                       "(%s) error sending request. Unrecoverable operation",                       ae->worker->name);                jk_shutdown_socket(ae->sd);                ae->sd = JK_INVALID_SOCKET;                JK_TRACE_EXIT(l);                return JK_FALSE;            }        }        else            break;    }    /*     * If we failed to reuse a connection, try to reconnect.     */    if (!IS_VALID_SOCKET(ae->sd)) {        if (err == 1) {            /* If err is set, the tomcat is disconnected */            jk_log(l, JK_LOG_INFO,                   "(%s) all endpoints are disconnected", ae->worker->name);            JK_TRACE_EXIT(l);            return JK_FALSE;        }        else if (err) {            /* If err is set, the tomcat is dead */            jk_log(l, JK_LOG_INFO,                   "(%s) all endpoints are dead", ae->worker->name);            /* TODO: What is the purpose of the following log message?             *       IMO it is very confusing and does not reflect the             *       real reason (CPING/CPONG failed) of the error.             *       Further more user might deliberately set the             *       connectionTimeout and this is normal operational             *       message in that case.             */            jk_log(l, JK_LOG_INFO,                   "(%s) increase the backend idle connection "                   "timeout or the connection_pool_minsize",                   ae->worker->name);            JK_TRACE_EXIT(l);            return JK_FALSE;        }        /* Connect to the backend.         * This can be either uninitalized connection or a reconnect.         */        if (ajp_connect_to_endpoint(ae, l) == JK_TRUE) {            /*             * After we are connected, each error that we are going to             * have is probably unrecoverable             */            if (ajp_connection_tcp_send_message(ae, op->request, l) != JK_TRUE) {                /* Close the socket if unable to send request */                jk_shutdown_socket(ae->sd);                ae->sd = JK_INVALID_SOCKET;                jk_log(l, JK_LOG_INFO,                       "(%s) error sending request on a fresh connection (errno=%d)",                       ae->worker->name, ae->last_errno);                JK_TRACE_EXIT(l);                return JK_FALSE;            }        }        else {            /* Close the socket if unable to connect */            jk_shutdown_socket(ae->sd);            ae->sd = JK_INVALID_SOCKET;            jk_log(l, JK_LOG_INFO,                   "(%s) error connecting to the backend server (errno=%d)",                   ae->worker->name, ae->last_errno);            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,               "(%s) request body to send %" JK_UINT64_T_FMT " - request body to resend %d",               ae->worker->name, 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) {            /* Close the socket if unable to send request */            jk_shutdown_socket(ae->sd);            ae->sd = JK_INVALID_SOCKET;            jk_log(l, JK_LOG_ERROR, "(%s) failed resending request body (%d)",                   ae->worker->name, postlen);            JK_TRACE_EXIT(l);            return JK_SERVER_ERROR;        }        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) {                /* Close the socket if unable to send request */                jk_shutdown_socket(ae->sd);                ae->sd = JK_INVALID_SOCKET;                jk_log(l, JK_LOG_ERROR,                       "(%s) failed resending request body (lb mode) (%d)",                       ae->worker->name, postlen);                JK_TRACE_EXIT(l);                return JK_SERVER_ERROR;            }        }        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 = AJP13_MAX_SEND_BODY_SZ;            if (ae->left_bytes_to_send < (jk_uint64_t)AJP13_MAX_SEND_BODY_SZ) {                len = (int)ae->left_bytes_to_send;            }            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 JK_CLIENT_RD_ERROR;            }            /* 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 = (jk_uint64_t)len;            if (ajp_connection_tcp_send_message(ae, op->post, l) != JK_TRUE) {                /* Close the socket if unable to send request */                jk_shutdown_socket(ae->sd);                ae->sd = JK_INVALID_SOCKET;                jk_log(l, JK_LOG_ERROR, "(%s) error sending request body",                       ae->worker->name);                JK_TRACE_EXIT(l);                return JK_SERVER_ERROR;            }        }    }    JK_TRACE_EXIT(l);    return (JK_TRUE);}static int is_http_status_fail(ajp_worker_t *w, int status){    unsigned int i;    int soft_status = -1 * status;    for (i = 0; i < w->http_status_fail_num; i++) {        if (w->http_status_fail[i] == status)            return 1;        else if (w->http_status_fail[i] == soft_status)            return -1;    }    return 0;}/* * 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:        {            int rc;            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->http_response_status = res.status;            rc  = is_http_status_fail(ae->worker, res.status);            if (rc > 0) {                JK_TRACE_EXIT(l);                return JK_STATUS_FATAL_ERROR;            }            else if (rc < 0) {                JK_TRACE_EXIT(l);                return JK_STATUS_ERROR;            }            r->start_response(r, res.status, res.msg,                              (const char *const *)res.header_names,                              (const char *const *)res.header_values,                              res.num_headers);            if (r->flush && r->flush_header)                r->flush(r);        }        return JK_AJP13_SEND_HEADERS;    case JK_AJP13_SEND_BODY_CHUNK:        {            unsigned int len = (unsigned int)jk_b_get_int(msg);            /*             * Do a sanity check on len to prevent write reading beyond buffer             * boundaries and thus revealing possible sensitive memory             * contents to the client.             * len cannot be larger than msg->len - 3 because the ajp message             * contains the magic byte for JK_AJP13_SEND_BODY_CHUNK (1 byte)             * and the length of the chunk (2 bytes). The remaining part of             * the message is the chunk.             */            if (len > (unsigned int)(msg->len - 3)) {                jk_log(l, JK_LOG_ERROR,                       "Chunk length too large. Length of AJP message is %i,"                       " chunk length is %i.", msg->len, len);                JK_TRACE_EXIT(l);                return JK_INTERNAL_ERROR;            }            if (len == 0) {                /* AJP13_SEND_BODY_CHUNK with length 0 is                 * explicit flush packet message.                 */                if (r->flush)                    r->flush(r);            }            else {                if (!r->write(r, msg->buf + msg->pos, len)) {                    jk_log(l, JK_LOG_INFO,                           "Writing to client aborted or client network problems");                    JK_TRACE_EXIT(l);                    return JK_CLIENT_WR_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 ((jk_uint64_t)len > ae->left_bytes_to_send) {                len = (int)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 += (jk_uint64_t)len;                JK_TRACE_EXIT(l);                return JK_AJP13_HAS_RESPONSE;            }            jk_log(l, JK_LOG_INFO,                   "Reding from client aborted or client network problems");            JK_TRACE_EXIT(l);            return JK_CLIENT_RD_ERROR;        }        break;    case JK_AJP13_END_RESPONSE:        ae->reuse = (int)jk_b_get_byte(msg);        if (!ae->reuse) {            /*             * AJP13 protocol reuse flag set to false.             * Tomcat will close its side of the connection.             */            jk_log(l, JK_LOG_WARNING, "AJP13 protocol: Reuse is set to false");        }        else if (r->disable_reuse) {            if (JK_IS_DEBUG_LEVEL(l)) {                jk_log(l, JK_LOG_DEBUG, "AJP13 protocol: Reuse is disabled");            }            ae->reuse = JK_FALSE;        }        else {            /* Reuse in all cases */            if (JK_IS_DEBUG_LEVEL(l)) {                jk_log(l, JK_LOG_DEBUG, "AJP13 protocol: Reuse is OK");            }            ae->reuse = JK_TRUE;        }        /* Flush after the last write */        if (r->flush && !r->flush_packets)            r->flush(r);        JK_TRACE_EXIT(l);        return JK_AJP13_END_RESPONSE;        break;    default:        jk_log(l, JK_LOG_ERROR,               "Unknown AJP protocol code: %02X", 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.

⌨️ 快捷键说明

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