-- File: HostWatcherPoke.mesa, Last Edit: HGM March 28, 1981 3:32 PM DIRECTORY Ascii USING [CR, LF, SP], InlineDefs USING [BcplLongNumber, BcplToMesaLongNumber], String USING [ AppendString, AppendChar, WordsForString, EquivalentString, AppendLongNumber], Time USING [Current], Librarian USING [PropertyList, PropertyPair, PropertyNumber], LibrarianPN USING [IDName, StringName], LibrarianOps USING [LibjectMessage, LibjectMessageType, ValidLibrarianMessage], Stream USING [Delete, GetChar, Handle, TimeOut], FTPDefs USING [ FTPUser, FTPCreateUser, FTPDestroyUser, FTPError, FTPInitialize, FTPFinalize, FTPOpenConnection, SomeFilePrimitives, PupCommunicationPrimitives], GateControlDefs USING [ gateControlStatsSend, gateControlStatsAck, GateControlStatsEntry], PupStream USING [PupByteStreamCreate, StreamClosing], PupDefs USING [ GetFreePupBuffer, ReturnFreePupBuffer, PupBuffer, PupSocket, PupSocketDestroy, PupSocketMake, SecondsToTocks, SetPupContentsWords, GetPupContentsBytes, veryLongWait], PupTypes USING [fillInSocketID, PupAddress, PupType], HostWatcherOps USING [Info, ShowErrorPup, State]; HostWatcherPoke: PROGRAM IMPORTS String, Time, InlineDefs, Stream, FTPDefs, PupDefs, PupStream, HostWatcherOps EXPORTS HostWatcherOps = BEGIN OPEN PupDefs, PupTypes; Info: TYPE = HostWatcherOps.Info; debug: BOOLEAN _ FALSE; PokeGateway: PUBLIC PROCEDURE [info: Info] = BEGIN b: PupBuffer _ NIL; packetNumber: CARDINAL _ NextSequenceNumber[]; mySoc: PupSocket _ PupSocketMake[ fillInSocketID, info.address, SecondsToTocks[5]]; tries: CARDINAL _ 10; THROUGH [0..tries) DO b _ GetFreePupBuffer[]; b.pupID.a _ 27182; b.pupID.b _ (packetNumber _ packetNumber + 1); b.pupType _ GateControlDefs.gateControlStatsSend; SetPupContentsWords[b, 0]; mySoc.put[b]; UNTIL (b _ mySoc.get[]) = NIL DO SELECT TRUE FROM (b.pupType = error AND b.errorCode = noProcessPupErrorCode) => BEGIN FOR i: CARDINAL IN [0..GetPupContentsBytes[b] - 2*(10 + 1 + 1)) DO String.AppendChar[info.text, b.errorText[i]]; ENDLOOP; HostWatcherOps.ShowErrorPup[b]; GOTO Rejecting; END; (b.pupType = error) => HostWatcherOps.ShowErrorPup[b]; (b.pupType = GateControlDefs.gateControlStatsAck) AND (b.pupID.b = packetNumber) => BEGIN gse: LONG POINTER TO GateControlDefs.GateControlStatsEntry; gse _ LOOPHOLE[@b.pupBody]; FOR i: CARDINAL IN [0..gse.versionText.length) DO String.AppendChar[info.text, gse.versionText.char[i]]; ENDLOOP; AppendUpTime[info.text, gse.startTime]; GOTO Up; END; ENDCASE => NULL; ReturnFreePupBuffer[b]; b _ NIL; ENDLOOP; REPEAT Rejecting => info.state _ rejecting; Up => info.state _ up; FINISHED => info.state _ timeout; ENDLOOP; IF b # NIL THEN ReturnFreePupBuffer[b]; PupSocketDestroy[mySoc]; END; AppendUpTime: PROCEDURE [s: STRING, startTime: InlineDefs.BcplLongNumber] = BEGIN now, then: LONG INTEGER; sec: LONG INTEGER; min: LONG INTEGER; hours: LONG INTEGER; String.AppendString[s, " up "L]; then _ InlineDefs.BcplToMesaLongNumber[startTime]; now _ Time.Current[]; sec _ now - then; IF sec < 0 THEN BEGIN -- Startup glitch sec _ -sec; String.AppendChar[s, '-]; END; hours _ sec/3600; sec _ sec - hours*3600; min _ sec/60; sec _ sec - min*60; String.AppendLongNumber[s, hours, 10]; String.AppendChar[s, ':]; IF min < 10 THEN String.AppendChar[s, '0]; String.AppendLongNumber[s, min, 10]; String.AppendChar[s, ':]; IF sec < 10 THEN String.AppendChar[s, '0]; String.AppendLongNumber[s, sec, 10]; END; PokeChat: PUBLIC PROCEDURE [info: Info] = BEGIN sh: Stream.Handle _ NIL; state: HostWatcherOps.State _ up; BEGIN ENABLE BEGIN PupStream.StreamClosing => BEGIN IF text # NIL THEN String.AppendString[info.text, text]; SELECT why FROM transmissionTimeout => state _ timeout; remoteReject => state _ rejecting; ENDCASE => BEGIN LookAtThis: SIGNAL = CODE; IF debug THEN SIGNAL LookAtThis; state _ unknown; END; IF CheckForFull[info.text] THEN state _ full; CONTINUE; END; Stream.TimeOut => {state _ timeout; CONTINUE; } END; sh _ PupStream.PupByteStreamCreate[info.address, PupDefs.veryLongWait]; IF sh # NIL THEN BEGIN DO c: CHARACTER _ Stream.GetChar[sh]; IF c = Ascii.LF THEN LOOP; IF c = Ascii.CR THEN {IF info.text.length = 0 THEN LOOP ELSE EXIT; }; String.AppendChar[info.text, c]; ENDLOOP; Stream.Delete[sh]; END; END; info.state _ state; END; CheckForFull: PROCEDURE [text: STRING] RETURNS [full: BOOLEAN] = BEGIN IF String.EquivalentString[text, "RFC Refused"L] THEN RETURN[TRUE]; -- Alto: FTP.run IF String.EquivalentString[text, "Server full, try again later"L] THEN RETURN[TRUE]; -- Maxc IF String.EquivalentString[text, "No dial-out lines available"L] THEN RETURN[TRUE]; -- DLS IF String.EquivalentString[text, "Server is full"L] THEN RETURN[TRUE]; -- Juniper IF String.EquivalentString[text, "IFS is full - try later"L] THEN RETURN[TRUE]; IF String.EquivalentString[text, "Server full"L] THEN RETURN[TRUE]; -- Grapevine IF String.EquivalentString[text, "Sorry, we are full now"L] THEN RETURN[TRUE]; -- Gateway RETURN[FALSE]; END; PokeFtp: PUBLIC PROCEDURE [info: Info] = BEGIN OPEN FTPDefs; ftpUser: FTPUser _ NIL; state: HostWatcherOps.State _ up; FTPInitialize[]; ftpUser _ FTPCreateUser[SomeFilePrimitives[], PupCommunicationPrimitives[]]; FTPOpenConnection[ ftpUser, info.name, files, info.text ! FTPError => BEGIN IF message # NIL THEN String.AppendString[info.text, message]; SELECT ftpError FROM connectionTimedOut => state _ timeout; connectionRejected => state _ rejecting; ENDCASE => BEGIN LookAtThis: SIGNAL = CODE; IF debug THEN SIGNAL LookAtThis; state _ unknown; END; IF CheckForFull[info.text] THEN state _ full; CONTINUE; END]; info.state _ state; FTPDestroyUser[ftpUser ! FTPError => CONTINUE]; FTPFinalize[]; END; PokeMail: PUBLIC PROCEDURE [info: Info] = BEGIN OPEN FTPDefs; ftpUser: FTPUser _ NIL; state: HostWatcherOps.State _ up; FTPInitialize[]; ftpUser _ FTPCreateUser[NIL, PupCommunicationPrimitives[]]; FTPOpenConnection[ ftpUser, info.name, mail, info.text ! FTPError => BEGIN IF message # NIL THEN String.AppendString[info.text, message]; SELECT ftpError FROM connectionTimedOut => state _ timeout; connectionRejected => state _ rejecting; ENDCASE => BEGIN LookAtThis: SIGNAL = CODE; IF debug THEN SIGNAL LookAtThis; state _ unknown; END; IF CheckForFull[info.text] THEN state _ full; CONTINUE; END]; info.state _ state; FTPDestroyUser[ftpUser ! FTPError => CONTINUE]; FTPFinalize[]; END; PokeLibrarian: PUBLIC PROCEDURE [info: Info] = BEGIN OPEN Librarian, LibrarianPN, LibrarianOps; request: LibjectMessageType = FindID; b: PupBuffer; message: LONG POINTER TO LibjectMessage; plist: LONG POINTER TO ARRAY [0..2) OF PropertyPair; transactionID: CARDINAL _ NextSequenceNumber[]; socket: PupSocket; socket _ PupSocketMake[fillInSocketID, info.address, SecondsToTocks[15]]; FOR i: CARDINAL IN [0..5) DO b _ GetFreePupBuffer[]; b.pupID _ [transactionID, i]; message _ LOOPHOLE[@b.pupWords]; message.id _ transactionID; message.password _ ValidLibrarianMessage; message.type _ request; message.plist _ DESCRIPTOR[NIL, 2]; plist _ LOOPHOLE[message + SIZE[LibjectMessage]]; message.nextfree _ LOOPHOLE[SIZE[LibjectMessage] + 2*SIZE[PropertyPair]]; BEGIN COPY: PROCEDURE [from: POINTER, nwords: CARDINAL, to: LONG POINTER] = BEGIN FOR i: CARDINAL IN [0..nwords) DO (to + i)^ _ (from + i)^; ENDLOOP; END; string: STRING = "HostWatcher"L; wordsforstring: CARDINAL = String.WordsForString[string.length]; dataArea: LONG POINTER _ message + LOOPHOLE[message.nextfree, CARDINAL]; plist[0] _ PropertyPair[ empty: FALSE, pn: StringName, body: String[ length: string.length, string: LOOPHOLE[2*SIZE[PropertyPair]]]]; COPY[from: string, nwords: wordsforstring, to: dataArea]; message.nextfree _ message.nextfree + wordsforstring; END; plist[1] _ PropertyPair[empty: TRUE, pn: IDName, body: TwoWord[[lc[0]]]]; SetPupContentsWords[b, LOOPHOLE[message.nextfree, INTEGER]]; socket.put[b]; UNTIL (b _ socket.get[]) = NIL DO message _ LOOPHOLE[@b.pupWords]; SELECT TRUE FROM (b.pupType = error AND b.errorCode = noProcessPupErrorCode) => BEGIN i: CARDINAL; FOR i IN [0..GetPupContentsBytes[b] - 2*(10 + 1 + 1)) DO String.AppendChar[info.text, b.errorText[i]]; ENDLOOP; HostWatcherOps.ShowErrorPup[b]; GOTO Rejecting; END; (b.pupType = error) => HostWatcherOps.ShowErrorPup[b]; message.password = ValidLibrarianMessage AND message.id = transactionID => GOTO Up; ENDCASE => NULL; -- I wonder what this is ReturnFreePupBuffer[b]; b _ NIL; ENDLOOP; REPEAT Rejecting => info.state _ rejecting; Up => info.state _ up; FINISHED => info.state _ timeout; ENDLOOP; IF b # NIL THEN ReturnFreePupBuffer[b]; PupSocketDestroy[socket]; END; PokeSpruce: PUBLIC PROCEDURE [info: Info] = BEGIN spruceStatusRequest: PupType = LOOPHOLE[200B]; spruceStatusReply: PupType = LOOPHOLE[201B]; b: PupBuffer _ NIL; packetNumber: CARDINAL _ NextSequenceNumber[]; mySoc: PupSocket _ PupSocketMake[ fillInSocketID, info.address, SecondsToTocks[5]]; THROUGH [0..20) DO b _ GetFreePupBuffer[]; b.pupID.a _ b.pupID.b _ packetNumber; b.pupType _ spruceStatusRequest; SetPupContentsWords[b, 0]; mySoc.put[b]; UNTIL (b _ mySoc.get[]) = NIL DO SELECT TRUE FROM (b.pupType = error AND b.errorCode = noProcessPupErrorCode) => BEGIN FOR i: CARDINAL IN [0..GetPupContentsBytes[b] - 2*(10 + 1 + 1)) DO String.AppendChar[info.text, b.errorText[i]]; ENDLOOP; HostWatcherOps.ShowErrorPup[b]; GOTO Rejecting; END; (b.pupType = error) => HostWatcherOps.ShowErrorPup[b]; ((b.pupType # spruceStatusReply) OR (b.pupID.a # packetNumber) OR (b.pupID.b # packetNumber)) => NULL; ENDCASE => BEGIN FOR i: CARDINAL IN [2..GetPupContentsBytes[b] - 1) DO c: CHARACTER _ b.pupChars[i]; IF c = Ascii.CR THEN c _ Ascii.SP; String.AppendChar[info.text, c]; ENDLOOP; SELECT b.pupWords[0] FROM 1 => GOTO Down; -- Not Spooling 2 => GOTO Up; -- Spooler is idle 3 => GOTO Up; -- Spooler is busy ENDCASE => NULL; GOTO Up; END; ReturnFreePupBuffer[b]; b _ NIL; ENDLOOP; REPEAT Rejecting => info.state _ rejecting; Down => info.state _ down; Up => info.state _ up; FINISHED => info.state _ timeout; ENDLOOP; IF b # NIL THEN ReturnFreePupBuffer[b]; PupSocketDestroy[mySoc]; END; PokeEftp: PUBLIC PROCEDURE [info: Info] = BEGIN b: PupBuffer _ NIL; mySoc: PupSocket _ PupSocketMake[ fillInSocketID, info.address, SecondsToTocks[5]]; THROUGH [0..20) DO b _ GetFreePupBuffer[]; b.pupID.a _ b.pupID.b _ 0; b.pupType _ eData; SetPupContentsWords[b, 0]; mySoc.put[b]; UNTIL (b _ mySoc.get[]) = NIL DO SELECT TRUE FROM (b.pupType = eAbort) => BEGIN FOR i: CARDINAL IN [0..GetPupContentsBytes[b] - 2) DO String.AppendChar[info.text, b.pupChars[i + 2]]; ENDLOOP; GOTO Rejecting; END; (b.pupType = error AND b.errorCode = noProcessPupErrorCode) => BEGIN FOR i: CARDINAL IN [0..GetPupContentsBytes[b] - 2*(10 + 1 + 1)) DO String.AppendChar[info.text, b.errorText[i]]; ENDLOOP; HostWatcherOps.ShowErrorPup[b]; GOTO Rejecting; END; (b.pupType = error) => HostWatcherOps.ShowErrorPup[b]; ((b.pupType = eAck) AND (b.pupID.a = 0) AND (b.pupID.b = 0)) => GOTO Up; ENDCASE => HostWatcherOps.ShowErrorPup[b]; ReturnFreePupBuffer[b]; b _ NIL; ENDLOOP; REPEAT Rejecting => info.state _ rejecting; Up => info.state _ up; FINISHED => info.state _ timeout; ENDLOOP; IF b # NIL THEN ReturnFreePupBuffer[b]; PupSocketDestroy[mySoc]; END; sequenceNumber: CARDINAL _ 0; NextSequenceNumber: PROCEDURE RETURNS [CARDINAL] = BEGIN RETURN[sequenceNumber _ sequenceNumber + 1]; END; END.