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
tcp/tcprecv.c@75:603b10404183, 2018-10-30 (annotated)
- Committer:
- andrewboyson
- Date:
- Tue Oct 30 22:11:22 2018 +0000
- Revision:
- 75:603b10404183
- Parent:
- 74:c3756bfa960e
- Child:
- 76:17534bde28d3
A lot of tidying up and prevented requests other than the first packet from doing anything.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
andrewboyson | 74:c3756bfa960e | 1 | #include <stdint.h> |
andrewboyson | 74:c3756bfa960e | 2 | #include <stdbool.h> |
andrewboyson | 75:603b10404183 | 3 | #include <stdarg.h> |
andrewboyson | 74:c3756bfa960e | 4 | |
andrewboyson | 74:c3756bfa960e | 5 | #include "log.h" |
andrewboyson | 74:c3756bfa960e | 6 | #include "net.h" |
andrewboyson | 74:c3756bfa960e | 7 | #include "action.h" |
andrewboyson | 74:c3756bfa960e | 8 | #include "tcp.h" |
andrewboyson | 74:c3756bfa960e | 9 | #include "tcphdr.h" |
andrewboyson | 74:c3756bfa960e | 10 | #include "tcpsend.h" |
andrewboyson | 74:c3756bfa960e | 11 | #include "tcb.h" |
andrewboyson | 74:c3756bfa960e | 12 | #include "ip4.h" |
andrewboyson | 74:c3756bfa960e | 13 | #include "dhcp.h" |
andrewboyson | 74:c3756bfa960e | 14 | #include "http.h" |
andrewboyson | 74:c3756bfa960e | 15 | #include "led.h" |
andrewboyson | 74:c3756bfa960e | 16 | |
andrewboyson | 74:c3756bfa960e | 17 | //Payload variables |
andrewboyson | 74:c3756bfa960e | 18 | static struct tcb* pTcb; |
andrewboyson | 74:c3756bfa960e | 19 | |
andrewboyson | 74:c3756bfa960e | 20 | static void logReset(char* message) |
andrewboyson | 74:c3756bfa960e | 21 | { |
andrewboyson | 74:c3756bfa960e | 22 | if (TcpTrace) { LogTime("TCP sent RST - "); Log(message); Log("\r\n"); } |
andrewboyson | 74:c3756bfa960e | 23 | } |
andrewboyson | 74:c3756bfa960e | 24 | |
andrewboyson | 75:603b10404183 | 25 | static void logTraceBack(void (*traceback)(void), char* fmt, ...) |
andrewboyson | 75:603b10404183 | 26 | { |
andrewboyson | 75:603b10404183 | 27 | if (TcpTrace) |
andrewboyson | 75:603b10404183 | 28 | { |
andrewboyson | 75:603b10404183 | 29 | if (NetTraceNewLine) Log("\r\n"); |
andrewboyson | 75:603b10404183 | 30 | va_list argptr; |
andrewboyson | 75:603b10404183 | 31 | va_start(argptr, fmt); |
andrewboyson | 75:603b10404183 | 32 | LogV(fmt, argptr); |
andrewboyson | 75:603b10404183 | 33 | va_end(argptr); |
andrewboyson | 75:603b10404183 | 34 | Log("\r\n"); |
andrewboyson | 75:603b10404183 | 35 | if (NetTraceStack) traceback(); |
andrewboyson | 75:603b10404183 | 36 | } |
andrewboyson | 75:603b10404183 | 37 | } |
andrewboyson | 75:603b10404183 | 38 | |
andrewboyson | 74:c3756bfa960e | 39 | static void startConnection(void *pPacket, int ipType, int remArIndex, int locMss) |
andrewboyson | 74:c3756bfa960e | 40 | { |
andrewboyson | 74:c3756bfa960e | 41 | //Get the MSS to use for sends - it is the lower of the MSS advertised by the remote host and our local MSS |
andrewboyson | 74:c3756bfa960e | 42 | int remMss = TcpHdrMssGet(); |
andrewboyson | 74:c3756bfa960e | 43 | pTcb->remMss = remMss ? remMss : 536; //default MSS for IPv4 [576 - 20(TCP) - 20(IP)]; |
andrewboyson | 74:c3756bfa960e | 44 | if (pTcb->remMss > locMss) pTcb->remMss = locMss; |
andrewboyson | 74:c3756bfa960e | 45 | |
andrewboyson | 75:603b10404183 | 46 | pTcb->lastSendTime = TcbElapsed; |
andrewboyson | 75:603b10404183 | 47 | pTcb->remArIndex = remArIndex; |
andrewboyson | 75:603b10404183 | 48 | pTcb->ipType = ipType; |
andrewboyson | 75:603b10404183 | 49 | pTcb->remPort = TcpHdrSrcPort; |
andrewboyson | 75:603b10404183 | 50 | pTcb->locPort = TcpHdrDstPort; |
andrewboyson | 75:603b10404183 | 51 | pTcb->rcvdFin = false; |
andrewboyson | 75:603b10404183 | 52 | pTcb->sentFin = false; |
andrewboyson | 75:603b10404183 | 53 | pTcb->window = TcpHdrWindow; |
andrewboyson | 75:603b10404183 | 54 | pTcb->todo = 0; |
andrewboyson | 75:603b10404183 | 55 | pTcb->remIsn = TcpHdrSeqNum; |
andrewboyson | 75:603b10404183 | 56 | pTcb->locIsn = TcbGetIsn(); |
andrewboyson | 75:603b10404183 | 57 | pTcb->bytesRcvdFromRem = 0; |
andrewboyson | 75:603b10404183 | 58 | pTcb->bytesAckdByRem = 0; |
andrewboyson | 75:603b10404183 | 59 | pTcb->bytesAckdToRem = 0; |
andrewboyson | 75:603b10404183 | 60 | pTcb->bytesSentToRem = 0; |
andrewboyson | 74:c3756bfa960e | 61 | } |
andrewboyson | 75:603b10404183 | 62 | static void handleReceivedData(void* pPacket, int dataLength, uint32_t position) |
andrewboyson | 74:c3756bfa960e | 63 | { |
andrewboyson | 74:c3756bfa960e | 64 | pTcb->window = TcpHdrWindow; |
andrewboyson | 74:c3756bfa960e | 65 | char* pData = (char*)pPacket + TcpHdrSizeGet(); |
andrewboyson | 74:c3756bfa960e | 66 | switch (pTcb->locPort) |
andrewboyson | 74:c3756bfa960e | 67 | { |
andrewboyson | 74:c3756bfa960e | 68 | case 80: |
andrewboyson | 75:603b10404183 | 69 | HttpHandleRequest(dataLength, pData, position, &pTcb->todo); |
andrewboyson | 74:c3756bfa960e | 70 | break; |
andrewboyson | 74:c3756bfa960e | 71 | default: |
andrewboyson | 74:c3756bfa960e | 72 | break; |
andrewboyson | 74:c3756bfa960e | 73 | } |
andrewboyson | 74:c3756bfa960e | 74 | } |
andrewboyson | 74:c3756bfa960e | 75 | |
andrewboyson | 74:c3756bfa960e | 76 | int TcpHandleReceivedPacket(void (*traceback)(void), int sizeRx, void* pPacketRx, int* pSizeTx, void* pPacketTx, int ipType, int remArIndex) |
andrewboyson | 74:c3756bfa960e | 77 | { |
andrewboyson | 74:c3756bfa960e | 78 | TcpHdrReadFromPacket(pPacketRx); |
andrewboyson | 74:c3756bfa960e | 79 | |
andrewboyson | 74:c3756bfa960e | 80 | int dataLength = sizeRx - TcpHdrSizeGet(); |
andrewboyson | 74:c3756bfa960e | 81 | int locMss = *pSizeTx - TcpHdrSizeGet(); |
andrewboyson | 74:c3756bfa960e | 82 | |
andrewboyson | 74:c3756bfa960e | 83 | TcpDoTrace = false; |
andrewboyson | 74:c3756bfa960e | 84 | |
andrewboyson | 74:c3756bfa960e | 85 | //Filter out unwanted links |
andrewboyson | 74:c3756bfa960e | 86 | switch (TcpHdrDstPort) |
andrewboyson | 74:c3756bfa960e | 87 | { |
andrewboyson | 74:c3756bfa960e | 88 | case 80: |
andrewboyson | 74:c3756bfa960e | 89 | if (HttpTrace) |
andrewboyson | 74:c3756bfa960e | 90 | { |
andrewboyson | 74:c3756bfa960e | 91 | if (NetTraceNewLine) Log("\r\n"); |
andrewboyson | 74:c3756bfa960e | 92 | LogTime("HTTP server request\r\n"); |
andrewboyson | 74:c3756bfa960e | 93 | TcpDoTrace = true; |
andrewboyson | 74:c3756bfa960e | 94 | } |
andrewboyson | 74:c3756bfa960e | 95 | break; |
andrewboyson | 74:c3756bfa960e | 96 | |
andrewboyson | 74:c3756bfa960e | 97 | default: |
andrewboyson | 75:603b10404183 | 98 | logTraceBack(traceback, "TCP - unknown port %d\r\n", TcpHdrDstPort); |
andrewboyson | 74:c3756bfa960e | 99 | return DO_NOTHING; //Ignore unknown ports |
andrewboyson | 74:c3756bfa960e | 100 | } |
andrewboyson | 74:c3756bfa960e | 101 | |
andrewboyson | 75:603b10404183 | 102 | //Get the existing Transmission Control Block |
andrewboyson | 74:c3756bfa960e | 103 | pTcb = TcbGetExisting(TcpHdrSrcPort); |
andrewboyson | 75:603b10404183 | 104 | |
andrewboyson | 74:c3756bfa960e | 105 | //Handle request to reset |
andrewboyson | 74:c3756bfa960e | 106 | if (TcpHdrRST) |
andrewboyson | 74:c3756bfa960e | 107 | { |
andrewboyson | 75:603b10404183 | 108 | if (pTcb) |
andrewboyson | 74:c3756bfa960e | 109 | { |
andrewboyson | 75:603b10404183 | 110 | logTraceBack(traceback, "TCP - received reset - resetting TCB\r\n"); |
andrewboyson | 75:603b10404183 | 111 | pTcb->state = TCB_EMPTY; |
andrewboyson | 74:c3756bfa960e | 112 | } |
andrewboyson | 74:c3756bfa960e | 113 | return DO_NOTHING; //Don't reply |
andrewboyson | 74:c3756bfa960e | 114 | } |
andrewboyson | 74:c3756bfa960e | 115 | |
andrewboyson | 74:c3756bfa960e | 116 | //Handle request to synchronise |
andrewboyson | 74:c3756bfa960e | 117 | if (TcpHdrSYN) |
andrewboyson | 74:c3756bfa960e | 118 | { |
andrewboyson | 75:603b10404183 | 119 | if (pTcb) |
andrewboyson | 75:603b10404183 | 120 | { |
andrewboyson | 75:603b10404183 | 121 | logReset("received a SYN when connection open"); |
andrewboyson | 75:603b10404183 | 122 | pTcb->state = TCB_EMPTY; |
andrewboyson | 75:603b10404183 | 123 | return TcpSendReset(pSizeTx, pPacketTx, pTcb); |
andrewboyson | 75:603b10404183 | 124 | } |
andrewboyson | 75:603b10404183 | 125 | pTcb = TcbGetEmpty(); |
andrewboyson | 75:603b10404183 | 126 | if (!pTcb) //Bomb out if no more tcbs are available |
andrewboyson | 75:603b10404183 | 127 | { |
andrewboyson | 75:603b10404183 | 128 | logTraceBack(traceback, "TCP - no more tcbs are available\r\n"); |
andrewboyson | 75:603b10404183 | 129 | return DO_NOTHING; |
andrewboyson | 75:603b10404183 | 130 | } |
andrewboyson | 75:603b10404183 | 131 | startConnection(pPacketRx, ipType, remArIndex, locMss); |
andrewboyson | 74:c3756bfa960e | 132 | } |
andrewboyson | 74:c3756bfa960e | 133 | |
andrewboyson | 74:c3756bfa960e | 134 | //Check window and just resend the last ACK if not good |
andrewboyson | 74:c3756bfa960e | 135 | uint32_t seqRcvdFromRem = TcpHdrSeqNum - pTcb->remIsn; |
andrewboyson | 74:c3756bfa960e | 136 | bool resendAck = seqRcvdFromRem != pTcb->bytesAckdToRem; |
andrewboyson | 75:603b10404183 | 137 | if (resendAck) return TcpResendLastAck(pSizeTx, pPacketTx, pTcb); |
andrewboyson | 74:c3756bfa960e | 138 | |
andrewboyson | 75:603b10404183 | 139 | //Record the number of bytes acked by the remote host |
andrewboyson | 75:603b10404183 | 140 | pTcb->bytesAckdByRem = TcpHdrAckNum - pTcb->locIsn; |
andrewboyson | 74:c3756bfa960e | 141 | |
andrewboyson | 74:c3756bfa960e | 142 | //Handle FIN |
andrewboyson | 74:c3756bfa960e | 143 | if (TcpHdrFIN) pTcb->rcvdFin = true; //When reply is all sent only a passive close is needed |
andrewboyson | 74:c3756bfa960e | 144 | |
andrewboyson | 74:c3756bfa960e | 145 | if (TcpDoTrace && NetTraceStack) traceback(); //This will already include the TCP header |
andrewboyson | 74:c3756bfa960e | 146 | |
andrewboyson | 75:603b10404183 | 147 | //Record the number of bytes received from the remote host |
andrewboyson | 74:c3756bfa960e | 148 | if (TcpHdrSYN) pTcb->bytesRcvdFromRem += 1; //Add one to acknowledge the SYN |
andrewboyson | 74:c3756bfa960e | 149 | pTcb->bytesRcvdFromRem += dataLength; //Add the number of bytes received |
andrewboyson | 74:c3756bfa960e | 150 | if (TcpHdrFIN) pTcb->bytesRcvdFromRem += 1; //Add one to acknowledge the FIN |
andrewboyson | 74:c3756bfa960e | 151 | |
andrewboyson | 74:c3756bfa960e | 152 | switch (pTcb->state) |
andrewboyson | 74:c3756bfa960e | 153 | { |
andrewboyson | 74:c3756bfa960e | 154 | case TCB_EMPTY: |
andrewboyson | 74:c3756bfa960e | 155 | pTcb->state = TCB_SYN_RECEIVED; |
andrewboyson | 74:c3756bfa960e | 156 | break; |
andrewboyson | 74:c3756bfa960e | 157 | |
andrewboyson | 74:c3756bfa960e | 158 | case TCB_SYN_RECEIVED: |
andrewboyson | 74:c3756bfa960e | 159 | if (dataLength) |
andrewboyson | 74:c3756bfa960e | 160 | { |
andrewboyson | 74:c3756bfa960e | 161 | logReset("data received before connection established"); |
andrewboyson | 74:c3756bfa960e | 162 | pTcb->state = TCB_EMPTY; |
andrewboyson | 75:603b10404183 | 163 | return TcpSendReset(pSizeTx, pPacketTx, pTcb); |
andrewboyson | 74:c3756bfa960e | 164 | } |
andrewboyson | 74:c3756bfa960e | 165 | pTcb->state = TCB_ESTABLISHED; |
andrewboyson | 74:c3756bfa960e | 166 | break; |
andrewboyson | 74:c3756bfa960e | 167 | |
andrewboyson | 74:c3756bfa960e | 168 | case TCB_ESTABLISHED: |
andrewboyson | 75:603b10404183 | 169 | if (dataLength) handleReceivedData (pPacketRx, dataLength, seqRcvdFromRem - 1); |
andrewboyson | 74:c3756bfa960e | 170 | if (pTcb->sentFin) |
andrewboyson | 74:c3756bfa960e | 171 | { |
andrewboyson | 74:c3756bfa960e | 172 | pTcb->state = pTcb->rcvdFin ? TCB_CLOSE_ACK_WAIT : TCB_CLOSE_FIN_WAIT; |
andrewboyson | 74:c3756bfa960e | 173 | } |
andrewboyson | 74:c3756bfa960e | 174 | break; |
andrewboyson | 74:c3756bfa960e | 175 | |
andrewboyson | 74:c3756bfa960e | 176 | case TCB_CLOSE_FIN_WAIT: //End of active close |
andrewboyson | 74:c3756bfa960e | 177 | if (TcpHdrFIN) |
andrewboyson | 74:c3756bfa960e | 178 | { |
andrewboyson | 74:c3756bfa960e | 179 | pTcb->state = TCB_EMPTY;//Ignore ACK to our FIN. Wait for FIN then close. |
andrewboyson | 74:c3756bfa960e | 180 | } |
andrewboyson | 74:c3756bfa960e | 181 | break; |
andrewboyson | 74:c3756bfa960e | 182 | |
andrewboyson | 74:c3756bfa960e | 183 | case TCB_CLOSE_ACK_WAIT: //End of passive close |
andrewboyson | 74:c3756bfa960e | 184 | pTcb->state = TCB_EMPTY; |
andrewboyson | 74:c3756bfa960e | 185 | break; |
andrewboyson | 74:c3756bfa960e | 186 | } |
andrewboyson | 74:c3756bfa960e | 187 | |
andrewboyson | 75:603b10404183 | 188 | return TcpSend(pSizeTx, pPacketTx, pTcb); |
andrewboyson | 74:c3756bfa960e | 189 | } |