Ejemplo n.º 1
0
 /**
  * We have to keep a static reference of eio event streams
  * because if we don't garbage collection can unload eio's
  * underlying pipe via a system close() call before it's
  * finished and generate a SIGPIPE.
  */
 public function __construct()
 {
     if (empty(self::$stream)) {
         \eio_init();
         self::$stream = \eio_get_event_stream();
     }
     $this->callableDecrementor = function () {
         \call_user_func($this->incrementor, -1);
     };
     $this->incrementor = function ($increment) {
         switch ($increment) {
             case 1:
             case -1:
                 $this->pending += $increment;
                 break;
             default:
                 throw new FilesystemException("Invalid pending event increment; 1 or -1 required");
         }
         if ($this->pending === 0) {
             \Amp\disable($this->watcher);
         } elseif ($this->pending === 1) {
             \Amp\enable($this->watcher);
         }
     };
     $this->watcher = \Amp\onReadable(self::$stream, function () {
         while (\eio_npending()) {
             \eio_poll();
         }
     }, $options = ["enable" => false]);
 }
Ejemplo n.º 2
0
 public function __construct($db, $socket, string $connectionString)
 {
     $this->db = $db;
     $this->socket = $socket;
     $this->connectionString = $connectionString;
     $this->readWatcher = \Amp\onReadable($socket, [$this, "onReadable"]);
     $this->writeWatcher = \Amp\onReadable($socket, [$this, "onWritable"], ["enable" => FALSE]);
 }
Ejemplo n.º 3
0
 protected function doStart(Console $console) : \Generator
 {
     $server = $this->bootstrapper->boot($this->logger, $console);
     (yield $server->start());
     $this->server = $server;
     \Amp\onReadable($this->ipcSock, function ($watcherId) {
         \Amp\cancel($watcherId);
         yield from $this->stop();
     });
 }
Ejemplo n.º 4
0
 protected function doStart(Console $console) : \Generator
 {
     // Shutdown the whole server in case we needed to stop during startup
     register_shutdown_function(function () use($console) {
         if (!$this->server) {
             // ensure a clean reactor for clean shutdown
             $reactor = \Amp\reactor();
             \Amp\reactor(\Amp\driver());
             \Amp\wait((new CommandClient((string) $console->getArg("config")))->stop());
             \Amp\reactor($reactor);
         }
     });
     $server = (yield from $this->bootstrapper->boot($this->logger, $console));
     (yield $server->start());
     $this->server = $server;
     \Amp\onReadable($this->ipcSock, function ($watcherId) {
         \Amp\cancel($watcherId);
         yield from $this->stop();
     });
 }
Ejemplo n.º 5
0
 public function __construct()
 {
     if (empty(self::$isEioInitialized)) {
         \eio_init();
         self::$isEioInitialized = true;
     }
     $this->stream = \eio_get_event_stream();
     $this->callableDelReq = function () {
         $this->decrementPending();
     };
     $this->internalIncrement = function () {
         $this->incrementPending();
     };
     $this->internalDecrement = function () {
         $this->decrementPending();
     };
     $this->watcher = \Amp\onReadable($this->stream, function () {
         while (\eio_npending()) {
             \eio_poll();
         }
     }, $options = ["enable" => false]);
 }
Ejemplo n.º 6
0
 private function doWrite(HttpTunnelStruct $struct)
 {
     $socket = $struct->socket;
     $bytesToWrite = strlen($struct->writeBuffer);
     $bytesWritten = @fwrite($socket, $struct->writeBuffer);
     if ($bytesToWrite === $bytesWritten) {
         \Amp\cancel($struct->writeWatcher);
         $struct->parser = new Parser(Parser::MODE_RESPONSE);
         $struct->parser->enqueueResponseMethodMatch('CONNECT');
         $struct->readWatcher = \Amp\onReadable($socket, function () use($struct) {
             $this->doRead($struct);
         });
     } elseif ($bytesWritten > 0) {
         $struct->writeBuffer = substr($struct->writeBuffer, 0, $bytesWritten);
         $this->enableWriteWatcher($struct);
     } elseif ($this->isSocketDead($socket)) {
         \Amp\cancel($struct->writeWatcher);
         $struct->promisor->fail(new SocketException('Proxy CONNECT failed: socket went away while writing tunneling request'));
     } else {
         $this->enableWriteWatcher($struct);
     }
 }
