Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
560e5f7881 | |||
6f45622b09 | |||
2cf95fcc85 |
5
doc/ObjectUserdata.md
Normal file
5
doc/ObjectUserdata.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Object UserData
|
||||||
|
|
||||||
|
There is no support for userdata on `WebSocketInterface`, `WebSocketConnection` or `ConnectionGroup`.
|
||||||
|
|
||||||
|
The rationale for this is that the connections can be easily managed using `SplObjectStorage` to link to a data object. Similarly, for groups, the names should be unique and can be used for lookups.
|
@ -1,28 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace NoccyLabs\React\WebSocket\Debug;
|
|
||||||
|
|
||||||
trait HexDumpTrait
|
|
||||||
{
|
|
||||||
|
|
||||||
private function hexdump($data): void
|
|
||||||
{
|
|
||||||
printf("_____ *%4d\n", strlen($data));
|
|
||||||
$rows = str_split($data, 16);
|
|
||||||
$offs = 0;
|
|
||||||
foreach ($rows as $row) {
|
|
||||||
$h = []; $a = [];
|
|
||||||
for ($n = 0; $n < 16; $n++) {
|
|
||||||
if ($n < strlen($row)) {
|
|
||||||
$h[] = sprintf("%02x%s", ord($row[$n]), ($n==7)?" ":" ");
|
|
||||||
$a[] = sprintf("%s%s", (ctype_print($row[$n])?$row[$n]:"."), ($n==7)?" ":"");
|
|
||||||
} else {
|
|
||||||
$h[] = (($n==7)?" ":" ");
|
|
||||||
$a[] = (($n==7)?" ":" ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("%04x | %s | %s\n", 16 * $offs++, join("", $h), join("", $a));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -18,6 +18,7 @@ class WebSocketConnection implements WebSocketInterface
|
|||||||
{
|
{
|
||||||
use EventEmitterTrait;
|
use EventEmitterTrait;
|
||||||
|
|
||||||
|
// TODO maybe move constants to WebSocketProtocol?
|
||||||
const OP_CONTINUATION = 0x0;
|
const OP_CONTINUATION = 0x0;
|
||||||
const OP_FRAME_TEXT = 0x1;
|
const OP_FRAME_TEXT = 0x1;
|
||||||
const OP_FRAME_BINARY = 0x2;
|
const OP_FRAME_BINARY = 0x2;
|
||||||
@ -58,10 +59,7 @@ class WebSocketConnection implements WebSocketInterface
|
|||||||
$this->groupManager = $groupManager;
|
$this->groupManager = $groupManager;
|
||||||
|
|
||||||
$this->inStream->on('data', $this->onWebSocketData(...));
|
$this->inStream->on('data', $this->onWebSocketData(...));
|
||||||
$this->inStream->on('close', function () {
|
$this->inStream->on('close', $this->close(...));
|
||||||
$this->close();
|
|
||||||
$this->emit('close', []);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function onWebSocketData($data)
|
private function onWebSocketData($data)
|
||||||
@ -79,15 +77,15 @@ class WebSocketConnection implements WebSocketInterface
|
|||||||
} else {
|
} else {
|
||||||
$this->buffer .= $payload;
|
$this->buffer .= $payload;
|
||||||
}
|
}
|
||||||
|
// Break out to avoid processing partial messages
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($final) {
|
if ($this->bufferedOp !== null) {
|
||||||
$payload = $this->buffer . $payload;
|
$payload = $this->buffer . $payload;
|
||||||
$this->buffer = null;
|
$this->buffer = null;
|
||||||
if ($this->bufferedOp !== null) {
|
$opcode = $this->bufferedOp;
|
||||||
$opcode = $this->bufferedOp;
|
$this->bufferedOp = null;
|
||||||
$this->bufferedOp = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($opcode) {
|
switch ($opcode) {
|
||||||
@ -165,6 +163,11 @@ class WebSocketConnection implements WebSocketInterface
|
|||||||
return $this->group;
|
return $this->group;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getServerRequest(): ServerRequestInterface
|
||||||
|
{
|
||||||
|
return $this->request;
|
||||||
|
}
|
||||||
|
|
||||||
public function getRemoteAddress()
|
public function getRemoteAddress()
|
||||||
{
|
{
|
||||||
return $this->request->getServerParams()['REMOTE_ADDR'];
|
return $this->request->getServerParams()['REMOTE_ADDR'];
|
||||||
@ -252,15 +255,14 @@ class WebSocketConnection implements WebSocketInterface
|
|||||||
*/
|
*/
|
||||||
public function close()
|
public function close()
|
||||||
{
|
{
|
||||||
// TODO send close
|
|
||||||
$this->outStream->close();
|
$this->outStream->close();
|
||||||
$this->inStream->close();
|
$this->inStream->close();
|
||||||
// TODO emit close event
|
|
||||||
|
$this->emit('close', []);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function closeWithReason(string $reason, int $code=1000)
|
public function closeWithReason(string $reason, int $code=1000)
|
||||||
{
|
{
|
||||||
// TODO send close
|
|
||||||
$payload = chr(($code >> 8) & 0xFF) . chr($code & 0xFF) . $reason;
|
$payload = chr(($code >> 8) & 0xFF) . chr($code & 0xFF) . $reason;
|
||||||
$this->send(self::OP_CLOSE, $payload);
|
$this->send(self::OP_CLOSE, $payload);
|
||||||
}
|
}
|
||||||
@ -270,7 +272,7 @@ class WebSocketConnection implements WebSocketInterface
|
|||||||
*/
|
*/
|
||||||
public function end($data = null)
|
public function end($data = null)
|
||||||
{
|
{
|
||||||
|
// TODO implement me
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -25,4 +25,6 @@ interface WebSocketInterface extends ConnectionInterface
|
|||||||
|
|
||||||
public function closeWithReason(string $reason, int $code=1000);
|
public function closeWithReason(string $reason, int $code=1000);
|
||||||
|
|
||||||
|
public function getServerRequest(): ServerRequestInterface;
|
||||||
|
|
||||||
}
|
}
|
@ -3,11 +3,14 @@
|
|||||||
namespace NoccyLabs\React\WebSocket\Group;
|
namespace NoccyLabs\React\WebSocket\Group;
|
||||||
|
|
||||||
use NoccyLabs\React\WebSocket\WebSocketConnection;
|
use NoccyLabs\React\WebSocket\WebSocketConnection;
|
||||||
|
use NoccyLabs\React\WebSocket\WebSocketProtocol;
|
||||||
use PHPUnit\Framework\Attributes\CoversClass;
|
use PHPUnit\Framework\Attributes\CoversClass;
|
||||||
use React\Http\Message\ServerRequest;
|
use React\Http\Message\ServerRequest;
|
||||||
use React\Stream\ThroughStream;
|
use React\Stream\ThroughStream;
|
||||||
|
|
||||||
#[CoversClass(ConnectionGroup::class)]
|
#[CoversClass(ConnectionGroup::class)]
|
||||||
|
#[CoversClass(WebSocketConnection::class)]
|
||||||
|
#[CoversClass(WebSocketProtocol::class)]
|
||||||
class ConnectionGroupTest extends \PHPUnit\Framework\TestCase
|
class ConnectionGroupTest extends \PHPUnit\Framework\TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ use PHPUnit\Framework\Attributes\CoversClass;
|
|||||||
use React\Http\Message\ServerRequest;
|
use React\Http\Message\ServerRequest;
|
||||||
|
|
||||||
#[CoversClass(WebSocketMiddleware::class)]
|
#[CoversClass(WebSocketMiddleware::class)]
|
||||||
|
#[CoversClass(WebSocketConnection::class)]
|
||||||
class WebSocketMiddlewareTest extends \PHPUnit\Framework\TestCase
|
class WebSocketMiddlewareTest extends \PHPUnit\Framework\TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user