PageRenderTime 32ms CodeModel.GetById 31ms RepoModel.GetById 5ms app.codeStats 1ms

/verify/src/Checked/Libraries/NetStack2/TCP/TCP.cs

#
C# | 2164 lines | 1691 code | 278 blank | 195 comment | 396 complexity | 8d77311fa08705dae54112f9875a5e1c MD5 | raw file
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Microsoft Research Singularity
  4. //
  5. // Copyright (c) Microsoft Corporation. All rights reserved.
  6. //
  7. // File:
  8. //
  9. // Note: Goal -- implement TCP RENO
  10. //
  11. //#define DEBUG_TCP
  12. //#define TCP_THREAD_POOL
  13. using System;
  14. using Drivers.Net;
  15. using System.Net.IP;
  16. using System.Threading;
  17. using System.Diagnostics;
  18. using System.Collections;
  19. using System.Runtime.CompilerServices;
  20. using Microsoft.Singularity;
  21. using Microsoft.Singularity.Channels;
  22. using Microsoft.Singularity.Io;
  23. using Microsoft.Singularity.Io.Net;
  24. using Microsoft.Singularity.V1.Services;
  25. using Microsoft.SingSharp;
  26. using Microsoft.Contracts;
  27. using TcpError = NetStack.Contracts.TcpError;
  28. namespace Microsoft.Singularity.NetStack2
  29. {
  30. public enum TcpState : short
  31. {
  32. //we break camel case here for the sake of tradition
  33. CLOSED = 0,
  34. LISTEN = 1,
  35. SYN_SENT = 2,
  36. SYN_RECEIVED = 3,
  37. ESTABLISHED = 4,
  38. FIN_WAIT_1 = 5,
  39. FIN_WAIT_2 = 6,
  40. CLOSE_WAIT = 7,
  41. CLOSING = 8,
  42. LAST_ACK = 9,
  43. TIME_WAIT = 10,
  44. }
  45. [FlagsAttribute]
  46. public enum TcpFlags : byte
  47. {
  48. FIN = 0x01,
  49. SYN = 0x02,
  50. RST = 0x04,
  51. PSH = 0x08,
  52. ACK = 0x10,
  53. URG = 0x20,
  54. ECE = 0x40,
  55. CWR = 0x80,
  56. }
  57. enum TcpOptions : byte
  58. {
  59. EOL = 0,
  60. NOP = 1,
  61. MSS = 2, //set the MSS
  62. WSF = 3, //windows scaling
  63. TIMESTAMP = 8, //use timestamps
  64. }
  65. public struct TcpHeader
  66. {
  67. public const int MinSize = 20;
  68. public ushort srcPort;
  69. public ushort destPort;
  70. public uint seqNumber;
  71. public uint ackNumber;
  72. public byte dataOffsetBytes; //offset counted in 4 byte intervals
  73. public byte dataOffset; //offset where data begins in 32 bit words
  74. public byte flags;
  75. public ushort windowSize;
  76. public ushort checksum;
  77. public ushort urgentPointer;
  78. // Compare two TCP sequence numbers:
  79. // - means A < B, 0 means A == B and + means A > B
  80. //[Pure]
  81. [Inline]
  82. private static int SequenceNumberCompare(uint seqA, uint seqB)
  83. {
  84. // Exploit integer underflow to compare correctly even in the case
  85. // of sequence number wraparound. This assumes the two numbers are
  86. // always in the same half of the numberspace.
  87. return unchecked((int)(unchecked(seqA - seqB)));
  88. }
  89. //[Pure]
  90. public static bool SeqEQ(uint seqA, uint seqB)
  91. {
  92. return TcpHeader.SequenceNumberCompare(seqA, seqB) == 0;
  93. }
  94. //[Pure]
  95. public static bool SeqNEQ(uint seqA, uint seqB)
  96. {
  97. return TcpHeader.SequenceNumberCompare(seqA, seqB) != 0;
  98. }
  99. //[Pure]
  100. public static bool SeqLEQ(uint seqA, uint seqB)
  101. {
  102. return TcpHeader.SequenceNumberCompare(seqA, seqB) <= 0;
  103. }
  104. //[Pure]
  105. public static bool SeqLess(uint seqA, uint seqB)
  106. {
  107. return TcpHeader.SequenceNumberCompare(seqA, seqB) < 0;
  108. }
  109. //[Pure]
  110. public static bool SeqGEQ(uint seqA, uint seqB)
  111. {
  112. return TcpHeader.SequenceNumberCompare(seqA, seqB) >= 0;
  113. }
  114. //[Pure]
  115. public static bool SeqGreater(uint seqA, uint seqB)
  116. {
  117. return TcpHeader.SequenceNumberCompare(seqA, seqB) > 0;
  118. }
  119. public TcpHeader(Bytes packet, int index)
  120. {
  121. srcPort = NetworkBitConverter.ToUInt16(packet, index);
  122. index += 2;
  123. destPort = NetworkBitConverter.ToUInt16(packet, index);
  124. index += 2;
  125. seqNumber = NetworkBitConverter.ToUInt32(packet, index);
  126. index += 4;
  127. ackNumber = NetworkBitConverter.ToUInt32(packet, index);
  128. index += 4;
  129. dataOffsetBytes = packet[index++];
  130. dataOffset = (byte) ((dataOffsetBytes >> 4) * 4);
  131. flags = packet[index++];
  132. windowSize = NetworkBitConverter.ToUInt16(packet, index);
  133. index += 2;
  134. checksum = NetworkBitConverter.ToUInt16(packet, index);
  135. index += 2;
  136. urgentPointer = NetworkBitConverter.ToUInt16(packet, index);
  137. }
  138. public static ushort SumHeader(TcpHeader tcpHeader)
  139. {
  140. int checksum = tcpHeader.srcPort;
  141. checksum += tcpHeader.destPort;
  142. checksum += (int) (tcpHeader.seqNumber >> 16);
  143. checksum += (int) (tcpHeader.seqNumber & 0xffff);
  144. checksum += (int) (tcpHeader.ackNumber >> 16);
  145. checksum += (int) (tcpHeader.ackNumber & 0xffff);
  146. checksum += (((int)tcpHeader.dataOffsetBytes) << 8) | (int)tcpHeader.flags;
  147. checksum += (int) tcpHeader.windowSize;
  148. checksum += (int) tcpHeader.urgentPointer;
  149. // Double-wrap checksum
  150. checksum = (checksum & 0xFFFF) + (checksum >> 16);
  151. checksum = (checksum & 0xFFFF) + (checksum >> 16);
  152. return (ushort)checksum;
  153. }
  154. public static bool IsChecksumValid(IpHeader ipHeader,
  155. TcpHeader tcpHeader,
  156. Bytes buffer)
  157. {
  158. int ipOffset = EthernetHeader.Size;
  159. ushort ipPayloadSize = 0;
  160. // Compute partial checksums of headers
  161. ushort chksum = IpHeader.SumPseudoHeader(buffer, ipOffset, ref ipPayloadSize);
  162. chksum = IpHeader.SumShortValues(chksum, SumHeader(tcpHeader));
  163. // Checksum payload (without potential odd byte)
  164. //XXX we include tcp options in the 'payload' for checksumming...related to legacy code from
  165. //old netstack...should be cleaned up.
  166. int payloadOffset = TcpHeader.MinSize + IpHeader.Size + EthernetHeader.Size;
  167. int payloadLength = ipPayloadSize - TcpHeader.MinSize;
  168. //DebugStub.WriteLine("payload length {0}\n", DebugStub.ArgList(payloadLength));
  169. ushort payloadSum = IpHeader.SumShortValues(buffer, payloadOffset, payloadLength);
  170. chksum = IpHeader.SumShortValues(chksum, payloadSum);
  171. unchecked {
  172. chksum = (ushort)~chksum;
  173. }
  174. //who know.....
  175. if (chksum == (ushort) 0xFFFF) {
  176. chksum = 0;
  177. }
  178. else if (chksum == (ushort) 0x0) {
  179. chksum = 0xFFFF;
  180. }
  181. // Check for match.
  182. bool checksumMatch = (tcpHeader.checksum == chksum);
  183. // If checksum error, unconditionally output message to debugger.
  184. if (checksumMatch == false) {
  185. DebugStub.WriteLine("Bad TCP checksum {0:x4} != {1:x4}: SEQ {2:x8} ACK {3:x8}",
  186. DebugStub.ArgList(tcpHeader.checksum, chksum,
  187. tcpHeader.seqNumber,
  188. tcpHeader.ackNumber
  189. ));
  190. }
  191. // IsValid is a Match.
  192. // return checksumMatch;
  193. return true;
  194. }
  195. public static void SetTcpChecksum(Bytes buffer,
  196. Bytes payload,
  197. int ipOffset,
  198. ushort tcpLength)
  199. {
  200. // sum IP pseudo
  201. ushort ipPayloadSize = 0;
  202. ushort headerSum = IpHeader.SumPseudoHeader(buffer, ipOffset,
  203. ref ipPayloadSize);
  204. DebugStub.Assert((tcpLength + payload.Length) == ipPayloadSize);
  205. // now add it to the udp header + data
  206. int ipHeaderSize = (buffer[ipOffset] & 0xf) * 4;
  207. int tcpOffset = ipOffset + ipHeaderSize;
  208. ushort tcpsum = IpHeader.SumShortValues(buffer, ipOffset+IpHeader.Size, tcpLength);
  209. DebugStub.Assert(buffer[tcpOffset + 16] == 0);
  210. DebugStub.Assert(buffer[tcpOffset + 17] == 0);
  211. ushort payloadSum = IpHeader.SumShortValues(payload, 0,
  212. payload.Length);
  213. ushort hdrSum = IpHeader.SumShortValues(headerSum, tcpsum);
  214. ushort chksum;
  215. chksum = (ushort) ~(
  216. IpHeader.SumShortValues(hdrSum, payloadSum)
  217. );
  218. if (chksum == 0) {
  219. chksum = (ushort) 0xFFFF;
  220. }
  221. buffer[tcpOffset + 16] = (byte) (chksum >> 8);
  222. buffer[tcpOffset + 17] = (byte) (chksum & 0xff);
  223. }
  224. public static void SetTcpChecksum(Bytes header,
  225. int ipOffset,
  226. ushort tcpLength)
  227. {
  228. // sum IP pseudo
  229. ushort ipPayloadSize = 0;
  230. ushort headerSum = IpHeader.SumPseudoHeader(header, ipOffset,
  231. ref ipPayloadSize);
  232. DebugStub.Assert(tcpLength == ipPayloadSize);
  233. // now add it to the tcp header + data
  234. int ipHeaderSize = (header[ipOffset] & 0xf) * 4;
  235. int tcpOffset = ipOffset + ipHeaderSize;
  236. // DebugStub.WriteLine("ipHeaderSize {0} tcpOffset {1}\n", DebugStub.ArgList(ipHeaderSize, tcpOffset));
  237. ushort tcpsum = IpHeader.SumShortValues(header, ipOffset+IpHeader.Size, tcpLength);
  238. DebugStub.Assert(header[tcpOffset + 16] == 0);
  239. DebugStub.Assert(header[tcpOffset + 17] == 0);
  240. ushort hdrSum = IpHeader.SumShortValues(headerSum, tcpsum);
  241. ushort chksum = (ushort) ~hdrSum;
  242. if (chksum == 0) {
  243. chksum = (ushort) 0xFFFF;
  244. }
  245. header[tcpOffset + 16] = (byte) (chksum >> 8);
  246. header[tcpOffset + 17] = (byte) (chksum & 0xff);
  247. }
  248. }
  249. public class TCP
  250. {
  251. private const uint DefaultRxWinSize = 65535;
  252. private const uint DefaultTxWinSize = 65535;
  253. private static ushort MaxPortNumber = 65535;
  254. //global data structures
  255. private static ushort srcMSS = 1460; //assuming ethernet
  256. private static uint nextISS = 1; //XXX wrong.
  257. private static MonitorLock thisLock = new MonitorLock();
  258. private static MonitorLock tcpPortsMtx;
  259. private static ushort nextPortNumber; //assigning ports on demand
  260. public ushort localPort;
  261. public ushort remotePort;
  262. public IPv4 localIPAddress;
  263. public IPv4 remoteIPAddress;
  264. public LinkedListNode chainedHashLLNode; //pointer into location in chained hash table
  265. public int acceptQueueMaxSize;
  266. public int acceptQueueLength;
  267. public int acceptQueueHead;
  268. public int acceptQueueTail;
  269. public TCP[] acceptQueue;
  270. public TCP listenSocket;
  271. private static TimerWheel slowWheel;
  272. private static TimerWheel fastWheel;
  273. private static ChainedHash activeHash;
  274. private static ChainedHash passiveHash;
  275. #if TCP_THREAD_POOL
  276. private static NetStackThreadPool threadPool;
  277. #endif
  278. public bool activeOpen;
  279. //per connection data structures
  280. private ushort defaultMaxSegSize = 536; //default unless notified in SYN options
  281. private TcpState currentState; //where we are in the state machine
  282. private short currentRxt; //current retransmission timeout
  283. private short dupAckCount; //number consecutive dup acks received
  284. private ushort maxSegSize; //max segement size to send
  285. //what about push?
  286. private bool ackNow; //send ack right away
  287. private bool delayAck; //use del ack timer
  288. private bool noDelay; //disable nagle
  289. private bool needFin;
  290. private bool needAck;
  291. //TCP options
  292. private bool rcvdScale; //did we receive the windows scaling option?
  293. private bool rcvdTimestamp; //did we receive request for echo timestamps?
  294. private bool isBound;
  295. private bool isConnected;
  296. //pointers into timer wheels
  297. private LinkedListNode delayAckTimeoutNode;
  298. private LinkedListNode retransmitTimeoutNode;
  299. private LinkedListNode connectionTimeoutNode;
  300. private LinkedListNode fin2MslTimeoutNode; //used for both fin2 and TimeWait
  301. //delegates for timer wheel
  302. public TimerWheel.TimerDelegate connectionTimeoutDelegate;
  303. public TimerWheel.TimerDelegate delayAckTimeoutDelegate;
  304. public TimerWheel.TimerDelegate retransmitTimeoutDelegate;
  305. public TimerWheel.TimerDelegate fin2MslTimeoutDelegate;
  306. public AutoResetEvent tcpWriterWait;
  307. public AutoResetEvent tcpReaderWait;
  308. public AutoResetEvent tcpConnWait;
  309. public bool finacked;
  310. public bool readerWaiting;
  311. public bool writerWaiting;
  312. public bool disposed;
  313. //RFC 793
  314. //Send Sequence Variables
  315. private uint sndUna; // send unacknowledged
  316. private uint sndNxt; // send next
  317. private uint sndMax;
  318. private uint sndWnd; // send window
  319. private uint sndUp ; // send urgent pointer
  320. private uint sndWn1; // segment sequence number used for last window update
  321. private uint sndWn2; // segment acknowledgment number used for last window update
  322. private uint iss; // initial send sequence number
  323. //Receive Sequence Variables
  324. private uint rcvNxt; // receive next
  325. private uint rcvWnd; // receive window
  326. private uint rcvUp; // receive urgent pointer
  327. private uint irs; // initial receive sequence number
  328. private uint rcvAdv; //windows advertised by other end
  329. private ushort sndMss; //mss received in tcp options
  330. private long timeWaiting;
  331. #if false
  332. //XXX implement later when congestion matters
  333. //congestion control comes later
  334. private uint cwnd; //congestion control window
  335. private uint sndSSThresh; //size threshold for slow start
  336. //rtt estimators
  337. //these are set in 'ticks' of the slowTimer
  338. private short rttEstimate; //rtt estiamte
  339. private short rttSequenceNumber; //seq currently timed
  340. private short smoothedRtt; //smoothed rtt ticks x 8
  341. private short rttVariance; //ticks x 4
  342. private ushort rttMinimum; //minimum allowed rtt
  343. private uint maxSndWindow //largest window offered by peer
  344. #endif
  345. private static uint rxBufferSize; //size of buffers for apps
  346. private static uint txBufferSize;
  347. private int timeoutValue;
  348. private int maxTimeoutValue;
  349. private TContainerTcpVectorQueueByte txContainer; //send buffer
  350. private TContainerTcpVectorQueueByte rxAssemblyContainer; //reassemble out of order segments
  351. private TContainerTcpVectorQueueByte rxContainer; //receieve buffer
  352. [Conditional("DEBUG_TCP")]
  353. internal static void DebugPrint(string format,
  354. params object [] arguments)
  355. {
  356. DebugStub.Print("TCP: {0}",
  357. DebugStub.ArgList(
  358. string.Format(format, arguments))
  359. );
  360. }
  361. [Conditional("DEBUG_TCP")]
  362. internal static void DebugPrint(string format)
  363. {
  364. DebugStub.Print("TCP: {0}",
  365. DebugStub.ArgList(format));
  366. }
  367. public TcpState CurrentState
  368. {
  369. get { return currentState; }
  370. }
  371. public bool AckNow
  372. {
  373. get { return this.ackNow; }
  374. }
  375. public static void Initialize()
  376. {
  377. //initialize timer wheels
  378. fastWheel = new TimerWheel(10, 200); //200 ms per 'tick'
  379. slowWheel = new TimerWheel(500); //500ms per 'tick'
  380. //initialize chained hash tables for demultiplexing
  381. activeHash = new ChainedHash(true);
  382. passiveHash = new ChainedHash(false);
  383. rxBufferSize = DefaultRxWinSize;
  384. txBufferSize = DefaultTxWinSize;
  385. tcpPortsMtx = new MonitorLock();
  386. nextPortNumber = 1024;
  387. #if TCP_THREAD_POOL
  388. threadPool = new NetStackThreadPool(16, 16*128);
  389. #endif
  390. }
  391. #if TCP_THREAD_POOL
  392. public static NetStackThreadPool ThreadPool {
  393. get { return threadPool; }
  394. }
  395. #endif
  396. internal class ConnectionTimeout: TimerWheel.TimerDelegate
  397. {
  398. public override void Run(TCP tcpSession)
  399. {
  400. DebugStub.Print("Got connection timeout!\n");
  401. if (slowWheel.DeleteTimerEvent(ref tcpSession.retransmitTimeoutNode) == true) {
  402. DisposeTcpSession(tcpSession);
  403. }
  404. }
  405. }
  406. public class DelayAckTimeout: TimerWheel.TimerDelegate
  407. {
  408. TCP tcp;
  409. internal DelayAckTimeout(TCP tcp) {this.tcp = tcp;}
  410. public override void Run(TCP tcpSession)
  411. {
  412. DebugStub.Print("Got ack delay timeout...sending latest ack\n");
  413. if (fastWheel.DeleteTimerEvent(ref tcpSession.delayAckTimeoutNode) == true) {
  414. tcp.delayAckTimeoutNode = null;
  415. tcp.ackNow = true;
  416. tcp.SendPacket(TcpFlags.ACK, false);
  417. }
  418. }
  419. }
  420. public class RetransmitTimeout: TimerWheel.TimerDelegate
  421. {
  422. TCP tcp;
  423. internal RetransmitTimeout(TCP tcp) {this.tcp = tcp;}
  424. public override void Run(TCP tcpSession)
  425. {
  426. DebugStub.Print("Got retransmit timeout\n");
  427. if (slowWheel.DeleteTimerEvent(ref tcpSession.retransmitTimeoutNode) == true) {
  428. //set timer to new backoff value
  429. if (tcp.timeoutValue > tcp.maxTimeoutValue) {
  430. DebugStub.Print("attempted final rentransmit....FAILED!\n");
  431. DebugStub.Assert(false);
  432. DebugStub.Break();
  433. }
  434. tcp.retransmitTimeoutNode = null;
  435. tcp.timeoutValue = tcp.timeoutValue * 2;
  436. if (tcp.currentState == TcpState.SYN_SENT) {
  437. tcp.SendPacket(TcpFlags.SYN, true);
  438. }
  439. else if (tcp.currentState == TcpState.SYN_RECEIVED) {
  440. tcp.SendPacket(TcpFlags.SYN | TcpFlags.ACK, true);
  441. }
  442. else {
  443. tcp.ackNow = true;
  444. tcp.SendPacket(TcpFlags.ACK, true);
  445. }
  446. }
  447. }
  448. }
  449. internal class Fin2MslTimeout: TimerWheel.TimerDelegate
  450. {
  451. public override void Run(TCP tcpSession)
  452. {
  453. DebugPrint("Got Fin2Msl timeout!\n");
  454. if (slowWheel.DeleteTimerEvent(ref tcpSession.fin2MslTimeoutNode) == true) {
  455. tcpSession.fin2MslTimeoutNode = null;
  456. DisposeTcpSession(tcpSession);
  457. }
  458. }
  459. }
  460. public IPv4 RemoteAddress { get { return remoteIPAddress; } }
  461. public ushort RemotePort { get { return remotePort; } }
  462. public IPv4 LocalAddress { get { return localIPAddress; } }
  463. public ushort LocalPort { get { return localPort; } }
  464. public TCP()
  465. {
  466. //begin with wildcards
  467. localIPAddress = IPv4.Any;
  468. localPort = 0;
  469. remotePort = 0;
  470. remoteIPAddress = IPv4.Any;
  471. iss = nextISS;
  472. nextISS += 64000;
  473. maxSegSize = defaultMaxSegSize;
  474. maxTimeoutValue = 80000;
  475. activeOpen = false;
  476. readerWaiting = false;
  477. writerWaiting = false;
  478. disposed = false;
  479. timeWaiting = 0;
  480. //default rtt estimates
  481. #if false
  482. rttEstimate = 0;
  483. smoothedRtt = 0;
  484. rttVariance = 24;
  485. rttMinimum = 1; //minimum of 500 ms retransmission timeout... ugh
  486. currentRxt = 12; //6 second initial retransmission timeout
  487. #endif
  488. //flags
  489. noDelay = true; //ignore nagle by default for now
  490. isBound = false;
  491. isConnected = false;
  492. finacked = false;
  493. ackNow = false;
  494. needFin = false;
  495. needAck = false;
  496. //timers
  497. //Note -- we're currently not using the persist timer
  498. retransmitTimeoutNode = null;
  499. connectionTimeoutNode = null;
  500. fin2MslTimeoutNode = null;
  501. delayAckTimeoutNode = null;
  502. connectionTimeoutDelegate = new ConnectionTimeout();
  503. delayAckTimeoutDelegate = new DelayAckTimeout(this);
  504. fin2MslTimeoutDelegate = new Fin2MslTimeout();
  505. retransmitTimeoutDelegate = new RetransmitTimeout(this);
  506. listenSocket = null;
  507. //window sizes
  508. rcvWnd = DefaultRxWinSize;
  509. rcvUp = 0;
  510. //initialize the per connection buffers
  511. txContainer = new TContainerTcpVectorQueueByte(
  512. new TcpVectorQueueByte()
  513. );
  514. rxContainer = new TContainerTcpVectorQueueByte(
  515. new TcpVectorQueueByte()
  516. );
  517. rxAssemblyContainer = new TContainerTcpVectorQueueByte(
  518. new TcpVectorQueueByte()
  519. );
  520. currentState = TcpState.CLOSED;
  521. tcpWriterWait = new AutoResetEvent(false);
  522. tcpReaderWait = new AutoResetEvent(false);
  523. tcpConnWait = new AutoResetEvent(false);
  524. }
  525. //XXX Right now we get a port and then grok the hashtable
  526. //to see if it exists, and then ask for another port....
  527. private bool AssignNextAvailablePort()
  528. {
  529. using (tcpPortsMtx.Lock()) {
  530. this.localPort = nextPortNumber;
  531. //Sing# complains if we just allow it to roll over?
  532. if (nextPortNumber + 1 > MaxPortNumber) {
  533. nextPortNumber = 1;
  534. }
  535. else {
  536. nextPortNumber++;
  537. }
  538. }
  539. return true;
  540. }
  541. //add read/write/poll read etc etc etc.
  542. //write send function. make changes to Nic so that we
  543. //can get a packetfifo a fill it with everything in the send buffer
  544. //finish writing timer delegates.
  545. public bool InternalConnect(IPv4 destIP, ushort destPort)
  546. {
  547. remoteIPAddress = destIP;
  548. remotePort = destPort;
  549. return true;
  550. }
  551. //interface calls
  552. //active open
  553. public bool Connect(IPv4 destIP, ushort destPort, out TcpError error)
  554. {
  555. error = TcpError.Unknown;
  556. if (isConnected == true) {
  557. error = TcpError.AlreadyConnected;
  558. return false;
  559. }
  560. InternalConnect(destIP, destPort);
  561. if (isBound == false) {
  562. if(AssignNextAvailablePort() == false) {
  563. DebugPrint("Ran out of ports!\n");
  564. error = TcpError.ResourcesExhausted;
  565. return false;
  566. }
  567. HostConfiguration hostConfiguration = IP.GetHostConfiguration();
  568. RouteEntry e = hostConfiguration.RoutingTable.Lookup(destIP);
  569. if (e != null) {
  570. localIPAddress = e.InterfaceAddress;
  571. DebugPrint("local address now {0}\n", localIPAddress);
  572. }
  573. else {
  574. DebugPrint("No route for {0}\n", destIP);
  575. DebugStub.Assert(false);
  576. //need better errors?
  577. error = TcpError.ResourcesExhausted;
  578. return false;
  579. }
  580. }
  581. DebugPrint("Starting connection src ip {0} port {1} dest ip {2} port {3}\n",
  582. localIPAddress, localPort, destIP, destPort);
  583. chainedHashLLNode = activeHash.InsertNewSession(this);
  584. this.sndUna = iss;
  585. this.sndNxt = iss;
  586. this.sndMax = iss;;
  587. slowWheel.AddTimerEvent(75000, this,
  588. this.connectionTimeoutDelegate,
  589. ref this.connectionTimeoutNode);
  590. this.timeoutValue = 500;
  591. slowWheel.AddTimerEvent(this.timeoutValue, this,
  592. this.retransmitTimeoutDelegate,
  593. ref this.retransmitTimeoutNode);
  594. currentState = TcpState.SYN_SENT;
  595. SendPacket(TcpFlags.SYN, false);
  596. DebugPrint("Tcp.Connect...waiting for response...\n");
  597. tcpConnWait.WaitOne();
  598. DebugPrint("Connection complete!\n");
  599. activeOpen = true;
  600. return true;
  601. }
  602. public int GetNumWaitingListenSessions()
  603. {
  604. DebugPrint("GetNumWaitingListenSessions!\n");
  605. DebugStub.Break();
  606. return 0;
  607. }
  608. public bool IsDataAvailable()
  609. {
  610. bool rc;
  611. TcpVectorQueueByte rxBuffer = rxContainer.Acquire();
  612. rc = (rxBuffer.Size() > 0);
  613. rxContainer.Release(rxBuffer);
  614. return rc;
  615. }
  616. public bool Listen(int backlog)
  617. {
  618. DebugPrint("TCP: Listen\n");
  619. if (isBound == false) {
  620. DebugStub.Print("socket isn't bound...rejecting\n");
  621. return false;
  622. }
  623. if (backlog < 1 || backlog > 50) {
  624. DebugPrint("Backlog out of bounds...silently changing to 50\n");
  625. backlog = 50;
  626. }
  627. TCP tcpSession = passiveHash.GetTCPSession(this.localIPAddress, this.localPort,
  628. IPv4.Any, 0);
  629. if (tcpSession != null) {
  630. if (tcpSession.currentState != TcpState.LISTEN) {
  631. DebugStub.Print("Calling listen over existing contract.....overwriting\n");
  632. DisposeTcpSession(tcpSession);
  633. return false;
  634. } else {
  635. DebugStub.Print("Failed! Already listening....\n");
  636. return false;
  637. }
  638. }
  639. this.acceptQueue = new TCP[backlog];
  640. this.acceptQueueHead = 0;
  641. this.acceptQueueTail = 0;
  642. for (int i = 0; i < backlog; i++) {
  643. this.acceptQueue[i] = null;
  644. }
  645. this.listenSocket = null;
  646. this.acceptQueueLength = 0;
  647. this.acceptQueueMaxSize = backlog;
  648. this.chainedHashLLNode = passiveHash.InsertNewSession(this);
  649. this.activeOpen = false;
  650. this.currentState = TcpState.LISTEN;
  651. return true;
  652. }
  653. public bool Bind(IPv4 sourceAddr, ushort sourcePort)
  654. {
  655. if (sourceAddr != IPv4.Any && !IsLocalAddress(sourceAddr)) {
  656. // Invalid address
  657. //set error
  658. return false;
  659. }
  660. localIPAddress = sourceAddr;
  661. DebugPrint("TCP port bound to {0}\n", localIPAddress);
  662. //check to see if this port/ip is in use.
  663. if ((this.localPort != sourcePort) && (sourcePort != 0)) {
  664. TCP tcpSession = activeHash.GetTCPSession(sourceAddr, sourcePort,
  665. IPv4.Any, 0);
  666. if (tcpSession == null) {
  667. tcpSession = passiveHash.GetTCPSession(sourceAddr, sourcePort,
  668. IPv4.Any, 0);
  669. if (tcpSession == null) {
  670. this.localPort = sourcePort;
  671. isBound = true;
  672. return true;
  673. }
  674. }
  675. isBound = false;
  676. return false;
  677. }
  678. isBound = true;
  679. return true;
  680. }
  681. public TCP Accept()
  682. {
  683. while (this.acceptQueue[this.acceptQueueHead] == null &&
  684. this.currentState == TcpState.LISTEN) {
  685. bool rc;
  686. rc = this.tcpConnWait.WaitOne(TimeSpan.FromSeconds(5));
  687. if (rc == false) {
  688. return null;
  689. }
  690. }
  691. if (this.currentState != TcpState.LISTEN) {
  692. DebugStub.Print("ack! no longer listening!!\n");
  693. return null;
  694. }
  695. TCP newConnection = this.acceptQueue[this.acceptQueueHead];
  696. DebugStub.Assert(newConnection != null);
  697. if (newConnection == null) {
  698. DebugStub.Break();
  699. }
  700. this.acceptQueueLength--;
  701. this.acceptQueue[this.acceptQueueHead] = null;
  702. this.acceptQueueHead =
  703. (this.acceptQueueHead + 1) % this.acceptQueueMaxSize;
  704. DebugPrint("AcceptQueueHead incremented now {0} " +
  705. " acceptMaxQueueSize {1}\n",
  706. this.acceptQueueHead, this.acceptQueueMaxSize);
  707. return newConnection;
  708. }
  709. public Bytes Read()
  710. {
  711. DebugPrint("TCP: Read\n");
  712. Bytes buff;
  713. while (((buff = PopData()) == null) &&
  714. (currentState == TcpState.ESTABLISHED)) {
  715. tcpReaderWait.WaitOne();
  716. }
  717. return buff;
  718. }
  719. public Bytes[] ReadV()
  720. {
  721. DebugPrint("TCP:ReadV");
  722. Bytes[] buff = null;
  723. while (((buff = PopAllData()) == null) &&
  724. (this.currentState == TcpState.ESTABLISHED)) {
  725. this.tcpReaderWait.WaitOne();
  726. }
  727. return buff;
  728. }
  729. public Bytes PollRead(TimeSpan timeout)
  730. {
  731. Bytes buff;
  732. bool rc = true;
  733. if ((buff = PopData()) == null) {
  734. rc = tcpReaderWait.WaitOne(timeout);
  735. if (rc == true) {
  736. buff = PopData();
  737. }
  738. }
  739. return buff;
  740. }
  741. public Bytes[] PollReadV(TimeSpan timeout)
  742. {
  743. Bytes[] buff;
  744. bool rc = true;
  745. if ((buff = PopAllData()) == null) {
  746. rc = tcpReaderWait.WaitOne(timeout);
  747. if (rc == true) {
  748. buff = PopAllData();
  749. }
  750. }
  751. return buff;
  752. }
  753. public void Close()
  754. {
  755. if (currentState == TcpState.ESTABLISHED) {
  756. needFin = true;
  757. SendPacket(TcpFlags.ACK, false);
  758. }
  759. else if (currentState == TcpState.CLOSE_WAIT) {
  760. //XXX might need a timer here
  761. needFin = true;
  762. SendPacket(TcpFlags.ACK, false);
  763. }
  764. else if (currentState == TcpState.CLOSED) {
  765. DisposeTcpSession(this);
  766. }
  767. else {
  768. DebugStub.WriteLine("Got close in state {0}\n", DebugStub.ArgList(currentState));
  769. }
  770. }
  771. public bool IsLocalAddress(IPv4 ipAddress)
  772. {
  773. return IP.IsLocalAddress(ipAddress);
  774. }
  775. private static Bytes GetHeader(int size)
  776. {
  777. //DebugPrint("Allocating header size {0}\n", size);
  778. byte[] header = new byte[size];
  779. return new Bytes(header);
  780. }
  781. //XXX need offset
  782. public static void BuildHeader(Bytes header, IPv4 destAddress,
  783. IPv4 srcAddress, ushort destPort, ushort srcPort,
  784. byte flags, uint seqNumber, uint ackNumber,
  785. uint windowSize, int optlen,
  786. short payloadLength, uint urgPtr, int ipHeaderOffset)
  787. {
  788. // DebugPrint("BuildHeader optlen {0}\n", optlen);
  789. int totalLength = IpHeader.Size + TcpHeader.MinSize + payloadLength + optlen;
  790. //write ip header
  791. int offset = ipHeaderOffset;
  792. int o = ipHeaderOffset;
  793. header[o++] = 0x45; //default version 4, header_len 5
  794. header[o++] = 0; //tos
  795. header[o++] = (byte) (((ushort)totalLength) >> 8); //total length of the ip header
  796. header[o++] = (byte) (((ushort)totalLength) & 0xff);
  797. header[o++] = (byte) (((ushort)0) >> 8); //fragment id
  798. header[o++] = (byte) (((ushort)0) & 0xff); //fragment id
  799. header[o++] = (byte) (((ushort)0) >> 8); //fragment offset
  800. header[o++] = (byte) (((ushort)0) & 0xff); //fragment offset
  801. header[o++] = 128; //default ttl
  802. header[o++] = 6; // protocol ID --> tcp
  803. header[o++] = 0; //ipchecksum (fill it in later)
  804. header[o++] = 0; //ipchecksum
  805. srcAddress.CopyOut(header.Array, header.Start + o);
  806. o += IPv4.Length;
  807. // set the ip addresses
  808. destAddress.CopyOut(header.Array, header.Start + o);
  809. o += IPv4.Length;
  810. // calculate ip checksum
  811. ushort chk = IpHeader.CalculateChecksum(header, offset, IpHeader.Size);
  812. header[offset + 10] = (byte) (((ushort)chk) >> 8);
  813. header[offset + 11] = (byte) (((ushort)chk) & 0xff);
  814. //write tcp segment header
  815. header[o++] = (byte)(((ushort)srcPort) >> 8);
  816. header[o++] = (byte) (((ushort)srcPort) & 0xff);
  817. header[o++] = (byte)(((ushort)destPort) >> 8);
  818. header[o++] = (byte) (((ushort)destPort) & 0xff);
  819. header[o++] = (byte)(((uint)seqNumber) >> 24);
  820. header[o++] = (byte)(((uint)seqNumber) >> 16);
  821. header[o++] = (byte)(((uint)seqNumber) >> 8);
  822. header[o++] = (byte) (((uint)seqNumber) & 0xff);
  823. header[o++] = (byte)(((uint)ackNumber) >> 24);
  824. header[o++] = (byte)(((uint)ackNumber) >> 16);
  825. header[o++] = (byte)(((uint)ackNumber) >> 8);
  826. header[o++] = (byte) (((uint)ackNumber) & 0xff);
  827. byte off = (byte) ((TcpHeader.MinSize + optlen) >> 2);
  828. // DebugPrint("BuildHeader: offset is {0}\n", off);
  829. header[o++] = (byte) (off << (byte) 4);
  830. header[o++] = flags;
  831. header[o++] = (byte)(((ushort)windowSize) >> 8);
  832. header[o++] = (byte) (((ushort)windowSize) & 0xff);
  833. // checksum
  834. header[o++] = 0;
  835. header[o++] = 0;
  836. header[o++] = (byte)(((ushort)urgPtr) >> 8);
  837. header[o++] = (byte) (((ushort)urgPtr) & 0xff);
  838. // DebugPrint("BuildHeader: Complete\n");
  839. }
  840. public static void DeleteTimers(TCP tcpSession)
  841. {
  842. slowWheel.DeleteTimerEvent(ref tcpSession.retransmitTimeoutNode);
  843. slowWheel.DeleteTimerEvent(ref tcpSession.connectionTimeoutNode);
  844. slowWheel.DeleteTimerEvent(ref tcpSession.fin2MslTimeoutNode);
  845. fastWheel.DeleteTimerEvent(ref tcpSession.delayAckTimeoutNode);
  846. }
  847. public static void DisposeTcpSession(TCP tcpSession)
  848. {
  849. if (tcpSession.disposed == true) {
  850. return;
  851. }
  852. tcpSession.disposed = true;
  853. //check to see whether this was a passive or active open
  854. if (tcpSession.activeOpen) {
  855. activeHash.RemoveTcpSession(tcpSession, tcpSession.chainedHashLLNode);
  856. }
  857. else {
  858. passiveHash.RemoveTcpSession(tcpSession, tcpSession.chainedHashLLNode);
  859. }
  860. tcpSession.currentState = TcpState.CLOSED;
  861. DeleteTimers(tcpSession);
  862. TcpVectorQueueByte txBuffer = tcpSession.txContainer.Acquire();
  863. uint bufferSize = txBuffer.Size();
  864. if (bufferSize > 0) {
  865. txBuffer.ReleaseDataFromTxBuffer(bufferSize);
  866. txBuffer.SetTxBuffTotalOffset(tcpSession.sndNxt - tcpSession.sndUna);
  867. }
  868. tcpSession.txContainer.Release(txBuffer);
  869. }
  870. public long TimeWaiting()
  871. {
  872. return this.timeWaiting;
  873. }
  874. //app level send
  875. public int Send(Bytes data)
  876. {
  877. TcpVectorQueueByte txBuffer = txContainer.Acquire();
  878. int bytesLeft = data.Length;
  879. int rc = bytesLeft;
  880. DebugPrint("Sending {0} bytes\n", data.Length);
  881. while (bytesLeft != 0) {
  882. Bytes dataToSave = null;
  883. if (bytesLeft > (txBufferSize - txBuffer.Size())) {
  884. uint offset = txBufferSize - txBuffer.Size();
  885. if (offset > 0) {
  886. dataToSave = Bitter.SplitOff(ref data, (int) offset);
  887. txBuffer.AddTail(data, 0, offset);
  888. bytesLeft -= (int) offset;
  889. }
  890. else {
  891. dataToSave = data;
  892. }
  893. }
  894. else {
  895. txBuffer.AddTail(data, 0, (uint) bytesLeft);
  896. bytesLeft = 0;
  897. }
  898. //execute internal send
  899. if (bytesLeft > 0) {
  900. txContainer.Release(txBuffer);
  901. SendPacket(TcpFlags.ACK, false);
  902. tcpWriterWait.WaitOne();
  903. if (currentState != TcpState.ESTABLISHED) {
  904. DebugPrint("Connection closed!\n");
  905. //delete dataToSave;
  906. return -1;
  907. }
  908. txBuffer = txContainer.Acquire();
  909. VTable.Assert(dataToSave != null);
  910. data = dataToSave;
  911. dataToSave = null;
  912. }
  913. }
  914. txContainer.Release(txBuffer);
  915. SendPacket(TcpFlags.ACK, false);
  916. return rc;
  917. }
  918. public void ProcessOptions(Bytes packet, int optionsSize)
  919. {
  920. int offset = EthernetHeader.Size + IpHeader.Size + TcpHeader.MinSize;
  921. int limit = offset + optionsSize;
  922. DebugPrint("Options size {0}\n", optionsSize);
  923. for(int i = offset; i < limit; i++) {
  924. byte p = packet[i];
  925. if (p == (byte) TcpOptions.EOL || p == (byte) TcpOptions.NOP) {
  926. continue;
  927. }
  928. if (p == (byte) TcpOptions.MSS) {
  929. i++;
  930. byte s = packet[i++];
  931. DebugStub.Assert(s == 4);
  932. VTable.Assert(s == 4);
  933. byte[] toConvert;
  934. toConvert = new byte[2];
  935. toConvert[0] = packet[i++];
  936. toConvert[1] = packet[i];
  937. ushort mss;
  938. mss = NetworkBitConverter.ToUInt16(toConvert, 0);
  939. DebugPrint("Reveived MSS option of {0}\n", mss);
  940. sndMss = mss;
  941. }
  942. else {
  943. byte s = packet[i + 1];
  944. DebugPrint("Unhandled options: {0} size {1}...\n", (int)p, (int)s);
  945. i += ((int)s-1);
  946. }
  947. }
  948. }
  949. public static void SendError(IpHeader ipHeader, TcpHeader tcpHeader, TcpFlags flags)
  950. {
  951. Bytes header;
  952. Bytes ethernetHeader;
  953. if (flags == TcpFlags.RST) {
  954. DebugPrint("Sending RST\n");
  955. header = new Bytes(new byte[IpHeader.Size + TcpHeader.MinSize]);
  956. ethernetHeader = new Bytes(new byte[EthernetHeader.Size]);
  957. BuildHeader (header, ipHeader.destAddress, ipHeader.srcAddress,
  958. tcpHeader.destPort, tcpHeader.srcPort, (byte) TcpFlags.RST,
  959. tcpHeader.ackNumber, 0, 0, 0, 0, 0, 0);
  960. TcpHeader.SetTcpChecksum(header, 0, TcpHeader.MinSize);
  961. IP.SendOutgoingPacket(ethernetHeader, header, ipHeader.srcAddress);
  962. }
  963. else if (((TcpFlags.RST & flags) != 0) &&
  964. ((TcpFlags.ACK & flags) != 0)) {
  965. DebugPrint("Sending RST | ACK\n");
  966. header = new Bytes(new byte[IpHeader.Size + TcpHeader.MinSize]);
  967. ethernetHeader = new Bytes(new byte[EthernetHeader.Size]);
  968. uint headerLength = (uint) (EthernetHeader.Size + IpHeader.Size + tcpHeader.dataOffset);
  969. uint segmentLength = (uint) (ipHeader.totalLength - IpHeader.Size) - headerLength;
  970. BuildHeader (header, ipHeader.destAddress, ipHeader.srcAddress, tcpHeader.destPort,
  971. tcpHeader.srcPort, (byte) (TcpFlags.RST | TcpFlags.ACK),
  972. 0, tcpHeader.seqNumber + segmentLength, 0, 0, 0, 0, 0);
  973. }
  974. else {
  975. DebugStub.Assert(false);
  976. }
  977. }
  978. private Bytes GetNextBuffer(out uint seqNmb)
  979. {
  980. TcpVectorQueueByte txBuffer = txContainer.Acquire();
  981. uint txBufferOffset = (this.sndNxt - this.sndUna);
  982. uint numBytes = (txBuffer.Size() - txBufferOffset);
  983. DebugPrint("size {0} offset {1} bytes {2}\n",
  984. txBuffer.Size(), txBufferOffset, numBytes);
  985. seqNmb = this.sndNxt;
  986. if (txBuffer.Size() == 0 || numBytes == 0 ||
  987. (this.sndWnd < 2*this.sndMss)) {
  988. txContainer.Release(txBuffer);
  989. return null;
  990. }
  991. int bufLen;
  992. int bufStart;
  993. int bufByteToSend;
  994. Bytes targetBuffer = txBuffer.GetCurrentBuffer(out bufStart, out bufLen, out bufByteToSend,
  995. (int) txBufferOffset);
  996. //"bufStart" represents the oficial start of the buffer (unacknowledged data to be sent
  997. //"bufByteToSend" represents that next byte to be sent
  998. if (bufByteToSend != bufStart) {
  999. if (bufByteToSend < bufStart) {
  1000. DebugStub.Break();
  1001. }
  1002. bufLen = bufLen - (bufByteToSend - bufStart);
  1003. }
  1004. //we ended at the end of a previous buffer
  1005. //on a new buffer, bufByteToSend is always equal to bufStart
  1006. if (bufLen == 0) {
  1007. targetBuffer = txBuffer.GetNextBuffer(out bufStart, out bufLen);
  1008. DebugPrint("GetNextBuffer result start {0} length {1}\n",
  1009. bufStart, bufLen);
  1010. bufByteToSend = bufStart;
  1011. }
  1012. DebugPrint("GetCurrentBuffer result start {0} length {1} offset {2}\n",
  1013. bufStart, bufLen, bufByteToSend);
  1014. DebugStub.Assert(targetBuffer != null);
  1015. VTable.Assert(targetBuffer != null);
  1016. int pcktLen = Math.Min((int) numBytes, this.sndMss);
  1017. if(pcktLen > 1460 || pcktLen < 0) {
  1018. DebugStub.WriteLine("sndNxt {0} sndUna {1} sndMax {2} buffer size {3}",
  1019. DebugStub.ArgList(this.sndNxt, this.sndUna, this.sndMax, txBuffer.Size()));
  1020. DebugStub.WriteLine("bufStart {0} bufLen {1} bufByteToSend{2}",
  1021. DebugStub.ArgList(bufStart, bufLen, bufByteToSend));
  1022. DebugStub.Break();
  1023. }
  1024. Bytes cpBuf = new Bytes(new byte[pcktLen]);
  1025. while(pcktLen > 0) {
  1026. //copy the lesser of the space left in
  1027. //the send buffer and the space left in the packet
  1028. int cpLen = Math.Min(bufLen, pcktLen);
  1029. int cpOff = 0;
  1030. try {
  1031. Bitter.Copy(cpBuf, cpOff, cpLen, targetBuffer, (int) bufByteToSend);
  1032. }
  1033. catch (Exception e) {
  1034. DebugStub.Print("copy failed exception {0}\n", DebugStub.ArgList(e.ToString()));
  1035. DebugStub.Print("cpOff {0} cplen {1} cp.Len {2} targetoffset {3} targetlen {4}length {5}\n",
  1036. DebugStub.ArgList(cpOff, cpLen, cpBuf.Length, bufByteToSend, (targetBuffer).Length,
  1037. pcktLen));
  1038. DebugStub.Break();
  1039. DebugStub.Assert(false);
  1040. VTable.Assert(false);
  1041. }
  1042. // DebugStub.WriteLine("pcktLen {0} cpOff {1} bufLen {2} cpLen {3}\n",
  1043. // DebugStub.ArgList(pcktLen, cpOff, bufLen, cpLen));
  1044. pcktLen -= cpLen;
  1045. cpOff += cpLen;
  1046. bufLen -= cpLen;
  1047. //we've run out of buffer to copy from and we still have space
  1048. //in this packet...
  1049. if (bufLen == 0) {
  1050. txBuffer.AdvanceBufferOffset((uint) cpLen);
  1051. if (pcktLen != 0) {
  1052. targetBuffer = txBuffer.GetNextBuffer(out bufStart, out bufLen);
  1053. DebugPrint("GetNextBuffer result start {0} length {1}\n",
  1054. bufStart, bufLen);
  1055. bufByteToSend = bufStart;
  1056. }
  1057. }
  1058. else {
  1059. txBuffer.AdvanceBufferOffset((uint) cpLen);
  1060. bufByteToSend += cpLen;
  1061. }
  1062. }
  1063. this.sndWnd -= (uint) cpBuf.Length;
  1064. this.sndNxt += (uint) cpBuf.Length;
  1065. if (TcpHeader.SeqGreater(this.sndNxt, this.sndMax)) {
  1066. this.sndMax = this.sndNxt;
  1067. }
  1068. txBuffer.SetTxBuffTotalOffset(this.sndNxt - this.sndUna);
  1069. txContainer.Release(txBuffer);
  1070. return cpBuf;
  1071. }
  1072. public void SendPacket(TcpFlags flags, bool resetSndNxt)
  1073. {
  1074. using (thisLock.Lock()) {
  1075. //three factors decide how many packets we generate
  1076. //1) the amount of data waiting to be sent in the txBuffer
  1077. //2) how many bytes are available in the remote window
  1078. //3) the number of packets available in the NIC
  1079. //we want the min of these three
  1080. bool dataToSend = false;
  1081. if (resetSndNxt == true) {
  1082. sndNxt = sndUna;
  1083. DebugStub.Print("SendPacket: sendWnd {0} rcvNxt {1} rcvWnd {2} " +
  1084. " flags 0x{4:x}, resetSndNxt {5}\n",
  1085. DebugStub.ArgList(this.sndWnd, this.rcvNxt, this.rcvWnd,
  1086. (uint) flags, sndNxt, resetSndNxt));
  1087. }
  1088. DebugPrint("SendPacket: sendWnd {0} rcvNxt {1} rcvWnd {2} " +
  1089. " flags 0x{3:x}, resetSndNxt {4}\n",
  1090. this.sndWnd, this.rcvNxt, this.rcvWnd, (uint) flags, sndNxt);
  1091. #if false
  1092. int bufferedBytes = (int) Math.Min (sndWnd, txBuffer.Size() - txBufferOffset);
  1093. if (bufferedBytes == 0 &&
  1094. sndWnd == 0 &&
  1095. TcpHeader.SeqLess(sndNxt, sndMax)) {
  1096. DebugStub.Print("zero window but resending....\n");
  1097. bufferedBytes = (int) (txBuffer.Size() - txBufferOffset);
  1098. }
  1099. #endif
  1100. uint seqNmb = 0;
  1101. Bytes pckt = GetNextBuffer(out seqNmb);
  1102. bool ackOnly = false;
  1103. while(pckt != null) {
  1104. dataToSend = true;
  1105. Bytes header =
  1106. new Bytes(new byte[EthernetHeader.Size + IpHeader.Size + TcpHeader.MinSize]);
  1107. if (pckt.Length < this.sndMss) {
  1108. flags |= TcpFlags.PSH;
  1109. }
  1110. BuildHeader (header, this.remoteIPAddress, this.localIPAddress, this.remotePort,
  1111. this.localPort, (byte) flags, seqNmb, this.rcvNxt, this.rcvWnd,
  1112. 0, (short) pckt.Length, 0, EthernetHeader.Size);
  1113. TcpHeader.SetTcpChecksum(header, pckt, EthernetHeader.Size, (ushort) TcpHeader.MinSize);
  1114. IP.SendOutgoingPacket(header, pckt, this.remoteIPAddress);
  1115. pckt = GetNextBuffer(out seqNmb);
  1116. }
  1117. if (this.sndMax == this.sndUna &&
  1118. needFin == true) {
  1119. DebugPrint("Sending FIN\n");
  1120. flags |= TcpFlags.FIN;
  1121. switch(this.currentState) {
  1122. case TcpState.ESTABLISHED:
  1123. currentState = TcpState.FIN_WAIT_1;
  1124. DebugPrint("Sending FIN -- moving to state FIN_WAIT_1");
  1125. break;
  1126. case TcpState.CLOSE_WAIT:
  1127. currentState = TcpState.LAST_ACK;
  1128. DebugPrint("Sending FIN -- moving to state LAST_ACK");
  1129. break;
  1130. default :
  1131. DebugStub.WriteLine("Sending FIN from state {0}??", DebugStub.ArgList(this.currentState));
  1132. DebugStub.Break();
  1133. break;
  1134. }
  1135. }
  1136. if (dataToSend == false &&
  1137. (ackNow == true || ((flags & (TcpFlags.SYN | TcpFlags.FIN)) != 0))) {
  1138. ushort optionsSize = 0;
  1139. Bytes ethernetHeader = new Bytes(new byte[EthernetHeader.Size]);
  1140. Bytes header;
  1141. if ((flags & TcpFlags.SYN) != 0) {
  1142. DebugPrint("Creating options for SYN packet srcmss {0}\n", srcMSS);
  1143. header = new Bytes(new byte[IpHeader.Size + TcpHeader.MinSize + 4]);
  1144. ushort mss;
  1145. ushort o = IpHeader.Size + TcpHeader.MinSize;
  1146. header[o++] = (byte) TcpOptions.MSS;
  1147. header[o++] = 4;
  1148. NetworkBitConverter.PutBytes(TCP.srcMSS, header.Array, header.Start + o);
  1149. optionsSize = 4;
  1150. }
  1151. else {
  1152. DebugPrint("sending packet either FIN or ACK flags {0}\n", flags);
  1153. header = new Bytes(new byte[IpHeader.Size + TcpHeader.MinSize]);
  1154. }
  1155. BuildHeader (header, this.remoteIPAddress, this.localIPAddress, this.remotePort,
  1156. this.localPort, (byte) flags, seqNmb, this.rcvNxt,
  1157. this.rcvWnd, optionsSize, 0, 0, 0);
  1158. TcpHeader.SetTcpChecksum(header, 0, (ushort) (TcpHeader.MinSize + optionsSize));
  1159. if ((flags & (TcpFlags.SYN | TcpFlags.FIN)) != 0) {
  1160. this.sndNxt++;
  1161. if (TcpHeader.SeqGreater(this.sndNxt, this.sndMax)) {
  1162. this.sndMax = this.sndNxt;
  1163. }
  1164. }
  1165. else {
  1166. ackOnly = true;
  1167. }
  1168. IP.SendOutgoingPacket(ethernetHeader, header, remoteIPAddress);
  1169. }
  1170. ackNow = false;
  1171. fastWheel.DeleteTimerEvent(ref this.delayAckTimeoutNode);
  1172. if (ackOnly == false) {
  1173. if(resetSndNxt == false) {
  1174. this.timeoutValue = 500;
  1175. }
  1176. slowWheel.AddTimerEvent(this.timeoutValue, this,
  1177. this.retransmitTimeoutDelegate,
  1178. ref this.retransmitTimeoutNode);
  1179. }
  1180. }
  1181. }
  1182. public Bytes[] PopAllData()
  1183. {
  1184. TcpVectorQueueByte rxBuffer = rxContainer.Acquire();
  1185. if (rxBuffer.Size() == 0) {
  1186. rxContainer.Release(rxBuffer);
  1187. return null;
  1188. }
  1189. int cnt = rxBuffer.Count();
  1190. VTable.Assert(cnt > 0);
  1191. Bytes[] ba = new Bytes[cnt];
  1192. for(int i = 0; i < cnt; i++) {
  1193. Bytes buf;
  1194. uint startOffset;
  1195. uint length;
  1196. buf = rxBuffer.ExtractHead(out startOffset, out length);
  1197. VTable.Assert(buf != null);
  1198. if (startOffset == 0 && length == buf.Length) {
  1199. ba[i] = buf;
  1200. }
  1201. else if (startOffset == 0 && length < buf.Length) {
  1202. VTable.Assert(buf != null);
  1203. //XXX without dummy, Sing# gets confused and is unsure which method
  1204. //is called.
  1205. Bytes dummy = buf;
  1206. Bytes leftOver = Bitter.SplitOff(ref dummy, (int) length);
  1207. //delete leftOver;
  1208. ba[i] = buf;
  1209. }
  1210. else {
  1211. Bytes buffer = new Bytes(new byte[length]);
  1212. Bitter.Copy(buffer, 0, (int) length, buf, (int) startOffset);
  1213. //delete buf;
  1214. ba[i] = buffer;
  1215. }
  1216. }
  1217. //The window is now fully open
  1218. rcvWnd = DefaultRxWinSize;
  1219. rxContainer.Release(rxBuffer);
  1220. return ba;
  1221. }
  1222. public Bytes PopData()
  1223. {
  1224. TcpVectorQueueByte rxBuffer = rxContainer.Acquire();
  1225. Bytes buf;
  1226. uint startOffset;
  1227. uint length;
  1228. buf = rxBuffer.ExtractHead(out startOffset, out length);
  1229. if (buf != null) {
  1230. this.rcvWnd += length;
  1231. }
  1232. rxContainer.Release(rxBuffer);
  1233. if (buf == null) {
  1234. return null;
  1235. }
  1236. else if (startOffset == 0 && length == buf.Length) {
  1237. return buf;
  1238. }
  1239. else if (startOffset == 0 && length < buf.Length) {
  1240. VTable.Assert(buf != null);
  1241. //XXX without dummy, Sing# gets confused and is unsure which method
  1242. //is called.
  1243. Bytes dummy = buf;
  1244. Bytes leftOver = Bitter.SplitOff(ref dummy, (int) length);
  1245. //delete leftOver;
  1246. return buf;
  1247. }
  1248. Bytes buffer = new Bytes(new byte[length]);
  1249. Bitter.Copy(buffer, 0, (int) length, buf, (int) startOffset);
  1250. //delete buf;
  1251. return buffer;
  1252. }
  1253. public void PushPacket(Bytes packet, uint packetLength, TcpHeader tcpHeader)
  1254. {
  1255. int offset = EthernetHeader.Size + IpHeader.Size + tcpHeader.dataOffset;
  1256. if (tcpHeader.dataOffset > TcpHeader.MinSize) {
  1257. DebugPrint("WARNING: processing data packet and ignoring options??\n");
  1258. }
  1259. if (offset == packetLength) {
  1260. DebugPrint("Received pure ack packet..\n");
  1261. //delete packet;
  1262. SendPacket(TcpFlags.ACK, false);
  1263. return;
  1264. }
  1265. Bytes packetData = Bitter.SplitOff(ref packet, offset);
  1266. //delete packet;
  1267. packetLength = packetLength - (uint) offset;
  1268. TcpVectorQueueByte rxAssembly = rxAssemblyContainer.Acquire();
  1269. TcpVectorQueueByte rxBuffer = rxContainer.Acquire();
  1270. if (tcpHeader.seqNumber == this.rcvNxt) {
  1271. if (packetLength > this.rcvWnd) {
  1272. packetLength = rcvWnd;
  1273. }
  1274. DebugPrint("adding packet to rxbuffer of size {0} byte length {1}\n", packetLength, packetData.Length);
  1275. rxBuffer.AddTail(packetData, tcpHeader.seqNumber, packetLength);
  1276. this.rcvWnd = this.rcvWnd - packetLength;
  1277. //avoid silly window syndrome
  1278. if (this.rcvWnd < this.maxSegSize * 2) {
  1279. this.rcvWnd = 0;
  1280. DebugPrint("rcvWnd closed to 0 to avoid silly window syndrom\n");
  1281. }
  1282. this.rcvNxt += packetLength;
  1283. if (rxAssembly.Empty == false) {
  1284. DebugStub.Print("going into assembly queue...\n");
  1285. int startOffset;
  1286. int length;
  1287. TcpVectorQueueByte.TcpVectorNode tcpVNode;
  1288. Bytes data;
  1289. while ((tcpVNode = rxAssembly.PopNextContiguousSegment(this.rcvNxt, this.rcvWnd)) != null) {
  1290. VTable.Assert(tcpVNode.length <= this.rcvWnd);
  1291. this.rcvWnd = this.rcvWnd - tcpVNode.length;
  1292. this.rcvNxt += tcpVNode.length;
  1293. rxBuffer.AddTail(tcpVNode);
  1294. }
  1295. }
  1296. //two segments in a row...ack immediately
  1297. if (fastWheel.DeleteTimerEvent(ref this.delayAckTimeoutNode) == true) {
  1298. DebugPrint("Received two segments in a row...ack'ing immediately\n");
  1299. ackNow = true;
  1300. }
  1301. else {
  1302. //delay the ack, hoping for an app message to piggy back
  1303. DebugPrint("Setting the ack delay timer\n");
  1304. fastWheel.AddTimerEvent(200, this,
  1305. this.delayAckTimeoutDelegate,
  1306. ref this.delayAckTimeoutNode);
  1307. }
  1308. //signal app thread if it is waiting for data
  1309. tcpReaderWait.Set();
  1310. }
  1311. else {
  1312. DebugPrint("received packet out of order, immediate ack in progress\n");
  1313. //XXX BUG BUG BUG we've effectively disabled fragmentation for now.
  1314. // rxAssembly.AddInSeqOrder(packetData, tcpHeader.seqNumber, packetLength);
  1315. ackNow = true;
  1316. }
  1317. rxContainer.Release(rxBuffer);
  1318. rxAssemblyContainer.Release(rxAssembly);
  1319. if (ackNow == true) {
  1320. SendPacket(TcpFlags.ACK, false);
  1321. }
  1322. }
  1323. public static void ProcessIncomingPacket(Bytes packet,
  1324. IpHeader ipHeader)
  1325. {
  1326. //14 byte ethernet header + 20 byte IP header
  1327. int offset = EthernetHeader.Size + IpHeader.Size;
  1328. bool hasOptions = false;
  1329. int packetLength = ipHeader.totalLength + EthernetHeader.Size;
  1330. TcpHeader tcpHeader = new TcpHeader(packet, offset);
  1331. if (!TcpHeader.IsChecksumValid(ipHeader, tcpHeader, packet)) {
  1332. DebugPrint("checksum failed, dropping packet\n");
  1333. //delete packet;
  1334. return;
  1335. }
  1336. int length = ipHeader.totalLength;
  1337. if (tcpHeader.dataOffset < TcpHeader.MinSize ||
  1338. tcpHeader.dataOffset + IpHeader.Size > length) {
  1339. DebugPrint("offset of tcp packet {0} invalid length:{1}\n", tcpHeader.dataOffset, length);
  1340. //delete packet;
  1341. return;
  1342. }
  1343. length = packetLength - (EthernetHeader.Size + IpHeader.Size + tcpHeader.dataOffset);
  1344. //process options
  1345. if ((tcpHeader.dataOffset - TcpHeader.MinSize) > 0) {
  1346. hasOptions = true;
  1347. }
  1348. //DebugPrint("ProcessIncomingPackets: tcp payload length {0}\n", length);
  1349. TCP tcpSession = activeHash.GetTCPSession(ipHeader.srcAddress, tcpHeader.srcPort,
  1350. ipHeader.destAddress, tcpHeader.destPort);
  1351. if (tcpSession == null) {
  1352. tcpSession = passiveHash.GetTCPSession(ipHeader.srcAddress, tcpHeader.srcPort,
  1353. ipHeader.destAddress, tcpHeader.destPort);
  1354. if (tcpSession == null) {
  1355. DebugStub.Print("Failed to find tcp session for conn {0}:{1} -> {2}:{3}\n", DebugStub.ArgList(
  1356. ipHeader.srcAddress, tcpHeader.srcPort,
  1357. ipHeader.destAddress, tcpHeader.destPort));
  1358. //delete packet;
  1359. return;
  1360. }
  1361. }
  1362. DebugPrint("Received TCP packet source ip {0} source port {1}\n" +
  1363. "dest ip {2} dest port {3} \nflags 0x{4,2:x} seq {5} ack {6}\n" +
  1364. "window size {7} length {8}\n", ipHeader.srcAddress, tcpHeader.srcPort,
  1365. ipHeader.destAddress, tcpHeader.destPort, tcpHeader.flags,
  1366. tcpHeader.seqNumber, tcpHeader.ackNumber, tcpHeader.windowSize,
  1367. length);
  1368. //header prediction fast path
  1369. if (tcpSession.currentState == TcpState.ESTABLISHED &&
  1370. (tcpHeader.flags & (byte) (TcpFlags.SYN | TcpFlags.RST | TcpFlags.URG | TcpFlags.ACK)) == (int) TcpFlags.ACK &&
  1371. (tcpHeader.seqNumber == tcpSession.rcvNxt) &&
  1372. // (tcpHeader.windowSize == tcpSession.sndWnd) &&
  1373. (tcpSession.sndNxt == tcpSession.sndMax)) {
  1374. if (length == 0) {
  1375. if (TcpHeader.SeqGreater(tcpHeader.ackNumber, tcpSession.sndUna) &&
  1376. TcpHeader.SeqLEQ(tcpHeader.ackNumber, tcpSession.sndMax)) {
  1377. uint acked = tcpHeader.ackNumber - tcpSession.sndUna;
  1378. TcpVectorQueueByte txBuffer = tcpSession.txContainer.Acquire();
  1379. tcpSession.sndUna = tcpHeader.ackNumber;
  1380. tcpSession.sndWnd = tcpHeader.windowSize;
  1381. tcpSession.sndWn1 = tcpHeader.seqNumber;
  1382. tcpSession.sndWn2 = tcpHeader.ackNumber;
  1383. if (acked > 0) {
  1384. txBuffer.ReleaseDataFromTxBuffer(acked);
  1385. }
  1386. txBuffer.SetTxBuffTotalOffset(tcpSession.sndNxt - tcpSession.sndUna);
  1387. slowWheel.DeleteTimerEvent(ref tcpSession.retransmitTimeoutNode);
  1388. bool sendit = false;
  1389. if (TcpHeader.SeqGreater(tcpSession.sndMax, tcpSession.sndUna)) {
  1390. tcpSession.timeoutValue = 500;
  1391. slowWheel.AddTimerEvent(tcpSession.timeoutValue, tcpSession,
  1392. tcpSession.retransmitTimeoutDelegate,
  1393. ref tcpSession.retransmitTimeoutNode);
  1394. }
  1395. else {
  1396. sendit = true;
  1397. }
  1398. tcpSession.txContainer.Release(txBuffer);
  1399. tcpSession.tcpWriterWait.Set();
  1400. if (sendit == true || tcpSession.needFin == true) {
  1401. tcpSession.SendPacket(TcpFlags.ACK, false);
  1402. }
  1403. return;
  1404. }
  1405. }
  1406. else if (tcpHeader.ackNumber == tcpSession.sndUna) {
  1407. int fast_offset = EthernetHeader.Size + IpHeader.Size + tcpHeader.dataOffset;
  1408. Bytes packetData = Bitter.SplitOff(ref packet, fast_offset);
  1409. //delete packet;
  1410. packetLength = packetLength - fast_offset;
  1411. TcpVectorQueueByte rxAssembly = tcpSession.rxAssemblyContainer.Acquire();
  1412. TcpVectorQueueByte rxBuffer = tcpSession.rxContainer.Acquire();
  1413. if (rxAssembly.Empty == true &&
  1414. tcpSession.rcvWnd >= packetLength) {
  1415. rxBuffer.AddTail(packetData, tcpHeader.seqNumber, (uint) packetLength);
  1416. tcpSession.rcvWnd = tcpSession.rcvWnd - (uint) packetLength;
  1417. tcpSession.rcvNxt += (uint) packetLength;
  1418. if (fastWheel.DeleteTimerEvent(ref tcpSession.delayAckTimeoutNode) == true) {
  1419. DebugPrint("Received two segments in a row...ack'ing immediately\n");
  1420. tcpSession.ackNow = true;
  1421. }
  1422. else {
  1423. //delay the ack, hoping for an app message to piggy back
  1424. fastWheel.AddTimerEvent(200, tcpSession,
  1425. tcpSession.delayAckTimeoutDelegate,
  1426. ref tcpSession.delayAckTimeoutNode);
  1427. }
  1428. }
  1429. tcpSession.rxContainer.Release(rxBuffer);
  1430. tcpSession.rxAssemblyContainer.Release(rxAssembly);
  1431. //signal app thread if it is waiting for data
  1432. tcpSession.tcpReaderWait.Set();
  1433. return;
  1434. }
  1435. }
  1436. DebugPrint("tcpSession state is currently {0}\n", tcpSession.currentState);
  1437. if(tcpSession.currentState == TcpState.LISTEN) {
  1438. //ignore RST
  1439. if ((tcpHeader.flags & (byte) TcpFlags.RST) != 0) {
  1440. DebugPrint("Got RST in Listen state...discarding\n");
  1441. //delete packet;
  1442. return;
  1443. }
  1444. if ((tcpHeader.flags & (byte) TcpFlags.FIN) != 0) {
  1445. DebugPrint("Got FIN in Listen state...discarding\n");
  1446. //delete packet;
  1447. return;
  1448. }
  1449. if ((tcpHeader.flags & (byte) TcpFlags.ACK) != 0) {
  1450. DebugPrint("Got packet with ack flag in listen state...sending RST\n");
  1451. SendError(ipHeader, tcpHeader, TcpFlags.RST);
  1452. //delete packet;
  1453. return;
  1454. }
  1455. //complete the connection
  1456. if ((tcpHeader.flags & (byte) TcpFlags.SYN) == 0) {
  1457. //delete packet;
  1458. return;
  1459. }
  1460. if (tcpSession.acceptQueueLength >= tcpSession.acceptQueueMaxSize) {
  1461. DebugStub.Print("No space left on listen queue...dumping packet\n");
  1462. //delete packet;
  1463. return;
  1464. }
  1465. DebugPrint("Received SYN on listening socket. Sending syn-ack queue length {0}\n",
  1466. (tcpSession.acceptQueueLength));
  1467. //see if there is space in the receivers accept queue
  1468. TCP activeTcpSession = new TCP();
  1469. activeTcpSession.localIPAddress = ipHeader.destAddress;
  1470. activeTcpSession.localPort = tcpHeader.destPort;
  1471. activeTcpSession.InternalConnect(ipHeader.srcAddress, tcpHeader.srcPort);
  1472. activeTcpSession.chainedHashLLNode = activeHash.InsertNewSession(activeTcpSession);
  1473. activeTcpSession.listenSocket = tcpSession;
  1474. tcpSession.acceptQueueLength++;
  1475. activeTcpSession.rcvNxt = tcpHeader.seqNumber + 1;
  1476. activeTcpSession.irs = tcpHeader.seqNumber;
  1477. activeTcpSession.sndWn1 = tcpHeader.seqNumber - 1;
  1478. activeTcpSession.sndNxt = activeTcpSession.iss;
  1479. activeTcpSession.sndMax = activeTcpSession.iss;
  1480. activeTcpSession.sndUna = activeTcpSession.iss;
  1481. activeTcpSession.sndWnd = tcpHeader.windowSize;
  1482. activeTcpSession.activeOpen = true;
  1483. activeTcpSession.currentState = TcpState.SYN_RECEIVED;
  1484. if (hasOptions == true) {
  1485. activeTcpSession.ProcessOptions(packet,
  1486. (tcpHeader.dataOffset - TcpHeader.MinSize));
  1487. }
  1488. activeTcpSession.SendPacket(TcpFlags.SYN | TcpFlags.ACK, false);
  1489. slowWheel.AddTimerEvent(75000, activeTcpSession,
  1490. activeTcpSession.connectionTimeoutDelegate,
  1491. ref activeTcpSession.connectionTimeoutNode);
  1492. //delete packet;
  1493. return;
  1494. }
  1495. else if (tcpSession.currentState == TcpState.SYN_SENT) {
  1496. bool ackRcvd = false;
  1497. if ((tcpHeader.flags & (byte) TcpFlags.FIN) != 0) {
  1498. DebugPrint("Got FIN in syn_sent state...discarding\n");
  1499. //delete packet;
  1500. return;
  1501. }
  1502. if ((tcpHeader.flags & (byte) TcpFlags.ACK) != 0) {
  1503. ackRcvd = true;
  1504. if (TcpHeader.SeqLEQ(tcpHeader.ackNumber, tcpSession.iss) ||
  1505. TcpHeader.SeqGreater(tcpHeader.ackNumber, tcpSession.sndNxt)) {
  1506. if ((tcpHeader.flags & (byte) TcpFlags.RST) != 0) {
  1507. DebugPrint("SYN_SENT: Received bogus ack with RST dropping...\n");
  1508. //delete packet;
  1509. return;
  1510. }
  1511. SendError(ipHeader, tcpHeader, TcpFlags.RST);
  1512. //delete packet;
  1513. return;
  1514. }
  1515. DebugStub.Assert(tcpHeader.ackNumber >= tcpSession.sndUna &&
  1516. tcpHeader.ackNumber <= tcpSession.sndNxt);
  1517. }
  1518. if ((tcpHeader.flags & (byte) TcpFlags.RST) != 0) {
  1519. DebugStub.Print("SYN_SENT: received RST\n");
  1520. tcpSession.currentState = TcpState.CLOSED;
  1521. tcpSession.tcpConnWait.Set();
  1522. DisposeTcpSession(tcpSession);
  1523. //delete packet;
  1524. return;
  1525. }
  1526. if ((tcpHeader.flags & (byte) TcpFlags.SYN) == 0) {
  1527. DebugPrint("SYN_SENT: No SYN flag in packet...dropping\n");
  1528. //delete packet;
  1529. return;
  1530. }
  1531. //ok..we've got a syn and no RST. We can continue the connection
  1532. // DebugPrint("Received SYN ack value {0} in SYN_SENT state\n", ackRcvd);
  1533. tcpSession.rcvNxt = tcpHeader.seqNumber + 1;
  1534. tcpSession.irs = tcpHeader.seqNumber;
  1535. tcpSession.sndWn1 = tcpHeader.seqNumber - 1;
  1536. if (ackRcvd == true) {
  1537. tcpSession.sndUna = tcpHeader.ackNumber;
  1538. if (TcpHeader.SeqGreater(tcpSession.sndUna, tcpSession.iss)) {
  1539. //DebugPrint("Entering state ESTABLISHED...woohoo! sending ack\n");
  1540. ////delete the connection timeout timer.
  1541. slowWheel.DeleteTimerEvent(ref tcpSession.connectionTimeoutNode);
  1542. slowWheel.DeleteTimerEvent(ref tcpSession.retransmitTimeoutNode);
  1543. tcpSession.currentState = TcpState.ESTABLISHED;
  1544. tcpSession.sndWnd = tcpHeader.windowSize;
  1545. tcpSession.sndWn1 = tcpHeader.seqNumber;
  1546. tcpSession.sndWn2 = tcpHeader.ackNumber;
  1547. if (hasOptions == true) {
  1548. tcpSession.ProcessOptions(packet,
  1549. (tcpHeader.dataOffset - TcpHeader.MinSize));
  1550. }
  1551. tcpSession.ackNow = true;
  1552. tcpSession.SendPacket(TcpFlags.ACK, false);
  1553. }
  1554. //delete packet;
  1555. }
  1556. else {
  1557. DebugPrint("Simultaneous open! ack!\n");
  1558. DebugStub.Assert(false);
  1559. //delete packet;
  1560. }
  1561. tcpSession.tcpConnWait.Set();
  1562. return;
  1563. }
  1564. else if (tcpSession.currentState == TcpState.CLOSED) {
  1565. //on a closed socket packets containing RST get an RST back.
  1566. if ((tcpHeader.flags & (byte) TcpFlags.RST) == 0) {
  1567. DebugPrint("Received packet on closed socket...sending RST\n");
  1568. if ((tcpHeader.flags & (byte) TcpFlags.FIN) != 0) {
  1569. //delete packet;
  1570. return;
  1571. }
  1572. if ((tcpHeader.flags & (byte) TcpFlags.ACK) != 0) {
  1573. SendError(ipHeader, tcpHeader, TcpFlags.RST);
  1574. }
  1575. else {
  1576. SendError(ipHeader, tcpHeader, TcpFlags.RST | TcpFlags.ACK);
  1577. }
  1578. }
  1579. //delete packet;
  1580. return;
  1581. }
  1582. else {
  1583. //first check whether the sequence number is valid
  1584. bool badSegment = false;
  1585. if (length == 0 && tcpSession.rcvWnd == 0) {
  1586. if (tcpHeader.seqNumber != tcpSession.rcvNxt) {
  1587. badSegment = true;
  1588. }
  1589. }
  1590. else if (length == 0 && tcpSession.rcvWnd > 0) {
  1591. if (TcpHeader.SeqLess(tcpHeader.seqNumber, tcpSession.rcvNxt) ||
  1592. TcpHeader.SeqGEQ(tcpHeader.seqNumber, (tcpSession.rcvNxt + tcpSession.rcvWnd))) {
  1593. badSegment = true;
  1594. }
  1595. }
  1596. else if (length > 0 && tcpSession.rcvWnd == 0) {
  1597. badSegment = true;
  1598. }
  1599. else {
  1600. if (TcpHeader.SeqLess(tcpHeader.seqNumber, tcpSession.rcvNxt) ||
  1601. TcpHeader.SeqGEQ(tcpHeader.seqNumber, (tcpSession.rcvNxt + tcpSession.rcvWnd))) {
  1602. badSegment = true;
  1603. }
  1604. else if (TcpHeader.SeqLess((tcpHeader.seqNumber + (uint) length - 1), tcpSession.rcvNxt) ||
  1605. TcpHeader.SeqGEQ((tcpHeader.seqNumber + (uint) length - 1),
  1606. (tcpSession.rcvNxt + tcpSession.rcvWnd))) {
  1607. badSegment = true;
  1608. }
  1609. }
  1610. if (badSegment == true) {
  1611. DebugPrint("Received bad segment in state {0}\n", tcpSession.currentState);
  1612. DebugPrint("rcvNxt {0} rcvwnd {1} rcvnxt + rcvwnd {2} seqnumber {3}\n",
  1613. tcpSession.rcvNxt, tcpSession.rcvWnd, tcpSession.rcvNxt + tcpSession.rcvWnd,
  1614. tcpHeader.seqNumber);
  1615. if ((tcpHeader.flags & (byte) TcpFlags.RST) == 0) {
  1616. tcpSession.ackNow = true;
  1617. tcpSession.SendPacket(TcpFlags.ACK, false);
  1618. }
  1619. //delete packet;
  1620. return;
  1621. }
  1622. //check the RST bit next
  1623. if ((tcpHeader.flags & (byte) TcpFlags.RST) != 0) {
  1624. DebugPrint("received RST\n");
  1625. if (tcpSession.currentState == TcpState.SYN_RECEIVED) {
  1626. //ok we need to propagate this up to the client somehow
  1627. DisposeTcpSession(tcpSession);
  1628. //send unsolicited "connection refused" error
  1629. //delete packet;
  1630. return;
  1631. }
  1632. else if (tcpSession.currentState >= TcpState.ESTABLISHED &&
  1633. tcpSession.currentState <= TcpState.CLOSE_WAIT) {
  1634. //send unsolicited "connection reset by peer"
  1635. DisposeTcpSession(tcpSession);
  1636. //delete packet;
  1637. return;
  1638. }
  1639. else {
  1640. //no error to propagate here
  1641. DisposeTcpSession(tcpSession);
  1642. //delete packet;
  1643. return;
  1644. }
  1645. }
  1646. //check for the SYN bit
  1647. if ((tcpHeader.flags & (byte) TcpFlags.SYN) != 0) {
  1648. DebugPrint("received SYN in unexpected state {1}\n", tcpSession.currentState);
  1649. Bytes header = GetHeader(IpHeader.Size + TcpHeader.MinSize);
  1650. Bytes ethernetHeader = GetHeader(EthernetHeader.Size);
  1651. BuildHeader (header, ipHeader.destAddress, ipHeader.srcAddress,
  1652. tcpHeader.destPort, tcpHeader.srcPort, (byte) TcpFlags.RST,
  1653. tcpSession.sndNxt, tcpSession.rcvNxt, tcpSession.rcvWnd, 0, 0, tcpSession.sndUp, 0);
  1654. TcpHeader.SetTcpChecksum(header, 0, TcpHeader.MinSize);
  1655. IP.SendOutgoingPacket(ethernetHeader, header, ipHeader.srcAddress);
  1656. DisposeTcpSession(tcpSession);
  1657. //delete packet;
  1658. return;
  1659. }
  1660. //ack processing
  1661. if ((tcpHeader.flags & (byte) TcpFlags.ACK) == 0) {
  1662. DebugPrint("No ack...discarding packet\n");
  1663. //delete packet;
  1664. return;
  1665. }
  1666. //XXX BUG BUG BUG if listener closed we need to close this connection.
  1667. if (tcpSession.currentState == TcpState.SYN_RECEIVED) {
  1668. if (TcpHeader.SeqLEQ(tcpSession.sndUna, tcpHeader.ackNumber) &&
  1669. TcpHeader.SeqGEQ(tcpSession.sndNxt, tcpHeader.ackNumber)) {
  1670. tcpSession.sndWnd = tcpHeader.windowSize;
  1671. tcpSession.sndWn1 = tcpHeader.seqNumber;
  1672. tcpSession.sndWn2 = tcpHeader.ackNumber;
  1673. tcpSession.sndUna = tcpHeader.ackNumber;
  1674. tcpSession.currentState = TcpState.ESTABLISHED;
  1675. TCP listener = tcpSession.listenSocket;
  1676. if (listener == null) {
  1677. DebugStub.Break();
  1678. }
  1679. if (listener.currentState != TcpState.LISTEN) {
  1680. DebugStub.Break();
  1681. }
  1682. DebugPrint("SYN_RECEIVED: Entering ESTABLISHED state tail is {0}\n", listener.acceptQueueTail);
  1683. listener.acceptQueue[listener.acceptQueueTail] = tcpSession;
  1684. listener.acceptQueueTail =
  1685. (listener.acceptQueueTail + 1) % listener.acceptQueueMaxSize;
  1686. slowWheel.DeleteTimerEvent(ref tcpSession.retransmitTimeoutNode);
  1687. slowWheel.DeleteTimerEvent(ref tcpSession.connectionTimeoutNode);
  1688. VTable.Assert(tcpSession.listenSocket != null);
  1689. listener.tcpConnWait.Set();
  1690. //delete packet;
  1691. return;
  1692. }
  1693. else {
  1694. DebugStub.Print("Received out of band sequence number in state SYN_RECEIVED\n");
  1695. //XXX should cleanup session here
  1696. SendError(ipHeader, tcpHeader, TcpFlags.RST);
  1697. //delete packet;
  1698. return;
  1699. }
  1700. }
  1701. else if (tcpSession.currentState == TcpState.ESTABLISHED ||
  1702. tcpSession.currentState == TcpState.FIN_WAIT_1 ||
  1703. tcpSession.currentState == TcpState.FIN_WAIT_2 ||
  1704. tcpSession.currentState == TcpState.CLOSE_WAIT ||
  1705. tcpSession.currentState == TcpState.CLOSING) {
  1706. if (TcpHeader.SeqGreater(tcpHeader.ackNumber, tcpSession.sndMax)) {
  1707. DebugStub.Print("Received ack: {0} > sndMax {1}...discaring\n",
  1708. DebugStub.ArgList(tcpHeader.ackNumber, tcpSession.sndMax));
  1709. tcpSession.ackNow = true;
  1710. tcpSession.SendPacket(TcpFlags.ACK, false);
  1711. //delete packet;
  1712. return;
  1713. }
  1714. bool dupAck = false;
  1715. if (TcpHeader.SeqLEQ(tcpHeader.ackNumber, tcpSession.sndUna)) {
  1716. if (TcpHeader.SeqLess(tcpSession.sndWn1, tcpHeader.seqNumber) ||
  1717. (TcpHeader.SeqEQ(tcpSession.sndWn1, tcpHeader.seqNumber) &&
  1718. (TcpHeader.SeqLEQ(tcpSession.sndWn2, tcpHeader.ackNumber) ||
  1719. tcpSession.sndWn1 == tcpHeader.ackNumber &&
  1720. tcpHeader.windowSize > tcpSession.sndWnd))) {
  1721. DebugPrint("dup ack pure window update updating sndWnd wn1 and wn2\n");
  1722. tcpSession.sndWnd = tcpHeader.windowSize;
  1723. tcpSession.sndWn1 = tcpHeader.seqNumber;
  1724. tcpSession.sndWn2 = tcpHeader.ackNumber;
  1725. tcpSession.tcpWriterWait.Set();
  1726. }
  1727. else {
  1728. DebugPrint("ignoring duplicate ack\n");
  1729. }
  1730. dupAck = true;
  1731. }
  1732. if (dupAck == false) {
  1733. //update the send window
  1734. //release bytes from the send queue
  1735. //Need to make sure we send a window update
  1736. uint acked = tcpHeader.ackNumber - tcpSession.sndUna;
  1737. //DebugPrint("Acked {0} bytes\n", acked);
  1738. TcpVectorQueueByte txBuffer = tcpSession.txContainer.Acquire();
  1739. uint toFree;
  1740. if (acked > txBuffer.Size()) {
  1741. DebugPrint("FIN was acked...\n");
  1742. tcpSession.needFin = false;
  1743. tcpSession.finacked = true;
  1744. toFree = txBuffer.Size();
  1745. }
  1746. else {
  1747. toFree = acked;
  1748. }
  1749. tcpSession.sndUna = tcpHeader.ackNumber;
  1750. if (TcpHeader.SeqLess(tcpSession.sndNxt, tcpSession.sndUna)) {
  1751. //if we're in retransmission mode, drag sndnxt along
  1752. tcpSession.sndNxt = tcpSession.sndUna;
  1753. }
  1754. if (toFree > 0) {
  1755. DebugPrint("Release {0} bytes\n", toFree);
  1756. txBuffer.ReleaseDataFromTxBuffer(toFree);
  1757. txBuffer.SetTxBuffTotalOffset(tcpSession.sndNxt - tcpSession.sndUna);
  1758. slowWheel.DeleteTimerEvent(ref tcpSession.retransmitTimeoutNode);
  1759. VTable.Assert(tcpSession.retransmitTimeoutNode == null);
  1760. tcpSession.tcpWriterWait.Set();
  1761. }
  1762. if (TcpHeader.SeqGreater(tcpSession.sndMax, tcpSession.sndNxt)) {
  1763. tcpSession.timeoutValue = 500;
  1764. slowWheel.AddTimerEvent(tcpSession.timeoutValue, tcpSession,
  1765. tcpSession.retransmitTimeoutDelegate,
  1766. ref tcpSession.retransmitTimeoutNode);
  1767. }
  1768. tcpSession.txContainer.Release(txBuffer);
  1769. if (TcpHeader.SeqLess(tcpSession.sndWn1, tcpHeader.seqNumber) ||
  1770. (TcpHeader.SeqEQ(tcpSession.sndWn1, tcpHeader.seqNumber) &&
  1771. (TcpHeader.SeqLEQ(tcpSession.sndWn2, tcpHeader.ackNumber) ||
  1772. tcpSession.sndWn1 == tcpHeader.ackNumber &&
  1773. tcpHeader.windowSize > tcpSession.sndWnd))) {
  1774. //DebugPrint("updating sndWnd wn1 and wn2\n");
  1775. tcpSession.sndWnd = tcpHeader.windowSize;
  1776. tcpSession.sndWn1 = tcpHeader.seqNumber;
  1777. tcpSession.sndWn2 = tcpHeader.ackNumber;
  1778. }
  1779. if (tcpSession.currentState == TcpState.FIN_WAIT_1) {
  1780. DebugPrint("in FIN_WAIT_1 finacked is {0}\n", tcpSession.finacked);
  1781. if (tcpSession.finacked == true) {
  1782. slowWheel.DeleteTimerEvent(ref tcpSession.retransmitTimeoutNode);
  1783. slowWheel.AddTimerEvent(30000, tcpSession,
  1784. tcpSession.fin2MslTimeoutDelegate,
  1785. ref tcpSession.fin2MslTimeoutNode);
  1786. tcpSession.currentState = TcpState.FIN_WAIT_2;
  1787. }
  1788. }
  1789. else if (tcpSession.currentState == TcpState.CLOSING) {
  1790. if (tcpSession.finacked == true) {
  1791. DebugPrint("CLOSING Received ack for FIN\n");
  1792. DeleteTimers(tcpSession);
  1793. tcpSession.currentState = TcpState.TIME_WAIT;
  1794. slowWheel.AddTimerEvent(30000, tcpSession,
  1795. tcpSession.fin2MslTimeoutDelegate,
  1796. ref tcpSession.fin2MslTimeoutNode);
  1797. //delete packet;
  1798. return;
  1799. }
  1800. }
  1801. }//if (dupAck == false)
  1802. }
  1803. else if (tcpSession.currentState == TcpState.LAST_ACK) {
  1804. if (TcpHeader.SeqLEQ(tcpSession.sndUna, tcpHeader.ackNumber) &&
  1805. TcpHeader.SeqGEQ(tcpSession.sndNxt, tcpHeader.ackNumber)) {
  1806. uint acked = tcpHeader.ackNumber - tcpSession.sndUna;
  1807. //DebugPrint("Acked {0} bytes\n", acked);
  1808. TcpVectorQueueByte txBuffer = tcpSession.txContainer.Acquire();
  1809. uint size = txBuffer.Size();
  1810. tcpSession.txContainer.Release(txBuffer);
  1811. if (acked > size) {
  1812. //DebugPrint("our fin was acked in LAST_ACK...disposing of session\n");
  1813. tcpSession.currentState = TcpState.CLOSED;
  1814. DisposeTcpSession(tcpSession);
  1815. return;
  1816. }
  1817. }
  1818. }
  1819. else if (tcpSession.currentState == TcpState.TIME_WAIT) {
  1820. //DebugPrint("time to ack and restart 2msl timer\n");
  1821. slowWheel.DeleteTimerEvent(ref tcpSession.fin2MslTimeoutNode);
  1822. slowWheel.AddTimerEvent(30000, tcpSession,
  1823. tcpSession.fin2MslTimeoutDelegate,
  1824. ref tcpSession.fin2MslTimeoutNode);
  1825. tcpSession.ackNow = true;
  1826. tcpSession.SendPacket(TcpFlags.ACK, false);
  1827. //delete packet;
  1828. return;
  1829. }
  1830. else {
  1831. DebugStub.Print("We're in a bad state!!\n");
  1832. DebugStub.Assert(false);
  1833. }
  1834. if ((tcpHeader.flags & (byte) TcpFlags.URG) != 0) {
  1835. DebugPrint("Got urgent data!!!\n");
  1836. DebugStub.Break();
  1837. //delete packet;
  1838. return;
  1839. }
  1840. //now we process the data in the segment
  1841. //this method takes care of delayed acks etc.
  1842. tcpSession.PushPacket(packet, (uint) packetLength, tcpHeader);
  1843. //finally, process the fin bit
  1844. if ((tcpHeader.flags & (byte) TcpFlags.FIN) != 0) {
  1845. tcpSession.rcvNxt++;
  1846. if ((tcpSession.currentState == TcpState.SYN_RECEIVED) ||
  1847. (tcpSession.currentState == TcpState.ESTABLISHED)) {
  1848. DebugPrint("Recieved FIN in {0} state...closing connection moving to CLOSE_WAIT\n",
  1849. tcpSession.currentState);
  1850. tcpSession.currentState = TcpState.CLOSE_WAIT;
  1851. tcpSession.tcpWriterWait.Set();
  1852. tcpSession.tcpReaderWait.Set();
  1853. tcpSession.tcpConnWait.Set();
  1854. }
  1855. else if (tcpSession.currentState == TcpState.FIN_WAIT_1) {
  1856. tcpSession.currentState = TcpState.CLOSING;
  1857. DebugPrint("Received FIN in FIN_WAIT_1..simultaneous close\n");
  1858. slowWheel.DeleteTimerEvent(ref tcpSession.retransmitTimeoutNode);
  1859. slowWheel.AddTimerEvent(30000, tcpSession,
  1860. tcpSession.fin2MslTimeoutDelegate,
  1861. ref tcpSession.fin2MslTimeoutNode);
  1862. /* clean up our sending queue */
  1863. TcpVectorQueueByte txBuffer = tcpSession.txContainer.Acquire();
  1864. if (txBuffer.Size() > 0) {
  1865. txBuffer.ReleaseDataFromTxBuffer(txBuffer.Size());
  1866. }
  1867. tcpSession.txContainer.Release(txBuffer);
  1868. }
  1869. else if (tcpSession.currentState == TcpState.FIN_WAIT_2) {
  1870. //DebugPrint("Recieved FIN in FIN_WAIT_2 entering TIME_WAIT\n");
  1871. tcpSession.currentState = TcpState.TIME_WAIT;
  1872. DeleteTimers(tcpSession);
  1873. slowWheel.AddTimerEvent(30000, tcpSession,
  1874. tcpSession.fin2MslTimeoutDelegate,
  1875. ref tcpSession.fin2MslTimeoutNode);
  1876. }
  1877. else if (tcpSession.currentState == TcpState.TIME_WAIT) {
  1878. //not sure what to do here
  1879. } //else stay in same state
  1880. tcpSession.ackNow = true;
  1881. tcpSession.SendPacket(TcpFlags.ACK, false);
  1882. }
  1883. }
  1884. }
  1885. }
  1886. }