Changeset View
Changeset View
Standalone View
Standalone View
src/infrastructure/ssh/PhabricatorSSHPassthruCommand.php
| Show All 37 Lines | |||||
| final class PhabricatorSSHPassthruCommand extends Phobject { | final class PhabricatorSSHPassthruCommand extends Phobject { | ||||
| private $commandChannel; | private $commandChannel; | ||||
| private $ioChannel; | private $ioChannel; | ||||
| private $errorChannel; | private $errorChannel; | ||||
| private $execFuture; | private $execFuture; | ||||
| private $willWriteCallback; | private $willWriteCallback; | ||||
| private $willReadCallback; | private $willReadCallback; | ||||
| private $pauseIOReads; | |||||
| public function setCommandChannelFromExecFuture(ExecFuture $exec_future) { | public function setCommandChannelFromExecFuture(ExecFuture $exec_future) { | ||||
| $exec_channel = new PhutilExecChannel($exec_future); | $exec_channel = new PhutilExecChannel($exec_future); | ||||
| $exec_channel->setStderrHandler(array($this, 'writeErrorIOCallback')); | $exec_channel->setStderrHandler(array($this, 'writeErrorIOCallback')); | ||||
| $this->execFuture = $exec_future; | $this->execFuture = $exec_future; | ||||
| $this->commandChannel = $exec_channel; | $this->commandChannel = $exec_channel; | ||||
| Show All 19 Lines | public function setWillWriteCallback($will_write_callback) { | ||||
| $this->willWriteCallback = $will_write_callback; | $this->willWriteCallback = $will_write_callback; | ||||
| return $this; | return $this; | ||||
| } | } | ||||
| public function writeErrorIOCallback(PhutilChannel $channel, $data) { | public function writeErrorIOCallback(PhutilChannel $channel, $data) { | ||||
| $this->errorChannel->write($data); | $this->errorChannel->write($data); | ||||
| } | } | ||||
| public function setPauseIOReads($pause) { | |||||
| $this->pauseIOReads = $pause; | |||||
| return $this; | |||||
| } | |||||
| public function execute() { | public function execute() { | ||||
| $command_channel = $this->commandChannel; | $command_channel = $this->commandChannel; | ||||
| $io_channel = $this->ioChannel; | $io_channel = $this->ioChannel; | ||||
| $error_channel = $this->errorChannel; | $error_channel = $this->errorChannel; | ||||
| if (!$command_channel) { | if (!$command_channel) { | ||||
| throw new Exception('Set a command channel before calling execute()!'); | throw new Exception('Set a command channel before calling execute()!'); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | while (true) { | ||||
| $error_channel->update(); | $error_channel->update(); | ||||
| } | } | ||||
| // If the subprocess has exited and we've read everything from it, | // If the subprocess has exited and we've read everything from it, | ||||
| // we're all done. | // we're all done. | ||||
| $done = !$command_channel->isOpenForReading() && | $done = !$command_channel->isOpenForReading() && | ||||
| $command_channel->isReadBufferEmpty(); | $command_channel->isReadBufferEmpty(); | ||||
| if (!$this->pauseIOReads) { | |||||
| $in_message = $io_channel->read(); | $in_message = $io_channel->read(); | ||||
| if ($in_message !== null) { | if ($in_message !== null) { | ||||
| $in_message = $this->willWriteData($in_message); | $this->writeIORead($in_message); | ||||
| if ($in_message !== null) { | |||||
| $command_channel->write($in_message); | |||||
| } | } | ||||
| } | } | ||||
| $out_message = $command_channel->read(); | $out_message = $command_channel->read(); | ||||
| if ($out_message !== null) { | if (strlen($out_message)) { | ||||
| $out_message = $this->willReadData($out_message); | $out_message = $this->willReadData($out_message); | ||||
| if ($out_message !== null) { | if ($out_message !== null) { | ||||
| $io_channel->write($out_message); | $io_channel->write($out_message); | ||||
| } | } | ||||
| } | } | ||||
| // If we have nothing left on stdin, close stdin on the subprocess. | // If we have nothing left on stdin, close stdin on the subprocess. | ||||
| if (!$io_channel->isOpenForReading()) { | if (!$io_channel->isOpenForReading()) { | ||||
| Show All 19 Lines | list($err) = $this->execFuture | ||||
| ->setStdoutSizeLimit(0) | ->setStdoutSizeLimit(0) | ||||
| ->setStderrSizeLimit(0) | ->setStderrSizeLimit(0) | ||||
| ->setReadBufferSize(null) | ->setReadBufferSize(null) | ||||
| ->resolve(); | ->resolve(); | ||||
| return $err; | return $err; | ||||
| } | } | ||||
| public function writeIORead($in_message) { | |||||
| $in_message = $this->willWriteData($in_message); | |||||
| if (strlen($in_message)) { | |||||
| $this->commandChannel->write($in_message); | |||||
| } | |||||
| } | |||||
| public function willWriteData($message) { | public function willWriteData($message) { | ||||
| if ($this->willWriteCallback) { | if ($this->willWriteCallback) { | ||||
| return call_user_func($this->willWriteCallback, $this, $message); | return call_user_func($this->willWriteCallback, $this, $message); | ||||
| } else { | } else { | ||||
| if (strlen($message)) { | if (strlen($message)) { | ||||
| return $message; | return $message; | ||||
| } else { | } else { | ||||
| return null; | return null; | ||||
| Show All 17 Lines | |||||