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