NetSim Source Code Help v14.4
All 13 Components
 
Loading...
Searching...
No Matches
TCP_Connection.c
1/************************************************************************************
2* Copyright (C) 2023 *
3* TETCOS, Bangalore. India *
4* *
5* Tetcos owns the intellectual property rights in the Product and its content. *
6* The copying, redistribution, reselling or publication of any or all of the *
7* Product or its content without express prior written consent of Tetcos is *
8* prohibited. Ownership and / or any other right relating to the software and all *
9* intellectual property rights therein shall remain at all times with Tetcos. *
10* *
11* This source code is licensed per the NetSim license agreement. *
12* *
13* No portion of this source code may be used as the basis for a derivative work, *
14* or used, for any purpose other than its intended use per the NetSim license *
15* agreement. *
16* *
17* This source code and the algorithms contained within it are confidential trade *
18* secrets of TETCOS and may not be used as the basis for any other software, *
19* hardware, product or service. *
20* *
21* Author: Shashi Kant Suman *
22* *
23* ----------------------------------------------------------------------------------*/
24#include "main.h"
25#include "TCP.h"
26#include "List.h"
27#include "TCP_Header.h"
28
29//Function prototype
30static void send_syn(PNETSIM_SOCKET s);
31
32void tcp_active_open(PNETSIM_SOCKET s)
33{
34 print_tcp_log("Creating TCB");
35 create_TCB(s);
36 print_tcp_log("Sending Syn");
37 send_syn(s);
38}
39
40void tcp_passive_open(PNETSIM_SOCKET s, PNETSIM_SOCKET ls)
41{
42 print_tcp_log("Creating TCB");
43 create_TCB(s);
44 memcpy(&s->tcb->SEG, &ls->tcb->SEG, sizeof s->tcb->SEG);
45 tcp_change_state(s, TCPCONNECTION_LISTEN);
46}
47
48static void send_syn(PNETSIM_SOCKET s)
49{
50 NetSim_PACKET* syn = create_syn(s,pstruEventDetails->dEventTime);
51
52 s->tcb->SND.UNA = s->tcb->ISS;
53 s->tcb->SND.NXT = s->tcb->ISS + 1;
54 tcp_change_state(s, TCPCONNECTION_SYN_SENT);
55
56 s->tcb->synRetries++;
57
58 s->tcpMetrics->synSent++;
59
60 send_to_network(syn, s);
61 add_timeout_event(s,syn);
62}
63
64void resend_syn(PNETSIM_SOCKET s)
65{
66 PTCP_DEV_VAR tcp = GET_TCP_DEV_VAR(pstruEventDetails->nDeviceId);
67
68 if (s->tcb->tcp_state != TCPCONNECTION_SYN_SENT &&
69 s->tcb->tcp_state != TCPCONNECTION_SYN_RECEIVED)
70 {
71 print_tcp_log("ERROR: %s is called for different TCP state %s. it must be %s or %s",
72 __FUNCTION__,
73 state_to_str(s->tcb->tcp_state),
74 state_to_str(TCPCONNECTION_SYN_SENT),
75 state_to_str(TCPCONNECTION_SYN_RECEIVED));
76 assert(false);
77 }
78
79 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(pstruEventDetails->pPacket);
80
81 NetSim_PACKET* syn = get_segment_from_queue(&s->tcb->retransmissionQueue, hdr->SeqNum);
82
83 fn_NetSim_Packet_FreePacket(pstruEventDetails->pPacket);
84 pstruEventDetails->pPacket = NULL;
85
86 if (s->tcb->synRetries < tcp->MaxSynRetries)
87 {
88 print_tcp_log("Resending syn/syn-ack packet.");
89 s->tcb->SND.UNA = s->tcb->ISS;
90 s->tcb->SND.NXT = s->tcb->ISS + 1;
91
92 send_to_network(syn, s);
93 add_timeout_event(s, syn);
94
95 if(syn->nControlDataType == TCPPACKET_SYN)
96 s->tcpMetrics->synSent++;
97 else
98 s->tcpMetrics->synAckSent++;
99
100 s->tcb->synRetries++;
101 }
102 else
103 {
104 print_tcp_log("Connection fails for local address %s:%d, Remote address %s:%d",
105 s->localAddr->ip->str_ip,
106 s->localAddr->port,
107 s->remoteAddr->ip->str_ip,
108 s->remoteAddr->port);
109 tcp_close_socket(s,pstruEventDetails->nDeviceId);
110 }
111}
112
113void process_syn(PNETSIM_SOCKET s,NetSim_PACKET* p)
114{
115 if (!s->localAddr)
116 {
117 s->listen_callback(s, p);
118 }
119 else
120 {
121 if ((s->tcb->IRS && s->tcb->IRS != s->tcb->SEG.SEQ) ||
122 (s->tcb->RCV.NXT && s->tcb->RCV.NXT != s->tcb->SEG.SEQ +1))
123 {
124 //send_rst(s, p, 1); //RFC 793
125 //Correction made by RFC 1122. Page93
126 send_rst(s, p, 2);
127 }
128 else
129 {
130 s->listen_callback(s, p);
131 }
132 }
133 fn_NetSim_Packet_FreePacket(p);
134}
135
136void rcv_SYN(PNETSIM_SOCKET s, NetSim_PACKET* syn)
137{
138 s->tcb->RCV.NXT = s->tcb->SEG.SEQ + 1;
139 s->tcb->IRS = s->tcb->SEG.SEQ;
140
141 //Store the Window scale option based on peer device
142 PWsopt wsopt = get_tcp_option(TCP_GET_SEGMENT_HDR(syn),
143 TCP_OPTION_WINDOW_SCALE);
144
145 set_window_scaling(s, wsopt);
146
147 //Store MSS based on peer device
148 PMSS_OPTION opt = get_tcp_option(TCP_GET_SEGMENT_HDR(syn),TCP_OPTION_MSS);
149 if (opt)
150 s->tcb->set_MSS(s, opt->MSSData);
151
152 //Store the timestamps option based on peer device
153 PTSopt tsopt = get_tcp_option(TCP_GET_SEGMENT_HDR(syn),
154 TCP_OPTION_TIMESTAMP);
155 set_timestamp_value(s, TCP_GET_SEGMENT_HDR(syn), tsopt);
156
157 if (s->tcb->isSackPermitted)
158 {
159 //Store Sack option based on peer device
160 PSACKPERMITTED_OPTION sackp = get_tcp_option(TCP_GET_SEGMENT_HDR(syn), TCP_OPTION_SACK_PERMITTED);
161 if (sackp)
162 s->tcb->isSackPermitted = true;
163 else
164 s->tcb->isSackPermitted = false;
165 }
166
167 NetSim_PACKET* synAck = create_synAck(s, pstruEventDetails->dEventTime);
168 tcp_change_state(s, TCPCONNECTION_SYN_RECEIVED);
169
170 s->tcb->SND.UNA = s->tcb->ISS;
171 s->tcb->SND.NXT = s->tcb->ISS + 1;
172
173 s->tcb->synRetries++;
174
175 s->tcpMetrics->synAckSent++;
176
177 send_to_network(synAck, s);
178 add_timeout_event(s, synAck);
179}
180
181void send_rst(PNETSIM_SOCKET s, NetSim_PACKET* p, UINT c)
182{
183 print_tcp_log("Sending RST packet");
184 NetSim_PACKET* rst = create_rst(p, pstruEventDetails->dEventTime, c);
185 send_to_network(rst, s);
186}
187
188void send_ack(PNETSIM_SOCKET s, double time, UINT32 seqNo, UINT32 ackNo)
189{
190 print_tcp_log("Sending ack with seq=%d, Ack=%d.", seqNo, ackNo);
191 NetSim_PACKET* ack = create_ack(s, time, seqNo, ackNo);
192 s->tcpMetrics->ackSent++;
193 send_to_network(ack, s);
194}
195
196void send_fin_ack(PNETSIM_SOCKET s, double time, UINT32 seqNo, UINT32 ackNo)
197{
198 print_tcp_log("Sending fin-ack with seq=%d, Ack=%d.", seqNo, ackNo);
199 NetSim_PACKET* ack = create_ack(s, time, seqNo, ackNo);
200 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(ack);
201 hdr->Fin = 1;
202 s->tcpMetrics->ackSent++;
203 send_to_network(ack, s);
204}
205
206void packet_arrive_at_closed_state(PNETSIM_SOCKET s, NetSim_PACKET* p)
207{
208 print_tcp_log("TCP_STATE=CLOSED");
209 if (isTCPControl(p))
210 {
211 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(p);
212 if (hdr->Rst)
213 goto DISCARD_PACKET;
214 else
215 {
216 send_rst(s, p, 0);
217 goto FREE_SEGMENT;
218 }
219 }
220 else
221 goto DISCARD_PACKET;
222
223DISCARD_PACKET:
224 //Discard packet
225 print_tcp_log("Discarding segment");
226FREE_SEGMENT:
227 fn_NetSim_Packet_FreePacket(p);
228 pstruEventDetails->pPacket = NULL;
229}
230
231void packet_arrives_at_listen_state(PNETSIM_SOCKET s, NetSim_PACKET* p)
232{
233 print_tcp_log("TCP_STATE=LISTEN");
234 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(p);
235 if (hdr->Rst)
236 goto DISCARD_PACKET;
237 else if (hdr->Ack)
238 {
239 send_rst(s, p, 0);
240 goto FREE_SEGMENT;
241 }
242 else if (hdr->Syn)
243 {
244 process_syn(s, p);
245 return;
246 }
247 else
248 fnNetSimError("Unknown processing mode in %s",
249 __FUNCTION__);
250
251
252DISCARD_PACKET:
253 print_tcp_log("Discarding Packet");
254FREE_SEGMENT:
255 fn_NetSim_Packet_FreePacket(p);
256 pstruEventDetails->pPacket = NULL;
257}
258
259void packet_arrives_at_synsent_state(PNETSIM_SOCKET s, NetSim_PACKET* p)
260{
261 bool isAckAcceptable = false;
262 print_tcp_log("TCP_STATE = SYN-SENT");
263
264 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(p);
265 if (hdr->Ack)
266 {
267 if (s->tcb->SEG.ACK <= s->tcb->ISS ||
268 s->tcb->SEG.ACK > s->tcb->SND.NXT)
269 {
270 send_rst(s, p, 0);
271 goto FREE_SEGMENT;
272 }
273
274 if (s->tcb->SND.UNA <= s->tcb->SEG.ACK &&
275 s->tcb->SEG.ACK <= s->tcb->SND.NXT)
276 isAckAcceptable = true;
277 }
278 if (hdr->Rst)
279 {
280 if (isAckAcceptable)
281 {
282 print_tcp_log("Error: Connection reset");
283 delete_tcb(s);
284 tcp_change_state(s, TCPCONNECTION_CLOSED);
285 tcp_close_socket(s, s->localDeviceId);
286 return;
287 }
288 else
289 {
290 goto DISCARD_PACKET;
291 }
292 }
293 if (isAckAcceptable)
294 {
295 if (hdr->Syn)
296 {
297 s->tcb->RCV.NXT = s->tcb->SEG.SEQ + 1;
298 s->tcb->IRS = s->tcb->SEG.SEQ;
299 s->tcb->SND.UNA = s->tcb->SEG.ACK;
300
301 //Store MSS based on peer device
302 PMSS_OPTION opt = get_tcp_option(hdr, TCP_OPTION_MSS);
303 if (opt)
304 s->tcb->set_MSS(s, opt->MSSData);
305
306 if (s->tcb->isTSopt)
307 {
308 //Store the timestamps option based on peer device
309 PTSopt tsopt = get_tcp_option(hdr,
310 TCP_OPTION_TIMESTAMP);
311 set_timestamp_value(s, hdr, tsopt);
312 }
313
314 delete_segment_from_queue(&s->tcb->retransmissionQueue, s->tcb->SEG.ACK);
315
316 if (s->tcb->SND.UNA > s->tcb->ISS)
317 {
318 //Correction made by RFC 1122. Page 93.
319 s->tcb->SND.WND = s->tcb->SEG.WND;
320 s->tcb->SND.WL1 = s->tcb->SEG.SEQ;
321 s->tcb->SND.WL2 = s->tcb->SEG.ACK;
322
323 send_ack(s,
324 pstruEventDetails->dEventTime,
325 s->tcb->SND.NXT,
326 s->tcb->RCV.NXT);
327 tcp_change_state(s, TCPCONNECTION_ESTABLISHED);
328 send_segment(s);
329 return;
330 }
331 }
332 }
333
334DISCARD_PACKET:
335 print_tcp_log("Discarding Packet");
336FREE_SEGMENT:
337 fn_NetSim_Packet_FreePacket(p);
338 pstruEventDetails->pPacket = NULL;
339}
340
341void send_fin(PNETSIM_SOCKET s)
342{
343 static bool isShowError = true;
344 NetSim_PACKET* fin = create_fin(s, pstruEventDetails->dEventTime);
345
346 send_to_network(fin, s);
347
348#ifdef _DEBUG
349 if(isShowError)
350 fnNetSimError("RTO timeout is not implemented for FIN");
351 isShowError = false;
352 //add_timeout_event(s, fin);
353#endif
354}