<?php 
use GuzzleHttp\Psr7\Uri; 
use Ratchet\RFC6455\Handshake\InvalidPermessageDeflateOptionsException; 
use Ratchet\RFC6455\Handshake\PermessageDeflateOptions; 
use Ratchet\RFC6455\Messaging\MessageBuffer; 
use Ratchet\RFC6455\Handshake\ClientNegotiator; 
use Ratchet\RFC6455\Messaging\CloseFrameChecker; 
use Ratchet\RFC6455\Messaging\MessageInterface; 
use React\Promise\Deferred; 
use Ratchet\RFC6455\Messaging\Frame; 
use React\Socket\ConnectionInterface; 
use React\Socket\Connector; 
 
require __DIR__ . '/../bootstrap.php'; 
 
define('AGENT', 'RatchetRFC/0.3'); 
 
$testServer = "127.0.0.1"; 
 
$loop = React\EventLoop\Factory::create(); 
 
$connector = new Connector($loop); 
 
function echoStreamerFactory($conn, $permessageDeflateOptions = null) 
{ 
    $permessageDeflateOptions = $permessageDeflateOptions ?: PermessageDeflateOptions::createDisabled(); 
 
    return new \Ratchet\RFC6455\Messaging\MessageBuffer( 
        new \Ratchet\RFC6455\Messaging\CloseFrameChecker, 
        function (\Ratchet\RFC6455\Messaging\MessageInterface $msg, MessageBuffer $messageBuffer) use ($conn) { 
            $messageBuffer->sendMessage($msg->getPayload(), true, $msg->isBinary()); 
        }, 
        function (\Ratchet\RFC6455\Messaging\FrameInterface $frame, MessageBuffer $messageBuffer) use ($conn) { 
            switch ($frame->getOpcode()) { 
                case Frame::OP_PING: 
                    return $conn->write((new Frame($frame->getPayload(), true, Frame::OP_PONG))->maskPayload()->getContents()); 
                    break; 
                case Frame::OP_CLOSE: 
                    return $conn->end((new Frame($frame->getPayload(), true, Frame::OP_CLOSE))->maskPayload()->getContents()); 
                    break; 
            } 
        }, 
        false, 
        null, 
        null, 
        null, 
        [$conn, 'write'], 
        $permessageDeflateOptions 
    ); 
} 
 
function getTestCases() { 
    global $testServer; 
    global $connector; 
 
    $deferred = new Deferred(); 
 
    $connector->connect($testServer . ':9001')->then(function (ConnectionInterface $connection) use ($deferred) { 
        $cn = new ClientNegotiator(); 
        $cnRequest = $cn->generateRequest(new Uri('ws://127.0.0.1:9001/getCaseCount')); 
 
        $rawResponse = ""; 
        $response = null; 
 
        /** @var MessageBuffer $ms */ 
        $ms = null; 
 
        $connection->on('data', function ($data) use ($connection, &$rawResponse, &$response, &$ms, $cn, $deferred, &$context, $cnRequest) { 
            if ($response === null) { 
                $rawResponse .= $data; 
                $pos = strpos($rawResponse, "\r\n\r\n"); 
                if ($pos) { 
                    $data = substr($rawResponse, $pos + 4); 
                    $rawResponse = substr($rawResponse, 0, $pos + 4); 
                    $response = \GuzzleHttp\Psr7\parse_response($rawResponse); 
 
                    if (!$cn->validateResponse($cnRequest, $response)) { 
                        $connection->end(); 
                        $deferred->reject(); 
                    } else { 
                        $ms = new MessageBuffer( 
                            new CloseFrameChecker, 
                            function (MessageInterface $msg) use ($deferred, $connection) { 
                                $deferred->resolve($msg->getPayload()); 
                                $connection->close(); 
                            }, 
                            null, 
                            false, 
                            null, 
                            null, 
                            null, 
                            function () {} 
                        ); 
                    } 
                } 
            } 
 
            // feed the message streamer 
            if ($ms) { 
                $ms->onData($data); 
            } 
        }); 
 
        $connection->write(\GuzzleHttp\Psr7\str($cnRequest)); 
    }); 
 
    return $deferred->promise(); 
} 
 
$cn = new \Ratchet\RFC6455\Handshake\ClientNegotiator( 
    PermessageDeflateOptions::permessageDeflateSupported() ? PermessageDeflateOptions::createEnabled() : null); 
 
