<> <> <> <> <> DIRECTORY Ascii USING [Digit], Commander USING [CommandProc, Register], ICMP USING [Echo, ICMPBody, ICMPChecksum], IO USING [int, GetChar, PeekChar, EndOf, PutF, PutRope, RIS, STREAM], IP USING [Byte, DataBuffer, Datagram, DatagramRec, DByte, Address, InternetHandle, InternetHeader, PrintDatagram, SendSpecific]; EchoTest: CEDAR PROGRAM IMPORTS Ascii, Commander, ICMP, IO, IP = BEGIN testProtocol: INT = 1; listenerTimeout: INT _ 10000; logStream: IO.STREAM _ NIL; myHandle: IP.InternetHandle _ NIL; listening: BOOL _ FALSE; remoteAddress: IP.Address; localAddress: IP.Address; sequenceNo: INT _ 0; -- sequence numbers for echo packets. Send: Commander.CommandProc = TRUSTED { <> d: IP.Datagram _ NEW [IP.DatagramRec]; out: IO.STREAM _ cmd.out; body: LONG POINTER TO ICMP.ICMPBody _ LOOPHOLE[@d.data]; d.inHdr.protocol _ testProtocol; d.inHdr.source _ localAddress; d.inHdr.destination _ remoteAddress; d.inHdr.timeToLive _ 100; d.dataLength _ 10; body.type _ ICMP.Echo; body.code _ 0; body.id _ 0; body.sequenceNo _ (sequenceNo _ sequenceNo+1); body.data[0] _ LOOPHOLE['H]; body.data[1] _ LOOPHOLE['e]; body.checksum _ ICMP.ICMPChecksum[body, 5]; d.SendSpecific[]; out.PutRope["Sending: "]; IP.PrintDatagram[out, d]; }; AToI: PROC [s: IO.STREAM] RETURNS [i: INT _ 0] = { <> WHILE NOT s.EndOf[] AND Ascii.Digit[s.PeekChar[]] DO i _ i*10 + (s.GetChar[]-'0); ENDLOOP; }; ParseAddress: PROC [s: IO.STREAM] RETURNS [a: IP.Address] = { <> WHILE s.PeekChar[] = ' DO [] _ s.GetChar[]; ENDLOOP; IF s.PeekChar[] = '[ THEN [] _ s.GetChar[]; FOR i: INT IN [0..3] DO a[i] _ AToI[s]; IF ~s.EndOf[] AND s.PeekChar[] = '. THEN [] _ s.GetChar[]; ENDLOOP; IF ~s.EndOf[] AND s.PeekChar[] = '] THEN [] _ s.GetChar[]; }; SetAddress: Commander.CommandProc = { out: IO.STREAM _ cmd.out; commandLineStream: IO.STREAM _ IO.RIS[cmd.commandLine]; remoteAddress _ ParseAddress[commandLineStream]; localAddress _ ParseAddress[commandLineStream]; out.PutF["[%g.%g.%g.%g]\n", IO.int[remoteAddress[0]], IO.int[remoteAddress[1]], IO.int[remoteAddress[2]], IO.int[remoteAddress[3]]]; }; <> Commander.Register["SetEchoAddress", SetAddress, "Set the address to aim echos at (setecho remote local)."]; Commander.Register["SendEchoMe", Send, "Send an echo me packet."]; END. << >>