Skip to content

Commit aa0e449

Browse files
committed
Version 0.0.1 - Initial implementation
0 parents  commit aa0e449

File tree

8 files changed

+1164
-0
lines changed

8 files changed

+1164
-0
lines changed

.gitignore

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Vim
2+
**.sw*
3+
4+
# Logs
5+
logs
6+
*.log
7+
npm-debug.log*
8+
yarn-debug.log*
9+
yarn-error.log*
10+
11+
# Runtime data
12+
pids
13+
*.pid
14+
*.seed
15+
*.pid.lock
16+
17+
# Dependency directories
18+
node_modules/
19+
20+
# Optional npm cache directory
21+
.npm
22+
23+
# Optional REPL history
24+
.node_repl_history
25+
26+
# Output of 'npm pack'
27+
*.tgz
28+
29+
# dotenv environment variables file
30+
.env
31+

LICENSE

+674
Large diffs are not rendered by default.

README.md

+154
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
2+
NetJam 🕸️
3+
===============
4+
5+
> Network congestion simulator for TCP connections.
6+
7+
8+
Usage
9+
-----
10+
11+
12+
```sh
13+
user@host:~$ npx netjam --help
14+
15+
netjam - Network (TCP) traffic jam simulator.
16+
17+
SYNTAX: npx netjam <remoteHost> <remotePort> [listenPort]
18+
Where:
19+
<remoteHost> Network name or IP of remote host.
20+
<remotePort> Destination port number
21+
[ListenPort] Sourece port number to forward (default = 5000
22+
```
23+
24+
25+
Example
26+
-------
27+
28+
Create a *jamable* TCP tunnel to local PostgreSQL Server listening in its
29+
default port (5432):
30+
31+
```sh
32+
user@host:~$ npx netjam localhost 5432
33+
Server listening on port 5000
34+
35+
STATUS:
36+
┌─────────────┬────────────────────────────┐
37+
│ (index) │ Values │
38+
├─────────────┼────────────────────────────┤
39+
│ remoteHost │ 'localhost'
40+
│ remotePort │ '5432'
41+
│ listenPort │ 5000 │
42+
│ timestamp │ '2024-08-06T18:52:11.042Z'
43+
│ waiting │ 0 │
44+
│ open │ 0 │
45+
│ closed │ 0 │
46+
│ withError │ 0 │
47+
│ tx │ 0 │
48+
│ rx │ 0 │
49+
│ iputDelay │ 0 │
50+
│ outputDelay │ 0 │
51+
│ logInterval │ '0 (Disabled)'
52+
└─────────────┴────────────────────────────┘
53+
54+
AVAILABLE COMMANDS:
55+
inputDelay - Sets input delay to specified value
56+
outputDelay - Sets output delay to specified value
57+
delay - Sets overall balanced delay to specified value
58+
logInterval - Show/Set status (stderr) logging interval in msecs
59+
quit - Quit the program
60+
61+
>
62+
```
63+
64+
> 📌 Now, every time you hit the `Enter` key, you will get an updated *Status
65+
> Report* and a list of available commands.
66+
>
67+
> Additionally, if you set logInterval to a non zero value, it will start
68+
> periodically logging status data in JSON format to *stderr*. You can use below
69+
> command instead of the previous one to keep it apart to a file:
70+
>
71+
> ```sh
72+
> user@host:~$ npx netjam localhost 5432 2> netjam_log.json
73+
> ```
74+
75+
76+
Now you can open another terminal and connect to your local Postgres database
77+
throug port 5000:
78+
79+
```sh
80+
user@host:~$ psql -h localhost -p 5000
81+
Contraseña para usuario user:
82+
user@constructor:~/112/mnt (master)$ LANG=C psql -h localhost -p 5000
83+
Password for user user:
84+
psql (15.7 (Ubuntu 15.7-1.pgdg22.04+1))
85+
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
86+
Type "help" for help.
87+
88+
user=>
89+
```
90+
91+
This is a fully working conection with almost no penalty.
92+
93+
Now, at netjam console, you can, for instance, set a 1 second delay for every
94+
round-trip (tx+rx) connection:
95+
96+
97+
98+
```
99+
> delay 1000
100+
STATUS:
101+
┌─────────────┬────────────────────────────┐
102+
│ (index) │ Values │
103+
├─────────────┼────────────────────────────┤
104+
│ remoteHost │ 'localhost'
105+
│ remotePort │ '5432'
106+
│ listenPort │ 5000 │
107+
│ timestamp │ '2024-08-06T19:02:33.886Z'
108+
│ waiting │ 0 │
109+
│ open │ 3 │
110+
│ closed │ 3 │
111+
│ withError │ 0 │
112+
│ tx │ 20 │
113+
│ rx │ 21 │
114+
│ iputDelay │ 0 │
115+
│ outputDelay │ 500 │
116+
│ inputDelay │ 500 │
117+
│ logInterval │ '0 (Disabled)'
118+
└─────────────┴────────────────────────────┘
119+
120+
AVAILABLE COMMANDS:
121+
inputDelay - Sets input delay to specified value
122+
outputDelay - Sets output delay to specified value
123+
delay - Sets overall balanced delay to specified value
124+
logInterval - Show/Set status (stderr) logging interval in msecs
125+
quit - Quit the program
126+
127+
>
128+
```
129+
130+
Now your PostgreSQL connection still works, but a little bit slower... 😉
131+
132+
133+
<a name="contributing"></a>Contributing
134+
---------------------------------------
135+
136+
If you are interested in contributing with this project, you can do it in many ways:
137+
138+
* Creating and/or mantainig documentation.
139+
140+
* Implementing new features or improving code implementation.
141+
142+
* Reporting bugs and/or fixing it.
143+
144+
* Sending me any other feedback.
145+
146+
* Whatever you like...
147+
148+
Please, contact-me, open issues or send pull-requests thought [this project GIT repository](https://github.com/bitifet/netjam)
149+
150+
151+
License
152+
-------
153+
154+
[GPLv3](LICENSE)

index.js

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/usr/bin/env node
2+
"use strict";
3+
4+
const net = require('net');
5+
6+
const status = require("./src/status");
7+
const handleClient = require("./src/clientHandler");
8+
const {welcome} = require("./src/console");
9+
10+
11+
12+
13+
// Crear el servidor TCP
14+
const server = net.createServer(handleClient);
15+
16+
server.listen(status.listenPort, () => {
17+
console.log(`Server listening on port ${status.listenPort}`);
18+
welcome();
19+
});
20+

package.json

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"name": "netjam",
3+
"version": "0.0.1",
4+
"description": "Network congestion simulator for TCP connections.",
5+
"main": "index.js",
6+
"bin": {
7+
"netjam": "./index.js"
8+
},
9+
"scripts": {
10+
"test": "echo \"Error: no test specified\" && exit 1"
11+
},
12+
"repository": {
13+
"type": "git",
14+
"url": "git+https://github.com/bitifet/netjam.git"
15+
},
16+
"keywords": [
17+
"network",
18+
"congestion",
19+
"bottleneck",
20+
"traffic",
21+
"simulator"
22+
],
23+
"author": "Joan Miquel Torres <[email protected]>",
24+
"license": "GPL-3.0-or-later",
25+
"bugs": {
26+
"url": "https://github.com/bitifet/netjam/issues"
27+
},
28+
"homepage": "https://github.com/bitifet/netjam#readme"
29+
}

