ServeHost:
PUBLIC
PROC [addr:
TMS.Host, role:
TMS.Role]
RETURNS [whyNot:
ROPE] ~ {
WithLock:
ENTRY
PROC [rm: RefLock]
RETURNS [
BOOL] ~ {
ENABLE UNWIND => NULL;
IF InnerIsHost[addr] THEN RETURN [TRUE];
addrs ¬ CONS[addr, addrs];
FOR is: InterestList ¬ interests, is.rest
WHILE is #
NIL
DO
is.first.NoteHost[is.first, addr, TRUE];
ENDLOOP;
RETURN [FALSE]};
whyNot ¬ NIL;
IF addr=NA.nullAddress THEN RETURN ["I can't serve the null client"];
[] ¬ WithLock[clientLock];
whyNot ¬ SendCommand[addr, roleCmds[role], TRUE, TRUE].ans;
whyNot ¬ IF whyNot.Length[]=0 THEN "no response" ELSE IF whyNot.Equal["OK"] THEN NIL ELSE whyNot;
IF whyNot # NIL THEN DontServeHost[addr];
RETURN};
SendCommand:
PROC [dest:
TMS.Host, cmd:
CHAR, postfixSelf, postfixVersions:
BOOL]
RETURNS [ok:
BOOL ¬
TRUE, ans:
ROPE] ~ {
cmdIn, cmdOut: IO.STREAM ¬ NIL;
pv: HaTO.ProtocolVersion ¬ 1;
desta: ROPE ¬ NIL;
destf: ATOM ¬ NIL;
ansFromRem: BOOL ¬ FALSE;
{
ENABLE {
IO.Error => {ok ¬ FALSE; ans ¬ IOErrorFormatting.FormatError[ec]; CONTINUE};
IO.EndOfStream => {ok ¬ FALSE; ans ¬ "IO.EndOfStream"; CONTINUE};
Nws.Error => {ok ¬ FALSE; ans ¬ NA.FormatError[codes, msg]; CONTINUE};
};
SendPVR:
PROC [protocol:
ROPE, pvr: HaTO.ProtocolVersionRange] ~ {
cmdOut.PutF["\"%q\" %g %g\r", [rope[protocol]], [integer[pvr.min]], [integer[pvr.max]]];
RETURN};
[desta, destf] ¬ NA.ToNnAddress[dest !NA.Error => {ok ¬ FALSE; ans ¬ IO.PutFR["%g while converting %g %g %g to address", [rope[NA.FormatError[codes, msg]]], [rope[NA.FormatAddress[dest, TRUE]]] ]; GOTO Dun}];
[cmdIn, cmdOut] ¬ Nws.CreateStreams[protocolFamily: destf, transportClass: $basicStream, remote: desta ];
cmdOut.PutChar[versionBrick];
cmdOut.PutChar[VAL[coordVersions.min]];
cmdOut.PutChar[VAL[coordVersions.max]];
cmdOut.Flush[];
IF debugSendCommand THEN SimpleFeedback.PutFL[$TerminalCoordination, oneLiner, $Debug, "Sending cmd %g to host %g", LIST[[character[cmd]], [rope[desta]]] ];
{hisBrick: CHAR ~ cmdIn.GetChar[];
IF hisBrick#versionBrick THEN {ans ¬ "Host didn't open with version brick"; GOTO Dun};
{hisVR: HaTO.ProtocolVersionRange ¬ [min: cmdIn.GetChar[].ORD];
hisVR.max ¬ cmdIn.GetChar[].ORD;
pv ¬ MIN[coordVersions.max, hisVR.max];
IF
MAX[coordVersions.min, hisVR.min] > pv
THEN {
ans ¬ IO.PutFLR["version mismatch: his[%g..%g] <> my[%g .. %g] coordination protocol", LIST[[integer[hisVR.min]], [integer[hisVR.max]], [integer[coordVersions.min]], [integer[coordVersions.max]]] ];
GOTO Dun};
}};
cmdOut.PutChar[cmd];
IF postfixSelf AND pv>=4 THEN cmdOut.PutF1["\"%q\";", [rope[NN.AddressFromName[$ARPA, NIL, arpaTerminalPort, port].addr]] ];
IF postfixVersions
THEN {
HaTO.EnumerateProtocolVersionsOfSide[Terminal, SendPVR];
cmdOut.PutRope["\"\" 0 0\r"]};
IO.Flush[cmdOut];
IF debugSendCommand THEN SimpleFeedback.PutFL[$TerminalCoordination, oneLiner, $Debug, "Waiting for reply to cmd %g from host %g", LIST[[character[cmd]], [rope[desta]]] ];
ans ¬ cmdIn.GetLineRope[]; ansFromRem ¬ TRUE;
EXITS Dun => cmd ¬ cmd;
};
IF debugSendCommand THEN SimpleFeedback.PutFL[$TerminalCoordination, oneLiner, $Debug, "Answer for cmd %g from host %g is %g", LIST[[character[cmd]], [rope[desta]], [rope[ans]]] ];
IF cmdIn#
NIL
THEN {
ENABLE IO.Error => CONTINUE;
cmdOut.PutChar['.]; cmdOut.Flush[];
cmdOut.Close[]; cmdIn.Close[]};
RETURN};