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:
Mon Jul 03 14:29:07 2017 +0000
Revision:
22:914b970356f0
Parent:
21:02c82594c8c0
Child:
37:793b39683406
Corrected NTP client function

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