Code cleanup, return value fix, comments
This commit is contained in:
parent
d603870d7f
commit
899dd3b7e4
@ -221,19 +221,33 @@ class WebSocketConnection implements WebSocketInterface
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see writeBinary() to write binary frames as opposed to text frames.
|
||||
*/
|
||||
public function write($data)
|
||||
{
|
||||
return $this->send(self::OP_FRAME_TEXT, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write binary frames.
|
||||
*
|
||||
* @param string $data
|
||||
* @return bool
|
||||
*/
|
||||
public function writeBinary($data)
|
||||
{
|
||||
return $this->send(self::OP_FRAME_BINARY, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode and send a frame.
|
||||
*
|
||||
* @param int $opcode
|
||||
* @param string $data
|
||||
* @param bool $final
|
||||
* @param bool $masked
|
||||
* @return bool
|
||||
*/
|
||||
public function send(int $opcode, string $data, bool $final = true, bool $masked = false)
|
||||
{
|
||||
@ -245,9 +259,7 @@ class WebSocketConnection implements WebSocketInterface
|
||||
'masked' => $masked
|
||||
]);
|
||||
|
||||
$this->outStream->write($frame);
|
||||
|
||||
return true;
|
||||
return $this->outStream->write($frame);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -261,7 +273,10 @@ class WebSocketConnection implements WebSocketInterface
|
||||
$this->emit('close', []);
|
||||
}
|
||||
|
||||
public function closeWithReason(string $reason, int $code=1000)
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function closeWithReason(string $reason, int $code=1000): void
|
||||
{
|
||||
$payload = chr(($code >> 8) & 0xFF) . chr($code & 0xFF) . $reason;
|
||||
$this->send(self::OP_CLOSE, $payload);
|
||||
|
@ -16,15 +16,46 @@ interface WebSocketInterface extends ConnectionInterface
|
||||
const EVENT_GROUP_JOIN = 'join';
|
||||
const EVENT_GROUP_LEAVE = 'leave';
|
||||
|
||||
/**
|
||||
* Close the connection with a reason and code.
|
||||
*
|
||||
* @param string $reason
|
||||
* @param int $code
|
||||
* @return void
|
||||
*/
|
||||
public function closeWithReason(string $reason, int $code=1000): void;
|
||||
|
||||
public function setGroup(?string $name): void;
|
||||
|
||||
public function getGroupName(): ?string;
|
||||
|
||||
public function getGroup(): ?ConnectionGroup;
|
||||
|
||||
public function closeWithReason(string $reason, int $code=1000);
|
||||
|
||||
/**
|
||||
* Get the initial HTTP request sent to the server.
|
||||
*
|
||||
* @return ServerRequestInterface
|
||||
*/
|
||||
public function getServerRequest(): ServerRequestInterface;
|
||||
|
||||
}
|
||||
/**
|
||||
* Assign this connection to a connection group. If the connection is already
|
||||
* part of a group, it will leave the current group before joining the new
|
||||
* group.
|
||||
*
|
||||
* @param null|string $name The group name to join
|
||||
* @return void
|
||||
*/
|
||||
public function setGroup(?string $name): void;
|
||||
|
||||
/**
|
||||
* Get the current connection group.
|
||||
*
|
||||
* @see getGroupName() if you want the name of the group.
|
||||
*
|
||||
* @return null|ConnectionGroup
|
||||
*/
|
||||
public function getGroup(): ?ConnectionGroup;
|
||||
|
||||
/**
|
||||
* Get the name of the current connection group
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function getGroupName(): ?string;
|
||||
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ class WebSocketMiddleware implements EventEmitterInterface
|
||||
|
||||
const MAGIC = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
|
||||
|
||||
const VERSION = 13;
|
||||
|
||||
use EventEmitterTrait;
|
||||
|
||||
private GroupManager $groupManager;
|
||||
@ -32,7 +34,7 @@ class WebSocketMiddleware implements EventEmitterInterface
|
||||
|
||||
public function addRoute(string $path, callable $handler, array $allowedOrigins=[]): void
|
||||
{
|
||||
|
||||
// TODO implement or remove
|
||||
}
|
||||
|
||||
public function __invoke(ServerRequestInterface $request, callable $next)
|
||||
@ -62,12 +64,14 @@ class WebSocketMiddleware implements EventEmitterInterface
|
||||
$this->emit(self::EVENT_CONNECTION, [ $websocket ]);
|
||||
//});
|
||||
|
||||
// TODO would it be possible or rather useful for the 'connection' event to set additional response headers to be sent here?
|
||||
return new Response(
|
||||
Response::STATUS_SWITCHING_PROTOCOLS,
|
||||
array(
|
||||
'Upgrade' => 'websocket',
|
||||
'Connection' => 'upgrade',
|
||||
'Sec-WebSocket-Accept' => $handshakeResponse
|
||||
'Sec-WebSocket-Accept' => $handshakeResponse,
|
||||
'Sec-WebSocket-Version' => self::VERSION
|
||||
),
|
||||
$stream
|
||||
);
|
||||
|
@ -125,6 +125,7 @@ class WebSocketProtocol
|
||||
$byte0 = ord($frame[0]);
|
||||
$decoded['final'] = !!($byte0 & 0x80);
|
||||
$decoded['opcode'] = $byte0 & 0x0F;
|
||||
|
||||
// Peek at the second byte, holding mask bit and len
|
||||
$byte1 = ord($frame[1]);
|
||||
$decoded['masked'] = $masked = !!($byte1 & 0x80);
|
||||
@ -146,14 +147,16 @@ class WebSocketProtocol
|
||||
$header += 4;
|
||||
}
|
||||
|
||||
// Now for the masking
|
||||
// Now for the masking, if present.
|
||||
if ($masked) {
|
||||
$mask = substr($frame, $header, 4);
|
||||
$header += 4;
|
||||
}
|
||||
|
||||
// Extract and unmask payload
|
||||
// Extract the payload, and unmask it if needed. The mask() function handles
|
||||
// both masking and unmasing as the algorithm uses xor.
|
||||
$payload = substr($frame, $header, $len);
|
||||
// TODO check that extracted payload len equals expected len
|
||||
if ($masked) {
|
||||
$payload = $this->mask($payload, $mask);
|
||||
$decoded['mask'] = $mask;
|
||||
@ -174,14 +177,17 @@ class WebSocketProtocol
|
||||
*/
|
||||
private function mask(string $payload, string $mask): string
|
||||
{
|
||||
// Unpack the payload and mask into byte values
|
||||
$payloadData = array_map("ord", str_split($payload,1));
|
||||
$maskData = array_map("ord", str_split($mask,1));
|
||||
// TODO check that mask len==4
|
||||
|
||||
$unmasked = [];
|
||||
for ($n = 0; $n < count($payloadData); $n++) {
|
||||
$unmasked[] = $payloadData[$n] ^ $maskData[$n % 4];
|
||||
}
|
||||
|
||||
// Return the masked byte values packed into a string
|
||||
return join("", array_map("chr", $unmasked));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user