예제 #1
0
파일: mk_http.c 프로젝트: freyes/monkey
/*
 * Check if the client request still has pending data.
 *
 * Return 0 when all parts of the expected data has arrived or -1 when
 * the connection is on a pending status due to HTTP spec.
 *
 * This function is called from request.c :: mk_handler_read(..)
 */
int mk_http_pending_request(struct client_session *cs)
{
    int n;
    char *end;

    if (cs->body_length >= mk_endblock.len) {
        end = (cs->body + cs->body_length) - mk_endblock.len;
    }
    else {
        return -1;
    }

    /* try to match CRLF at the end of the request */
    if (cs->body_pos_end < 0) {
        if (strncmp(end, mk_endblock.data, mk_endblock.len) == 0) {
            cs->body_pos_end = cs->body_length - mk_endblock.len;
        }
        else if ((n = mk_string_search(cs->body, mk_endblock.data, MK_STR_SENSITIVE)) >= 0 ) {
            cs->body_pos_end = n;
        }
        else {
            return -1;
        }
    }

    if (cs->first_method == MK_HTTP_METHOD_UNKNOWN) {
        cs->first_method = mk_http_method_get(cs->body);
    }

    if (cs->first_method == MK_HTTP_METHOD_POST || cs->first_method == MK_HTTP_METHOD_PUT) {
        if (cs->body_pos_end > 0) {
            int content_length;
            int current;

            current = cs->body_length - cs->body_pos_end - mk_endblock.len;
            content_length = mk_method_validate_content_length(cs->body, current);

            MK_TRACE("HTTP DATA %i/%i", current, content_length);

            if (content_length >= config->max_request_size) {
                return 0;
            }

            /* if first block has ended, we need to verify if exists
             * a previous block end, that will means that the POST
             * method has sent the whole information.
             * just for ref: pipelining is not allowed with POST
             */
            if ((unsigned int) cs->body_pos_end == cs->body_length - mk_endblock.len) {
                /* Content-length is required, if is it not found,
                 * we pass as successful in order to raise the error
                 * later
                 */
                if (content_length <= 0) {
                    cs->status = MK_REQUEST_STATUS_COMPLETED;
                    return 0;
                }
                else {
                    return -1;
                }
            }
            else {
                if (current < content_length) {
                    return -1;
                }
                else {
                    cs->status = MK_REQUEST_STATUS_COMPLETED;
                    return 0;
                }
            }
        }
        else {
            return -1;
        }
    }

    cs->status = MK_REQUEST_STATUS_COMPLETED;
    return 0;
}
예제 #2
0
static int mk_request_parse(struct client_session *cs)
{
    int i, end;
    int blocks = 0;
    struct session_request *sr_node;
    struct mk_list *sr_list, *sr_head;

    for (i = 0; i <= cs->body_pos_end; i++) {
        /*
         * Pipelining can just exists in a persistent connection or
         * well known as KeepAlive, so if we are in keepalive mode
         * we should check if we have multiple request in our body buffer
         */
        end = mk_string_search(cs->body + i, mk_endblock.data, MK_STR_SENSITIVE) + i;
        if (end <  0) {
            return -1;
        }

        /* Allocating request block */
        if (blocks == 0) {
            sr_node = &cs->sr_fixed;
            memset(sr_node, '\0', sizeof(struct session_request));
        }
        else {
            sr_node = mk_mem_malloc_z(sizeof(struct session_request));
        }
        mk_request_init(sr_node);

        /* We point the block with a mk_ptr_t */
        sr_node->body.data = cs->body + i;
        sr_node->body.len = end - i;

        /* Method, previous catch in mk_http_pending_request */
        if (i == 0) {
            sr_node->method = cs->first_method;
        }
        else {
            sr_node->method = mk_http_method_get(sr_node->body.data);
        }

        /* Looking for POST data */
        if (sr_node->method == MK_HTTP_METHOD_POST) {
            int offset;
            offset = end + mk_endblock.len;
            sr_node->data = mk_method_get_data(cs->body + offset,
                                               cs->body_length - offset);
        }

        /* Increase index to the end of the current block */
        i = (end + mk_endblock.len) - 1;

        /* Link block */
        mk_list_add(&sr_node->_head, &cs->request_list);

        /* Update counter */
        blocks++;
    }

    /* DEBUG BLOCKS
    struct mk_list *head;
    struct session_request *entry;

    printf("\n*******************\n");
    mk_list_foreach(head, &cs->request_list) {
        entry = mk_list_entry(head, struct session_request, _head);
        mk_ptr_print(entry->body);
        fflush(stdout);
    }
    */

    /* Checking pipelining connection */
    if (blocks > 1) {
        sr_list = &cs->request_list;
        mk_list_foreach(sr_head, sr_list) {
            sr_node = mk_list_entry(sr_head, struct session_request, _head);
            /* Pipelining request must use GET or HEAD methods */
            if (sr_node->method != MK_HTTP_METHOD_GET &&
                sr_node->method != MK_HTTP_METHOD_HEAD) {
                return -1;
            }
        }