Ejemplo n.º 7
0
 private function accept($watcherId, $ipcServer)
 {
     if (!($ipcClient = @stream_socket_accept($ipcServer, $timeout = 0))) {
         return;
     }
     if ($this->stopPromisor) {
         @\fwrite($ipcClient, "\n");
     }
     stream_set_blocking($ipcClient, false);
     $parser = $this->parser($ipcClient);
     $readWatcherId = \Amp\onReadable($ipcClient, function () use($parser) {
         $parser->next();
     });
     $this->ipcClients[$readWatcherId] = $ipcClient;
     $parser->send($readWatcherId);
     assert(!empty($this->spawnPromisors));
     array_shift($this->spawnPromisors)->succeed();
 }
Ejemplo n.º 8
0
 public function reapClient($watcherId, InternalRequest $ireq)
 {
     $client = new Rfc6455Client();
     $client->connectedAt = $this->now;
     $socket = $ireq->client->socket;
     $client->id = (int) $socket;
     $client->socket = $socket;
     $client->writeBuffer = $ireq->client->writeBuffer;
     $client->serverRefClearer = ($ireq->client->exporter)($ireq->client);
     $client->parser = $this->parser([$this, "onParse"], $options = ["cb_data" => $client]);
     $client->readWatcher = \Amp\onReadable($socket, [$this, "onReadable"], $options = ["enable" => true, "cb_data" => $client]);
     $client->writeWatcher = \Amp\onWritable($socket, [$this, "onWritable"], $options = ["enable" => $client->writeBuffer != "", "cb_data" => $client]);
     $this->clients[$client->id] = $client;
     $this->heartbeatTimeouts[$client->id] = $this->now + $this->heartbeatPeriod;
     resolve($this->tryAppOnOpen($client->id, $ireq->locals["aerys.websocket"]));
     return $client;
 }
Ejemplo n.º 9
0
 public function do(InternalRequest $ireq)
 {
     $headers = yield;
     if ($headers[":status"] == 101) {
         $yield = (yield $headers);
     } else {
         return $headers;
         // detach if we don't want to establish websocket connection
     }
     while ($yield !== null) {
         $yield = (yield $yield);
     }
     \Amp\immediately(function () use($ireq) {
         $client = new Rfc6455Client();
         $client->connectedAt = $this->now;
         $socket = $ireq->client->socket;
         $client->id = (int) $socket;
         $client->socket = $socket;
         $client->writeBuffer = $ireq->client->writeBuffer;
         $client->serverRefClearer = ($ireq->client->exporter)($ireq->client);
         $client->parser = $this->parser([$this, "onParse"], $options = ["cb_data" => $client]);
         $client->readWatcher = \Amp\onReadable($socket, [$this, "onReadable"], $options = ["enable" => true, "cb_data" => $client]);
         $client->writeWatcher = \Amp\onWritable($socket, [$this, "onWritable"], $options = ["enable" => $client->writeBuffer != "", "cb_data" => $client]);
         $this->clients[$client->id] = $client;
         $this->heartbeatTimeouts[$client->id] = $this->now + $this->heartbeatPeriod;
         resolve($this->tryAppOnOpen($client->id, $ireq->locals["aerys.websocket"]));
     });
 }
Ejemplo n.º 10
0
 private function accept($watcherId, $ipcServer)
 {
     if (!($ipcClient = @stream_socket_accept($ipcServer, $timeout = 0))) {
         return;
     }
     $clientId = (int) $ipcClient;
     $this->ipcClients[$clientId] = $ipcClient;
     stream_set_blocking($ipcClient, false);
     $parser = $this->parser($ipcClient);
     $onReadable = function () use($parser) {
         $parser->next();
     };
     $readWatcherId = \Amp\onReadable($ipcClient, $onReadable);
     $parser->send($readWatcherId);
 }
