Esempio n. 1
0
long ion_stream_search_token(struct evbuffer * buffer, ion_stream_token * token) {
    struct evbuffer_ptr ptr_end;
    struct evbuffer_ptr ptr_start;
    struct evbuffer_ptr ptr_result;
    size_t current_size = evbuffer_get_length(buffer);
    size_t end = (size_t)token->offset + (size_t)token->length - 1;
    size_t length = (size_t)token->length;
    if(current_size == 0) {
        token->position = -1;
        return SUCCESS;
    }
    if(token->offset >= current_size || ZSTR_LEN(token->token) > current_size) {
        token->position = -1;
        return SUCCESS;
    }
    if(end >= current_size - 1) { // libevent bug? if <end> is last element - evbuffer_search_range can't find token
        length = 0;
    }

    if(evbuffer_ptr_set(buffer, &ptr_start, (size_t)token->offset, EVBUFFER_PTR_SET) == FAILURE) {
        return FAILURE;
    }
    if(length) {
        if(evbuffer_ptr_set(buffer, &ptr_end, end, EVBUFFER_PTR_SET) == FAILURE) {
            return FAILURE;
        }
        ptr_result = evbuffer_search_range(buffer, ZSTR_VAL(token->token), ZSTR_LEN(token->token), &ptr_start, &ptr_end);
    } else {
        ptr_result = evbuffer_search(buffer, ZSTR_VAL(token->token), ZSTR_LEN(token->token), &ptr_start);
    }
    if(token->length > 0 && current_size >= token->length) {
        token->flags |= ION_STREAM_TOKEN_LIMIT;
    }
    token->offset = (zend_long)(current_size - ZSTR_LEN(token->token) + 1);
    token->position = (long)ptr_result.pos;
    return SUCCESS;
}
Esempio n. 2
0
int netstring_read_evbuffer(struct bufferevent *bev, netstring_t **netstring)
{
    int bytes, offset;
    size_t read_len;
    char *temp_buffer;
    temp_buffer = NULL;
    offset = 0;
    struct evbuffer *ib = bufferevent_get_input(bev);

    if (*netstring == NULL) {
        /* No buffer yet. Peek at first 10 bytes, to get length and colon. */
        unsigned char *lenstr;
        int i, len;
        struct evbuffer_ptr *search_end = pkg_malloc(sizeof(struct evbuffer_ptr));
        CHECK_MALLOC(search_end);

        i = evbuffer_get_length(ib);
        len = ((NETSTRING_PEEKLEN <= i) ? (NETSTRING_PEEKLEN) : (i-1));
        evbuffer_ptr_set(ib, search_end, len, EVBUFFER_PTR_SET);
        struct evbuffer_ptr loc = evbuffer_search_range(ib, ":", 1, NULL, search_end);
        pkg_free(search_end);
        if (loc.pos < 0) {
            // no colon found
            if (i > NETSTRING_PEEKLEN)
                return NETSTRING_ERROR_TOO_LONG;
            // TODO: peek at what's available and return suitable errors
            return NETSTRING_INCOMPLETE;
        }


        lenstr = pkg_malloc(loc.pos+1);
        CHECK_MALLOC(lenstr);
        bytes = evbuffer_remove(ib, lenstr, loc.pos+1);

        /* First character must be a digit */
        if (!isdigit(lenstr[0]))
            return NETSTRING_ERROR_NO_LENGTH;

        /* No leading zeros allowed! */
        if (lenstr[0] == '0' && isdigit(lenstr[1]))
            return NETSTRING_ERROR_LEADING_ZERO;
        if (lenstr[loc.pos] != ':') {
            return NETSTRING_ERROR_NO_COLON;
        }
        len = i = 0;

        /* Read the number of bytes */
        for (i = 0; i < loc.pos; i++) {
            /* Accumulate each digit, assuming ASCII. */
            len = len*10 + (lenstr[i] - '0');
        }
        pkg_free(lenstr);
        /* alloc the memory needed for the whole netstring */
        read_len = len+1;
        temp_buffer = pkg_malloc(read_len);
        CHECK_MALLOC(temp_buffer);

        /* initialize the netstring struct */
        *netstring = pkg_malloc(sizeof(netstring_t));
        CHECK_MALLOC(netstring);
        (*netstring)->read = 0;
        (*netstring)->length = len;
        (*netstring)->buffer = temp_buffer;
        (*netstring)->string = NULL;
    } else {
        /* Continue reading into an existing buffer. */
        offset = (*netstring)->read;
        read_len = (*netstring)->length-offset+1;
        temp_buffer = (*netstring)->buffer + offset;
    }

    /* Read from the evbuffer */
    bytes = evbuffer_remove(ib, temp_buffer, read_len);
    int total = (*netstring)->read += bytes;

    /* See if we have the whole netstring yet */
    if (read_len > bytes) {
        return NETSTRING_INCOMPLETE;
    }

    /* Test for the trailing comma */
    if (((*netstring)->buffer)[total-1] != ',') {
        return NETSTRING_ERROR_NO_COMMA;
    }

    /* Replace the comma with \0 */
    (*netstring)->buffer[total-1] = '\0';

    /* Set the string pointer to the "body" of the netstring */
    (*netstring)->string = (*netstring)->buffer;
    return 0;
}