<> <> <> <<>> <> DIRECTORY Process USING [Abort], XNS USING [Address, Socket], XNSBuf USING [Buffer], XNSEchoBuf USING [Buffer], XNSEchoServer USING [], XNSErrorTypes USING [protocolViolationErr], XNSSocket USING [Create, Destroy, FreeBuffer, Get, Handle, ReturnError, ReturnToSender, SetNoErrors, waitForever], XNSWKS USING [echo]; XNSEchoServerImpl: CEDAR MONITOR IMPORTS Process, XNSSocket EXPORTS XNSEchoServer ~ BEGIN echoProcess: PROCESS; Create: PUBLIC ENTRY PROC [buffers: CARDINAL] ~ { < NULL; -- No ERRORs>> IF echoProcess = NIL THEN { nGood _ nNotRequest _ nNotEcho _ 0; echoProcess _ FORK EchoServer[buffers] }; }; Destroy: PUBLIC ENTRY PROC ~ { < NULL; -- No ERRORs>> IF echoProcess # NIL THEN TRUSTED { Process.Abort[echoProcess]; JOIN echoProcess; echoProcess _ NIL }; }; nGood: INT; nNotEcho: INT; nNotRequest: INT; EchoServer: PROC [buffers: CARDINAL] ~ { b: XNSBuf.Buffer _ NIL; eb: XNSEchoBuf.Buffer _ NIL; h: XNSSocket.Handle _ XNSSocket.Create[sendBuffers~0, recvBuffers~buffers, getTimeout~XNSSocket.waitForever, local~XNSWKS.echo]; DO ENABLE ABORTED => EXIT; b _ XNSSocket.Get[h]; SELECT b.hdr1.type FROM echo => { TRUSTED { eb _ LOOPHOLE[b] }; SELECT eb.hdr2.type FROM request => { nGood _ nGood.SUCC; eb.hdr2.type _ reply; XNSSocket.ReturnToSender[handle~h, b~b]; b _ NIL } ENDCASE => { nNotRequest _ nNotRequest.SUCC; XNSSocket.ReturnError[handle~h, b~b, type~XNSErrorTypes.protocolViolationErr]; b _ NIL }; }; ENDCASE => { nNotEcho _ nNotEcho.SUCC; XNSSocket.ReturnError[handle~h, b~b, type~XNSErrorTypes.protocolViolationErr]; b _ NIL }; ENDLOOP; IF b # NIL THEN XNSSocket.FreeBuffer[handle~h, b~b]; XNSSocket.SetNoErrors[handle~h, noErrors~TRUE]; XNSSocket.Destroy[h]; }; END.