Ejemplo n.º 11
0
function __watchCrypto($method, $socket)
{
    $result = \stream_socket_enable_crypto($socket, $enable = true, $method);
    if ($result === true) {
        return new Success($socket);
    } elseif ($result === false) {
        return new Failure(new CryptoException("Crypto negotiation failed: " . \error_get_last()["message"]));
    } else {
        $promisor = new \Amp\Deferred();
        $cbData = [$promisor, $method];
        \Amp\onReadable($socket, '\\Amp\\Socket\\__onCryptoWatchReadability', $options = ["cb_data" => $cbData]);
        return $promisor->promise();
    }
}
Ejemplo n.º 12
0
 private function importClient($socket, string $peerName, HttpDriver $http)
 {
     $client = new Client();
     $client->id = (int) $socket;
     $client->socket = $socket;
     $client->httpDriver = $http;
     $client->exporter = $this->exporter;
     $client->remainingKeepAlives = $this->options->maxKeepAliveRequests ?: null;
     $portStartPos = strrpos($peerName, ":");
     $client->clientAddr = substr($peerName, 0, $portStartPos);
     $client->clientPort = substr($peerName, $portStartPos + 1);
     $serverName = stream_socket_get_name($socket, false);
     $portStartPos = strrpos($serverName, ":");
     $client->serverAddr = substr($serverName, 0, $portStartPos);
     $client->serverPort = substr($serverName, $portStartPos + 1);
     $meta = stream_get_meta_data($socket);
     $client->cryptoInfo = $meta["crypto"] ?? [];
     $client->isEncrypted = (bool) $client->cryptoInfo;
     $client->requestParser = $http->parser($client);
     $client->requestParser->send("");
     $client->readWatcher = \Amp\onReadable($socket, $this->onReadable, $options = ["enable" => true, "cb_data" => $client]);
     $client->writeWatcher = \Amp\onWritable($socket, $this->onWritable, $options = ["enable" => false, "cb_data" => $client]);
     $this->renewKeepAliveTimeout($client);
     $this->clients[$client->id] = $client;
 }
Ejemplo n.º 13
0
 private function onCryptoCompletion(RequestCycle $cycle)
 {
     $parser = new Parser(Parser::MODE_RESPONSE);
     $parser->enqueueResponseMethodMatch($cycle->request->getMethod());
     $futureResponse = $cycle->futureResponse;
     $parser->setAllOptions([Parser::OP_DISCARD_BODY => $cycle->options[self::OP_DISCARD_BODY], Parser::OP_BODY_SWAP_SIZE => $cycle->options[self::OP_BODY_SWAP_SIZE], Parser::OP_MAX_HEADER_BYTES => $cycle->options[self::OP_MAX_HEADER_BYTES], Parser::OP_MAX_BODY_BYTES => $cycle->options[self::OP_MAX_BODY_BYTES], Parser::OP_RETURN_BEFORE_ENTITY => true, Parser::OP_BODY_DATA_CALLBACK => function ($data) use($futureResponse) {
         $futureResponse->update([Notify::RESPONSE_BODY_DATA, $data]);
     }]);
     $cycle->parser = $parser;
     $cycle->readWatcher = \Amp\onReadable($cycle->socket, function () use($cycle) {
         $this->onReadableSocket($cycle);
     });
     $timeout = $cycle->options[self::OP_MS_TRANSFER_TIMEOUT];
     if ($timeout > 0) {
         $cycle->transferTimeoutWatcher = \Amp\once(function () use($cycle, $timeout) {
             $this->fail($cycle, new TimeoutException(sprintf('Allowed transfer timeout exceeded: %d ms', $timeout)));
         }, $timeout);
     }
     $streamMeta = stream_get_meta_data($cycle->socket);
     $cycle->futureResponse->update([Notify::HANDSHAKE_COMPLETE, $streamMeta]);
     $this->writeRequest($cycle);
 }