function runTest($case) 
{ 
    global $connector; 
    global $testServer; 
    global $cn; 
 
    $casePath = "/runCase?case={$case}&agent=" . AGENT; 
 
    $deferred = new Deferred(); 
 
    $connector->connect($testServer . ':9001')->then(function (ConnectionInterface $connection) use ($deferred, $casePath, $case) { 
        $cn = new ClientNegotiator( 
            PermessageDeflateOptions::permessageDeflateSupported() ? PermessageDeflateOptions::createEnabled() : null); 
        $cnRequest = $cn->generateRequest(new Uri('ws://127.0.0.1:9001' . $casePath)); 
 
        $rawResponse = ""; 
        $response = null; 
 
        $ms = null; 
 
        $connection->on('data', function ($data) use ($connection, &$rawResponse, &$response, &$ms, $cn, $deferred, &$context, $cnRequest) { 
            if ($response === null) { 
                $rawResponse .= $data; 
                $pos = strpos($rawResponse, "\r\n\r\n"); 
                if ($pos) { 
                    $data = substr($rawResponse, $pos + 4); 
                    $rawResponse = substr($rawResponse, 0, $pos + 4); 
                    $response = \GuzzleHttp\Psr7\parse_response($rawResponse); 
 
                    if (!$cn->validateResponse($cnRequest, $response)) { 
                        echo "Invalid response.\n"; 
                        $connection->end(); 
                        $deferred->reject(); 
                    } else { 
                        try { 
                            $permessageDeflateOptions = PermessageDeflateOptions::fromRequestOrResponse($response)[0]; 
                            $ms = echoStreamerFactory( 
                                $connection, 
                                $permessageDeflateOptions 
                            ); 
                        } catch (InvalidPermessageDeflateOptionsException $e) { 
                            $connection->end(); 
                        } 
                    } 
                } 
            } 
 
            // feed the message streamer 
            if ($ms) { 
                $ms->onData($data); 
            } 
        }); 
 
        $connection->on('close', function () use ($deferred) { 
            $deferred->resolve(); 
        }); 
 
        $connection->write(\GuzzleHttp\Psr7\str($cnRequest)); 
    }); 
 
    return $deferred->promise(); 
} 
 
function createReport() { 
    global $connector; 
    global $testServer; 
 
    $deferred = new Deferred(); 
 
    $connector->connect($testServer . ':9001')->then(function (ConnectionInterface $connection) use ($deferred) { 
        // $reportPath = "/updateReports?agent=" . AGENT . "&shutdownOnComplete=true"; 
        // we will stop it using docker now instead of just shutting down 
        $reportPath = "/updateReports?agent=" . AGENT; 
        $cn = new ClientNegotiator(); 
        $cnRequest = $cn->generateRequest(new Uri('ws://127.0.0.1:9001' . $reportPath)); 
 
        $rawResponse = ""; 
        $response = null; 
 
        /** @var MessageBuffer $ms */ 
        $ms = null; 
 
        $connection->on('data', function ($data) use ($connection, &$rawResponse, &$response, &$ms, $cn, $deferred, &$context, $cnRequest) { 
            if ($response === null) { 
                $rawResponse .= $data; 
                $pos = strpos($rawResponse, "\r\n\r\n"); 
                if ($pos) { 
                    $data = substr($rawResponse, $pos + 4); 
                    $rawResponse = substr($rawResponse, 0, $pos + 4); 
                    $response = \GuzzleHttp\Psr7\parse_response($rawResponse); 
 
                    if (!$cn->validateResponse($cnRequest, $response)) { 
                        $connection->end(); 
                        $deferred->reject(); 
                    } else { 
                        $ms = new MessageBuffer( 
                            new CloseFrameChecker, 
                            function (MessageInterface $msg) use ($deferred, $connection) { 
                                $deferred->resolve($msg->getPayload()); 
                                $connection->close(); 
                            }, 
                            null, 
                            false, 
                            null, 
                            null, 
                            null, 
                            function () {} 
                        ); 
                    } 
                } 
            } 
 
            // feed the message streamer 
            if ($ms) { 
                $ms->onData($data); 
            } 
        }); 
 
        $connection->write(\GuzzleHttp\Psr7\str($cnRequest)); 
    }); 
 
    return $deferred->promise(); 
} 
 
 
$testPromises = []; 
 
getTestCases()->then(function ($count) use ($loop) { 
    $allDeferred = new Deferred(); 
 
    $runNextCase = function () use (&$i, &$runNextCase, $count, $allDeferred) { 
        $i++; 
        if ($i > $count) { 
            $allDeferred->resolve(); 
            return; 
        } 
        echo "Running test $i/$count..."; 
        $startTime = microtime(true); 
        runTest($i) 
            ->then(function () use ($startTime) { 
                echo " completed " . round((microtime(true) - $startTime) * 1000) . " ms\n"; 
            }) 
            ->then($runNextCase); 
    }; 
 
    $i = 0; 
    $runNextCase(); 
 
    $allDeferred->promise()->then(function () { 
        createReport(); 
    }); 
}); 
 
$loop->run(); 
 
 |