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:
- 90:955f4c6e18a9
- Parent:
- 89:9b765a67699b
- Child:
- 91:879545b19260
diff -r 9b765a67699b -r 955f4c6e18a9 tcp/tcprecv.c --- a/tcp/tcprecv.c Wed Nov 21 17:13:04 2018 +0000 +++ b/tcp/tcprecv.c Thu Nov 22 17:35:59 2018 +0000 @@ -62,8 +62,19 @@ break; } } -static int sendResetFromPacket(int* pSizeTx, void* pPacketTx, int ipType, int remArIndex, int locIpScope) +static int sendResetFromPacket(int* pSizeTx, void* pPacketTx, int ipType, int remArIndex, int locIpScope, int seqLengthRcvd) { + /*RFC793 p36 If the connection does not exist (CLOSED) then a reset is sent + in response to any incoming segment except another reset. + If the incoming segment has an ACK field, the reset takes its sequence number from the ACK field of the segment, + otherwise the reset has sequence number zero + and + the ACK field is set to the sum of the sequence number and segment length of the incoming segment. + The connection remains in the CLOSED state. + In TcpSendReset TcpHdrAckNum = pTcb->bytesAckdToRem + pTcb->remIsn; //Set up the acknowledgement field ready to send + TcpHdrSeqNum = pTcb->bytesSentToRem + pTcb->locIsn; //Set up the start of the message before adding the bytes sent + */ + struct tcb tcb; struct tcb* pTcb = &tcb; pTcb->timeLastRcvd = TcbElapsed; @@ -75,12 +86,24 @@ pTcb->window = TcpHdrWindow; pTcb->state = TCB_EMPTY; + pTcb->timeSendsBeingAcked = TcbElapsed; + pTcb->countSendsNotAcked = 0; + pTcb->rcvdFin = false; + pTcb->sentFin = false; + pTcb->todo = 0; + pTcb->remIsn = TcpHdrSeqNum + seqLengthRcvd; //Ack number + pTcb->locIsn = TcpHdrACK ? TcpHdrAckNum : 0; //Seq number + pTcb->bytesRcvdFromRem = 0; + pTcb->bytesAckdByRem = 0; + pTcb->bytesAckdToRem = 0; + pTcb->bytesSentToRem = 0; + return TcpSendReset(pSizeTx, pPacketTx, pTcb); } int TcpHandleReceivedPacket(void (*traceback)(void), int sizeRx, void* pPacketRx, int* pSizeTx, void* pPacketTx, int ipType, int remArIndex, int locIpScope) { - int dest = DO_NOTHING; + int action = DO_NOTHING; bool traceRequested = false; Led1Set(true); @@ -97,6 +120,12 @@ int dataLength = sizeRx - TcpHdrSizeGet(); int locMss = *pSizeTx - TcpHdrSizeGet(); + //Calculate the sequence length of the received packet + int seqLengthRcvd = 0; + if (TcpHdrSYN) seqLengthRcvd += 1; //Add one to acknowledge the SYN + seqLengthRcvd += dataLength; //Add the number of bytes received + if (TcpHdrFIN) seqLengthRcvd += 1; //Add one to acknowledge the FIN + //Filter out unwanted links switch (TcpHdrDstPort) { @@ -111,9 +140,9 @@ default: //Send reset if unknown port log(traceback, "unhandled local port %hu -> sent reset", TcpHdrDstPort); - dest = sendResetFromPacket(pSizeTx, pPacketTx, ipType, remArIndex, locIpScope); + action = sendResetFromPacket(pSizeTx, pPacketTx, ipType, remArIndex, locIpScope, seqLengthRcvd); Led1Set(false); - return ActionMakeFromDestAndTrace(dest, traceRequested && NetTraceStack); + return action; } //Get the Transmission Control Block @@ -122,9 +151,9 @@ if (!pTcb) //send reset if no more tcbs are available { log(traceback, "no more tcbs available -> sent reset"); - dest = sendResetFromPacket(pSizeTx, pPacketTx, ipType, remArIndex, locIpScope); + action = sendResetFromPacket(pSizeTx, pPacketTx, ipType, remArIndex, locIpScope, seqLengthRcvd); Led1Set(false); - return ActionMakeFromDestAndTrace(dest, traceRequested && NetTraceStack); + return action; } pTcb->timeLastRcvd = TcbElapsed; pTcb->remArIndex = remArIndex; @@ -153,9 +182,9 @@ { log(traceback, "received a SYN on an open connection -> sent reset"); pTcb->state = TCB_EMPTY; - dest = TcpSendReset(pSizeTx, pPacketTx, pTcb); + action = TcpSendReset(pSizeTx, pPacketTx, pTcb); Led1Set(false); - ActionMakeFromDestAndTrace(dest, traceRequested && NetTraceStack); + return action; } else { @@ -163,36 +192,15 @@ } } - //Calculate the sequence length of the received packet - int seqLengthRcvd = 0; - if (TcpHdrSYN) seqLengthRcvd += 1; //Add one to acknowledge the SYN - seqLengthRcvd += dataLength; //Add the number of bytes received - if (TcpHdrFIN) seqLengthRcvd += 1; //Add one to acknowledge the FIN - - /*RFC793 p36 If the connection does not exist (CLOSED) then a reset is sent - in response to any incoming segment except another reset. - If the incoming segment has an ACK field, the reset takes its sequence number from the ACK field of the segment, - otherwise the reset has sequence number zero - and - the ACK field is set to the sum of the sequence number and segment length of the incoming segment. - The connection remains in the CLOSED state. - In TcpSendReset TcpHdrAckNum = pTcb->bytesAckdToRem + pTcb->remIsn; //Set up the acknowledgement field ready to send - TcpHdrSeqNum = pTcb->bytesSentToRem + pTcb->locIsn; //Set up the start of the message before adding the bytes sent - */ + //Handle non SYN packet on an empty connection if (!TcpHdrSYN && !pTcb->state) { - pTcb->remIsn = 0; - pTcb->locIsn = 0; - pTcb->bytesRcvdFromRem = 0; - pTcb->bytesAckdByRem = 0; - - pTcb->bytesSentToRem = TcpHdrACK ? TcpHdrAckNum : 0; //Seq number - pTcb->bytesAckdToRem = TcpHdrSeqNum + seqLengthRcvd; //Ack number + log(traceback, "non SYN packet received on a closed connection -> sent reset"); pTcb->state = TCB_EMPTY; - dest = TcpSendReset(pSizeTx, pPacketTx, pTcb); + action = sendResetFromPacket(pSizeTx, pPacketTx, ipType, remArIndex, locIpScope, seqLengthRcvd); Led1Set(false); - return ActionMakeFromDestAndTrace(dest, traceRequested && NetTraceStack); + return action; } //Check if the acks of bytes sent has progressed and reset the timer @@ -220,15 +228,27 @@ { log(traceback, "seq rcvd is %d and last seq ackd was %d -> resent last ACK", seqRcvdFromRem, pTcb->bytesAckdToRem); } - dest = TcpResendLastAck(pSizeTx, pPacketTx, pTcb); + action = TcpResendLastAck(pSizeTx, pPacketTx, pTcb); Led1Set(false); - return ActionMakeFromDestAndTrace(dest, traceRequested && NetTraceStack); + return action; } + //Ignore data before established + if (pTcb->state != TCB_ESTABLISHED && dataLength) + { + log(traceback, "data received before connection established -> sent reset"); + pTcb->state = TCB_EMPTY; + action = TcpSendReset(pSizeTx, pPacketTx, pTcb); + Led1Set(false); + return action; + } + Led2Set(true); + //Handle FIN if (TcpHdrFIN) pTcb->rcvdFin = true; //When reply is all sent only a passive close is needed - - if (traceRequested && NetTraceStack) traceback(); //This will already include the TCP header + + //From now on there are no errors so display traceback if requested + if (traceRequested && NetTraceStack) traceback(); //Record the number of bytes received from the remote host pTcb->bytesRcvdFromRem += seqLengthRcvd; @@ -240,15 +260,6 @@ break; case TCB_SYN_RECEIVED: - if (dataLength) - { - log(traceback, "data received before connection established -> sent reset"); - pTcb->state = TCB_EMPTY; - dest = TcpSendReset(pSizeTx, pPacketTx, pTcb); - Led1Set(false); - Led2Set(false); - return ActionMakeFromDestAndTrace(dest, traceRequested && NetTraceStack); - } pTcb->state = TCB_ESTABLISHED; break; @@ -269,9 +280,9 @@ } - dest = TcpSend(pSizeTx, pPacketTx, pTcb); + action = TcpSend(pSizeTx, pPacketTx, pTcb); Led1Set(false); Led2Set(false); - return ActionMakeFromDestAndTrace(dest, traceRequested && NetTraceStack); + return action; }