Ferreteria/v0.6/clade/IO/Aspect/Connx/run/Session/@code/cur/2026/09/04
Jump to navigation
Jump to search
| 2026/09/03 | 2026/09/04 | 2026/09/05 |
I'm about to do some more intensive rearranging of how this works...
/* APipes* [c,i] */ use Woozalia\Ferret\IO\Aspect\Connx\run\aux\A\{ cPipes as APipesClass, iPipes as APipesIface };
/* Base* [ca,i] */ use Woozalia\Ferret\Sys\InOut\{ caConnx as BaseClass, iConnx as BaseIface };
/* Canals* [c,i] */ use Woozalia\Ferret\IO\Aspect\Connx\aux\A\iCanals as CanalsIface;
/* CommandIface */ use Woozalia\Ferret\IO\Aspect\Connx\run\iCommand as CommandIface;
/* EventIface */ use Woozalia\Ferret\Sys\Events\iEvent as EventIface;
/* EventOnAfter */ use Woozalia\Ferret\Sys\Events\Event\Loops\cOnAfter as EventOnAfter;
/* EventOnBefore */ use Woozalia\Ferret\Sys\Events\Event\Loops\cOnBefore as EventOnBefore;
/* EventOnLoop */ use Woozalia\Ferret\Sys\Events\Event\Loops\cOnLoop as EventOnLoop;
/* OpCmd* [c,i] */ use Woozalia\Ferret\IO\Aspect\Connx\run\Starter\ops\{ cOpCmd as OpCmdClass, iOpCmd as OpCmdIface };
/* OpDataIface */ use Woozalia\Ferret\Sys\Events\ItWent\OpComm\cOpData as OpDataIface;
/* OpOpenIface */ use Woozalia\Ferret\Sys\Events\ItWent\connx\iOpOpen as OpOpenIface;
/* OpShutIface */ use Woozalia\Ferret\Sys\Events\ItWent\connx\iOpShut as OpShutIface;
/* QPanel* [c,i] */ use Woozalia\Ferret\IO\O\Panel\aux\{ cQPanel as QPanelClass, iQPanel as QPanelIface };
/* QStream* [c,i] */ use Woozalia\Ferret\Sys\InOut\Connx\aux\Q\{ cStream as QStreamClass, iStream as QStreamIface };
/* SelfIface */ use Woozalia\Ferret\IO\Aspect\Connx\run\iSession as SelfIface;
/* StartIface */ use Woozalia\Ferret\IO\Aspect\Connx\run\iStarter as StartIface;
/* StreamIface */ use Woozalia\Ferret\Sys\InOut\Connx\iStream as StreamIface;
interface iSession extends BaseIface {
// SETUP
static function FromCommand(CommandIface $o) : SelfIface;
#static function FromStartCmd(StartIface $o, CommandIface $oCmd) : SelfIface;
#static function FromStarter(StartIface $o) : SelfIface;
// STATUS
var bool $IsRunning { get; }
// ACTION
#function DoCommand(CommandIface &$oCmd) : OpCmdIface;
function DoStream(StreamIface $oStrm) : OpCmdIface;
#function DoRequest(CommandIface $o) : OpDataIface;
function DoInOutLoop() : OpCmdIface; // FUTURE (2026/03/17): We *might* eventually need a different Op class. This is what we had been using, however.
function DoBreak();
// OBJECTS
var StartIface $OStart { get; }
var CommandIface $OCommand { get; }
function QPanel() : QPanelIface;
function OOpCmd(?OpCmdIface $o=NULL) : OpCmdIface;
// OBJECTS: action
function NewSession(CommandIface &$oCmd) : SelfIface;
// OBJECTS: streams
var StreamIface $OExecLecture { get; } // stream received from process (stdout) (the process's lecture)
var StreamIface $OExecRespond { get; } // stream for talking to process (stdin) (responding to the process)
var StreamIface $OExecErrsBin { get; } // stream for process to send errors (stderr) (errors from process)
var QStreamIface $QOAppLecturer { get; }
var QStreamIface $QOAppListener { get; }
var QStreamIface $QOAppErrorBin { get; }
}
class cSession extends BaseClass implements SelfIface {
// ++ CONFIG ++ //
// CONFIG
public function SType() : string { return 'run session'; }
public string $SIdentityForLog { get => parent::$SIdentityForLog::get().' '.$this->OCommand->AsString; }
protected string $SCSession { get => cSession::class; }
// -- CONFIG -- //
// ++ SETUP ++ //
public static function FromCommand(CommandIface $oCmd) : SelfIface {
$oThis = new static;
$oThis->OCommand = $oCmd;
return $oThis;
}
/* 2026-09-03 use FromCommand() instead
public static function FromStarter(StartIface $oStart) : SelfIface {
$oThis = new static;
$oThis->OStart = $oStart;
return $oThis;
}
*/
// -- SETUP -- //
// ++ STATUS ++ //
var bool $IsRunning { get => $this->OCommand->OConn->IsRunning; }
// -- STATUS -- //
// ++ ACTION ++ //
private $doBreak;
public function DoBreak() { $this->doBreak = TRUE; }
#public function DoCommand(CommandIface &$oCmd) : OpCmdIface {
public function DoCommand() : OpCmdIface {
#$this->OCommand = $oCmd;
$oCmd = $this->OCommand;
$oCmd->OSession = $this;
// if this command has an updater, deploy it:
$oUpd = $oCmd->OUpdate;
$qoUpd = self::QOUpdater();
$qoUpd->SetObjNz($oUpd);
$qoUpd->OnEvent(new EventOnBefore);
$oOpComm = $this->SendCommand();
if ($oOpComm->IsOkay) {
$oOpLoop = $this->DoInOutLoop();
$oOpComm->Assimilate($oOpLoop);
}
$oUpd->OnEvent(new EventOnAfter);
#$oStrm->Shut();
return $oOpComm;
}
public function DoStream(StreamIface $oStrm) : OpCmdIface {
$oUpd = $this->OCommand->OUpdate;
$qoUpd = self::QOUpdater();
$qoUpd->SetIt($oUpd);
$this->QOAppLecturer->SetIt($oStrm);
return $this->DoInOutLoop();
}
protected function SendCommand() : OpCmdIface {
$oCmd = $this->OCommand;
$sCmd = $oCmd->AsString;
$oOpComm = $this->OExecRespond->PushBytes($sCmd."\n");
$oOpCmd = new OpCmdClass;
$oOpCmd->Assimilate($oOpComm);
return $oOpCmd;
}
// -- ACTION -- //
// ++ LIFECYCLE ++ //
protected function ActualOpen() : OpOpenIface {
$oConn = $this->OCommand->ORunner;
return $oConn->Open();
}
protected function ActualShut() : OpShutIface {
$oConn = $this->OCommand->ORunner;
return $oConn->Shut();
}
// ++ LIFECYCLE: internals ++ //
protected function StartProcess() {
$oConn = $this->OCommand->ORunner;
// WORKING HERE
}
// USAGE: Call this after setting up one or more Streams on the Command, and before calling DoInOutLoop().
# 2026-09-03 If this is needed here, it should be a shortcut to the Comm object's implementation.
#abstract protected function CanalSetup();
public function DoInOutLoop() : OpCmdIface {
$this->CanalSetup();
$qoUpdate = self::QOUpdater();
$oCanals = $this->OCanals;
$oCanals->Open();
$oOpConvey = NULL;
$oOpThis = $this->OOpCmd();
$doLoop = TRUE;
$this->doBreak = FALSE;
$oeBefore = new EventOnBefore;
$oeLoop = new EventOnLoop;
$oeAfter = new EventOnAfter;
$oCanals->OnEvent($oeBefore);
$qoUpdate->OnEvent($oeBefore);
while ($doLoop) {
$qoUpdate->OnEvent($oeLoop);
$oOpNew = $oCanals->ConveyCheck();
if (!$oOpNew->IsOkay) {
$this->DoBreak();
}
$oOpThis->Assimilate($oOpNew);
$doLoop = $this->IsRunning && !$this->doBreak;
}
$oCanals->OnEvent($oeAfter);
$qoUpdate->OnEvent($oeAfter);
$oCanals->Shut();
return $oOpThis;
}
// -- LIFECYCLE -- //
// ++ OBJECTS ++ //
public function NewSession(CommandIface &$oCmd) : SelfIface {
$oSess = ($this->SCSession)::FromStarter($this);
$oSess->OCommand = $oCmd;
return $oSess;
}
public StartIface $OStart;
public APipesIface $OACodePipes { get => $this->OACodePipes ??= new APipesClass; } // pipes from application code
// NOTE: Local-Proc defines an additional set for the process (2026-08-23 why don't we need that for SSH2?)
// OBJECTS: streams
public StreamIface $OExecLecture { get => $this->OCommand->OConn->OLecture; } // stream received from process (stdout) (the process's lecture)
public StreamIface $OExecRespond { get => $this->OCommand->OConn->OListen; } // stream for talking to process (stdin) (responding to the process)
public StreamIface $OExecErrsBin { get => $this->OCommand->OConn->OErrors; } // stream for process to send errors (stderr) (errors from process)
// SHORTCUTS
public QStreamIface $QOAppLecturer { get => $this->OACodePipes->QOStream; }
public QStreamIface $QOAppListener { get => $this->OACodePipes->QIStream; }
public QStreamIface $QOAppErrorBin { get => $this->OACodePipes->QEStream; }
protected CanalsIface $OCanals;
public CommandIface $OCommand {
set(CommandIface $o) {
$o->OSession = $this;
$this->OCommand = $o;
$oUpd = $o->OUpdate;
self::QOUpdater()->SetObjNz($oUpd);
}
}
private $qoPanel = NULL;
public function QPanel() : QPanelIface { return $this->qoPanel ?? ($this->qoPanel = QPanelClass::AsNew()); }
// 2026-04-01 copied from Starter
private $oRes = NULL;
public function OOpCmd(?OpCmdIface $o=NULL) : OpCmdIface { return is_null($o) ? ($this->oRes ?? $this->OOpCmdNew()) : ($this->oRes = $o); }
protected function OOpCmdNew() : OpCmdIface { return new OpCmdClass; }
// -- OBJECTS -- //
// ++ DEBUG ++ //
public function VIEW_Inline() : string {
$a = $this->OACodePipes->AVals;
$s = '';
foreach ($a as $key => $oStream) {
$sType = $oStream->SType();
$sID = $oStream->SIdentityForLog;
$s .= "[#$key:$sID ($sType)]";
}
return $s;
}
// -- DEBUG -- //
}