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; }
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; }