StateToRope:
PROC [state: ConnectionState]
RETURNS [stateRope: Rope.
ROPE] = {
SELECT state
FROM
closed => stateRope ← "CLS";
listen => stateRope ← "LSN";
synSent => stateRope ← "SSN";
synRcvd => stateRope ← "SRD";
established => stateRope ← "EST";
finWait1 => stateRope ← "FW1";
finWait2 => stateRope ← "FW2";
closeWait => stateRope ← "CWT";
closing => stateRope ← "CLG";
lastAck => stateRope ← "LAK";
timeWait => stateRope ← "TWT"
ENDCASE; };
PrintTCPPacket:
PUBLIC
ENTRY
PROC [handle: TCPOps.TCPHandle, data: IPDefs.Datagram, dir: Direction] =
TRUSTED {
Print or log TCP packets. The following information is printed for each packet:
state of Connection
Received, Sent or Retransmitted (R, S or X)
Control Flags (Urgent, Ack, Push, Reset, SYN, FIN)
Sequence number mod 100000
Ack number mod 100000
Window
length (number of bytes of TCP header and data)
source Address and Port -> Destination Address and Port
tcpHdrPtr: TCPHeaderP ← LOOPHOLE[@data.data];
dirString, stateString, ctlString, time: Rope.ROPE;
IF pktFile = NIL AND logFile = NIL THEN RETURN;
time ← Convert.RopeFromTime[
from: BasicTime.Now[], start: hours, end: seconds, useAMPM: FALSE, includeZone: FALSE];
SELECT dir
FROM
fromNet => dirString ← "R";
toNet => dirString ← "S";
rexmitToNet => dirString ← "X"
ENDCASE;
IF handle =
NIL
THEN
stateString ← "CLS"
ELSE
stateString ← StateToRope[handle.state];
ctlString ← "";
IF tcpHdrPtr.urg THEN ctlString ← ctlString.Cat["U"];
IF tcpHdrPtr.ack THEN ctlString ← ctlString.Cat["A"];
IF tcpHdrPtr.psh THEN ctlString ← ctlString.Cat["P"];
IF tcpHdrPtr.rst THEN ctlString ← ctlString.Cat["R"];
IF tcpHdrPtr.syn THEN ctlString ← ctlString.Cat["S"];
IF tcpHdrPtr.fin THEN ctlString ← ctlString.Cat["F"];
IF pktFile #
NIL
THEN {
pktFile.PutChar['\n];
PutAddr[pktFile, data.inHdr.source];
pktFile.PutF[" %g -> ", IO.int[tcpHdrPtr.sourcePort]];
PutAddr[pktFile, data.inHdr.destination];
pktFile.PutF[" %g\n", IO.int[tcpHdrPtr.dstnPort]];
pktFile.PutF[" %g %g %6g ", IO.rope[stateString], IO.rope[dirString], IO.rope[ctlString]];
pktFile.PutF["%7g %7g %7g %7g\n", IO.int[Flip[tcpHdrPtr.seqNumber] MOD 100000], IO.int[Flip[tcpHdrPtr.ackNumber] MOD 100000], IO.int[tcpHdrPtr.window], IO.int[data.dataLength]];
PutData[pktFile, data, dir = fromNet]; };
IF logFile #
NIL
THEN {
logFile.PutChar['\n];
logFile.PutF["%g ", IO.rope[time]];
PutAddr[logFile, data.inHdr.source];
logFile.PutF[" %g -> ", IO.int[tcpHdrPtr.sourcePort]];
PutAddr[logFile, data.inHdr.destination];
logFile.PutF[" %g\n", IO.int[tcpHdrPtr.dstnPort]];
logFile.PutF[" %g %g %6g ", IO.rope[stateString], IO.rope[dirString], IO.rope[ctlString]];
logFile.PutF["%7g %7g %7g %7g\n", IO.int[Flip[tcpHdrPtr.seqNumber] MOD 100000], IO.int[Flip[tcpHdrPtr.ackNumber] MOD 100000], IO.int[tcpHdrPtr.window], IO.int[data.dataLength]];
PutData[logFile, data, dir = fromNet];
logFile.Flush[]; }; };
PrintStateChange:
PUBLIC
ENTRY
PROC [handle: TCPOps.TCPHandle, newState: TCPOps.ConnectionState] = {
Print or log state transitions.
old, new, time: Rope.ROPE;
IF pktFile = NIL AND logFile = NIL THEN RETURN;
time ← Convert.RopeFromTime[
from: BasicTime.Now[], start: hours, end: seconds, useAMPM: FALSE, includeZone: FALSE];
old ← StateToRope[handle.state];
new ← StateToRope[newState];
IF pktFile #
NIL
THEN {
pktFile.PutChar['\n];
pktFile.PutF["[ME] %g <-> ", IO.int[handle.localPort]];
PutAddr[pktFile, handle.foreignAddr];
pktFile.PutF[" %g", IO.int[handle.foreignPort]];
pktFile.PutF[" %g -> %g\n", IO.rope[old], IO.rope[new]]; };
IF logFile #
NIL
THEN {
logFile.PutF["\n%g ", IO.rope[time]];
logFile.PutF["[ME] %g <-> ", IO.int[handle.localPort]];
PutAddr[logFile, handle.foreignAddr];
logFile.PutF[" %g", IO.int[handle.foreignPort]];
logFile.PutF[" %g -> %g\n", IO.rope[old], IO.rope[new]];
logFile.Flush[]; }; };