예제 #1
0
APR_DECLARE(apr_status_t) stomp_read(stomp_connection *connection, stomp_frame **frame, apr_pool_t *pool) {
   
   apr_status_t rc;
   stomp_frame *f;
      
   f = apr_pcalloc(pool, sizeof(stomp_frame));
   if( f == NULL )
      return APR_ENOMEM;
   
   f->headers = apr_hash_make(pool);
   if( f->headers == NULL )
      return APR_ENOMEM;
         
#define CHECK_SUCCESS if( rc!=APR_SUCCESS ) { return rc; }
   
   // Parse the frame out.
   {
      char *p;
	  int length;
      
      // Parse the command.
	  rc = stomp_read_line(connection, &p, &length, pool);
	  CHECK_SUCCESS;

      f->command = p;
      
      // Start parsing the headers.
      while( 1 ) {
         rc = stomp_read_line(connection, &p, &length, pool);
		 CHECK_SUCCESS;
		 
		 // Done with headers
		 if(length == 0)
			break;

         {
            // Parse the header line.
            char *p2; 
            void *key;
            void *value;
            
            p2 = strstr(p,":");
            if( p2 == NULL ) {
               // Expected at 1 : to delimit the key from the value.
               return APR_EGENERAL;
            }
            
            // Null terminate the key
            *p2=0;            
            key = p;
            
            // The rest if the value.
            value = p2+1;
            
            // Insert key/value into hash table.
            apr_hash_set(f->headers, key, APR_HASH_KEY_STRING, value);            
         }
      }
      
      // Check for content length
	  {
		  char* content_length = apr_hash_get(f->headers, "content-length", APR_HASH_KEY_STRING);
		  if(content_length) {
			  char endbuffer[2];
			  apr_size_t length = 2;

			  f->body_length = atoi(content_length);
			  f->body = apr_pcalloc(pool, f->body_length);
			  rc = apr_socket_recv(connection->socket, f->body, &f->body_length);
			  CHECK_SUCCESS;

			  // Expect a \n after the end
			  rc = apr_socket_recv(connection->socket, endbuffer, &length);
			  CHECK_SUCCESS;
			  if(length != 2 || endbuffer[0] != '\0' || endbuffer[1] != '\n')
				  return APR_EGENERAL;
		  }
		  else
		  {
			  // The remainder of the buffer (including the \n at the end) is the body)
			  rc = stomp_read_buffer(connection, &f->body, pool);
			  CHECK_SUCCESS;
		  }
	  }
   }
   
#undef CHECK_SUCCESS
   *frame = f;
	return APR_SUCCESS;
}
예제 #2
0
파일: stomp.c 프로젝트: SAppleton/narayana
apr_status_t stomp_read(stomp_connection *connection, stomp_frame **frame, apr_pool_t *pool) {
   
   apr_status_t rc;
   stomp_frame *f;

   btlogger_trace("stomp_read");
   f = apr_pcalloc(pool, sizeof(stomp_frame));
   if( f == NULL ) {
      btlogger_warn("stomp_read returning APR_ENONMEM");
      return APR_ENOMEM; } f->headers = apr_hash_make(pool);
   if( f->headers == NULL ) {
     btlogger_warn("stomp_read returning 2nd APR_ENONMEM");
     return APR_ENOMEM;
   }
         
#define CHECK_SUCCESS if( rc!=APR_SUCCESS ) { return rc; }
   
   // Parse the frame out.
   {
      char *p;
	  int length;
      
      // Parse the command.
	  rc = stomp_read_line(connection, &p, &length, pool);
	  CHECK_SUCCESS;
	  btlogger_trace("Read the command %s", p);

      f->command = p;
      
      // Start parsing the headers.
      while( 1 ) {
         rc = stomp_read_line(connection, &p, &length, pool);
		 CHECK_SUCCESS;
         btlogger_trace("Read a header: %s length: %d", p, length);
		 
		 // Done with headers
		 if(length == 0)
			break;

         {
            // Parse the header line.
            char *p2; 
            void *key;
            void *value;
            
            p2 = strstr(p,":");
            if( p2 == NULL ) {
               // Expected at 1 : to delimit the key from the value.
               btlogger_warn("stomp_read returning APR_EGENERAL");
               return APR_EGENERAL;
            }
            
            // Null terminate the key
            *p2=0;            
            key = p;
            
            // The rest if the value.
            value = p2+1;
            
            // Insert key/value into hash table.
            btlogger_trace("Add key %s with value %s to stomp headers", key, value);
            apr_hash_set(f->headers, key, APR_HASH_KEY_STRING, value);            
         }
      }
      
      // Check for content length
	  {
		  char* content_length = apr_hash_get(f->headers, "content-length", APR_HASH_KEY_STRING);
		  if(content_length) {
			  char endbuffer[2];
			  apr_size_t length = 2;
			  apr_size_t bodysz;
			  apr_size_t tlen = 0;	// number of bytes read

			  btlogger_debug("Content-length %s detected", content_length);

			  bodysz = f->body_length = atoi(content_length);
				if ((f->body = apr_pcalloc(pool, f->body_length)) == NULL) {
					btlogger_warn("stomp_read insufficient memory for buffer");
					return APR_ENOMEM;
				}

				/*
				 * Cannot read the content in one go since network byte buffers are finite.
				 * Keep reading from the socket until body_length bytes have been read.
				 */
				while (tlen < bodysz) {
					char *bp = f->body + tlen;
					apr_size_t len = bodysz - tlen;

					rc = apr_socket_recv(connection->socket, bp, &len);
					CHECK_SUCCESS;
					tlen += len;
				}

			  // Expect a \n after the end
			  rc = apr_socket_recv(connection->socket, endbuffer, &length);
			  CHECK_SUCCESS;
			  if(length != 2 || endbuffer[0] != '\0' || endbuffer[1] != '\n') {
				  btlogger_warn("stomp_read returning 2nd APR_EGENERAL %d %c %c", length, endbuffer[0], endbuffer[1]);
				  return APR_EGENERAL;
                          }
		  }
		  else
		  {
			  btlogger_debug("No content-length detected");
			  // The remainder of the buffer (including the \n at the end) is the body)
			  rc = stomp_read_buffer(connection, &f->body, pool);
			  CHECK_SUCCESS;
		  }
	  }
   }
   
#undef CHECK_SUCCESS
   *frame = f;
	return APR_SUCCESS;
}