-- File: PtSocket.mesa, Last Edit: HGM November 19, 1979 12:03 PM DIRECTORY InlineDefs: FROM "InlineDefs" USING [COPY], IODefs: FROM "IODefs" USING [WriteChar, WriteDecimal, WriteLine, WriteOctal, WriteString], ProcessDefs: FROM "ProcessDefs" USING [Detach, Yield, Abort, Aborted], StatsDefs: FROM "StatsDefs" USING [StatBump, StatIncr, StatCounterIndex], PupDefs: FROM "PupDefs" USING [ GetFreePupBuffer, ReturnFreePupBuffer, PupAddress, PupBuffer, PupSocket, PupSocketDestroy, PupSocketMake, PrintErrorPup, SecondsToTocks, SetPupContentsWords, veryLongWait], PupTypes: FROM "PupTypes" USING [fillInPupAddress, statisticsAre, statisticsRequest, statSoc], BufferDefs: FROM "BufferDefs" USING [ReturnFreeBuffer, Buffer], PtDefs: FROM "PtDefs" USING [ CursorBits, echoIndex, lostIndex, recvIndex, sendIndex, turnIndex, packetCycle, PtInterface, PtLookerReady, Random, statRawPacketsEarly, statRawPacketsLate, statRawPacketsMissed, statRawPacketsRecv, statRawPacketsSent, statRawPacketsTurnedBack, statRawPacketsUnexpected, SeeStorms, Done, WaitUntilDone]; PtSocket: PROGRAM [pt: PtDefs.PtInterface] IMPORTS InlineDefs, IODefs, ProcessDefs, BufferDefs, StatsDefs, PupDefs, PtDefs EXPORTS PtDefs = BEGIN OPEN pt, IODefs, StatsDefs, PupDefs, PtDefs; hardWay: BOOLEAN _ FALSE; -- patch via debugger pushSock: PupSocket _ NIL; pullSock: PupSocket _ NIL; Header: PROCEDURE [s, t: STRING, remote: POINTER TO PupAddress] = BEGIN WriteString[s]; SELECT length FROM short => WriteString[" short"]; long => WriteString[" long"]; random => WriteString[" random length"]; cyclic => WriteString[" cyclic length"]; ignore => WriteString[" unknown length"]; ENDCASE => ERROR; WriteString[" pups"]; IF remote.host=myHost AND remote.net=myNet THEN WriteString[" locally"] ELSE BEGIN WriteString[" "]; WriteString[t]; IF remote.net#myNet THEN BEGIN WriteString[" net "]; WriteOctal[remote.net] END; WriteString[" host "]; WriteOctal[remote.host]; END; WriteLine["."]; SeeStorms[]; END; EatUnexpectedPups: PROCEDURE [soc: PupSocket, stop: POINTER TO BOOLEAN] = BEGIN b: PupBuffer; UNTIL stop^ DO b _ soc.get[]; IF b#NIL THEN BEGIN PrintErrorPup[b]; ReturnFreePupBuffer[b]; END; ENDLOOP; END; RequeueProc: PROCEDURE [b: BufferDefs.Buffer] = BEGIN BufferDefs.ReturnFreeBuffer[b]; END; Echo: PROCEDURE = BEGIN l: CARDINAL; b: PupBuffer; r: CARDINAL _ 0; packetNumber: CARDINAL _ 0; stop: BOOLEAN _ FALSE; eat: PROCESS _ FORK EatUnexpectedPups[pushSock,@stop]; 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 FOR pushI IN [0..packetCycle) UNTIL stopFlag DO b _ GetFreePupBuffer[]; SELECT length FROM short, long, ignore => NULL; cyclic => l_pushI; random => l_((r_Random[r]) MOD dataWordsPerPup)+1; ENDCASE => ERROR; SetPupContentsWords[b,l]; b.pupID.a_b.pupID.b _ (packetNumber_packetNumber+1); StatIncr[statDataPacketsSent]; StatBump[statDataBytesSent,b.pupLength-22]; pushSock.put[b]; StatIncr[statRawPacketsSent]; UNTIL (b_pullSock.get[])=NIL DO SELECT TRUE FROM (b.pupType#data) => WriteChar['E]; (b.source#pullHim) => WriteChar['A]; (b.pupID.b=packetNumber) => BEGIN StatIncr[statDataPacketsReceived]; StatBump[statDataBytesReceived,b.pupLength-22]; CursorBits[echoIndex] _ CursorBits[echoIndex]+1; StatIncr[statRawPacketsRecv]; EXIT; END; ENDCASE => StatIncr[statRawPacketsUnexpected]; ReturnFreePupBuffer[b]; ENDLOOP; IF b#NIL THEN ReturnFreePupBuffer[b] ELSE BEGIN CursorBits[lostIndex] _ CursorBits[lostIndex]+1; IF info THEN WriteChar['?]; END; ENDLOOP; CursorBits[sendIndex] _ CursorBits[sendIndex]+1; IF info THEN WriteChar['s]; ENDLOOP; stop _ TRUE; JOIN eat; PupSocketDestroy[pullSock]; PupSocketDestroy[pushSock]; pushSock _ pullSock _ NIL; Done[]; END; pushI: CARDINAL; -- global for debugging Push: PROCEDURE = BEGIN l: CARDINAL; b: PupBuffer; r: CARDINAL _ 0; packetNumber: CARDINAL _ 0; stop: BOOLEAN _ FALSE; eat: PROCESS _ FORK EatUnexpectedPups[pushSock,@stop]; 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 FOR pushI IN [0..packetCycle) UNTIL stopFlag DO b _ GetFreePupBuffer[]; SELECT length FROM short, long, ignore => NULL; cyclic => l_pushI; random => l_((r_Random[r]) MOD dataWordsPerPup)+1; ENDCASE => ERROR; SetPupContentsWords[b,l]; IF hardWay THEN b.requeueProcedure _ RequeueProc; b.pupID.a_b.pupID.b _ (packetNumber_packetNumber+1); StatIncr[statDataPacketsSent]; StatBump[statDataBytesSent,b.pupLength-22]; pushSock.put[b]; StatIncr[statRawPacketsSent]; CursorBits[sendIndex] _ CursorBits[sendIndex]+1; IF (pushI MOD 16)=0 THEN ProcessDefs.Yield[]; ENDLOOP; IF info THEN WriteChar['s]; ENDLOOP; stop _ TRUE; JOIN eat; PupSocketDestroy[pushSock]; pushSock _ NIL; Done[]; END;(0,65535)(1,3528)(2,4057)(9,12347)\1134t7 4t0 7t7 11t0 114t7 2t2 2t0 141b6B669b17B209b11B88b4B765t2 6t0 44t2 6t0 8t2 6t0 62t2 6t0 235t2 6t0 52t2 19t0 9t2 15t0 9t2 5t0 152t2 9t0 52t2 9t0 29t2 19t0 9t2 15t0 9t2 5t0 311t10 25t0 1b4B433t2 30t0 25t2 8t0 29t2 8t0 19t2 8t0 51t2 8t0 18t2 28t0 1t2 1t3 1t2 10t0 7t2 8t0 16t2 3t0 11t2 16t0 1t2 9t0 1t2 40t0 31t2 6t0 44t2 6t0 8t2 9t0 36t2 17t0 1t2 23t0 1t2 22t0 6t2 7t0 1t2 26t0 2t2 7t0 8t2 8t0 4t2 6t0 14t2 5t0 34t2 2t0 28t2 2t0 26t2 2t0 pullI: CARDINAL; -- global for debugging Pull: PROCEDURE = BEGIN b: PupBuffer; packetNumber: CARDINAL _ 0; i: INTEGER; pullI _ 1; UNTIL stopFlag DO UNTIL (b_pullSock.get[])=NIL DO SELECT TRUE FROM (b.pupType#data) => WriteChar['E]; (b.source#pullHim) => WriteChar['A]; ENDCASE => BEGIN i _ b.pupID.b-(packetNumber_packetNumber+1); StatIncr[statRawPacketsRecv]; SELECT i FROM =0 => BEGIN StatIncr[statDataPacketsReceived]; StatBump[statDataBytesReceived,b.pupLength-22]; CursorBits[recvIndex] _ CursorBits[recvIndex]+1; EXIT; END; IN (0..250] => BEGIN StatBump[statRawPacketsMissed,i]; StatIncr[statRawPacketsEarly]; IF info THEN BEGIN WriteChar['m]; IF i#1 THEN WriteDecimal[i]; END; CursorBits[lostIndex] _ CursorBits[lostIndex]+CARDINAL[i]; packetNumber _ b.pupID.b; END; IN [-250..0) => BEGIN StatIncr[statRawPacketsLate]; IF info THEN BEGIN IF i=-1 THEN WriteChar['D] ELSE BEGIN WriteChar['L]; WriteDecimal[-i]; END; END; packetNumber _ packetNumber-1; END; ENDCASE => BEGIN IF info THEN BEGIN WriteLine[""]; WriteLine["Packet number way out of range. Resyncing."]; END; packetNumber_b.pupID.b; EXIT; END; END; ReturnFreePupBuffer[b] ENDLOOP; IF b#NIL THEN ReturnFreePupBuffer[b] ELSE IF info THEN WriteChar['?]; IF (pullI_pullI+1)>packetCycle THEN BEGIN pullI _ 1; IF info THEN WriteChar['r]; END; ENDLOOP; PupSocketDestroy[pullSock]; pullSock _ NIL; Done[]; END;\18t10 25t0 1b4B136t2 6t0 170t2 7t0 1t2 30t0 52t2 13t0 14t2 4t0 15t2 5t0 126t2 11t0 9t2 15t0 9t2 3t0 16t2 4t0 16t2 3t0 14t2 14t0 15t2 5t0 108t2 3t0 4t2 5t0 17t2 5t0 17t2 14t0 17t2 28t0 17t2 4t0 15t2 11t0 9t2 15t0 9t2 1t0 12t2 1t0 15t2 12t0 4t2 7t0 1t2 1t0 15t2 4t0 13t2 15t0 79t2 3t0 4t2 5t0 17t2 5t0 17t2 26t0 17t2 48t0 17t2 4t0 15t2 12t0 3t2 15t0 15t2 4t0 58t2 3t0 4t2 5t0 17t2 5t0 17t2 14t0 17t2 57t0 17t2 4t0 15t2 13t0 1t2 7t0 1t2 1t0 35t2 3t0 33t2 9t0 47t2 9t0 117t2 3t0 4t2 6t0 Turnabout: PROCEDURE = BEGIN packetNumber: CARDINAL _ 0; b: PupBuffer; i: INTEGER; stop: BOOLEAN _ FALSE; eat: PROCESS _ FORK EatUnexpectedPups[pushSock,@stop]; pullI _ 1; UNTIL stopFlag DO IF (b_pullSock.get[])#NIL THEN BEGIN i _ b.pupID.b-(packetNumber_packetNumber+1); StatIncr[statRawPacketsTurnedBack]; SELECT i FROM =0 => BEGIN StatIncr[statDataPacketsReceived]; StatBump[statDataBytesReceived,b.pupLength-22]; END; IN (0..250] => BEGIN StatBump[statRawPacketsMissed,i]; StatIncr[statRawPacketsEarly]; IF info THEN BEGIN WriteChar['m]; IF i#1 THEN WriteDecimal[i]; END; CursorBits[lostIndex] _ CursorBits[lostIndex]+CARDINAL[i]; packetNumber _ b.pupID.b; END; IN [-250..0) => BEGIN StatIncr[statRawPacketsLate]; IF info THEN BEGIN IF i=-1 THEN WriteChar['D] ELSE BEGIN WriteChar['L]; WriteDecimal[-i]; END; END; packetNumber _ packetNumber-1; END; ENDCASE => BEGIN IF info THEN BEGIN WriteLine[""]; WriteLine["Packet number way out of range. Resyncing."]; END; packetNumber _ b.pupID.b; END; StatIncr[statDataPacketsSent]; StatBump[statDataBytesSent,b.pupLength-22]; pushSock.put[b]; CursorBits[turnIndex] _ CursorBits[turnIndex]+1; IF (pullI_pullI+1)>packetCycle THEN BEGIN pullI _ 1; CursorBits[recvIndex] _ CursorBits[recvIndex]+1; IF info THEN WriteChar['t]; END; END ELSE IF info THEN WriteChar['?]; ENDLOOP; stop _ TRUE; JOIN eat; PupSocketDestroy[pullSock]; PupSocketDestroy[pushSock]; pushSock _ pullSock _ NIL; Done[]; END;\2b9B255t2 7t0 1t2 30t0 46t2 17t0 3t2 38t0 33t2 1t0 61t2 12t0 3t2 20t0 3t2 13t0 3t2 8t0 36t2 8t0 33t2 11t0 4t2 5t0 3t2 15t0 3t2 24t0 3t2 38t0 3t2 14t0 3t2 19t0 9t2 15t0 9t2 1t0 12t2 1t0 3t2 20t0 4t2 7t0 1t2 1t0 3t2 12t0 3t2 21t0 3t2 8t0 48t2 11t0 4t2 5t0 3t2 15t0 3t2 36t0 3t2 58t0 3t2 14t0 3t2 20t0 3t2 15t0 3t2 12t0 22t2 8t0 8t2 11t0 4t2 5t0 3t2 15t0 3t2 24t0 3t2 67t0 3t2 14t0 3t2 20t0 4t2 7t0 1t2 1t0 3t2 11t0 4t2 4t0 31t2 6t0 58t2 5t0 1t2 2t0 7t2 11t0 9t2 15t0 9t2 3t0 86t2 11t0 9t2 15t0 -- statsistics via Network - lives here because its raw packet mode statsFork: PROCESS; statSocket: PupSocket _ NIL; statStop: BOOLEAN; PtStatsOn: PUBLIC PROCEDURE = BEGIN statStop _ FALSE; statSocket _ PupSocketMake[ PupTypes.statSoc, PupTypes.fillInPupAddress, veryLongWait]; statsFork _ FORK PtStatsSender[]; ProcessDefs.Yield[]; -- let it get started to avoid Abort BUG END; PtStatsOff: PUBLIC PROCEDURE = BEGIN statStop _ TRUE; ProcessDefs.Abort[statsFork]; JOIN statsFork[]; PupSocketDestroy[statSocket]; statSocket _ NIL; END; -- use the incomming buffer to send back the desired info PtStatsSender: PROCEDURE = BEGIN b: PupBuffer; size: CARDINAL = LOOPHOLE[LAST[StatsDefs.StatCounterIndex]]; UNTIL statStop DO IF (b_statSocket.get[ ! ProcessDefs.Aborted => EXIT])#NIL THEN BEGIN IF b.pupType=PupTypes.statisticsRequest THEN WriteChar['^] ELSE WriteChar['_]; statSocket.setRemoteAddress[b.source]; InlineDefs.COPY[to:@b.pupWords,from:NIL,nwords:size]; b.pupType _ PupTypes.statisticsAre; SetPupContentsWords[b,size]; statSocket.put[b]; END; ENDLOOP; END; PtSocEcho: PUBLIC PROCEDURE = BEGIN IF pullHim.socket=[0,0] OR pushMe.socket=[0,0] THEN BEGIN WriteLine["Need a SocketNumber."]; RETURN; END; Header["Echoing","from",@pushHim]; PtLookerReady[]; pushSock _ PupSocketMake[pushMe.socket,pushHim,SecondsToTocks[1]]; pullSock _ PupSocketMake[pullMe.socket,pullHim,SecondsToTocks[1]]; ProcessDefs.Detach[FORK Echo[]]; WaitUntilDone[1]; END; PtSocPushPull: PUBLIC PROCEDURE = BEGIN IF pullHim.socket=[0,0] OR pushMe.socket=[0,0] THEN BEGIN WriteLine["Need a SocketNumber."]; RETURN; END; Header["Exchanging","with",@pushHim]; PtLookerReady[]; pushSock _ PupSocketMake[pushMe.socket,pushHim,SecondsToTocks[1]]; pullSock _ PupSocketMake[pullMe.socket,pullHim,SecondsToTocks[1]]; ProcessDefs.Detach[FORK Pull[]]; ProcessDefs.Detach[FORK Push[]]; WaitUntilDone[2]; END; PtSocRecv: PUBLIC PROCEDURE = BEGIN IF pullHim.socket=[0,0] THEN BEGIN WriteLine["Need a SocketNumber."]; RETURN; END; Header["Receiving","from",@pullHim]; PtLookerReady[]; pullSock _ PupSocketMake[pullMe.socket,pullHim,SecondsToTocks[1]]; ProcessDefs.Detach[FORK Pull[]]; WaitUntilDone[1]; END; PtSocSend: PUBLIC PROCEDURE = BEGIN IF pushMe.socket=[0,0] THEN BEGIN WriteLine["Need a SocketNumber."]; RETURN; END; Header["Sending","to",@pushHim]; PtLookerReady[]; pushSock _ PupSocketMake[pushMe.socket,pushHim,SecondsToTocks[1]]; ProcessDefs.Detach[FORK Push[]]; WaitUntilDone[1]; END; PtSocTurnabout: PUBLIC PROCEDURE = BEGIN IF pullHim.socket=[0,0] OR pushMe.socket=[0,0] THEN BEGIN WriteLine["Need a SocketNumber."]; RETURN; END; Header["Turnabouting","to",@pushHim]; PtLookerReady[]; pushSock _ PupSocketMake[pushMe.socket,pushHim,SecondsToTocks[1]]; pullSock _ PupSocketMake[pullMe.socket,pullHim,SecondsToTocks[1]]; ProcessDefs.Detach[FORK Turnabout[]]; WaitUntilDone[1]; END; -- initialization END.\140b9B266b10B159b1B58b13B441t2 3t0 81b9B398b13B436b9B308b9B303b14B