Ferreteria/v0.6/clade/IO/Aspect/Connx/run/Session/@code/cur/2026/09/01
Jump to navigation
Jump to search
| 2026/08/31 | 2026/09/01 | 2026/09/02 |
/* APipes* [c,i] */ use Woozalia\Ferret\IO\Aspect\Connx\run\Session\Local\proc\{ 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;
/* 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;
// 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();
// STATUS
function IsRunning() : bool;
// OBJECTS
var StartIface $OStart { get; }
var CommandIface $OCommand { get; }
function QPanel() : QPanelIface;
function OOpCmd(?OpCmdIface $o=NULL) : OpCmdIface;
// 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; }
}
abstract class caSession extends BaseClass implements SelfIface {
// ++ CONFIG ++ //
public string $SIdentityForLog { get => parent::$SIdentityForLog::get().' '.$this->OCommand->AsString; }
// -- CONFIG -- //
// ++ SETUP ++ //
public static function FromStarter(StartIface $oStart) : SelfIface {
$oThis = new static;
$oThis->OStart = $oStart;
return $oThis;
}
// -- SETUP -- //
// ++ ACTION ++ //
private $doBreak;
public function DoBreak() { $this->doBreak = TRUE; }
public function DoCommand(CommandIface &$oCmd) : OpCmdIface {
$this->OCommand = $oCmd;
$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: internals ++ //
abstract protected function StartProcess();
// USAGE: Call this after setting up one or more Streams on the Command, and before calling DoInOutLoop().
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 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?)
// 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 -- //
}