+++
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