ZealOS/docs/Home/Net/Protocols/TCP/TCP.CC.html
TomAwezome 1b75d91002 Fix Mount AHCI Port selection.
Add arg to SATARep to specify drive types to show.
Add checks in AHCIPortInit to verify port signatures, add helper method to get signatures from port.
2021-08-02 16:40:05 -04:00

1593 lines
136 KiB
HTML
Executable file

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=US-ASCII">
<meta name="generator" content="ZealOS V0.13">
<style type="text/css">
body {background-color:#fef1f0;}
.cF0{color:#000000;background-color:#fef1f0;}
.cF1{color:#0148a4;background-color:#fef1f0;}
.cF2{color:#3b7901;background-color:#fef1f0;}
.cF3{color:#057c7e;background-color:#fef1f0;}
.cF4{color:#bb2020;background-color:#fef1f0;}
.cF5{color:#9e42ae;background-color:#fef1f0;}
.cF6{color:#b57901;background-color:#fef1f0;}
.cF7{color:#b2b6af;background-color:#fef1f0;}
.cF8{color:#555753;background-color:#fef1f0;}
.cF9{color:#678fbb;background-color:#fef1f0;}
.cFA{color:#82bc49;background-color:#fef1f0;}
.cFB{color:#0097a2;background-color:#fef1f0;}
.cFC{color:#e26a6a;background-color:#fef1f0;}
.cFD{color:#c671bc;background-color:#fef1f0;}
.cFE{color:#c7ab00;background-color:#fef1f0;}
.cFF{color:#fef1f0;background-color:#fef1f0;}
</style>
</head>
<body>
<pre style="font-family:monospace;font-size:12pt">
<a name="l1"></a><span class=cF0>
<a name="l2"></a></span><span class=cF1>U0</span><span class=cF0> TCPGlobalsInit()
<a name="l3"></a>{
<a name="l4"></a> tcp_globals.bound_socket_tree = </span><span class=cF3>NULL</span><span class=cF0>;
<a name="l5"></a> tcp_globals.next_source_port = </span><span class=cFE>0</span><span class=cF0>;
<a name="l6"></a>}
<a name="l7"></a>
<a name="l8"></a></span><span class=cF1>Bool</span><span class=cF0> IsTCPStateSync(CTCPSocket *tcp_socket)
<a name="l9"></a>{
<a name="l10"></a> </span><span class=cF1>switch</span><span class=cF0> (tcp_socket-&gt;state)
<a name="l11"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l12"></a> </span><span class=cF1>case</span><span class=cF0> TCP_STATE_ESTABLISHED:
<a name="l13"></a> </span><span class=cF1>case</span><span class=cF0> TCP_STATE_FIN_WAIT1:
<a name="l14"></a> </span><span class=cF1>case</span><span class=cF0> TCP_STATE_FIN_WAIT2:
<a name="l15"></a> </span><span class=cF1>case</span><span class=cF0> TCP_STATE_CLOSE_WAIT:
<a name="l16"></a> </span><span class=cF1>case</span><span class=cF0> TCP_STATE_CLOSING:
<a name="l17"></a> </span><span class=cF1>case</span><span class=cF0> TCP_STATE_LAST_ACK:
<a name="l18"></a> </span><span class=cF1>case</span><span class=cF0> TCP_STATE_TIME_WAIT:
<a name="l19"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>TRUE</span><span class=cF0>;
<a name="l20"></a> </span><span class=cF1>default</span><span class=cF0>:
<a name="l21"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>FALSE</span><span class=cF0>;
<a name="l22"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l23"></a>}
<a name="l24"></a>
<a name="l25"></a></span><span class=cF2>// TODO: Merge IPV4Checksum, TCPChecksumPartial, and TCPChecksumFinal into 1.</span><span class=cF0>
<a name="l26"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2> All use same alg.</span><span class=cF0>
<a name="l27"></a></span><span class=cF9>U16</span><span class=cF0> TCPChecksumPartial(</span><span class=cF9>U32</span><span class=cF0> sum, </span><span class=cF1>U8</span><span class=cF0> *header, </span><span class=cF9>I64</span><span class=cF0> length)
<a name="l28"></a>{ </span><span class=cF2>// same algorithm as IPV4Checksum, except sum is arg. First half.</span><span class=cF0>
<a name="l29"></a> </span><span class=cF2>//todo. make names clearer, and better comments.</span><span class=cF0>
<a name="l30"></a> </span><span class=cF9>I64</span><span class=cF0> nleft = length;
<a name="l31"></a> </span><span class=cF9>U16</span><span class=cF0> *w = header;
<a name="l32"></a>
<a name="l33"></a> </span><span class=cF1>while</span><span class=cF0> (nleft &gt; </span><span class=cFE>1</span><span class=cF0>)
<a name="l34"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l35"></a> sum += *w++;
<a name="l36"></a> nleft -= </span><span class=cFE>2</span><span class=cF0>;
<a name="l37"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l38"></a>
<a name="l39"></a> </span><span class=cF1>return</span><span class=cF0> sum;
<a name="l40"></a>}
<a name="l41"></a>
<a name="l42"></a></span><span class=cF9>U16</span><span class=cF0> TCPChecksumFinal(</span><span class=cF9>U32</span><span class=cF0> sum, </span><span class=cF1>U8</span><span class=cF0> *header, </span><span class=cF9>I64</span><span class=cF0> length)
<a name="l43"></a>{ </span><span class=cF2>// same algorithm as IPV4Checksum, except sum is arg. Both halves.</span><span class=cF0>
<a name="l44"></a> </span><span class=cF2>//todo. make names clearer, and better comments.</span><span class=cF0>
<a name="l45"></a> </span><span class=cF9>I64</span><span class=cF0> nleft = length;
<a name="l46"></a> </span><span class=cF9>U16</span><span class=cF0> *w = header;
<a name="l47"></a>
<a name="l48"></a> </span><span class=cF1>while</span><span class=cF0> (nleft &gt; </span><span class=cFE>1</span><span class=cF0>)
<a name="l49"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l50"></a> sum += *w++;
<a name="l51"></a> nleft -= </span><span class=cFE>2</span><span class=cF0>;
<a name="l52"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l53"></a>
<a name="l54"></a> </span><span class=cF2>// &quot;mop up an odd byte, if necessary&quot;</span><span class=cF0>
<a name="l55"></a> </span><span class=cF1>if</span><span class=cF0> (nleft == </span><span class=cFE>1</span><span class=cF0>)
<a name="l56"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l57"></a> sum += *w &amp; </span><span class=cFE>0x00FF</span><span class=cF0>;
<a name="l58"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l59"></a>
<a name="l60"></a> </span><span class=cF2>// &quot;add back carry outs from top 16 bits to low 16 bits&quot;</span><span class=cF0>
<a name="l61"></a> sum = sum &gt;&gt; </span><span class=cFE>16</span><span class=cF0> + sum &amp; </span><span class=cFE>0xFFFF</span><span class=cF0>; </span><span class=cF2>// &quot;add hi 16 to low 16&quot;</span><span class=cF0>
<a name="l62"></a> sum += sum &gt;&gt; </span><span class=cFE>16</span><span class=cF0>; </span><span class=cF2>// add carry</span><span class=cF0>
<a name="l63"></a> </span><span class=cF1>return</span><span class=cF0> ~sum &amp; </span><span class=cFE>0xFFFF</span><span class=cF0>;
<a name="l64"></a>
<a name="l65"></a>}
<a name="l66"></a>
<a name="l67"></a></span><span class=cF9>I64</span><span class=cF0> TCPPacketAllocate(</span><span class=cF1>U8</span><span class=cF0> **frame_out,
<a name="l68"></a> </span><span class=cF9>U32</span><span class=cF0> source_ip,
<a name="l69"></a> </span><span class=cF9>U16</span><span class=cF0> source_port,
<a name="l70"></a> </span><span class=cF9>U32</span><span class=cF0> destination_ip,
<a name="l71"></a> </span><span class=cF9>U16</span><span class=cF0> destination_port,
<a name="l72"></a> </span><span class=cF9>U32</span><span class=cF0> seq_num,
<a name="l73"></a> </span><span class=cF9>U32</span><span class=cF0> ack_num,
<a name="l74"></a> </span><span class=cF1>U8</span><span class=cF0> flags,
<a name="l75"></a> </span><span class=cF9>I64</span><span class=cF0> length)
<a name="l76"></a>{
<a name="l77"></a> </span><span class=cF1>U8</span><span class=cF0> *tcp_frame;
<a name="l78"></a> </span><span class=cF9>I64</span><span class=cF0> de_index;
<a name="l79"></a> CTCPHeader *header;
<a name="l80"></a>
<a name="l81"></a> de_index = IPV4PacketAllocate(&amp;tcp_frame,
<a name="l82"></a> IP_PROTOCOL_TCP,
<a name="l83"></a> source_ip,
<a name="l84"></a> destination_ip,
<a name="l85"></a> </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CTCPHeader</span><span class=cF7>)</span><span class=cF0> + length);
<a name="l86"></a> </span><span class=cF1>if</span><span class=cF0> (de_index &lt; </span><span class=cFE>0</span><span class=cF0>)
<a name="l87"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l88"></a> NetLog(</span><span class=cF6>&quot;TCP PACKET ALLOCATE: Ethernet Frame Allocate failed.&quot;</span><span class=cF0>);
<a name="l89"></a> </span><span class=cF1>return</span><span class=cF0> de_index;
<a name="l90"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l91"></a>
<a name="l92"></a> header = tcp_frame;
<a name="l93"></a>
<a name="l94"></a> header-&gt;source_port = </span><span class=cF5>EndianU16</span><span class=cF0>(source_port);
<a name="l95"></a> header-&gt;destination_port = </span><span class=cF5>EndianU16</span><span class=cF0>(destination_port);
<a name="l96"></a>
<a name="l97"></a> NetDebug(</span><span class=cF6>&quot;TCP PACKET ALLOCATE: Outputting header port src/dest 0x%0X/0x%0X:&quot;</span><span class=cF0>,
<a name="l98"></a> header-&gt;source_port, header-&gt;destination_port);
<a name="l99"></a>
<a name="l100"></a> header-&gt;seq_num = </span><span class=cF5>EndianU32</span><span class=cF0>(seq_num);
<a name="l101"></a> header-&gt;ack_num = </span><span class=cF5>EndianU32</span><span class=cF0>(ack_num);
<a name="l102"></a> header-&gt;data_offset = (</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CTCPHeader</span><span class=cF7>)</span><span class=cF0> / </span><span class=cFE>4</span><span class=cF0>) &lt;&lt; </span><span class=cFE>4</span><span class=cF0>; </span><span class=cF2>// ???</span><span class=cF0>
<a name="l103"></a> header-&gt;flags = flags;
<a name="l104"></a> header-&gt;window_size = </span><span class=cF5>EndianU16</span><span class=cF0>(TCP_WINDOW_SIZE / </span><span class=cFE>2</span><span class=cF0>);</span><span class=cF2>// TODO: What is window size supposed to be ?</span><span class=cF0>
<a name="l105"></a> header-&gt;checksum = </span><span class=cFE>0</span><span class=cF0>;
<a name="l106"></a> header-&gt;urgent_pointer = </span><span class=cFE>0</span><span class=cF0>;
<a name="l107"></a>
<a name="l108"></a> *frame_out = tcp_frame + </span><span class=cF1>sizeof</span><span class=cF0>(CTCPHeader);
<a name="l109"></a>
<a name="l110"></a> </span><span class=cF1>return</span><span class=cF0> de_index;
<a name="l111"></a>}
<a name="l112"></a>
<a name="l113"></a></span><span class=cF1>U0</span><span class=cF0> TCPPacketFinish(</span><span class=cF9>I64</span><span class=cF0> de_index,
<a name="l114"></a> </span><span class=cF9>U32</span><span class=cF0> source_ip,
<a name="l115"></a> </span><span class=cF9>U32</span><span class=cF0> destination_ip,
<a name="l116"></a> </span><span class=cF1>U8</span><span class=cF0> *frame,
<a name="l117"></a> </span><span class=cF9>I64</span><span class=cF0> length,
<a name="l118"></a> CTCPAckQueue **send_buffer_out=</span><span class=cF3>NULL</span><span class=cF0>)
<a name="l119"></a>{
<a name="l120"></a> CTCPHeader *header = frame - </span><span class=cF1>sizeof</span><span class=cF0>(CTCPHeader);
<a name="l121"></a> CTCPPseudoHeader *pseudoheader = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CTCPPseudoHeader</span><span class=cF7>)</span><span class=cF0>);
<a name="l122"></a> </span><span class=cF9>U32</span><span class=cF0> checksum;
<a name="l123"></a> CTCPAckQueue *send_buffer;
<a name="l124"></a>
<a name="l125"></a> pseudoheader-&gt;source_address = </span><span class=cF5>EndianU32</span><span class=cF0>(source_ip);
<a name="l126"></a> pseudoheader-&gt;destination_address = </span><span class=cF5>EndianU32</span><span class=cF0>(destination_ip);
<a name="l127"></a> pseudoheader-&gt;zeros = </span><span class=cFE>0</span><span class=cF0>;
<a name="l128"></a> pseudoheader-&gt;protocol = IP_PROTOCOL_TCP;
<a name="l129"></a> pseudoheader-&gt;tcp_length = </span><span class=cF5>EndianU16</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CTCPHeader</span><span class=cF7>)</span><span class=cF0> + length);
<a name="l130"></a>
<a name="l131"></a> checksum = TCPChecksumPartial(</span><span class=cFE>0</span><span class=cF0>, pseudoheader, </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CTCPPseudoHeader</span><span class=cF7>)</span><span class=cF0>);
<a name="l132"></a> header-&gt;checksum = TCPChecksumFinal(checksum, header, </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CTCPHeader</span><span class=cF7>)</span><span class=cF0> + length);
<a name="l133"></a>
<a name="l134"></a> </span><span class=cF1>if</span><span class=cF0> (send_buffer_out)
<a name="l135"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l136"></a> send_buffer = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CTCPAckQueue</span><span class=cF7>)</span><span class=cF0>);
<a name="l137"></a>
<a name="l138"></a> send_buffer-&gt;time_sent = </span><span class=cF5>tS</span><span class=cF0>;
<a name="l139"></a> send_buffer-&gt;retries = </span><span class=cFE>0</span><span class=cF0>;
<a name="l140"></a> send_buffer-&gt;start_seq_num = </span><span class=cF5>EndianU32</span><span class=cF0>(header-&gt;seq_num);
<a name="l141"></a> send_buffer-&gt;end_seq_num = </span><span class=cFE>0</span><span class=cF0>; </span><span class=cF2>// must set this upstream</span><span class=cF0>
<a name="l142"></a> send_buffer-&gt;tcp_packet_size = length;
<a name="l143"></a> send_buffer-&gt;tcp_packet = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CTCPHeader</span><span class=cF7>)</span><span class=cF0> + length);
<a name="l144"></a>
<a name="l145"></a> </span><span class=cF5>MemCopy</span><span class=cF0>(send_buffer-&gt;tcp_packet, frame, </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CTCPHeader</span><span class=cF7>)</span><span class=cF0> + length);
<a name="l146"></a>
<a name="l147"></a> *send_buffer_out = send_buffer; </span><span class=cF2>// set output param as new send buffer</span><span class=cF0>
<a name="l148"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l149"></a>
<a name="l150"></a> IPV4PacketFinish(de_index);
<a name="l151"></a>}
<a name="l152"></a>
<a name="l153"></a></span><span class=cF9>I64</span><span class=cF0> TCPSend(</span><span class=cF9>U32</span><span class=cF0> source_ip,
<a name="l154"></a> </span><span class=cF9>U16</span><span class=cF0> source_port,
<a name="l155"></a> </span><span class=cF9>U32</span><span class=cF0> destination_ip,
<a name="l156"></a> </span><span class=cF9>U16</span><span class=cF0> destination_port,
<a name="l157"></a> </span><span class=cF9>U32</span><span class=cF0> seq_num,
<a name="l158"></a> </span><span class=cF9>U32</span><span class=cF0> ack_num,
<a name="l159"></a> </span><span class=cF1>U8</span><span class=cF0> flags)
<a name="l160"></a>{ </span><span class=cF2>// send raw unsocketed TCP packet, flags and/or data. Does not store into ACK Queue (Send Buffer).</span><span class=cF0>
<a name="l161"></a>
<a name="l162"></a> </span><span class=cF1>U8</span><span class=cF0> *payload_frame;
<a name="l163"></a> </span><span class=cF9>I64</span><span class=cF0> de_index = TCPPacketAllocate(&amp;payload_frame,
<a name="l164"></a> source_ip,
<a name="l165"></a> source_port,
<a name="l166"></a> destination_ip,
<a name="l167"></a> destination_port,
<a name="l168"></a> seq_num,
<a name="l169"></a> ack_num,
<a name="l170"></a> flags,
<a name="l171"></a> </span><span class=cFE>0</span><span class=cF0>);
<a name="l172"></a> </span><span class=cF1>if</span><span class=cF0> (de_index &lt; </span><span class=cFE>0</span><span class=cF0>)
<a name="l173"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l174"></a> NetErr(</span><span class=cF6>&quot;TCP SEND: TCP Packet Allocate failed.&quot;</span><span class=cF0>);
<a name="l175"></a> </span><span class=cF1>return</span><span class=cF0> de_index;
<a name="l176"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l177"></a>
<a name="l178"></a> TCPPacketFinish(de_index, source_ip, destination_ip, payload_frame, </span><span class=cFE>0</span><span class=cF0>, </span><span class=cF3>NULL</span><span class=cF0>);
<a name="l179"></a>
<a name="l180"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cFE>0</span><span class=cF0>;
<a name="l181"></a>}
<a name="l182"></a>
<a name="l183"></a></span><span class=cF9>I64</span><span class=cF0> TCPSendFlags(CTCPSocket *tcp_socket, </span><span class=cF1>U8</span><span class=cF0> flags)
<a name="l184"></a>{ </span><span class=cF2>// send TCP packet, flags only. Stores into ACK Queue (Send Buffer) if flags SYN or FIN.</span><span class=cF0>
<a name="l185"></a>
<a name="l186"></a> </span><span class=cF1>U8</span><span class=cF0> *payload_frame;
<a name="l187"></a> CSocketAddressStorage *dest = &amp;tcp_socket-&gt;destination_address;
<a name="l188"></a> CSocketAddressStorage *source = &amp;tcp_socket-&gt;source_address;
<a name="l189"></a> CSocketAddressIPV4 *dest_ipv4;
<a name="l190"></a> CSocketAddressIPV6 *dest_ipv6;
<a name="l191"></a> CSocketAddressIPV4 *source_ipv4;
<a name="l192"></a> CSocketAddressIPV6 *source_ipv6;
<a name="l193"></a> </span><span class=cF9>I64</span><span class=cF0> de_index;
<a name="l194"></a> CTCPAckQueue *send_buffer = </span><span class=cF3>NULL</span><span class=cF0>;
<a name="l195"></a> CTCPAckQueue **send_buffer_ptr = </span><span class=cF3>NULL</span><span class=cF0>;
<a name="l196"></a>
<a name="l197"></a> NetDebug(</span><span class=cF6>&quot;TCP SEND FLAGS: Attempting Send using param TCP socket&quot;</span><span class=cF0>);
<a name="l198"></a>
<a name="l199"></a> </span><span class=cF1>switch</span><span class=cF0> (dest-&gt;family)
<a name="l200"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l201"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET:
<a name="l202"></a> dest_ipv4 = dest;
<a name="l203"></a>
<a name="l204"></a> </span><span class=cF1>switch</span><span class=cF0> (source-&gt;family)
<a name="l205"></a> {
<a name="l206"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET:
<a name="l207"></a> source_ipv4 = source;
<a name="l208"></a>
<a name="l209"></a> NetDebug(</span><span class=cF6>&quot;TCP SEND FLAGS: Trying TCP Packet Allocate... port src/dest 0x%0X/0x%0X&quot;</span><span class=cF0>,
<a name="l210"></a> source_ipv4-&gt;port, dest_ipv4-&gt;port);
<a name="l211"></a>
<a name="l212"></a> de_index = TCPPacketAllocate(&amp;payload_frame,
<a name="l213"></a> source_ipv4-&gt;address.address,
<a name="l214"></a> </span><span class=cF5>EndianU16</span><span class=cF7>(</span><span class=cF0>source_ipv4-&gt;port</span><span class=cF7>)</span><span class=cF0>,
<a name="l215"></a> dest_ipv4-&gt;address.address,
<a name="l216"></a> </span><span class=cF5>EndianU16</span><span class=cF7>(</span><span class=cF0>dest_ipv4-&gt;port</span><span class=cF7>)</span><span class=cF0>,
<a name="l217"></a> tcp_socket-&gt;next_send_seq_num,
<a name="l218"></a> tcp_socket-&gt;next_recv_seq_num,
<a name="l219"></a> flags,
<a name="l220"></a> </span><span class=cFE>0</span><span class=cF0>);
<a name="l221"></a> </span><span class=cF1>if</span><span class=cF0> (de_index &lt; </span><span class=cFE>0</span><span class=cF0>)
<a name="l222"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l223"></a> NetErr(</span><span class=cF6>&quot;TCP SEND FLAGS: TCP Packet Allocate failed.&quot;</span><span class=cF0>);
<a name="l224"></a> </span><span class=cF1>return</span><span class=cF0> de_index;
<a name="l225"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l226"></a>
<a name="l227"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l228"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET6:
<a name="l229"></a> source_ipv6 = source;
<a name="l230"></a> NetErr(</span><span class=cF6>&quot;TCP SEND FLAGS: FIXME, IPV6 not implemented yet&quot;</span><span class=cF0>);
<a name="l231"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l232"></a> </span><span class=cF1>case</span><span class=cF0> AF_UNSPEC:
<a name="l233"></a> NetErr(</span><span class=cF6>&quot;TCP SEND FLAGS: Error, TCP Send from AF_UNSPEC\n&quot;</span><span class=cF0>);
<a name="l234"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l235"></a> }
<a name="l236"></a>
<a name="l237"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l238"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET6:
<a name="l239"></a> dest_ipv6 = dest;
<a name="l240"></a> NetErr(</span><span class=cF6>&quot;TCP SEND FLAGS: FIXME, IPV6 not implemented yet&quot;</span><span class=cF0>);
<a name="l241"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l242"></a> </span><span class=cF1>case</span><span class=cF0> AF_UNSPEC:
<a name="l243"></a> NetErr(</span><span class=cF6>&quot;TCP SEND FLAGS: Error, TCP Send to AF_UNSPEC\n&quot;</span><span class=cF0>);
<a name="l244"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l245"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l246"></a>
<a name="l247"></a> </span><span class=cF2>// at this point, a TCP packet has been allocated.</span><span class=cF0>
<a name="l248"></a> </span><span class=cF2>// TODO: Is there a better way to manage links across different address types?</span><span class=cF0>
<a name="l249"></a>
<a name="l250"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;flags, TCPf_SYN</span><span class=cF7>)</span><span class=cF0>)
<a name="l251"></a> tcp_socket-&gt;next_send_seq_num++;
<a name="l252"></a>
<a name="l253"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;flags, TCPf_FIN</span><span class=cF7>)</span><span class=cF0>)
<a name="l254"></a> tcp_socket-&gt;next_send_seq_num++;
<a name="l255"></a>
<a name="l256"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;flags, TCPf_FIN</span><span class=cF7>)</span><span class=cF0> || </span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;flags, TCPf_SYN</span><span class=cF7>)</span><span class=cF0>)
<a name="l257"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l258"></a> send_buffer_ptr = &amp;send_buffer;
<a name="l259"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l260"></a>
<a name="l261"></a>
<a name="l262"></a> </span><span class=cF1>switch</span><span class=cF0> (dest-&gt;family)
<a name="l263"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l264"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET:
<a name="l265"></a> dest_ipv4 = dest;
<a name="l266"></a>
<a name="l267"></a> </span><span class=cF1>switch</span><span class=cF0> (source-&gt;family)
<a name="l268"></a> {
<a name="l269"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET:
<a name="l270"></a> source_ipv4 = source;
<a name="l271"></a>
<a name="l272"></a> TCPPacketFinish(de_index,
<a name="l273"></a> source_ipv4-&gt;address.address,
<a name="l274"></a> dest_ipv4-&gt;address.address,
<a name="l275"></a> payload_frame,
<a name="l276"></a> </span><span class=cFE>0</span><span class=cF0>,
<a name="l277"></a> send_buffer_ptr);
<a name="l278"></a>
<a name="l279"></a> </span><span class=cF1>if</span><span class=cF0> (send_buffer)
<a name="l280"></a> </span><span class=cF7>{</span><span class=cF0> </span><span class=cF2>// modifying ptr should affect our send_buffer variable</span><span class=cF0>
<a name="l281"></a> send_buffer-&gt;end_seq_num = tcp_socket-&gt;next_send_seq_num;
<a name="l282"></a>
<a name="l283"></a> </span><span class=cF2>// append it to the socket, ACK Queue needs to be ready (head)...</span><span class=cF0>
<a name="l284"></a> </span><span class=cF5>QueueInsertRev</span><span class=cF0>(send_buffer, tcp_socket-&gt;ack_queue);
<a name="l285"></a>
<a name="l286"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l287"></a>
<a name="l288"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l289"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET6:
<a name="l290"></a> source_ipv6 = source;
<a name="l291"></a> NetErr(</span><span class=cF6>&quot;TCP SEND FLAGS: FIXME, IPV6 not implemented yet&quot;</span><span class=cF0>);
<a name="l292"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l293"></a> </span><span class=cF1>case</span><span class=cF0> AF_UNSPEC:
<a name="l294"></a> NetErr(</span><span class=cF6>&quot;TCP SEND FLAGS: Error, TCP Send from AF_UNSPEC\n&quot;</span><span class=cF0>);
<a name="l295"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l296"></a> }
<a name="l297"></a>
<a name="l298"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l299"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET6:
<a name="l300"></a> dest_ipv6 = dest;
<a name="l301"></a> NetErr(</span><span class=cF6>&quot;TCP SEND FLAGS: FIXME, IPV6 not implemented yet&quot;</span><span class=cF0>);
<a name="l302"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l303"></a> </span><span class=cF1>case</span><span class=cF0> AF_UNSPEC:
<a name="l304"></a> NetErr(</span><span class=cF6>&quot;TCP SEND FLAGS: Error, TCP Send to AF_UNSPEC\n&quot;</span><span class=cF0>);
<a name="l305"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l306"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l307"></a>}
<a name="l308"></a>
<a name="l309"></a></span><span class=cF9>I64</span><span class=cF0> TCPSendData(CTCPSocket *tcp_socket, </span><span class=cF1>U8</span><span class=cF0> flags, </span><span class=cF1>U8</span><span class=cF0> *data, </span><span class=cF9>I64</span><span class=cF0> length)
<a name="l310"></a>{ </span><span class=cF2>// send TCP packet, flags and data. Stores into ACK Queue (Send Buffer).</span><span class=cF0>
<a name="l311"></a>
<a name="l312"></a> </span><span class=cF1>U8</span><span class=cF0> *payload_frame;
<a name="l313"></a> CSocketAddressStorage *dest = &amp;tcp_socket-&gt;destination_address;
<a name="l314"></a> CSocketAddressStorage *source = &amp;tcp_socket-&gt;source_address;
<a name="l315"></a> CSocketAddressIPV4 *dest_ipv4;
<a name="l316"></a> CSocketAddressIPV6 *dest_ipv6;
<a name="l317"></a> CSocketAddressIPV4 *source_ipv4;
<a name="l318"></a> CSocketAddressIPV6 *source_ipv6;
<a name="l319"></a> </span><span class=cF9>I64</span><span class=cF0> de_index;
<a name="l320"></a> CTCPAckQueue *send_buffer;
<a name="l321"></a>
<a name="l322"></a> NetDebug(</span><span class=cF6>&quot;TCP SEND DATA: Attempting Send using param TCP socket&quot;</span><span class=cF0>);
<a name="l323"></a>
<a name="l324"></a> </span><span class=cF1>switch</span><span class=cF0> (dest-&gt;family)
<a name="l325"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l326"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET:
<a name="l327"></a> dest_ipv4 = dest;
<a name="l328"></a>
<a name="l329"></a> </span><span class=cF1>switch</span><span class=cF0> (source-&gt;family)
<a name="l330"></a> {
<a name="l331"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET:
<a name="l332"></a> source_ipv4 = source;
<a name="l333"></a>
<a name="l334"></a> NetDebug(</span><span class=cF6>&quot;TCP SEND DATA: Trying TCP Packet Allocate... port src/dest 0x%0X/0x%0X&quot;</span><span class=cF0>,
<a name="l335"></a> source_ipv4-&gt;port, dest_ipv4-&gt;port);
<a name="l336"></a>
<a name="l337"></a> de_index = TCPPacketAllocate(&amp;payload_frame,
<a name="l338"></a> source_ipv4-&gt;address.address,
<a name="l339"></a> </span><span class=cF5>EndianU16</span><span class=cF7>(</span><span class=cF0>source_ipv4-&gt;port</span><span class=cF7>)</span><span class=cF0>,
<a name="l340"></a> dest_ipv4-&gt;address.address,
<a name="l341"></a> </span><span class=cF5>EndianU16</span><span class=cF7>(</span><span class=cF0>dest_ipv4-&gt;port</span><span class=cF7>)</span><span class=cF0>,
<a name="l342"></a> tcp_socket-&gt;next_send_seq_num,
<a name="l343"></a> tcp_socket-&gt;next_recv_seq_num,
<a name="l344"></a> flags,
<a name="l345"></a> length);
<a name="l346"></a> </span><span class=cF1>if</span><span class=cF0> (de_index &lt; </span><span class=cFE>0</span><span class=cF0>)
<a name="l347"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l348"></a> NetLog(</span><span class=cF6>&quot;TCP SEND DATA: TCP Packet Allocate failed.&quot;</span><span class=cF0>);
<a name="l349"></a> </span><span class=cF1>return</span><span class=cF0> de_index;
<a name="l350"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l351"></a>
<a name="l352"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l353"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET6:
<a name="l354"></a> source_ipv6 = source;
<a name="l355"></a> NetErr(</span><span class=cF6>&quot;TCP SEND DATA: FIXME, IPV6 not implemented yet&quot;</span><span class=cF0>);
<a name="l356"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l357"></a> </span><span class=cF1>case</span><span class=cF0> AF_UNSPEC:
<a name="l358"></a> NetErr(</span><span class=cF6>&quot;TCP SEND DATA: Error, TCP Send from AF_UNSPEC\n&quot;</span><span class=cF0>);
<a name="l359"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l360"></a> }
<a name="l361"></a>
<a name="l362"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l363"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET6:
<a name="l364"></a> dest_ipv6 = dest;
<a name="l365"></a> NetErr(</span><span class=cF6>&quot;TCP SEND DATA: FIXME, IPV6 not implemented yet&quot;</span><span class=cF0>);
<a name="l366"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l367"></a> </span><span class=cF1>case</span><span class=cF0> AF_UNSPEC:
<a name="l368"></a> NetErr(</span><span class=cF6>&quot;TCP SEND DATA: Error, TCP Send to AF_UNSPEC\n&quot;</span><span class=cF0>);
<a name="l369"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l370"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l371"></a>
<a name="l372"></a> </span><span class=cF2>// at this point, a TCP packet has been allocated.</span><span class=cF0>
<a name="l373"></a> </span><span class=cF2>// TODO: Is there a better way to manage links across different address types?</span><span class=cF0>
<a name="l374"></a>
<a name="l375"></a> </span><span class=cF1>if</span><span class=cF0> (length)
<a name="l376"></a> </span><span class=cF5>MemCopy</span><span class=cF0>(payload_frame, data, length);
<a name="l377"></a>
<a name="l378"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;flags, TCPf_SYN</span><span class=cF7>)</span><span class=cF0>)
<a name="l379"></a> tcp_socket-&gt;next_send_seq_num++;
<a name="l380"></a>
<a name="l381"></a> tcp_socket-&gt;next_send_seq_num += length;
<a name="l382"></a>
<a name="l383"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;flags, TCPf_FIN</span><span class=cF7>)</span><span class=cF0>)
<a name="l384"></a> tcp_socket-&gt;next_send_seq_num++;
<a name="l385"></a>
<a name="l386"></a> </span><span class=cF1>switch</span><span class=cF0> (dest-&gt;family)
<a name="l387"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l388"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET:
<a name="l389"></a> dest_ipv4 = dest;
<a name="l390"></a>
<a name="l391"></a> </span><span class=cF1>switch</span><span class=cF0> (source-&gt;family)
<a name="l392"></a> {
<a name="l393"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET:
<a name="l394"></a> source_ipv4 = source;
<a name="l395"></a>
<a name="l396"></a> TCPPacketFinish(de_index,
<a name="l397"></a> source_ipv4-&gt;address.address,
<a name="l398"></a> dest_ipv4-&gt;address.address,
<a name="l399"></a> payload_frame,
<a name="l400"></a> length,
<a name="l401"></a> &amp;send_buffer);
<a name="l402"></a>
<a name="l403"></a> send_buffer-&gt;end_seq_num = tcp_socket-&gt;next_send_seq_num;
<a name="l404"></a>
<a name="l405"></a> </span><span class=cF2>// append it to the socket, ACK Queue needs to be ready (head)...</span><span class=cF0>
<a name="l406"></a> </span><span class=cF5>QueueInsertRev</span><span class=cF0>(send_buffer, tcp_socket-&gt;ack_queue);
<a name="l407"></a>
<a name="l408"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l409"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET6:
<a name="l410"></a> source_ipv6 = source;
<a name="l411"></a> NetErr(</span><span class=cF6>&quot;TCP SEND DATA: FIXME, IPV6 not implemented yet&quot;</span><span class=cF0>);
<a name="l412"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l413"></a> </span><span class=cF1>case</span><span class=cF0> AF_UNSPEC:
<a name="l414"></a> NetErr(</span><span class=cF6>&quot;TCP SEND DATA: Error, TCP Send from AF_UNSPEC\n&quot;</span><span class=cF0>);
<a name="l415"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l416"></a> }
<a name="l417"></a>
<a name="l418"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l419"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET6:
<a name="l420"></a> dest_ipv6 = dest;
<a name="l421"></a> NetErr(</span><span class=cF6>&quot;TCP SEND DATA: FIXME, IPV6 not implemented yet&quot;</span><span class=cF0>);
<a name="l422"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l423"></a> </span><span class=cF1>case</span><span class=cF0> AF_UNSPEC:
<a name="l424"></a> NetErr(</span><span class=cF6>&quot;TCP SEND DATA: Error, TCP Send to AF_UNSPEC\n&quot;</span><span class=cF0>);
<a name="l425"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l426"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l427"></a>}
<a name="l428"></a>
<a name="l429"></a></span><span class=cF9>I64</span><span class=cF0> TCPPacketParse(CTCPHeader **header_out,
<a name="l430"></a> </span><span class=cF1>U8</span><span class=cF0> **data_out,
<a name="l431"></a> </span><span class=cF9>I64</span><span class=cF0> *length_out,
<a name="l432"></a> CIPV4Packet *packet)
<a name="l433"></a>{
<a name="l434"></a> CTCPHeader *header = packet-&gt;data;
<a name="l435"></a> </span><span class=cF9>I64</span><span class=cF0> header_length = (header-&gt;data_offset &gt;&gt; </span><span class=cFE>4</span><span class=cF0>) * </span><span class=cFE>4</span><span class=cF0>; </span><span class=cF2>// ?? why</span><span class=cF0>
<a name="l436"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>U32</span><span class=cF0> </span><span class=cF2> checksum, sum;</span><span class=cF0>
<a name="l437"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>CTCPPseudoHeader *pseudoheader</span><span class=cF0> </span><span class=cF2>= CAlloc(sizeof(CTCPPseudoHeader));</span><span class=cF0>
<a name="l438"></a>
<a name="l439"></a> </span><span class=cF2>// TODO: Validate packet-&gt;length !</span><span class=cF0>
<a name="l440"></a>
<a name="l441"></a> </span><span class=cF2>// Verify Checksum:</span><span class=cF0>
<a name="l442"></a></span><span class=cF2>/*</span><span class=cF0> </span><span class=cF2>NetWarn(&quot;DEBUG: TCPPACKETPARSE:</span><span class=cF0> </span><span class=cF2>0x%X = checksum from packet, verifying...&quot;, EndianU16(header-&gt;checksum));</span><span class=cF0>
<a name="l443"></a> </span><span class=cF2>pseudoheader-&gt;source_address</span><span class=cF0> </span><span class=cF2>= EndianU32(packet-&gt;source_ip_address);</span><span class=cF0>
<a name="l444"></a> </span><span class=cF2>pseudoheader-&gt;destination_address</span><span class=cF0> </span><span class=cF2>= EndianU32(packet-&gt;destination_ip_address);</span><span class=cF0>
<a name="l445"></a> </span><span class=cF2>pseudoheader-&gt;zeros</span><span class=cF0> </span><span class=cF2>= 0;</span><span class=cF0>
<a name="l446"></a> </span><span class=cF2>pseudoheader-&gt;protocol</span><span class=cF0> </span><span class=cF2>= IP_PROTOCOL_TCP;</span><span class=cF0>
<a name="l447"></a> </span><span class=cF2>pseudoheader-&gt;tcp_length</span><span class=cF0> </span><span class=cF2>= EndianU16(packet-&gt;length);</span><span class=cF0>
<a name="l448"></a>
<a name="l449"></a> </span><span class=cF2>checksum = TCPChecksumPartial(0, pseudoheader, sizeof(CTCPPseudoHeader));</span><span class=cF0>
<a name="l450"></a> </span><span class=cF2>NetWarn(&quot;DEBUG: TCPPACKETPARSE:</span><span class=cF0> </span><span class=cF2>0x%X = partial checksum&quot;, checksum);</span><span class=cF0>
<a name="l451"></a>
<a name="l452"></a> </span><span class=cF2>Free(pseudoheader); // No longer needed, discard</span><span class=cF0>
<a name="l453"></a>
<a name="l454"></a> </span><span class=cF2>sum = TCPChecksumFinal(checksum, header, packet-&gt;length);</span><span class=cF0>
<a name="l455"></a>
<a name="l456"></a> </span><span class=cF2>if (sum != EndianU16(header-&gt;checksum))</span><span class=cF0>
<a name="l457"></a> </span><span class=cF2>{</span><span class=cF0>
<a name="l458"></a> </span><span class=cF2>NetErr(&quot;DEBUG: TCPPACKETPARSE:</span><span class=cF0> </span><span class=cF2>0x%X = NOT MATCH&quot;, sum);</span><span class=cF0>
<a name="l459"></a> </span><span class=cF2>//return -1; // is checksum not being 0 in received header going to mess this up?..</span><span class=cF0>
<a name="l460"></a> </span><span class=cF2>}</span><span class=cF0>
<a name="l461"></a> </span><span class=cF2>// Checksum verified.</span><span class=cF0>
<a name="l462"></a></span><span class=cF2>*/</span><span class=cF0>
<a name="l463"></a>
<a name="l464"></a> *header_out = header;
<a name="l465"></a> *data_out = packet-&gt;data + header_length;
<a name="l466"></a> *length_out = packet-&gt;length - header_length;
<a name="l467"></a>
<a name="l468"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cFE>0</span><span class=cF0>;
<a name="l469"></a>}
<a name="l470"></a>
<a name="l471"></a></span><span class=cF1>U0</span><span class=cF0> TCPAcknowledgePacket(CTCPSocket *tcp_socket, </span><span class=cF9>U32</span><span class=cF0> segment_ack)
<a name="l472"></a>{
<a name="l473"></a> </span><span class=cF1>F64</span><span class=cF0> time = </span><span class=cF5>tS</span><span class=cF0>;
<a name="l474"></a> </span><span class=cF1>F64</span><span class=cF0> rtt;
<a name="l475"></a> CTCPAckQueue *send_buffer = tcp_socket-&gt;ack_queue-&gt;next;
<a name="l476"></a> CTCPAckQueue *send_buffer_temp;
<a name="l477"></a> </span><span class=cF9>I64</span><span class=cF0> segment_ack_relative;
<a name="l478"></a> </span><span class=cF9>I64</span><span class=cF0> send_next_relative;
<a name="l479"></a>
<a name="l480"></a> NetDebug(</span><span class=cF6>&quot;TCP ACKNOWLEDGE PACKET: Looking to see if there are any send buffers&quot;</span><span class=cF0>);
<a name="l481"></a>
<a name="l482"></a> </span><span class=cF1>while</span><span class=cF0> (send_buffer != tcp_socket-&gt;ack_queue)
<a name="l483"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l484"></a> segment_ack_relative = (segment_ack - send_buffer-&gt;end_seq_num) &amp; </span><span class=cFE>0xFFFFFFFF</span><span class=cF0>;
<a name="l485"></a> send_next_relative = (tcp_socket-&gt;next_send_seq_num - send_buffer-&gt;end_seq_num) &amp; </span><span class=cFE>0xFFFFFFFF</span><span class=cF0>;
<a name="l486"></a> </span><span class=cF2>// ???</span><span class=cF0>
<a name="l487"></a>
<a name="l488"></a> </span><span class=cF1>if</span><span class=cF0> (segment_ack_relative &lt;= send_next_relative)
<a name="l489"></a> {
<a name="l490"></a> NetDebug(</span><span class=cF6>&quot;TCP ACKNOWLEDGE PACKET: Saw send buffer entry with ACK &lt;= next relative send ACK, removing.&quot;</span><span class=cF0>);
<a name="l491"></a> rtt = time - send_buffer-&gt;time_sent; </span><span class=cF2>// Round-Trip Time</span><span class=cF0>
<a name="l492"></a>
<a name="l493"></a> tcp_socket-&gt;srtt = (tcp_socket-&gt;srtt * TCP_SRTT_ALPHA) + (</span><span class=cF7>(</span><span class=cFE>1</span><span class=cF0>.</span><span class=cFE>0</span><span class=cF0> - TCP_SRTT_ALPHA</span><span class=cF7>)</span><span class=cF0> * rtt);
<a name="l494"></a> </span><span class=cF2>// Smoothed Round-Trip Time</span><span class=cF0>
<a name="l495"></a>
<a name="l496"></a> </span><span class=cF5>QueueRemove</span><span class=cF0>(send_buffer);
<a name="l497"></a> </span><span class=cF5>Free</span><span class=cF0>(send_buffer-&gt;tcp_packet);
<a name="l498"></a>
<a name="l499"></a> send_buffer_temp = send_buffer-&gt;next; </span><span class=cF2>// QueueRemove doesn't change removed queue's links</span><span class=cF0>
<a name="l500"></a> </span><span class=cF5>Free</span><span class=cF0>(send_buffer);
<a name="l501"></a>
<a name="l502"></a> send_buffer = send_buffer_temp;
<a name="l503"></a>
<a name="l504"></a> }
<a name="l505"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l506"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l507"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l508"></a>}
<a name="l509"></a>
<a name="l510"></a></span><span class=cF1>U0</span><span class=cF0> TCPCheckACKQueue(CTCPSocket *tcp_socket)
<a name="l511"></a>{
<a name="l512"></a> </span><span class=cF1>F64</span><span class=cF0> time = </span><span class=cF5>tS</span><span class=cF0>;
<a name="l513"></a> </span><span class=cF1>F64</span><span class=cF0> rto = TCP_RTO_BETA * tcp_socket-&gt;srtt; </span><span class=cF2>// Retransmission Timeout, Smoothed Round-Trip Time</span><span class=cF0>
<a name="l514"></a> CTCPAckQueue *send_buffer = tcp_socket-&gt;ack_queue-&gt;next;
<a name="l515"></a> CTCPAckQueue *first_buffer = send_buffer;
<a name="l516"></a> </span><span class=cF1>U8</span><span class=cF0> *tcp_frame;
<a name="l517"></a> </span><span class=cF9>I64</span><span class=cF0> de_index;
<a name="l518"></a> CSocketAddressStorage *dest = &amp;tcp_socket-&gt;destination_address;
<a name="l519"></a> CSocketAddressStorage *source = &amp;tcp_socket-&gt;source_address;
<a name="l520"></a> CSocketAddressIPV4 *dest_ipv4;
<a name="l521"></a> CSocketAddressIPV6 *dest_ipv6;
<a name="l522"></a> CSocketAddressIPV4 *source_ipv4;
<a name="l523"></a> CSocketAddressIPV6 *source_ipv6;
<a name="l524"></a>
<a name="l525"></a>
<a name="l526"></a> </span><span class=cF1>if</span><span class=cF0> (send_buffer == tcp_socket-&gt;ack_queue)
<a name="l527"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l528"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>NetWarn(&quot;TCP CHECK ACK QUEUE: ACK Queue empty, bailing early.&quot;);</span><span class=cF0>
<a name="l529"></a> </span><span class=cF1>return</span><span class=cF0>;
<a name="l530"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l531"></a>
<a name="l532"></a> </span><span class=cF1>if</span><span class=cF0> (rto &lt; TCP_RTO_MIN)
<a name="l533"></a> rto = TCP_RTO_MIN;
<a name="l534"></a> </span><span class=cF1>if</span><span class=cF0> (rto &lt; TCP_RTO_MAX)
<a name="l535"></a> rto = TCP_RTO_MAX;
<a name="l536"></a>
<a name="l537"></a> </span><span class=cF1>do</span><span class=cF0>
<a name="l538"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l539"></a> </span><span class=cF1>if</span><span class=cF0> (time &gt; send_buffer-&gt;time_sent + rto)
<a name="l540"></a> {
<a name="l541"></a> NetWarn(</span><span class=cF6>&quot;TCP CHECK ACK QUEUE: Retransmitting TCP packet in ACK Queue.&quot;</span><span class=cF0>);
<a name="l542"></a>
<a name="l543"></a> </span><span class=cF1>switch</span><span class=cF0> (dest-&gt;family)
<a name="l544"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l545"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET:
<a name="l546"></a> dest_ipv4 = dest;
<a name="l547"></a>
<a name="l548"></a> </span><span class=cF1>switch</span><span class=cF0> (source-&gt;family)
<a name="l549"></a> {
<a name="l550"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET:
<a name="l551"></a> source_ipv4 = source;
<a name="l552"></a>
<a name="l553"></a> de_index = IPV4PacketAllocate(&amp;tcp_frame,
<a name="l554"></a> IP_PROTOCOL_TCP,
<a name="l555"></a> source_ipv4-&gt;address.address,
<a name="l556"></a> dest_ipv4-&gt;address.address,
<a name="l557"></a> send_buffer-&gt;tcp_packet_size);
<a name="l558"></a>
<a name="l559"></a> </span><span class=cF1>if</span><span class=cF0> (de_index &lt; </span><span class=cFE>0</span><span class=cF0>)
<a name="l560"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l561"></a> NetErr(</span><span class=cF6>&quot;TCP CHECK ACK QUEUE: IPV4 Packet Allocate failed.&quot;</span><span class=cF0>);
<a name="l562"></a> </span><span class=cF1>return</span><span class=cF0>;</span><span class=cF2>// de_index;</span><span class=cF0>
<a name="l563"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l564"></a>
<a name="l565"></a> </span><span class=cF5>MemCopy</span><span class=cF0>(&amp;tcp_frame, send_buffer-&gt;tcp_packet, send_buffer-&gt;tcp_packet_size);
<a name="l566"></a>
<a name="l567"></a> IPV4PacketFinish(de_index);
<a name="l568"></a>
<a name="l569"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l570"></a>
<a name="l571"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET6:
<a name="l572"></a> source_ipv6 = source;
<a name="l573"></a> NetErr(</span><span class=cF6>&quot;TCP CHECK ACK QUEUE: FIXME, IPV6 not implemented yet&quot;</span><span class=cF0>);
<a name="l574"></a> </span><span class=cF1>return</span><span class=cF0>;</span><span class=cF2>// -1;</span><span class=cF0>
<a name="l575"></a> </span><span class=cF1>case</span><span class=cF0> AF_UNSPEC:
<a name="l576"></a> NetErr(</span><span class=cF6>&quot;TCP CHECK ACK QUEUE: Error, TCP Send from AF_UNSPEC\n&quot;</span><span class=cF0>);
<a name="l577"></a> </span><span class=cF1>return</span><span class=cF0>;</span><span class=cF2>// -1;</span><span class=cF0>
<a name="l578"></a> }
<a name="l579"></a>
<a name="l580"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l581"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET6:
<a name="l582"></a> dest_ipv6 = dest;
<a name="l583"></a> NetErr(</span><span class=cF6>&quot;TCP CHECK ACK QUEUE: FIXME, IPV6 not implemented yet&quot;</span><span class=cF0>);
<a name="l584"></a> </span><span class=cF1>return</span><span class=cF0>;</span><span class=cF2>// -1;</span><span class=cF0>
<a name="l585"></a> </span><span class=cF1>case</span><span class=cF0> AF_UNSPEC:
<a name="l586"></a> NetErr(</span><span class=cF6>&quot;TCP CHECK ACK QUEUE: Error, TCP Send to AF_UNSPEC\n&quot;</span><span class=cF0>);
<a name="l587"></a> </span><span class=cF1>return</span><span class=cF0>;</span><span class=cF2>// -1;</span><span class=cF0>
<a name="l588"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l589"></a>
<a name="l590"></a> send_buffer-&gt;time_sent = </span><span class=cF5>tS</span><span class=cF0>;
<a name="l591"></a>
<a name="l592"></a> </span><span class=cF2>// If it gets here, retransmit was successful.</span><span class=cF0>
<a name="l593"></a>
<a name="l594"></a> </span><span class=cF2>// Move to the END OF THE CHAIN (BACK OF THE QUEUE. SO, REQUEUE.)</span><span class=cF0>
<a name="l595"></a> </span><span class=cF5>QueueRemove</span><span class=cF0>(send_buffer);
<a name="l596"></a> </span><span class=cF5>QueueInsertRev</span><span class=cF0>(send_buffer, tcp_socket-&gt;ack_queue);
<a name="l597"></a>
<a name="l598"></a> send_buffer = tcp_socket-&gt;ack_queue-&gt;next;
<a name="l599"></a>
<a name="l600"></a> }
<a name="l601"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l602"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l603"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l604"></a> </span><span class=cF1>while</span><span class=cF0> (send_buffer != first_buffer);
<a name="l605"></a>}
<a name="l606"></a>
<a name="l607"></a>CTCPSocket TCPSocket(</span><span class=cF9>U16</span><span class=cF0> domain=AF_UNSPEC)
<a name="l608"></a>{
<a name="l609"></a> </span><span class=cF9>U16</span><span class=cF0> type = SOCKET_STREAM;
<a name="l610"></a> CTCPSocket *tcp_socket = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CTCPSocket</span><span class=cF7>)</span><span class=cF0>);
<a name="l611"></a> CTCPAckQueue *ack_queue = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CTCPAckQueue</span><span class=cF7>)</span><span class=cF0>);
<a name="l612"></a> CTCPAcceptQueue *accept_queue = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CTCPAcceptQueue</span><span class=cF7>)</span><span class=cF0>);
<a name="l613"></a> CSocketAddressIPV4 *ipv4_address;
<a name="l614"></a> CSocketAddressIPV6 *ipv6_address;
<a name="l615"></a>
<a name="l616"></a> tcp_socket-&gt;socket = Socket(domain, type);
<a name="l617"></a> tcp_socket-&gt;state = TCP_STATE_CLOSED;
<a name="l618"></a>
<a name="l619"></a> tcp_socket-&gt;source_address.family = domain; </span><span class=cF2>// INET, INET6, or unspecified</span><span class=cF0>
<a name="l620"></a>
<a name="l621"></a> </span><span class=cF1>switch</span><span class=cF0> (domain)
<a name="l622"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l623"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET:
<a name="l624"></a> ipv4_address = &amp;tcp_socket-&gt;source_address;
<a name="l625"></a>
<a name="l626"></a> ipv4_address-&gt;address.address = IPV4AddressGet;
<a name="l627"></a> </span><span class=cF2>// do we need to set local port? does that only make sense to do later?</span><span class=cF0>
<a name="l628"></a> </span><span class=cF2>// CAlloc will leave it at 0</span><span class=cF0>
<a name="l629"></a>
<a name="l630"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l631"></a>
<a name="l632"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET6:
<a name="l633"></a> ipv6_address = &amp;tcp_socket-&gt;source_address;
<a name="l634"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET: FIXME, IPV6 not implemented yet&quot;</span><span class=cF0>);
<a name="l635"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>NULL</span><span class=cF0>;
<a name="l636"></a>
<a name="l637"></a> </span><span class=cF1>case</span><span class=cF0> AF_UNSPEC:
<a name="l638"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET: Error TCP Socket to AF_UNSPEC&quot;</span><span class=cF0>);
<a name="l639"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>NULL</span><span class=cF0>;
<a name="l640"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l641"></a>
<a name="l642"></a> </span><span class=cF5>QueueInit</span><span class=cF0>(ack_queue); </span><span class=cF2>// init send buffer queue head</span><span class=cF0>
<a name="l643"></a> tcp_socket-&gt;ack_queue = ack_queue;
<a name="l644"></a>
<a name="l645"></a> </span><span class=cF5>QueueInit</span><span class=cF0>(accept_queue); </span><span class=cF2>// init pending connection queue</span><span class=cF0>
<a name="l646"></a> tcp_socket-&gt;accept_queue = accept_queue;
<a name="l647"></a>
<a name="l648"></a> tcp_socket-&gt;receive_buffer_size = TCP_WINDOW_SIZE;
<a name="l649"></a> tcp_socket-&gt;receive_buffer = </span><span class=cF5>CAlloc</span><span class=cF0>(TCP_WINDOW_SIZE);
<a name="l650"></a>
<a name="l651"></a> tcp_socket-&gt;max_segment_size = TCP_MSS;
<a name="l652"></a>
<a name="l653"></a> </span><span class=cF1>return</span><span class=cF0> tcp_socket;
<a name="l654"></a>}
<a name="l655"></a>
<a name="l656"></a></span><span class=cF9>I64</span><span class=cF0> TCPSocketBind(CTCPSocket *tcp_socket, CSocketAddressStorage *address)
<a name="l657"></a>{ </span><span class=cF2>// Binds a TCP socket to address, which contains the local port and remote address to use.</span><span class=cF0>
<a name="l658"></a> CTCPTreeNode *head = tcp_globals.bound_socket_tree;
<a name="l659"></a> CTCPTreeNode *temp_node;
<a name="l660"></a> CSocketAddressIPV4 *ipv4_address;
<a name="l661"></a> CSocketAddressIPV4 *ipv4_destination;
<a name="l662"></a> CSocketAddressIPV4 *ipv4_source;
<a name="l663"></a> CSocketAddressIPV6 *ipv6_address;
<a name="l664"></a> CSocketAddressIPV6 *ipv6_destination;
<a name="l665"></a> </span><span class=cF9>U16</span><span class=cF0> port;
<a name="l666"></a>
<a name="l667"></a> </span><span class=cF1>if</span><span class=cF0> (!SocketBind</span><span class=cF7>(</span><span class=cF0>tcp_socket-&gt;socket</span><span class=cF7>)</span><span class=cF0>)
<a name="l668"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l669"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET BIND: Failed, Socket state-machine must be in READY state.&quot;</span><span class=cF0>);
<a name="l670"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l671"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l672"></a>
<a name="l673"></a> </span><span class=cF1>if</span><span class=cF0> (tcp_socket-&gt;state != TCP_STATE_CLOSED)
<a name="l674"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l675"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET BIND: Failed, TCP Socket must be in CLOSED state.&quot;</span><span class=cF0>);
<a name="l676"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l677"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l678"></a>
<a name="l679"></a> </span><span class=cF1>switch</span><span class=cF0> (address-&gt;family)
<a name="l680"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l681"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET:
<a name="l682"></a>
<a name="l683"></a> </span><span class=cF1>if</span><span class=cF0> (tcp_socket-&gt;source_address.family == AF_INET6)
<a name="l684"></a> {
<a name="l685"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET BIND: FIXME, IPV6-&gt;IPV4 TCP BIND&quot;</span><span class=cF0>);
<a name="l686"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l687"></a> }
<a name="l688"></a>
<a name="l689"></a> ipv4_address = address;
<a name="l690"></a> ipv4_destination = &amp;tcp_socket-&gt;destination_address;
<a name="l691"></a>
<a name="l692"></a> ipv4_destination-&gt;family = AF_INET;
<a name="l693"></a> ipv4_destination-&gt;address.address = ipv4_address-&gt;address.address; </span><span class=cF2>// bind socket to address in parameter.</span><span class=cF0>
<a name="l694"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>ipv4_destination-&gt;port</span><span class=cF0> </span><span class=cF2>= ipv4_address-&gt;port; // ... consistency would say keep in Big Endian ...</span><span class=cF0>
<a name="l695"></a>
<a name="l696"></a> ipv4_source = &amp;tcp_socket-&gt;source_address;
<a name="l697"></a>
<a name="l698"></a> ipv4_source-&gt;port = ipv4_address-&gt;port;
<a name="l699"></a>
<a name="l700"></a> port = </span><span class=cF5>EndianU16</span><span class=cF0>(ipv4_address-&gt;port); </span><span class=cF2>// port member should be Big Endian, so now we're going L.E (?)</span><span class=cF0>
<a name="l701"></a>
<a name="l702"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l703"></a>
<a name="l704"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET6:
<a name="l705"></a>
<a name="l706"></a> </span><span class=cF1>if</span><span class=cF0> (tcp_socket-&gt;source_address.family == AF_INET)
<a name="l707"></a> {
<a name="l708"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET BIND: Incompatible Address type.&quot;</span><span class=cF0>);
<a name="l709"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l710"></a> }
<a name="l711"></a>
<a name="l712"></a> ipv6_address = address;
<a name="l713"></a> ipv6_destination = &amp;tcp_socket-&gt;destination_address;
<a name="l714"></a> </span><span class=cF2>// ...</span><span class=cF0>
<a name="l715"></a> </span><span class=cF2>// ...</span><span class=cF0>
<a name="l716"></a>
<a name="l717"></a> port = </span><span class=cF5>EndianU16</span><span class=cF0>(ipv6_address-&gt;port); </span><span class=cF2>// port member should be Big Endian, so now we're going L.E (?)</span><span class=cF0>
<a name="l718"></a>
<a name="l719"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET BIND: FIXME, IPV6 TCP BIND&quot;</span><span class=cF0>);
<a name="l720"></a>
<a name="l721"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l722"></a>
<a name="l723"></a> </span><span class=cF1>case</span><span class=cF0> AF_UNSPEC:
<a name="l724"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET BIND: Error, AF_UNSPEC TCP BIND -- param family&quot;</span><span class=cF0>);
<a name="l725"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l726"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l727"></a>
<a name="l728"></a> </span><span class=cF1>if</span><span class=cF0> (head)
<a name="l729"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l730"></a> </span><span class=cF2>// look for our port.</span><span class=cF0>
<a name="l731"></a> temp_node = TCPTreeNodeFind(port, head);
<a name="l732"></a>
<a name="l733"></a> </span><span class=cF1>if</span><span class=cF0> (temp_node)
<a name="l734"></a> { </span><span class=cF2>// if we find we have bound sockets at port, check address before adding to queue</span><span class=cF0>
<a name="l735"></a> </span><span class=cF1>switch</span><span class=cF0> (address-&gt;family)
<a name="l736"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l737"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET:
<a name="l738"></a> </span><span class=cF1>if</span><span class=cF0> (TCPTreeNodeQueueIPV4Find</span><span class=cF7>(</span><span class=cF0>ipv4_destination-&gt;address.address, temp_node, </span><span class=cF3>TRUE</span><span class=cF7>)</span><span class=cF0>)
<a name="l739"></a> {
<a name="l740"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET BIND: Address already in Bound Socket Tree !&quot;</span><span class=cF0>);
<a name="l741"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l742"></a> }
<a name="l743"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l744"></a> { </span><span class=cF2>// if no address match, free to add socket to the node queue</span><span class=cF0>
<a name="l745"></a> NetDebug(</span><span class=cF6>&quot;TCP SOCKET BIND: No address match, adding socket to node queue&quot;</span><span class=cF0>);
<a name="l746"></a> TCPTreeNodeQueueAdd(tcp_socket, temp_node);
<a name="l747"></a> }
<a name="l748"></a>
<a name="l749"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l750"></a>
<a name="l751"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET6:
<a name="l752"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET BIND: FIXME, IPV6 TCP BIND&quot;</span><span class=cF0>);
<a name="l753"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l754"></a>
<a name="l755"></a> </span><span class=cF1>case</span><span class=cF0> AF_UNSPEC:
<a name="l756"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET BIND: Error, AF_UNSPEC TCP BIND -- found in bound tree&quot;</span><span class=cF0>);
<a name="l757"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l758"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l759"></a> }
<a name="l760"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l761"></a> { </span><span class=cF2>// if we get no node back from port search, we didn't find it and are free to add a new node.</span><span class=cF0>
<a name="l762"></a> temp_node = TCPTreeNodeParamAdd(port, head); </span><span class=cF2>// add new node with port, return its *.</span><span class=cF0>
<a name="l763"></a> TCPTreeNodeQueueAdd(tcp_socket, temp_node);
<a name="l764"></a> }
<a name="l765"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l766"></a> </span><span class=cF1>else</span><span class=cF0> </span><span class=cF2>// if no bound sockets, we init the tree as a new node</span><span class=cF0>
<a name="l767"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l768"></a> tcp_globals.bound_socket_tree = head = TCPTreeNodeParamInit(port); </span><span class=cF2>//... shouuuld be in L.E .. ?</span><span class=cF0>
<a name="l769"></a> TCPTreeNodeQueueAdd(tcp_socket, head); </span><span class=cF2>// add the tcp socket to the port queue</span><span class=cF0>
<a name="l770"></a> </span><span class=cF2>// maybe more checks to do before this, dunno rn.</span><span class=cF0>
<a name="l771"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l772"></a>
<a name="l773"></a>
<a name="l774"></a> </span><span class=cF2>// do we need to do anything else after bind add to tree? ...</span><span class=cF0>
<a name="l775"></a>
<a name="l776"></a>
<a name="l777"></a> </span><span class=cF1>switch</span><span class=cF0> (tcp_socket-&gt;socket-&gt;state)
<a name="l778"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l779"></a> </span><span class=cF1>case</span><span class=cF0> SOCKET_STATE_BIND_REQ: </span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>if BIND request success, set BOUND.</span><span class=cF0>
<a name="l780"></a> tcp_socket-&gt;socket-&gt;state = SOCKET_STATE_BOUND;
<a name="l781"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l782"></a>
<a name="l783"></a> </span><span class=cF1>default</span><span class=cF0>:
<a name="l784"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET BIND: Failed, Misconfigured Socket state-machine.&quot;</span><span class=cF0>);
<a name="l785"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l786"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l787"></a>
<a name="l788"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cFE>0</span><span class=cF0>;
<a name="l789"></a>}
<a name="l790"></a>
<a name="l791"></a></span><span class=cF9>I64</span><span class=cF0> TCPSocketClose(CTCPSocket *tcp_socket)
<a name="l792"></a>{
<a name="l793"></a> CTCPTreeNode *head = tcp_globals.bound_socket_tree;
<a name="l794"></a> CTCPTreeNode *node;
<a name="l795"></a> CTCPTreeQueue *queue;
<a name="l796"></a> CTCPAckQueue *send_buffer;
<a name="l797"></a> CTCPAcceptQueue *pending;
<a name="l798"></a> CSocketAddressIPV4 *address = &amp;tcp_socket-&gt;source_address;
<a name="l799"></a> </span><span class=cF9>I64</span><span class=cF0> timeout;
<a name="l800"></a>
<a name="l801"></a> SocketClose(tcp_socket-&gt;socket); </span><span class=cF2>// TODO: testing on closing a socket while another task is using it</span><span class=cF0>
<a name="l802"></a>
<a name="l803"></a> </span><span class=cF1>switch</span><span class=cF0> (tcp_socket-&gt;state)
<a name="l804"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l805"></a> </span><span class=cF1>case</span><span class=cF0> TCP_STATE_ESTABLISHED:
<a name="l806"></a> </span><span class=cF1>while</span><span class=cF0> (TCPSendFlags</span><span class=cF7>(</span><span class=cF0>tcp_socket, TCPF_FIN | TCPF_ACK</span><span class=cF7>)</span><span class=cF0> &lt; </span><span class=cFE>0</span><span class=cF0>)
<a name="l807"></a> {
<a name="l808"></a> TCPCheckACKQueue(tcp_socket);
<a name="l809"></a> </span><span class=cF5>Sleep</span><span class=cF0>(</span><span class=cFE>1</span><span class=cF0>);
<a name="l810"></a> }
<a name="l811"></a>
<a name="l812"></a> tcp_socket-&gt;state = TCP_STATE_FIN_WAIT1;
<a name="l813"></a>
<a name="l814"></a> </span><span class=cF2>// Shrine has TODOs:</span><span class=cF0> </span><span class=cF2>- What states are allowed here?</span><span class=cF0>
<a name="l815"></a> </span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>- This can block forever if our recv buffer fills up</span><span class=cF0>
<a name="l816"></a> </span><span class=cF2>//</span><span class=cF0> </span><span class=cF2> </span><span class=cF0> </span><span class=cF2> but remote insists on sending more.</span><span class=cF0>
<a name="l817"></a> </span><span class=cF2>// Implementing timeout here to force close.</span><span class=cF0>
<a name="l818"></a> timeout = </span><span class=cFB>counts</span><span class=cF0>.jiffies + tcp_socket-&gt;timeout * </span><span class=cF3>JIFFY_FREQ</span><span class=cF0> / </span><span class=cFE>1000</span><span class=cF0>;
<a name="l819"></a>
<a name="l820"></a> </span><span class=cF1>while</span><span class=cF0> (tcp_socket-&gt;state == TCP_STATE_FIN_WAIT1 &amp;&amp;
<a name="l821"></a> tcp_socket-&gt;first_unacked_seq != tcp_socket-&gt;next_send_seq_num &amp;&amp;
<a name="l822"></a> </span><span class=cFB>counts</span><span class=cF0>.jiffies &lt; timeout)
<a name="l823"></a> {
<a name="l824"></a> TCPCheckACKQueue(tcp_socket);
<a name="l825"></a> </span><span class=cF5>Sleep</span><span class=cF0>(</span><span class=cFE>1</span><span class=cF0>);
<a name="l826"></a> }
<a name="l827"></a>
<a name="l828"></a> </span><span class=cF1>if</span><span class=cF0> (tcp_socket-&gt;state == TCP_STATE_FIN_WAIT1)
<a name="l829"></a> tcp_socket-&gt;state = TCP_STATE_FIN_WAIT2;
<a name="l830"></a>
<a name="l831"></a> timeout = </span><span class=cFB>counts</span><span class=cF0>.jiffies + tcp_socket-&gt;timeout * </span><span class=cF3>JIFFY_FREQ</span><span class=cF0> / </span><span class=cFE>1000</span><span class=cF0>;
<a name="l832"></a> </span><span class=cF1>while</span><span class=cF0> (tcp_socket-&gt;state == TCP_STATE_FIN_WAIT2 &amp;&amp; </span><span class=cFB>counts</span><span class=cF0>.jiffies &lt; timeout)
<a name="l833"></a> </span><span class=cF5>Sleep</span><span class=cF0>(</span><span class=cFE>1</span><span class=cF0>);
<a name="l834"></a>
<a name="l835"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l836"></a>
<a name="l837"></a> </span><span class=cF1>case</span><span class=cF0> TCP_STATE_CLOSE_WAIT:
<a name="l838"></a> </span><span class=cF1>while</span><span class=cF0> (TCPSendFlags</span><span class=cF7>(</span><span class=cF0>tcp_socket, TCPF_FIN | TCPF_ACK</span><span class=cF7>)</span><span class=cF0> &lt; </span><span class=cFE>0</span><span class=cF0>)
<a name="l839"></a> {
<a name="l840"></a> TCPCheckACKQueue(tcp_socket);
<a name="l841"></a> </span><span class=cF5>Sleep</span><span class=cF0>(</span><span class=cFE>1</span><span class=cF0>);
<a name="l842"></a> }
<a name="l843"></a>
<a name="l844"></a> </span><span class=cF1>if</span><span class=cF0> (tcp_socket-&gt;state == TCP_STATE_CLOSE_WAIT)
<a name="l845"></a> tcp_socket-&gt;state = TCP_STATE_LAST_ACK;
<a name="l846"></a>
<a name="l847"></a> timeout = </span><span class=cFB>counts</span><span class=cF0>.jiffies + tcp_socket-&gt;timeout * </span><span class=cF3>JIFFY_FREQ</span><span class=cF0> / </span><span class=cFE>1000</span><span class=cF0>;
<a name="l848"></a> </span><span class=cF1>while</span><span class=cF0> (tcp_socket-&gt;state == TCP_STATE_LAST_ACK &amp;&amp;
<a name="l849"></a> tcp_socket-&gt;first_unacked_seq != tcp_socket-&gt;next_send_seq_num &amp;&amp;
<a name="l850"></a> </span><span class=cFB>counts</span><span class=cF0>.jiffies &lt; timeout)
<a name="l851"></a> {
<a name="l852"></a> TCPCheckACKQueue(tcp_socket);
<a name="l853"></a> </span><span class=cF5>Sleep</span><span class=cF0>(</span><span class=cFE>1</span><span class=cF0>);
<a name="l854"></a> }
<a name="l855"></a>
<a name="l856"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l857"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l858"></a>
<a name="l859"></a> </span><span class=cF1>if</span><span class=cF0> (IsTCPStateSync</span><span class=cF7>(</span><span class=cF0>tcp_socket</span><span class=cF7>)</span><span class=cF0>)
<a name="l860"></a> TCPSendFlags(tcp_socket, TCPF_RST);
<a name="l861"></a>
<a name="l862"></a> </span><span class=cF2>// remove from bound list, free associated allocs</span><span class=cF0>
<a name="l863"></a>
<a name="l864"></a> node = TCPTreeNodeFind(</span><span class=cF5>EndianU16</span><span class=cF7>(</span><span class=cF0>address-&gt;port</span><span class=cF7>)</span><span class=cF0>, head);
<a name="l865"></a>
<a name="l866"></a> </span><span class=cF1>if</span><span class=cF0> (node)
<a name="l867"></a> queue = TCPTreeNodeQueueSocketFind(tcp_socket, node);
<a name="l868"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l869"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l870"></a> </span><span class=cF5>Debug</span><span class=cF0>(</span><span class=cF6>&quot;TODO: Didn't find node at socket during TCPSocketClose!\n&quot;</span><span class=cF0>);
<a name="l871"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l872"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l873"></a>
<a name="l874"></a> </span><span class=cF1>if</span><span class=cF0> (queue)
<a name="l875"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l876"></a> TCPTreeNodeQueueSocketSinglePop(tcp_socket, node);
<a name="l877"></a>
<a name="l878"></a> </span><span class=cF1>if</span><span class=cF0> (node-&gt;queue == node-&gt;queue-&gt;next)
<a name="l879"></a> { </span><span class=cF2>// if we popped the only queue on the node, remove the node.</span><span class=cF0>
<a name="l880"></a> </span><span class=cF1>if</span><span class=cF0> (node == head)
<a name="l881"></a> </span><span class=cF7>{</span><span class=cF0> </span><span class=cF2>// head is the global. if node is the global, change it and add branches.</span><span class=cF0>
<a name="l882"></a> </span><span class=cF1>if</span><span class=cF0> (node-&gt;left)
<a name="l883"></a> {
<a name="l884"></a> tcp_globals.bound_socket_tree = head = node-&gt;left;
<a name="l885"></a> </span><span class=cF1>if</span><span class=cF0> (node-&gt;right)
<a name="l886"></a> TCPTreeNodeAdd(node-&gt;right, head);
<a name="l887"></a> }
<a name="l888"></a> </span><span class=cF1>else</span><span class=cF0> </span><span class=cF1>if</span><span class=cF0> (node-&gt;right)
<a name="l889"></a> tcp_globals.bound_socket_tree = node-&gt;right;
<a name="l890"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l891"></a> tcp_globals.bound_socket_tree = </span><span class=cF3>NULL</span><span class=cF0>;
<a name="l892"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l893"></a> </span><span class=cF1>else</span><span class=cF0> </span><span class=cF2>// if node is not the global, just pop it from the tree</span><span class=cF0>
<a name="l894"></a> TCPTreeNodeSinglePop(node-&gt;value, head);
<a name="l895"></a>
<a name="l896"></a> </span><span class=cF5>Free</span><span class=cF0>(node);
<a name="l897"></a> }
<a name="l898"></a>
<a name="l899"></a> </span><span class=cF5>Free</span><span class=cF0>(tcp_socket-&gt;socket);
<a name="l900"></a>
<a name="l901"></a> NetWarn(</span><span class=cF6>&quot;TCP SOCKET CLOSE: Freeing socket, ACK queue, accept() queue, &amp; receive buffer.&quot;</span><span class=cF0>);
<a name="l902"></a> </span><span class=cF5>Free</span><span class=cF0>(tcp_socket-&gt;receive_buffer);
<a name="l903"></a>
<a name="l904"></a> send_buffer = tcp_socket-&gt;ack_queue-&gt;next;
<a name="l905"></a> </span><span class=cF1>while</span><span class=cF0> (send_buffer != tcp_socket-&gt;ack_queue)
<a name="l906"></a> {
<a name="l907"></a> NetWarn(</span><span class=cF6>&quot;TCP SOCKET CLOSE: Freeing send buffer @ 0x%0X&quot;</span><span class=cF0>, send_buffer);
<a name="l908"></a> </span><span class=cF5>QueueRemove</span><span class=cF0>(send_buffer);
<a name="l909"></a> </span><span class=cF5>Free</span><span class=cF0>(send_buffer-&gt;tcp_packet);
<a name="l910"></a> </span><span class=cF5>Free</span><span class=cF0>(send_buffer);
<a name="l911"></a> send_buffer = tcp_socket-&gt;ack_queue-&gt;next;
<a name="l912"></a> }
<a name="l913"></a>
<a name="l914"></a> pending = tcp_socket-&gt;accept_queue-&gt;next;
<a name="l915"></a> </span><span class=cF1>while</span><span class=cF0> (pending != tcp_socket-&gt;accept_queue)
<a name="l916"></a> {
<a name="l917"></a> NetWarn(</span><span class=cF6>&quot;TCP SOCKET CLOSE: Freeing pending connection @ 0x%0X&quot;</span><span class=cF0>, pending);
<a name="l918"></a> </span><span class=cF5>QueueRemove</span><span class=cF0>(pending);
<a name="l919"></a> </span><span class=cF5>Free</span><span class=cF0>(pending);
<a name="l920"></a> pending = tcp_socket-&gt;accept_queue-&gt;next;
<a name="l921"></a> }
<a name="l922"></a>
<a name="l923"></a>
<a name="l924"></a> </span><span class=cF5>Free</span><span class=cF0>(tcp_socket);
<a name="l925"></a> </span><span class=cF5>Free</span><span class=cF0>(queue);
<a name="l926"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l927"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l928"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l929"></a> </span><span class=cF5>Debug</span><span class=cF0>(</span><span class=cF6>&quot;TODO: Didn't find queue at socket during TCPSocketClose!\n&quot;</span><span class=cF0>);
<a name="l930"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l931"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l932"></a>
<a name="l933"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cFE>0</span><span class=cF0>;
<a name="l934"></a>
<a name="l935"></a>}
<a name="l936"></a>
<a name="l937"></a></span><span class=cF9>I64</span><span class=cF0> TCPSocketConnect(CTCPSocket *tcp_socket, CSocketAddressStorage *address)
<a name="l938"></a>{ </span><span class=cF2>// Bind and connect a socket to the destination address and port in address param, local port automatic.</span><span class=cF0>
<a name="l939"></a> </span><span class=cF9>U16</span><span class=cF0> source_port = </span><span class=cF5>EndianU16</span><span class=cF0>(</span><span class=cFE>0x8000</span><span class=cF0> + tcp_globals.next_source_port++ &amp; </span><span class=cFE>0x7FFF</span><span class=cF0>);
<a name="l940"></a> CTCPTreeNode *head = tcp_globals.bound_socket_tree;
<a name="l941"></a> CTCPTreeNode *temp_node;
<a name="l942"></a> CSocketAddressIPV4 *ipv4_address;
<a name="l943"></a> CSocketAddressIPV4 *ipv4_destination;
<a name="l944"></a> CSocketAddressIPV4 *ipv4_source;
<a name="l945"></a> CSocketAddressIPV6 *ipv6_address;
<a name="l946"></a> CSocketAddressIPV6 *ipv6_destination;
<a name="l947"></a> </span><span class=cF9>I64</span><span class=cF0> timeout;
<a name="l948"></a> </span><span class=cF9>U16</span><span class=cF0> port;
<a name="l949"></a>
<a name="l950"></a>
<a name="l951"></a> </span><span class=cF1>if</span><span class=cF0> (!SocketConnect</span><span class=cF7>(</span><span class=cF0>tcp_socket-&gt;socket</span><span class=cF7>)</span><span class=cF0>)
<a name="l952"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l953"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET CONNECT: Failed, Socket state-machine must be in READY state.&quot;</span><span class=cF0>);
<a name="l954"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l955"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l956"></a>
<a name="l957"></a> </span><span class=cF1>if</span><span class=cF0> (tcp_socket-&gt;state != TCP_STATE_CLOSED)
<a name="l958"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l959"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET CONNECT: TCP Socket must be in CLOSED state.&quot;</span><span class=cF0>);
<a name="l960"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l961"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l962"></a>
<a name="l963"></a> </span><span class=cF1>switch</span><span class=cF0> (address-&gt;family)
<a name="l964"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l965"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET:
<a name="l966"></a>
<a name="l967"></a> </span><span class=cF1>if</span><span class=cF0> (tcp_socket-&gt;source_address.family == AF_INET6)
<a name="l968"></a> {
<a name="l969"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET CONNECT: FIXME, IPV6-&gt;IPV4 TCP CONNECT&quot;</span><span class=cF0>);
<a name="l970"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l971"></a> }
<a name="l972"></a>
<a name="l973"></a> ipv4_address = address;
<a name="l974"></a> ipv4_destination = &amp;tcp_socket-&gt;destination_address;
<a name="l975"></a>
<a name="l976"></a> ipv4_destination-&gt;family = AF_INET;
<a name="l977"></a> ipv4_destination-&gt;address.address = ipv4_address-&gt;address.address; </span><span class=cF2>// bind socket to address in parameter.</span><span class=cF0>
<a name="l978"></a> ipv4_destination-&gt;port = ipv4_address-&gt;port; </span><span class=cF2>// ... consistency would say keep in Big Endian ...</span><span class=cF0>
<a name="l979"></a>
<a name="l980"></a> ipv4_source = &amp;tcp_socket-&gt;source_address;
<a name="l981"></a>
<a name="l982"></a> ipv4_source-&gt;port = source_port;
<a name="l983"></a>
<a name="l984"></a> port = </span><span class=cF5>EndianU16</span><span class=cF0>(source_port); </span><span class=cF2>// port member should be Big Endian, so now we're going L.E (?)</span><span class=cF0>
<a name="l985"></a>
<a name="l986"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l987"></a>
<a name="l988"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET6:
<a name="l989"></a>
<a name="l990"></a> </span><span class=cF1>if</span><span class=cF0> (tcp_socket-&gt;source_address.family == AF_INET)
<a name="l991"></a> {
<a name="l992"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET CONNECT: Incompatible Address type.&quot;</span><span class=cF0>);
<a name="l993"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l994"></a> }
<a name="l995"></a>
<a name="l996"></a> ipv6_address = address;
<a name="l997"></a> ipv6_destination = &amp;tcp_socket-&gt;destination_address;
<a name="l998"></a> </span><span class=cF2>// ...</span><span class=cF0>
<a name="l999"></a> </span><span class=cF2>// ...</span><span class=cF0>
<a name="l1000"></a>
<a name="l1001"></a> port = </span><span class=cF5>EndianU16</span><span class=cF0>(source_port); </span><span class=cF2>// port member should be Big Endian, so now we're going L.E (?)</span><span class=cF0>
<a name="l1002"></a>
<a name="l1003"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET CONNECT: FIXME, IPV6 TCP CONNECT&quot;</span><span class=cF0>);
<a name="l1004"></a>
<a name="l1005"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l1006"></a>
<a name="l1007"></a> </span><span class=cF1>case</span><span class=cF0> AF_UNSPEC:
<a name="l1008"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET CONNECT: Error, AF_UNSPEC TCP CONNECT -- param family&quot;</span><span class=cF0>);
<a name="l1009"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l1010"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1011"></a>
<a name="l1012"></a> </span><span class=cF1>if</span><span class=cF0> (head)
<a name="l1013"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1014"></a> </span><span class=cF2>// look for our port.</span><span class=cF0>
<a name="l1015"></a> temp_node = TCPTreeNodeFind(port, head);
<a name="l1016"></a>
<a name="l1017"></a> </span><span class=cF1>if</span><span class=cF0> (temp_node)
<a name="l1018"></a> { </span><span class=cF2>// if we find we have bound sockets at port, check address before adding to queue</span><span class=cF0>
<a name="l1019"></a> </span><span class=cF1>switch</span><span class=cF0> (address-&gt;family)
<a name="l1020"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1021"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET:
<a name="l1022"></a> </span><span class=cF1>if</span><span class=cF0> (TCPTreeNodeQueueIPV4Find</span><span class=cF7>(</span><span class=cF0>ipv4_destination-&gt;address.address, temp_node, </span><span class=cF3>TRUE</span><span class=cF7>)</span><span class=cF0>)
<a name="l1023"></a> {
<a name="l1024"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET CONNECT: Address already in Bound Socket Tree !&quot;</span><span class=cF0>);
<a name="l1025"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l1026"></a> }
<a name="l1027"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l1028"></a> { </span><span class=cF2>// if no address match, free to add socket to the node queue</span><span class=cF0>
<a name="l1029"></a> NetDebug(</span><span class=cF6>&quot;TCP SOCKET CONNECT: No address match, adding socket to node queue&quot;</span><span class=cF0>);
<a name="l1030"></a> TCPTreeNodeQueueAdd(tcp_socket, temp_node);
<a name="l1031"></a> }
<a name="l1032"></a>
<a name="l1033"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l1034"></a>
<a name="l1035"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET6:
<a name="l1036"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET CONNECT: FIXME, IPV6 TCP CONNECT&quot;</span><span class=cF0>);
<a name="l1037"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l1038"></a>
<a name="l1039"></a> </span><span class=cF1>case</span><span class=cF0> AF_UNSPEC:
<a name="l1040"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET CONNECT: Error, AF_UNSPEC TCP CONNECT -- found in bound tree&quot;</span><span class=cF0>);
<a name="l1041"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l1042"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1043"></a> }
<a name="l1044"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l1045"></a> { </span><span class=cF2>// if we get no node back from port search, we didn't find it and are free to add a new node.</span><span class=cF0>
<a name="l1046"></a> temp_node = TCPTreeNodeParamAdd(port, head); </span><span class=cF2>// add new node with port, return its *.</span><span class=cF0>
<a name="l1047"></a> TCPTreeNodeQueueAdd(tcp_socket, temp_node);
<a name="l1048"></a> }
<a name="l1049"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1050"></a> </span><span class=cF1>else</span><span class=cF0> </span><span class=cF2>// if no bound sockets, we init the tree as a new node</span><span class=cF0>
<a name="l1051"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1052"></a> tcp_globals.bound_socket_tree = head = TCPTreeNodeParamInit(port); </span><span class=cF2>//... shouuuld be in L.E .. ?</span><span class=cF0>
<a name="l1053"></a> TCPTreeNodeQueueAdd(tcp_socket, head); </span><span class=cF2>// add the tcp socket to the port queue</span><span class=cF0>
<a name="l1054"></a> </span><span class=cF2>// maybe more checks to do before this, dunno rn.</span><span class=cF0>
<a name="l1055"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1056"></a>
<a name="l1057"></a> tcp_socket-&gt;connection_time = </span><span class=cF5>tS</span><span class=cF0>;
<a name="l1058"></a> tcp_socket-&gt;receive_window = TCP_WINDOW_SIZE;
<a name="l1059"></a>
<a name="l1060"></a> tcp_socket-&gt;state = TCP_STATE_SYN_SENT;
<a name="l1061"></a> TCPSendFlags(tcp_socket, TCPF_SYN);
<a name="l1062"></a>
<a name="l1063"></a> timeout = </span><span class=cFB>counts</span><span class=cF0>.jiffies + tcp_socket-&gt;timeout * </span><span class=cF3>JIFFY_FREQ</span><span class=cF0> / </span><span class=cFE>1000</span><span class=cF0>;
<a name="l1064"></a> </span><span class=cF1>while</span><span class=cF0> (</span><span class=cFB>counts</span><span class=cF0>.jiffies &lt; timeout)
<a name="l1065"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1066"></a> </span><span class=cF1>switch</span><span class=cF0> (tcp_socket-&gt;state)
<a name="l1067"></a> {
<a name="l1068"></a> </span><span class=cF1>case</span><span class=cF0> TCP_STATE_ESTABLISHED:
<a name="l1069"></a> </span><span class=cF1>case</span><span class=cF0> TCP_STATE_CLOSED:
<a name="l1070"></a> timeout = </span><span class=cFE>0</span><span class=cF0>; </span><span class=cF2>// break out of while loop</span><span class=cF0>
<a name="l1071"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l1072"></a>
<a name="l1073"></a> </span><span class=cF1>default</span><span class=cF0>:
<a name="l1074"></a> </span><span class=cF5>Sleep</span><span class=cF0>(</span><span class=cFE>1</span><span class=cF0>);
<a name="l1075"></a> }
<a name="l1076"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1077"></a>
<a name="l1078"></a> </span><span class=cF1>if</span><span class=cF0> (tcp_socket-&gt;state != TCP_STATE_ESTABLISHED)
<a name="l1079"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l1080"></a>
<a name="l1081"></a> </span><span class=cF1>switch</span><span class=cF0> (tcp_socket-&gt;socket-&gt;state)
<a name="l1082"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1083"></a> </span><span class=cF1>case</span><span class=cF0> SOCKET_STATE_CONNECT_REQ: </span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>if CONNECT request success, set OPEN.</span><span class=cF0>
<a name="l1084"></a> tcp_socket-&gt;socket-&gt;state = SOCKET_STATE_OPEN;
<a name="l1085"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l1086"></a>
<a name="l1087"></a> </span><span class=cF1>default</span><span class=cF0>:
<a name="l1088"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET CONNECT: Failed, Misconfigured Socket state-machine.&quot;</span><span class=cF0>);
<a name="l1089"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l1090"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1091"></a>
<a name="l1092"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cFE>0</span><span class=cF0>;
<a name="l1093"></a>}
<a name="l1094"></a>
<a name="l1095"></a></span><span class=cF9>I64</span><span class=cF0> TCPSocketListen(CTCPSocket *tcp_socket, </span><span class=cF9>I64</span><span class=cF0> backlog_size)
<a name="l1096"></a>{ </span><span class=cF2>// Set a bound socket to Listen for incoming connections. Backlog size is max amount of waiting connections allowed</span><span class=cF0>
<a name="l1097"></a> </span><span class=cF1>if</span><span class=cF0> (!SocketListen</span><span class=cF7>(</span><span class=cF0>tcp_socket-&gt;socket</span><span class=cF7>)</span><span class=cF0>)
<a name="l1098"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1099"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET LISTEN: Socket state-machine must be in BOUND state.&quot;</span><span class=cF0>);
<a name="l1100"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l1101"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1102"></a>
<a name="l1103"></a> </span><span class=cF1>if</span><span class=cF0> (tcp_socket-&gt;state != TCP_STATE_CLOSED)
<a name="l1104"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1105"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET LISTEN: TCP Socket must be in CLOSED state.&quot;</span><span class=cF0>);
<a name="l1106"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l1107"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1108"></a>
<a name="l1109"></a> tcp_socket-&gt;state = TCP_STATE_LISTEN;
<a name="l1110"></a> tcp_socket-&gt;accept_queue_limit = backlog_size;
<a name="l1111"></a>
<a name="l1112"></a> </span><span class=cF1>switch</span><span class=cF0> (tcp_socket-&gt;socket-&gt;state)
<a name="l1113"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1114"></a> </span><span class=cF1>case</span><span class=cF0> SOCKET_STATE_LISTEN_REQ: </span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>if LISTEN request success, set BOUND.</span><span class=cF0>
<a name="l1115"></a> tcp_socket-&gt;socket-&gt;state = SOCKET_STATE_LISTENING;
<a name="l1116"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l1117"></a>
<a name="l1118"></a> </span><span class=cF1>default</span><span class=cF0>:
<a name="l1119"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET BIND: Failed, Misconfigured Socket state-machine.&quot;</span><span class=cF0>);
<a name="l1120"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l1121"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1122"></a>
<a name="l1123"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cFE>0</span><span class=cF0>;
<a name="l1124"></a>}
<a name="l1125"></a>
<a name="l1126"></a>CTCPSocket *TCPSocketAccept(CTCPSocket *tcp_socket)
<a name="l1127"></a>{ </span><span class=cF2>// Accepts &amp; creates a new socket, uses timeout inherited from Listening socket.</span><span class=cF0>
<a name="l1128"></a> CTCPAcceptQueue *pending;
<a name="l1129"></a> CTCPSocket *new_socket;
<a name="l1130"></a> CSocketAddressIPV4 *temp_addr;
<a name="l1131"></a> CSocketAddressIPV4 ipv4_address;
<a name="l1132"></a> </span><span class=cF9>I64</span><span class=cF0> timeout;
<a name="l1133"></a>
<a name="l1134"></a> </span><span class=cF1>if</span><span class=cF0> (!SocketAccept</span><span class=cF7>(</span><span class=cF0>tcp_socket-&gt;socket</span><span class=cF7>)</span><span class=cF0>)
<a name="l1135"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1136"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET ACCEPT: Failed, Socket state-machine must be in LISTENING state.&quot;</span><span class=cF0>);
<a name="l1137"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>NULL</span><span class=cF0>;
<a name="l1138"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1139"></a>
<a name="l1140"></a> </span><span class=cF1>if</span><span class=cF0> (tcp_socket-&gt;state != TCP_STATE_LISTEN)
<a name="l1141"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1142"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET LISTEN: TCP Socket must be in LISTEN state.&quot;</span><span class=cF0>);
<a name="l1143"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>NULL</span><span class=cF0>;
<a name="l1144"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1145"></a>
<a name="l1146"></a> timeout = </span><span class=cFB>counts</span><span class=cF0>.jiffies + tcp_socket-&gt;timeout * </span><span class=cF3>JIFFY_FREQ</span><span class=cF0> / </span><span class=cFE>1000</span><span class=cF0>;
<a name="l1147"></a> </span><span class=cF1>while</span><span class=cF0> (</span><span class=cF7>(</span><span class=cF0>pending = tcp_socket-&gt;accept_queue-&gt;next</span><span class=cF7>)</span><span class=cF0> == tcp_socket-&gt;accept_queue)
<a name="l1148"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1149"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cFB>counts</span><span class=cF0>.jiffies &gt; timeout)
<a name="l1150"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>NULL</span><span class=cF0>;
<a name="l1151"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l1152"></a> </span><span class=cF5>Sleep</span><span class=cF0>(</span><span class=cFE>1</span><span class=cF0>);
<a name="l1153"></a> </span><span class=cF2>// Yield;</span><span class=cF0>
<a name="l1154"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1155"></a>
<a name="l1156"></a> </span><span class=cF5>QueueRemove</span><span class=cF0>(pending); </span><span class=cF2>// whether successful accept() or not, remove pending connection.</span><span class=cF0>
<a name="l1157"></a>
<a name="l1158"></a></span><span class=cF2>// TODO: rework accept logic to handle IPV6 addresses</span><span class=cF0>
<a name="l1159"></a> new_socket = TCPSocket(AF_INET);
<a name="l1160"></a>
<a name="l1161"></a> new_socket-&gt;next_recv_seq_num = ++pending-&gt;segment_seq_num;
<a name="l1162"></a> new_socket-&gt;connection_time = </span><span class=cF5>tS</span><span class=cF0>;
<a name="l1163"></a> new_socket-&gt;receive_window = TCP_WINDOW_SIZE;
<a name="l1164"></a> new_socket-&gt;timeout = tcp_socket-&gt;timeout;
<a name="l1165"></a>
<a name="l1166"></a> temp_addr = &amp;tcp_socket-&gt;source_address;
<a name="l1167"></a>
<a name="l1168"></a> ipv4_address.family = AF_INET;
<a name="l1169"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>ipv4_address.port</span><span class=cF0> </span><span class=cF2>= pending-&gt;port;</span><span class=cF0>
<a name="l1170"></a> ipv4_address.port = temp_addr-&gt;port;
<a name="l1171"></a> ipv4_address.address.address = pending-&gt;ipv4_address;
<a name="l1172"></a>
<a name="l1173"></a> NetDebug(</span><span class=cF6>&quot;TCP SOCKET ACCEPT: Attempting to Bind to pending connection %0X @ src/dst ports %d,%d.&quot;</span><span class=cF0>,
<a name="l1174"></a> pending-&gt;ipv4_address, ipv4_address.port, pending-&gt;port);
<a name="l1175"></a>
<a name="l1176"></a> </span><span class=cF1>if</span><span class=cF0> (TCPSocketBind</span><span class=cF7>(</span><span class=cF0>new_socket, &amp;ipv4_address</span><span class=cF7>)</span><span class=cF0> == -</span><span class=cFE>1</span><span class=cF0>)
<a name="l1177"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1178"></a> </span><span class=cF5>Free</span><span class=cF0>(pending);
<a name="l1179"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>NULL</span><span class=cF0>;
<a name="l1180"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1181"></a>
<a name="l1182"></a> temp_addr = &amp;new_socket-&gt;destination_address;
<a name="l1183"></a>
<a name="l1184"></a> temp_addr-&gt;port = pending-&gt;port;
<a name="l1185"></a>
<a name="l1186"></a> new_socket-&gt;state = TCP_STATE_SYN_RECEIVED;
<a name="l1187"></a>
<a name="l1188"></a> NetDebug(</span><span class=cF6>&quot;TCP SOCKET ACCEPT: Attempting Send Flags SYN ACK back to requester.&quot;</span><span class=cF0>);
<a name="l1189"></a> TCPSendFlags(new_socket, TCPF_SYN | TCPF_ACK);
<a name="l1190"></a>
<a name="l1191"></a> timeout = </span><span class=cFB>counts</span><span class=cF0>.jiffies + new_socket-&gt;timeout * </span><span class=cF3>JIFFY_FREQ</span><span class=cF0> / </span><span class=cFE>1000</span><span class=cF0>;
<a name="l1192"></a> </span><span class=cF1>while</span><span class=cF0> (</span><span class=cFB>counts</span><span class=cF0>.jiffies &lt; timeout)
<a name="l1193"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1194"></a> </span><span class=cF1>switch</span><span class=cF0> (new_socket-&gt;state)
<a name="l1195"></a> {
<a name="l1196"></a> </span><span class=cF1>case</span><span class=cF0> TCP_STATE_ESTABLISHED:
<a name="l1197"></a> </span><span class=cF1>case</span><span class=cF0> TCP_STATE_CLOSED:
<a name="l1198"></a> timeout = </span><span class=cFE>0</span><span class=cF0>; </span><span class=cF2>// break out of while loop</span><span class=cF0>
<a name="l1199"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l1200"></a>
<a name="l1201"></a> </span><span class=cF1>default</span><span class=cF0>:
<a name="l1202"></a> </span><span class=cF5>Sleep</span><span class=cF0>(</span><span class=cFE>1</span><span class=cF0>);
<a name="l1203"></a> }
<a name="l1204"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1205"></a>
<a name="l1206"></a> </span><span class=cF1>if</span><span class=cF0> (new_socket-&gt;state != TCP_STATE_ESTABLISHED)
<a name="l1207"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1208"></a> TCPSocketClose(new_socket);
<a name="l1209"></a> </span><span class=cF5>Free</span><span class=cF0>(pending);
<a name="l1210"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>NULL</span><span class=cF0>;
<a name="l1211"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1212"></a>
<a name="l1213"></a> </span><span class=cF5>Free</span><span class=cF0>(pending);
<a name="l1214"></a>
<a name="l1215"></a> new_socket-&gt;socket-&gt;state = SOCKET_STATE_OPEN;
<a name="l1216"></a>
<a name="l1217"></a> </span><span class=cF1>return</span><span class=cF0> new_socket;
<a name="l1218"></a>}
<a name="l1219"></a>
<a name="l1220"></a></span><span class=cF9>I64</span><span class=cF0> TCPSocketReceive(CTCPSocket *tcp_socket, </span><span class=cF1>U8</span><span class=cF0> *buffer, </span><span class=cF9>I64</span><span class=cF0> length)
<a name="l1221"></a>{
<a name="l1222"></a> </span><span class=cF9>I64</span><span class=cF0> read_position;
<a name="l1223"></a> </span><span class=cF9>I64</span><span class=cF0> write_position;
<a name="l1224"></a> </span><span class=cF9>I64</span><span class=cF0> read_total = </span><span class=cFE>0</span><span class=cF0>;
<a name="l1225"></a> </span><span class=cF9>I64</span><span class=cF0> step;
<a name="l1226"></a> </span><span class=cF9>I64</span><span class=cF0> timeout;
<a name="l1227"></a>
<a name="l1228"></a> </span><span class=cF1>if</span><span class=cF0> (!SocketReceive</span><span class=cF7>(</span><span class=cF0>tcp_socket-&gt;socket</span><span class=cF7>)</span><span class=cF0>)
<a name="l1229"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1230"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET RECEIVE: Failed, Socket state-machine must be in OPEN or BOUND state.&quot;</span><span class=cF0>);
<a name="l1231"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>NULL</span><span class=cF0>;
<a name="l1232"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1233"></a>
<a name="l1234"></a> timeout = </span><span class=cFB>counts</span><span class=cF0>.jiffies + tcp_socket-&gt;timeout * </span><span class=cF3>JIFFY_FREQ</span><span class=cF0> / </span><span class=cFE>1000</span><span class=cF0>;
<a name="l1235"></a>
<a name="l1236"></a> </span><span class=cF1>while</span><span class=cF0> (</span><span class=cF7>(</span><span class=cF0>tcp_socket-&gt;state == TCP_STATE_ESTABLISHED || tcp_socket-&gt;state == TCP_STATE_FIN_WAIT1</span><span class=cF7>)</span><span class=cF0> &amp;&amp;
<a name="l1237"></a> tcp_socket-&gt;read_position == tcp_socket-&gt;write_position)
<a name="l1238"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1239"></a> TCPCheckACKQueue(tcp_socket);
<a name="l1240"></a> </span><span class=cF5>Sleep</span><span class=cF0>(</span><span class=cFE>1</span><span class=cF0>);
<a name="l1241"></a>
<a name="l1242"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cFB>counts</span><span class=cF0>.jiffies &gt; timeout)
<a name="l1243"></a> {
<a name="l1244"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>if (tcp_socket-&gt;timeout != 0) // Don't flood NetLog on non-blocking receives.</span><span class=cF0>
<a name="l1245"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>NetErr(&quot;TCP SOCKET RECEIVE: Timed out.&quot;);</span><span class=cF0>
<a name="l1246"></a>
<a name="l1247"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>return -1;</span><span class=cF0>
<a name="l1248"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l1249"></a> }
<a name="l1250"></a>
<a name="l1251"></a>
<a name="l1252"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1253"></a>
<a name="l1254"></a> </span><span class=cF2>// Shrine has TODO: Should still be able to receive in closing states ...</span><span class=cF0>
<a name="l1255"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF7>(</span><span class=cF0>tcp_socket-&gt;state != TCP_STATE_ESTABLISHED || tcp_socket-&gt;state == TCP_STATE_FIN_WAIT1</span><span class=cF7>)</span><span class=cF0> &amp;&amp;
<a name="l1256"></a> tcp_socket-&gt;read_position == tcp_socket-&gt;write_position || length == </span><span class=cFE>0</span><span class=cF0>)
<a name="l1257"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cFE>0</span><span class=cF0>;
<a name="l1258"></a>
<a name="l1259"></a>
<a name="l1260"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cFB>counts</span><span class=cF0>.jiffies &gt; timeout)
<a name="l1261"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1262"></a> </span><span class=cF1>if</span><span class=cF0> (tcp_socket-&gt;timeout != </span><span class=cFE>0</span><span class=cF0>) </span><span class=cF2>// Don't flood NetLog on non-blocking receives.</span><span class=cF0>
<a name="l1263"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET RECEIVE: Timed out.&quot;</span><span class=cF0>);
<a name="l1264"></a>
<a name="l1265"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l1266"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1267"></a>
<a name="l1268"></a>
<a name="l1269"></a> read_position = tcp_socket-&gt;read_position;
<a name="l1270"></a> write_position = tcp_socket-&gt;write_position;
<a name="l1271"></a>
<a name="l1272"></a> </span><span class=cF1>if</span><span class=cF0> (write_position &lt; read_position)
<a name="l1273"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1274"></a> step = tcp_socket-&gt;receive_buffer_size - read_position;
<a name="l1275"></a>
<a name="l1276"></a> </span><span class=cF1>if</span><span class=cF0> (step &gt; length)
<a name="l1277"></a> step = length;
<a name="l1278"></a>
<a name="l1279"></a> </span><span class=cF5>MemCopy</span><span class=cF0>(buffer, tcp_socket-&gt;receive_buffer + read_position, step);
<a name="l1280"></a> buffer += step;
<a name="l1281"></a> length -= step;
<a name="l1282"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>read_position = (read_position + step) &amp; (tcp_socket-&gt;receive_buffer_size - 1);</span><span class=cF0>
<a name="l1283"></a> read_position = (read_position + step) % tcp_socket-&gt;receive_buffer_size;
<a name="l1284"></a> read_total += step;
<a name="l1285"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1286"></a>
<a name="l1287"></a> </span><span class=cF1>if</span><span class=cF0> (length &gt; </span><span class=cFE>0</span><span class=cF0>)
<a name="l1288"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1289"></a> step = write_position - read_position;
<a name="l1290"></a>
<a name="l1291"></a> </span><span class=cF1>if</span><span class=cF0> (step &gt; length)
<a name="l1292"></a> step = length;
<a name="l1293"></a>
<a name="l1294"></a> </span><span class=cF5>MemCopy</span><span class=cF0>(buffer, tcp_socket-&gt;receive_buffer + read_position, step);
<a name="l1295"></a> buffer += step;
<a name="l1296"></a> length -= step;
<a name="l1297"></a> read_position += step;
<a name="l1298"></a> read_total += step;
<a name="l1299"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1300"></a>
<a name="l1301"></a> tcp_socket-&gt;read_position = read_position;
<a name="l1302"></a>
<a name="l1303"></a> </span><span class=cF1>return</span><span class=cF0> read_total;
<a name="l1304"></a>}
<a name="l1305"></a>
<a name="l1306"></a></span><span class=cF9>I64</span><span class=cF0> TCPSocketSend(CTCPSocket *tcp_socket, </span><span class=cF1>U8</span><span class=cF0> *buffer, </span><span class=cF9>I64</span><span class=cF0> length)
<a name="l1307"></a>{
<a name="l1308"></a> </span><span class=cF9>I64</span><span class=cF0> sent_total = </span><span class=cFE>0</span><span class=cF0>;
<a name="l1309"></a> </span><span class=cF9>I64</span><span class=cF0> timeout = </span><span class=cFB>counts</span><span class=cF0>.jiffies + tcp_socket-&gt;timeout * </span><span class=cF3>JIFFY_FREQ</span><span class=cF0> / </span><span class=cFE>1000</span><span class=cF0>;
<a name="l1310"></a> </span><span class=cF9>I64</span><span class=cF0> send_length;
<a name="l1311"></a>
<a name="l1312"></a> </span><span class=cF1>if</span><span class=cF0> (!SocketSend</span><span class=cF7>(</span><span class=cF0>tcp_socket-&gt;socket</span><span class=cF7>)</span><span class=cF0>)
<a name="l1313"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1314"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET SEND: Failed, Socket state-machine must be in OPEN state.&quot;</span><span class=cF0>);
<a name="l1315"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>;
<a name="l1316"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1317"></a>
<a name="l1318"></a> </span><span class=cF1>while</span><span class=cF0> (</span><span class=cF7>(</span><span class=cF0>tcp_socket-&gt;state == TCP_STATE_ESTABLISHED || tcp_socket-&gt;state == TCP_STATE_CLOSE_WAIT</span><span class=cF7>)</span><span class=cF0> &amp;&amp;
<a name="l1319"></a> length)
<a name="l1320"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1321"></a> send_length = (tcp_socket-&gt;first_unacked_seq + tcp_socket-&gt;send_window - tcp_socket-&gt;next_send_seq_num) &amp; </span><span class=cFE>0xFFFFFFFF</span><span class=cF0>;
<a name="l1322"></a>
<a name="l1323"></a> </span><span class=cF2>// Shrine has TODO: Keep trying, tie to timeout: RFC 793 &quot;Managing The Window&quot;</span><span class=cF0>
<a name="l1324"></a>
<a name="l1325"></a> </span><span class=cF1>if</span><span class=cF0> (send_length == </span><span class=cFE>0</span><span class=cF0>)
<a name="l1326"></a> {
<a name="l1327"></a> </span><span class=cF1>if</span><span class=cF0> (sent_total &gt; </span><span class=cFE>0</span><span class=cF0>)
<a name="l1328"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l1329"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l1330"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1331"></a> TCPCheckACKQueue(tcp_socket);
<a name="l1332"></a> </span><span class=cF5>Sleep</span><span class=cF0>(</span><span class=cFE>1</span><span class=cF0>);
<a name="l1333"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1334"></a> }
<a name="l1335"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l1336"></a> {
<a name="l1337"></a> </span><span class=cF1>if</span><span class=cF0> (send_length &gt; length)
<a name="l1338"></a> send_length = length;
<a name="l1339"></a>
<a name="l1340"></a> </span><span class=cF1>if</span><span class=cF0> (send_length &gt; tcp_socket-&gt;max_segment_size)
<a name="l1341"></a> send_length = tcp_socket-&gt;max_segment_size;
<a name="l1342"></a>
<a name="l1343"></a> NetDebug(</span><span class=cF6>&quot;TCP SOCKET SEND: Trying TCPSendData() of %d bytes.&quot;</span><span class=cF0>, send_length);
<a name="l1344"></a> </span><span class=cF1>if</span><span class=cF0> (TCPSendData</span><span class=cF7>(</span><span class=cF0>tcp_socket, TCPF_ACK, buffer, send_length</span><span class=cF7>)</span><span class=cF0> &lt; </span><span class=cFE>0</span><span class=cF0>)
<a name="l1345"></a> </span><span class=cF7>{</span><span class=cF0> </span><span class=cF2>// Stall until outgoing data acknowledged.</span><span class=cF0>
<a name="l1346"></a> </span><span class=cF1>if</span><span class=cF0> (sent_total &gt; </span><span class=cFE>0</span><span class=cF0>)
<a name="l1347"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l1348"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l1349"></a> {
<a name="l1350"></a> TCPCheckACKQueue(tcp_socket);
<a name="l1351"></a> </span><span class=cF5>Sleep</span><span class=cF0>(</span><span class=cFE>1</span><span class=cF0>);
<a name="l1352"></a> }
<a name="l1353"></a>
<a name="l1354"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1355"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l1356"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1357"></a> buffer += send_length;
<a name="l1358"></a> length -= send_length;
<a name="l1359"></a> sent_total += send_length;
<a name="l1360"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1361"></a> }
<a name="l1362"></a>
<a name="l1363"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cFB>counts</span><span class=cF0>.jiffies &gt; timeout)
<a name="l1364"></a> {
<a name="l1365"></a> </span><span class=cF1>if</span><span class=cF0> (tcp_socket-&gt;timeout != </span><span class=cFE>0</span><span class=cF0>) </span><span class=cF2>// Don't flood NetLog on non-blocking sends.</span><span class=cF0>
<a name="l1366"></a> NetErr(</span><span class=cF6>&quot;TCP SOCKET SEND: Timed out.&quot;</span><span class=cF0>);
<a name="l1367"></a>
<a name="l1368"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l1369"></a> }
<a name="l1370"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1371"></a>
<a name="l1372"></a> </span><span class=cF1>return</span><span class=cF0> sent_total;
<a name="l1373"></a>}
<a name="l1374"></a>
<a name="l1375"></a></span><span class=cF9>I64</span><span class=cF0> TCPSocketSendAll(CTCPSocket *tcp_socket, </span><span class=cF1>U8</span><span class=cF0> *buffer, </span><span class=cF9>I64</span><span class=cF0> length)
<a name="l1376"></a>{
<a name="l1377"></a> </span><span class=cF9>I64</span><span class=cF0> total = </span><span class=cFE>0</span><span class=cF0>;
<a name="l1378"></a> </span><span class=cF9>I64</span><span class=cF0> sent = </span><span class=cFE>0</span><span class=cF0>;
<a name="l1379"></a>
<a name="l1380"></a> </span><span class=cF1>while</span><span class=cF0> (length)
<a name="l1381"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1382"></a> sent = TCPSocketSend(tcp_socket, buffer, length);
<a name="l1383"></a>
<a name="l1384"></a> </span><span class=cF1>if</span><span class=cF0> (sent &gt; </span><span class=cFE>0</span><span class=cF0>)
<a name="l1385"></a> {
<a name="l1386"></a> buffer += sent;
<a name="l1387"></a> total += sent;
<a name="l1388"></a> length -= sent;
<a name="l1389"></a> }
<a name="l1390"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l1391"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l1392"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1393"></a>
<a name="l1394"></a> </span><span class=cF1>return</span><span class=cF0> total;
<a name="l1395"></a>}
<a name="l1396"></a>
<a name="l1397"></a></span><span class=cF9>I64</span><span class=cF0> TCPSocketSendString(CTCPSocket *tcp_socket, </span><span class=cF1>U8</span><span class=cF0> *string)
<a name="l1398"></a>{
<a name="l1399"></a> </span><span class=cF1>return</span><span class=cF0> TCPSocketSendAll(tcp_socket, string, </span><span class=cF5>StrLen</span><span class=cF7>(</span><span class=cF0>string</span><span class=cF7>)</span><span class=cF0>);
<a name="l1400"></a>}
<a name="l1401"></a>
<a name="l1402"></a></span><span class=cF1>U0</span><span class=cF0> TCPTreeNodeRep(CTCPTreeNode *node)
<a name="l1403"></a>{
<a name="l1404"></a> CTCPTreeQueue *queue = node-&gt;queue-&gt;next;
<a name="l1405"></a> CTCPSocket *socket;
<a name="l1406"></a> CSocketAddressIPV4 *ipv4_addr;
<a name="l1407"></a> CSocketAddressIPV6 *ipv6_addr;
<a name="l1408"></a> </span><span class=cF1>U8</span><span class=cF0> *string;
<a name="l1409"></a> CTCPAcceptQueue *pending;
<a name="l1410"></a>
<a name="l1411"></a>
<a name="l1412"></a> </span><span class=cF6>&quot;Local Port $YELLOW$%d$FG$ (TCP Node @ $CYAN$0x%X$FG$):\n&quot;</span><span class=cF0>, node-&gt;value, node;
<a name="l1413"></a>
<a name="l1414"></a> </span><span class=cF1>while</span><span class=cF0> (queue != node-&gt;queue)
<a name="l1415"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1416"></a>
<a name="l1417"></a> socket = queue-&gt;socket;
<a name="l1418"></a>
<a name="l1419"></a> </span><span class=cF1>switch</span><span class=cF0> (socket-&gt;destination_address.family)
<a name="l1420"></a> {
<a name="l1421"></a>
<a name="l1422"></a> </span><span class=cF1>case</span><span class=cF0> AF_UNSPEC:
<a name="l1423"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l1424"></a>
<a name="l1425"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET:
<a name="l1426"></a> ipv4_addr = &amp;socket-&gt;destination_address;
<a name="l1427"></a> string = </span><span class=cF5>MStrPrint</span><span class=cF0>(</span><span class=cF6>&quot;%d.%d.%d.%d&quot;</span><span class=cF0>,
<a name="l1428"></a> ipv4_addr-&gt;address.address.u8[</span><span class=cFE>3</span><span class=cF0>],
<a name="l1429"></a> ipv4_addr-&gt;address.address.u8[</span><span class=cFE>2</span><span class=cF0>],
<a name="l1430"></a> ipv4_addr-&gt;address.address.u8[</span><span class=cFE>1</span><span class=cF0>],
<a name="l1431"></a> ipv4_addr-&gt;address.address.u8[</span><span class=cFE>0</span><span class=cF0>]); </span><span class=cF2>// todo: kludge, endianness...</span><span class=cF0>
<a name="l1432"></a>
<a name="l1433"></a> </span><span class=cF6>&quot;</span><span class=cF0> </span><span class=cF6>$BROWN$%s$FG$ Destination Port $YELLOW$%d$FG$ (TCP Tree Queue @ $CYAN$0x%X$FG$):\n&quot;</span><span class=cF0>,
<a name="l1434"></a> string, </span><span class=cF5>EndianU16</span><span class=cF0>(ipv4_addr-&gt;port), queue;
<a name="l1435"></a> </span><span class=cF5>Free</span><span class=cF0>(string);
<a name="l1436"></a>
<a name="l1437"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l1438"></a>
<a name="l1439"></a> </span><span class=cF1>case</span><span class=cF0> AF_INET6:
<a name="l1440"></a> ipv6_addr = &amp;socket-&gt;destination_address;
<a name="l1441"></a>
<a name="l1442"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l1443"></a>
<a name="l1444"></a> </span><span class=cF1>default</span><span class=cF0>:
<a name="l1445"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l1446"></a>
<a name="l1447"></a> }
<a name="l1448"></a>
<a name="l1449"></a> </span><span class=cF6>&quot;</span><span class=cF0> </span><span class=cF6>Timeout: %dms\n&quot;</span><span class=cF0>, socket-&gt;timeout;
<a name="l1450"></a>
<a name="l1451"></a> pending = socket-&gt;accept_queue-&gt;next;
<a name="l1452"></a>
<a name="l1453"></a> </span><span class=cF1>while</span><span class=cF0> (pending != socket-&gt;accept_queue-&gt;next)
<a name="l1454"></a> {
<a name="l1455"></a> </span><span class=cF6>&quot;</span><span class=cF0> </span><span class=cF6>Pending connection from $BROWN$%d.%d.%d.%d$FG$:&quot;</span><span class=cF0>,
<a name="l1456"></a> pending-&gt;ipv4_address.u8[</span><span class=cFE>3</span><span class=cF0>],
<a name="l1457"></a> pending-&gt;ipv4_address.u8[</span><span class=cFE>2</span><span class=cF0>],
<a name="l1458"></a> pending-&gt;ipv4_address.u8[</span><span class=cFE>1</span><span class=cF0>],
<a name="l1459"></a> pending-&gt;ipv4_address.u8[</span><span class=cFE>0</span><span class=cF0>]; </span><span class=cF2>//todo: kludge, endianness?</span><span class=cF0>
<a name="l1460"></a>
<a name="l1461"></a> pending = pending-&gt;next;
<a name="l1462"></a> }
<a name="l1463"></a>
<a name="l1464"></a>
<a name="l1465"></a> queue = queue-&gt;next;
<a name="l1466"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1467"></a>
<a name="l1468"></a> </span><span class=cF6>&quot;\n&quot;</span><span class=cF0>;
<a name="l1469"></a>}
<a name="l1470"></a>
<a name="l1471"></a></span><span class=cF1>U0</span><span class=cF0> TCPRep()
<a name="l1472"></a>{
<a name="l1473"></a> CTCPTreeNode *node = tcp_globals.bound_socket_tree;
<a name="l1474"></a> CTCPRepEntry *head;
<a name="l1475"></a> CTCPRepEntry *entry;
<a name="l1476"></a> CTCPRepEntry *temp_entry;
<a name="l1477"></a>
<a name="l1478"></a> </span><span class=cF6>&quot;$LTBLUE$TCP Report:$FG$\n\n&quot;</span><span class=cF0>;
<a name="l1479"></a>
<a name="l1480"></a> </span><span class=cF1>if</span><span class=cF0> (node)
<a name="l1481"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1482"></a> head = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CTCPRepEntry</span><span class=cF7>)</span><span class=cF0>);
<a name="l1483"></a> </span><span class=cF5>QueueInit</span><span class=cF0>(head); </span><span class=cF2>// no QueueRemove the head</span><span class=cF0>
<a name="l1484"></a>
<a name="l1485"></a> entry = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CTCPRepEntry</span><span class=cF7>)</span><span class=cF0>);
<a name="l1486"></a> entry-&gt;node = node;
<a name="l1487"></a> </span><span class=cF5>QueueInsert</span><span class=cF0>(entry, head);
<a name="l1488"></a>
<a name="l1489"></a> </span><span class=cF2>// perform depth-first-search while Entry Queue has nodes not fully visited.</span><span class=cF0>
<a name="l1490"></a> </span><span class=cF1>while</span><span class=cF0> (entry != head)
<a name="l1491"></a> {
<a name="l1492"></a> </span><span class=cF1>if</span><span class=cF0> (entry-&gt;node-&gt;left)
<a name="l1493"></a> </span><span class=cF7>{</span><span class=cF0> </span><span class=cF2>// if node has one, add an Entry for the left branch, continue loop.</span><span class=cF0>
<a name="l1494"></a> temp_entry = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CTCPRepEntry</span><span class=cF7>)</span><span class=cF0>);
<a name="l1495"></a> temp_entry-&gt;node = entry-&gt;node-&gt;left;
<a name="l1496"></a> </span><span class=cF5>QueueInsertRev</span><span class=cF0>(temp_entry, head);
<a name="l1497"></a>
<a name="l1498"></a> </span><span class=cF2>// if left branch, but no right: toss early, now fully traveled.</span><span class=cF0>
<a name="l1499"></a> </span><span class=cF1>if</span><span class=cF0> (!entry-&gt;node-&gt;right)
<a name="l1500"></a> {
<a name="l1501"></a> </span><span class=cF5>QueueRemove</span><span class=cF0>(entry);
<a name="l1502"></a> TCPTreeNodeRep(entry-&gt;node);
<a name="l1503"></a> </span><span class=cF5>Free</span><span class=cF0>(entry);
<a name="l1504"></a> }
<a name="l1505"></a>
<a name="l1506"></a> entry = temp_entry;
<a name="l1507"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1508"></a> </span><span class=cF1>else</span><span class=cF0> </span><span class=cF1>if</span><span class=cF0> (entry-&gt;node-&gt;right)
<a name="l1509"></a> </span><span class=cF7>{</span><span class=cF0> </span><span class=cF2>// if no left, but right: add right to queue, pop Entry, Rep, set entry to right.</span><span class=cF0>
<a name="l1510"></a> temp_entry = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CTCPRepEntry</span><span class=cF7>)</span><span class=cF0>);
<a name="l1511"></a> temp_entry-&gt;node = entry-&gt;node-&gt;right;
<a name="l1512"></a> </span><span class=cF5>QueueInsertRev</span><span class=cF0>(temp_entry, head);
<a name="l1513"></a>
<a name="l1514"></a> </span><span class=cF5>QueueRemove</span><span class=cF0>(entry);
<a name="l1515"></a> TCPTreeNodeRep(entry-&gt;node);
<a name="l1516"></a> </span><span class=cF5>Free</span><span class=cF0>(entry);
<a name="l1517"></a>
<a name="l1518"></a> entry = temp_entry;
<a name="l1519"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1520"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l1521"></a> </span><span class=cF7>{</span><span class=cF0> </span><span class=cF2>// pop Entry, Rep, if last Entry in Queue has right add it, pop &amp; Rep travelled Entry, entry = right.</span><span class=cF0>
<a name="l1522"></a> </span><span class=cF5>QueueRemove</span><span class=cF0>(entry);
<a name="l1523"></a> TCPTreeNodeRep(entry-&gt;node);
<a name="l1524"></a> </span><span class=cF5>Free</span><span class=cF0>(entry);
<a name="l1525"></a>
<a name="l1526"></a> </span><span class=cF1>if</span><span class=cF0> (head-&gt;last != head)
<a name="l1527"></a> {
<a name="l1528"></a> temp_entry = head-&gt;last;
<a name="l1529"></a>
<a name="l1530"></a> </span><span class=cF1>if</span><span class=cF0> (temp_entry-&gt;node-&gt;right)
<a name="l1531"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1532"></a> entry = temp_entry;
<a name="l1533"></a>
<a name="l1534"></a> temp_entry = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CTCPRepEntry</span><span class=cF7>)</span><span class=cF0>);
<a name="l1535"></a> temp_entry-&gt;node = entry-&gt;node-&gt;right;
<a name="l1536"></a> </span><span class=cF5>QueueInsertRev</span><span class=cF0>(temp_entry, head);
<a name="l1537"></a>
<a name="l1538"></a> </span><span class=cF5>QueueRemove</span><span class=cF0>(entry);
<a name="l1539"></a> TCPTreeNodeRep(entry-&gt;node);
<a name="l1540"></a> </span><span class=cF5>Free</span><span class=cF0>(entry);
<a name="l1541"></a>
<a name="l1542"></a> entry = temp_entry;
<a name="l1543"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1544"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l1545"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1546"></a> </span><span class=cF5>QueueRemove</span><span class=cF0>(temp_entry);
<a name="l1547"></a> TCPTreeNodeRep(temp_entry-&gt;node);
<a name="l1548"></a> </span><span class=cF5>Free</span><span class=cF0>(temp_entry);
<a name="l1549"></a>
<a name="l1550"></a> entry = head-&gt;last;
<a name="l1551"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1552"></a> }
<a name="l1553"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l1554"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l1555"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1556"></a> }
<a name="l1557"></a>
<a name="l1558"></a> </span><span class=cF5>Free</span><span class=cF0>(head);
<a name="l1559"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1560"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l1561"></a> </span><span class=cF6>&quot;No TCP Sockets currently bound.\n\n&quot;</span><span class=cF0>;
<a name="l1562"></a>}
<a name="l1563"></a>
<a name="l1564"></a>
<a name="l1565"></a>TCPGlobalsInit;</span></pre></body>
</html>