Skip to content

Commit 4682343

Browse files
committed
Merge pull request #2 from centraldesktop/feature/read-content-length
Feature/read content length
2 parents 787a86a + 2b63756 commit 4682343

File tree

5 files changed

+228
-30
lines changed

5 files changed

+228
-30
lines changed

src/CentralDesktop/Stomp/Connection.php

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,7 @@ function readFrame() {
608608
$end = false;
609609

610610
do {
611+
$data = '';
611612
// Only read from the socket if we don't have a complete message in the buffer.
612613
if (!$this->_bufferContainsMessage()) {
613614
$read = fread($this->_socket, $rb);
@@ -694,6 +695,21 @@ function _appendToBuffer($packet) {
694695
*/
695696
public
696697
function _bufferContainsMessage() {
698+
699+
// we want to check on 'content-length' header first
700+
$buffer = ltrim($this->read_buffer, "\n");
701+
$headers_string = strstr($buffer, "\n\n", true);
702+
703+
if(preg_match('%^content-length:(\d++)$%m', $headers_string, $matches) > 0) {
704+
$content_length = (int) $matches[1];
705+
706+
$buffer = strstr($buffer, "\n\n", false);
707+
$buffer = substr($buffer, 2);
708+
709+
return mb_strlen($buffer, '8bit') >= $content_length;
710+
}
711+
712+
// else check on eol for message to be present
697713
return (strpos($this->read_buffer, "\x00") !== false);
698714
}
699715

@@ -704,12 +720,32 @@ function _bufferContainsMessage() {
704720
*/
705721
public
706722
function _extractNextMessage() {
723+
707724
$message = '';
708725
if ($this->_bufferContainsMessage()) {
709-
$end_of_message = strpos($this->read_buffer, "\x00");
710-
$message = substr($this->read_buffer, 0, $end_of_message); // Fetch the message, leave the Ascii NUL
711-
$message = ltrim($message, "\n");
712-
$this->read_buffer = substr($this->read_buffer, $end_of_message + 1); // Delete the message, including the Ascii NUL
726+
727+
// clean up brakes on the beggining of the buffer if any
728+
$this->read_buffer = ltrim($this->read_buffer, "\n");
729+
730+
// use regex to check on 'content-length' header and don't do whole headers parcing
731+
if(preg_match('%^content-length:(\d++)$%m', $this->read_buffer, $matches) > 0) {
732+
733+
$end_of_headers = strpos($this->read_buffer, "\n\n");
734+
$content_length = (int) $matches[1];
735+
736+
// read message (headers + \n\n + body)
737+
$message = substr($this->read_buffer, 0, $end_of_headers + 2 + $content_length);
738+
739+
// remove message (headers + body) from buffer including Ascii NULL
740+
$this->read_buffer = substr($this->read_buffer, $end_of_headers + 2 + $content_length + 1);
741+
742+
} else {
743+
744+
$end_of_message = strpos($this->read_buffer, "\x00");
745+
$message = substr($this->read_buffer, 0, $end_of_message); // Fetch the message, leave the Ascii NUL
746+
$message = ltrim($message, "\n");
747+
$this->read_buffer = substr($this->read_buffer, $end_of_message + 1); // Delete the message, including the Ascii NUL
748+
}
713749
}
714750

715751
return ($message);
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
/**
3+
*
4+
* Copyright 2005-2006 The Apache Software Foundation
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
namespace CentralDesktop\Stomp\ConnectionFactory;
20+
21+
use CentralDesktop\Stomp;
22+
23+
/**
24+
* simple null factory that makes easy testing
25+
*
26+
*/
27+
class NullFactory implements Stomp\ConnectionFactory\FactoryI {
28+
29+
/**
30+
* Gets the next URL to connect to
31+
*
32+
* @return \InfiniteIterator
33+
*/
34+
public
35+
function getHostIterator() {
36+
return new \InfiniteIterator(new \ArrayIterator(array()));
37+
}
38+
39+
public
40+
function __toString() {
41+
return __CLASS__;
42+
}
43+
}

src/CentralDesktop/Stomp/Message/Map.php

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
*
2525
* @package Stomp
2626
*/
27-
class Map extends Stomp\Message {
27+
class Map extends Stomp\Message\Bytes {
2828
public $map;
2929

3030
/**
@@ -51,12 +51,14 @@ function __construct($msg, $headers = null) {
5151

5252
}
5353
else {
54-
$this->_init("SEND", $headers, $msg);
55-
if ($this->headers == null) {
56-
$this->headers = array();
54+
55+
if(!is_array($headers)) {
56+
$headers = array();
5757
}
58-
$this->headers['transformation'] = 'jms-map-json';
59-
$this->body = json_encode($msg);
58+
59+
$headers = array_merge($headers, array('transformation' => 'jms-map-json'));
60+
61+
parent::__construct(json_encode($msg), $headers);
6062
}
6163
}
6264

@@ -78,4 +80,3 @@ function decode_xml($body) {
7880
}
7981
}
8082

81-
?>

test/src/CentralDesktop/Stomp/Test/BufferTest.php

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,7 @@
66
namespace CentralDesktop\Stomp\Test;
77

88
use CentralDesktop\Stomp;
9-
10-
11-
class NullFactory implements Stomp\ConnectionFactory\FactoryI {
12-
13-
/**
14-
* Gets the next URL to connect to
15-
*
16-
* @return \InfiniteIterator
17-
*/
18-
public
19-
function getHostIterator() {
20-
return new \InfiniteIterator(new \ArrayIterator(array()));
21-
}
22-
23-
public
24-
function __toString() {
25-
return __CLASS__;
26-
}
27-
}
9+
use CentralDesktop\Stomp\ConnectionFactory\NullFactory;
2810

2911

3012
class BufferTest extends \PHPUnit_Framework_TestCase {
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
<?php
2+
/**
3+
*
4+
* Copyright 2005-2006 The Apache Software Foundation
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
namespace CentralDesktop\Stomp\Test;
20+
21+
use CentralDesktop\Stomp;
22+
use CentralDesktop\Stomp\Connection;
23+
24+
25+
/**
26+
* Stomp test case.
27+
* @package Stomp
28+
* @author Val Minyaylo <[email protected]>
29+
*/
30+
class ConnectionReadTest extends \PHPUnit_Framework_TestCase {
31+
32+
/**
33+
* simple read test from buffer
34+
* put couple of messages in buffer and try to read them
35+
*/
36+
public function testConnectionRad() {
37+
38+
39+
$connection = new Connection(new Stomp\ConnectionFactory\NullFactory());
40+
41+
$this->assertFalse($connection->_bufferContainsMessage(), 'Do not expect any messages in connection');
42+
43+
$frame1 = new Stomp\Message\Bytes("lorem ipsum \n\n \x00 dolore sitamet", array('foo' => 'meta'));
44+
$connection->_appendToBuffer("\n\n");
45+
$connection->_appendToBuffer($frame1->__toString());
46+
$connection->_appendToBuffer("\n\n\n");
47+
48+
$frame2 = new Stomp\Message\Bytes("lorem forem \n\n, none \x00", array('beta' => 'treu', 'mod' => false));
49+
$connection->_appendToBuffer($frame2->__toString());
50+
51+
$this->assertTrue($connection->_bufferContainsMessage(), 'Expect to have frame to read.');
52+
$result = $connection->readFrame();
53+
54+
$this->assertInstanceOf('CentralDesktop\Stomp\Frame', $result);
55+
$this->assertEquals($frame1->body, $result->body);
56+
57+
$this->assertTrue($connection->_bufferContainsMessage(), "We should have some message in buffer");
58+
$connection->readFrame();
59+
60+
$this->assertFalse($connection->_bufferContainsMessage(), 'Now buffer should be empty');
61+
62+
}
63+
64+
/**
65+
* append messages to a buffer in chunks
66+
* and make sure we properly determine if there is a message in a buffer
67+
* and properly read messages
68+
*/
69+
public function testConnectionReadChunks() {
70+
71+
$connection = new Connection(new Stomp\ConnectionFactory\NullFactory());
72+
$frame1 = new Stomp\Message\Map(array("title" => "lorem ipsum \n\n test \x00 end of line", "descripiton" => "test1\x00\n\n"));
73+
$frame2 = new Stomp\Message\Map(array("title" => "lorem ipsum \n\n test \x00 end of line", "descripiton" => "test2\x00\n\n"));
74+
75+
$this->assertFalse($connection->_bufferContainsMessage(), 'Do not expect any messages in connection');
76+
77+
$connection->_appendToBuffer($frame1->__toString());
78+
79+
// brake second message apart so we can insert chunks of it in to buffer
80+
$frame2_msg = $frame2->__toString();
81+
$frame2_part1 = substr($frame2_msg, 0, 50);
82+
$frame2_part2 = substr($frame2_msg, 50);
83+
84+
// append just a chunk of a second message
85+
$connection->_appendToBuffer("\n\n");
86+
$connection->_appendToBuffer($frame2_part1);
87+
88+
$this->assertTrue($connection->_bufferContainsMessage(), 'Expect a message and a half');
89+
90+
//remove first message from buffer
91+
$message = $connection->readFrame();
92+
$this->assertNotNull($message, "Expected a message");
93+
94+
$this->assertFalse($connection->_bufferContainsMessage(), "There is only half of message in a buffere");
95+
96+
// put second chank in to a buffer
97+
$connection->_appendToBuffer($frame2_part2);
98+
$this->assertTrue($connection->_bufferContainsMessage(), "We should have got a message in a buffer");
99+
100+
$message2 = $connection->readFrame();
101+
$this->assertNotNull($message2, "Expected second frame here");
102+
}
103+
}
104+
105+
106+
107+
108+
109+
110+
111+
112+
113+
114+
115+
116+
117+
118+
119+
120+
121+
122+
123+
124+
125+
126+
127+
128+
129+
130+
131+
132+
133+
134+
135+
136+

0 commit comments

Comments
 (0)