26#include "TCP_Header.h"
34static bool Validate_segment(PNETSIM_SOCKET s)
54 if (!t->SEG.LEN && !t->RCV.WND)
55 return t->SEG.SEQ == t->RCV.NXT;
56 else if (!t->SEG.LEN && t->RCV.WND > 0)
57 return (t->RCV.NXT <= t->SEG.SEQ) &&
58 (t->SEG.SEQ < t->RCV.NXT + t->RCV.WND);
59 else if (t->SEG.LEN > 0 && t->RCV.WND == 0)
61 else if (t->SEG.LEN > 0 && t->RCV.WND > 0)
62 return ((t->RCV.NXT <= t->SEG.SEQ) &&
63 (t->SEG.SEQ < t->RCV.NXT + t->RCV.WND)) ||
64 ((t->RCV.NXT <= t->SEG.SEQ + t->SEG.LEN - 1) &&
65 (t->SEG.SEQ + t->SEG.LEN - 1 < t->RCV.NXT + t->RCV.WND));
71static void process_rst_packet(PNETSIM_SOCKET s, NetSim_PACKET* p)
73 switch (s->tcb->tcp_state)
75 case TCPCONNECTION_SYN_RECEIVED:
77 delete_all_segment_from_queue(&s->tcb->retransmissionQueue);
78 if (s->tcb->tcp_prev_state == TCPCONNECTION_LISTEN)
81 tcp_change_state(s, TCPCONNECTION_LISTEN);
86 print_tcp_log(
"Connection Refused for local addr %s:%d, remote addr %s:%d",
87 s->localAddr->ip->str_ip,
89 s->remoteAddr->ip->str_ip,
91 tcp_close_socket(s, s->localDeviceId);
95 case TCPCONNECTION_ESTABLISHED:
96 case TCPCONNECTION_FIN_WAIT_1:
97 case TCPCONNECTION_FIN_WAIT_2:
98 case TCPCONNECTION_CLOSE_WAIT:
100 print_tcp_log(
"Connection Reset for local addr %s:%d, remote addr %s:%d",
101 s->localAddr->ip->str_ip,
103 s->remoteAddr->ip->str_ip,
104 s->remoteAddr->port);
106 case TCPCONNECTION_CLOSING:
107 case TCPCONNECTION_LAST_ACK:
108 case TCPCONNECTION_TIME_WAIT:
109 tcp_close_socket(s, s->localDeviceId);
112 fn_NetSim_Packet_FreePacket(p);
113 pstruEventDetails->pPacket = NULL;
116static void process_syn_packet(PNETSIM_SOCKET s, NetSim_PACKET* p)
118 switch (s->tcb->tcp_state)
120 case TCPCONNECTION_SYN_RECEIVED:
122 tcp_change_state(s, TCPCONNECTION_LISTEN);
124 case TCPCONNECTION_ESTABLISHED:
125 case TCPCONNECTION_FIN_WAIT_1:
126 case TCPCONNECTION_FIN_WAIT_2:
127 case TCPCONNECTION_CLOSE_WAIT:
128 case TCPCONNECTION_CLOSING:
129 case TCPCONNECTION_LAST_ACK:
130 case TCPCONNECTION_TIME_WAIT:
131 print_tcp_log(
"Connection Reset for local addr %s:%d, remote addr %s:%d",
132 s->localAddr->ip->str_ip,
134 s->remoteAddr->ip->str_ip,
135 s->remoteAddr->port);
136 tcp_close_socket(s, s->localDeviceId);
139 fn_NetSim_Packet_FreePacket(p);
140 pstruEventDetails->pPacket = NULL;
143static bool process_ack_in_establishedState(PNETSIM_SOCKET s, PTCP_SEGMENT_HDR hdr)
146 fprintf(fp,
"%lf,,,,,%d,\n",
147 pstruEventDetails->dEventTime,
155 receive_sack_option(s, hdr);
160 PTSopt tsopt = get_tcp_option(hdr,
161 TCP_OPTION_TIMESTAMP);
162 set_timestamp_value(s, hdr, tsopt);
169 s->tcpMetrics->ackReceived++;
171 if (t->SND.UNA < t->SEG.ACK &&
172 t->SEG.ACK <= t->SND.NXT)
176 TCP_RTO(s->tcb) = calculate_RTO(get_RTT(s->tcb,t->SEG.ACK),
178 &TCP_RTTVAR(s->tcb));
181 t->SND.UNA = t->SEG.ACK;
182 delete_segment_from_queue(&t->retransmissionQueue, t->SEG.ACK);
183 restart_rto_timer(s);
184 if (t->SND.WL1 < t->SEG.SEQ ||
185 (t->SND.WL1 == t->SEG.SEQ &&
186 t->SND.WL2 <= t->SEG.ACK))
188 t->SND.WND = t->SEG.WND;
189 t->SND.WL1 = t->SEG.SEQ;
190 t->SND.WL2 = t->SEG.ACK;
195 else if (t->SEG.ACK <= t->SND.UNA)
198 s->tcpMetrics->dupAckReceived++;
199 UINT dupackcount = s->tcb->get_dup_ack_count(s);
200 if (dupackcount == 1 || dupackcount == 2)
return true;
203 else if (t->SEG.ACK > t->SND.NXT)
205 send_ack(s, pstruEventDetails->dEventTime, t->SEG.SEQ, t->SEG.ACK);
212static void process_ack_packet(PNETSIM_SOCKET s, NetSim_PACKET* p)
214 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(p);
215 bool isContinueProcessing=
false;
216 switch (s->tcb->tcp_state)
218 case TCPCONNECTION_SYN_RECEIVED:
220 if (!(s->tcb->SND.UNA <= s->tcb->SEG.ACK &&
221 s->tcb->SEG.ACK <= s->tcb->SND.NXT))
229 s->tcb->SND.WND = s->tcb->SEG.WND;
230 s->tcb->SND.WL1 = s->tcb->SEG.SEQ;
231 s->tcb->SND.WL2 = s->tcb->SEG.ACK;
233 tcp_change_state(s, TCPCONNECTION_ESTABLISHED);
236 case TCPCONNECTION_ESTABLISHED:
238 isContinueProcessing = process_ack_in_establishedState(s, hdr);
239 if (isContinueProcessing)
243 case TCPCONNECTION_FIN_WAIT_1:
244 isContinueProcessing = process_ack_in_establishedState(s, hdr);
245 if (isContinueProcessing)
248 tcp_change_state(s, TCPCONNECTION_FIN_WAIT_2);
250 case TCPCONNECTION_FIN_WAIT_2:
251 case TCPCONNECTION_CLOSE_WAIT:
252 isContinueProcessing = process_ack_in_establishedState(s, hdr);
253 if (isContinueProcessing)
256 case TCPCONNECTION_CLOSING:
257 isContinueProcessing = process_ack_in_establishedState(s, hdr);
258 if (isContinueProcessing)
262 start_timewait_timer(s);
263 tcp_change_state(s, TCPCONNECTION_TIME_WAIT);
266 case TCPCONNECTION_LAST_ACK:
267 s->tcpMetrics->ackReceived++;
268 tcp_change_state(s, TCPCONNECTION_CLOSED);
270 tcp_close_socket(s, pstruEventDetails->nDeviceId);
272 case TCPCONNECTION_TIME_WAIT:
273 send_fin_ack(s, pstruEventDetails->dEventTime, s->tcb->SEG.SEQ, s->tcb->SEG.ACK);
274 start_timewait_timer(s);
275 s->tcb->istimewaittimerrestarted =
true;
278 fnNetSimError(
"Unknown TCP connection state %d in %s",
283 fn_NetSim_Packet_FreePacket(p);
284 pstruEventDetails->pPacket = NULL;
287static void process_fin_packet(PNETSIM_SOCKET s, NetSim_PACKET* p)
289 switch (s->tcb->tcp_state)
291 case TCPCONNECTION_CLOSED:
292 case TCPCONNECTION_LISTEN:
293 case TCPCONNECTION_SYN_SENT:
294 goto DISCARD_SEGMENT;
297 switch (s->tcb->tcp_state)
299 case TCPCONNECTION_SYN_RECEIVED:
300 case TCPCONNECTION_ESTABLISHED:
301 send_fin_ack(s, pstruEventDetails->dEventTime, s->tcb->SND.NXT, s->tcb->RCV.NXT);
302 tcp_change_state(s, TCPCONNECTION_CLOSE_WAIT);
305 tcp_change_state(s, TCPCONNECTION_LAST_ACK);
306 print_tcp_log(
"Canceling all timer.");
307 s->tcb->isOtherTimerCancel =
true;
309 case TCPCONNECTION_FIN_WAIT_1:
310 tcp_change_state(s, TCPCONNECTION_CLOSING);
311 send_fin_ack(s, pstruEventDetails->dEventTime, s->tcb->SND.NXT, s->tcb->RCV.NXT);
313 case TCPCONNECTION_FIN_WAIT_2:
314 tcp_change_state(s, TCPCONNECTION_TIME_WAIT);
315 start_timewait_timer(s);
316 send_ack(s, pstruEventDetails->dEventTime, s->tcb->SND.NXT+1, s->tcb->SEG.SEQ+1);
318 case TCPCONNECTION_CLOSE_WAIT:
319 case TCPCONNECTION_CLOSING:
320 case TCPCONNECTION_LAST_ACK:
323 case TCPCONNECTION_TIME_WAIT:
324 s->tcb->istimewaittimerrestarted =
true;
325 start_timewait_timer(s);
328 fnNetSimError(
"Unknown tcp state %d", s->tcb->tcp_state);
332 fn_NetSim_Packet_FreePacket(p);
333 pstruEventDetails->pPacket = NULL;
336static bool check_segment(PNETSIM_SOCKET s, NetSim_PACKET* p)
338 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(p);
339 if (s->tcb->RCV.NXT == hdr->SeqNum)
341 s->tcb->RCV.NXT += s->tcb->SEG.LEN;
343 check_segment_in_queue(s);
346 else if ((s->tcb->RCV.NXT > hdr->SeqNum))
349 s->tcpMetrics->dupSegmentReceived++;
354 s->tcpMetrics->outOfOrderSegmentReceived++;
355 if (isSegmentInQueue(&s->tcb->outOfOrderSegment, p))
356 s->tcpMetrics->dupSegmentReceived++;
358 add_packet_to_queue(&s->tcb->outOfOrderSegment, p, pstruEventDetails->dEventTime);
363static bool process_segment_text(PNETSIM_SOCKET s, NetSim_PACKET* p)
365 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(p);
368 fprintf(fp,
"%lf,%d,,,,,\n",
369 pstruEventDetails->dEventTime,
374 write_congestion_plot(s, p);
375 s->tcpMetrics->segmentReceived++;
380 PTSopt tsopt = get_tcp_option(hdr,
381 TCP_OPTION_TIMESTAMP);
382 set_timestamp_value(s, hdr, tsopt);
385 if (s->tcb->tcp_state == TCPCONNECTION_ESTABLISHED ||
386 s->tcb->tcp_state == TCPCONNECTION_FIN_WAIT_1 ||
387 s->tcb->tcp_state == TCPCONNECTION_FIN_WAIT_2)
389 bool isinorder = check_segment(s, p);
391 if((!isinorder || send_ack_or_not(s)) && !hdr->Fin)
392 send_ack(s, pstruEventDetails->dEventTime, s->tcb->SND.NXT, s->tcb->RCV.NXT);
395 send_to_application(s, p);
403 else if (s->tcb->tcp_state == TCPCONNECTION_CLOSE_WAIT ||
404 s->tcb->tcp_state == TCPCONNECTION_CLOSING ||
405 s->tcb->tcp_state == TCPCONNECTION_LAST_ACK ||
406 s->tcb->tcp_state == TCPCONNECTION_TIME_WAIT)
408 fn_NetSim_Packet_FreePacket(p);
409 pstruEventDetails->pPacket = NULL;
412 else if (s->tcb->tcp_state == TCPCONNECTION_SYN_RECEIVED)
415 fn_NetSim_Packet_FreePacket(p);
416 pstruEventDetails->pPacket = NULL;
421 fnNetSimError(
"Unknown TCP connection state %s in %s",
422 state_to_str(s->tcb->tcp_state),
424 fn_NetSim_Packet_FreePacket(p);
425 pstruEventDetails->pPacket = NULL;
430void packet_arrives_at_incoming_tcp(PNETSIM_SOCKET s, NetSim_PACKET* p)
437 fp = fopen(
"IncomingTCP.csv",
"w");
438 fprintf(fp,
"Time,Seq,,,Ack\n");
443 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(p);
445 bool isValidSeg = Validate_segment(s);
450 process_rst_packet(s, p);
452 process_syn_packet(s, p);
454 process_ack_packet(s, p);
457 isContinue = process_segment_text(s, p);
459 if (isContinue && hdr->Fin)
460 process_fin_packet(s, p);
465 print_tcp_log(
"unacceptable segment");
469 pstruEventDetails->dEventTime,
473 fn_NetSim_Packet_FreePacket(p);
474 pstruEventDetails->pPacket = NULL;