Skip to content

Commit 94a9fdd

Browse files
fix: retransmit SYN-ACK if it goes missing (#277)
This PR makes hosts retransmit SYN-ACKs if they go missing. It also adds a check that was missing, which responds to wrong sequence numbers with ACK segments. --------- Co-authored-by: Pedro Gallino <[email protected]>
1 parent c8ca970 commit 94a9fdd

File tree

1 file changed

+23
-5
lines changed

1 file changed

+23
-5
lines changed

src/types/network-modules/tcp/tcpState.ts

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,9 @@ export class TcpState {
184184

185185
// Move to SYN_SENT state
186186
this.state = TcpStateEnum.SYN_SENT;
187+
// NOTE: according to the RFC, we should return immediately,
188+
// but here we wait for the connection to be established.
189+
// This is done to make visualizations easier.
187190
return await this.connectionQueue.pop();
188191
}
189192

@@ -202,10 +205,7 @@ export class TcpState {
202205
this.initialRecvSeqNum = synSegment.sequenceNumber;
203206

204207
// Send a SYN-ACK
205-
const flags = new Flags().withSyn().withAck();
206-
const segment = this.newSegment(this.initialSendSeqNum, this.recvNext);
207-
208-
if (!sendIpPacket(this.srcHost, this.dstHost, segment.withFlags(flags))) {
208+
if (!this.sendSynSegment()) {
209209
return false;
210210
}
211211
this.rttEstimator.startMeasurement(this.initialSendSeqNum);
@@ -340,6 +340,12 @@ export class TcpState {
340340
const segLen = segment.data.length;
341341
if (!this.isSeqNumValid(segSeq, segLen)) {
342342
console.debug("Sequence number not valid");
343+
344+
// RFC 5961 suggests sending a challenge ACK, but here we keep things simple
345+
// If RST is not set, send an ACK in response
346+
if (!flags.rst) {
347+
this.notifySendPackets();
348+
}
343349
return ProcessingResult.DISCARD;
344350
}
345351

@@ -775,9 +781,21 @@ export class TcpState {
775781
this.tcpQueue.close();
776782
}
777783

784+
/**
785+
* Sends a SYN or SYN-ACK segment
786+
*/
778787
private sendSynSegment() {
788+
let ack = 0;
779789
const flags = new Flags().withSyn();
780-
const segment = this.newSegment(this.initialSendSeqNum, 0).withFlags(flags);
790+
791+
if (this.recvNext) {
792+
// It's a SYN-ACK
793+
ack = this.recvNext;
794+
flags.withAck();
795+
}
796+
const segment = this.newSegment(this.initialSendSeqNum, ack);
797+
segment.withFlags(flags);
798+
781799
if (!sendIpPacket(this.srcHost, this.dstHost, segment)) {
782800
console.warn(
783801
`Device ${this.srcHost.id} couldn't send SYN to device ${this.dstHost.id}.`,

0 commit comments

Comments
 (0)