-- File: PtEcho.mesa, Last Edit: HGM November 19, 1979 12:00 PM DIRECTORY IODefs: FROM "IODefs" USING [CR, WriteChar], ProcessDefs: FROM "ProcessDefs" USING [Detach, Yield, Abort, Aborted], StatsDefs: FROM "StatsDefs" USING [StatBump, StatIncr], PupDefs: FROM "PupDefs" USING [ GetFreePupBuffer, ReturnFreePupBuffer, PupBuffer, PupSocket, PupSocketDestroy, PupSocketMake, PrintErrorPup, SecondsToTocks, SetPupContentsBytes, GetPupContentsBytes, veryLongWait], PupTypes: FROM "PupTypes" USING [ PupAddress, fillInPupAddress, fillInSocketID, echoSoc], PtDefs: FROM "PtDefs" USING [ PtLookerReady, Done, WaitUntilDone, CursorBits, echoIndex, lostIndex, recvIndex, sendIndex, PtInterface, Random]; PtEcho: PROGRAM [pt: PtDefs.PtInterface] IMPORTS IODefs, ProcessDefs, StatsDefs, PupDefs, PtDefs EXPORTS PtDefs = BEGIN OPEN pt, IODefs, StatsDefs, PupDefs, PupTypes, PtDefs; PtEchoer: PUBLIC PROCEDURE = BEGIN PtLookerReady[]; ProcessDefs.Detach[FORK PtEchoit[]]; WaitUntilDone[1]; END; PtEchoit: PROCEDURE = BEGIN l, k: CARDINAL; b: PupBuffer; r: CARDINAL _ 0; cycle: CARDINAL; where: PupAddress _ [pushHim.net,pushHim.host,echoSoc]; packetNumber: CARDINAL _ 0; mySoc: PupSocket _ PupSocketMake[fillInSocketID,where,SecondsToTocks[2]]; SELECT length FROM -- can't use zero short => l_1; cyclic => l_1; -- start at short long, ignore => l_dataWordsPerPup; random => NULL; ENDCASE => ERROR; UNTIL stopFlag DO cycle _ 0; UNTIL stopFlag DO b _ GetFreePupBuffer[]; SELECT length FROM short, long, ignore => NULL; cyclic => l_cycle; random => l_((r_Random[r]) MOD dataWordsPerPup*2)+1; ENDCASE => ERROR; SELECT data FROM ignore => NULL; cyclic => FOR k IN [0..l) DO b.pupBytes[k]_k+cycle; ENDLOOP; ones => FOR k IN [0..l) DO b.pupBytes[k]_377B; ENDLOOP; zeros => FOR k IN [0..l) DO b.pupBytes[k]_0; ENDLOOP; alternating => FOR k IN [0..l) DO b.pupBytes[k]_252B; ENDLOOP; random => FOR k IN [0..l) DO b.pupBytes[k]_(r_Random[r]); ENDLOOP; ENDCASE => ERROR; b.pupID.a_b.pupID.b _ (packetNumber_packetNumber+1); b.pupType _ echoMe; SetPupContentsBytes[b,l]; StatIncr[statDataPacketsSent]; StatBump[statDataBytesSent,l]; mySoc.put[b]; CursorBits[sendIndex] _ CursorBits[sendIndex]+1; UNTIL (b_mySoc.get[])=NIL DO SELECT TRUE FROM (b.pupType=error) => BEGIN PrintErrorPup[b]; END; ((b.pupType#iAmEcho) OR (b.pupID.a#packetNumber) OR (b.pupID.b#packetNumber) OR (l#GetPupContentsBytes[b])) => WriteChar['#]; ENDCASE => BEGIN SELECT data FROM ignore => NULL; cyclic => FOR k IN [0..l) DO IF b.pupBytes[k]#((k+cycle) MOD 400B) THEN WriteChar['~]; ENDLOOP; ones => FOR k IN [0..l) DO IF b.pupBytes[k]#377B THEN WriteChar['~]; ENDLOOP; zeros => FOR k IN [0..l) DO IF b.pupBytes[k]#0 THEN WriteChar['~]; ENDLOOP; alternating => FOR k IN [0..l) DO IF b.pupBytes[k]#252B THEN WriteChar['~]; ENDLOOP; random => FOR k IN [0..l) DO IF b.pupBytes[k]#((r_Random[r]) MOD 400B) THEN WriteChar['~]; ENDLOOP; ENDCASE => ERROR; IF info THEN WriteChar['!]; StatIncr[statDataPacketsReceived]; StatBump[statDataBytesReceived,l]; CursorBits[recvIndex] _ CursorBits[recvIndex]+1; EXIT; END; ReturnFreePupBuffer[b]; ENDLOOP; IF b#NIL THEN ReturnFreePupBuffer[b] ELSE BEGIN CursorBits[lostIndex] _ CursorBits[lostIndex]+1; WriteChar['?]; LOOP; -- Try same packet again, thats why the funny control structure END; cycle _ cycle+1; IF cycle>dataWordsPerPup*2 THEN EXIT; ENDLOOP; WriteChar[CR]; ENDLOOP; PupSocketDestroy[mySoc]; Done[]; END; -- Echo Server echoFork: PROCESS; echoSocket: PupSocket _ NIL; echoStop: BOOLEAN; PtEchoOn: PUBLIC PROCEDURE = BEGIN echoStop _ FALSE; echoSocket _ PupSocketMake[ echoSoc, fillInPupAddress, veryLongWait]; echoFork _ FORK PtEchoServer[]; ProcessDefs.Yield[]; -- let it get started to avoid Abort BUG END; PtEchoOff: PUBLIC PROCEDURE = BEGIN echoStop _ TRUE; ProcessDefs.Abort[echoFork]; JOIN echoFork[]; PupSocketDestroy[echoSocket]; echoSocket _ NIL; END; PtEchoServer: PROCEDURE = BEGIN b: PupBuffer; UNTIL echoStop DO IF (b_echoSocket.get[ ! ProcessDefs.Aborted => EXIT])#NIL THEN BEGIN IF b.pupType#echoMe THEN BEGIN WriteChar['^]; ReturnFreePupBuffer[b]; LOOP; END; IF info THEN WriteChar['$]; echoSocket.setRemoteAddress[b.source]; b.pupType _ iAmEcho; echoSocket.put[b]; CursorBits[echoIndex] _ CursorBits[echoIndex]+1; END; ENDLOOP; END; -- initialization END.(0,65535)(1,3528)(2,4057)(9,12347)\720t7 4t0 7t7 11t0 90t7 2t2 2t0 1481t2 6t0 5t2 6t0 78t2 6t0 1335t2 19t0 9t2 15t0 9t2 5t0 53t2 9t0 52t2 9t0 29t2 19t0 9t2 15t0 9t2 5t0