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
tcprecv.c
00001 #include <stdint.h> 00002 #include <stdbool.h> 00003 #include <stdarg.h> 00004 00005 #include "log.h" 00006 #include "net.h" 00007 #include "action.h" 00008 #include "tcp.h" 00009 #include "tcphdr.h" 00010 #include "tcpsend.h" 00011 #include "tcb.h" 00012 #include "ip4.h" 00013 #include "dhcp.h" 00014 #include "httpv.h" 00015 #include "https.h" 00016 #include "led.h" 00017 #include "mstimer.h" 00018 #include "restart.h" 00019 00020 00021 static void log(void (*traceback)(void), char* fmt, ...) 00022 { 00023 if (TcpTrace) 00024 { 00025 if (NetTraceNewLine) Log("\r\n"); 00026 LogTimeF("TCP port %hu - ", TcpHdrSrcPort); 00027 va_list argptr; 00028 va_start(argptr, fmt); 00029 LogV(fmt, argptr); 00030 va_end(argptr); 00031 Log("\r\n"); 00032 if (NetTraceStack) traceback(); 00033 } 00034 } 00035 static void handleSyn(void *pPacket, int ipType, int remArIndex, int locMss, struct tcb* pTcb) 00036 { 00037 //Get the MSS to use for sends - it is the lower of the MSS advertised by the remote host and our local MSS 00038 int remMss = TcpHdrMssGet(); 00039 pTcb->remMss = remMss ? remMss : 536; //default MSS for IPv4 [576 - 20(TCP) - 20(IP)]; 00040 if (pTcb->remMss > locMss) pTcb->remMss = locMss; 00041 00042 pTcb->timeSendsBeingAcked = MsTimerCount; 00043 pTcb->countSendsNotAcked = 0; 00044 pTcb->rcvdFin = false; 00045 pTcb->sentFin = false; 00046 pTcb->remIsn = TcpHdrSeqNum; 00047 pTcb->locIsn = TcbGetIsn(); 00048 pTcb->bytesRcvdFromRem = 0; 00049 pTcb->bytesAckdByRem = 0; 00050 pTcb->bytesAckdToRem = 0; 00051 pTcb->bytesSentToRem = 0; 00052 switch (pTcb->locPort) //Reset the application 00053 { 00054 case 80: HttpvReset(TcbGetId(pTcb)); break; 00055 case 443: HttpsReset(TcbGetId(pTcb)); break; 00056 } 00057 } 00058 static void handleReceivedData(void* pPacket, int dataLength, uint32_t position, struct tcb* pTcb) 00059 { 00060 pTcb->window = TcpHdrWindow; 00061 uint8_t* pData = (uint8_t*)pPacket + TcpHdrSizeGet(); 00062 switch (pTcb->locPort) 00063 { 00064 case 80: HttpvRequest(TcbGetId(pTcb), dataLength, pData, position); break; 00065 case 443: HttpsRequest(TcbGetId(pTcb), dataLength, pData, position); break; 00066 } 00067 } 00068 static int sendResetFromPacket(int* pSizeTx, void* pPacketTx, int ipType, int remArIndex, int locIpScope, int seqLengthRcvd) 00069 { 00070 /*RFC793 p36 If the connection does not exist (CLOSED) then a reset is sent 00071 in response to any incoming segment except another reset. 00072 If the incoming segment has an ACK field, the reset takes its sequence number from the ACK field of the segment, 00073 otherwise the reset has sequence number zero 00074 and 00075 the ACK field is set to the sum of the sequence number and segment length of the incoming segment. 00076 The connection remains in the CLOSED state. 00077 In TcpSendReset TcpHdrAckNum = pTcb->bytesAckdToRem + pTcb->remIsn; //Set up the acknowledgement field ready to send 00078 TcpHdrSeqNum = pTcb->bytesSentToRem + pTcb->locIsn; //Set up the start of the message before adding the bytes sent 00079 */ 00080 00081 struct tcb tcb; 00082 struct tcb* pTcb = &tcb; 00083 pTcb->timeLastRcvd = MsTimerCount; 00084 pTcb->remArIndex = remArIndex; 00085 pTcb->ipType = ipType; 00086 pTcb->locIpScope = locIpScope; 00087 pTcb->remPort = TcpHdrSrcPort; 00088 pTcb->locPort = TcpHdrDstPort; 00089 pTcb->window = TcpHdrWindow; 00090 pTcb->state = TCB_EMPTY; 00091 00092 pTcb->timeSendsBeingAcked = MsTimerCount; 00093 pTcb->countSendsNotAcked = 0; 00094 pTcb->rcvdFin = false; 00095 pTcb->sentFin = false; 00096 pTcb->remIsn = TcpHdrSeqNum + seqLengthRcvd; //Ack number 00097 pTcb->locIsn = TcpHdrACK ? TcpHdrAckNum : 0; //Seq number 00098 pTcb->bytesRcvdFromRem = 0; 00099 pTcb->bytesAckdByRem = 0; 00100 pTcb->bytesAckdToRem = 0; 00101 pTcb->bytesSentToRem = 0; 00102 00103 return TcpSendReset(pSizeTx, pPacketTx, pTcb); 00104 } 00105 00106 int TcpHandleReceivedPacket(void (*traceback)(void), int sizeRx, void* pPacketRx, int* pSizeTx, void* pPacketTx, int ipType, int remArIndex, int locIpScope) 00107 { 00108 int lastRestartPoint = RestartPoint; 00109 RestartPoint = FAULT_POINT_TcpHandleReceivedPacket; 00110 00111 int action = DO_NOTHING; 00112 bool traceRequested = false; 00113 00114 TcpHdrReadFromPacket(pPacketRx); 00115 00116 if (remArIndex < 0) 00117 { 00118 log(traceback, "invalid remote AR index %d -> ignored packet", remArIndex); 00119 RestartPoint = lastRestartPoint; 00120 return DO_NOTHING; 00121 } 00122 RestartPoint += 100; 00123 00124 int dataLength = sizeRx - TcpHdrSizeGet(); 00125 int locMss = *pSizeTx - TcpHdrSizeGet(); 00126 00127 //Calculate the sequence length of the received packet 00128 int seqLengthRcvd = 0; 00129 if (TcpHdrSYN) seqLengthRcvd += 1; //Add one to acknowledge the SYN 00130 seqLengthRcvd += dataLength; //Add the number of bytes received 00131 if (TcpHdrFIN) seqLengthRcvd += 1; //Add one to acknowledge the FIN 00132 00133 //Filter out unwanted links 00134 RestartPoint++; 00135 switch (TcpHdrDstPort) 00136 { 00137 case 80: 00138 if (HttpvGetTrace()) 00139 { 00140 if (NetTraceNewLine) Log("\r\n"); 00141 LogTime("HTTP server request\r\n"); 00142 traceRequested = true; 00143 } 00144 break; 00145 00146 case 443: 00147 if (HttpsGetTrace()) 00148 { 00149 if (NetTraceNewLine) Log("\r\n"); 00150 LogTimeF("HTTPS server request of %d bytes\r\n", dataLength); 00151 traceRequested = true; 00152 } 00153 break; 00154 00155 default: //Send reset if unknown port 00156 log(traceback, "unhandled local port %hu -> sent reset", TcpHdrDstPort); 00157 action = sendResetFromPacket(pSizeTx, pPacketTx, ipType, remArIndex, locIpScope, seqLengthRcvd); 00158 RestartPoint = lastRestartPoint; 00159 return action; 00160 } 00161 00162 //Get the Transmission Control Block 00163 RestartPoint++; 00164 struct tcb* pTcb = TcbGetExisting(ipType, remArIndex, locIpScope, TcpHdrSrcPort, TcpHdrDstPort); 00165 if (!pTcb) pTcb = TcbGetEmpty(); 00166 if (!pTcb) //send reset if no more tcbs are available 00167 { 00168 log(traceback, "no more tcbs available -> sent reset"); 00169 action = sendResetFromPacket(pSizeTx, pPacketTx, ipType, remArIndex, locIpScope, seqLengthRcvd); 00170 RestartPoint = lastRestartPoint; 00171 return action; 00172 } 00173 pTcb->timeLastRcvd = MsTimerCount; 00174 pTcb->remArIndex = remArIndex; 00175 pTcb->ipType = ipType; 00176 pTcb->locIpScope = locIpScope; 00177 pTcb->remPort = TcpHdrSrcPort; 00178 pTcb->locPort = TcpHdrDstPort; 00179 pTcb->window = TcpHdrWindow; 00180 00181 //Handle request to reset 00182 RestartPoint++; 00183 if (TcpHdrRST) 00184 { 00185 if (pTcb->state) 00186 { 00187 log(traceback, "received reset -> reaped TCB"); 00188 pTcb->state = TCB_EMPTY; 00189 } 00190 RestartPoint = lastRestartPoint; 00191 return DO_NOTHING; //Don't reply 00192 } 00193 00194 //Handle request to synchronise 00195 RestartPoint++; 00196 if (TcpHdrSYN) 00197 { 00198 if (pTcb->state) 00199 { 00200 log(traceback, "received a SYN on an open connection -> sent reset"); 00201 pTcb->state = TCB_EMPTY; 00202 action = TcpSendReset(pSizeTx, pPacketTx, pTcb); 00203 RestartPoint = lastRestartPoint; 00204 return action; 00205 } 00206 else 00207 { 00208 handleSyn(pPacketRx, ipType, remArIndex, locMss, pTcb); 00209 } 00210 } 00211 00212 //Handle non SYN packet on an empty connection 00213 RestartPoint++; 00214 if (!TcpHdrSYN && !pTcb->state) 00215 { 00216 00217 log(traceback, "non SYN packet received on a closed connection -> sent reset"); 00218 pTcb->state = TCB_EMPTY; 00219 action = sendResetFromPacket(pSizeTx, pPacketTx, ipType, remArIndex, locIpScope, seqLengthRcvd); 00220 RestartPoint = lastRestartPoint; 00221 return action; 00222 } 00223 00224 //Check if the acks of bytes sent has progressed and reset the timer 00225 RestartPoint++; 00226 uint32_t ackRcvdFromRem = TcpHdrACK ? TcpHdrAckNum - pTcb->locIsn : 0; 00227 if (ackRcvdFromRem > pTcb->bytesAckdByRem) 00228 { 00229 pTcb->timeSendsBeingAcked = MsTimerCount; 00230 pTcb->countSendsNotAcked = 0; 00231 } 00232 00233 //Record the number of bytes acked by the remote host 00234 RestartPoint++; 00235 pTcb->bytesAckdByRem = ackRcvdFromRem; 00236 00237 /* If the connection is in a synchronized state 00238 any unacceptable segment (out of window sequence number or 00239 unacceptible acknowledgment number) must elicit only an empty 00240 acknowledgment segment containing the current send-sequence number 00241 and an acknowledgment indicating the next sequence number expected 00242 to be received, and the connection remains in the same state.*/ 00243 RestartPoint++; 00244 uint32_t seqRcvdFromRem = TcpHdrSeqNum - pTcb->remIsn; 00245 if (seqRcvdFromRem != pTcb->bytesAckdToRem) 00246 { 00247 //Only warn non keep-alives 00248 if (seqRcvdFromRem != 0 || pTcb->bytesAckdToRem != 1) 00249 { 00250 log(traceback, "seq rcvd is %d and last seq ackd was %d -> resent last ACK", seqRcvdFromRem, pTcb->bytesAckdToRem); 00251 } 00252 action = TcpResendLastAck(pSizeTx, pPacketTx, pTcb); 00253 RestartPoint = lastRestartPoint; 00254 return action; 00255 } 00256 //Ignore data before established 00257 RestartPoint++; 00258 if (pTcb->state != TCB_ESTABLISHED && dataLength) 00259 { 00260 log(traceback, "data received before connection established -> sent reset"); 00261 pTcb->state = TCB_EMPTY; 00262 action = TcpSendReset(pSizeTx, pPacketTx, pTcb); 00263 RestartPoint = lastRestartPoint; 00264 return action; 00265 } 00266 00267 //Handle FIN 00268 RestartPoint++; 00269 if (TcpHdrFIN) pTcb->rcvdFin = true; //When reply is all sent only a passive close is needed 00270 00271 //From now on there are no errors so display traceback if requested 00272 RestartPoint++; 00273 if (traceRequested && NetTraceStack) traceback(); 00274 00275 //Record the number of bytes received from the remote host 00276 RestartPoint++; 00277 pTcb->bytesRcvdFromRem += seqLengthRcvd; 00278 00279 switch (pTcb->state) //This is the state of the connection BEFORE this packet arrived 00280 { 00281 case TCB_EMPTY: 00282 pTcb->state = TCB_SYN_RECEIVED; 00283 break; 00284 00285 case TCB_SYN_RECEIVED: 00286 pTcb->state = TCB_ESTABLISHED; 00287 break; 00288 00289 case TCB_ESTABLISHED: 00290 if (dataLength) 00291 { 00292 handleReceivedData(pPacketRx, dataLength, seqRcvdFromRem - 1, pTcb); 00293 } 00294 if (pTcb->sentFin) 00295 { 00296 pTcb->state = pTcb->rcvdFin ? TCB_EMPTY : TCB_CLOSE_FIN_WAIT; 00297 } 00298 break; 00299 00300 case TCB_CLOSE_FIN_WAIT: //End of active close 00301 if (TcpHdrFIN) 00302 { 00303 pTcb->state = TCB_EMPTY;//Ignore ACK to our FIN. Wait for FIN then close. 00304 } 00305 break; 00306 00307 } 00308 00309 RestartPoint++; 00310 action = TcpSend(pSizeTx, pPacketTx, pTcb); 00311 00312 RestartPoint = lastRestartPoint; 00313 return action; 00314 }
Generated on Tue Jul 12 2022 18:53:40 by 1.7.2