Skip to content
This repository was archived by the owner on Aug 25, 2022. It is now read-only.

Commit 4dfc847

Browse files
authored
Merge pull request #152 from SeinopSys/master
Add Socket.IO v2 support
2 parents cf20d57 + f3b71e6 commit 4dfc847

File tree

7 files changed

+93
-12
lines changed

7 files changed

+93
-12
lines changed

‎src/Client.php‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public function initialize($keepAlive = false)
7878
/**
7979
* Reads a message from the socket
8080
*
81-
* @return MessageInterface Message read from the socket
81+
* @return string Message read from the socket
8282
*/
8383
public function read()
8484
{
@@ -89,6 +89,9 @@ public function read()
8989
/**
9090
* Emits a message through the engine
9191
*
92+
* @param string $event
93+
* @param array $args
94+
*
9295
* @return $this
9396
*/
9497
public function emit($event, array $args)

‎src/Engine/AbstractSocketIO.php‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace ElephantIO\Engine;
1313

1414
use DomainException;
15+
use ElephantIO\Engine\SocketIO\Session;
1516
use RuntimeException;
1617

1718
use Psr\Log\LoggerInterface;
@@ -37,7 +38,7 @@ abstract class AbstractSocketIO implements EngineInterface
3738
/** @var array cookies received during handshake */
3839
protected $cookies = [];
3940

40-
/** @var string[] Session information */
41+
/** @var Session Session information */
4142
protected $session;
4243

4344
/** @var mixed[] Array of options for the engine */
@@ -190,6 +191,8 @@ public function getName()
190191
/**
191192
* Parse an url into parts we may expect
192193
*
194+
* @param string $url
195+
*
193196
* @return string[] information on the given URL
194197
*/
195198
protected function parseUrl($url)

‎src/Engine/SocketIO/Session.php‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,12 @@ public function __construct($id, $interval, $timeout, array $upgrades)
4242
'interval' => $interval];
4343
}
4444

45-
/** The property should not be modified, hence the private accessibility on them */
45+
/**
46+
* The property should not be modified, hence the private accessibility on them
47+
*
48+
* @param string $prop
49+
* @return mixed
50+
*/
4651
public function __get($prop)
4752
{
4853
static $list = ['id', 'upgrades'];

‎src/Engine/SocketIO/Version0X.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public function connect()
6868
$this->stream = stream_socket_client($host, $errors[0], $errors[1], $this->options['timeout'], STREAM_CLIENT_CONNECT, stream_context_create($this->context));
6969

7070
if (!is_resource($this->stream)) {
71-
throw new SocketException($error[0], $error[1]);
71+
throw new SocketException($errors[0], $errors[1]);
7272
}
7373

7474
stream_set_timeout($this->stream, $this->options['timeout']);

‎src/Engine/SocketIO/Version1X.php‎

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,9 @@ protected function handshake()
167167
throw new ServerConnectionFailureException;
168168
}
169169

170-
$decoded = json_decode(substr($result, strpos($result, '{')), true);
170+
$open_curly_at = strpos($result, '{');
171+
$todecode = substr($result, $open_curly_at, strrpos($result, '}')-$open_curly_at+1);
172+
$decoded = json_decode($todecode, true);
171173

172174
if (!in_array('websocket', $decoded['upgrades'])) {
173175
throw new UnsupportedTransportException('websocket');
@@ -184,16 +186,27 @@ protected function handshake()
184186
$this->session = new Session($decoded['sid'], $decoded['pingInterval'], $decoded['pingTimeout'], $decoded['upgrades']);
185187
}
186188

