Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: oldheating gps motorhome heating
tcp/tcp.c@73:43e3d7fb3d60, 2018-10-23 (annotated)
- Committer:
- andrewboyson
- Date:
- Tue Oct 23 06:46:50 2018 +0000
- Revision:
- 73:43e3d7fb3d60
- Parent:
- 72:19457bba58d0
- Child:
- 74:c3756bfa960e
Separated the TCP header into its own module
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
andrewboyson | 61:aad055f1b0d1 | 1 | #include <stdint.h> |
andrewboyson | 61:aad055f1b0d1 | 2 | #include <stdbool.h> |
andrewboyson | 61:aad055f1b0d1 | 3 | |
andrewboyson | 37:793b39683406 | 4 | #include "log.h" |
andrewboyson | 37:793b39683406 | 5 | #include "net.h" |
andrewboyson | 37:793b39683406 | 6 | #include "action.h" |
andrewboyson | 37:793b39683406 | 7 | #include "tcp.h" |
andrewboyson | 73:43e3d7fb3d60 | 8 | #include "tcphdr.h" |
andrewboyson | 37:793b39683406 | 9 | #include "tcb.h" |
andrewboyson | 37:793b39683406 | 10 | #include "ip4.h" |
andrewboyson | 37:793b39683406 | 11 | #include "dhcp.h" |
andrewboyson | 49:1a6336f2b3f9 | 12 | #include "http.h" |
andrewboyson | 71:736a5747ade1 | 13 | #include "led.h" |
andrewboyson | 10:f0854784e960 | 14 | |
andrewboyson | 73:43e3d7fb3d60 | 15 | |
andrewboyson | 73:43e3d7fb3d60 | 16 | //Payload variables |
andrewboyson | 73:43e3d7fb3d60 | 17 | static int dataLength; |
andrewboyson | 59:e0e556c8bd46 | 18 | static int maxMss = 0; |
andrewboyson | 10:f0854784e960 | 19 | |
andrewboyson | 52:fbc5a46b5e16 | 20 | bool TcpTrace = false; |
andrewboyson | 55:e64b8b47a2b6 | 21 | static bool doTrace = false; |
andrewboyson | 52:fbc5a46b5e16 | 22 | |
andrewboyson | 54:84ef2b29cf7e | 23 | static struct tcb* pTcb; |
andrewboyson | 54:84ef2b29cf7e | 24 | |
andrewboyson | 73:43e3d7fb3d60 | 25 | static void resetConnectionOut(char* message) |
andrewboyson | 55:e64b8b47a2b6 | 26 | { |
andrewboyson | 56:35117a8b5c65 | 27 | if (TcpTrace) |
andrewboyson | 56:35117a8b5c65 | 28 | { |
andrewboyson | 56:35117a8b5c65 | 29 | LogTime("TCP "); |
andrewboyson | 56:35117a8b5c65 | 30 | Log(message); |
andrewboyson | 56:35117a8b5c65 | 31 | Log("\r\n"); |
andrewboyson | 56:35117a8b5c65 | 32 | } |
andrewboyson | 55:e64b8b47a2b6 | 33 | dataLength = 0; |
andrewboyson | 73:43e3d7fb3d60 | 34 | TcpHdrClearOptions(); |
andrewboyson | 73:43e3d7fb3d60 | 35 | TcpHdrACK = false; |
andrewboyson | 73:43e3d7fb3d60 | 36 | TcpHdrPSH = false; |
andrewboyson | 73:43e3d7fb3d60 | 37 | TcpHdrRST = true; |
andrewboyson | 73:43e3d7fb3d60 | 38 | TcpHdrSYN = false; |
andrewboyson | 73:43e3d7fb3d60 | 39 | TcpHdrFIN = false; |
andrewboyson | 61:aad055f1b0d1 | 40 | |
andrewboyson | 61:aad055f1b0d1 | 41 | pTcb->state = TCB_EMPTY; |
andrewboyson | 55:e64b8b47a2b6 | 42 | } |
andrewboyson | 73:43e3d7fb3d60 | 43 | static void startConnectionIn(void *pPacket, void* pCachedRemIp) |
andrewboyson | 10:f0854784e960 | 44 | { |
andrewboyson | 73:43e3d7fb3d60 | 45 | TcpHdrReadOptions(pPacket); //Get the MSS |
andrewboyson | 73:43e3d7fb3d60 | 46 | if (TcpHdrMss > maxMss) TcpHdrMss = maxMss; |
andrewboyson | 73:43e3d7fb3d60 | 47 | |
andrewboyson | 73:43e3d7fb3d60 | 48 | pTcb->mss = TcpHdrMss; |
andrewboyson | 52:fbc5a46b5e16 | 49 | pTcb->state = TCB_SYN_RECEIVED; |
andrewboyson | 52:fbc5a46b5e16 | 50 | pTcb->elapsed = TcbElapsed; |
andrewboyson | 71:736a5747ade1 | 51 | pTcb->pIp = pCachedRemIp; |
andrewboyson | 73:43e3d7fb3d60 | 52 | pTcb->port = TcpHdrSrcPort; |
andrewboyson | 57:e0fb648acf48 | 53 | pTcb->hadFin = false; |
andrewboyson | 71:736a5747ade1 | 54 | } |
andrewboyson | 73:43e3d7fb3d60 | 55 | static void startConnectionOut(void* pPacket) |
andrewboyson | 71:736a5747ade1 | 56 | { |
andrewboyson | 73:43e3d7fb3d60 | 57 | TcpHdrMss = maxMss; //Ethernet 1500 - 20 - 20; or, in our case 768 - 20 - 20 |
andrewboyson | 73:43e3d7fb3d60 | 58 | TcpHdrWriteOptions(pPacket); |
andrewboyson | 10:f0854784e960 | 59 | dataLength = 0; |
andrewboyson | 10:f0854784e960 | 60 | |
andrewboyson | 73:43e3d7fb3d60 | 61 | TcpHdrACK = true; //Send ACK and SYN |
andrewboyson | 73:43e3d7fb3d60 | 62 | TcpHdrPSH = false; |
andrewboyson | 73:43e3d7fb3d60 | 63 | TcpHdrRST = false; |
andrewboyson | 73:43e3d7fb3d60 | 64 | TcpHdrSYN = true; |
andrewboyson | 73:43e3d7fb3d60 | 65 | TcpHdrFIN = false; |
andrewboyson | 10:f0854784e960 | 66 | } |
andrewboyson | 71:736a5747ade1 | 67 | static void establishConnectionIn() |
andrewboyson | 10:f0854784e960 | 68 | { |
andrewboyson | 56:35117a8b5c65 | 69 | pTcb->state = TCB_ESTABLISHED; |
andrewboyson | 56:35117a8b5c65 | 70 | pTcb->elapsed = TcbElapsed; |
andrewboyson | 57:e0fb648acf48 | 71 | pTcb->todo = 0; |
andrewboyson | 10:f0854784e960 | 72 | } |
andrewboyson | 73:43e3d7fb3d60 | 73 | static void handleEstablishedConnectionIn(void* pPacket) |
andrewboyson | 73:43e3d7fb3d60 | 74 | { |
andrewboyson | 73:43e3d7fb3d60 | 75 | char* pData = (char*)pPacket + TcpHdrSize; |
andrewboyson | 73:43e3d7fb3d60 | 76 | HttpHandleRequest(dataLength, pData, pTcb->recdBytes - 1, &pTcb->todo); |
andrewboyson | 71:736a5747ade1 | 77 | } |
andrewboyson | 73:43e3d7fb3d60 | 78 | static void handleEstablishedConnectionOut(void* pPacket) |
andrewboyson | 71:736a5747ade1 | 79 | { |
andrewboyson | 73:43e3d7fb3d60 | 80 | TcpHdrClearOptions(); |
andrewboyson | 73:43e3d7fb3d60 | 81 | char* pData = (char*)pPacket + TcpHdrSize; |
andrewboyson | 73:43e3d7fb3d60 | 82 | HttpSendReply(&dataLength, pData, pTcb->sentBytes - 1, TcpHdrMss, pTcb->todo); |
andrewboyson | 10:f0854784e960 | 83 | |
andrewboyson | 73:43e3d7fb3d60 | 84 | TcpHdrACK = true; //Send ACK |
andrewboyson | 73:43e3d7fb3d60 | 85 | TcpHdrRST = false; |
andrewboyson | 73:43e3d7fb3d60 | 86 | TcpHdrSYN = false; |
andrewboyson | 73:43e3d7fb3d60 | 87 | TcpHdrPSH = false; |
andrewboyson | 10:f0854784e960 | 88 | |
andrewboyson | 73:43e3d7fb3d60 | 89 | if (dataLength < TcpHdrMss) //If a part packet then there can be no more to send |
andrewboyson | 10:f0854784e960 | 90 | { |
andrewboyson | 73:43e3d7fb3d60 | 91 | TcpHdrFIN = true; //Inform the client that we have no more to send after this |
andrewboyson | 57:e0fb648acf48 | 92 | if (pTcb->hadFin) pTcb->state = TCB_ACK_WAIT; //Passive close |
andrewboyson | 57:e0fb648acf48 | 93 | else pTcb->state = TCB_FIN_WAIT; //Active close |
andrewboyson | 10:f0854784e960 | 94 | } |
andrewboyson | 56:35117a8b5c65 | 95 | else |
andrewboyson | 56:35117a8b5c65 | 96 | { |
andrewboyson | 73:43e3d7fb3d60 | 97 | TcpHdrFIN = false; |
andrewboyson | 56:35117a8b5c65 | 98 | } |
andrewboyson | 22:914b970356f0 | 99 | |
andrewboyson | 52:fbc5a46b5e16 | 100 | pTcb->elapsed = TcbElapsed; |
andrewboyson | 10:f0854784e960 | 101 | } |
andrewboyson | 71:736a5747ade1 | 102 | static void closeConnectionOut() |
andrewboyson | 56:35117a8b5c65 | 103 | { |
andrewboyson | 73:43e3d7fb3d60 | 104 | TcpHdrACK = true; //Send ACK |
andrewboyson | 73:43e3d7fb3d60 | 105 | TcpHdrPSH = false; |
andrewboyson | 73:43e3d7fb3d60 | 106 | TcpHdrRST = false; |
andrewboyson | 73:43e3d7fb3d60 | 107 | TcpHdrSYN = false; |
andrewboyson | 73:43e3d7fb3d60 | 108 | TcpHdrFIN = false; |
andrewboyson | 10:f0854784e960 | 109 | |
andrewboyson | 73:43e3d7fb3d60 | 110 | TcpHdrClearOptions(); |
andrewboyson | 10:f0854784e960 | 111 | dataLength = 0; |
andrewboyson | 10:f0854784e960 | 112 | |
andrewboyson | 57:e0fb648acf48 | 113 | pTcb->state = TCB_EMPTY; |
andrewboyson | 10:f0854784e960 | 114 | } |
andrewboyson | 10:f0854784e960 | 115 | |
andrewboyson | 71:736a5747ade1 | 116 | int TcpHandleReceivedPacket(void (*traceback)(void), int sizeRx, void* pPacketRx, int* pSizeTx, void* pPacketTx, int type, void* pCachedRemIp) |
andrewboyson | 10:f0854784e960 | 117 | { |
andrewboyson | 73:43e3d7fb3d60 | 118 | TcpHdrRead(pPacketRx); |
andrewboyson | 59:e0e556c8bd46 | 119 | |
andrewboyson | 73:43e3d7fb3d60 | 120 | dataLength = sizeRx - TcpHdrSize; |
andrewboyson | 73:43e3d7fb3d60 | 121 | maxMss = *pSizeTx - TcpHdrSize; |
andrewboyson | 73:43e3d7fb3d60 | 122 | |
andrewboyson | 57:e0fb648acf48 | 123 | doTrace = false; |
andrewboyson | 57:e0fb648acf48 | 124 | |
andrewboyson | 57:e0fb648acf48 | 125 | //Filter out unwanted links |
andrewboyson | 73:43e3d7fb3d60 | 126 | switch (TcpHdrDstPort) |
andrewboyson | 57:e0fb648acf48 | 127 | { |
andrewboyson | 57:e0fb648acf48 | 128 | case 80: |
andrewboyson | 57:e0fb648acf48 | 129 | if (HttpTrace) |
andrewboyson | 57:e0fb648acf48 | 130 | { |
andrewboyson | 57:e0fb648acf48 | 131 | if (NetTraceNewLine) Log("\r\n"); |
andrewboyson | 57:e0fb648acf48 | 132 | LogTime("HTTP server request\r\n"); |
andrewboyson | 57:e0fb648acf48 | 133 | doTrace = true; |
andrewboyson | 57:e0fb648acf48 | 134 | } |
andrewboyson | 57:e0fb648acf48 | 135 | break; |
andrewboyson | 57:e0fb648acf48 | 136 | |
andrewboyson | 57:e0fb648acf48 | 137 | default: |
andrewboyson | 57:e0fb648acf48 | 138 | if (TcpTrace) |
andrewboyson | 57:e0fb648acf48 | 139 | { |
andrewboyson | 57:e0fb648acf48 | 140 | if (NetTraceNewLine) Log("\r\n"); |
andrewboyson | 73:43e3d7fb3d60 | 141 | LogTimeF("TCP unknown port %d\r\n", TcpHdrDstPort); |
andrewboyson | 59:e0e556c8bd46 | 142 | if (NetTraceStack) traceback(); |
andrewboyson | 57:e0fb648acf48 | 143 | } |
andrewboyson | 57:e0fb648acf48 | 144 | return DO_NOTHING; //Ignore unknown ports |
andrewboyson | 57:e0fb648acf48 | 145 | } |
andrewboyson | 55:e64b8b47a2b6 | 146 | |
andrewboyson | 55:e64b8b47a2b6 | 147 | //Get the Transmission Control Block |
andrewboyson | 73:43e3d7fb3d60 | 148 | pTcb = TcbGetExisting(TcpHdrSrcPort); |
andrewboyson | 10:f0854784e960 | 149 | if (!pTcb) pTcb = TcbGetEmpty(); |
andrewboyson | 52:fbc5a46b5e16 | 150 | if (!pTcb) |
andrewboyson | 52:fbc5a46b5e16 | 151 | { |
andrewboyson | 52:fbc5a46b5e16 | 152 | if (TcpTrace) |
andrewboyson | 52:fbc5a46b5e16 | 153 | { |
andrewboyson | 57:e0fb648acf48 | 154 | if (NetTraceNewLine) Log("\r\n"); |
andrewboyson | 52:fbc5a46b5e16 | 155 | LogTime("TCP no more tcbs are available\r\n"); |
andrewboyson | 59:e0e556c8bd46 | 156 | if (NetTraceStack) traceback(); |
andrewboyson | 52:fbc5a46b5e16 | 157 | } |
andrewboyson | 52:fbc5a46b5e16 | 158 | return DO_NOTHING; //Bomb out if no more tcbs are available |
andrewboyson | 52:fbc5a46b5e16 | 159 | } |
andrewboyson | 10:f0854784e960 | 160 | |
andrewboyson | 55:e64b8b47a2b6 | 161 | //Handle request to reset |
andrewboyson | 73:43e3d7fb3d60 | 162 | if (TcpHdrRST) |
andrewboyson | 10:f0854784e960 | 163 | { |
andrewboyson | 57:e0fb648acf48 | 164 | if (TcpTrace) |
andrewboyson | 57:e0fb648acf48 | 165 | { |
andrewboyson | 57:e0fb648acf48 | 166 | if (NetTraceNewLine) Log("\r\n"); |
andrewboyson | 57:e0fb648acf48 | 167 | LogTime("TCP received reset - resetting TCB\r\n"); |
andrewboyson | 59:e0e556c8bd46 | 168 | if (NetTraceStack) traceback(); |
andrewboyson | 57:e0fb648acf48 | 169 | } |
andrewboyson | 57:e0fb648acf48 | 170 | pTcb->state = TCB_EMPTY; //Reset connection |
andrewboyson | 57:e0fb648acf48 | 171 | return DO_NOTHING; //Don't reply |
andrewboyson | 10:f0854784e960 | 172 | } |
andrewboyson | 55:e64b8b47a2b6 | 173 | |
andrewboyson | 55:e64b8b47a2b6 | 174 | //Handle request to synchronise |
andrewboyson | 73:43e3d7fb3d60 | 175 | if (TcpHdrSYN) |
andrewboyson | 55:e64b8b47a2b6 | 176 | { |
andrewboyson | 73:43e3d7fb3d60 | 177 | pTcb->recvIsn = TcpHdrSeqNum; |
andrewboyson | 72:19457bba58d0 | 178 | pTcb->sendIsn = TcbGetIsn(); |
andrewboyson | 57:e0fb648acf48 | 179 | pTcb->recdBytes = 0; |
andrewboyson | 57:e0fb648acf48 | 180 | pTcb->sentBytes = 0; |
andrewboyson | 55:e64b8b47a2b6 | 181 | } |
andrewboyson | 72:19457bba58d0 | 182 | else |
andrewboyson | 10:f0854784e960 | 183 | { |
andrewboyson | 73:43e3d7fb3d60 | 184 | pTcb->recdBytes = TcpHdrSeqNum - pTcb->recvIsn; |
andrewboyson | 73:43e3d7fb3d60 | 185 | pTcb->sentBytes = TcpHdrAckNum - pTcb->sendIsn; |
andrewboyson | 52:fbc5a46b5e16 | 186 | } |
andrewboyson | 72:19457bba58d0 | 187 | |
andrewboyson | 59:e0e556c8bd46 | 188 | if (doTrace && NetTraceStack) traceback(); //This will already include the TCP header |
andrewboyson | 55:e64b8b47a2b6 | 189 | |
andrewboyson | 73:43e3d7fb3d60 | 190 | if (TcpHdrSYN) pTcb->recdBytes += 1; //Add one to acknowledge the SYN |
andrewboyson | 73:43e3d7fb3d60 | 191 | pTcb->recdBytes += dataLength; //Add the number of bytes received |
andrewboyson | 73:43e3d7fb3d60 | 192 | if (TcpHdrFIN) pTcb->recdBytes += 1; //Add one to acknowledge the FIN |
andrewboyson | 10:f0854784e960 | 193 | |
andrewboyson | 10:f0854784e960 | 194 | switch (pTcb->state) |
andrewboyson | 10:f0854784e960 | 195 | { |
andrewboyson | 57:e0fb648acf48 | 196 | case TCB_EMPTY: |
andrewboyson | 73:43e3d7fb3d60 | 197 | if (!TcpHdrSYN) { resetConnectionOut("received other than a SYN when connection closed"); break; } |
andrewboyson | 73:43e3d7fb3d60 | 198 | startConnectionIn(pPacketRx, pCachedRemIp); |
andrewboyson | 73:43e3d7fb3d60 | 199 | startConnectionOut(pPacketTx); |
andrewboyson | 56:35117a8b5c65 | 200 | break; |
andrewboyson | 56:35117a8b5c65 | 201 | |
andrewboyson | 56:35117a8b5c65 | 202 | case TCB_SYN_RECEIVED: |
andrewboyson | 73:43e3d7fb3d60 | 203 | if (dataLength) { resetConnectionOut("data received before connection established"); break; } |
andrewboyson | 73:43e3d7fb3d60 | 204 | if (!TcpHdrACK) { resetConnectionOut("received other than an ACK before connection established"); break; } |
andrewboyson | 71:736a5747ade1 | 205 | establishConnectionIn(); |
andrewboyson | 56:35117a8b5c65 | 206 | return DO_NOTHING; |
andrewboyson | 56:35117a8b5c65 | 207 | |
andrewboyson | 56:35117a8b5c65 | 208 | case TCB_ESTABLISHED: |
andrewboyson | 73:43e3d7fb3d60 | 209 | if (!TcpHdrACK) { resetConnectionOut("received other than an ACK during established conection"); break; } |
andrewboyson | 73:43e3d7fb3d60 | 210 | if (TcpHdrFIN) pTcb->hadFin = true; //When reply is all sent only a passive close is needed |
andrewboyson | 73:43e3d7fb3d60 | 211 | handleEstablishedConnectionIn (pPacketRx); |
andrewboyson | 73:43e3d7fb3d60 | 212 | handleEstablishedConnectionOut(pPacketTx); |
andrewboyson | 56:35117a8b5c65 | 213 | break; |
andrewboyson | 56:35117a8b5c65 | 214 | |
andrewboyson | 57:e0fb648acf48 | 215 | case TCB_FIN_WAIT: //End of active close |
andrewboyson | 73:43e3d7fb3d60 | 216 | if (!TcpHdrFIN) return DO_NOTHING; //Ignore ACK to our FIN. Wait for FIN then close. |
andrewboyson | 71:736a5747ade1 | 217 | closeConnectionOut(); |
andrewboyson | 56:35117a8b5c65 | 218 | break; |
andrewboyson | 57:e0fb648acf48 | 219 | |
andrewboyson | 57:e0fb648acf48 | 220 | case TCB_ACK_WAIT: //End of passive close |
andrewboyson | 73:43e3d7fb3d60 | 221 | if (!TcpHdrACK) { resetConnectionOut("received other than an ACK when closing half open connection"); break; } |
andrewboyson | 57:e0fb648acf48 | 222 | pTcb->state = TCB_EMPTY; |
andrewboyson | 57:e0fb648acf48 | 223 | return DO_NOTHING; |
andrewboyson | 10:f0854784e960 | 224 | } |
andrewboyson | 10:f0854784e960 | 225 | |
andrewboyson | 72:19457bba58d0 | 226 | //Specify the start of the data being sent and acknowledge the data received |
andrewboyson | 73:43e3d7fb3d60 | 227 | TcpHdrAckNum = pTcb->recdBytes + pTcb->recvIsn; //Set up the acknowledgement field ready to send |
andrewboyson | 73:43e3d7fb3d60 | 228 | TcpHdrSeqNum = pTcb->sentBytes + pTcb->sendIsn; //Set up the start of the message before adding the bytes sent |
andrewboyson | 57:e0fb648acf48 | 229 | |
andrewboyson | 57:e0fb648acf48 | 230 | //Keep a record of where we expect the next packet send to start |
andrewboyson | 73:43e3d7fb3d60 | 231 | if (TcpHdrSYN) pTcb->sentBytes += 1; //Add one to acknowledge the SYN |
andrewboyson | 73:43e3d7fb3d60 | 232 | pTcb->sentBytes += dataLength; //Record the next sequence number |
andrewboyson | 73:43e3d7fb3d60 | 233 | if (TcpHdrFIN) pTcb->sentBytes += 1; //Add one to acknowledge the FIN |
andrewboyson | 55:e64b8b47a2b6 | 234 | |
andrewboyson | 57:e0fb648acf48 | 235 | //Swap the ports for the reply |
andrewboyson | 73:43e3d7fb3d60 | 236 | TcpHdrSrcPort = TcpHdrDstPort; |
andrewboyson | 73:43e3d7fb3d60 | 237 | TcpHdrDstPort = pTcb->port; |
andrewboyson | 10:f0854784e960 | 238 | |
andrewboyson | 62:9b8c1e1761b6 | 239 | //Specify the receive window size to not throttle |
andrewboyson | 73:43e3d7fb3d60 | 240 | TcpHdrWindow = 4000; |
andrewboyson | 62:9b8c1e1761b6 | 241 | |
andrewboyson | 57:e0fb648acf48 | 242 | //Calculate the size of the reply |
andrewboyson | 73:43e3d7fb3d60 | 243 | *pSizeTx = TcpHdrSize + dataLength; |
andrewboyson | 54:84ef2b29cf7e | 244 | |
andrewboyson | 55:e64b8b47a2b6 | 245 | return ActionMakeFromDestAndTrace(UNICAST, doTrace && NetTraceStack); |
andrewboyson | 71:736a5747ade1 | 246 | } |
andrewboyson | 10:f0854784e960 | 247 | |
andrewboyson | 71:736a5747ade1 | 248 | int TcpPollForPacketToSend(int* pSize, void* pPacket, int type, void* pCachedRemIp) |
andrewboyson | 71:736a5747ade1 | 249 | { |
andrewboyson | 73:43e3d7fb3d60 | 250 | int dataLength = *pSize - TcpHdrSize; |
andrewboyson | 71:736a5747ade1 | 251 | |
andrewboyson | 71:736a5747ade1 | 252 | int action = DO_NOTHING; |
andrewboyson | 71:736a5747ade1 | 253 | |
andrewboyson | 73:43e3d7fb3d60 | 254 | TcpHdrSrcPort = TcpHdrDstPort; |
andrewboyson | 73:43e3d7fb3d60 | 255 | TcpHdrDstPort = pTcb->port; |
andrewboyson | 71:736a5747ade1 | 256 | |
andrewboyson | 73:43e3d7fb3d60 | 257 | *pSize = TcpHdrSize + dataLength; |
andrewboyson | 71:736a5747ade1 | 258 | return action; |
andrewboyson | 10:f0854784e960 | 259 | } |
andrewboyson | 71:736a5747ade1 | 260 |