TCP State Machine Interactive Diagram

const EDGES = [ {from:'CLOSED',to:'LISTEN',label:'passive open\nlisten()'}, {from:'CLOSED',to:'SYN_SENT',label:'active open\nconnect()'}, {from:'LISTEN',to:'SYN_RCVD',label:'rcv SYN\nsnd SYN-ACK'}, {from:'SYN_SENT',to:'ESTABLISHED',label:'rcv SYN-ACK\nsnd ACK'}, {from:'SYN_SENT',to:'SYN_RCVD',label:'rcv SYN\n(simultaneous)'}, {from:'SYN_RCVD',to:'ESTABLISHED',label:'rcv ACK'}, {from:'SYN_RCVD',to:'FIN_WAIT_1',label:'close()\nsnd FIN'}, {from:'ESTABLISHED',to:'FIN_WAIT_1',label:'close()\nsnd FIN'}, {from:'ESTABLISHED',to:'CLOSE_WAIT',label:'rcv FIN\nsnd ACK'}, {from:'FIN_WAIT_1',to:'FIN_WAIT_2',label:'rcv ACK'}, {from:'FIN_WAIT_1',to:'CLOSING',label:'rcv FIN\nsnd ACK'}, {from:'FIN_WAIT_1',to:'TIME_WAIT',label:'rcv FIN+ACK\nsnd ACK'}, {from:'FIN_WAIT_2',to:'TIME_WAIT',label:'rcv FIN\nsnd ACK'}, {from:'CLOSE_WAIT',to:'LAST_ACK',label:'close()\nsnd FIN'}, {from:'CLOSING',to:'TIME_WAIT',label:'rcv ACK'}, {from:'LAST_ACK',to:'CLOSED',label:'rcv ACK'}, {from:'TIME_WAIT',to:'CLOSED',label:'2×MSL\ntimeout'}, ]; const positions = { CLOSED: {x:400,y:50}, LISTEN: {x:150,y:150}, SYN_SENT: {x:650,y:150}, SYN_RCVD: {x:150,y:280}, ESTABLISHED: {x:400,y:280}, FIN_WAIT_1: {x:650,y:280}, CLOSE_WAIT: {x:150,y:410}, FIN_WAIT_2: {x:650,y:410}, CLOSING: {x:500,y:410}, LAST_ACK: {x:150,y:540}, TIME_WAIT: {x:650,y:540}, }; const cy = cytoscape({ container: document.getElementById('cy'), elements: [ ...Object.keys(STATE_DATA).map(id => ({ data: { id, label: id.replace(/_/g,' ') }, position: positions[id] || {x:400,y:300}, })), ...EDGES.map((e,i) => ({ data: { id:`e${i}`, source:e.from, target:e.to, label:e.label }, })), ], style: [ { selector: 'node', style: { 'label': 'data(label)', 'text-wrap': 'wrap', 'width': 110, 'height': 44, 'shape': 'roundrectangle', 'background-color': ele => STATE_DATA[ele.id()]?.color || '#0f3460', 'color': '#fff', 'font-size': 11, 'font-weight': 'bold', 'text-valign': 'center', 'text-halign': 'center', 'border-width': 2, 'border-color': '#fff', }}, { selector: 'node:selected', style: { 'border-color': '#ffd200', 'border-width': 3, 'box-shadow': '0 0 8px #ffd200', }}, { selector: 'edge', style: { 'label': 'data(label)', 'curve-style': 'bezier', 'target-arrow-shape': 'triangle', 'arrow-scale': 1.2, 'line-color': '#667', 'target-arrow-color': '#667', 'font-size': 9, 'text-wrap': 'wrap', 'text-background-color': '#fff', 'text-background-opacity': 0.85, 'text-background-padding': 2, 'color': '#333', 'width': 1.5, }}, ], layout: { name: 'preset' }, userZoomingEnabled: true, userPanningEnabled: true, }); cy.on('tap', 'node', function(evt) { const id = evt.target.id(); const d = STATE_DATA[id]; if (!d) return; const diag = d.diagnosis ? `
Diagnosis: ${d.diagnosis}
` : ''; document.getElementById('detailContent').innerHTML = `

${id.replace(/_/g,' ')}

Description:${d.desc}
Trigger:${d.event}
Packets:${d.packet}
Timer:${d.timer}
${diag}`; }); cy.fit(cy.nodes(), 30);