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:
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?

UserRevisionLine numberNew 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 }