Ejemplo n.º 14
0
 /**
  * @param int $buffer one of the self::BUFFER_* constants. Determines whether it will buffer the stdout and/or stderr data internally
  * @return Promise is updated with ["out", $data] or ["err", $data] for data received on stdout or stderr
  * That Promise will be resolved to a stdClass object with stdout, stderr (when $buffer is true), exit (holding exit code) and signal (only present when terminated via signal) properties
  */
 public function exec($buffer = self::BUFFER_NONE)
 {
     if ($this->proc) {
         throw new \RuntimeException("Process was already launched");
     }
     $fds = [["pipe", "r"], ["pipe", "w"], ["pipe", "w"]];
     $cwd = isset($this->options["cwd"]) ? $this->options["cwd"] : NULL;
     $env = isset($this->options["env"]) ? $this->options["env"] : NULL;
     if (!($this->proc = @proc_open($this->cmd, $fds, $pipes, $cwd, $env, $this->options))) {
         return new Failure(new \RuntimeException("Failed executing command: {$this->cmd}"));
     }
     $this->writeBuf = "";
     $this->writeTotal = 0;
     $this->writeCur = 0;
     stream_set_blocking($pipes[0], false);
     stream_set_blocking($pipes[1], false);
     stream_set_blocking($pipes[2], false);
     $this->deferred = new Deferred();
     $result = new \stdClass();
     if ($buffer & self::BUFFER_STDOUT) {
         $result->stdout = "";
     }
     if ($buffer & self::BUFFER_STDERR) {
         $result->stderr = "";
     }
     $this->stdout = \Amp\onReadable($pipes[1], function ($watcher, $sock) use($result) {
         if ("" == ($data = @fread($sock, 8192))) {
             \Amp\cancel($watcher);
             \Amp\cancel($this->stdin);
             \Amp\immediately(function () use($result) {
                 $status = proc_get_status($this->proc);
                 assert($status["running"] === false);
                 if ($status["signaled"]) {
                     $result->signal = $status["termsig"];
                 }
                 $result->exit = $status["exitcode"];
                 $this->proc = NULL;
                 $this->deferred->succeed($result);
                 foreach ($this->writeDeferreds as $deferred) {
                     $deferred->fail(new \Exception("Write could not be completed, process finished"));
                 }
                 $this->writeDeferreds = [];
             });
         } else {
             isset($result->stdout) && ($result->stdout .= $data);
             $this->deferred->update(["out", $data]);
         }
     });
     $this->stderr = \Amp\onReadable($pipes[2], function ($watcher, $sock) use($result) {
         if ("" == ($data = @fread($sock, 8192))) {
             \Amp\cancel($watcher);
         } else {
             isset($result->stderr) && ($result->stderr .= $data);
             $this->deferred->update(["err", $data]);
         }
     });
     $this->stdin = \Amp\onWritable($pipes[0], function ($watcher, $sock) {
         $this->writeCur += @fwrite($sock, $this->writeBuf);
         if ($this->writeCur == $this->writeTotal) {
             \Amp\disable($watcher);
         }
         while (($next = key($this->writeDeferreds)) !== null && $next <= $this->writeCur) {
             $this->writeDeferreds[$next]->succeed($this->writeCur);
             unset($this->writeDeferreds[$next]);
         }
     }, ["enable" => false]);
     return $this->deferred->promise();
 }
Ejemplo n.º 15
0
 public function reapClient($watcherId, InternalRequest $ireq)
 {
     $client = $ireq->client->socket;
     list($reverse, $externBuf) = $ireq->locals["aerys.reverse.socket"];
     $serverRefClearer = ($ireq->client->exporter)($ireq->client)();
     $internBuf = "";
     $clientWrite = \Amp\onWritable($client, [self::class, "writer"], ["cb_data" => [&$externBuf, &$reverseRead, &$extern], "enable" => false, "keep_alive" => false]);
     $reverseWrite = \Amp\onWritable($reverse, [self::class, "writer"], ["cb_data" => [&$internBuf, &$clientRead, &$intern], "enable" => false, "keep_alive" => false]);
     $clientRead = \Amp\onReadable($client, [self::class, "reader"], ["cb_data" => [&$internBuf, $reverseWrite, &$intern], "keep_alive" => false]);
     $reverseRead = \Amp\onReadable($reverse, [self::class, "reader"], ["cb_data" => [&$externBuf, $clientWrite, &$intern], "keep_alive" => false]);
 }
