Exemplo n.º 1
0
static ngx_int_t
ngx_http_ajp_create_request(ngx_http_request_t *r)
{
    ajp_msg_t                *msg;
    ngx_chain_t              *cl;
    ngx_http_ajp_ctx_t       *a;
    ngx_http_ajp_loc_conf_t  *alcf;

    a = ngx_http_get_module_ctx(r, ngx_http_ajp_module);
    alcf = ngx_http_get_module_loc_conf(r, ngx_http_ajp_module);

    if (a == NULL || alcf == NULL) {
        return NGX_ERROR;
    }

    msg = ajp_msg_reuse(&a->msg);

    if (NGX_OK != ajp_msg_create_buffer(r->pool,
                alcf->ajp_header_packet_buffer_size_conf, msg)) {
        return NGX_ERROR;
    }

    if (NGX_OK != ajp_marshal_into_msgb(msg, r, alcf)) {
        return NGX_ERROR;
    }

    ajp_msg_end(msg);

    cl = ngx_alloc_chain_link(r->pool);
    if (cl == NULL) {
        return NGX_ERROR;
    }

    cl->buf = msg->buf;
    cl->buf->flush = 1;

    a->state = ngx_http_ajp_st_forward_request_sent;

    if (alcf->upstream.pass_request_body) {
        a->body = r->upstream->request_bufs;
        r->upstream->request_bufs = cl;

        cl->next = ajp_data_msg_send_body(r,
                alcf->max_ajp_data_packet_size_conf, &a->body);

        if (a->body) {
            a->state = ngx_http_ajp_st_request_body_data_sending;
        }
        else {
            a->state = ngx_http_ajp_st_request_send_all_done;
        }

    } else {
        a->state = ngx_http_ajp_st_request_send_all_done;
        r->upstream->request_bufs = cl;
        cl->next = NULL;
    }

    return NGX_OK;
}
Exemplo n.º 2
0
/*
 * Read the ajp message and return the type of the message.
 */
