-- File: CourierImplN.mesa - last edit:
-- AOF 9-Nov-87 18:38:29
-- Copyright (C) 1984, 1985, 1986, 1987 by Xerox Corporation. All rights reserved.
DIRECTORY
CommSwitches USING [sppNegotiation],
Courier USING [Error, ErrorCode, LocalSystemElement, Object],
CourierInternal USING [
activeTimeout, AugmentedObj, AugmentedStream, CreateNewStream,
createTimeout, Creator, doStats, hopWeight, Listener, longZone,
NewStreamFailed, Receiver, stats, UserConnection],
CourierProtocol USING [Protocol, ProtocolRange, pvHigh],
Environment USING [bytesPerWord, nullBlock],
NetworkStream USING [
ApproveConnection, Close, CloseReply, closeSST, ConnectionFailed,
ConnectionSuspended, Create, CreateListener, FailureReason, Listen,
ListenerHandle, SuspendReason, WaitTime],
NewNetworkStream,
NSConstants USING [courierSocket],
Process USING [Detach],
Router USING [GetDelayToNet, NoTableEntryForNet],
Stream USING [
defaultObject, DeleteProcedure, GetProcedure, Handle, Object,
PutProcedure, SendAttentionProcedure, SendNowProcedure, SetSSTProcedure,
SubSequenceType, WaitAttentionProcedure],
System USING [NetworkAddress, NetworkNumber, switches];
CourierImplN: PROGRAM
IMPORTS
Courier, CourierInternal, NetworkStream, NewNetworkStream,
Process, Router, Stream, System
EXPORTS CourierInternal =
BEGIN
pvLow: CourierProtocol.Protocol = CourierProtocol.pvHigh;
pvHigh: CourierProtocol.Protocol = CourierProtocol.pvHigh;
z: UNCOUNTED ZONE = CourierInternal.longZone;
bpw: CARDINAL = Environment.bytesPerWord;
negotiating: BOOLEAN = System.switches[CommSwitches.sppNegotiation] = down;
xlateFailure: ARRAY NetworkStream.FailureReason OF Courier.ErrorCode = [
timeout: remoteSystemElementNotResponding,
noRouteToDestination: noRouteToSystemElement,
noServiceAtDestination: noCourierAtRemoteSite,
noAnswerOrBusy: noAnswerOrBusy,
noTranslationForDestination: noRouteToSystemElement,
circuitInUse: transmissionMediumUnavailable,
circuitNotReady: transmissionMediumNotReady,
noDialingHardware: transmissionMediumUnavailable,
dialerHardwareProblem: transmissionMediumHardwareProblem,
remoteReject: tooManyConnections,
tooManyConnections: tooManyConnections];
xlateSuspend: ARRAY NetworkStream.SuspendReason OF Courier.ErrorCode = [
notSuspended: noError,
transmissionTimeout: transportTimeout,
remoteServiceDisappeared: transportTimeout,
noRouteToDestination: noRouteToSystemElement];
BuildCourierTransport: PROC[sH: Stream.Handle]
RETURNS[aH: CourierInternal.AugmentedStream] =
BEGIN
IF CourierInternal.doStats THEN CourierInternal.stats[streamsCreated] ←
CourierInternal.stats[streamsCreated] + 1;
--Build the stream for Courier to use with our own filters.
aH ← z.NEW[CourierInternal.AugmentedObj[SIZE[Stream.Handle]]];
aH.object ← sH↑; --Copy for the filtered stream
aH.object.get ← Get; --and put in the filters.
aH.object.put ← Put;
aH.object.setSST ← SetSST;
aH.object.sendNow ← SendNow;
aH.object.delete ← DeleteStream;
aH.object.waitAttention ← WaitAttn;
aH.object.sendAttention ← SendAttn;
aH.object.getByte ← Stream.defaultObject.getByte;
aH.object.putByte ← Stream.defaultObject.putByte;
aH.object.getWord ← Stream.defaultObject.getWord;
aH.object.putWord ← Stream.defaultObject.putWord;
LOOPHOLE[@aH.context, LONG POINTER TO Stream.Handle]↑ ← sH;
END; --BuildCourierTransport
DeleteStream: Stream.DeleteProcedure =
BEGIN --The delete proc in the stream object visable to courier.
--Access to the direct network stream.
aH: CourierInternal.AugmentedStream ← LOOPHOLE[sH];
ch: CourierInternal.UserConnection ← LOOPHOLE[aH.back];
sH ← LOOPHOLE[@aH.context, LONG POINTER TO Stream.Handle]↑;
--Is the other side smart enough for the close protocol?
IF ch.protocolRange.high > protocol2 THEN
BEGIN
sst: Stream.SubSequenceType;
sst ← sH.get[sH, Environment.nullBlock, sH.options].sst;
sH.setTimeout[sH, WaitTime[ch.object.remote.net, 10000]];
IF sst # NetworkStream.closeSST THEN [] ← NetworkStream.Close[sH]
ELSE [] ← NetworkStream.CloseReply[sH];
END;
sH.delete[sH];
z.FREE[@aH];
END; --DeleteStream
CreateDefaultStream: PUBLIC CourierInternal.Creator =
BEGIN
<<
CourierInternal.Creator: TYPE = PROC[ch: CourierInternal.ConnectionHandle]
RETURNS[
aH: CourierInternal.AugmentedStream,
protocolRange: CourierProtocol.ProtocolRange,
connectionless: BOOLEAN];
Creates a user side transport (NetworkStream), arbitrates protocol
versions.
>>
sH: Stream.Handle ← NIL;
error: Courier.ErrorCode;
BEGIN
ENABLE NetworkStream.ConnectionFailed =>
BEGIN
CourierInternal.NewStreamFailed[]; --Decrements stream count.
error ← xlateFailure[why]; GOTO error; --translate reason and quit
END;
wt: NetworkStream.WaitTime = WaitTime[
ch.object.remote.net, CourierInternal.createTimeout];
IF ~CourierInternal.CreateNewStream[] THEN --are we permitted another?
{error ← tooManyConnections; GOTO error}; --evidently not
sH ← IF ~negotiating THEN NetworkStream.Create[
remote: ch.object.remote, classOfService: bulk, timeout: wt]
ELSE NewNetworkStream.NewCreate[remote: ch.object.remote, timeout: wt];
EXITS error => {IF sH # NIL THEN sH.delete[sH]; ERROR Courier.Error[error]};
END;
--build the returned paramters
aH ← BuildCourierTransport[sH]; aH.back ← ch;
RETURN[aH, [pvLow, pvHigh], FALSE];
END; --CreateDefaultStream
DefaultListener: PUBLIC CourierInternal.Listener =
BEGIN
<<
SERVER
Listens on a particular socket for requests. Also arbitrates
protocol versions. When request arrives, creates the stream and
hands it to Courier.
Set here in this detached process waiting for somebody (hopefully the
system element wanting to Call) to initiate a connection. When that
happens, spawn another process to service the request.
>>
sH: Stream.Handle;
remote: System.NetworkAddress;
aH: CourierInternal.AugmentedStream;
listenerHandle: NetworkStream.ListenerHandle;
listenerHandle ← NetworkStream.CreateListener[Courier.LocalSystemElement[]];
DO
remote ← IF ~negotiating THEN
NetworkStream.Listen[listenerH: listenerHandle].remote
ELSE NewNetworkStream.NewListen[listenerH: listenerHandle].remote;
--May fail due to too many connections
SELECT TRUE FROM
(CourierInternal.CreateNewStream[]) => --are we allowed?
BEGIN
ENABLE NetworkStream.ConnectionFailed =>
{CourierInternal.NewStreamFailed[]; CONTINUE};
sH ← IF ~negotiating THEN
NetworkStream.ApproveConnection[
listenerH: listenerHandle,
streamTimeout: CourierInternal.activeTimeout,
classOfService: bulk]
ELSE NewNetworkStream.NewApprove[
listenerH: listenerHandle,
streamTimeout: CourierInternal.activeTimeout];
remote.socket ← NSConstants.courierSocket;
aH ← BuildCourierTransport[sH]; --get things set up
Process.Detach[FORK CourierInternal.Receiver[
aH, remote, [pvLow, pvHigh], FALSE]];
END;
(negotiating) =>
NewNetworkStream.NewReject[listenerH: listenerHandle];
ENDCASE;
ENDLOOP;
END; --DefaultListener
Get: Stream.GetProcedure =
BEGIN
<<
The Get procedure we give to Courier. Calls the direct network
stream's get procedure, catches transport-specific errors, and
translates them into the appropriate Courier.Error.
>>
error: Courier.ErrorCode ← noError;
sH ← TransportFromFilter[sH];
{[bytesTransferred, why, sst] ← sH.get[sH, block, options !
NetworkStream.ConnectionSuspended =>
{error ← xlateSuspend[why]; GOTO transportError}];
EXITS transportError => Courier.Error[error]};
END; --Get
Put: Stream.PutProcedure =
BEGIN
<<
The Put procedure we give to Courier. Calls the direct network
stream's put procedure, catches transport-specific errors, and
translates them into the appropriate Courier.Error.
>>
error: Courier.ErrorCode ← noError;
sH ← TransportFromFilter[sH]; --get to transport's stream
{sH.put[sH, block, endRecord !
NetworkStream.ConnectionSuspended =>
{error ← xlateSuspend[why]; GOTO transportError}];
EXITS transportError => Courier.Error[error]};
END; --Put
SendNow: Stream.SendNowProcedure =
BEGIN
<<
The sendNow procedure we give to Courier. Calls the direct network
stream's sendNow procedure, catches transport-specific errors, and
translates them into the appropriate Courier.Error.
>>
error: Courier.ErrorCode ← noError;
sH ← TransportFromFilter[sH]; --get to transport's stream
{sH.sendNow[sH, endRecord !
NetworkStream.ConnectionSuspended =>
{error ← xlateSuspend[why]; GOTO transportError}];
EXITS transportError => Courier.Error[error]};
END; --SendNow
SetSST: Stream.SetSSTProcedure =
BEGIN
error: Courier.ErrorCode ← noError;
sH ← TransportFromFilter[sH]; --get to transport's stream
{sH.setSST[sH, sst !
NetworkStream.ConnectionSuspended =>
{error ← xlateSuspend[why]; GOTO transportError}];
EXITS transportError => Courier.Error[error]};
END; --SetSST
WaitAttn: Stream.WaitAttentionProcedure =
BEGIN
<<
The waitForAttention procedure we give to Courier. Calls the direct
network stream's waitForAttention procedure, catches
transport-specific errors, and translates them into the appropriate
Courier.Error.
>>
error: Courier.ErrorCode ← noError;
sH ← TransportFromFilter[sH]; --get to transport's stream
{RETURN[sH.waitAttention[sH !
NetworkStream.ConnectionSuspended =>
{error ← xlateSuspend[why]; GOTO transportError}]];
EXITS transportError => Courier.Error[error]};
END; --WaitAttn
SendAttn: Stream.SendAttentionProcedure =
BEGIN
<<
The sendAttention procedure we give to Courier. Calls the direct
network stream's sendAttention procedure, catches transport-specific
errors and translates them into the appropriate Courier.Error.
>>
error: Courier.ErrorCode ← noError;
sH ← TransportFromFilter[sH]; --get to transport's stream
{sH.sendAttention[sH, byte !
NetworkStream.ConnectionSuspended =>
{error ← xlateSuspend[why]; GOTO transportError}];
EXITS transportError => Courier.Error[error]};
END; --SendAttn
TransportFromFilter: PROC[sH: Stream.Handle] RETURNS[Stream.Handle] = INLINE
{RETURN[LOOPHOLE[@LOOPHOLE[sH, CourierInternal.AugmentedStream].context,
LONG POINTER TO Stream.Handle]↑]};
WaitTime: PROC[net: System.NetworkNumber, base: NetworkStream.WaitTime]
RETURNS[tmo: NetworkStream.WaitTime] =
BEGIN
ENABLE Router.NoTableEntryForNet =>
{tmo ← LONG[CourierInternal.hopWeight * 10000]; CONTINUE};
tmo ← base + (CourierInternal.hopWeight * Router.GetDelayToNet[net] * 1000);
END; --WaitTime
END...
LOG
25-Jun-84 12:31:44 SMA Created file.
20-Jul-84 10:41:07 SMA Catch SpecialCourier.Closed.
21-Dec-84 13:07:24 SMA AugmentedStreams and new interfaces.
27-Dec-84 11:46:19 AOF FORK Receiver with AugmentedStream, not nsH.
7-Jan-85 8:54:39 AOF Moved Closed back to CourierImplC.
7-Jan-85 10:17:07 SMA Take out TransportHandle.
7-Jan-85 17:05:38 SMA No translations to callerAborted.
5-Mar-85 19:18:59 AOF Don't stomp on CourierInternal.createTimeout.
9-Apr-85 15:41:59 AOF DeleteStream looking for closeSST already received.
24-May-85 14:32:01 AOF Resetting stream timeout before close.
16-Jan-86 13:17:04 AOF cleanup LOOPHOLEs.
3-Mar-86 15:43:50 AOF Correct getting input SST in Delete code.
15-Apr-86 10:44:31 AOF Computation of wait time (missing * 1000).
16-Jan-87 9:47:06 AOF Removal of Courier Version 2.0
14-Apr-87 12:34:46 AOF Catch ConnectionFailed in listener
9-Nov-87 18:27:35 AOF Add access to Spp Negotiation