Ejemplo n.º 16
0
 public function reapClient($watcherId, InternalRequest $ireq)
 {
     $client = new Rfc6455Client();
     $client->capacity = $this->maxBytesPerMinute;
     $client->connectedAt = $this->now;
     $socket = $ireq->client->socket;
     $client->id = (int) $socket;
     $client->socket = $socket;
     $client->writeBuffer = $ireq->client->writeBuffer;
     $client->serverRefClearer = ($ireq->client->exporter)($ireq->client);
     $client->parser = $this->parser([$this, "onParse"], $options = ["cb_data" => $client, "max_msg_size" => $this->maxMsgSize, "max_frame_size" => $this->maxFrameSize, "validate_utf8" => $this->validateUtf8, "text_only" => $this->textOnly, "threshold" => $this->autoFrameSize]);
     $client->readWatcher = \Amp\onReadable($socket, [$this, "onReadable"], $options = ["enable" => true, "cb_data" => $client]);
     $client->writeWatcher = \Amp\onWritable($socket, [$this, "onWritable"], $options = ["enable" => $client->writeBuffer != "", "cb_data" => $client]);
     $this->clients[$client->id] = $client;
     $this->heartbeatTimeouts[$client->id] = $this->now + $this->heartbeatPeriod;
     resolve($this->tryAppOnOpen($client->id, $ireq->locals["aerys.websocket"]));
     return $client;
 }
Ejemplo n.º 17
0
 public function send($socket)
 {
     $deferred = new Deferred();
     stream_set_blocking($socket, false);
     $data = $this->getRequest();
     \Amp\onWritable($socket, function ($writer, $socket) use($deferred, &$data) {
         if ($bytes = fwrite($socket, $data)) {
             if ($bytes < \strlen($data)) {
                 $data = substr($data, $bytes);
                 return;
             }
             $size = 8192;
             \Amp\onReadable($socket, function ($reader, $socket) use($deferred, &$size) {
                 /* make attention to not read too much data */
                 $data = stream_socket_recvfrom($socket, $size, STREAM_PEEK);
                 if (false === ($pos = strpos($data, "\r\n\r\n"))) {
                     if (\strlen($data) == $size) {
                         $size *= 2;
                         // unbounded??
                     }
                     return;
                 }
                 \Amp\cancel($reader);
                 $deferred->succeed($this->parseResponse(fread($socket, $pos + 4)));
             });
         } else {
             $deferred->succeed(null);
         }
         \Amp\cancel($writer);
     });
     return $deferred->promise();
 }
Ejemplo n.º 18
0
 private function loadNewServer($uri)
 {
     if (!($socket = @\stream_socket_client($uri, $errno, $errstr, 0, STREAM_CLIENT_ASYNC_CONNECT))) {
         throw new ResolutionException(sprintf("Connection to %s failed: [Error #%d] %s", $uri, $errno, $errstr));
     }
     \stream_set_blocking($socket, false);
     $id = (int) $socket;
     $server = new \StdClass();
     $server->id = $id;
     $server->uri = $uri;
     $server->socket = $socket;
     $server->buffer = "";
     $server->length = INF;
     $server->pendingRequests = [];
     $server->watcherId = \Amp\onReadable($socket, $this->makePrivateCallable("onReadable"), ["enable" => true, "keep_alive" => true]);
     $this->serverIdMap[$id] = $server;
     $this->serverUriMap[$uri] = $server;
     if (substr($uri, 0, 6) == "tcp://") {
         $promisor = new Deferred();
         $server->connect = $promisor->promise();
         $watcher = \Amp\onWritable($server->socket, static function ($watcher) use($server, $promisor, &$timer) {
             \Amp\cancel($watcher);
             \Amp\cancel($timer);
             unset($server->connect);
             $promisor->succeed();
         });
         $timer = \Amp\once(function () use($id, $promisor, $watcher, $uri) {
             \Amp\cancel($watcher);
             $this->unloadServer($id);
             $promisor->fail(new TimeoutException("Name resolution timed out, could not connect to server at {$uri}"));
         }, 5000);
     }
     return $server;
 }
