php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #64670
Patch stomp-patch-content-length revision 2013-05-06 21:20 UTC by mi+php at aldan dot algebra dot com
revision 2013-05-06 15:35 UTC by mi+php at aldan dot algebra dot com
revision 2013-04-18 18:41 UTC by mi+php at aldan dot algebra dot com

Patch stomp-patch-content-length for stomp Bug #64670

Patch version 2013-05-06 21:20 UTC

Return to Bug #64670 | Download this patch
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 UTC

Developer: mi+php@aldan.algebra.com



  --- stomp.h	2012-11-18 17:35:40.000000000 -0500
 +++ stomp.h	2013-05-03 17:19:36.000000000 -0400
 @@ -82,7 +82,9 @@
 +++ stomp.h	2013-05-06 12:26:05.000000000 -0400
 @@ -74,4 +74,5 @@
  #endif
  	stomp_frame_cell_t *buffer;
 +    char lead;
  } stomp_t;
  
 @@ -82,7 +83,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);
  -void stomp_set_error(stomp_t *stomp, const char *error, int errnum, const char *details);


   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-05-03 16:28:18.000000000 -0400
 @@ -36,5 +36,6 @@
 +++ stomp.c	2013-05-06 13:42:27.000000000 -0400
 @@ -24,5 +24,4 @@
  
  #include "php.h"
 -#include "zend_exceptions.h"
  #include "ext/standard/php_smart_str.h"
  #include "stomp.h"
 @@ -32,9 +31,9 @@
  
  ZEND_EXTERN_MODULE_GLOBALS(stomp);
 -extern zend_class_entry *stomp_ce_exception;
  
   /* {{{ stomp_init
    */
  -stomp_t *stomp_init() 
  +stomp_t *
  +stomp_init()
   {
   	/* Memory allocation */
 @@ -67,5 +68,6 @@
 @@ -61,4 +60,5 @@
  
  	stomp->buffer = NULL;
 +	stomp->lead = '\0';
  	return stomp;
  }
 @@ -67,5 +67,6 @@
   /* {{{ stomp_frame_buffer_push
   */
   */
  -void stomp_frame_buffer_push(stomp_frame_cell_t **pcell, stomp_frame_t *frame)
  +static void
  +stomp_frame_buffer_push(stomp_frame_cell_t **pcell, stomp_frame_t *frame)
   {
   	stomp_frame_cell_t *cell = (stomp_frame_cell_t *) emalloc(sizeof(stomp_frame_cell_t));
 @@ -85,5 +87,6 @@
 @@ -85,5 +86,6 @@
   /* {{{ stomp_frame_buffer_shift
    */
  -stomp_frame_t *stomp_frame_buffer_shift(stomp_frame_cell_t **pcell) {
  +static stomp_frame_t *
  +stomp_frame_buffer_shift(stomp_frame_cell_t **pcell) {
  	stomp_frame_t *frame = NULL;
  	stomp_frame_t *frame = NULL;
   	if (*pcell) {
 @@ -99,18 +102,24 @@
 @@ -99,18 +101,24 @@
   /* {{{ stomp_frame_buffer_clear
    */
  -void stomp_frame_buffer_clear(stomp_frame_cell_t **pcell) {
  +static void


  -	}   
  +	}
   	if (stomp->error_details != NULL) {
   		efree(stomp->error_details);
 @@ -121,13 +130,26 @@
 @@ -121,13 +129,26 @@
   		stomp->error = estrdup(error);
   	}
  -	if (details != NULL) {
  -		stomp->error_details = estrdup(details);


  +		va_end(ap);
  +		if (len < STOMP_BUFSIZE) /* shrink the buffer down */
  +			stomp->error_details =
  +			    erealloc(stomp->error_details, len + 1);
  	}
  }
  /* }}} */
  
  	}
  }
  /* }}} */
  
  -/* {{{ stomp_writeable 
  +/* {{{ stomp_writeable
    */
  -int stomp_writeable(stomp_t *stomp) 
  +static int
  +stomp_writeable(stomp_t *stomp)
   {
   	int     n;
 @@ -147,7 +169,8 @@
 @@ -147,7 +168,8 @@
   /* }}} */
   
  -/* {{{ stomp_connect 
  +/* {{{ stomp_connect


  +int
  +stomp_connect(stomp_t *stomp, const char *host, unsigned short port TSRMLS_DC)
   {
   	char error[1024];
 @@ -159,5 +182,5 @@
 @@ -159,5 +181,5 @@
   		efree(stomp->host);
   	}
  -	stomp->host = (char *) emalloc(strlen(host) + 1);
  +	stomp->host = emalloc(strlen(host) + 1);
   	memcpy(stomp->host, host, strlen(host));
   	stomp->host[strlen(host)] = '\0';
 @@ -171,5 +194,5 @@
 @@ -171,5 +193,5 @@
   	if (stomp->fd == -1) {
   		snprintf(error, sizeof(error), "Unable to connect to %s:%ld", stomp->host, stomp->port);
  -		stomp_set_error(stomp, error, errno, NULL);
  +		stomp_set_error(stomp, error, errno, "%s", strerror(errno));
   		return 0;
   	}
 @@ -179,6 +202,6 @@
 @@ -179,6 +201,6 @@
   	if (getsockname(stomp->fd, (struct sockaddr*) &stomp->localaddr, &size) == -1) {
   		snprintf(error, sizeof(error), "getsockname failed: %s (%d)", strerror(errno), errno);
  -		stomp_set_error(stomp, error, errno, NULL); 
  -		return 0; 
  +		stomp_set_error(stomp, error, errno, NULL);
  +		return 0;
   	}
   
 @@ -187,4 +210,6 @@
 @@ -187,4 +209,6 @@
   		if (stomp->options.use_ssl) {
   			SSL_CTX *ctx = SSL_CTX_new(SSLv23_client_method());
  +			int	 ret;
 +
 +
   			if (NULL == ctx) {
   				stomp_set_error(stomp, "failed to create the SSL context", 0, NULL);
 @@ -200,18 +225,19 @@
 @@ -200,18 +224,19 @@
   				return 0;
   			}
  -			
  +


  -		stomp_set_error(stomp, error, errno, NULL); 
  +		stomp_set_error(stomp, error, errno, "%s", strerror(errno));
   		return 0;
   	}
 @@ -221,5 +247,6 @@
 @@ -221,5 +246,6 @@
   /* {{{ stomp_close
    */
  -void stomp_close(stomp_t *stomp)
  +void
  +stomp_close(stomp_t *stomp)
  {
  {
   	if (NULL == stomp) {
 @@ -254,7 +281,8 @@
 @@ -254,7 +280,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 = { .c = NULL };
  
  
   	/* Command */
 @@ -265,15 +293,15 @@
 @@ -265,15 +292,15 @@
   	if (frame->headers) {
   
  -		char *key; 
  +		char *key;


  -			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);
   			}
 @@ -293,13 +321,11 @@
 @@ -293,13 +320,11 @@
   	smart_str_appendc(&buf, '\n');
   
  -	if (frame->body > 0) {
  +	if (frame->body) {


   		smart_str_free(&buf);
  +		stomp_set_error(stomp, "Unable to send data", errno, "%s", strerror(errno));
   		return 0;
   	}
 @@ -307,23 +333,23 @@
 @@ -307,23 +332,23 @@
   #ifdef HAVE_STOMP_SSL
   	if (stomp->options.use_ssl) {
  -		if (-1 == SSL_write(stomp->ssl_handle, buf.c, buf.len) || -1 == SSL_write(stomp->ssl_handle, "\0\n", 2)) {
  -			char error[1024];


  -#endif        
  +#endif
   
   	smart_str_free(&buf);
 @@ -335,5 +361,6 @@
 @@ -335,5 +360,6 @@
   /* {{{ stomp_recv
    */
  -int stomp_recv(stomp_t *stomp, char *msg, size_t length)
  +static int
  +stomp_recv(stomp_t *stomp, char *msg, size_t length)
   {
   	int len;
 @@ -349,8 +376,23 @@
 @@ -349,8 +375,23 @@
   #endif
   
  -	if (len == 0) {
  -		TSRMLS_FETCH();


  +		stomp->status = -1;
  +		break;
   	}
   	return len;
 @@ -358,55 +400,68 @@
 @@ -358,55 +399,68 @@
   /* }}} */
   
  -/* {{{ stomp_read_buffer 
  +/* {{{ stomp_recv_full


  -				}
  -				break;
  -			}
  +		if (buffer[i] == '\0')
 +			break;
  
 -			if (i >= bufsize) {
 -				buffer = (char *) erealloc(buffer, bufsize + STOMP_BUFSIZE);
 +			break;
  
 -			if (i >= bufsize) {
 -				buffer = (char *) erealloc(buffer, bufsize + STOMP_BUFSIZE);
  -				bufsize += STOMP_BUFSIZE;
  -			}
  +		i++;
   


   			return -1;
   		}
  +	} else
  +		efree(buffer);
  
  
  -		memcpy(*data, buffer, i);
  -	}
  -
  -	efree(buffer);


  -	return i-1;
  +	return i;
   }
   /* }}} */
 @@ -414,15 +469,14 @@
 @@ -414,15 +468,24 @@
   /* {{{ stomp_read_line
    */
  -static int stomp_read_line(stomp_t *stomp, char **data)
  +static int


   	size_t bufsize = STOMP_BUFSIZE + 1;
  -	char *buffer = (char *) emalloc(STOMP_BUFSIZE + 1);
  +	char *buffer = emalloc(STOMP_BUFSIZE + 1);
   
  	while (1) {
 -
 -	while (1) {
 +	/*
 +	 * While skipping the trailing newlines from the previous frame,
 +	 * we may have stumbled upon the first byte of this one.
 +	 */
 +	if (stomp->lead != '\0') {
 +		buffer[i++] = stomp->lead;
 +		stomp->lead = '\0';
 +		drain = 0;
 +	}
  
  -		size_t length = 1;
  -		rc = stomp_recv(stomp, buffer + i, length);
 +	while (1) {
  +		rc = stomp_recv(stomp, buffer + i, 1);
   		if (rc < 1) {
   			efree(buffer);
 @@ -430,36 +484,41 @@
 @@ -430,36 +493,35 @@
   		}
   
  -		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;


  -				break;
  -			} else if (buffer[i-1] == 0) {
  -				efree(buffer);
  -				return 0;
 -			}
 -			}
  +		i++;
   
  -			if (i >= bufsize) {
  -				buffer = (char *) erealloc(buffer, bufsize + STOMP_BUFSIZE);


  -			}
  +		if (i >= bufsize) {
  +			buffer = erealloc(buffer, bufsize + STOMP_BUFSIZE);
  +			bufsize += STOMP_BUFSIZE;
  		}
  		}
  -
   	}
   
  -	if (i > 1) {


  -	return i-1;
  +	return i;
   }
   /* }}} */
 @@ -467,5 +526,6 @@
 @@ -467,5 +529,6 @@
   /* {{{ stomp_free_frame
    */
  -void stomp_free_frame(stomp_frame_t *frame)
  +void
  +stomp_free_frame(stomp_frame_t *frame)
   {
   	if (frame) {
 @@ -485,11 +545,13 @@
 @@ -485,11 +548,13 @@
   /* }}} */
   
  -/* {{{ stomp_read_frame 
  +/* {{{ stomp_read_frame


   {
   	stomp_frame_t *f = NULL;
  -	char *cmd = NULL, *length_str = NULL;
  -	int length = 0;
 +	char *cmd = NULL;
 +	char *cmd;
  +	int length;
  +	char endbyte;
   
   	if (stomp->buffer) {
 @@ -498,4 +560,9 @@
 @@ -498,4 +563,9 @@
   
   	if (!stomp_select(stomp)) {
  +		stomp_set_error(stomp, "Timeout", 0, "No data available "
  +		    "within the specified timeout ",


  +		    stomp->options.read_timeout_sec,
  +		    stomp->options.read_timeout_sec);
   		return NULL;
   	}
 @@ -507,6 +574,8 @@
 @@ -507,6 +577,8 @@
   	}
   
  +	f->body_length = -1;
  +


  -	length = stomp_read_line(stomp, &cmd);
  +	length = stomp_read_line(stomp, &cmd, 1);
   	if (length < 1) {
   		RETURN_READ_FRAME_FAIL;
 @@ -518,54 +587,91 @@
 @@ -518,57 +590,96 @@
   	/* Parse the header */
   	while (1) {
  -		char *p = NULL;
  -		length = stomp_read_line(stomp, &p);


  +		break;
  +	case -1: /* Content-length not found among the headers */
   		f->body_length = stomp_read_buffer(stomp, &f->body);
   	}
 @@ -577,10 +683,10 @@
  
 +	stomp_select_ex(stomp, 0, 0); /* Drain any newlines already here */
 +
  	return f;
  }
 @@ -577,10 +688,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 +695,11 @@
 @@ -589,12 +700,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 +707,8 @@
 @@ -602,8 +712,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) {


  -					}
  +					void *error_msg = NULL;
  +					zend_hash_find(res->headers, "message", sizeof("message"), &error_msg);
  +					stomp_set_error(stomp, error_msg ? error_msg : "ERROR", 0,
 +					    res->body ? "%s" : NULL, res->body);
 +					    "%s", res->body ? res->body : "zhopa");
   					stomp_free_frame(res);
   					stomp->buffer = buffer;
 @@ -624,5 +729,6 @@
 @@ -624,27 +734,45 @@
   /* {{{ stomp_select
    */
  -int stomp_select(stomp_t *stomp)
  +int
  +stomp_select_ex(stomp_t *stomp, long sec, long usec)
   {
   	int     n;
 @@ -633,14 +739,14 @@
  	}
  	struct timeval tv;
  
 -	if (stomp->buffer) {
 +	if (stomp->buffer || stomp->lead != '\0') {
  		return 1;
  	}
   
  -	tv.tv_sec = stomp->options.read_timeout_sec;
  -	tv.tv_usec = stomp->options.read_timeout_usec;
  +	tv.tv_sec = sec;
  +	tv.tv_usec = usec;
 +	/*
 +	 * STOMP 1.1 spec says, there may be any number of newlines between
 +	 * frames. Though we tried to drain as many as have already arrived
 +	 * when we were finishing the processing of the previous frame, more
 +	 * may have come since then... So, before confirming, there is another
 +	 * frame pending, we have to ensure, the socket is not just readable,
 +	 * but that it has something other than newlines waiting in it...
 +	 */
 +	for (;;) {
 +		char byte;
   
  	n = php_pollfd_for(stomp->fd, PHP_POLLREADABLE, &tv);
  	if (n < 1) {
 -	n = php_pollfd_for(stomp->fd, PHP_POLLREADABLE, &tv);
 -	if (n < 1) {
 +		switch (php_pollfd_for(stomp->fd, PHP_POLLREADABLE, &tv)) {
 +		case -1:
 +			return 0;
 +		case 0:
   #if !defined(PHP_WIN32) && !(defined(NETWARE) && defined(USE_WINSOCK))
  -		if (n == 0) { 
 +		if (n == 0) {
   			errno = ETIMEDOUT;
  -		}   
  -#endif          
 +		}
 -		return 0;
  +#endif
  		return 0;
 +			return 0;
 +		case 1:
 +			if (stomp_recv(stomp, &byte, 1) < 1)
 +				return 0;
 +			if (byte == '\n')
 +				continue;
 +			stomp->lead = byte;
 +			return 1;
 +		}
   	}
 -
 -	return 1;
  }
 +
  /* }}} */
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun May 05 11:01:33 2024 UTC