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

📄 jk_ajp_common.c

📁 精通tomcat书籍原代码,希望大家共同学习
💻 C
📖 第 1 页 / 共 5 页
字号:
}


/*
 * Handle the CPING/CPONG initial query
 */
static int ajp_handle_cping_cpong(ajp_endpoint_t * ae, int timeout, jk_logger_t *l)
{
    int cmd;
    jk_msg_buf_t *msg;

    JK_TRACE_ENTER(l);
    msg = jk_b_new(&ae->pool);
    jk_b_set_buffer_size(msg, 16);      /* 16 is way too large but I'm lazy :-) */
    jk_b_reset(msg);
    jk_b_append_byte(msg, AJP13_CPING_REQUEST);

    /* Send CPing query */
    if (ajp_connection_tcp_send_message(ae, msg, l) != JK_TRUE) {
        jk_log(l, JK_LOG_INFO,
               "can't send cping query");
        JK_TRACE_EXIT(l);
        return JK_FALSE;
    }

    /* wait for Pong reply for timeout milliseconds
     */
    if (ajp_is_input_event(ae, timeout, l) == JK_FALSE) {
        jk_log(l, JK_LOG_INFO, "timeout in reply pong");
        JK_TRACE_EXIT(l);
        return JK_FALSE;
    }

    /* Read and check for Pong reply
     */
    if (ajp_connection_tcp_get_message(ae, msg, l) != JK_TRUE) {
        jk_log(l, JK_LOG_INFO,
               "awaited reply cpong, not received");
        JK_TRACE_EXIT(l);
        return JK_FALSE;
    }

    if ((cmd = jk_b_get_byte(msg)) != AJP13_CPONG_REPLY) {
        jk_log(l, JK_LOG_INFO,
               "awaited reply cpong, received %d instead",
               cmd);
        JK_TRACE_EXIT(l);
        return JK_FALSE;
    }

    JK_TRACE_EXIT(l);
    return JK_TRUE;
}

int ajp_connect_to_endpoint(ajp_endpoint_t * ae, jk_logger_t *l)
{
    char buf[32];
    int rc = JK_TRUE;

    JK_TRACE_ENTER(l);

    ae->sd = jk_open_socket(&ae->worker->worker_inet_addr,
                            ae->worker->keepalive,
                            ae->worker->socket_timeout,
                            ae->worker->socket_buf, l);
    if (ae->sd >= 0) {
        if (JK_IS_DEBUG_LEVEL(l)) {
            jk_log(l, JK_LOG_DEBUG,
                   "Connected socket %d to (%s)",
                   ae->sd,
                   jk_dump_hinfo(&ae->worker->worker_inet_addr, buf));
        }
        /* set last_access only if needed */
        if (ae->worker->cache_timeout > 0 || ae->worker->recycle_timeout > 0)
            ae->last_access = time(NULL);
        /* Check if we must execute a logon after the physical connect */
        if (ae->worker->logon != NULL) {
            rc = ae->worker->logon(ae, l);
            JK_TRACE_EXIT(l);
            return rc;
        }
        /* should we send a CPING to validate connection ? */
        if (ae->worker->connect_timeout > 0) {
            rc = ajp_handle_cping_cpong (ae,
                        ae->worker->connect_timeout, l);
            JK_TRACE_EXIT(l);
            return rc;
        }
        JK_TRACE_EXIT(l);
        return JK_TRUE;
    }

    jk_log(l, JK_LOG_INFO,
           "Failed opening socket to (%s) with (errno=%d)",
           jk_dump_hinfo(&ae->worker->worker_inet_addr, buf), errno);
    JK_TRACE_EXIT(l);
    return JK_FALSE;
}

/*
 * Send a message to endpoint, using corresponding PROTO HEADER
 */

int ajp_connection_tcp_send_message(ajp_endpoint_t * ae,
                                    jk_msg_buf_t *msg, jk_logger_t *l)
{
    int rc;

    JK_TRACE_ENTER(l);
    if (ae->proto == AJP13_PROTO) {
        jk_b_end(msg, AJP13_WS_HEADER);
        if (JK_IS_DEBUG_LEVEL(l))
            jk_dump_buff(l, JK_LOG_DEBUG, "sending to ajp13", msg);
    }
    else if (ae->proto == AJP14_PROTO) {
        jk_b_end(msg, AJP14_WS_HEADER);
        if (JK_IS_DEBUG_LEVEL(l))
            jk_dump_buff(l, JK_LOG_DEBUG, "sending to ajp14", msg);
    }
    else {
        jk_log(l, JK_LOG_ERROR,
               "unknown protocol %d, supported are AJP13/AJP14", ae->proto);
        JK_TRACE_EXIT(l);
        return JK_FATAL_ERROR;
    }

    if ((rc = jk_tcp_socket_sendfull(ae->sd, msg->buf,
                                     msg->len)) > 0) {
        ae->endpoint.wr += msg->len;
        JK_TRACE_EXIT(l);
        return JK_TRUE;
    }
    jk_log(l, JK_LOG_ERROR,
           "sendfull returned %d with errno=%d ", rc, errno);

    JK_TRACE_EXIT(l);
    return JK_FALSE;
}