Ejemplo n.º 19
0
 /**
  * @param int $buffer one of the self::BUFFER_* constants. Determines whether it will buffer the stdout and/or stderr data internally
  * @return Promise is updated with ["out", $data] or ["err", $data] for data received on stdout or stderr
  * That Promise will be resolved to a stdClass object with stdout, stderr (when $buffer is true), exit (holding exit code) and signal (only present when terminated via signal) properties
  */
 public function exec($buffer = self::BUFFER_NONE)
 {
     if ($this->proc) {
         throw new \RuntimeException("Process was already launched");
     }
     $cwd = isset($this->options["cwd"]) ? $this->options["cwd"] : NULL;
     $env = isset($this->options["env"]) ? $this->options["env"] : NULL;
     if (stripos(PHP_OS, "WIN") !== 0) {
         $fds = [["pipe", "r"], ["pipe", "w"], ["pipe", "w"], ["pipe", "w"]];
         $this->proc = @proc_open("{$this->cmd}; echo \$? >&3", $fds, $pipes, $cwd, $env, $this->options);
     } else {
         $options = $this->options;
         $options["bypass_shell"] = true;
         $fds = [["pipe", "r"], ["pipe", "w"], ["pipe", "w"]];
         $this->proc = @proc_open($this->cmd, $fds, $pipes, $cwd, $env, $options);
     }
     if (!$this->proc) {
         return new Failure(new \RuntimeException("Failed executing command: {$this->cmd}"));
     }
     $this->writeBuf = "";
     $this->writeTotal = 0;
     $this->writeCur = 0;
     stream_set_blocking($pipes[0], false);
     stream_set_blocking($pipes[1], false);
     stream_set_blocking($pipes[2], false);
     if (isset($pipes[3])) {
         stream_set_blocking($pipes[3], false);
         $this->openPipes = 3;
     } else {
         $this->openPipes = 2;
     }
     $this->deferred = new Deferred();
     $result = new \stdClass();
     if ($buffer & self::BUFFER_STDOUT) {
         $result->stdout = "";
     }
     if ($buffer & self::BUFFER_STDERR) {
         $result->stderr = "";
     }
     $cleanup = function () use($result) {
         \Amp\cancel($this->stdin);
         $deferreds = $this->writeDeferreds;
         $this->writeDeferreds = [];
         $status = \proc_get_status($this->proc);
         if ($status["running"] === false && $status["signaled"]) {
             $result->signal = $status["termsig"];
             $result->exit = $status["exitcode"];
         }
         if (!isset($this->exit)) {
             $result->exit = proc_close($this->proc);
         }
         unset($this->proc);
         $this->deferred->succeed($result);
         foreach ($deferreds as $deferred) {
             $deferred->fail(new \Exception("Write could not be completed, process finished"));
         }
     };
     $this->stdout = \Amp\onReadable($pipes[1], function ($watcher, $sock) use($result, $cleanup) {
         if ("" == ($data = @\fread($sock, 8192))) {
             \Amp\cancel($watcher);
             if (--$this->openPipes == 0) {
                 \Amp\immediately($cleanup);
             }
         } else {
             if (isset($result->stdout)) {
                 $result->stdout .= $data;
             }
             $this->deferred->update(["out", $data]);
         }
     });
     $this->stderr = \Amp\onReadable($pipes[2], function ($watcher, $sock) use($result, $cleanup) {
         if ("" == ($data = @\fread($sock, 8192))) {
             \Amp\cancel($watcher);
             if (--$this->openPipes == 0) {
                 \Amp\immediately($cleanup);
             }
         } else {
             if (isset($result->stderr)) {
                 $result->stderr .= $data;
             }
             $this->deferred->update(["err", $data]);
         }
     });
     $this->stdin = \Amp\onWritable($pipes[0], function ($watcher, $sock) {
         $this->writeCur += @\fwrite($sock, $this->writeBuf);
         if ($this->writeCur == $this->writeTotal) {
             \Amp\disable($watcher);
         }
         while (($next = key($this->writeDeferreds)) !== null && $next <= $this->writeCur) {
             $this->writeDeferreds[$next]->succeed($this->writeCur);
             unset($this->writeDeferreds[$next]);
         }
     }, ["enable" => false]);
     if (isset($pipes[3])) {
         $this->exit = \Amp\onReadable($pipes[3], function ($watcher, $sock) use($result, $cleanup) {
             stream_set_blocking($sock, true);
             // it should never matter, but just to be really 100% sure.
             $result->exit = (int) stream_get_contents($sock);
             \Amp\cancel($watcher);
             if (--$this->openPipes == 0) {
                 \Amp\immediately($cleanup);
             }
         });
     }
     return $this->deferred->promise();
 }
