Initial commit
This commit is contained in:
91
src/WebSocketMiddleware.php
Normal file
91
src/WebSocketMiddleware.php
Normal file
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace NoccyLabs\React\WebSocket;
|
||||
|
||||
use Evenement\EventEmitterInterface;
|
||||
use Evenement\EventEmitterTrait;
|
||||
use NoccyLabs\React\WebSocket\Group\GroupManager;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use React\EventLoop\Loop;
|
||||
use React\Http\Message\Response;
|
||||
use React\Stream\CompositeStream;
|
||||
use React\Stream\ThroughStream;
|
||||
use SplObjectStorage;
|
||||
|
||||
class WebSocketMiddleware implements EventEmitterInterface
|
||||
{
|
||||
const MAGIC = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
|
||||
|
||||
use EventEmitterTrait;
|
||||
|
||||
private GroupManager $groupManager;
|
||||
|
||||
private SplObjectStorage $websockets;
|
||||
|
||||
public function __construct(?GroupManager $groupManager = null)
|
||||
{
|
||||
$this->groupManager = $groupManager ?? new GroupManager();
|
||||
$this->websockets = new SplObjectStorage();
|
||||
}
|
||||
|
||||
public function addRoute(string $path, callable $handler, array $allowedOrigins=[]): void
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function __invoke(ServerRequestInterface $request, callable $next)
|
||||
{
|
||||
if ($request->getHeaderLine('upgrade') !== 'websocket') {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
$handshakeKey = trim($request->getHeaderLine('sec-websocket-key'));
|
||||
$handshakeResponse = base64_encode(sha1($handshakeKey.self::MAGIC,true));
|
||||
|
||||
// Create the streams we need to pass the websocket data back and forth.
|
||||
// This is returned with the response, and passed to the WebSocketConnection.
|
||||
$inStream = new ThroughStream();
|
||||
$outStream = new ThroughStream();
|
||||
$stream = new CompositeStream($outStream, $inStream);
|
||||
|
||||
$websocket = new WebSocketConnection($request, $inStream, $outStream, $this->groupManager);
|
||||
$this->websockets->attach($websocket);
|
||||
$websocket->on('close', function () use ($websocket) {
|
||||
$this->websockets->detach($websocket);
|
||||
});
|
||||
|
||||
Loop::futureTick(function () use ($websocket) {
|
||||
$this->emit('connect', [ $websocket ]);
|
||||
});
|
||||
|
||||
return new Response(
|
||||
Response::STATUS_SWITCHING_PROTOCOLS,
|
||||
array(
|
||||
'Upgrade' => 'websocket',
|
||||
'Connection' => 'upgrade',
|
||||
'Sec-WebSocket-Accept' => $handshakeResponse
|
||||
),
|
||||
$stream
|
||||
);
|
||||
}
|
||||
|
||||
// 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));
|
||||
// }
|
||||
// }
|
||||
}
|
Reference in New Issue
Block a user