-- 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