-- Copyright (C) 1984, 1985, 1987 by Xerox Corporation. All rights reserved.
-- PhantomCHS.mesa, WIrish, 30-Oct-87 17:40:07
DIRECTORY
AddressTranslation USING [Error, PrintError, StringToNetworkAddress],
Ascii USING [CR],
CmFile USING [Handle, TableError],
Format USING [NetworkAddress, NetworkNumber, StringProc],
Heap USING [systemZone],
Process USING [Detach],
Put USING [Text],
String USING [AppendChar, AppendString],
StringLookUp USING [noMatch],
System USING [
NetworkAddress, NetworkNumber, nullNetworkAddress, nullSocketNumber, SocketNumber],
Token USING [FreeTokenString, Item, NetworkNumber],
Unformat USING [Error, NetworkAddress],
Buffer USING [NSBuffer, ReturnBuffer],
Driver USING [Network],
Indirect USING [Close, OpenSection, NextValue],
NSConstants USING [newClearinghouseSocket],
RouterInternal USING [SendPacket],
RoutingTable USING [NetworkContext],
Socket USING [
ChannelHandle, Create,
GetPacket,
SetDestination, SetWaitTime, TimeOut];
PhantomCHS: MONITOR
IMPORTS
CmFile, Format, Heap, Indirect, Process, Put,
String, Token, Unformat,
AddressTranslation, Buffer, RouterInternal, Socket
EXPORTS Buffer =
BEGIN
Network: PUBLIC TYPE = Driver.Network;
pleaseStop: BOOLEAN ← FALSE;
remote: Chain ← NIL;
z: UNCOUNTED ZONE = Heap.systemZone;
Chain: TYPE = LONG POINTER TO ChainSlot;
ChainSlot: TYPE = RECORD [
next: Chain,
source: System.NetworkNumber,
dest: System.NetworkAddress,
target: LONG STRING];
ActivateServer: PUBLIC ENTRY PROCEDURE =
BEGIN
ScanParameterFile[];
IF remote = NIL THEN RETURN;
pleaseStop ← FALSE;
Process.Detach[FORK Server[]];
END;
Server: PROCEDURE =
BEGIN
soc: Socket.ChannelHandle;
b: Buffer.NSBuffer;
soc ← Socket.Create[NSConstants.newClearinghouseSocket, 0, 2];
Socket.SetWaitTime[soc, 10000--ms--];
DO
b ← NIL;
b ← Socket.GetPacket[soc ! Socket.TimeOut => CONTINUE];
IF b = NIL THEN LOOP;
IF b.ns.packetType = packetExchange
AND b.ns.exchangeType = clearinghouseService
THEN
BEGIN
context: RoutingTable.NetworkContext = b.context;
FOR finger: Chain ← remote, finger.next UNTIL finger = NIL DO
IF context.netNumber = finger.source THEN
BEGIN
IF finger.dest = System.nullNetworkAddress THEN GOTO Reject;
Socket.SetDestination[b, finger.dest];
EXIT;
END;
REPEAT FINISHED => GOTO Reject;
ENDLOOP;
RouterInternal.SendPacket[b]; -- Socket.PutPacket smashes b.ns.source
b ← NIL;
EXITS Reject => NULL;
END;
IF b # NIL THEN Buffer.ReturnBuffer[b];
ENDLOOP;
END;
ScanParameterFile: PROCEDURE =
BEGIN
cmFile: CmFile.Handle;
Option: TYPE = {remote};
NextValue: PROCEDURE [
h: CmFile.Handle, table: LONG DESCRIPTOR FOR ARRAY Option OF LONG STRING]
RETURNS [Option] = LOOPHOLE[Indirect.NextValue];
optionTable: ARRAY Option OF LONG STRING ← [remote: "Remote"L];
cmFile ← Indirect.OpenSection["PhantomCHS"L];
IF cmFile = NIL THEN RETURN;
DO
option: Option;
option ← NextValue[
cmFile, DESCRIPTOR[optionTable] !
CmFile.TableError =>
BEGIN
IF name[0] # '; THEN Message["Unrecognized parameter: ", name];
RETRY;
END];
SELECT option FROM
LOOPHOLE[StringLookUp.noMatch] => EXIT;
remote =>
BEGIN
source: System.NetworkNumber = Token.NetworkNumber[cmFile];
temp: LONG STRING ← Token.Item[cmFile, FALSE];
new: Chain ← z.NEW[ChainSlot];
new↑ ← [NIL, source, System.nullNetworkAddress, z.NEW[StringBody[temp.length]]];
String.AppendString[new.target, temp];
[] ← Token.FreeTokenString[temp];
new.dest ← GetAddress[new.target, NSConstants.newClearinghouseSocket ! Trouble => CONTINUE];
IF remote = NIL THEN remote ← new
ELSE
BEGIN
FOR finger: Chain ← remote, finger.next DO
IF finger.next = NIL THEN
BEGIN
finger.next ← new;
EXIT;
END;
ENDLOOP;
END;
MessageNet[new];
END;
ENDCASE => ERROR;
ENDLOOP;
Indirect.Close[cmFile];
END;
ForgetParameters: PROCEDURE =
BEGIN
UNTIL remote = NIL DO
temp: Chain ← remote;
remote ← remote.next;
z.FREE[@temp.target];
z.FREE[@temp];
ENDLOOP;
END;
MessageNet: PROCEDURE [new: Chain] =
BEGIN
text: STRING = [200];
String.AppendString[text, "Forwarding ClearingHouse probes from "L];
AppendNetNumber[text, new.source];
String.AppendString[text, " to "L];
String.AppendString[text, new.target];
String.AppendString[text, " ("L];
AppendNetworkAddress[text, new.dest];
String.AppendString[text, ")"L];
LogString[text];
END;
Message: PROCEDURE [one, two, three, four: LONG STRING ← NIL] =
BEGIN
text: STRING = [200];
String.AppendString[text, one];
IF two # NIL THEN String.AppendString[text, two];
IF three # NIL THEN String.AppendString[text, three];
IF four # NIL THEN String.AppendString[text, four];
LogString[text];
END;
AppendNetNumber: PROCEDURE [string: LONG STRING, net: System.NetworkNumber] =
BEGIN
Append: PROCEDURE [s: LONG STRING, clientData: LONG POINTER] =
BEGIN String.AppendString[string, s]; END;
Format.NetworkNumber[Append, net, productSoftware];
END;
AppendNetworkAddress: PROCEDURE [string: LONG STRING, addr: System.NetworkAddress] =
BEGIN
Append: PROCEDURE [s: LONG STRING, clientData: LONG POINTER] =
BEGIN String.AppendString[string, s]; END;
Format.NetworkAddress[Append, addr, productSoftware];
END;
LogString: PROCEDURE [text: LONG STRING] =
BEGIN
String.AppendChar[text, '.];
String.AppendChar[text, Ascii.CR];
Put.Text[NIL, text];
END;
Trouble: ERROR [reason: LONG STRING] = CODE;
GetAddress: PROCEDURE [host: LONG STRING, socket: System.SocketNumber]
RETURNS [addr: System.NetworkAddress] =
BEGIN
localFailed: BOOLEAN ← FALSE;
IF host = NIL THEN ERROR Trouble ["NIL => Address Fault"L];
addr ← Unformat.NetworkAddress[host, octal !
Unformat.Error => BEGIN localFailed ← TRUE; CONTINUE; END ];
IF localFailed THEN
BEGIN
addr ← AddressTranslation.StringToNetworkAddress[host !
AddressTranslation.Error =>
BEGIN
temp: STRING = [200];
proc: Format.StringProc = {String.AppendString[temp, s]};
AddressTranslation.PrintError[errorRecord, proc];
ERROR Trouble[temp];
END].addr;
addr.socket ← socket; -- CH returns trash in socket
END;
IF addr.socket = System.nullSocketNumber THEN addr.socket ← socket;
END;
ActivateServer[];
END.