| 3 |
liveuser |
1 |
<?php
|
|
|
2 |
|
|
|
3 |
use GuzzleHttp\Psr7\Response;
|
|
|
4 |
use Ratchet\RFC6455\Handshake\PermessageDeflateOptions;
|
|
|
5 |
use Ratchet\RFC6455\Messaging\MessageBuffer;
|
|
|
6 |
use Ratchet\RFC6455\Messaging\MessageInterface;
|
|
|
7 |
use Ratchet\RFC6455\Messaging\FrameInterface;
|
|
|
8 |
use Ratchet\RFC6455\Messaging\Frame;
|
|
|
9 |
|
|
|
10 |
require_once __DIR__ . "/../bootstrap.php";
|
|
|
11 |
|
|
|
12 |
$loop = \React\EventLoop\Factory::create();
|
|
|
13 |
|
|
|
14 |
$socket = new \React\Socket\Server('0.0.0.0:9001', $loop);
|
|
|
15 |
|
|
|
16 |
$closeFrameChecker = new \Ratchet\RFC6455\Messaging\CloseFrameChecker;
|
|
|
17 |
$negotiator = new \Ratchet\RFC6455\Handshake\ServerNegotiator(new \Ratchet\RFC6455\Handshake\RequestVerifier, PermessageDeflateOptions::permessageDeflateSupported());
|
|
|
18 |
|
|
|
19 |
$uException = new \UnderflowException;
|
|
|
20 |
|
|
|
21 |
|
|
|
22 |
$socket->on('connection', function (React\Socket\ConnectionInterface $connection) use ($negotiator, $closeFrameChecker, $uException, $socket) {
|
|
|
23 |
$headerComplete = false;
|
|
|
24 |
$buffer = '';
|
|
|
25 |
$parser = null;
|
|
|
26 |
$connection->on('data', function ($data) use ($connection, &$parser, &$headerComplete, &$buffer, $negotiator, $closeFrameChecker, $uException, $socket) {
|
|
|
27 |
if ($headerComplete) {
|
|
|
28 |
$parser->onData($data);
|
|
|
29 |
return;
|
|
|
30 |
}
|
|
|
31 |
|
|
|
32 |
$buffer .= $data;
|
|
|
33 |
$parts = explode("\r\n\r\n", $buffer);
|
|
|
34 |
if (count($parts) < 2) {
|
|
|
35 |
return;
|
|
|
36 |
}
|
|
|
37 |
$headerComplete = true;
|
|
|
38 |
$psrRequest = \GuzzleHttp\Psr7\parse_request($parts[0] . "\r\n\r\n");
|
|
|
39 |
$negotiatorResponse = $negotiator->handshake($psrRequest);
|
|
|
40 |
|
|
|
41 |
$negotiatorResponse = $negotiatorResponse->withAddedHeader("Content-Length", "0");
|
|
|
42 |
|
|
|
43 |
if ($negotiatorResponse->getStatusCode() !== 101 && $psrRequest->getUri()->getPath() === '/shutdown') {
|
|
|
44 |
$connection->end(\GuzzleHttp\Psr7\str(new Response(200, [], 'Shutting down echo server.' . PHP_EOL)));
|
|
|
45 |
$socket->close();
|
|
|
46 |
return;
|
|
|
47 |
};
|
|
|
48 |
|
|
|
49 |
$connection->write(\GuzzleHttp\Psr7\str($negotiatorResponse));
|
|
|
50 |
|
|
|
51 |
if ($negotiatorResponse->getStatusCode() !== 101) {
|
|
|
52 |
$connection->end();
|
|
|
53 |
return;
|
|
|
54 |
}
|
|
|
55 |
|
|
|
56 |
// there is no need to look through the client requests
|
|
|
57 |
// we support any valid permessage deflate
|
|
|
58 |
$deflateOptions = PermessageDeflateOptions::fromRequestOrResponse($psrRequest)[0];
|
|
|
59 |
|
|
|
60 |
$parser = new \Ratchet\RFC6455\Messaging\MessageBuffer($closeFrameChecker,
|
|
|
61 |
function (MessageInterface $message, MessageBuffer $messageBuffer) {
|
|
|
62 |
$messageBuffer->sendMessage($message->getPayload(), true, $message->isBinary());
|
|
|
63 |
}, function (FrameInterface $frame) use ($connection, &$parser) {
|
|
|
64 |
switch ($frame->getOpCode()) {
|
|
|
65 |
case Frame::OP_CLOSE:
|
|
|
66 |
$connection->end($frame->getContents());
|
|
|
67 |
break;
|
|
|
68 |
case Frame::OP_PING:
|
|
|
69 |
$connection->write($parser->newFrame($frame->getPayload(), true, Frame::OP_PONG)->getContents());
|
|
|
70 |
break;
|
|
|
71 |
}
|
|
|
72 |
}, true, function () use ($uException) {
|
|
|
73 |
return $uException;
|
|
|
74 |
},
|
|
|
75 |
null,
|
|
|
76 |
null,
|
|
|
77 |
[$connection, 'write'],
|
|
|
78 |
$deflateOptions);
|
|
|
79 |
|
|
|
80 |
array_shift($parts);
|
|
|
81 |
$parser->onData(implode("\r\n\r\n", $parts));
|
|
|
82 |
});
|
|
|
83 |
});
|
|
|
84 |
|
|
|
85 |
$loop->run();
|