Subversion Repositories php-qbpwcf

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
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();