Move new Class Driver powered demos to a new ClassDriver subdirectory, re-add old...
[pub/lufa.git] / Demos / Device / RNDISEthernet / Lib / TCP.c
diff --git a/Demos/Device/RNDISEthernet/Lib/TCP.c b/Demos/Device/RNDISEthernet/Lib/TCP.c
deleted file mode 100644 (file)
index 7c3f3b4..0000000
+++ /dev/null
@@ -1,614 +0,0 @@
-/*\r
-             LUFA Library\r
-     Copyright (C) Dean Camera, 2009.\r
-              \r
-  dean [at] fourwalledcubicle [dot] com\r
-      www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
-  Copyright 2009  Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
-  Permission to use, copy, modify, and distribute this software\r
-  and its documentation for any purpose and without fee is hereby\r
-  granted, provided that the above copyright notice appear in all\r
-  copies and that both that the copyright notice and this\r
-  permission notice and warranty disclaimer appear in supporting\r
-  documentation, and that the name of the author not be used in\r
-  advertising or publicity pertaining to distribution of the\r
-  software without specific, written prior permission.\r
-\r
-  The author disclaim all warranties with regard to this\r
-  software, including all implied warranties of merchantability\r
-  and fitness.  In no event shall the author be liable for any\r
-  special, indirect or consequential damages or any damages\r
-  whatsoever resulting from loss of use, data or profits, whether\r
-  in an action of contract, negligence or other tortious action,\r
-  arising out of or in connection with the use or performance of\r
-  this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- *  Transmission Control Protocol (TCP) packet handling routines. This protocol handles the reliable in-order transmission\r
- *  and reception of packets to and from devices on a network, to "ports" on the device. It is used in situations where data\r
- *  delivery must be reliable and correct, e.g. HTTP, TELNET and most other non-streaming protocols.\r
- */\r
\r
-#define  INCLUDE_FROM_TCP_C\r
-#include "TCP.h"\r
-\r
-/* Global Variables: */\r
-/** Port state table array. This contains the current status of TCP ports in the device. To save on space, only open ports are\r
- *  stored - closed ports may be overwritten at any time, and the system will assume any ports not present in the array are closed. This\r
- *  allows for MAX_OPEN_TCP_PORTS to be less than the number of ports used by the application if desired.\r
- */\r
-TCP_PortState_t        PortStateTable[MAX_OPEN_TCP_PORTS];\r
-\r
-/** Connection state table array. This contains the current status of TCP connections in the device. To save on space, only active\r
- *  (non-closed) connections are stored - closed connections may be overwritten at any time, and the system will assume any connections\r
- *  not present in the array are closed.\r
- */\r
-TCP_ConnectionState_t  ConnectionStateTable[MAX_TCP_CONNECTIONS];\r
-\r
-\r
-/** Task to handle the calling of each registered application's callback function, to process and generate TCP packets at the application\r
- *  level. If an application produces a response, this task constructs the appropriate Ethernet frame and places it into the Ethernet OUT\r
- *  buffer for later transmission.\r
- */\r
-void TCP_TCPTask(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo)\r
-{\r
-       /* Task to hand off TCP packets to and from the listening applications. */\r
-\r
-       /* Run each application in sequence, to process incoming and generate outgoing packets */\r
-       for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)\r
-       {\r
-               /* Find the corresponding port entry in the port table */\r
-               for (uint8_t PTableEntry = 0; PTableEntry < MAX_TCP_CONNECTIONS; PTableEntry++)\r
-               {\r
-                       /* Run the application handler for the port */\r
-                       if ((PortStateTable[PTableEntry].Port  == ConnectionStateTable[CSTableEntry].Port) && \r
-                           (PortStateTable[PTableEntry].State == TCP_Port_Open))\r
-                       {\r
-                               PortStateTable[PTableEntry].ApplicationHandler(&ConnectionStateTable[CSTableEntry], &ConnectionStateTable[CSTableEntry].Info.Buffer);\r
-                       }\r
-               }\r
-       }\r
-       \r
-       /* Bail out early if there is already a frame waiting to be sent in the Ethernet OUT buffer */\r
-       if (RNDISInterfaceInfo->FrameOUT.FrameInBuffer)\r
-         return;\r
-       \r
-       /* Send response packets from each application as the TCP packet buffers are filled by the applications */\r
-       for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)\r
-       {\r
-               /* For each completely received packet, pass it along to the listening application */\r
-               if ((ConnectionStateTable[CSTableEntry].Info.Buffer.Direction == TCP_PACKETDIR_OUT) &&\r
-                   (ConnectionStateTable[CSTableEntry].Info.Buffer.Ready))\r
-               {\r
-                       Ethernet_Frame_Header_t* FrameOUTHeader = (Ethernet_Frame_Header_t*)&RNDISInterfaceInfo->FrameOUT.FrameData;\r
-                       IP_Header_t*    IPHeaderOUT  = (IP_Header_t*)&RNDISInterfaceInfo->FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t)];\r
-                       TCP_Header_t*   TCPHeaderOUT = (TCP_Header_t*)&RNDISInterfaceInfo->FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t) +\r
-                                                                                                             sizeof(IP_Header_t)];                                             \r
-                       void*           TCPDataOUT     = &RNDISInterfaceInfo->FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t) +\r
-                                                                                                sizeof(IP_Header_t) +\r
-                                                                                                sizeof(TCP_Header_t)];\r
-\r
-                       uint16_t PacketSize = ConnectionStateTable[CSTableEntry].Info.Buffer.Length;\r
-\r
-                       /* Fill out the TCP data */\r
-                       TCPHeaderOUT->SourcePort           = ConnectionStateTable[CSTableEntry].Port;\r
-                       TCPHeaderOUT->DestinationPort      = ConnectionStateTable[CSTableEntry].RemotePort;\r
-                       TCPHeaderOUT->SequenceNumber       = SwapEndian_32(ConnectionStateTable[CSTableEntry].Info.SequenceNumberOut);\r
-                       TCPHeaderOUT->AcknowledgmentNumber = SwapEndian_32(ConnectionStateTable[CSTableEntry].Info.SequenceNumberIn);\r
-                       TCPHeaderOUT->DataOffset           = (sizeof(TCP_Header_t) / sizeof(uint32_t));\r
-                       TCPHeaderOUT->WindowSize           = SwapEndian_16(TCP_WINDOW_SIZE);\r
-\r
-                       TCPHeaderOUT->Flags                = TCP_FLAG_ACK;\r
-                       TCPHeaderOUT->UrgentPointer        = 0;\r
-                       TCPHeaderOUT->Checksum             = 0;\r
-                       TCPHeaderOUT->Reserved             = 0;\r
-\r
-                       memcpy(TCPDataOUT, ConnectionStateTable[CSTableEntry].Info.Buffer.Data, PacketSize);\r
-                       \r
-                       ConnectionStateTable[CSTableEntry].Info.SequenceNumberOut += PacketSize;\r
-\r
-                       TCPHeaderOUT->Checksum             = TCP_Checksum16(TCPHeaderOUT, ServerIPAddress,\r
-                                                                           ConnectionStateTable[CSTableEntry].RemoteAddress,\r
-                                                                           (sizeof(TCP_Header_t) + PacketSize));\r
-\r
-                       PacketSize += sizeof(TCP_Header_t);\r
-\r
-                       /* Fill out the response IP header */\r
-                       IPHeaderOUT->TotalLength        = SwapEndian_16(sizeof(IP_Header_t) + PacketSize);\r
-                       IPHeaderOUT->TypeOfService      = 0;\r
-                       IPHeaderOUT->HeaderLength       = (sizeof(IP_Header_t) / sizeof(uint32_t));\r
-                       IPHeaderOUT->Version            = 4;\r
-                       IPHeaderOUT->Flags              = 0;\r
-                       IPHeaderOUT->FragmentOffset     = 0;\r
-                       IPHeaderOUT->Identification     = 0;\r
-                       IPHeaderOUT->HeaderChecksum     = 0;\r
-                       IPHeaderOUT->Protocol           = PROTOCOL_TCP;\r
-                       IPHeaderOUT->TTL                = DEFAULT_TTL;\r
-                       IPHeaderOUT->SourceAddress      = ServerIPAddress;\r
-                       IPHeaderOUT->DestinationAddress = ConnectionStateTable[CSTableEntry].RemoteAddress;\r
-                       \r
-                       IPHeaderOUT->HeaderChecksum     = Ethernet_Checksum16(IPHeaderOUT, sizeof(IP_Header_t));\r
-               \r
-                       PacketSize += sizeof(IP_Header_t);\r
-               \r
-                       /* Fill out the response Ethernet frame header */\r
-                       FrameOUTHeader->Source          = ServerMACAddress;\r
-                       FrameOUTHeader->Destination     = (MAC_Address_t){{0x02, 0x00, 0x02, 0x00, 0x02, 0x00}};\r
-                       FrameOUTHeader->EtherType       = SwapEndian_16(ETHERTYPE_IPV4);\r
-\r
-                       PacketSize += sizeof(Ethernet_Frame_Header_t);\r
-\r
-                       /* Set the response length in the buffer and indicate that a response is ready to be sent */\r
-                       RNDISInterfaceInfo->FrameOUT.FrameLength   = PacketSize;\r
-                       RNDISInterfaceInfo->FrameOUT.FrameInBuffer = true;\r
-                       \r
-                       ConnectionStateTable[CSTableEntry].Info.Buffer.Ready = false;\r
-                       \r
-                       break;\r
-               }\r
-       }\r
-}\r
-\r
-/** Initializes the TCP protocol handler, clearing the port and connection state tables. This must be called before TCP packets are\r
- *  processed.\r
- */\r
-void TCP_Init(void)\r
-{\r
-       /* Initialize the port state table with all CLOSED entries */\r
-       for (uint8_t PTableEntry = 0; PTableEntry < MAX_OPEN_TCP_PORTS; PTableEntry++)\r
-         PortStateTable[PTableEntry].State = TCP_Port_Closed;\r
-\r
-       /* Initialize the connection table with all CLOSED entries */\r
-       for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)\r
-         ConnectionStateTable[CSTableEntry].State = TCP_Connection_Closed;\r
-}\r
-\r
-/** Sets the state and callback handler of the given port, specified in big endian to the given state.\r
- *\r
- *  \param Port     Port whose state and callback function to set, specified in big endian\r
- *  \param State    New state of the port, a value from the TCP_PortStates_t enum\r
- *  \param Handler  Application callback handler for the port\r
- *\r
- *  \return Boolean true if the port state was set, false otherwise (no more space in the port state table)\r
- */\r
-bool TCP_SetPortState(uint16_t Port, uint8_t State, void (*Handler)(TCP_ConnectionState_t*, TCP_ConnectionBuffer_t*))\r
-{\r
-       /* Note, Port number should be specified in BIG endian to simplify network code */\r
-\r
-       /* Check to see if the port entry is already in the port state table */\r
-       for (uint8_t PTableEntry = 0; PTableEntry < MAX_TCP_CONNECTIONS; PTableEntry++)\r
-       {\r
-               /* Find existing entry for the port in the table, update it if found */\r
-               if (PortStateTable[PTableEntry].Port == Port)\r
-               {\r
-                       PortStateTable[PTableEntry].State = State;\r
-                       PortStateTable[PTableEntry].ApplicationHandler = Handler;\r
-                       return true;\r
-               }\r
-       }\r
-\r
-       /* Check if trying to open the port -- if so we need to find an unused (closed) entry and replace it */\r
-       if (State == TCP_Port_Open)\r
-       {\r
-               for (uint8_t PTableEntry = 0; PTableEntry < MAX_TCP_CONNECTIONS; PTableEntry++)\r
-               {\r
-                       /* Find a closed port entry in the table, change it to the given port and state */\r
-                       if (PortStateTable[PTableEntry].State == TCP_Port_Closed)\r
-                       {\r
-                               PortStateTable[PTableEntry].Port  = Port;\r
-                               PortStateTable[PTableEntry].State = State;\r
-                               PortStateTable[PTableEntry].ApplicationHandler = Handler;\r
-                               return true;\r
-                       }\r
-               }\r
-               \r
-               /* Port not in table and no room to add it, return failure */\r
-               return false;\r
-       }\r
-       else\r
-       {\r
-               /* Port not in table but trying to close it, so operation successful */\r
-               return true;\r
-       }\r
-}\r
-\r
-/** Retrieves the current state of a given TCP port, specified in big endian.\r
- *\r
- *  \param Port  TCP port whose state is to be retrieved, given in big-endian\r
- *\r
- *  \return A value from the TCP_PortStates_t enum\r
- */\r
-uint8_t TCP_GetPortState(uint16_t Port)\r
-{\r
-       /* Note, Port number should be specified in BIG endian to simplify network code */\r
-\r
-       for (uint8_t PTableEntry = 0; PTableEntry < MAX_TCP_CONNECTIONS; PTableEntry++)\r
-       {\r
-               /* Find existing entry for the port in the table, return the port status if found */\r
-               if (PortStateTable[PTableEntry].Port == Port)\r
-                 return PortStateTable[PTableEntry].State;\r
-       }\r
-       \r
-       /* Port not in table, assume closed */\r
-       return TCP_Port_Closed;\r
-}\r
-\r
-/** Sets the connection state of the given port, remote address and remote port to the given TCP connection state. If the\r
- *  connection exists in the connection state table it is updated, otherwise it is created if possible.\r
- *\r
- *  \param Port           TCP port of the connection on the device, specified in big endian\r
- *  \param RemoteAddress  Remote protocol IP address of the connected device\r
- *  \param RemotePort     TCP port of the remote device in the connection, specified in big endian\r
- *  \param State          TCP connection state, a value from the TCP_ConnectionStates_t enum\r
- *\r
- *  \return Boolean true if the connection was updated or created, false otherwise (no more space in the connection state table)\r
- */\r
-bool TCP_SetConnectionState(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort, uint8_t State)\r
-{\r
-       /* Note, Port number should be specified in BIG endian to simplify network code */\r
-\r
-       for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)\r
-       {\r
-               /* Find port entry in the table */\r
-               if ((ConnectionStateTable[CSTableEntry].Port == Port) &&\r
-                    IP_COMPARE(&ConnectionStateTable[CSTableEntry].RemoteAddress, &RemoteAddress) &&\r
-                        ConnectionStateTable[CSTableEntry].RemotePort == RemotePort)\r
-               {\r
-                       ConnectionStateTable[CSTableEntry].State = State;\r
-                       return true;\r
-               }\r
-       }\r
-       \r
-       for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)\r
-       {\r
-               /* Find empty entry in the table */\r
-               if (ConnectionStateTable[CSTableEntry].State == TCP_Connection_Closed)\r
-               {\r
-                       ConnectionStateTable[CSTableEntry].Port          = Port;\r
-                       ConnectionStateTable[CSTableEntry].RemoteAddress = RemoteAddress;                       \r
-                       ConnectionStateTable[CSTableEntry].RemotePort    = RemotePort;\r
-                       ConnectionStateTable[CSTableEntry].State         = State;\r
-                       return true;\r
-               }\r
-       }\r
-       \r
-       return false;\r
-}\r
-\r
-/** Retrieves the current state of a given TCP connection to a host.\r
- *\r
- *  \param Port           TCP port on the device in the connection, specified in big endian\r
- *  \param RemoteAddress  Remote protocol IP address of the connected host\r
- *  \param RemotePort     Remote TCP port of the connected host, specified in big endian\r
- *\r
- *  \return A value from the TCP_ConnectionStates_t enum\r
- */\r
-uint8_t TCP_GetConnectionState(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort)\r
-{\r
-       /* Note, Port number should be specified in BIG endian to simplify network code */\r
-\r
-       for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)\r
-       {\r
-               /* Find port entry in the table */\r
-               if ((ConnectionStateTable[CSTableEntry].Port == Port) &&\r
-                    IP_COMPARE(&ConnectionStateTable[CSTableEntry].RemoteAddress, &RemoteAddress) &&\r
-                        ConnectionStateTable[CSTableEntry].RemotePort == RemotePort)\r
-                        \r
-               {\r
-                       return ConnectionStateTable[CSTableEntry].State;\r
-               }\r
-       }\r
-       \r
-       return TCP_Connection_Closed;\r
-}\r
-\r
-/** Retrieves the connection info structure of a given connection to a host.\r
- *\r
- *  \param Port           TCP port on the device in the connection, specified in big endian\r
- *  \param RemoteAddress  Remote protocol IP address of the connected host\r
- *  \param RemotePort     Remote TCP port of the connected host, specified in big endian\r
- *\r
- *  \return ConnectionInfo structure of the connection if found, NULL otherwise\r
- */\r
-TCP_ConnectionInfo_t* TCP_GetConnectionInfo(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort)\r
-{\r
-       /* Note, Port number should be specified in BIG endian to simplify network code */\r
-\r
-       for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)\r
-       {\r
-               /* Find port entry in the table */\r
-               if ((ConnectionStateTable[CSTableEntry].Port == Port) &&\r
-                    IP_COMPARE(&ConnectionStateTable[CSTableEntry].RemoteAddress, &RemoteAddress) &&\r
-                        ConnectionStateTable[CSTableEntry].RemotePort == RemotePort)\r
-               {\r
-                       return &ConnectionStateTable[CSTableEntry].Info;\r
-               }\r
-       }\r
-       \r
-       return NULL;\r
-}\r
-\r
-/** Processes a TCP packet inside an Ethernet frame, and writes the appropriate response\r
- *  to the output Ethernet frame if one is created by a application handler.\r
- *\r
- *  \param IPHeaderInStart    Pointer to the start of the incoming packet's IP header\r
- *  \param TCPHeaderInStart   Pointer to the start of the incoming packet's TCP header\r
- *  \param TCPHeaderOutStart  Pointer to the start of the outgoing packet's TCP header\r
- *\r
- *  \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE if no\r
- *           response was generated, NO_PROCESS if the packet processing was deferred until the\r
- *           next Ethernet packet handler iteration\r
- */\r
-int16_t TCP_ProcessTCPPacket(void* IPHeaderInStart, void* TCPHeaderInStart, void* TCPHeaderOutStart)\r
-{\r
-       IP_Header_t*  IPHeaderIN   = (IP_Header_t*)IPHeaderInStart;\r
-       TCP_Header_t* TCPHeaderIN  = (TCP_Header_t*)TCPHeaderInStart;\r
-       TCP_Header_t* TCPHeaderOUT = (TCP_Header_t*)TCPHeaderOutStart;\r
-\r
-       TCP_ConnectionInfo_t* ConnectionInfo;\r
-       \r
-       DecodeTCPHeader(TCPHeaderInStart);\r
-\r
-       bool PacketResponse = false;\r
-               \r
-       /* Check if the destination port is open and allows incoming connections */\r
-       if (TCP_GetPortState(TCPHeaderIN->DestinationPort) == TCP_Port_Open)\r
-       {\r
-               /* Detect SYN from host to start a connection */\r
-               if (TCPHeaderIN->Flags & TCP_FLAG_SYN)\r
-                 TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, TCPHeaderIN->SourcePort, TCP_Connection_Listen);\r
-\r
-               /* Detect RST from host to abort existing connection */\r
-               if (TCPHeaderIN->Flags & TCP_FLAG_RST)\r
-               {\r
-                       TCPHeaderOUT->Flags = (TCP_FLAG_RST | TCP_FLAG_ACK);                            \r
-                       PacketResponse = true;\r
-                       \r
-                       TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
-                                              TCPHeaderIN->SourcePort, TCP_Connection_Closed);                 \r
-               }\r
-               else\r
-               {\r
-                       /* Process the incoming TCP packet based on the current connection state for the sender and port */\r
-                       switch (TCP_GetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, TCPHeaderIN->SourcePort))\r
-                       {\r
-                               case TCP_Connection_Listen:\r
-                                       if (TCPHeaderIN->Flags == TCP_FLAG_SYN)\r
-                                       {\r
-                                               /* SYN connection when closed starts a connection with a peer */\r
-\r
-                                               TCPHeaderOUT->Flags = (TCP_FLAG_SYN | TCP_FLAG_ACK);                            \r
-                                               PacketResponse      = true;\r
-                                                                       \r
-                                               TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, TCPHeaderIN->SourcePort,\r
-                                                                                          TCP_Connection_SYNReceived);\r
-                                                                                          \r
-                                               ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, TCPHeaderIN->SourcePort);\r
-\r
-                                               ConnectionInfo->SequenceNumberIn  = (SwapEndian_32(TCPHeaderIN->SequenceNumber) + 1);\r
-                                               ConnectionInfo->SequenceNumberOut = 0;\r
-                                               ConnectionInfo->Buffer.InUse      = false;\r
-                                       }\r
-                                       \r
-                                       break;\r
-                               case TCP_Connection_SYNReceived:\r
-                                       if (TCPHeaderIN->Flags == TCP_FLAG_ACK)\r
-                                       {\r
-                                               /* ACK during the connection process completes the connection to a peer */\r
-\r
-                                               TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
-                                                                                          TCPHeaderIN->SourcePort, TCP_Connection_Established);\r
-\r
-                                               ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
-                                                                                                                          TCPHeaderIN->SourcePort);\r
-                                                                                                                          \r
-                                               ConnectionInfo->SequenceNumberOut++;\r
-                                       }\r
-                                       \r
-                                       break;\r
-                               case TCP_Connection_Established:\r
-                                       if (TCPHeaderIN->Flags == (TCP_FLAG_FIN | TCP_FLAG_ACK))\r
-                                       {\r
-                                               /* FIN ACK when connected to a peer starts the finalization process */\r
-                                       \r
-                                               TCPHeaderOUT->Flags = (TCP_FLAG_FIN | TCP_FLAG_ACK);                            \r
-                                               PacketResponse      = true;\r
-                                               \r
-                                               TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
-                                                                                          TCPHeaderIN->SourcePort, TCP_Connection_CloseWait);\r
-\r
-                                               ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
-                                                                                                                          TCPHeaderIN->SourcePort);\r
-\r
-                                               ConnectionInfo->SequenceNumberIn++;\r
-                                               ConnectionInfo->SequenceNumberOut++;\r
-                                       }\r
-                                       else if ((TCPHeaderIN->Flags == TCP_FLAG_ACK) || (TCPHeaderIN->Flags == (TCP_FLAG_ACK | TCP_FLAG_PSH)))\r
-                                       {\r
-                                               ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
-                                                                                                                          TCPHeaderIN->SourcePort);\r
-\r
-                                               /* Check if the buffer is currently in use either by a buffered data to send, or receive */             \r
-                                               if ((ConnectionInfo->Buffer.InUse == false) && (ConnectionInfo->Buffer.Ready == false))\r
-                                               {                                               \r
-                                                       ConnectionInfo->Buffer.Direction = TCP_PACKETDIR_IN;\r
-                                                       ConnectionInfo->Buffer.InUse     = true;\r
-                                                       ConnectionInfo->Buffer.Length    = 0;\r
-                                               }\r
-                                               \r
-                                               /* Check if the buffer has been claimed by us to read in data from the peer */\r
-                                               if ((ConnectionInfo->Buffer.Direction == TCP_PACKETDIR_IN) &&\r
-                                                       (ConnectionInfo->Buffer.Length != TCP_WINDOW_SIZE))\r
-                                               {\r
-                                                       uint16_t IPOffset   = (IPHeaderIN->HeaderLength * sizeof(uint32_t));\r
-                                                       uint16_t TCPOffset  = (TCPHeaderIN->DataOffset * sizeof(uint32_t));\r
-                                                       uint16_t DataLength = (SwapEndian_16(IPHeaderIN->TotalLength) - IPOffset - TCPOffset);\r
-\r
-                                                       /* Copy the packet data into the buffer */\r
-                                                       memcpy(&ConnectionInfo->Buffer.Data[ConnectionInfo->Buffer.Length],\r
-                                                                  &((uint8_t*)TCPHeaderInStart)[TCPOffset],\r
-                                                                  DataLength);\r
-\r
-                                                       ConnectionInfo->SequenceNumberIn += DataLength;\r
-                                                       ConnectionInfo->Buffer.Length    += DataLength;\r
-                                                       \r
-                                                       /* Check if the buffer is full or if the PSH flag is set, if so indicate buffer ready */\r
-                                                       if ((!(TCP_WINDOW_SIZE - ConnectionInfo->Buffer.Length)) || (TCPHeaderIN->Flags & TCP_FLAG_PSH))\r
-                                                       {\r
-                                                               ConnectionInfo->Buffer.InUse = false;\r
-                                                               ConnectionInfo->Buffer.Ready = true;\r
-\r
-                                                               TCPHeaderOUT->Flags = TCP_FLAG_ACK;\r
-                                                               PacketResponse      = true;\r
-                                                       }\r
-                                               }\r
-                                               else\r
-                                               {\r
-                                                       /* Buffer is currently in use by the application, defer processing of the incoming packet */\r
-                                                       return NO_PROCESS;\r
-                                               }\r
-                                       }\r
-                                       \r
-                                       break;\r
-                               case TCP_Connection_Closing:\r
-                                               ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
-                                                                                                                          TCPHeaderIN->SourcePort);\r
-\r
-                                               TCPHeaderOUT->Flags = (TCP_FLAG_ACK | TCP_FLAG_FIN);\r
-                                               PacketResponse      = true;\r
-                                               \r
-                                               ConnectionInfo->Buffer.InUse = false;\r
-                                               \r
-                                               TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
-                                                                                          TCPHeaderIN->SourcePort, TCP_Connection_FINWait1);\r
-\r
-                                       break;\r
-                               case TCP_Connection_FINWait1:\r
-                                       if (TCPHeaderIN->Flags == (TCP_FLAG_FIN | TCP_FLAG_ACK))\r
-                                       {\r
-                                               ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
-                                                                                                                          TCPHeaderIN->SourcePort);\r
-\r
-                                               TCPHeaderOUT->Flags = TCP_FLAG_ACK;\r
-                                               PacketResponse      = true;\r
-\r
-                                               ConnectionInfo->SequenceNumberIn++;\r
-                                               ConnectionInfo->SequenceNumberOut++;\r
-                                               \r
-                                               TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
-                                                                                          TCPHeaderIN->SourcePort, TCP_Connection_Closed);\r
-                                       }\r
-                                       else if (TCPHeaderIN->Flags == TCP_FLAG_ACK)\r
-                                       {\r
-                                               TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
-                                                                                          TCPHeaderIN->SourcePort, TCP_Connection_FINWait2);\r
-                                       }\r
-                                       \r
-                                       break;\r
-                               case TCP_Connection_FINWait2:\r
-                                       if (TCPHeaderIN->Flags == (TCP_FLAG_FIN | TCP_FLAG_ACK))\r
-                                       {\r
-                                               ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
-                                                                                                                          TCPHeaderIN->SourcePort);\r
-\r
-                                               TCPHeaderOUT->Flags = TCP_FLAG_ACK;\r
-                                               PacketResponse      = true;\r
-\r
-                                               ConnectionInfo->SequenceNumberIn++;\r
-                                               ConnectionInfo->SequenceNumberOut++;\r
-                                               \r
-                                               TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
-                                                                                          TCPHeaderIN->SourcePort, TCP_Connection_Closed);\r
-                                       }\r
-                               \r
-                                       break;\r
-                               case TCP_Connection_CloseWait:\r
-                                       if (TCPHeaderIN->Flags == TCP_FLAG_ACK)\r
-                                       {\r
-                                               TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
-                                                                                          TCPHeaderIN->SourcePort, TCP_Connection_Closed);\r
-                                       }\r
-                                       \r
-                                       break;\r
-                       }\r
-               }\r
-       }\r
-       else\r
-       {\r
-               /* Port is not open, indicate via a RST/ACK response to the sender */\r
-               TCPHeaderOUT->Flags = (TCP_FLAG_RST | TCP_FLAG_ACK);                            \r
-               PacketResponse      = true;\r
-       }\r
-       \r
-       /* Check if we need to respond to the sent packet */\r
-       if (PacketResponse)\r
-       {\r
-               ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
-                                                      TCPHeaderIN->SourcePort);\r
-\r
-               TCPHeaderOUT->SourcePort           = TCPHeaderIN->DestinationPort;\r
-               TCPHeaderOUT->DestinationPort      = TCPHeaderIN->SourcePort;\r
-               TCPHeaderOUT->SequenceNumber       = SwapEndian_32(ConnectionInfo->SequenceNumberOut);\r
-               TCPHeaderOUT->AcknowledgmentNumber = SwapEndian_32(ConnectionInfo->SequenceNumberIn);\r
-               TCPHeaderOUT->DataOffset           = (sizeof(TCP_Header_t) / sizeof(uint32_t));\r
-               \r
-               if (!(ConnectionInfo->Buffer.InUse))\r
-                 TCPHeaderOUT->WindowSize         = SwapEndian_16(TCP_WINDOW_SIZE);\r
-               else\r
-                 TCPHeaderOUT->WindowSize         = SwapEndian_16(TCP_WINDOW_SIZE - ConnectionInfo->Buffer.Length);\r
-\r
-               TCPHeaderOUT->UrgentPointer        = 0;\r
-               TCPHeaderOUT->Checksum             = 0;\r
-               TCPHeaderOUT->Reserved             = 0;\r
-               \r
-               TCPHeaderOUT->Checksum             = TCP_Checksum16(TCPHeaderOUT, IPHeaderIN->DestinationAddress,\r
-                                                                   IPHeaderIN->SourceAddress, sizeof(TCP_Header_t));                                   \r
-\r
-               return sizeof(TCP_Header_t);    \r
-       }\r
-\r
-       return NO_RESPONSE;\r
-}\r
-\r
-/** Calculates the appropriate TCP checksum, consisting of the addition of the one's compliment of each word,\r
- *  complimented.\r
- *\r
- *  \param TCPHeaderOutStart  Pointer to the start of the packet's outgoing TCP header\r
- *  \param SourceAddress      Source protocol IP address of the outgoing IP header\r
- *  \param DestinationAddress DestinationAddress protocol IP address of the outgoing IP header\r
- *  \param TCPOutSize         Size in bytes of the TCP data header and payload\r
- *\r
- *  \return A 16-bit TCP checksum value\r
- */\r
-static uint16_t TCP_Checksum16(void* TCPHeaderOutStart, IP_Address_t SourceAddress,\r
-                               IP_Address_t DestinationAddress, uint16_t TCPOutSize)\r
-{\r
-       uint32_t Checksum = 0;\r
-       \r
-       /* TCP/IP checksums are the addition of the one's compliment of each word including the IP pseudo-header,\r
-          complimented */\r
-       \r
-       Checksum += ((uint16_t*)&SourceAddress)[0];\r
-       Checksum += ((uint16_t*)&SourceAddress)[1];\r
-       Checksum += ((uint16_t*)&DestinationAddress)[0];\r
-       Checksum += ((uint16_t*)&DestinationAddress)[1];\r
-       Checksum += SwapEndian_16(PROTOCOL_TCP);\r
-       Checksum += SwapEndian_16(TCPOutSize);\r
-\r
-       for (uint8_t CurrWord = 0; CurrWord < (TCPOutSize >> 1); CurrWord++)\r
-         Checksum += ((uint16_t*)TCPHeaderOutStart)[CurrWord];\r
-       \r
-       if (TCPOutSize & 0x01)\r
-         Checksum += (((uint16_t*)TCPHeaderOutStart)[TCPOutSize >> 1] & 0x00FF);\r
-         \r
-       while (Checksum & 0xFFFF0000)\r
-         Checksum = ((Checksum & 0xFFFF) + (Checksum >> 16));\r
-       \r
-       return ~Checksum;\r
-}\r