Ejemplo n.º 20
0
function __loadNewServer($state, $uri)
{
    if (!($socket = @\stream_socket_client($uri, $errno, $errstr))) {
        throw new ResolutionException(sprintf("Connection to %s failed: [Error #%d] %s", $uri, $errno, $errstr));
    }
    \stream_set_blocking($socket, false);
    $id = (int) $socket;
    $server = new \StdClass();
    $server->id = $id;
    $server->uri = $uri;
    $server->socket = $socket;
    $server->buffer = "";
    $server->length = INF;
    $server->pendingRequests = [];
    $server->watcherId = \Amp\onReadable($socket, 'Amp\\Dns\\__onReadable', ["enable" => true, "keep_alive" => true, "cb_data" => $state]);
    $state->serverIdMap[$id] = $server;
    $state->serverUriMap[$uri] = $server;
    return $server;
}
Ejemplo n.º 21
0
 /**
  * @return Promise
  */
 private function connect()
 {
     if ($this->promisor) {
         return $this->promisor->promise();
     }
     // Already connected
     if (is_resource($this->socket)) {
         return new Success();
     }
     $this->promisor = new \Amp\Deferred();
     /** @var $socketPromise Promise */
     $socketPromise = \Amp\Socket\connect($this->uri, ['timeout' => 1000]);
     $socketPromise->when(function ($error, $socket) {
         $promisor = $this->promisor;
         $this->promisor = null;
         $this->socket = $socket;
         $this->reader = \Amp\onReadable($this->socket, [$this, "onRead"]);
         $this->writer = \Amp\onWritable($this->socket, [$this, "onWrite"]);
         $promisor->succeed();
     });
     return $this->promisor->promise();
 }
Ejemplo n.º 22
0
 public function send($socket)
 {
     $deferred = new Deferred();
     stream_set_blocking($socket, false);
     $data = $this->getRequest();
     \Amp\onWritable($socket, function ($writer, $socket) use($deferred, &$data) {
         if ($bytes = fwrite($socket, $data)) {
             if ($bytes < \strlen($data)) {
                 $data = substr($data, $bytes);
                 return;
             }
             $data = '';
             \Amp\onReadable($socket, function ($reader, $socket) use($deferred, &$data) {
                 $data .= $bytes = fgets($socket);
                 if ($bytes == '' || \strlen($bytes) > 32768) {
                     \Amp\cancel($reader);
                     $deferred->succeed(null);
                 } elseif (substr($data, -4) == "\r\n\r\n") {
                     \Amp\cancel($reader);
                     $deferred->succeed($this->parseResponse($data));
                 }
             });
         } else {
             $deferred->succeed(null);
         }
         \Amp\cancel($writer);
     });
     return $deferred->promise();
 }