-- File: PupErrors.mesa, Last Edit:
-- MAS April 17, 1980 8:43 PM
-- HGM October 24, 1979 8:30 PM

-- Copyright Xerox Corporation 1979, 1980

DIRECTORY
StatsDefs: FROM "StatsDefs" USING [StatIncr],
PupRouterDefs: FROM "PupRouterDefs" USING [SneakySendUnlocked],
PupStream: FROM "PupStream" USING [CloseReason],
PupDefs: FROM "PupDefs",
DriverDefs: FROM "DriverDefs" USING [
Glitch, doStats, doDebug, Network,
PutOnGlobalDoneQueue],
BufferDefs: FROM "BufferDefs", -- SHARES
PupTypes: FROM "PupTypes" USING [
allHosts, PupErrorCode, badChecksumPupErrorCode,
noProcessPupErrorCode, resourceLimitsPupErrorCode],
DriverTypes: FROM "DriverTypes" USING [bufferSeal];

PupErrors: PROGRAM
IMPORTS StatsDefs, PupRouterDefs, DriverDefs, PupDefs
EXPORTS PupRouterDefs, PupStream, PupDefs
SHARES BufferDefs =
BEGIN OPEN DriverDefs, Pup
Defs;

Network: TYPE = DriverDefs.Network;

-- PktStream/ByteStream SIGNALs live here
so they are defined only once
StreamClosing: PUBLIC ERROR [why: P
upStream.CloseReason, text: STRING] = CODE;
RejectThisRequest: PUBLIC ERROR [error: STRING] = CODE;


suppressErrors: BOOLEAN ← FALSE;
suppressBufferFull: BOOLEAN ← FALSE;

BufferSealBroken: PUBLIC ERROR = COD
E;
BufferDidntArriv
e: PUBLIC ERROR = CODE;

SetErrorSuppression: PUBLIC PROCEDURE [dontSendErrors: BOOLEAN] =
BEGIN

suppressErrors ← dont
SendErrors;
END;

SetBufferFullSuppression: PUBLIC PROCEDURE [dontSend: BOOLEAN] =
BEGI
N
suppressBufferFull ←
dontSend;
END;


RejectPupWithBadChecksum: PUBLIC PROCEDURE [b: PupBuffer] =
BEGIN
Reject[b
,PupTypes.badChecksumPupErrorCode];
END;

Reject: PUBLIC PROCEDURE [b: PupBuffer, code: PupTypes.PupErrorCode] =
BEGIN
IF BuildErrorPup[b,code,NIL] THEN P
upRouterDefs.SneakySendUnlocked[b];
END;

SendErrorPup: PUBLIC PROCEDURE [b: PupBuffer, code: PupTypes.PupErrorCode, text: STRING] =
BEGIN
IF BuildErrorPup[b,cod
e,text] THEN PupRouterSendThis[b];
END;

BuildErrorPup: PUBLIC PROCEDURE [
b: PupBuffer, code: PupTypes.PupErrorCode, text: STRING]
RETURNS [ok: BOOLEAN] =
BEGIN OPEN PupTypes;
i: CARDINAL;
p: POINTER TO ARRAY [0..9] OF WORD = LOOPHOLE[@b.pupLength];
temp: PupSocketID;
network: Network ← b.network;
IF doDebug AND b.seal#DriverTypes.bufferSeal THEN Glitch[BufferSealBroken];
IF suppressErrors OR (suppressBufferFull AND code=resourceLimitsPupErrorCode)
OR b.pupType=error OR b.dest.host=PupTypes.allHosts THEN
BEGIN DriverDefs.PutOnGlobalDoneQueue[b]; RETURN[FALSE]; END;
IF doDebug AND b.network=NIL THEN Glitch[BufferDidntArrive];
FOR i IN [0..9] DO b.errorHeader[i] ← p[i]; ENDLOOP;
b.pupType ← error;
b.errorCode ← code;
b.errorOptions ← 0;
temp ← b.dest.socket;
b.dest ← b.source;
b.source ← [[network.netNumber],[network.hostNumber],temp];
IF text=NIL THEN SELECT code FROM
badChecksumPupErrorCode => text ← "Bad Software Checksum"L;
noProcessPupErrorCode => text ← "No such Port"L;
resourceLimitsPupErrorCode => text ← "Buffers full"L;
ENDCASE => NULL;
IF text#NIL THEN
BEGIN
FOR i←0,i+1 UNTIL i=text.length DO b.errorText[i] ← text[i]; ENDLOOP;
END
ELSE i ← 0;
SetPupContentsBytes[b,2*(10+1+1)+i]; -- Yetch
IF doStats THEN StatsDefs.StatIncr[statErrorPupsSent];
RETURN[TRUE];
END;

-- initialization
END. -- PupErrors