Ferreteria/v0.6/clade/IO/Aspect/Connx/run/Session/@code/cur/2026/09/10
Jump to navigation
Jump to search
| 2026/09/09 | 2026/09/10 | 2026/09/11 |
This is a snapshot from just before cleaning out some code that I've commented out (including some that I commented out just now, shortly after re-enabling it).
/* 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 };
/* CanalClass */ use Woozalia\Ferret\IO\Aspect\Connx\cCanal as CanalClass;
/* Canals* [c,i] */ use Woozalia\Ferret\IO\Aspect\Connx\aux\A\{ cCanals as CanalsClass, iCanals as CanalsIface };
/* CommandIface */ use Woozalia\Ferret\IO\Aspect\Connx\run\iCommand as CommandIface;
/* EngineIface */ use Woozalia\Ferret\Sys\Data\iEngine as EngineIface;
/* 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;
/* EventOnReset */ use Woozalia\Ferret\IO\Aspect\Connx\Stream\aux\Event\cReset as EventOnReset;
/* OpCmd* [c,i] */ use Woozalia\Ferret\IO\Aspect\Connx\run\Session\aux\{ 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;
/* ServIface */ use Woozalia\Ferret\Sys\InOut\Connx\iServer as ServIface;
/* 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;
#static function FromServer(ServIface $o) : SelfIface;
#static function FromEngine(EngineIface $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;
var OpCmdIface $OOpCmd { get; }
// 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 $QOAppOuStrm { get; }
var QStreamIface $QOAppInStrm { get; }
var QStreamIface $QOAppEIStrm { 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 ++ //
// 2026-09-10 This is just FromServer() again, but with a less confusing name.
public static function FromRunner(ServIface $o) : SelfIface {
$oThis = new static;
$oThis->ORun = $o;
return $oThis;
}
/* 2026-09-10 I actually think maybe Command needs to be the key.
public static function FromEngine(EngineIface $o) : SelfIface {
$oThis = new static;
$oThis->OEng = $o;
if (!isset($o->OCmdConn)) {
$this->AmHere('WARNING: Engine connection object needs to be set in the configuration.');
}
return $oThis;
}
*/
/* 2026-09-07 replacing with FromEngine()
public static function FromServer(ServIface $o) : SelfIface {
$oThis = new static;
$oThis->OServ = $o;
return $oThis;
}
*/
/*
public static function FromCommand(CommandIface $oCmd) : SelfIface {
$oThis = new static;
$oThis->OCommand = $oCmd;
return $oThis;
}
*/
// -- SETUP -- //
// ++ STATUS ++ //
var bool $IsRunning { get => $this->ORun->IsRunning; }
// -- STATUS -- //
// ++ ACTION ++ //
private $doBreak;
public function DoBreak() { $this->doBreak = TRUE; }
// ACTION: Runs the executable and makes I/O/E Streams available
public function DoCommand(CommandIface &$oCmd) : OpCmdIface {
$qoUpd = self::QOUpdater();
$oUpdSave = $qoUpd->ItNz;
// if this command has an updater, deploy it:
$oUpd = $oCmd->OUpdate;
$qoUpd->ItNz = $oUpd;
$qoUpd->OnEvent(new EventOnBefore);
$oRun = $this->ORun;
$ok = $oRun->Run($oCmd->AsString);
$this->AmHere('Session after running "'.$oCmd->AsString.'":'.CRLF.$this->DIAG_AsBlock);
if ($ok) {
$oOpCmd = $this->DoInOutLoop();
#$oOpComm->Assimilate($oOpLoop);
} else {
$oOpCmd = OpCmdClass::FromOkay(FALSE);
}
/* 2026-09-07 old version
#$oOpComm = $this->SendCommand($oCmd);
if ($oOpComm->IsOkay) {
$oOpLoop = $this->DoInOutLoop();
$oOpComm->Assimilate($oOpLoop);
}
*/
$oUpd->OnEvent(new EventOnAfter);
$qoUpd->ItNz = $oUpdSave;
return $oOpCmd;
}
public function DoStream(StreamIface $oStrm) : OpCmdIface {
$oUpd = $this->OCommand->OUpdate;
$qoUpd = self::QOUpdater();
$qoUpd->It = $oUpd;
$this->QOAppOuStrm->SetIt($oStrm);
return $this->DoInOutLoop();
}
/* 2026-09-08 no longer used.
protected function SendCommand(CommandIface &$oCmd) : OpCmdIface {
$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->ORun;
$this->AmHere('ActualOpen of process, class '.get_class($oConn));
return $oConn->Open();
// TODO 2026-09-09: This is where we need to call Run(), I think -- not in DoCommand(). Or something.
}
protected function ActualShut() : OpShutIface {
$this->AmHere('ActualShut of process, class');
$oConn = $this->ORun;
return $oConn->Shut();
}
// ++ LIFECYCLE: internals ++ //
public function DoInOutLoop() : OpCmdIface {
$this->CanalSetup();
$qoUpdate = self::QOUpdater();
if ($qoUpdate->HasIt) {
$ou = $qoUpdate->It;
$ou->OSession = $this;
}
$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);
$this->AmHere('SESSION: before loop'.CRLF.$this->DIAG_AsBlock);
while ($doLoop) {
$qoUpdate->OnEvent($oeLoop);
$oOpNew = $oCanals->ConveyCheck();
if (!$oOpNew->IsOkay) {
$this->DoBreak();
}
$oOpThis->Assimilate($oOpNew);
$doLoop = $this->IsRunning && !$this->doBreak;
}
$this->AmHere('SESSION: after loop'.CRLF.$this->DIAG_AsBlock);
$oCanals->OnEvent($oeAfter);
$qoUpdate->OnEvent($oeAfter);
$oCanals->Shut();
return $oOpThis;
}
// 2026-03-30 This will need some tweaking to work on anything except Local\Proc.
// 2026-04-03 Moved from base Session to Proc.
// 2026-09-07 Moved back to Session, at least for now. Tweakage shall commence forthwith.
protected function CanalSetup() {
$this->AmHere('SETUP local Canals');
$oRun = $this->ORun;
$oProcLect = $oRun->OuStrm; // Process Lecturer
$oProcLstn = $oRun->InStrm; // Process Listener
$oProcErrs = $oRun->EOStrm; // Process Errors
$qoAppLect = $this->QOAppOuStrm;
$qoAppLstn = $this->QOAppInStrm;
$qoAppErrs = $this->QOAppEIStrm;
// ++ CANALS: build the Canals Stream-list
$oCanals = CanalsClass::FromVoid();
$oCanalRecv = CanalClass::FromPair($oProcLect,$qoAppLstn->It);
$oCanals->AddIt($oCanalRecv);
if ($qoAppLect->HasIt) {
$oCanalSend = CanalClass::FromPair($qoAppLect->It,$oProcLstn);
$oCanals->AddIt($oCanalSend);
}
$oCanalErrs = CanalClass::FromPair($oProcErrs,$qoAppErrs->It);
$oCanals->AddIt($oCanalErrs);
$this->AmHere('CANALS:'.CRLF.$oCanals->VIEW_AsBlock);
// -- CANALS
$oCanals->OnEvent(new EventOnReset); // reset all the streams
$this->OCanals = $oCanals;
/* 2026-09-07 old
$oaPrcStrms = $oRun->OPipes;
$oaPrcStrms->Block(FALSE);
$oaAppStrms = $this->OACodeStrms;
$oCanals = CanalsClass::FromVoid();
$oProcLecture = $oaPrcStrms->OStream; // Process Lecturer
$oProcListen = $oaPrcStrms->IStream; // Process Listener
$oProcErrors = $oaPrcStrms->EStream; // Process Errors
$qoAppLect = $this->QOAppOuStrm;
$qoAppLstn = $this->QOAppInStrm;
$qoAppErrs = $this->QOAppEIStrm;
$oCmdListen = NULL;
$oCmdLecture = NULL;
$oCmdErrors = NULL;
if ($qoAppLstn->HasIt) {
$oCmdListen = $qoAppLstn->It; // Command Listener stream
$oCanalRecv = CanalClass::FromPair($oProcLecture,$oCmdListen);
$oCanals->AddIt($oCanalRecv);
} else {
$this->AmHereShort('Application has no listener.');
}
if ($qoAppLect->HasIt) {
$oCmdLecture = $qoAppLect->It; // Command Lecturer stream
$oCanalSend = CanalClass::FromPair($oCmdLecture,$oProcListen);
$oCanals->AddIt($oCanalSend);
#} else {
# $this->AmHereShort('No command-lecturer.');
}
if ($qoAppErrs->HasIt) {
$oCmdErrors = $qoAppErrs->It; // Command Error-messages stream
$oCanalErrs = CanalClass::FromPair($oProcErrors,$oCmdErrors);
$oCanals->AddIt($oCanalErrs);
} else {
$this->AmHereShort('Application has no error-bin.');
}
$oCanals->OnEvent(new EventOnReset); // reset all the streams
$this->OCanals = $oCanals;
*/
}
// -- LIFECYCLE -- //
// ++ OBJECTS ++ //
/* 2026-09-05 not sure about this...
public function NewSession(CommandIface &$oCmd) : SelfIface {
$oSess = ($this->SCSession)::FromStarter($this);
$oSess->OCommand = $oCmd;
return $oSess;
}
*/
#protected ServIface $OServ;
#protected EngineIface $OEng;
protected CommandIface $OCmd;
protected ServIface $ORun { get => $this->OEng->OCmdConn; }
#public StartIface $OStart;
public APipesIface $OACodeStrms { get => $this->OACodeStrms ??= 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->ORun->OuStrm; } // stream received from process (stdout) (the process's lecture)
public StreamIface $OExecRespond { get => $this->ORun->InStrm; } // stream for talking to process (stdin) (responding to the process)
public StreamIface $OExecErrsBin { get => $this->ORun->EOStrm; } // stream for process to send errors (stderr) (errors from process)
// SHORTCUTS
public QStreamIface $QOAppOuStrm { get => $this->OACodeStrms->QOStream; }
public QStreamIface $QOAppInStrm { get => $this->OACodeStrms->QIStream; }
public QStreamIface $QOAppEIStrm { get => $this->OACodeStrms->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); }
public OpCmdIface $OOpCmd { get => $this->OOpCmd ??= $this->OOpCmdNew(); }
protected function OOpCmdNew() : OpCmdIface { return OpCmdClass::FromSession($this); }
// -- OBJECTS -- //
// ++ DEBUG ++ //
public function VIEW_Inline() : string {
$a = $this->OACodeStrms->AVals;
$s = '';
foreach ($a as $key => $oStream) {
$sType = $oStream->SType();
$sID = $oStream->SIdentityForLog;
$s .= "[#$key:$sID ($sType)]";
}
return $s;
}
public string $DIAG_AsBlock { get {
$a = $this->OACodeStrms->AVals;
$s = 'Code streams'.CRLF;
foreach ($a as $key => $oStream) {
$sType = $oStream->SType();
$sID = $oStream->SIdentityForLog;
$s .= " - [#$key:$sID ($sType)] - ".get_class($oStream).CRLF;
}
if (isset($this->OCanals)) {
$s .= $this->OCanals->VIEW_AsBlock;
} else {
$s .= "(Canals not yet created.)".CRLF;
}
return $s;
} }
// -- DEBUG -- //
}