php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login | |
Patch stomp-patch-content-length for stomp Bug #64670Patch version 2013-05-06 15:35 UTC Return to Bug #64670 | Download this patchThis patch is obsolete Obsoleted by patches: This patch renders other patches obsolete Obsolete patches: Patch Revisions: 2013-05-06 21:20 UTC | 2013-05-06 15:35 UTC | 2013-04-18 18:41 UTCDeveloper: mi+php@aldan.algebra.com--- stomp.h 2012-11-18 17:35:40.000000000 -0500 +++ stomp.h 2013-04-17 16:41:22.000000000 -0400 @@ -83,5 +83,5 @@ +++ stomp.h 2013-05-03 17:19:36.000000000 -0400 @@ -82,7 +82,9 @@ stomp_frame_t *stomp_read_frame(stomp_t *connection); int stomp_valid_receipt(stomp_t *connection, stomp_frame_t *frame); int stomp_select(stomp_t *connection); -int stomp_select(stomp_t *connection); -void stomp_set_error(stomp_t *stomp, const char *error, int errnum, const char *details); +int stomp_select_ex(stomp_t *connection, long sec, long usec); +void stomp_set_error(stomp_t *stomp, const char *error, int errnum, const char *fmt, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 4, 0); void stomp_free_frame(stomp_frame_t *frame); + +#define stomp_select(s) stomp_select_ex(s, s->options.read_timeout_sec, s->options.read_timeout_usec) #endif /* _STOMP_H_ */ --- stomp.c 2012-11-18 17:35:40.000000000 -0500 +++ stomp.c 2013-04-18 12:22:03.000000000 -0400 +++ stomp.c 2013-05-03 16:28:18.000000000 -0400 @@ -36,5 +36,6 @@ /* {{{ stomp_init */ -stomp_t *stomp_init() +static stomp_frame_t * +stomp_frame_buffer_shift(stomp_frame_cell_t **pcell) { stomp_frame_t *frame = NULL; if (*pcell) { @@ -99,5 +102,6 @@ @@ -99,18 +102,24 @@ /* {{{ stomp_frame_buffer_clear */ -void stomp_frame_buffer_clear(stomp_frame_cell_t **pcell) { +static void +stomp_frame_buffer_clear(stomp_frame_cell_t **pcell) { stomp_frame_t *frame = NULL; while (frame = stomp_frame_buffer_shift(pcell)) efree(frame); @@ -105,12 +109,17 @@ - while (frame = stomp_frame_buffer_shift(pcell)) efree(frame); + while ((frame = stomp_frame_buffer_shift(pcell))) efree(frame); } /* }}} */ -/* {{{ stomp_set_error +/* {{{ stomp_set_error @@ -221,5 +247,6 @@ /* {{{ stomp_close */ -void stomp_close(stomp_t *stomp) +void +void +stomp_close(stomp_t *stomp) { if (NULL == stomp) { @@ -254,5 +281,6 @@ @@ -254,7 +281,8 @@ /* {{{ stomp_send */ -int stomp_send(stomp_t *stomp, stomp_frame_t *frame TSRMLS_DC) +int +stomp_send(stomp_t *stomp, stomp_frame_t *frame TSRMLS_DC) { smart_str buf = {0}; - smart_str buf = {0}; + smart_str buf = { .c = NULL }; /* Command */ @@ -265,15 +293,15 @@ if (frame->headers) { - char *key; while (zend_hash_get_current_key(frame->headers, &key, &pos, 0) == HASH_KEY_IS_STRING) { - char *value = NULL; + void *value = NULL; smart_str_appends(&buf, key); smart_str_appendc(&buf, ':'); - if (zend_hash_get_current_data(frame->headers, (void **)&value) == SUCCESS) { + if (zend_hash_get_current_data(frame->headers, &value) == SUCCESS) { smart_str_appends(&buf, value); } @@ -298,8 +326,6 @@ @@ -293,13 +321,11 @@ smart_str_appendc(&buf, '\n'); - if (frame->body > 0) { + if (frame->body) { smart_str_appendl(&buf, frame->body, frame->body_length > 0 ? frame->body_length : strlen(frame->body)); } if (!stomp_writeable(stomp)) { - char error[1024]; - snprintf(error, sizeof(error), "Unable to send data"); Line 262 (now 277), was 28 lines, now 26 lines +#else + "not " +#endif + ); + stomp->status = -1; stomp->status = -1; + break; + case 0: + stomp_set_error(stomp, "Sender closed connection unexpectedly", + 0, NULL); stomp->status = -1; + stomp->status = -1; + break; } return len; @@ -358,55 +400,77 @@ @@ -358,55 +400,68 @@ /* }}} */ -/* {{{ stomp_read_buffer +/* {{{ stomp_recv_full */ -static int stomp_read_buffer(stomp_t *stomp, char **data) + */ +static int +stomp_recv_full(stomp_t *stomp, char *msg, size_t length) { - int rc = 0; +{ + int i; + size_t length_read = 0; + + while (length_read < length) { + return length_read; +} +/* }}} */ + + + +/* {{{ stomp_read_buffer + */ */ -static int stomp_read_buffer(stomp_t *stomp, char **data) +static int +stomp_read_buffer(stomp_t *stomp, char **data) +{ + int rc; size_t i = 0; size_t bufsize = STOMP_BUFSIZE + 1; - char *buffer = (char *) emalloc(STOMP_BUFSIZE + 1); + char *buffer = emalloc(STOMP_BUFSIZE + 1); while (1) { - - size_t length = 1; - rc = stomp_recv(stomp, buffer + i, length); + rc = stomp_recv(stomp, buffer + i, 1); if (rc < 1) { { - int rc = 0; + int rc; size_t i = 0; size_t bufsize = STOMP_BUFSIZE + 1; - char *buffer = (char *) emalloc(STOMP_BUFSIZE + 1); + char *buffer = emalloc(STOMP_BUFSIZE + 1); while (1) { - - size_t length = 1; - rc = stomp_recv(stomp, buffer + i, length); + rc = stomp_recv(stomp, buffer + i, 1); if (rc < 1) { - efree(buffer); + efree(buffer); /* stomp_recv already threw */ + efree(buffer); /* stomp_recv already set error */ return -1; } - if (1 == length) { Line 335 (now 350), was 19 lines, now 11 lines - efree(buffer); - return 0; - } - break; + if (buffer[i] == '\0') { + char endline[1]; + if (1 != stomp_recv(stomp, endline, 1) && '\n' != endline[0]) { + efree(buffer); + stomp_set_error(stomp, "Protocol violation", 0, + "The byte after nil is %hu, rather than newline", + (unsigned short)endline[0]); + return 0; } - } + if (buffer[i] == '\0') + break; + } - if (i >= bufsize) { - buffer = (char *) erealloc(buffer, bufsize + STOMP_BUFSIZE); - bufsize += STOMP_BUFSIZE; - return i-1; + return i; } /* }}} */ @@ -414,15 +478,14 @@ @@ -414,15 +469,14 @@ /* {{{ stomp_read_line */ -static int stomp_read_line(stomp_t *stomp, char **data) +static int +stomp_read_line(stomp_t *stomp, char **data) +stomp_read_line(stomp_t *stomp, char **data, int drain) { - int rc = 0; + int rc; size_t i = 0; - rc = stomp_recv(stomp, buffer + i, length); + rc = stomp_recv(stomp, buffer + i, 1); if (rc < 1) { efree(buffer); @@ -430,36 +493,32 @@ @@ -430,36 +484,41 @@ } - if (1 == length) { - i++; + if (buffer[i] == '\n') { + /* + * Drain leading newlines, if any, that the STOMP + * protocol allows after the nul-byte of an earlier + * frame: + * http://stomp.github.io/stomp-specification-1.1.html + */ + if (drain) + continue; + buffer[i] = '\0'; + break; + } else if (buffer[i] == '\0') { + efree(buffer); + stomp_set_error(stomp, "Protocol violation", 0, + "Sender sent 0-byte before the newline"); + return 0; + } + drain = 0; - if (buffer[i-1] == '\n') { - buffer[i-1] = 0; - break; - char *cmd = NULL, *length_str = NULL; - int length = 0; + char *cmd = NULL; + int length; + char endbuffer[2]; + char endbyte; if (stomp->buffer) { @@ -507,4 +569,6 @@ @@ -498,4 +560,9 @@ if (!stomp_select(stomp)) { + stomp_set_error(stomp, "Timeout", 0, "No data available " + "within the specified timeout ", + "(%ld seconds, %ld microseconds)", + stomp->options.read_timeout_sec, + stomp->options.read_timeout_sec); return NULL; } @@ -507,6 +574,8 @@ } + f->body_length = -1; + + /* Parse the command */ length = stomp_read_line(stomp, &cmd); @@ -518,54 +582,76 @@ - length = stomp_read_line(stomp, &cmd); + length = stomp_read_line(stomp, &cmd, 1); if (length < 1) { RETURN_READ_FRAME_FAIL; @@ -518,54 +587,91 @@ /* Parse the header */ while (1) { - char *p = NULL; - length = stomp_read_line(stomp, &p); - + char *p, *p2, *key, *value; + size_t keylen, vallen; + length = stomp_read_line(stomp, &p); - + length = stomp_read_line(stomp, &p, 0); + if (length < 0) { RETURN_READ_FRAME_FAIL; } - if (p2 == NULL) { - efree(p); - RETURN_READ_FRAME_FAIL; - } - - /* Null terminate the key */ - *p2=0; - key = p; + p2 = strchr(p, ':'); - /* The rest is the value. */ - value = p2+1; - + p2 = strchr(p, ':'); - /* Insert key/value into hash table. */ - zend_hash_add(f->headers, key, strlen(key) + 1, value, strlen(value) + 1, NULL); + if (p2 == NULL) { efree(p); + stomp_set_error(stomp, "Protocol violation", 0, + "Header section contains a string without ", + "colon: %.*s", length, p); + RETURN_READ_FRAME_FAIL; } - } + vallen = length - keylen - 1; + + /* Check, if the header specifies content-length */ + if (keylen == sizeof("content-length") - 1 && + key[0] == 'c' && + strcmp("content-length", key) == 0) { + char *ep; + long lbodylen = strtol(value, &ep, 0); + - - if (length != stomp_recv(stomp, endbuffer, length) || endbuffer[0] != '\0' || endbuffer[1] != '\n') { + /* FALLTHROUGH */ + case 0: /* Content-length is explicitly specified as zero */ + if (stomp_recv(stomp, endbuffer, 2) != 2 || + endbuffer[0] != '\0' || endbuffer[1] != '\n') { + switch (stomp_recv_full(stomp, &endbyte, 1)) { + case 0: + stomp_set_error(stomp, "Protocol violation", 0, + "Could not read the ending of the frame"); + /* FALLTHROUGH */ + case -1: + /* stomp_recv already complained about error */ + RETURN_READ_FRAME_FAIL; + case 1: + if (endbyte == '\0') + break; /* Excellent */ + stomp_set_error(stomp, "Protocol violation", 0, + "Could not read the two closing bytes of the frame"); + "Ending byte frame read -- " + "0x%hhx -- is not \\0", + endbyte); RETURN_READ_FRAME_FAIL; } - } else { + break; + case -1: /* Content-length not found among the headers */ f->body_length = stomp_read_buffer(stomp, &f->body); } @@ -577,10 +663,10 @@ @@ -577,10 +683,10 @@ /* {{{ stomp_valid_receipt */ -int stomp_valid_receipt(stomp_t *stomp, stomp_frame_t *frame) { +int - if (zend_hash_find(frame->headers, "receipt", sizeof("receipt"), (void **)&receipt) == SUCCESS) { + if (zend_hash_find(frame->headers, "receipt", sizeof("receipt"), &receipt) == SUCCESS) { stomp_frame_cell_t *buffer = NULL; success = 0; @@ -589,12 +675,11 @@ @@ -589,12 +695,11 @@ if (res) { if (0 == strncmp("RECEIPT", res->command, sizeof("RECEIPT") - 1)) { - char *receipt_id = NULL; - if (zend_hash_find(res->headers, "receipt-id", sizeof("receipt-id"), (void **)&receipt_id) == SUCCESS - stomp_set_error(stomp, error, 0, NULL); + stomp_set_error(stomp, "Unexpected receipt id", 0, "%s", receipt_id); } stomp_free_frame(res); @@ -602,8 +687,8 @@ @@ -602,8 +707,8 @@ return success; } else if (0 == strncmp("ERROR", res->command, sizeof("ERROR") - 1)) { - char *error_msg = NULL; - if (zend_hash_find(res->headers, "message", sizeof("message"), (void **)&error_msg) == SUCCESS) { + stomp_set_error(stomp, error_msg ? error_msg : "ERROR", 0, + res->body ? "%s" : NULL, res->body); stomp_free_frame(res); stomp->buffer = buffer; @@ -624,5 +709,6 @@ @@ -624,5 +729,6 @@ /* {{{ stomp_select */ -int stomp_select(stomp_t *stomp) +int +stomp_select(stomp_t *stomp) +stomp_select_ex(stomp_t *stomp, long sec, long usec) { int n; @@ -639,8 +725,8 @@ @@ -633,14 +739,14 @@ } - tv.tv_sec = stomp->options.read_timeout_sec; - tv.tv_usec = stomp->options.read_timeout_usec; + tv.tv_sec = sec; + tv.tv_usec = usec; n = php_pollfd_for(stomp->fd, PHP_POLLREADABLE, &tv); if (n < 1) { #if !defined(PHP_WIN32) && !(defined(NETWARE) && defined(USE_WINSOCK)) - if (n == 0) { + if (n == 0) { |
Copyright © 2001-2024 The PHP Group All rights reserved. |
Last updated: Sat May 25 13:01:31 2024 UTC |