DIRECTORY
Rope USING [Fetch, Length, ROPE],
StatsDefs USING [StatIncr],
PupRouterDefs USING [SneakySendUnlocked],
PupStream USING [CloseReason],
PupDefs,
CommFlags USING [doStats, doDebug],
DriverDefs
USING [
Glitch, Network, PutOnGlobalDoneQueue, GetDeviceChain],
BufferDefs, -- SHARES
PupTypes USING [allHosts, PupErrorCode, PupSocketID],
DriverTypes USING [bufferSeal];
PupErrors:
PROGRAM
IMPORTS StatsDefs, PupRouterDefs, DriverDefs, PupDefs, Rope
EXPORTS BufferDefs, PupRouterDefs, PupStream, PupDefs
SHARES BufferDefs =
BEGIN OPEN DriverDefs, PupDefs;
Network: PUBLIC TYPE = DriverDefs.Network;
PktStream/ByteStream SIGNALs live here so they are defined only once
StreamClosing: PUBLIC ERROR [why: PupStream.CloseReason, text: Rope.ROPE] = CODE;
RejectThisRequest: PUBLIC ERROR [error: Rope.ROPE] = CODE;
suppressErrors: BOOLEAN ← FALSE;
suppressBufferFull: BOOLEAN ← FALSE;
BufferSealBroken: PUBLIC ERROR = CODE;
BufferDidntArrive: PUBLIC ERROR = CODE;
SetErrorSuppression:
PUBLIC
PROCEDURE [dontSendErrors:
BOOLEAN] =
BEGIN suppressErrors ← dontSendErrors; END;
SetBufferFullSuppression:
PUBLIC
PROCEDURE [dontSend:
BOOLEAN] =
BEGIN suppressBufferFull ← dontSend; END;
RejectPupWithBadChecksum:
PUBLIC
PROCEDURE [b: PupBuffer] =
BEGIN Reject[b, badChecksumPupErrorCode]; END;
Reject:
PUBLIC
PROCEDURE [b: PupBuffer, code: PupTypes.PupErrorCode] =
BEGIN
IF BuildErrorPup[b, code, NIL] THEN PupRouterDefs.SneakySendUnlocked[b];
END;
SendErrorPup:
PUBLIC
PROCEDURE [
b: PupBuffer, code: PupTypes.PupErrorCode, text: Rope.ROPE] =
BEGIN IF BuildErrorPup[b, code, text] THEN PupRouterSendThis[b]; END;
BuildErrorPup:
PUBLIC
PROCEDURE [
b: PupBuffer, code: PupTypes.PupErrorCode, text: Rope.ROPE]
RETURNS [ok: BOOLEAN] =
BEGIN
p: LONG POINTER TO ARRAY [0..9] OF WORD = LOOPHOLE[@b.pupLength];
temp: PupTypes.PupSocketID;
network: Network ← b.network;
IF CommFlags.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 CommFlags.doDebug AND network= NIL THEN Glitch[BufferDidntArrive];
IF network.netNumber.b > 377B THEN network ← DriverDefs.GetDeviceChain[];
FOR i: CARDINAL 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.b], [network.hostNumber], temp];
IF text =
NIL
THEN
SELECT code
FROM
badChecksumPupErrorCode => text ← "Bad Software Checksum";
noProcessPupErrorCode => text ← "No such Port";
resourceLimitsPupErrorCode => text ← "Buffers full";
ENDCASE => NULL;
IF text #
NIL
THEN
BEGIN
length: INT = text.Length[];
FOR i: INT IN [0..length) DO b.errorText[i] ← text.Fetch[i]; ENDLOOP;
SetPupContentsBytes[b, 2*(10 + 1 + 1) + length];
END
ELSE SetPupContentsBytes[b, 2*(10 + 1 + 1) + 0];
IF CommFlags.doStats THEN StatsDefs.StatIncr[statErrorPupsSent];
RETURN[TRUE];
END;
END.