/*
 * Receive a message from endpoint, checking PROTO HEADER
 */

int ajp_connection_tcp_get_message(ajp_endpoint_t * ae,
                                   jk_msg_buf_t *msg, jk_logger_t *l)
{
    unsigned char head[AJP_HEADER_LEN];
    int rc;
    int msglen;
    unsigned int header;
    char buf[32];

    JK_TRACE_ENTER(l);

    rc = jk_tcp_socket_recvfull(ae->sd, head, AJP_HEADER_LEN);

    if (rc < 0) {
        if (rc == JK_SOCKET_EOF) {
            jk_log(l, JK_LOG_INFO,
                   "Tomcat has forced a connection close for socket %d",
                   ae->sd);
            JK_TRACE_EXIT(l);
        }
        else {
            jk_log(l, JK_LOG_ERROR,
                   "Can't receive the response message from tomcat, "
                   "network problems or tomcat is down (%s), err=%d",
                   jk_dump_hinfo(&ae->worker->worker_inet_addr, buf), rc);
             JK_TRACE_EXIT(l);
        }
        return JK_FALSE;
    }
    ae->endpoint.rd += rc;
    header = ((unsigned int)head[0] << 8) | head[1];

    if (ae->proto == AJP13_PROTO) {
        if (header != AJP13_SW_HEADER) {

            if (header == AJP14_SW_HEADER) {
                jk_log(l, JK_LOG_ERROR,
                       "received AJP14 reply on an AJP13 connection from %s",
                       jk_dump_hinfo(&ae->worker->worker_inet_addr, buf));
            }
            else {
                jk_log(l, JK_LOG_ERROR,
                       "wrong message format 0x%04x from %s",
                       header, jk_dump_hinfo(&ae->worker->worker_inet_addr,
                                             buf));
            }
            JK_TRACE_EXIT(l);
            return JK_FALSE;
        }
    }
    else if (ae->proto == AJP14_PROTO) {
        if (header != AJP14_SW_HEADER) {

            if (header == AJP13_SW_HEADER) {
                jk_log(l, JK_LOG_ERROR,
                       "received AJP13 reply on an AJP14 connection from %s",
                       jk_dump_hinfo(&ae->worker->worker_inet_addr, buf));
            }
            else {
                jk_log(l, JK_LOG_ERROR,
                       "wrong message format 0x%04x from %s",
                       header, jk_dump_hinfo(&ae->worker->worker_inet_addr,
                                             buf));
            }
            JK_TRACE_EXIT(l);
            return JK_FALSE;
        }
    }

    msglen = ((head[2] & 0xff) << 8);
    msglen += (head[3] & 0xFF);

    if (msglen > msg->maxlen) {
        jk_log(l, JK_LOG_ERROR,
               "wrong message size %d %d from %s",
               msglen, msg->maxlen,
               jk_dump_hinfo(&ae->worker->worker_inet_addr, buf));
        JK_TRACE_EXIT(l);
        return JK_FALSE;
    }

    msg->len = msglen;
    msg->pos = 0;

    rc = jk_tcp_socket_recvfull(ae->sd, msg->buf, msglen);
    if (rc < 0) {
        jk_log(l, JK_LOG_ERROR,
               "ERROR: can't receive the response message from tomcat, "
               "network problems or tomcat (%s) is down %d",
               jk_dump_hinfo(&ae->worker->worker_inet_addr, buf), rc);
        JK_TRACE_EXIT(l);
        return JK_FALSE;
    }
    ae->endpoint.rd += rc;

    if (ae->proto == AJP13_PROTO) {
        if (JK_IS_DEBUG_LEVEL(l))
            jk_dump_buff(l, JK_LOG_DEBUG, "received from ajp13", msg);
    }
    else if (ae->proto == AJP14_PROTO) {
        if (JK_IS_DEBUG_LEVEL(l))
            jk_dump_buff(l, JK_LOG_DEBUG, "received from ajp14", msg);
    }
    JK_TRACE_EXIT(l);
    return JK_TRUE;
}

