A stack which works with or without an Mbed os library. Provides IPv4 or IPv6 with a full 1500 byte buffer.

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Sun Apr 16 14:21:55 2017 +0000
Revision:
10:f0854784e960
Child:
21:02c82594c8c0
MDNS and LLMNR now working.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 10:f0854784e960 1 #include "mbed.h"
andrewboyson 10:f0854784e960 2 #include "log.h"
andrewboyson 10:f0854784e960 3 #include "net.h"
andrewboyson 10:f0854784e960 4 #include "tcp.h"
andrewboyson 10:f0854784e960 5 #include "tcb.h"
andrewboyson 10:f0854784e960 6 #include "http.h"
andrewboyson 10:f0854784e960 7 #include "ip4.h"
andrewboyson 10:f0854784e960 8 #include "dhcp.h"
andrewboyson 10:f0854784e960 9
andrewboyson 10:f0854784e960 10 #define MAX_MSS 536 //This is 576 - 20 - 20
andrewboyson 10:f0854784e960 11
andrewboyson 10:f0854784e960 12 __packed struct header
andrewboyson 10:f0854784e960 13 {
andrewboyson 10:f0854784e960 14 uint16_t srcPort;
andrewboyson 10:f0854784e960 15 uint16_t dstPort;
andrewboyson 10:f0854784e960 16 uint32_t seqnum;
andrewboyson 10:f0854784e960 17 uint32_t acknum;
andrewboyson 10:f0854784e960 18 uint8_t dataOffset;
andrewboyson 10:f0854784e960 19 uint8_t flags;
andrewboyson 10:f0854784e960 20 uint16_t window;
andrewboyson 10:f0854784e960 21 uint16_t checksum;
andrewboyson 10:f0854784e960 22 uint16_t urgent;
andrewboyson 10:f0854784e960 23 };
andrewboyson 10:f0854784e960 24
andrewboyson 10:f0854784e960 25 uint32_t now = 0;
andrewboyson 10:f0854784e960 26 static void ticked()
andrewboyson 10:f0854784e960 27 {
andrewboyson 10:f0854784e960 28 now++;
andrewboyson 10:f0854784e960 29 TcbReap(now);
andrewboyson 10:f0854784e960 30 }
andrewboyson 10:f0854784e960 31 static Ticker ticker;
andrewboyson 10:f0854784e960 32
andrewboyson 10:f0854784e960 33 void TcpInit()
andrewboyson 10:f0854784e960 34 {
andrewboyson 10:f0854784e960 35 ticker.attach(&ticked, 1);
andrewboyson 10:f0854784e960 36 TcbInit();
andrewboyson 10:f0854784e960 37 }
andrewboyson 10:f0854784e960 38
andrewboyson 10:f0854784e960 39 //Header variables
andrewboyson 10:f0854784e960 40
andrewboyson 10:f0854784e960 41 static uint16_t srcPort;
andrewboyson 10:f0854784e960 42 static uint16_t dstPort;
andrewboyson 10:f0854784e960 43 static uint32_t seqnum;
andrewboyson 10:f0854784e960 44 static uint32_t acknum;
andrewboyson 10:f0854784e960 45 static int headersize;
andrewboyson 10:f0854784e960 46 static uint8_t flags;
andrewboyson 10:f0854784e960 47 static bool URG; //indicates that the Urgent pointer field is significant
andrewboyson 10:f0854784e960 48 static bool ACK; //indicates that the Acknowledgment field is significant. All packets after the initial SYN packet sent by the client should have this flag set.
andrewboyson 10:f0854784e960 49 static bool PSH; //Push function. Asks to push the buffered data to the receiving application.
andrewboyson 10:f0854784e960 50 static bool RST; //Reset the connection
andrewboyson 10:f0854784e960 51 static bool SYN; //Synchronize sequence numbers. Only the first packet sent from each end should have this flag set. Some other flags and fields change meaning based on this flag, and some are only valid for when it is set, and others when it is clear.
andrewboyson 10:f0854784e960 52 static bool FIN; //No more data from sender
andrewboyson 10:f0854784e960 53
andrewboyson 10:f0854784e960 54 static uint16_t window;
andrewboyson 10:f0854784e960 55 static uint16_t checksum;
andrewboyson 10:f0854784e960 56 static uint16_t urgent;
andrewboyson 10:f0854784e960 57 static int optionLength;
andrewboyson 10:f0854784e960 58
andrewboyson 10:f0854784e960 59 static char* pOptions;
andrewboyson 10:f0854784e960 60 static void* pData;
andrewboyson 10:f0854784e960 61 static int dataLength;
andrewboyson 10:f0854784e960 62 static uint16_t mss;
andrewboyson 10:f0854784e960 63
andrewboyson 10:f0854784e960 64 void TcpLogHeader(char* title, void* pPacket, uint16_t calculatedChecksum)
andrewboyson 10:f0854784e960 65 {
andrewboyson 10:f0854784e960 66 LogTimeF("TCP %s\r\n", title);
andrewboyson 10:f0854784e960 67 LogF(" Source port %hu\r\n", srcPort);
andrewboyson 10:f0854784e960 68 LogF(" Destination port %hu\r\n", dstPort);
andrewboyson 10:f0854784e960 69 LogF(" Sequence number %u\r\n", seqnum);
andrewboyson 10:f0854784e960 70 LogF(" Ack number %u\r\n", acknum);
andrewboyson 10:f0854784e960 71 LogF(" Header size %u\r\n", headersize);
andrewboyson 10:f0854784e960 72 LogF(" Flags %02X", flags);
andrewboyson 10:f0854784e960 73 if (URG) LogF(" URG");
andrewboyson 10:f0854784e960 74 if (ACK) LogF(" ACK");
andrewboyson 10:f0854784e960 75 if (PSH) LogF(" PSH");
andrewboyson 10:f0854784e960 76 if (RST) LogF(" RST");
andrewboyson 10:f0854784e960 77 if (SYN) LogF(" SYN");
andrewboyson 10:f0854784e960 78 if (FIN) LogF(" FIN");
andrewboyson 10:f0854784e960 79 LogF("\r\n");
andrewboyson 10:f0854784e960 80 LogF(" Window %hu\r\n", window);
andrewboyson 10:f0854784e960 81 LogF(" Checksum (hex) %04hX\r\n", checksum);
andrewboyson 10:f0854784e960 82 LogF(" Calculated (hex) %04hX\r\n", calculatedChecksum);
andrewboyson 10:f0854784e960 83 LogF(" Urgent pointer %hu\r\n", urgent);
andrewboyson 10:f0854784e960 84 LogF(" Option length %d\r\n", optionLength);
andrewboyson 10:f0854784e960 85 LogF(" Data length %d\r\n", dataLength);
andrewboyson 10:f0854784e960 86 }
andrewboyson 10:f0854784e960 87 void TcpAddChecksum(void* pPacket, uint16_t checksum)
andrewboyson 10:f0854784e960 88 {
andrewboyson 10:f0854784e960 89 struct header* pHeader = (header*)pPacket;
andrewboyson 10:f0854784e960 90 pHeader->checksum = checksum;
andrewboyson 10:f0854784e960 91 }
andrewboyson 10:f0854784e960 92 static void readOptions()
andrewboyson 10:f0854784e960 93 {
andrewboyson 10:f0854784e960 94 mss = 536; //default MSS for IPv4 [576 - 20(TCP) - 20(IP)];
andrewboyson 10:f0854784e960 95 for (char* p = pOptions; p < pOptions + optionLength; p++)
andrewboyson 10:f0854784e960 96 {
andrewboyson 10:f0854784e960 97 switch (*p)
andrewboyson 10:f0854784e960 98 {
andrewboyson 10:f0854784e960 99 case 0: break; //End of options - used to pad to 32 bit boundary
andrewboyson 10:f0854784e960 100 case 1: break; //NOP, padding - optional
andrewboyson 10:f0854784e960 101 case 2:
andrewboyson 10:f0854784e960 102 p++;
andrewboyson 10:f0854784e960 103 if (*p != 4) LogTimeF("MSS option width %d when expected 4\r\n", *p);
andrewboyson 10:f0854784e960 104 p++;
andrewboyson 10:f0854784e960 105 mss = ((uint16_t)*p) << 8;
andrewboyson 10:f0854784e960 106 p++;
andrewboyson 10:f0854784e960 107 mss += *p;
andrewboyson 10:f0854784e960 108 return;
andrewboyson 10:f0854784e960 109 default: LogTimeF("Unrecognised TCP option %d\r\n", *p);
andrewboyson 10:f0854784e960 110 }
andrewboyson 10:f0854784e960 111 }
andrewboyson 10:f0854784e960 112 if (mss > MAX_MSS) mss = MAX_MSS;
andrewboyson 10:f0854784e960 113 }
andrewboyson 10:f0854784e960 114 static void writeOptions()
andrewboyson 10:f0854784e960 115 {
andrewboyson 10:f0854784e960 116 pOptions[0] = 2;
andrewboyson 10:f0854784e960 117 pOptions[1] = 4;
andrewboyson 10:f0854784e960 118 pOptions[2] = mss >> 8;
andrewboyson 10:f0854784e960 119 pOptions[3] = mss & 0xFF;
andrewboyson 10:f0854784e960 120 optionLength = 4;
andrewboyson 10:f0854784e960 121 }
andrewboyson 10:f0854784e960 122
andrewboyson 10:f0854784e960 123 void TcpReadHeader(void* pPacket, uint16_t size)
andrewboyson 10:f0854784e960 124 {
andrewboyson 10:f0854784e960 125 struct header* pHeader = (header*)pPacket;
andrewboyson 10:f0854784e960 126
andrewboyson 10:f0854784e960 127 srcPort = NetToHost16(pHeader->srcPort);
andrewboyson 10:f0854784e960 128 dstPort = NetToHost16(pHeader->dstPort);
andrewboyson 10:f0854784e960 129 seqnum = NetToHost32(pHeader->seqnum);
andrewboyson 10:f0854784e960 130 acknum = NetToHost32(pHeader->acknum);
andrewboyson 10:f0854784e960 131 headersize = (pHeader->dataOffset >> 2) & 0xFC; //Same as right shifting by 4 bits and multiplying by 4
andrewboyson 10:f0854784e960 132 flags = pHeader->flags;
andrewboyson 10:f0854784e960 133 URG = flags & 0x20; //indicates that the Urgent pointer field is significant
andrewboyson 10:f0854784e960 134 ACK = flags & 0x10; //indicates that the Acknowledgment field is significant. All packets after the initial SYN packet sent by the client should have this flag set.
andrewboyson 10:f0854784e960 135 PSH = flags & 0x08; //Push function. Asks to push the buffered data to the receiving application.
andrewboyson 10:f0854784e960 136 RST = flags & 0x04; //Reset the connection
andrewboyson 10:f0854784e960 137 SYN = flags & 0x02; //Synchronize sequence numbers. Only the first packet sent from each end should have this flag set. Some other flags and fields change meaning based on this flag, and some are only valid for when it is set, and others when it is clear.
andrewboyson 10:f0854784e960 138 FIN = flags & 0x01; //No more data from sender
andrewboyson 10:f0854784e960 139
andrewboyson 10:f0854784e960 140 window = NetToHost16(pHeader->window);
andrewboyson 10:f0854784e960 141 checksum = NetToHost16(pHeader->checksum);
andrewboyson 10:f0854784e960 142 urgent = NetToHost16(pHeader->urgent);
andrewboyson 10:f0854784e960 143 pOptions = (char*)pPacket + 20;
andrewboyson 10:f0854784e960 144 optionLength = headersize - 20;
andrewboyson 10:f0854784e960 145
andrewboyson 10:f0854784e960 146 pData = (char*)pPacket + headersize;
andrewboyson 10:f0854784e960 147 dataLength = size - headersize;
andrewboyson 10:f0854784e960 148 }
andrewboyson 10:f0854784e960 149
andrewboyson 10:f0854784e960 150 void TcpMakeHeader(int size, void* pPacket)
andrewboyson 10:f0854784e960 151 {
andrewboyson 10:f0854784e960 152 struct header* pHeader = (header*)pPacket;
andrewboyson 10:f0854784e960 153
andrewboyson 10:f0854784e960 154 pHeader->dstPort = NetToHost16(dstPort);
andrewboyson 10:f0854784e960 155 pHeader->srcPort = NetToHost16(srcPort);
andrewboyson 10:f0854784e960 156 pHeader->seqnum = NetToHost32(seqnum); //This is the sequence number of the first byte of this message
andrewboyson 10:f0854784e960 157 pHeader->acknum = NetToHost32(acknum); //This is the sequence number we expect in the next message
andrewboyson 10:f0854784e960 158 pHeader->dataOffset = headersize << 2; //Same as dividing by 4 to get bytes and left shifting by 4 bits
andrewboyson 10:f0854784e960 159 flags = 0;
andrewboyson 10:f0854784e960 160 if(URG) flags |= 0x20; //indicates that the Urgent pointer field is significant
andrewboyson 10:f0854784e960 161 if(ACK) flags |= 0x10; //indicates that the Acknowledgment field is significant. All packets after the initial SYN packet sent by the client should have this flag set.
andrewboyson 10:f0854784e960 162 if(PSH) flags |= 0x08; //Push function. Asks to push the buffered data to the receiving application.
andrewboyson 10:f0854784e960 163 if(RST) flags |= 0x04; //Reset the connection
andrewboyson 10:f0854784e960 164 if(SYN) flags |= 0x02; //Synchronize sequence numbers. Only the first packet sent from each end should have this flag set. Some other flags and fields change meaning based on this flag, and some are only valid for when it is set, and others when it is clear.
andrewboyson 10:f0854784e960 165 if(FIN) flags |= 0x01; //No more data from sender
andrewboyson 10:f0854784e960 166 pHeader->flags = flags;
andrewboyson 10:f0854784e960 167 pHeader->window = NetToHost16(window);
andrewboyson 10:f0854784e960 168 pHeader->urgent = NetToHost16(urgent);
andrewboyson 10:f0854784e960 169
andrewboyson 10:f0854784e960 170 pHeader->checksum = 0;
andrewboyson 10:f0854784e960 171 }
andrewboyson 10:f0854784e960 172 static int stateClosed(struct tcb* pTcb)
andrewboyson 10:f0854784e960 173 {
andrewboyson 10:f0854784e960 174 if (!SYN) //Reset if anything other than a request to establish conection from client
andrewboyson 10:f0854784e960 175 {
andrewboyson 10:f0854784e960 176 dataLength = 0;
andrewboyson 10:f0854784e960 177 headersize = 20;
andrewboyson 10:f0854784e960 178 seqnum = acknum;
andrewboyson 10:f0854784e960 179 acknum = 0;
andrewboyson 10:f0854784e960 180 ACK = false; //Send RST
andrewboyson 10:f0854784e960 181 PSH = false;
andrewboyson 10:f0854784e960 182 RST = true;
andrewboyson 10:f0854784e960 183 SYN = false;
andrewboyson 10:f0854784e960 184 FIN = false;
andrewboyson 10:f0854784e960 185 return 1;
andrewboyson 10:f0854784e960 186 }
andrewboyson 10:f0854784e960 187
andrewboyson 10:f0854784e960 188 readOptions(); //Get the MSS
andrewboyson 10:f0854784e960 189 pTcb->mss = mss;
andrewboyson 10:f0854784e960 190
andrewboyson 10:f0854784e960 191 pTcb->state = TCB_SYN_RECEIVED;
andrewboyson 10:f0854784e960 192 pTcb->timer = now;
andrewboyson 10:f0854784e960 193 pTcb->port = srcPort;
andrewboyson 10:f0854784e960 194 pTcb->locIsn = TcbGetIsn();
andrewboyson 10:f0854784e960 195 pTcb->locSeq = pTcb->locIsn;
andrewboyson 10:f0854784e960 196 pTcb->remIsn = seqnum;
andrewboyson 10:f0854784e960 197 pTcb->remSeq = pTcb->remIsn;
andrewboyson 10:f0854784e960 198
andrewboyson 10:f0854784e960 199 pTcb->remSeq += 1; //Add one to acknowledge the SYN
andrewboyson 10:f0854784e960 200 acknum = pTcb->remSeq;
andrewboyson 10:f0854784e960 201
andrewboyson 10:f0854784e960 202 seqnum = pTcb->locSeq; //Set the sequence number to the first byte of this message
andrewboyson 10:f0854784e960 203 pTcb->locSeq += 1; //Add one to the next sequence number as we are sending a SYN
andrewboyson 10:f0854784e960 204
andrewboyson 10:f0854784e960 205 dataLength = 0;
andrewboyson 10:f0854784e960 206
andrewboyson 10:f0854784e960 207 mss = MAX_MSS; //Ethernet 1500 - 20 - 20; or, in our case 768 - 20 - 20
andrewboyson 10:f0854784e960 208 writeOptions();
andrewboyson 10:f0854784e960 209 headersize = 24; //20 header plus 4 option
andrewboyson 10:f0854784e960 210
andrewboyson 10:f0854784e960 211 ACK = true; //Send ACK and SYN
andrewboyson 10:f0854784e960 212 PSH = false;
andrewboyson 10:f0854784e960 213 RST = false;
andrewboyson 10:f0854784e960 214 SYN = true;
andrewboyson 10:f0854784e960 215 FIN = false;
andrewboyson 10:f0854784e960 216
andrewboyson 10:f0854784e960 217 return 1;
andrewboyson 10:f0854784e960 218 }
andrewboyson 10:f0854784e960 219 static int stateSynReceived(struct tcb* pTcb)
andrewboyson 10:f0854784e960 220 {
andrewboyson 10:f0854784e960 221 if (dataLength) LogTimeF("%d bytes data received before TCB established\r\n", dataLength);
andrewboyson 10:f0854784e960 222 if (ACK)
andrewboyson 10:f0854784e960 223 {
andrewboyson 10:f0854784e960 224 pTcb->state = TCB_ESTABLISHED;
andrewboyson 10:f0854784e960 225 pTcb->timer = now;
andrewboyson 10:f0854784e960 226 pTcb->tag = 0;
andrewboyson 10:f0854784e960 227 }
andrewboyson 10:f0854784e960 228 return 0;
andrewboyson 10:f0854784e960 229 }
andrewboyson 10:f0854784e960 230 static int stateEstablished(struct tcb* pTcb)
andrewboyson 10:f0854784e960 231 {
andrewboyson 10:f0854784e960 232 if (!ACK) return 0; //Ignore any packets which don't contain an ACK
andrewboyson 10:f0854784e960 233
andrewboyson 10:f0854784e960 234 //Handle reception of data
andrewboyson 10:f0854784e960 235 if (dataLength)
andrewboyson 10:f0854784e960 236 {
andrewboyson 10:f0854784e960 237 pTcb->tag = HttpRequest(seqnum - pTcb->remIsn - 1, dataLength, (char*)pData);
andrewboyson 10:f0854784e960 238 pTcb->remSeq = seqnum + dataLength;
andrewboyson 10:f0854784e960 239 }
andrewboyson 10:f0854784e960 240 acknum = pTcb->remSeq; //Set the ack num to the next byte expected from the client
andrewboyson 10:f0854784e960 241
andrewboyson 10:f0854784e960 242
andrewboyson 10:f0854784e960 243 //Rearrange the buffers
andrewboyson 10:f0854784e960 244 headersize = 20;
andrewboyson 10:f0854784e960 245 pData = pOptions;
andrewboyson 10:f0854784e960 246
andrewboyson 10:f0854784e960 247 //Handle sending of any data
andrewboyson 10:f0854784e960 248 dataLength = HttpResponse(pTcb->locSeq - pTcb->locIsn - 1, mss, (char*)pData, pTcb->tag);
andrewboyson 10:f0854784e960 249
andrewboyson 10:f0854784e960 250 seqnum = pTcb->locSeq; //Set the sequence number to the first byte of this message
andrewboyson 10:f0854784e960 251
andrewboyson 10:f0854784e960 252
andrewboyson 10:f0854784e960 253 ACK = true; //Send ACK
andrewboyson 10:f0854784e960 254 RST = false;
andrewboyson 10:f0854784e960 255 SYN = false;
andrewboyson 10:f0854784e960 256
andrewboyson 10:f0854784e960 257 if (dataLength)
andrewboyson 10:f0854784e960 258 {
andrewboyson 10:f0854784e960 259 pTcb->locSeq += dataLength; //Record the next sequence number
andrewboyson 10:f0854784e960 260 PSH = false;
andrewboyson 10:f0854784e960 261 FIN = false;
andrewboyson 10:f0854784e960 262 }
andrewboyson 10:f0854784e960 263 else
andrewboyson 10:f0854784e960 264 {
andrewboyson 10:f0854784e960 265 pTcb->locSeq += 1; //Record the FIN
andrewboyson 10:f0854784e960 266 PSH = true;
andrewboyson 10:f0854784e960 267 FIN = true;
andrewboyson 10:f0854784e960 268 pTcb->state = TCB_CLOSING; //Start closing
andrewboyson 10:f0854784e960 269 }
andrewboyson 10:f0854784e960 270 pTcb->timer = now;
andrewboyson 10:f0854784e960 271 return 1;
andrewboyson 10:f0854784e960 272 }
andrewboyson 10:f0854784e960 273 static int stateClosing(struct tcb* pTcb)
andrewboyson 10:f0854784e960 274 {
andrewboyson 10:f0854784e960 275 if (!FIN) return 0; //Ignore any packets which don't contain a FIN
andrewboyson 10:f0854784e960 276
andrewboyson 10:f0854784e960 277 pTcb->remSeq += 1; //Add one to acknowledge the FIN
andrewboyson 10:f0854784e960 278 acknum = pTcb->remSeq;
andrewboyson 10:f0854784e960 279
andrewboyson 10:f0854784e960 280 seqnum = pTcb->locSeq; //Set the sequence number to the first byte of this message
andrewboyson 10:f0854784e960 281 //but don't change it for the next
andrewboyson 10:f0854784e960 282
andrewboyson 10:f0854784e960 283 ACK = true; //Send ACK
andrewboyson 10:f0854784e960 284 PSH = false;
andrewboyson 10:f0854784e960 285 RST = false;
andrewboyson 10:f0854784e960 286 SYN = false;
andrewboyson 10:f0854784e960 287 FIN = false;
andrewboyson 10:f0854784e960 288
andrewboyson 10:f0854784e960 289 headersize = 20;
andrewboyson 10:f0854784e960 290 dataLength = 0;
andrewboyson 10:f0854784e960 291
andrewboyson 10:f0854784e960 292 pTcb->state = TCB_CLOSED;
andrewboyson 10:f0854784e960 293
andrewboyson 10:f0854784e960 294 return 1;
andrewboyson 10:f0854784e960 295 }
andrewboyson 10:f0854784e960 296
andrewboyson 10:f0854784e960 297 int TcpHandleReceivedPacket(int* pSize, void* pPacket)
andrewboyson 10:f0854784e960 298 {
andrewboyson 10:f0854784e960 299 struct tcb* pTcb = TcbGetExisting(srcPort);
andrewboyson 10:f0854784e960 300 if (!pTcb) pTcb = TcbGetEmpty();
andrewboyson 10:f0854784e960 301 if (!pTcb) return DO_NOTHING; //Bomb out if no more tcbs are available
andrewboyson 10:f0854784e960 302
andrewboyson 10:f0854784e960 303 if (RST)
andrewboyson 10:f0854784e960 304 {
andrewboyson 10:f0854784e960 305 pTcb->state = TCB_CLOSED; //Reset connection
andrewboyson 10:f0854784e960 306 return DO_NOTHING; //Bomb out
andrewboyson 10:f0854784e960 307 }
andrewboyson 10:f0854784e960 308
andrewboyson 10:f0854784e960 309 switch (dstPort)
andrewboyson 10:f0854784e960 310 {
andrewboyson 10:f0854784e960 311 case 80: break;
andrewboyson 10:f0854784e960 312 default: return DO_NOTHING; //This needs to become a reset
andrewboyson 10:f0854784e960 313 }
andrewboyson 10:f0854784e960 314
andrewboyson 10:f0854784e960 315 //Drop duplicate packets
andrewboyson 10:f0854784e960 316 //if (!TCB_CLOSED && (int32_t)(seqnum - pTcb->remSeq) < 0)
andrewboyson 10:f0854784e960 317 //{
andrewboyson 10:f0854784e960 318 // LogTimeF("Dropped duplicate seq num=%d expected=%d packet length %d from port %u\r\n", seqnum, pTcb->remSeq, size, srcPort);
andrewboyson 10:f0854784e960 319 // return IP4_DO_NOTHING;
andrewboyson 10:f0854784e960 320 //}
andrewboyson 10:f0854784e960 321
andrewboyson 10:f0854784e960 322 switch (pTcb->state)
andrewboyson 10:f0854784e960 323 {
andrewboyson 10:f0854784e960 324 case TCB_CLOSED: if (stateClosed (pTcb)) break; return DO_NOTHING;
andrewboyson 10:f0854784e960 325 case TCB_SYN_RECEIVED: if (stateSynReceived(pTcb)) break; return DO_NOTHING;
andrewboyson 10:f0854784e960 326 case TCB_ESTABLISHED: if (stateEstablished(pTcb)) break; return DO_NOTHING;
andrewboyson 10:f0854784e960 327 case TCB_CLOSING: if (stateClosing (pTcb)) break; return DO_NOTHING;
andrewboyson 10:f0854784e960 328 }
andrewboyson 10:f0854784e960 329
andrewboyson 10:f0854784e960 330 srcPort = dstPort;
andrewboyson 10:f0854784e960 331 dstPort = pTcb->port;
andrewboyson 10:f0854784e960 332
andrewboyson 10:f0854784e960 333 *pSize = dataLength + headersize;
andrewboyson 10:f0854784e960 334 return UNICAST;
andrewboyson 10:f0854784e960 335
andrewboyson 10:f0854784e960 336 }