src/clientHandler.js

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
"use strict";
2+
const status = require("./status");
3+
const net = require('net');
4+
let connCount = 0;
5+
6+
7+
8+
module.exports = function handleClient(clientSocket) {
9+
///console.log('Client connected:', clientSocket.remoteAddress, clientSocket.remotePort);
10+
11+
const connId = connCount++;
12+
13+
let closed = false;
14+
function flagClosed(hadError) {
15+
if (closed) return;
16+
status.stats.closed++;
17+
if (hadError) status.stats.withError++;
18+
status.allConnections.delete(connId);
19+
closed = true;
20+
};
21+
22+
status.stats.waiting++;
23+
24+
// Crear un socket per a connectar al servidor remot
25+
const remoteSocket = new net.Socket();
26+
27+
28+
status.allConnections.set(connId, {
29+
clientSocket,
30+
remoteSocket,
31+
});
32+
33+
34+
remoteSocket.connect(status.remotePort, status.remoteHost, (c) => {
35+
///console.log('Connected to remote server');
36+
status.stats.open++;
37+
status.stats.waiting--;
38+
});
39+
40+
// Manejar dades del client
41+
clientSocket.on('data', (data) => {
42+
43+
///console.log('Data from client:', data.toString());
44+
status.stats.tx++;
45+
46+
// Implementar un retard de 1 segon abans d'enviar les dades al servidor remot
47+
setTimeout(() => {
48+
remoteSocket.write(data);
49+
}, status.cfg.outputDelay);
50+
});
51+
52+
// Manejar dades del servidor remot
53+
remoteSocket.on('data', (data) => {
54+
55+
///console.log('Data from remote server:', data.toString());
56+
status.stats.rx++;
57+
58+
// Implementar un retard de 1 segon abans d'enviar les dades al client
59+
setTimeout(() => {
60+
clientSocket.write(data);
61+
}, status.cfg.inputDelay);
62+
});
63+
64+
// Manejar el tancament de la connexió del client
65+
clientSocket.on('close', (hadError) => {
66+
///console.log('Client connection closed', hadError ? 'with error' : 'cleanly');
67+
flagClosed(hadError);
68+
remoteSocket.end();
69+
});
70+
71+
// Manejar el tancament de la connexió remota
72+
remoteSocket.on('close', (hadError) => {
73+
///console.log('Remote connection closed', hadError ? 'with error' : 'cleanly');
74+
flagClosed(hadError);
75+
clientSocket.end();
76+
});
77+
78+
// Manejar errors de connexió del client
79+
clientSocket.on('error', (err) => {
80+
///console.error('Client socket error:', err);
81+
flagClosed(true);
82+
remoteSocket.destroy();
83+
});
84+
85+
// Manejar errors de connexió remota
86+
remoteSocket.on('error', (err) => {
87+
///console.error('Remote socket error:', err);
88+
flagClosed(true);
89+
clientSocket.destroy();
90+
});
91+
};

0 commit comments

Comments
 (0)