[WAMP] Message verification, fixes #105

Validate all messages follow WAMP protocol
This commit is contained in:
Chris Boden 2013-07-20 12:31:44 -04:00
parent d7cbafb074
commit 9a50835637
5 changed files with 44 additions and 9 deletions

View File

@ -6,7 +6,7 @@ use Ratchet\ConnectionInterface;
/** /**
* WebSocket Application Messaging Protocol * WebSocket Application Messaging Protocol
* *
* @link http://wamp.ws/spec * @link http://wamp.ws/spec
* @link https://github.com/oberstet/AutobahnJS * @link https://github.com/oberstet/AutobahnJS
* *
@ -89,6 +89,10 @@ class ServerProtocol implements MessageComponentInterface, WsServerInterface {
throw new JsonException; throw new JsonException;
} }
if (!is_array($json) || $json !== array_values($json)) {
throw new \UnexpectedValueException("Invalid WAMP message format");
}
switch ($json[0]) { switch ($json[0]) {
case static::MSG_PREFIX: case static::MSG_PREFIX:
$from->WAMP->prefixes[$json[1]] = $json[2]; $from->WAMP->prefixes[$json[1]] = $json[2];

View File

@ -6,7 +6,7 @@ use Ratchet\Wamp\ServerProtocol as WAMP;
/** /**
* A ConnectionInterface object wrapper that is passed to your WAMP application * A ConnectionInterface object wrapper that is passed to your WAMP application
* representing a client. Methods on this Connection are therefore different. * representing a client. Methods on this Connection are therefore different.
* @property \stdClass $WAMP * @property \stdClass $WAMP
*/ */
class WampConnection extends AbstractConnectionDecorator { class WampConnection extends AbstractConnectionDecorator {
@ -96,7 +96,7 @@ class WampConnection extends AbstractConnectionDecorator {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function close() { public function close($opt = null) {
$this->getConnection()->close(); $this->getConnection()->close($opt);
} }
} }

View File

@ -37,7 +37,13 @@ class WampServer implements MessageComponentInterface, WsServerInterface {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function onMessage(ConnectionInterface $conn, $msg) { public function onMessage(ConnectionInterface $conn, $msg) {
$this->wampProtocol->onMessage($conn, $msg); try {
$this->wampProtocol->onMessage($conn, $msg);
} catch (JsonException $je) {
$conn->close(1007);
} catch (\UnexpectedValueException $uve) {
$conn->close(1007);
}
} }
/** /**

View File

@ -247,4 +247,23 @@ class ServerProtocolTest extends \PHPUnit_Framework_TestCase {
$this->assertContains('wamp', $wamp->getSubProtocols()); $this->assertContains('wamp', $wamp->getSubProtocols());
} }
public function badFormatProvider() {
return array(
array(json_encode(true))
, array('{"valid":"json", "invalid": "message"}')
, array('{"0": "fail", "hello": "world"}')
);
}
/**
* @dataProvider badFormatProvider
*/
public function testValidJsonButInvalidProtocol($message) {
$this->setExpectedException('\UnexpectedValueException');
$conn = $this->newConn();
$this->_comp->onOpen($conn);
$this->_comp->onMessage($conn, $message);
}
} }

View File

@ -7,10 +7,6 @@ use Ratchet\AbstractMessageComponentTestCase;
* @covers Ratchet\Wamp\WampServer * @covers Ratchet\Wamp\WampServer
*/ */
class WampServerTest extends AbstractMessageComponentTestCase { class WampServerTest extends AbstractMessageComponentTestCase {
private $serv;
private $mock;
private $conn;
public function getConnectionClassString() { public function getConnectionClassString() {
return '\Ratchet\Wamp\WampConnection'; return '\Ratchet\Wamp\WampConnection';
} }
@ -41,4 +37,14 @@ class WampServerTest extends AbstractMessageComponentTestCase {
// todo: could expand on this // todo: could expand on this
$this->assertInternalType('array', $this->_serv->getSubProtocols()); $this->assertInternalType('array', $this->_serv->getSubProtocols());
} }
public function testConnectionClosesOnInvalidJson() {
$this->_conn->expects($this->once())->method('close');
$this->_serv->onMessage($this->_conn, 'invalid json');
}
public function testConnectionClosesOnProtocolError() {
$this->_conn->expects($this->once())->method('close');
$this->_serv->onMessage($this->_conn, json_encode(array('valid' => 'json', 'invalid' => 'protocol')));
}
} }