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
Diff: tcp/tcprecv.c
- Revision:
- 75:603b10404183
- Parent:
- 74:c3756bfa960e
- Child:
- 76:17534bde28d3
--- a/tcp/tcprecv.c Mon Oct 29 09:33:44 2018 +0000 +++ b/tcp/tcprecv.c Tue Oct 30 22:11:22 2018 +0000 @@ -1,5 +1,6 @@ #include <stdint.h> #include <stdbool.h> +#include <stdarg.h> #include "log.h" #include "net.h" @@ -21,6 +22,20 @@ if (TcpTrace) { LogTime("TCP sent RST - "); Log(message); Log("\r\n"); } } +static void logTraceBack(void (*traceback)(void), char* fmt, ...) +{ + if (TcpTrace) + { + if (NetTraceNewLine) Log("\r\n"); + va_list argptr; + va_start(argptr, fmt); + LogV(fmt, argptr); + va_end(argptr); + Log("\r\n"); + if (NetTraceStack) traceback(); + } +} + static void startConnection(void *pPacket, int ipType, int remArIndex, int locMss) { //Get the MSS to use for sends - it is the lower of the MSS advertised by the remote host and our local MSS @@ -28,24 +43,30 @@ pTcb->remMss = remMss ? remMss : 536; //default MSS for IPv4 [576 - 20(TCP) - 20(IP)]; if (pTcb->remMss > locMss) pTcb->remMss = locMss; - pTcb->lastSendTime = TcbElapsed; - pTcb->remArIndex = remArIndex; - pTcb->ipType = ipType; - pTcb->remPort = TcpHdrSrcPort; - pTcb->locPort = TcpHdrDstPort; - pTcb->rcvdFin = false; - pTcb->sentFin = false; - pTcb->window = TcpHdrWindow; - pTcb->todo = 0; + pTcb->lastSendTime = TcbElapsed; + pTcb->remArIndex = remArIndex; + pTcb->ipType = ipType; + pTcb->remPort = TcpHdrSrcPort; + pTcb->locPort = TcpHdrDstPort; + pTcb->rcvdFin = false; + pTcb->sentFin = false; + pTcb->window = TcpHdrWindow; + pTcb->todo = 0; + pTcb->remIsn = TcpHdrSeqNum; + pTcb->locIsn = TcbGetIsn(); + pTcb->bytesRcvdFromRem = 0; + pTcb->bytesAckdByRem = 0; + pTcb->bytesAckdToRem = 0; + pTcb->bytesSentToRem = 0; } -static void handleReceivedData(void* pPacket, int dataLength) +static void handleReceivedData(void* pPacket, int dataLength, uint32_t position) { pTcb->window = TcpHdrWindow; char* pData = (char*)pPacket + TcpHdrSizeGet(); switch (pTcb->locPort) { case 80: - HttpHandleRequest(dataLength, pData, pTcb->bytesRcvdFromRem - 1, &pTcb->todo); + HttpHandleRequest(dataLength, pData, position, &pTcb->todo); break; default: break; @@ -74,67 +95,56 @@ break; default: - if (TcpTrace) - { - if (NetTraceNewLine) Log("\r\n"); - LogTimeF("TCP unknown port %d\r\n", TcpHdrDstPort); - if (NetTraceStack) traceback(); - } + logTraceBack(traceback, "TCP - unknown port %d\r\n", TcpHdrDstPort); return DO_NOTHING; //Ignore unknown ports } - //Get the Transmission Control Block + //Get the existing Transmission Control Block pTcb = TcbGetExisting(TcpHdrSrcPort); - if (!pTcb) pTcb = TcbGetEmpty(); - if (!pTcb) - { - if (TcpTrace) - { - if (NetTraceNewLine) Log("\r\n"); - LogTime("TCP no more tcbs are available\r\n"); - if (NetTraceStack) traceback(); - } - return DO_NOTHING; //Bomb out if no more tcbs are available - } - + //Handle request to reset if (TcpHdrRST) { - if (TcpTrace) + if (pTcb) { - if (NetTraceNewLine) Log("\r\n"); - LogTime("TCP received reset - resetting TCB\r\n"); - if (NetTraceStack) traceback(); + logTraceBack(traceback, "TCP - received reset - resetting TCB\r\n"); + pTcb->state = TCB_EMPTY; } - pTcb->state = TCB_EMPTY; return DO_NOTHING; //Don't reply } //Handle request to synchronise if (TcpHdrSYN) { - pTcb->remIsn = TcpHdrSeqNum; - pTcb->locIsn = TcbGetIsn(); - pTcb->bytesRcvdFromRem = 0; - pTcb->bytesAckdByRem = 0; - pTcb->bytesAckdToRem = 0; - pTcb->bytesSentToRem = 0; + if (pTcb) + { + logReset("received a SYN when connection open"); + pTcb->state = TCB_EMPTY; + return TcpSendReset(pSizeTx, pPacketTx, pTcb); + } + pTcb = TcbGetEmpty(); + if (!pTcb) //Bomb out if no more tcbs are available + { + logTraceBack(traceback, "TCP - no more tcbs are available\r\n"); + return DO_NOTHING; + } + startConnection(pPacketRx, ipType, remArIndex, locMss); } //Check window and just resend the last ACK if not good uint32_t seqRcvdFromRem = TcpHdrSeqNum - pTcb->remIsn; bool resendAck = seqRcvdFromRem != pTcb->bytesAckdToRem; - if (resendAck) return TcpSend(pSizeTx, pPacketTx, pTcb, TCP_RESEND_ACK); + if (resendAck) return TcpResendLastAck(pSizeTx, pPacketTx, pTcb); - pTcb->bytesRcvdFromRem = TcpHdrSeqNum - pTcb->remIsn; - pTcb->bytesAckdByRem = TcpHdrAckNum - pTcb->locIsn; - + //Record the number of bytes acked by the remote host + pTcb->bytesAckdByRem = TcpHdrAckNum - pTcb->locIsn; //Handle FIN if (TcpHdrFIN) pTcb->rcvdFin = true; //When reply is all sent only a passive close is needed if (TcpDoTrace && NetTraceStack) traceback(); //This will already include the TCP header + //Record the number of bytes received from the remote host if (TcpHdrSYN) pTcb->bytesRcvdFromRem += 1; //Add one to acknowledge the SYN pTcb->bytesRcvdFromRem += dataLength; //Add the number of bytes received if (TcpHdrFIN) pTcb->bytesRcvdFromRem += 1; //Add one to acknowledge the FIN @@ -142,13 +152,6 @@ switch (pTcb->state) { case TCB_EMPTY: - if (!TcpHdrSYN) - { - logReset("received other than a SYN when connection closed"); - pTcb->state = TCB_EMPTY; - return TcpSend(pSizeTx, pPacketTx, pTcb, TCP_SEND_RESET); - } - startConnection(pPacketRx, ipType, remArIndex, locMss); pTcb->state = TCB_SYN_RECEIVED; break; @@ -157,13 +160,13 @@ { logReset("data received before connection established"); pTcb->state = TCB_EMPTY; - return TcpSend(pSizeTx, pPacketTx, pTcb, TCP_SEND_RESET); + return TcpSendReset(pSizeTx, pPacketTx, pTcb); } pTcb->state = TCB_ESTABLISHED; break; case TCB_ESTABLISHED: - if (dataLength) handleReceivedData (pPacketRx, dataLength); + if (dataLength) handleReceivedData (pPacketRx, dataLength, seqRcvdFromRem - 1); if (pTcb->sentFin) { pTcb->state = pTcb->rcvdFin ? TCB_CLOSE_ACK_WAIT : TCB_CLOSE_FIN_WAIT; @@ -182,5 +185,5 @@ break; } - return TcpSend(pSizeTx, pPacketTx, pTcb, TCP_SEND_NORMAL); + return TcpSend(pSizeTx, pPacketTx, pTcb); }