host = $host; $this->port = $port; $this->loop = $loop; } public function createProxy(ConnectionInterface $clientConnection, $connectionData) { $connector = new Connector($this->loop); $connector->connect("{$this->host}:{$this->port}")->then(function (ConnectionInterface $proxyConnection) use ($clientConnection, $connector, $connectionData) { $proxyConnection->write(json_encode([ 'event' => 'registerProxy', 'data' => [ 'request_id' => $connectionData->request_id ?? null, 'client_id' => $clientConnection->_id, ], ])); $proxyConnection->on('data', function ($data) use (&$proxyData, $proxyConnection, $connector) { if (!isset($proxyConnection->buffer)) { $proxyConnection->buffer = ''; } $proxyConnection->buffer .= $data; if ($this->hasBufferedAllData($proxyConnection)) { $tunnel = app(TunnelConnection::class); $tunnel->performRequest($proxyConnection->buffer, $proxyConnection); } }); }); } private function parseResponse(string $response) { try { return gPsr\parse_response($response); } catch (\Throwable $e) { return null; } } private function parseRequest($data) { return gPsr\parse_request($data); } protected function getContentLength($proxyConnection): ?int { $request = parse_request($proxyConnection->buffer); return Arr::first($request->getHeader('Content-Length')); } protected function hasBufferedAllData($proxyConnection) { return is_null($this->getContentLength($proxyConnection)) || strlen(Str::after($proxyConnection->buffer, "\r\n\r\n")) >= $this->getContentLength($proxyConnection); } }