Skip to content

Commit 9e79323

Browse files
authored
feat: allow switching between TCP Reno and Tahoe versions (#237)
Closes #222 Depends on #236 This PR allows switching between TCP Reno and Tahoe versions.
1 parent 071249d commit 9e79323

File tree

5 files changed

+89
-15
lines changed

5 files changed

+89
-15
lines changed

src/config.ts

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,15 @@ export class ConfigModal {
1212
private colorPicker: HTMLInputElement | null;
1313
private selectedColor: number; // Stores the actual selected color as a number
1414
private tempColor: number; // Temporary color for selection
15+
1516
private enableTooltipsSwitch: HTMLInputElement | null;
1617
private enableTooltips: boolean;
1718
private tempEnableTooltips: boolean;
1819

20+
private useTcpRenoSwitch: HTMLInputElement | null;
21+
private useTcpReno: boolean;
22+
private tempUseTcpReno: boolean;
23+
1924
constructor(ctx: GlobalContext) {
2025
this.ctx = ctx;
2126
this.modalOverlay = null;
@@ -27,6 +32,8 @@ export class ConfigModal {
2732
this.tempColor = this.selectedColor; // Temporary color for selection
2833
this.enableTooltips = true; // Default saved value
2934
this.tempEnableTooltips = this.enableTooltips; // Temporary value for selection
35+
this.useTcpReno = true; // Default saved value
36+
this.tempUseTcpReno = this.useTcpReno; // Temporary value for selection
3037

3138
this.createModal();
3239
this.setupEventListeners();
@@ -83,6 +90,13 @@ export class ConfigModal {
8390
<span class="switch-slider"></span>
8491
</label>
8592
</li>
93+
<li class="setting-item">
94+
<label for="useTcpReno">Use TCP Reno</label>
95+
<label class="switch">
96+
<input type="checkbox" id="useTcpReno" class="switch-input" checked>
97+
<span class="switch-slider"></span>
98+
</label>
99+
</li>
86100
</ul>
87101
</div>
88102
</div>
@@ -111,6 +125,9 @@ export class ConfigModal {
111125
this.enableTooltipsSwitch = document.getElementById(
112126
"enableTooltips",
113127
) as HTMLInputElement;
128+
this.useTcpRenoSwitch = document.getElementById(
129+
"useTcpReno",
130+
) as HTMLInputElement;
114131
}
115132

116133
private setupEventListeners() {
@@ -120,7 +137,8 @@ export class ConfigModal {
120137
!this.closeBtn ||
121138
!this.saveSettingsButton ||
122139
!this.colorPicker ||
123-
!this.enableTooltipsSwitch
140+
!this.enableTooltipsSwitch ||
141+
!this.useTcpRenoSwitch
124142
) {
125143
console.error("Some modal elements were not found.");
126144
return;
@@ -152,6 +170,12 @@ export class ConfigModal {
152170
this.tempEnableTooltips = isEnabled; // Update the local variable only
153171
console.log("Tooltips setting changed (not saved yet):", isEnabled);
154172
};
173+
174+
this.useTcpRenoSwitch.onchange = () => {
175+
const isEnabled = this.useTcpRenoSwitch?.checked || false;
176+
this.tempUseTcpReno = isEnabled; // Update the local variable only
177+
console.log("TCP Reno setting changed (not saved yet):", isEnabled);
178+
};
155179
}
156180

157181
private setUpShortCuts() {
@@ -192,6 +216,11 @@ export class ConfigModal {
192216
this.enableTooltipsSwitch.checked = this.tempEnableTooltips; // Reflect the saved value in the UI
193217
}
194218

219+
if (this.useTcpRenoSwitch) {
220+
this.tempUseTcpReno = this.useTcpReno;
221+
this.useTcpRenoSwitch.checked = this.tempUseTcpReno; // Reflect the saved value in the UI
222+
}
223+
195224
this.modalOverlay.style.display = "flex"; // Make it visible first
196225
setTimeout(() => {
197226
this.modalOverlay?.classList.add("show");
@@ -223,27 +252,45 @@ export class ConfigModal {
223252
this.tempEnableTooltips = this.enableTooltips; // Reset temp value
224253
this.enableTooltipsSwitch.checked = this.enableTooltips; // Reflect saved value in UI
225254
}
255+
256+
if (this.useTcpRenoSwitch) {
257+
this.tempUseTcpReno = this.useTcpReno; // Reset temp value
258+
this.useTcpRenoSwitch.checked = this.useTcpReno; // Reflect saved value in UI
259+
}
226260
}
227261

228262
private saveSettings() {
229263
// Save the temp color as the actual selected color
230264
if (this.tempColor != this.selectedColor) {
231265
this.selectedColor = this.tempColor;
232-
this.ctx.change_select_color(this.selectedColor);
266+
this.ctx.setSelectColor(this.selectedColor);
233267
}
234268

269+
let updateTooltips = false;
270+
235271
// Save the tooltips setting
236272
if (this.enableTooltipsSwitch) {
237273
this.enableTooltips = this.tempEnableTooltips; // Save the temporary value
238-
this.ctx.change_enable_tooltips(this.enableTooltips); // Update the GlobalContext
239-
updateTooltipsState(); // Update tooltips state in the app
274+
this.ctx.setEnableTooltips(this.enableTooltips); // Update the GlobalContext
275+
updateTooltips = true;
276+
}
277+
278+
if (this.useTcpRenoSwitch) {
279+
this.useTcpReno = this.tempUseTcpReno; // Save the temporary value
280+
this.ctx.setUseTcpReno(this.useTcpReno); // Update the GlobalContext
281+
updateTooltips = true;
240282
}
241283

284+
if (updateTooltips) {
285+
updateTooltipsState(); // Update tooltips state in the app
286+
}
242287
console.log(
243288
"Settings saved. Applied color:",
244289
this.selectedColor,
245290
"Tooltips enabled:",
246291
this.enableTooltips,
292+
"TCP Reno enabled:",
293+
this.useTcpReno,
247294
);
248295
}
249296

src/context.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@ export class GlobalContext {
2525
private saveIntervalId: NodeJS.Timeout | null = null;
2626
private ipGenerator: IpAddressGenerator;
2727
private macGenerator: MacAddressGenerator;
28+
29+
// Settings
2830
private selectColor: number;
2931
private tooltipsEnabled: boolean;
32+
private useTcpReno: boolean;
3033

3134
constructor(viewport: Viewport) {
3235
this.selectColor = Colors.Violet;
@@ -203,19 +206,27 @@ export class GlobalContext {
203206
console.log(this.datagraph);
204207
}
205208

206-
public change_select_color(color: number) {
209+
setSelectColor(color: number) {
207210
this.selectColor = color;
208211
}
209212

210-
public get_select_color() {
213+
getSelectColor() {
211214
return this.selectColor;
212215
}
213216

214-
public change_enable_tooltips(enabled: boolean) {
217+
setEnableTooltips(enabled: boolean) {
215218
this.tooltipsEnabled = enabled;
216219
}
217220

218-
public get_enable_tooltips() {
221+
getEnableTooltips() {
219222
return this.tooltipsEnabled;
220223
}
224+
225+
setUseTcpReno(enabled: boolean) {
226+
this.useTcpReno = enabled;
227+
}
228+
229+
getUseTcpReno() {
230+
return this.useTcpReno;
231+
}
221232
}

src/graphics/renderables/tooltip_manager.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export function attachTooltip(
2323
key: string,
2424
hideDelay = false,
2525
): void {
26-
const tooltipsEnabled = globalContext?.get_enable_tooltips() ?? true;
26+
const tooltipsEnabled = globalContext?.getEnableTooltips() ?? true;
2727

2828
if (key in TOOLTIP_CONTENT) {
2929
if (tooltipsEnabled) {
@@ -66,7 +66,7 @@ export function attachTooltip(
6666
* @param key - The key for the tooltip content.
6767
*/
6868
export function showTooltip(key: string): void {
69-
const tooltipsEnabled = globalContext?.get_enable_tooltips() ?? true;
69+
const tooltipsEnabled = globalContext?.getEnableTooltips() ?? true;
7070
if (!tooltipsEnabled) return;
7171

7272
const text = TOOLTIP_CONTENT[key as keyof typeof TOOLTIP_CONTENT];
@@ -107,7 +107,7 @@ export function hideTooltip(): void {
107107
* Updates the state of tooltips (enabled/disabled).
108108
*/
109109
export function updateTooltipsState(): void {
110-
const tooltipsEnabled = globalContext?.get_enable_tooltips() ?? true;
110+
const tooltipsEnabled = globalContext?.getEnableTooltips() ?? true;
111111

112112
// Select all elements with the "has-tooltip" class
113113
const tooltipElements = document.querySelectorAll(".has-tooltip");

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

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ export class TcpState {
125125
private initialRecvSeqNum: number;
126126

127127
private rttEstimator: RTTEstimator;
128-
private congestionControl = new CongestionControl();
128+
private congestionControl: CongestionControl;
129129

130130
constructor(
131131
srcHost: ViewHost,
@@ -148,6 +148,10 @@ export class TcpState {
148148
this.rttEstimator,
149149
);
150150

151+
this.congestionControl = new CongestionControl(
152+
this.srcHost.ctx.getUseTcpReno(),
153+
);
154+
151155
this.mainLoop();
152156
}
153157

@@ -383,6 +387,8 @@ export class TcpState {
383387
? (segment.sequenceNumber + 1) % u32_MODULUS
384388
: segment.sequenceNumber;
385389
if (seqNum > this.recvNext) {
390+
// Send a possibly duplicate ACK
391+
this.notifySendPackets();
386392
// Postpone the segment
387393
return ProcessingResult.POSTPONE;
388394
} else if (seqNum < this.recvNext) {
@@ -838,21 +844,31 @@ type CongestionControlStateBehavior =
838844
class CongestionControl {
839845
private state: CongestionControlState;
840846
private stateBehavior: CongestionControlStateBehavior;
847+
private useFastRecovery: boolean;
841848

842-
constructor() {
849+
constructor(useFastRecovery: boolean) {
843850
this.state = {
844851
cwnd: 1 * MAX_SEGMENT_SIZE,
845852
ssthresh: Infinity,
846853
dupAckCount: 0,
847854
};
848855
this.stateBehavior = new SlowStart();
856+
this.useFastRecovery = useFastRecovery;
849857
}
850858

851859
getCwnd(): number {
852860
return this.state.cwnd;
853861
}
854862

855863
notifyDupAck(): boolean {
864+
if (!this.useFastRecovery) {
865+
this.state.dupAckCount++;
866+
const isThreeDupAcks = this.state.dupAckCount === 3;
867+
if (isThreeDupAcks) {
868+
this.notifyTimeout();
869+
}
870+
return isThreeDupAcks;
871+
}
856872
this.stateBehavior.handleAck(this.state, 0);
857873
return this.state.dupAckCount === 3;
858874
}

src/types/view-devices/vDevice.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,11 +260,11 @@ export abstract class ViewDevice extends Container {
260260
this.highlightMarker.roundRect(-width / 2, -height / 2, width, height, 5);
261261
this.highlightMarker.stroke({
262262
width: 3,
263-
color: this.ctx.get_select_color(),
263+
color: this.ctx.getSelectColor(),
264264
alpha: 0.6,
265265
});
266266
this.highlightMarker.fill({
267-
color: this.ctx.get_select_color(),
267+
color: this.ctx.getSelectColor(),
268268
alpha: 0.1,
269269
});
270270
this.highlightMarker.zIndex = ZIndexLevels.Device;

0 commit comments

Comments
 (0)