This commit is contained in:
Daniel Flanagan 2022-06-24 23:11:49 -05:00
parent 8d2567cb5a
commit 3407774a1a
Signed by: lytedev
GPG Key ID: 5B2020A0F9921EF4
2 changed files with 57 additions and 3 deletions

20
readme.md Normal file
View File

@ -0,0 +1,20 @@
# tcplexer
`tcplexer` is a tiny Deno app that receives TCP packets from one socket and
copies those packets' contents to them all connected clients on another socket.
# Example Usage
```bash
SOURCE_PORT=7517 CLIENT_PORT=7518 deno run --allow-net --allow-env tcplexer.ts &
ffmpeg -i 'rtsp://admin:pass@10.0.0.104' -vn \
-i 'rtsp://admin:pass@10.0.0.222' -vn \
-ac 1 -filter_complex amerge=inputs=2 \
-hide_banner -loglevel error -f mp3 - \
| netcat localhost 7517
vlc 'tcp://localhost:7518'
```
> TODO: show client with mpv or cvlc or something

40
tcplexer.ts Normal file → Executable file
View File

@ -1,10 +1,21 @@
#!/usr/bin/env -S deno run --allow-net --allow-env
import { iterateReader } from "https://deno.land/std@0.145.0/streams/conversion.ts"; import { iterateReader } from "https://deno.land/std@0.145.0/streams/conversion.ts";
const clients: Set<Deno.Conn> = new Set(); const clients: Set<Deno.Conn> = new Set();
(async () => { (async () => {
try { try {
const sourceListener = Deno.listen({ port: 8080 }); const sourcePort = parseInt(Deno.env.get("SOURCE_PORT") || "") || 0;
const sourceSockOpts = {
port: sourcePort,
};
const sourceListener = Deno.listen(sourceSockOpts);
console.info(
"Listening for source connections on port",
(sourceListener.addr as Deno.NetAddr).port,
);
for await (const source of sourceListener) { for await (const source of sourceListener) {
console.info("Source connected from", source.remoteAddr); console.info("Source connected from", source.remoteAddr);
for await (const packet of iterateReader(source)) { for await (const packet of iterateReader(source)) {
@ -18,13 +29,23 @@ const clients: Set<Deno.Conn> = new Set();
console.info(`Source disconnected from`, source.remoteAddr); console.info(`Source disconnected from`, source.remoteAddr);
} }
} catch (err) { } catch (err) {
console.error("Error listening for TCP connections on port 8080:", err); console.error("Error listening for source TCP connections:", err);
Deno.exit(1);
} }
})(); })();
(async () => { (async () => {
try { try {
const clientsListener = Deno.listen({ port: 8081 }); const clientPort = parseInt(Deno.env.get("CLIENT_PORT") || "") || 0;
const clientSockOpts = {
port: clientPort,
};
const clientsListener = Deno.listen(clientSockOpts);
console.info(
"Listening for client connections on port",
(clientsListener.addr as Deno.NetAddr).port,
);
while (true) { while (true) {
try { try {
const conn = await clientsListener.accept(); const conn = await clientsListener.accept();
@ -38,3 +59,16 @@ const clients: Set<Deno.Conn> = new Set();
console.error("Error listening for TCP connections on port 8081:", err); console.error("Error listening for TCP connections on port 8081:", err);
} }
})(); })();
/* stdin
(async () => {
for await (const packet of iterateReader(Deno.stdin)) {
clients.forEach((client, _v2, _set) =>
client.write(packet).catch(() => {
console.log(`Client disconnected from`, client.remoteAddr);
clients.delete(client);
})
);
}
})();
*/