187-
/** Upgrades the transport to WebSocket */
188-
private function upgradeTransport()
189+
/**
190+
* Upgrades the transport to WebSocket
191+
*
192+
* FYI:
193+
* Version "2" is used for the EIO param by socket.io v1
194+
* Version "3" is used by socket.io v2
195+
*/
196+
protected function upgradeTransport()
189197
{
190198
$query = ['sid' => $this->session->id,
191199
'EIO' => $this->options['version'],
192-
'use_b64' => $this->options['use_b64'],
193200
'transport' => static::TRANSPORT_WEBSOCKET];
194201

202+
if ($this->options['version'] === 2)
203+
$query['use_b64'] = $this->options['use_b64'];
204+
195205
$url = sprintf('/%s/?%s', trim($this->url['path'], '/'), http_build_query($query));
196-
$key = base64_encode(sha1(uniqid(mt_rand(), true), true));
206+
$hash = sha1(uniqid(mt_rand(), true), true);
207+
if ($this->options['version'] !== 2)
208+
$hash = substr($hash, 0, 16);
209+
$key = base64_encode($hash);
197210

198211
$origin = '*';
199212
$headers = isset($this->context['headers']) ? (array) $this->context['headers'] : [] ;
@@ -208,7 +221,7 @@ private function upgradeTransport()
208221
}
209222

210223
$request = "GET {$url} HTTP/1.1\r\n"
211-
. "Host: {$this->url['host']}\r\n"
224+
. "Host: {$this->url['host']}:{$this->url['port']}\r\n"
212225
. "Upgrade: WebSocket\r\n"
213226
. "Connection: Upgrade\r\n"
214227
. "Sec-WebSocket-Key: {$key}\r\n"
@@ -234,7 +247,8 @@ private function upgradeTransport()
234247
$this->write(EngineInterface::UPGRADE);
235248

236249
//remove message '40' from buffer, emmiting by socket.io after receiving EngineInterface::UPGRADE
237-
$this->read();
250+
if ($this->options['version'] === 2)
251+
$this->read();
238252
}
239253
}
240254

‎src/Engine/SocketIO/Version2X.php‎

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
/**
3+
* This file is part of the Elephant.io package
4+
*
5+
* For the full copyright and license information, please view the LICENSE file
6+
* that was distributed with this source code.
7+
*
8+
* @copyright Wisembly
9+
* @license http://www.opensource.org/licenses/MIT-License MIT License
10+
*/
11+
12+
namespace ElephantIO\Engine\SocketIO;
13+
14+
use DomainException;
15+
use InvalidArgumentException;
16+
use UnexpectedValueException;
17+
18+
use Psr\Log\LoggerInterface;
19+
20+
use ElephantIO\EngineInterface;
21+
use ElephantIO\Payload\Encoder;
22+
use ElephantIO\Engine\AbstractSocketIO;
23+
24+
use ElephantIO\Exception\SocketException;
25+
use ElephantIO\Exception\UnsupportedTransportException;
26+
use ElephantIO\Exception\ServerConnectionFailureException;
27+
28+
/**
29+
* Implements the dialog with Socket.IO version 2.x
30+
*
31+
* Based on the work of Mathieu Lallemand (@lalmat)
32+
*
33+
* @author Baptiste Clavié <baptiste@wisembly.com>
34+
* @link https://tools.ietf.org/html/rfc6455#section-5.2 Websocket's RFC
35+
*/
36+
class Version2X extends Version1X
37+
{
38+
39+
/** {@inheritDoc} */
40+
public function getName()
41+
{
42+
return 'SocketIO Version 2.X';
43+
}
44+
45+
/** {@inheritDoc} */
46+
protected function getDefaultOptions()
47+
{
48+
$defaults = parent::getDefaultOptions();
49+
50+
$defaults['version'] = 3;
51+
52+
return $defaults;
53+
}
54+
}
55+

‎src/Payload/Encoder.php‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,12 @@
2525
class Encoder extends AbstractPayload
2626
{
2727
private $data;
28+
/** @var string */
2829
private $payload;
2930

3031
/**
3132
* @param string $data data to encode
32-
* @param integer $opcode OpCode to use (one of AbstractPayload's constant)
33+
* @param integer $opCode OpCode to use (one of AbstractPayload's constant)
3334
* @param bool $mask Should we use a mask ?
3435
*/
3536
public function __construct($data, $opCode, $mask)

0 commit comments

Comments
 (0)