/*
 * Read all the data from the socket.
 *
 * Socket API doesn't guaranty that all the data will be kept in a
 * single read, so we must loop until all awaited data is received
 */

static int ajp_read_fully_from_server(jk_ws_service_t *s, jk_logger_t *l,
                                      unsigned char *buf, unsigned int len)
{
    unsigned int rdlen = 0;
    unsigned int padded_len = len;

    JK_TRACE_ENTER(l);
    if (s->is_chunked && s->no_more_chunks) {
        JK_TRACE_EXIT(l);
        return 0;
    }
    if (s->is_chunked) {
        /* Corner case: buf must be large enough to hold next
         * chunk size (if we're on or near a chunk border).
         * Pad the length to a reasonable value, otherwise the
         * read fails and the remaining chunks are tossed.
         */
        padded_len = (len < CHUNK_BUFFER_PAD) ? len : len - CHUNK_BUFFER_PAD;
    }

    while (rdlen < padded_len) {
        unsigned int this_time = 0;
        if (!s->read(s, buf + rdlen, len - rdlen, &this_time)) {
            /* Remote Client read failed. */
            JK_TRACE_EXIT(l);
            return JK_CLIENT_ERROR;
        }

        if (0 == this_time) {
            if (s->is_chunked) {
                s->no_more_chunks = 1;  /* read no more */
            }
            break;
        }
        rdlen += this_time;
    }

    return (int)rdlen;
}


/*
 * Read data from AJP13/AJP14 protocol
 * Returns -1 on error, else number of bytes read
 */

static int ajp_read_into_msg_buff(ajp_endpoint_t * ae,
                                  jk_ws_service_t *r,
                                  jk_msg_buf_t *msg, int len, jk_logger_t *l)
{
    unsigned char *read_buf = msg->buf;

    JK_TRACE_ENTER(l);
    jk_b_reset(msg);

    read_buf += AJP_HEADER_LEN; /* leave some space for the buffer headers */
    read_buf += AJP_HEADER_SZ_LEN;      /* leave some space for the read length */

    /* Pick the max size since we don't know the content_length */
    if (r->is_chunked && len == 0) {
        len = AJP13_MAX_SEND_BODY_SZ;
    }

    if ((len = ajp_read_fully_from_server(r, l, read_buf, len)) < 0) {
        jk_log(l, JK_LOG_INFO,
               "Receiving data from client failed. "
               "Connection aborted or network problems");
        JK_TRACE_EXIT(l);
        return JK_CLIENT_ERROR;
    }

    if (!r->is_chunked) {
        ae->left_bytes_to_send -= len;
    }

    if (len > 0) {
        /* Recipient recognizes empty packet as end of stream, not
           an empty body packet */
        if (0 != jk_b_append_int(msg, (unsigned short)len)) {
            jk_log(l, JK_LOG_INFO,
                   "Failed appending message length");
            JK_TRACE_EXIT(l);
            return JK_CLIENT_ERROR;
        }
    }

    msg->len += len;

    JK_TRACE_EXIT(l);
    return len;
}


/*
 * send request to Tomcat via Ajp13
 * - first try to find reuseable socket
 * - if no one available, try to connect
 * - send request, but send must be see as asynchronous,
 *   since send() call will return noerror about 95% of time
 *   Hopefully we'll get more information on next read.
 *
 * nb: reqmsg is the original request msg buffer
 *     repmsg is the reply msg buffer which could be scratched
 */
static int ajp_send_request(jk_endpoint_t *e,
                            jk_ws_service_t *s,
                            jk_logger_t *l,
                            ajp_endpoint_t * ae, ajp_operation_t * op)
{
    int err = 0;
    int postlen;

    JK_TRACE_ENTER(l);
    /* Up to now, we can recover */
    op->recoverable = JK_TRUE;

    /*
     * First try to reuse open connections...
     */
    while ((ae->sd > 0)) {
        int rc = 0;
        err = 0;
        if (ae->worker->socket_timeout) {
            if (!jk_is_socket_connected(ae->sd)) {
                jk_log(l, JK_LOG_INFO,
                       "Socket %d is not connected any more (errno=%d)",
                       ae->sd, errno);
                jk_close_socket(ae->sd);
                ae->sd = -1;
                err++;
            }
        }
        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)
                err++;
        }

⌨️ 快捷键说明

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