int ajp_connection_tcp_get_message()

in native/common/jk_ajp_common.c [1327:1484]


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

    JK_TRACE_ENTER(l);

    ae->last_errno = 0;
    /* If recvfull gets an error, it implicitely closes the socket.
     * We will invalidate the endpoint connection.
     */
    rc = jk_tcp_socket_recvfull(ae->sd, head, AJP_HEADER_LEN, l);

    /* If the return code is not negative
     * then we always get back the correct number of bytes.
     */
    if (rc < 0) {
        if (rc == JK_SOCKET_EOF) {
            ae->last_errno = EPIPE;
            jk_log(l, JK_LOG_INFO,
                   "(%s) can't receive the response header message from tomcat, "
                   "tomcat (%s) has forced a connection close for socket %d",
                   ae->worker->name, jk_dump_hinfo(&ae->worker->worker_inet_addr,
                   buf, sizeof(buf)), ae->sd);
        }
        else {
            ae->last_errno = -rc;
            jk_log(l, JK_LOG_INFO,
                   "(%s) can't receive the response header message from tomcat, "
                   "network problems or tomcat (%s) is down (errno=%d)",
                   ae->worker->name, jk_dump_hinfo(&ae->worker->worker_inet_addr,
                   buf, sizeof(buf)), ae->last_errno);
        }
        ajp_abort_endpoint(ae, JK_FALSE, l);
        JK_TRACE_EXIT(l);
        return JK_FALSE;
    }
    ae->endpoint.rd += (jk_uint64_t)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,
                       "(%s) received AJP14 reply on an AJP13 connection from %s",
                       ae->worker->name,
                       jk_dump_hinfo(&ae->worker->worker_inet_addr, buf,
                                     sizeof(buf)));
            }
            else {
                jk_log(l, JK_LOG_ERROR,
                       "(%s) wrong message format 0x%04x from %s",
                       ae->worker->name, header,
                       jk_dump_hinfo(&ae->worker->worker_inet_addr, buf,
                                     sizeof(buf)));
            }
            /* We've got a protocol error.
             * We can't trust this connection any more.
             */
            ajp_abort_endpoint(ae, JK_TRUE, l);
            JK_TRACE_EXIT(l);
            return JK_AJP_PROTOCOL_ERROR;
        }
    }
    else if (ae->proto == AJP14_PROTO) {
        if (header != AJP14_SW_HEADER) {

            if (header == AJP13_SW_HEADER) {
                jk_log(l, JK_LOG_ERROR,
                       "(%s) received AJP13 reply on an AJP14 connection from %s",
                       ae->worker->name,
                       jk_dump_hinfo(&ae->worker->worker_inet_addr, buf,
                                     sizeof(buf)));
            }
            else {
                jk_log(l, JK_LOG_ERROR,
                       "(%s) wrong message format 0x%04x from %s",
                       ae->worker->name, header,
                       jk_dump_hinfo(&ae->worker->worker_inet_addr, buf,
                                     sizeof(buf)));
            }
            /* We've got a protocol error.
             * We can't trust this connection any more.
             */
            ajp_abort_endpoint(ae, JK_TRUE, l);
            JK_TRACE_EXIT(l);
            return JK_AJP_PROTOCOL_ERROR;
        }
    }

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

    if (msglen > msg->maxlen) {
        jk_log(l, JK_LOG_ERROR,
               "(%s) wrong message size %d %d from %s",
               ae->worker->name, msglen, msg->maxlen,
               jk_dump_hinfo(&ae->worker->worker_inet_addr, buf, sizeof(buf)));
        /* We've got a protocol error.
         * We can't trust this connection any more.
         */
        ajp_abort_endpoint(ae, JK_TRUE, l);
        JK_TRACE_EXIT(l);
        return JK_AJP_PROTOCOL_ERROR;
    }

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

    /* If recvfull gets an error, it implicitely closes the socket.
     * We will invalidate the endpoint connection.
     */
    rc = jk_tcp_socket_recvfull(ae->sd, msg->buf, msglen, l);
    /* If the return code is not negative
     * then we always get back the correct number of bytes.
     */
    if (rc < 0) {
        if (rc == JK_SOCKET_EOF) {
            ae->last_errno = EPIPE;
            jk_log(l, JK_LOG_ERROR,
                   "(%s) can't receive the response body message from tomcat, "
                   "tomcat (%s) has forced a connection close for socket %d",
                   ae->worker->name,
                   jk_dump_hinfo(&ae->worker->worker_inet_addr, buf, sizeof(buf)),
                   ae->sd);
        }
        else {
            ae->last_errno = -rc;
            jk_log(l, JK_LOG_ERROR,
                   "(%s) can't receive the response body message from tomcat, "
                   "network problems or tomcat (%s) is down (errno=%d)",
                   ae->worker->name,
                   jk_dump_hinfo(&ae->worker->worker_inet_addr, buf, sizeof(buf)),
                   ae->last_errno);
        }
        ajp_abort_endpoint(ae, JK_FALSE, l);
        JK_TRACE_EXIT(l);
        /* Although we have a connection, this is effectively a protocol error.
         * We received the AJP header packet, but not the packet payload
         */
        return JK_AJP_PROTOCOL_ERROR;
    }
    ae->endpoint.rd += (jk_uint64_t)rc;

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