126 lines
3.3 KiB
Markdown
126 lines
3.3 KiB
Markdown
|
+++
|
||
|
title = 'Command Line Call'
|
||
|
date = 2024-05-27T20:15:23-05:00
|
||
|
draft = true
|
||
|
+++
|
||
|
|
||
|
# Calling from the command line
|
||
|
|
||
|
I was thinking about setting up Jitsi recently and have been researching internet audio and video calling.
|
||
|
|
||
|
# One to one example code
|
||
|
```bash
|
||
|
# Record audio and send it to whatever's listening on 127.0.0.1:6969
|
||
|
arecord -f S16 -r 48000 - | nc -u 127.0.0.1 6969
|
||
|
# Receive audio from port 6969 and play it
|
||
|
nc -lvp 6969 | aplay -f S16 -r 48000 -
|
||
|
```
|
||
|
|
||
|
# Multiple people chat example
|
||
|
|
||
|
## Client(s)
|
||
|
|
||
|
```bash
|
||
|
# Record audio and send it to whatever's listening on 127.0.0.1:6969
|
||
|
#arecord -f S16 -r 48000 - | nc -u 127.0.0.1 6969
|
||
|
# Receive audio from port 6969 and play it
|
||
|
#nc -u <server> 6970 | aplay -f S16 -r 48000 -
|
||
|
arecord -f S16 -r 48000 - | nc -u <server> 6969 | aplay -f S16 -r 48000 -
|
||
|
```
|
||
|
|
||
|
## Server
|
||
|
```perl
|
||
|
#!/usr/bin/env perl
|
||
|
use v5.36;
|
||
|
use IO::Socket::INET;
|
||
|
use Time::HiRes 'gettimeofday';
|
||
|
|
||
|
my $listen_addr = "0.0.0.0";
|
||
|
my $port = 6969;
|
||
|
my $udp_max_datagram_size = 65535;
|
||
|
my $sample_rate = 48000;
|
||
|
my $sample_template = "s";
|
||
|
|
||
|
my $last_time;
|
||
|
my $buffer;
|
||
|
|
||
|
sub fit_together($audio_in) {
|
||
|
my @temp1 = unpack "$sample_template*", $buffer;
|
||
|
my @temp2 = unpack "$sample_template*", $audio_in;
|
||
|
|
||
|
my $time_diff = gettimeofday() - $last_time;
|
||
|
my $sample_skip = floor($time_diff * $sample_rate);
|
||
|
|
||
|
@temp1 = @temp1[ $sample_skip .. $#temp1 ];
|
||
|
while ($#temp1 < $#temp2) {
|
||
|
push @temp1, 0;
|
||
|
}
|
||
|
while ($#temp2 < $#temp1) {
|
||
|
push @temp2, 0;
|
||
|
}
|
||
|
|
||
|
$last_time = gettimeofday();
|
||
|
return (@temp1, @temp2);
|
||
|
}
|
||
|
|
||
|
sub process_audio_in($peer, $audio_in) {
|
||
|
if(not $last_time) {
|
||
|
$last_time = gettimeofday();
|
||
|
$buffer = $audio_in;
|
||
|
} else {
|
||
|
my (@temp1, @temp2) = fit_together($audio_in);
|
||
|
$buffer = pack "$sample_template*",
|
||
|
map {
|
||
|
my $addition = $temp1[$_]+$temp2[$_];
|
||
|
if($addition > $sample_max) {
|
||
|
$sample_max
|
||
|
} elsif($addition < $sample_min) {
|
||
|
$sample_min
|
||
|
} else {
|
||
|
$addition
|
||
|
}
|
||
|
} 0..$#temp1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
my $sock = IO::Socket::INET->new(
|
||
|
LocalAddr => "$listen_addr:$port",
|
||
|
Proto => "udp"
|
||
|
) or die "INET Socket no work :( $@";
|
||
|
|
||
|
say "Listening for clients on addr $listen_addr:$port";
|
||
|
|
||
|
while("humanity" != "extinct") {
|
||
|
my $audio_data_in = eval {
|
||
|
$sock->recv($udp_max_datagram_size) or die "INET Socket recv() fail: $!";
|
||
|
};
|
||
|
if ($@) {
|
||
|
say "Peer ".$sock->peername." sent invalid request, skipping: $@";
|
||
|
next;
|
||
|
}
|
||
|
process_audio($sock->peername, $audio_data_in);
|
||
|
eval {
|
||
|
$sock->send($buffer, $#next_packet) or die "INET Socket recv() fail: $!";
|
||
|
}
|
||
|
if ($@) {
|
||
|
say "Failed to send audio packet to ".$sock->peername.": $@";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
```
|
||
|
|
||
|
The issue with this is that it's not private or anonymous. My attempts to tackle these issues is detailed below:
|
||
|
|
||
|
# Making it secure
|
||
|
|
||
|
Anonymity and privacy can be easily added by simply running nc with `torsocks` on the sending end and running `nc` behind `tor` on the receiving end. i2p could also probably be used for this.
|
||
|
|
||
|
```bash
|
||
|
arecord -f S16 -r 48000 - | torsocks nc example.onion 6969
|
||
|
```
|
||
|
|
||
|
The audio will be anonymous due to tor's design. The audio will also be encrypted by the hidden service tunnel.
|
||
|
|
||
|
# Authentication
|
||
|
|
||
|
TOR Access Keys
|