From 3ef9f45de5d4613c68b7aa78c0686c8d68627c20 Mon Sep 17 00:00:00 2001 From: Chris Boden Date: Wed, 7 Sep 2011 11:19:28 -0400 Subject: [PATCH] Attempting to circumvent "golden hammer" issue --- lib/Ratchet/Socket.php | 48 +++++++++++++++++++++++++++--- tests/Ratchet/Tests/SocketTest.php | 26 +++++++++++++++- 2 files changed, 69 insertions(+), 5 deletions(-) diff --git a/lib/Ratchet/Socket.php b/lib/Ratchet/Socket.php index 2982025..263bf9a 100644 --- a/lib/Ratchet/Socket.php +++ b/lib/Ratchet/Socket.php @@ -10,7 +10,7 @@ class Socket { /** * @type resource */ - protected $_socket; + public $_resource; public static $_defaults = Array( 'domain' => AF_INET @@ -27,9 +27,9 @@ class Socket { public function __construct($domain = null, $type = null, $protocol = null) { list($domain, $type, $protocol) = static::getConfig($domain, $type, $protocol); - $this->_socket = @socket_create($domain, $type, $protocol); + $this->_resource = @socket_create($domain, $type, $protocol); - if (!is_resource($this->_socket)) { + if (!is_resource($this->_resource)) { throw new Exception(); } } @@ -73,6 +73,46 @@ class Socket { return Array($domain, $type, $protocol); } + /** + * Since PHP is retarded and their golden hammer, the array, doesn't implement any interfaces I have to hackishly overload socket_select + * @param Iterator|Array|NULL The sockets listed in the read array will be watched to see if characters become available for reading (more precisely, to see if a read will not block - in particular, a socket resource is also ready on end-of-file, in which case a socket_read() will return a zero length string). + * @param Iterator|Array|NULL The sockets listed in the write array will be watched to see if a write will not block. + * @param Iterator|Array|NULL The sockets listed in the except array will be watched for exceptions. + * @param int The tv_sec and tv_usec together form the timeout parameter. The timeout is an upper bound on the amount of time elapsed before socket_select() return. tv_sec may be zero , causing socket_select() to return immediately. This is useful for polling. If tv_sec is NULL (no timeout), socket_select() can block indefinitely. + * @param int + * @throws \InvalidArgumentException + * @todo See if this crack-pot scheme works! + */ + public function select(&$read, &$write, &$except, $tv_sec, $tv_usec = 0) { + $read = static::mungForSelect($read); + $write = static::mungForSelect($write); + $except = static::mungForSelect($except); + + socket_select($read, $write, $except, $tv_sec, $tv_usec); + } + + /** + * @param Iterator|Array|NULL + * @return Array|NULL + * @throws \InvalidArgumentException + */ + protected static function mungForSelect($collection) { + if (null === $collection || is_array($collection)) { + return $collection; + } + + if (!($collection instanceof \Traversable)) { + throw new \InvalidArgumentException('Object pass is not traversable'); + } + + $return = Array(); + foreach ($collection as $key => $socket) { + $return[$key] = ($socket instanceof \Ratchet\Socket ? $socket->_resource : $socket); + } + + return $return; + } + /** * @internal * @param string @@ -82,7 +122,7 @@ class Socket { */ public function __call($method, $arguments) { if (function_exists('socket_' . $method)) { - array_unshift($arguments, $this->_socket); + array_unshift($arguments, $this->_resource); return call_user_func_array('socket_' . $method, $arguments); } diff --git a/tests/Ratchet/Tests/SocketTest.php b/tests/Ratchet/Tests/SocketTest.php index 967638b..e9f9e9e 100644 --- a/tests/Ratchet/Tests/SocketTest.php +++ b/tests/Ratchet/Tests/SocketTest.php @@ -62,9 +62,33 @@ class SocketTest extends \PHPUnit_Framework_TestCase { $socket = Socket::createFromConfig($protocol); $config = $protocol::getDefaultConfig(); - // chnage this to array_filter late + // change this to array_filter late unset($config['options']); $this->assertAttributeEquals($config, '_arguments', $socket); } + + public function asArrayProvider() { + return Array( + Array(Array('hello' => 'world'), Array('hello' => 'world')) + , Array(null, null) + , Array(Array('hello' => 'world'), new \ArrayObject(Array('hello' => 'world'))) + ); + } + + /** + * @dataProvider asArrayProvider + */ + public function testMethodMungforselectReturnsExpectedValues($output, $input) { + $method = static::getMethod('mungForSelect'); + $return = $method->invokeArgs($this->_socket, Array($input)); + + $this->assertEquals($return, $output); + } + + public function testMethodMungforselectRejectsNonTraversable() { + $this->setExpectedException('\\InvalidArgumentException'); + $method = static::getMethod('mungForSelect'); + $method->invokeArgs($this->_socket, Array('I am upset with PHP ATM')); + } } \ No newline at end of file