-- File: ArpaEchoServerImpl.mesa - last edit: -- AOF 11-Mar-87 16:25:45 -- SMA 11-Dec-85 11:58:39 -- Copyright (C) 1985, 1987 by Xerox Corporation. All rights reserved. DIRECTORY ArpaConstants USING [echoPort], ArpaEchoServer, ArpaPort USING [WaitTime], CommHeap USING [zone], Environment USING [Block], Process USING [Abort], TcpStream USING [CompletionCode, Failed, Handle, Listen, Suspended], TcpStreamInternal USING [minTcpHeaderBytes, maxTcpDataBytes]; ArpaEchoServerImpl: PROGRAM IMPORTS CommHeap, Process, TcpStream EXPORTS ArpaEchoServer = BEGIN echoServerFork: PROCESS; --udpEchoH: ArpaPort.Handle; echoPackets : LONG CARDINAL ¬ 0; echoBytes: LONG CARDINAL ¬ 0; tmo: ArpaPort.WaitTime = LAST[ArpaPort.WaitTime]; --equates to disabled CreateServer: PUBLIC PROC [buffers: CARDINAL] = BEGIN <> echoServerFork ¬ FORK EchoServer[]; END; -- CreateServer DeleteServer: PUBLIC PROC = BEGIN Process.Abort[echoServerFork]; JOIN echoServerFork; <> END; --DeleteServer EchoServer: PROC = BEGIN block: Environment.Block; tsH: TcpStream.Handle ¬ NIL; BEGIN ENABLE ABORTED => BEGIN IF tsH # NIL THEN {CommHeap.zone.FREE[@block.blockPointer]; tsH.destroy[tsH]}; GOTO exit; END; n: CARDINAL ¬ 0; outcome: TcpStream.CompletionCode; maxBytes: CARDINAL = TcpStreamInternal.maxTcpDataBytes; Block: TYPE = PACKED ARRAY[0..maxBytes) OF CHARACTER; DO < EXIT]; SELECT b.arpa.protocol FROM (udp) => BEGIN ArpaPort.SwapSourceAndDestination[b]; echoPackets ¬ echoPackets + 1; echoBytes ¬ echoBytes + b.arpa.length; IF CommFlags.doStats THEN ArpaStats.Incr[udpsEchoed]; IF CommFlags.doStats THEN ArpaStats.Bump[bytesEchoed, b.arpa.length]; ArpaPort.PutPacket[echoCH, b]; END END; (tcp) => Process.Detach[FORK TcpEcho[b]]; ENDCASE => {--**ICMP error packet here?--};>> <> tsH ¬ TcpStream.Listen[ArpaConstants.echoPort, tmo ! TcpStream.Failed => LOOP]; --build the input data block. block.blockPointer ¬ LOOPHOLE[CommHeap.zone.NEW[Block]]; block.startIndex ¬ 0; DO --until other end gets bored. ENABLE TcpStream.Suspended => GOTO finished; --whoops block.stopIndexPlusOne ¬ maxBytes; [n, outcome] ¬ tsH.get[block]; echoPackets ¬ echoPackets + 1; IF outcome = timeout THEN GOTO finished; --give up. --'cause SPP echo counts packet headers. Estimate (ignore options). echoBytes ¬ echoBytes + n + TcpStreamInternal.minTcpHeaderBytes; block.stopIndexPlusOne ¬ n; tsH.put[block, TRUE, FALSE]; IF outcome = closing THEN {tsH.close[]; GOTO finished}; REPEAT finished => BEGIN CommHeap.zone.FREE[@block.blockPointer]; tsH.destroy[tsH]; tsH ¬ NIL; END; ENDLOOP; --end of the echo session. ENDLOOP; END; --enabled scope. EXITS exit => NULL; END; -- EchoServer GetCounters: PUBLIC PROC RETURNS [packets, bytes: LONG CARDINAL] = {RETURN[echoPackets, echoBytes]}; END... LOG 14-Oct-85 9:31:18 SMA Created file. 11-Mar-87 16:20:45 AOF Use CommHeap.