-- File: EchoServerImpl.mesa - last edit: -- AOF 5-May-87 12:58:07 -- SMA 22-May-86 11:37:27 -- Copyright (C) 1984, 1985, 1986, 1987 by Xerox Corporation. All rights reserved. DIRECTORY CommFlags USING [doStats], CommSwitches USING [remoteSwat], EchoServer USING [], HostNumbers USING [IsMulticastID], NetworkStream USING [closeSST, closeReplySST], NSConstants USING [echoerSocket], NSBuffer USING [Body, Buffer, ReturnBuffer], NSTypes USING [bytesPerSppHeader, bytesPerIDPHeader, EchoType], PacketStream USING [ ConnectionAlreadyThere, ConnectionFailed, ConnectionSuspended, Make, Handle, unknownConnID, WaitTime], Process USING [Detach], Protocol1 USING [EncapsulateAndTransmit], RouterInternal USING [SendErrorPacket], Runtime USING [CallDebugger], Socket USING [ChannelHandle, Delete, PutPacket, SwapSourceAndDestination], SocketInternal USING [ListenerProcType, CreateListen], Stats USING [StatIncr, StatBump], System USING [nullNetworkAddress, SocketNumber, switches]; EchoServerImpl: PROGRAM IMPORTS NSBuffer, HostNumbers, Process, PacketStream, Protocol1, RouterInternal, Runtime, Socket, SocketInternal, Stats, System EXPORTS EchoServer = BEGIN echoCH: Socket.ChannelHandle; echoPackets : LONG CARDINAL ← 0; echoBytes: LONG CARDINAL ← 0; swatRequest: WORD = 17; swatCH: Socket.ChannelHandle; swatSocket: System.SocketNumber ← LOOPHOLE[27]; --Action Request 7176 CreateServer: PUBLIC PROCEDURE [buffers: CARDINAL] = BEGIN echoCH ← SocketInternal.CreateListen[ socket: NSConstants.echoerSocket, callback: EchoServer, receive: buffers, clientData: NIL]; IF System.switches[CommSwitches.remoteSwat] = down THEN BEGIN swatCH ← SocketInternal.CreateListen[ socket: swatSocket, receive: 1, callback: SwatWatcher, clientData: NIL]; END; END; -- CreateServer DeleteServer: PUBLIC PROCEDURE = BEGIN Socket.Delete[echoCH]; IF System.switches[CommSwitches.remoteSwat] = down THEN Socket.Delete[swatCH]; END; --DeleteServer EchoServer: SocketInternal.ListenerProcType = BEGIN nsb: NSBuffer.Body = b.ns; SELECT nsb.packetType FROM (echo) => BEGIN IF nsb.echoType = echoRequest THEN BEGIN Socket.SwapSourceAndDestination[b]; nsb.echoType ← echoResponse; echoPackets ← echoPackets + 1; echoBytes ← echoBytes + nsb.pktLength; IF CommFlags.doStats THEN Stats.StatIncr[packetsEchoed]; IF CommFlags.doStats THEN Stats.StatBump[bytesEchoed, nsb.pktLength]; SELECT TRUE FROM (nsb.checksum # 177777B) => Socket.PutPacket[echoCH, b]; --he checksum'd => me too (nsb.source.host = nsb.destination.host) => Socket.PutPacket[echoCH, b]; --it's gotta be ME => ME (nsb.source.net # nsb.destination.net) => Socket.PutPacket[echoCH, b]; --need router's help router's help ENDCASE => BEGIN <<nsb.checksum ← 177777B;>> --that field's already set nsb.transportControl ← [FALSE, 0, 0]; Protocol1.EncapsulateAndTransmit[ LOOPHOLE[b], @nsb.destination.host]; END; END ELSE RouterInternal.SendErrorPacket[b, protocolViolation]; END; (sequencedPacket) => Process.Detach[FORK Sequenced[b]]; ENDCASE => RouterInternal.SendErrorPacket[b, protocolViolation]; END; -- EchoServer GetCounters: PUBLIC PROCEDURE RETURNS [packets, bytes: LONG CARDINAL] = {RETURN[echoPackets, echoBytes]}; Sequenced: PROC[rb: NSBuffer.Buffer] = BEGIN echo: LONG POINTER TO NSTypes.EchoType; rbody: NSBuffer.Body ← rb.ns; --make things closer dontcopy: CARDINAL = NSTypes.bytesPerSppHeader + NSTypes.bytesPerIDPHeader; SELECT TRUE FROM (rb = NIL) => NULL; --rb is NIL if client aborted this process (rb.fo.status # goodCompletion) => NSBuffer.ReturnBuffer[rb]; (rbody.destinationConnectionID # PacketStream.unknownConnID) => RouterInternal.SendErrorPacket[rb, protocolViolation]; (rbody.sourceConnectionID = PacketStream.unknownConnID) => RouterInternal.SendErrorPacket[rb, protocolViolation]; (rbody.sequenceNumber # 0) => RouterInternal.SendErrorPacket[rb, protocolViolation]; (~rbody.systemPacket) => RouterInternal.SendErrorPacket[rb, protocolViolation]; (~PacketStream.ConnectionAlreadyThere[ rbody.source, rbody.sourceConnectionID]) => BEGIN psH: PacketStream.Handle ← PacketStream.Make[ System.nullNetworkAddress, rbody.source, PacketStream.unknownConnID, rbody.sourceConnectionID, TRUE, LAST[PacketStream.WaitTime], bulk ! PacketStream.ConnectionFailed => GOTO failed]; NSBuffer.ReturnBuffer[rb]; --we don't need buffer any longer --UNTIL stream ends-- DO ENABLE PacketStream.ConnectionSuspended => EXIT; --that's an out IF (rb ← psH.get[]) = NIL THEN EXIT; --Stream.TimeOut => quit rbody ← rb.ns; --pick up pointer to the body echo ← LOOPHOLE[@rbody.sppWords[0]]; IF rbody.subtype = NetworkStream.closeReplySST THEN GOTO exit; IF echo↑ = echoRequest THEN echo↑ ← echoResponse; --maybe echoPackets ← echoPackets + 1; echoBytes ← echoBytes + rbody.pktLength; IF CommFlags.doStats THEN Stats.StatIncr[packetsEchoed]; IF CommFlags.doStats THEN Stats.StatBump[bytesEchoed, rbody.pktLength]; rbody.subtype ← IF rbody.subtype = NetworkStream.closeSST THEN NetworkStream.closeReplySST ELSE 0; psH.put[rb]; --send the buffer back REPEAT exit => psH.returnReceiveBuffer[rb]; ENDLOOP; psH.destroy[psH]; --get rid of stream EXITS failed => NSBuffer.ReturnBuffer[rb]; END; ENDCASE => NSBuffer.ReturnBuffer[rb]; END; --Sequenced SwatWatcher: SocketInternal.ListenerProcType = BEGIN nsb: NSBuffer.Body = b.ns; ok: BOOLEAN ← (nsb.packetType = private) AND (nsb.nsWords[0] = swatRequest) AND (~HostNumbers.IsMulticastID[LOOPHOLE[@nsb.destination.host]]); NSBuffer.ReturnBuffer[b]; IF ok THEN Runtime.CallDebugger["SwatRequest"L]; END; --SwatWatcher END.... LOG 16-May-84 20:29:43 AOF Post Klamath. 5-Apr-85 10:37:18 AOF Remote call debug. 30-Dec-85 14:12:26 AOF Restructure listeners. 22-May-86 11:34:56 SMA Remove dependencies on Buffer. 19-Aug-86 10:30:26 AOF Caching pointer to buffer body. 16-Sep-86 18:50:40 AOF One last "rbody ← r.ns". 18-Nov-86 16:06:56 AOF PilotSwitchesExtra5 => CommSwitches 4-May-87 11:32:11 AOF Sequenced is real echo protocol and uses buffer swap