-- EchoServerImpl.mesa (last edited by: Garlick on: January 23, 1981 5:43 PM -- Function: The implementation module for the Pilot OISCP Echo Server. DIRECTORY BufferDefs USING [OisBuffer], CommunicationInternal USING [], CommFlags USING [doStats], Echo USING [echoRequest, echoResponse], OISCP USING [ReturnFreeOisBuffer, unknownNetID], OISCPConstants USING [echoerSocket], Router USING [FindMyHostID], Socket USING [ Abort, ChannelAborted, Create, Delete, GetPacket, PutPacket, SetWaitTime, TimeOut, TransferStatus, WaitTime], SocketInternal USING [SocketObject], NSAddress USING [NetworkAddress], StatsDefs USING [StatIncr, StatBump]; EchoServerImpl: PROGRAM IMPORTS OISCP, Router, Socket, StatsDefs EXPORTS CommunicationInternal, Echo, Socket SHARES BufferDefs = BEGIN -- EXPORTED TYPE(s) NetworkAddress: PUBLIC TYPE = NSAddress.NetworkAddress; ChannelHandle: TYPE = REF ChannelObject; ChannelObject: PUBLIC TYPE = SocketInternal.SocketObject; -- global constants to all nBuffers: CARDINAL = 2; -- global variables to all cH: ChannelHandle; localAddr: NetworkAddress; echoServerFork: PROCESS; echoerTimeout: Socket.WaitTime = 7777777777B; -- in msec (about 10 days) -- Cold Procedures -- This procedure creates an echo server. CreateServer: PUBLIC PROCEDURE = BEGIN localAddr ← [net: OISCP.unknownNetID, host: Router.FindMyHostID[], socket: OISCPConstants.echoerSocket]; cH ← Socket.Create[localAddr, 0, nBuffers, 0, FALSE]; -- no send or reserve buffers, 2 receive buffers, FALSE -> share buffers from system pool. echoServerFork ← FORK EchoServer[]; END; -- CreateServer -- This procedure deletes the echo server. DeleteServer: PUBLIC PROCEDURE = BEGIN Socket.Abort[cH]; JOIN echoServerFork; Socket.Delete[cH]; END; -- DeleteListener -- Hot Procedures -- This procedure echos Echo protocol packets back to the remote end. EchoServer: PROCEDURE = BEGIN buf: BufferDefs.OisBuffer; Socket.SetWaitTime[cH, echoerTimeout]; -- init the PhysicalRecords and start the gets DO -- wait for an echo request packet buf ← NIL; buf ← Socket.GetPacket[ cH ! Socket.TimeOut => RETRY; Socket.ChannelAborted => EXIT]; -- b.status can be one of aborted or goodCompletion SELECT LOOPHOLE[buf.status, Socket.TransferStatus] FROM goodCompletion => BEGIN IF buf.ois.transCntlAndPktTp.packetType = echo THEN BEGIN firstWord: LONG POINTER TO WORD ← @buf.ois.oisWords[0]; -- examine this packet IF firstWord↑ = Echo.echoRequest THEN BEGIN -- good packet, echo it buf.ois.destination ← buf.ois.source; firstWord↑ ← Echo.echoResponse; IF CommFlags.doStats THEN StatsDefs.StatIncr[packetsEchoed]; IF CommFlags.doStats THEN StatsDefs.StatBump[bytesEchoed, buf.ois.pktLength]; Socket.PutPacket[cH, buf ! Socket.ChannelAborted => BEGIN OISCP.ReturnFreeOisBuffer[buf]; EXIT; END]; LOOP; END ELSE IF CommFlags.doStats THEN StatsDefs.StatIncr[packetsBadEchoed] END ELSE IF CommFlags.doStats THEN StatsDefs.StatIncr[packetsBadEchoed]; END; -- end goodCompletion aborted => EXIT; ENDCASE => NULL; OISCP.ReturnFreeOisBuffer[buf]; ENDLOOP; -- we got here via an abort or error; now clean up this world. Socket.Abort[cH]; END; -- EchoServer END.