-- Copyright (C) 1981, 1984, 1985 by Xerox Corporation. All rights reserved.
-- OthelloPup.mesa, HGM, 10-Mar-85 5:51:08
-- File: OthelloPup.mesa, Last Edit: HGM May 22, 1979 10:35 PM
-- File: OthelloPup.mesa, Last Edit: Fay/BLyon August 21, 1980 3:42 PM
-- File: OthelloPup.mesa, Last Edit: BLyon August 29, 1980 9:21 AM
-- File: OthelloPup.mesa, Last Edit: ?? 25-Nov-81 13:22:47
-- File: OthelloPup.mesa, Last Edit: Fay 17-Dec-81 14:22:18
DIRECTORY
Process USING [Detach, Pause, Yield],
Buffer USING [GetBuffer, ReturnBuffer],
Driver USING [Network],
OthelloDefs,
PupDefs USING [
AppendPupAddress, DataWordsPerPupBuffer, GetPupAddress,
GetPupContentsBytes, PupBuffer, PupNameTrouble,
PupPackageDestroy, PupPackageMake, PupSocket, PupSocketDestroy,
PupSocketMake, SecondsToTocks, SetPupContentsBytes, veryShortWait],
PupRouterDefs USING [GetRoutingTable, RoutingTableEntry, RoutingTableObject],
PupPktOps USING [pupBuffers],
PupTypes USING [echoSoc, fillInSocketID, maxDataWordsPerGatewayPup, PupAddress];
OthelloPup: PROGRAM
IMPORTS Process,Buffer, PupDefs, PupRouterDefs, PupPktOps, OthelloDefs =
BEGIN OPEN OthelloDefs;
PrintErrorPup: PROCEDURE [b: PupDefs.PupBuffer] =
BEGIN
source: PupTypes.PupAddress ← b.pup.source;
NewLine[];
IF b.pup.pupType = error THEN
BEGIN
len: CARDINAL = PupDefs.GetPupContentsBytes[b];
WriteString["[Error Pup, code="L];
WriteOctal[LOOPHOLE[b.pup.errorCode]];
WriteString[", from: "L];
PrintPupAddress[@source];
WriteString["] "L];
FOR i: CARDINAL IN [0..len - 2*(10 + 1 + 1)) DO
WriteChar[b.pup.errorText[i]] ENDLOOP;
END
ELSE
BEGIN
WriteString[" ***** "L];
WriteString["Funny PupType = "L];
WriteOctal[LOOPHOLE[b.pup.pupType]];
WriteString[" ***** "L];
END;
NewLine[];
END;
EchoUser: PROCEDURE =
BEGIN OPEN PupDefs, PupTypes;
bytesPerBuffer: CARDINAL;
funny, late: LONG CARDINAL ← 0;
recv, sent: LONG CARDINAL ← 0;
wrong: LONG CARDINAL ← 0;
me, where: PupAddress ← [, , echoSoc];
mySoc: PupSocket;
packetNumber: CARDINAL ← 0;
routing: PupRouterDefs.RoutingTableEntry;
pleaseStop: BOOLEAN ← FALSE;
Watch: PROCEDURE =
BEGIN
[] ← ReadChar[ ! ABORTED => CONTINUE];
pleaseStop ← TRUE;
END;
GetName["Echo to: "L, @echoName];
GetPupAddress[
@where, echoName ! PupNameTrouble => AbortingCommand[e]];
routing ← @PupRouterDefs.GetRoutingTable[][where.net];
IF routing=NIL OR routing.network = NIL THEN AbortingCommand["Can't reach that network"L];
mySoc ← PupSocketMake[fillInSocketID, where, SecondsToTocks[5]];
me ← mySoc.getLocalAddress[];
PrintPupAddress[@me];
WriteString[" => "L];
IF routing.hop # 0 THEN {
WriteOctal[routing.network.pupNetNumber]; WriteChar['#];
WriteOctal[routing.route]; WriteChar['#]; WriteString[" => "L]};
PrintPupAddress[@where];
NewLine[];
Process.Detach[FORK Watch[]];
bytesPerBuffer ← 2*MIN[DataWordsPerPupBuffer[], maxDataWordsPerGatewayPup];
UNTIL pleaseStop DO
FOR len: CARDINAL IN [0..bytesPerBuffer] UNTIL pleaseStop DO
b: PupBuffer;
b ← Buffer.GetBuffer[pup, PupPktOps.pupBuffers, send, fullBuffer];
b.pup.pupID.a ← b.pup.pupID.b ← (packetNumber ← packetNumber + 1);
b.pup.pupType ← echoMe;
SetPupContentsBytes[b, len];
FOR i: CARDINAL IN [0..len) DO b.pup.pupBytes[i] ← i ENDLOOP;
mySoc.put[b];
sent ← sent + 1;
Process.Yield[]; -- be sure we don't hog machine
UNTIL (b ← mySoc.get[]) = NIL DO
SELECT TRUE FROM
(b.pup.pupType # iAmEcho) => {funny ← funny + 1; PrintErrorPup[b]};
((b.pup.pupID.a # packetNumber) OR (b.pup.pupID.b # packetNumber)
OR (len # GetPupContentsBytes[b])) => {
WriteChar['#]; late ← late + 1};
ENDCASE => {
FOR i: CARDINAL IN [0..len) DO
IF b.pup.pupBytes[i] # (i MOD 400B) THEN {
wrong ← wrong + 1; WriteChar['~]; GOTO Wrong};
ENDLOOP;
WriteChar['!];
recv ← recv + 1;
EXIT};
Buffer.ReturnBuffer[b];
REPEAT Wrong => NULL;
ENDLOOP;
IF b # NIL THEN Buffer.ReturnBuffer[b] ELSE WriteChar['?];
ENDLOOP;
NewLine[];
ENDLOOP;
PupSocketDestroy[mySoc];
WriteLine["."L];
WriteString["Out: "L];
WriteLongNumber[sent];
WriteString[", In: "L];
WriteLongNumber[recv];
WriteString[" ("L];
WriteLongNumber[(recv*100)/sent];
WriteLine["%)"L];
IF late # 0 THEN
BEGIN
WriteString["Late: "L];
WriteLongNumber[late];
WriteString[" ("L];
WriteLongNumber[(late*100)/sent];
WriteLine["%)"L];
END;
IF funny # 0 THEN
BEGIN
WriteLongNumber[funny];
WriteLine[" funny"L];
END;
IF wrong # 0 THEN
BEGIN
WriteLongNumber[wrong];
WriteLine[" wrong data"L];
END;
END;
PupSender: PROCEDURE =
BEGIN OPEN PupDefs, PupTypes;
bytesPerBuffer: CARDINAL;
me, where: PupAddress ← [, , echoSoc];
mySoc: PupSocket;
sent, echo, full, other: LONG CARDINAL ← 0;
routing: PupRouterDefs.RoutingTableEntry;
pleaseStop: BOOLEAN ← FALSE;
Watch: PROCEDURE =
BEGIN
[] ← ReadChar[ ! ABORTED => CONTINUE];
pleaseStop ← TRUE;
END;
GetName["Send to: "L, @echoName];
GetPupAddress[
@where, echoName ! PupNameTrouble => AbortingCommand[e]];
routing ← @PupRouterDefs.GetRoutingTable[][where.net];
IF routing=NIL OR routing.network = NIL THEN AbortingCommand["Can't reach that network"L];
mySoc ← PupSocketMake[fillInSocketID, where, PupDefs.veryShortWait];
me ← mySoc.getLocalAddress[];
PrintPupAddress[@me];
WriteString[" => "L];
IF routing.hop # 0 THEN
BEGIN
WriteOctal[routing.network.pupNetNumber]; WriteChar['#];
WriteOctal[routing.route]; WriteChar['#]; WriteString[" => "L];
END;
PrintPupAddress[@where];
NewLine[];
Process.Detach[FORK Watch[]];
bytesPerBuffer ← 100;
UNTIL pleaseStop DO
b: PupBuffer;
FOR i: CARDINAL IN [0..3) DO
b ← Buffer.GetBuffer[pup, PupPktOps.pupBuffers, send, fullBuffer];
b.pup.pupID.a ← b.pup.pupID.b ← i;
b.pup.pupType ← echoMe;
FOR i: CARDINAL IN [0..bytesPerBuffer) DO b.pup.pupBytes[i] ← i; ENDLOOP;
SetPupContentsBytes[b, bytesPerBuffer];
mySoc.put[b];
sent ← sent + 1;
IF (sent MOD 100) = 0 THEN BEGIN WriteChar['s]; Process.Pause[1]; END;
ENDLOOP;
UNTIL (b ← mySoc.get[]) = NIL DO
IF b.pup.pupType = iAmEcho THEN
BEGIN
echo ← echo + 1;
IF (echo MOD 100) = 0 THEN WriteChar['r];
END
ELSE
BEGIN
IF b.pup.pupType = error AND b.pup.errorCode # resourceLimitsPupErrorCode THEN
BEGIN
other ← other + 1;
PrintErrorPup[b];
END
ELSE full ← full + 1;
END;
Buffer.ReturnBuffer[b];
b ← NIL;
ENDLOOP;
Process.Yield[]; -- be sure we don't hog machine
ENDLOOP;
NewLine[];
WriteString["Sent: "L];
WriteLongNumber[sent];
WriteString[", Echoed: "L];
WriteLongNumber[echo];
IF full # 0 THEN
BEGIN
WriteString[", BufferFull: "L];
WriteLongNumber[full];
END;
IF other # 0 THEN
BEGIN
WriteString[", Other: "L];
WriteLongNumber[other];
END;
WriteLine["."L];
PupSocketDestroy[mySoc];
END;
PrintLocalPupRoutingTable: PROCEDURE =
BEGIN
pupRt: LONG DESCRIPTOR FOR ARRAY OF PupRouterDefs.RoutingTableObject;
k: CARDINAL ← 0;
WriteLine["| Net Via Hops | Net Via Hops | Net Via Hops | Net Via Hops |"L];
WriteLine["|-----------------|-----------------|-----------------|-----------------|"L];
pupRt ← PupRouterDefs.GetRoutingTable[];
FOR i: CARDINAL IN [0..LENGTH[pupRt]) DO
D3: PROC [n: CARDINAL] = INLINE {WriteFixedWidthNumber[n, 3, 10]};
O4: PROC [n: CARDINAL] = INLINE {WriteFixedWidthNumber[n, 4, 8]};
O3Z: PROC [n: CARDINAL] = {
n ← n MOD 1000B;
THROUGH [0..3) DO WriteChar['0 + (n/100B) MOD 10B]; n ← n*10B ENDLOOP};
r: PupRouterDefs.RoutingTableEntry = @pupRt[i];
network: Driver.Network = r.network;
OthelloDefs.CheckUserAbort[! ABORTED => EXIT];
IF network = NIL THEN LOOP;
IF k = 0 THEN WriteChar['|];
O4[i]; O4[network.pupNetNumber];
WriteChar['#];
O3Z[IF r.hop # 0 THEN r.route ELSE network.pupHostNumber];
WriteChar['#];
D3[r.hop]; WriteString[" |"L];
IF (k ← k + 1) = 4 THEN BEGIN NewLine[]; k ← 0; Process.Yield[]; END;
ENDLOOP;
IF k # 0 THEN NewLine[];
END;
PrintPupAddress: PROC [a: POINTER TO PupTypes.PupAddress] = {
buffer: STRING ← [50];
PupDefs.AppendPupAddress[buffer, a↑]; WriteString[buffer]};
echoName: LONG STRING ← NIL;
Commands: PROC [index: CARDINAL] =
BEGIN
SELECT index FROM
0 => {
MyNameIs[myNameIs: "Pup Echo User"L, myHelpIs: "Pup echo user"L];
PupDefs.PupPackageMake[];
EchoUser[! UNWIND => PupDefs.PupPackageDestroy[]]};
1 => {
MyNameIs[myNameIs: "Pup Sender"L, myHelpIs: "Send Pups rapidly"L];
PupDefs.PupPackageMake[];
PupSender[! UNWIND => PupDefs.PupPackageDestroy[]]};
2 => {
MyNameIs[
myNameIs: "Pup Routing Tables"L,
myHelpIs: "Show pup network routing tables"L];
PupDefs.PupPackageMake[];
PrintLocalPupRoutingTable[! UNWIND => PupDefs.PupPackageDestroy[]]};
ENDCASE => IndexTooLarge;
PupDefs.PupPackageDestroy[];
END;
commandProcessor: CommandProcessor ← [Commands];
RegisterCommandProc[@commandProcessor];
END.....