apr_status_t ajp_read_header(apr_socket_t *sock,
                             request_rec  *r,
                             apr_size_t buffsize,
                             ajp_msg_t **msg)
{
    apr_byte_t result;
    apr_status_t rc;

    if (*msg) {
        rc = ajp_msg_reuse(*msg);
        if (rc != APR_SUCCESS) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00990)
                   "ajp_read_header: ajp_msg_reuse failed");
            return rc;
        }
    }
    else {
        rc = ajp_msg_create(r->pool, buffsize, msg);
        if (rc != APR_SUCCESS) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00991)
                   "ajp_read_header: ajp_msg_create failed");
            return rc;
        }
    }
    ajp_msg_reset(*msg);
    rc = ajp_ilink_receive(sock, *msg);
    if (rc != APR_SUCCESS) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00992)
               "ajp_read_header: ajp_ilink_receive failed");
        return rc;
    }
    ajp_msg_log(r, *msg, "ajp_read_header: ajp_ilink_receive packet dump");
    rc = ajp_msg_peek_uint8(*msg, &result);
    if (rc != APR_SUCCESS) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00993)
                      "ajp_read_header: ajp_msg_peek_uint8 failed");
        return rc;
    }
    ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
               "ajp_read_header: ajp_ilink_received %s (0x%02x)",
               ajp_type_str(result), result);
    return APR_SUCCESS;
}
Exemplo n.º 3
0
static ngx_int_t
ngx_http_ajp_reinit_request(ngx_http_request_t *r)
{
    ngx_http_ajp_ctx_t       *a;
    ngx_http_ajp_loc_conf_t  *alcf;

    a = ngx_http_get_module_ctx(r, ngx_http_ajp_module);
    alcf = ngx_http_get_module_loc_conf(r, ngx_http_ajp_module);

    if (a == NULL || alcf == NULL) {
        return NGX_ERROR;
    }

    a->state = ngx_http_ajp_st_init_state;
    a->pstate = ngx_http_ajp_pst_init_state;
    a->length = 0;
    a->extra_zero_byte = 0;

    ajp_msg_reuse(&a->msg);

    a->body = NULL;

    return NGX_OK;
}
Exemplo n.º 4
0
ngx_chain_t *
ajp_data_msg_send_body(ngx_http_request_t *r, size_t max_size,
    ngx_chain_t **body)
{
    size_t               size;
    ngx_buf_t           *b_in, *b_out;
    ajp_msg_t           *msg;
    ngx_chain_t         *out, *cl, *in;
    ngx_http_ajp_ctx_t  *a;

    a = ngx_http_get_module_ctx(r, ngx_http_ajp_module);

    if (*body == NULL || a == NULL) {
        return NULL;
    }

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "ajp_data_msg_send_body");

    msg = ajp_msg_reuse(&a->msg);

    if (ajp_alloc_data_msg(r->pool, msg) != NGX_OK) {
        return NULL;
    }

    out = cl = ngx_alloc_chain_link(r->pool);
    if (cl == NULL) {
        return NULL;
    }

    cl->buf = msg->buf;

    max_size -= AJP_HEADER_SZ;
    size = 0;
    in = *body;

    b_out = NULL;
    while (in) {
        b_in = in->buf;

        b_out = ngx_alloc_buf(r->pool);
        if (b_out == NULL) {
            return NULL;
        }
        ngx_memcpy(b_out, b_in, sizeof(ngx_buf_t));

        if (b_in->in_file) {
            if ((size_t)(b_in->file_last - b_in->file_pos) <=
                (max_size - size)) {

                b_out->file_pos = b_in->file_pos;
                b_out->file_last = b_in->file_pos = b_in->file_last;

                size += (size_t) b_out->file_last - (size_t) b_out->file_pos;

            } else if ((size_t)(b_in->file_last - b_in->file_pos) >
                       (max_size - size)) {

                b_out->file_pos = b_in->file_pos;
                b_in->file_pos += max_size - size;
                b_out->file_last = b_in->file_pos;

                size += (size_t) b_out->file_last - (size_t) b_out->file_pos;
            }

        } else {
            if ((size_t)(b_in->last - b_in->pos) <= (max_size - size)) {
                b_out->pos = b_in->pos;
                b_out->last = b_in->pos = b_in->last;

                size += b_out->last - b_out->pos;

            } else if ((size_t)(b_in->last - b_in->pos) > (max_size - size)) {
                b_out->pos = b_in->pos;
                b_in->pos += max_size - size;
                b_out->last = b_in->pos;

                size += b_out->last - b_out->pos;
            }
        }

        cl->next = ngx_alloc_chain_link(r->pool);
        if (cl->next == NULL) {
            return NULL;
        }

        cl = cl->next;
        cl->buf = b_out;

        if (size >= max_size) {
            break;

        } else {
            in = in->next;
        }
    }

    *body = in;
    cl->next = NULL;

    ajp_data_msg_end(msg, size);

    return out;
}
Exemplo n.º 5
0
static ngx_int_t
ngx_http_upstream_send_request_body(ngx_http_request_t *r,
    ngx_http_upstream_t *u)
{
    ngx_int_t                  rc;
    ngx_chain_t               *cl;
    ajp_msg_t                 *msg, local_msg;
    ngx_connection_t          *c;
    ngx_http_ajp_ctx_t        *a;
    ngx_http_ajp_loc_conf_t   *alcf;

    c = u->peer.connection;

    a = ngx_http_get_module_ctx(r, ngx_http_ajp_module);
    alcf = ngx_http_get_module_loc_conf(r, ngx_http_ajp_module);

    if (a->state > ngx_http_ajp_st_request_body_data_sending) {
        ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
                      "ngx_http_upstream_send_request_body: bad state(%d)",
                      a->state);
    }

    cl = ajp_data_msg_send_body(r, alcf->max_ajp_data_packet_size_conf,
                                &a->body);

    if (u->output.in == NULL && u->output.busy == NULL) {
        if (cl == NULL) {
            /* If there is no more data in the body (i.e. the servlet
             * container is trying to read past the end of the body),
             * the server will send back an "empty" packet, which is
             * a body packet with a payload length of 0.
             * (0x12,0x34,0x00,0x00)
             */
            msg = ajp_msg_reuse(&local_msg);

            if (ajp_alloc_data_msg(r->pool, msg) != NGX_OK) {
                return NGX_ERROR;
            }

            ajp_data_msg_end(msg, 0);

            cl = ngx_alloc_chain_link(r->pool);
            if (cl == NULL) {
                return NGX_ERROR;
            }

            cl->buf = msg->buf;
            cl->next = NULL;
        }
    }

    if (a->body) {
        a->state = ngx_http_ajp_st_request_body_data_sending;

    } else {
        a->state = ngx_http_ajp_st_request_send_all_done;
    }

    c->log->action = "sending request body again to upstream";

    rc = ngx_output_chain(&u->output, cl);

    if (rc == NGX_ERROR) {
        return NGX_ERROR;
    }

    if (c->write->timer_set) {
        ngx_del_timer(c->write);
    }

    if (rc == NGX_AGAIN) {
        ngx_add_timer(c->write, u->conf->send_timeout);

        if (ngx_handle_write_event(c->write, u->conf->send_lowat) != NGX_OK) {
            return NGX_ERROR;
        }

        u->write_event_handler = ngx_http_upstream_send_request_body_handler;

        return NGX_AGAIN;
    }

    /* rc == NGX_OK */

    if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
        if (ngx_tcp_push(c->fd) == NGX_ERROR) {
            ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno,
                          ngx_tcp_push_n " failed");
            return NGX_ERROR;
        }

        c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
    }

    ngx_add_timer(c->read, u->conf->read_timeout);

    if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
        return NGX_ERROR;
    }

    u->write_event_handler = ngx_http_upstream_dummy_handler;

    return NGX_OK;
}
Exemplo n.º 6
0
static ngx_int_t
ngx_http_ajp_process_header(ngx_http_request_t *r)
{
    u_char                   *pos, *last, type, reuse;
    uint16_t                  length;
    ngx_int_t                 rc;
    ngx_buf_t                *buf;
    ajp_msg_t                *msg;
    ngx_http_ajp_ctx_t       *a;
    ngx_http_upstream_t      *u;
    ngx_http_ajp_loc_conf_t  *alcf;

    a = ngx_http_get_module_ctx(r, ngx_http_ajp_module);
    alcf = ngx_http_get_module_loc_conf(r, ngx_http_ajp_module);

    if (a == NULL || alcf == NULL) {
        return NGX_ERROR;
    }

    ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0,
                  "ngx_http_ajp_process_header: state(%d)", a->state);

    u = r->upstream;

    msg = ajp_msg_reuse(&a->msg);
    buf = msg->buf = &u->buffer;

    while (buf->pos < buf->last) {

        ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0,
                      "ngx_http_ajp_process_header: parse response, "
                      "pos:%p, last:%p", buf->pos, buf->last);

        /* save the position for returning NGX_AGAIN */
        pos = buf->pos;
        last = buf->last;

        if (ngx_buf_size(msg->buf) < AJP_HEADER_LEN + 1) {
            return ngx_http_ajp_move_buffer(r, buf, pos, last);
        }

        rc = ajp_msg_parse_begin(msg);
        if (rc != NGX_OK) {
            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                          "ngx_http_ajp_process_header: bad header\n"
                          "%s", ajp_msg_dump(r->pool, msg, "bad header"));

            return NGX_ERROR;
        }

        rc = ajp_msg_get_uint8(msg, (u_char *)&type);
        if (rc != NGX_OK) {
            return NGX_ERROR;
        }

        switch (type) {
            case CMD_AJP13_GET_BODY_CHUNK:

                rc = ajp_msg_get_uint16(msg, &length);
                if (rc == AJP_EOVERFLOW) {
                    return ngx_http_ajp_move_buffer(r, buf, pos, last);
                }

                rc = ngx_http_upstream_send_request_body(r, u);
                if (rc != NGX_OK) {
                    return rc;
                }

                break;

            case CMD_AJP13_SEND_HEADERS:

                rc = ajp_unmarshal_response(msg, r, alcf);

                if (rc == NGX_OK) {
                    a->state = ngx_http_ajp_st_response_parse_headers_done;
                    return NGX_OK;

                } else if (rc == AJP_EOVERFLOW) {
                    a->state = ngx_http_ajp_st_response_recv_headers;

                    /* reinit the headers_int list, the memory may be stale */
                    ngx_list_reinit(&u->headers_in.headers);

                    /* It's an uncomplete AJP packet, move back to the header
                     * of packet, and parse the header again in next call
                     */
                    return ngx_http_ajp_move_buffer(r, buf, pos, last);

                } else {
                    return  NGX_ERROR;
                }

                break;

            case CMD_AJP13_SEND_BODY_CHUNK:

                buf->pos = pos;
                a->state = ngx_http_ajp_st_response_body_data_sending;

                /* input_filter function will process these data */
                return NGX_OK;

            case CMD_AJP13_END_RESPONSE:

                rc = ajp_msg_get_uint8(msg, &reuse);
                if (rc == AJP_EOVERFLOW) {
                    return ngx_http_ajp_move_buffer(r, buf, pos, last);
                }

                ngx_http_ajp_end_response(r, reuse);

                buf->last_buf = 1;
                return NGX_OK;

            default:

                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                              "ngx_http_ajp_process_header: "
                              "bad_packet_type(%d)\n%s",
                              type, ajp_msg_dump(r->pool, msg, "bad type"));

                return  NGX_ERROR;
        }
    }

    return NGX_AGAIN;
}