Format the bash script
This commit is contained in:
parent
8ad02453a7
commit
087d6fbc55
1 changed files with 2499 additions and 2495 deletions
248
terminalphone.sh
248
terminalphone.sh
|
|
@ -29,7 +29,6 @@ NONCE_LOG_FILE="$DATA_DIR/run/nonces_$$"
|
|||
AUTO_LISTEN_FLAG="$DATA_DIR/run/autolisten_$$"
|
||||
AUTO_LISTEN_PID=""
|
||||
|
||||
|
||||
# Defaults
|
||||
LISTEN_PORT=7777
|
||||
TOR_SOCKS_PORT=9050
|
||||
|
|
@ -136,7 +135,7 @@ kill_bg_processes() {
|
|||
save_pid() {
|
||||
local name="$1" pid="$2"
|
||||
mkdir -p "$PID_DIR"
|
||||
echo "$pid" > "$PID_DIR/${name}.pid"
|
||||
echo "$pid" >"$PID_DIR/${name}.pid"
|
||||
}
|
||||
|
||||
log_info() {
|
||||
|
|
@ -174,7 +173,7 @@ load_config() {
|
|||
echo ""
|
||||
if [ -n "$_unlock_pass" ]; then
|
||||
SHARED_SECRET=$(openssl enc -d -aes-256-cbc -pbkdf2 -iter 100000 \
|
||||
-pass "fd:3" -in "$SECRET_FILE" 3<<< "${_unlock_pass}" 2>/dev/null) || true
|
||||
-pass "fd:3" -in "$SECRET_FILE" 3<<<"${_unlock_pass}" 2>/dev/null) || true
|
||||
if [ -z "$SHARED_SECRET" ]; then
|
||||
log_warn "Failed to unlock secret (wrong passphrase?)"
|
||||
log_info "You can re-enter the secret with option 4"
|
||||
|
|
@ -202,7 +201,7 @@ load_config() {
|
|||
echo ""
|
||||
if [ "$_new_pass" = "$_confirm_pass" ]; then
|
||||
echo -n "$SHARED_SECRET" | openssl enc -aes-256-cbc -pbkdf2 -iter 100000 \
|
||||
-pass "fd:3" -out "$SECRET_FILE" 3<<< "${_new_pass}" 2>/dev/null
|
||||
-pass "fd:3" -out "$SECRET_FILE" 3<<<"${_new_pass}" 2>/dev/null
|
||||
chmod 600 "$SECRET_FILE"
|
||||
log_ok "Secret encrypted with passphrase"
|
||||
else
|
||||
|
|
@ -221,7 +220,7 @@ load_config() {
|
|||
|
||||
save_config() {
|
||||
mkdir -p "$DATA_DIR"
|
||||
cat > "$CONFIG_FILE" << EOF
|
||||
cat >"$CONFIG_FILE" <<EOF
|
||||
LISTEN_PORT=$LISTEN_PORT
|
||||
TOR_SOCKS_PORT=$TOR_SOCKS_PORT
|
||||
OPUS_BITRATE=$OPUS_BITRATE
|
||||
|
|
@ -355,7 +354,7 @@ setup_tor() {
|
|||
mkdir -p "$TOR_DIR/hidden_service"
|
||||
chmod 700 "$TOR_DIR/hidden_service"
|
||||
|
||||
cat > "$TOR_CONF" << EOF
|
||||
cat >"$TOR_CONF" <<EOF
|
||||
SocksPort $TOR_SOCKS_PORT
|
||||
DataDirectory $TOR_DIR/data
|
||||
HiddenServiceDir $TOR_DIR/hidden_service
|
||||
|
|
@ -371,13 +370,13 @@ EOF
|
|||
[ -n "$geoip" ] && break
|
||||
done
|
||||
if [ -n "$geoip" ]; then
|
||||
echo "GeoIPFile $geoip" >> "$TOR_CONF"
|
||||
[ -n "$geoip6" ] && echo "GeoIPv6File $geoip6" >> "$TOR_CONF"
|
||||
echo "GeoIPFile $geoip" >>"$TOR_CONF"
|
||||
[ -n "$geoip6" ] && echo "GeoIPv6File $geoip6" >>"$TOR_CONF"
|
||||
fi
|
||||
|
||||
# Append ControlPort config if circuit display is enabled
|
||||
if [ "$SHOW_CIRCUIT" -eq 1 ]; then
|
||||
cat >> "$TOR_CONF" << EOF
|
||||
cat >>"$TOR_CONF" <<EOF
|
||||
|
||||
ControlPort $TOR_CONTROL_PORT
|
||||
CookieAuthentication 1
|
||||
|
|
@ -387,7 +386,7 @@ EOF
|
|||
|
||||
# Append ExcludeNodes if configured
|
||||
if [ -n "$EXCLUDE_NODES" ]; then
|
||||
cat >> "$TOR_CONF" << EOF
|
||||
cat >>"$TOR_CONF" <<EOF
|
||||
|
||||
ExcludeNodes $EXCLUDE_NODES
|
||||
StrictNodes 1
|
||||
|
|
@ -399,7 +398,7 @@ EOF
|
|||
if [ "$SNOWFLAKE_ENABLED" -eq 1 ] && check_dep snowflake-client; then
|
||||
local sf_bin
|
||||
sf_bin=$(command -v snowflake-client)
|
||||
cat >> "$TOR_CONF" << EOF
|
||||
cat >>"$TOR_CONF" <<EOF
|
||||
|
||||
UseBridges 1
|
||||
ClientTransportPlugin snowflake exec $sf_bin
|
||||
|
|
@ -450,20 +449,17 @@ install_snowflake() {
|
|||
fi
|
||||
}
|
||||
|
||||
|
||||
|
||||
start_tor() {
|
||||
if [ -n "$TOR_PID" ] && kill -0 "$TOR_PID" 2>/dev/null; then
|
||||
log_info "Tor is already running (PID $TOR_PID)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
|
||||
setup_tor
|
||||
|
||||
# Clear old log so we only see fresh output
|
||||
local tor_log="$TOR_DIR/tor.log"
|
||||
> "$tor_log"
|
||||
>"$tor_log"
|
||||
|
||||
log_info "Starting Tor..."
|
||||
if [ "$SNOWFLAKE_ENABLED" -eq 1 ]; then
|
||||
|
|
@ -586,34 +582,34 @@ rotate_onion() {
|
|||
# Map 2-letter country code to full name
|
||||
cc_to_country() {
|
||||
case "${1,,}" in
|
||||
ad) echo "Andorra";; ae) echo "UAE";; al) echo "Albania";; am) echo "Armenia";;
|
||||
at) echo "Austria";; au) echo "Australia";; az) echo "Azerbaijan";;
|
||||
ba) echo "Bosnia";; be) echo "Belgium";; bg) echo "Bulgaria";; br) echo "Brazil";;
|
||||
by) echo "Belarus";; ca) echo "Canada";; ch) echo "Switzerland";; cl) echo "Chile";;
|
||||
cn) echo "China";; co) echo "Colombia";; cr) echo "Costa Rica";;
|
||||
cy) echo "Cyprus";; cz) echo "Czechia";; de) echo "Germany";; dk) echo "Denmark";;
|
||||
dz) echo "Algeria";; ec) echo "Ecuador";; ee) echo "Estonia";; eg) echo "Egypt";;
|
||||
es) echo "Spain";; fi) echo "Finland";; fr) echo "France";;
|
||||
gb) echo "UK";; ge) echo "Georgia";; gr) echo "Greece";;
|
||||
hk) echo "Hong Kong";; hr) echo "Croatia";; hu) echo "Hungary";;
|
||||
id) echo "Indonesia";; ie) echo "Ireland";; il) echo "Israel";; in) echo "India";;
|
||||
iq) echo "Iraq";; ir) echo "Iran";; is) echo "Iceland";; it) echo "Italy";;
|
||||
jp) echo "Japan";; ke) echo "Kenya";; kg) echo "Kyrgyzstan";;
|
||||
kr) echo "South Korea";; kz) echo "Kazakhstan";;
|
||||
lb) echo "Lebanon";; li) echo "Liechtenstein";; lt) echo "Lithuania";;
|
||||
lu) echo "Luxembourg";; lv) echo "Latvia";;
|
||||
ma) echo "Morocco";; md) echo "Moldova";; me) echo "Montenegro";; mk) echo "N. Macedonia";;
|
||||
mt) echo "Malta";; mx) echo "Mexico";; my) echo "Malaysia";;
|
||||
ng) echo "Nigeria";; nl) echo "Netherlands";; no) echo "Norway";; nz) echo "New Zealand";;
|
||||
pa) echo "Panama";; pe) echo "Peru";; ph) echo "Philippines";; pk) echo "Pakistan";;
|
||||
pl) echo "Poland";; pt) echo "Portugal";;
|
||||
ro) echo "Romania";; rs) echo "Serbia";; ru) echo "Russia";;
|
||||
sa) echo "Saudi Arabia";; se) echo "Sweden";; sg) echo "Singapore";; si) echo "Slovenia";;
|
||||
sk) echo "Slovakia";; th) echo "Thailand";; tn) echo "Tunisia";; tr) echo "Turkey";;
|
||||
tw) echo "Taiwan";; ua) echo "Ukraine";; us) echo "USA";;
|
||||
uy) echo "Uruguay";; uz) echo "Uzbekistan";; ve) echo "Venezuela";;
|
||||
vn) echo "Vietnam";; za) echo "South Africa";;
|
||||
*) echo "${1^^}";;
|
||||
ad) echo "Andorra" ;; ae) echo "UAE" ;; al) echo "Albania" ;; am) echo "Armenia" ;;
|
||||
at) echo "Austria" ;; au) echo "Australia" ;; az) echo "Azerbaijan" ;;
|
||||
ba) echo "Bosnia" ;; be) echo "Belgium" ;; bg) echo "Bulgaria" ;; br) echo "Brazil" ;;
|
||||
by) echo "Belarus" ;; ca) echo "Canada" ;; ch) echo "Switzerland" ;; cl) echo "Chile" ;;
|
||||
cn) echo "China" ;; co) echo "Colombia" ;; cr) echo "Costa Rica" ;;
|
||||
cy) echo "Cyprus" ;; cz) echo "Czechia" ;; de) echo "Germany" ;; dk) echo "Denmark" ;;
|
||||
dz) echo "Algeria" ;; ec) echo "Ecuador" ;; ee) echo "Estonia" ;; eg) echo "Egypt" ;;
|
||||
es) echo "Spain" ;; fi) echo "Finland" ;; fr) echo "France" ;;
|
||||
gb) echo "UK" ;; ge) echo "Georgia" ;; gr) echo "Greece" ;;
|
||||
hk) echo "Hong Kong" ;; hr) echo "Croatia" ;; hu) echo "Hungary" ;;
|
||||
id) echo "Indonesia" ;; ie) echo "Ireland" ;; il) echo "Israel" ;; in) echo "India" ;;
|
||||
iq) echo "Iraq" ;; ir) echo "Iran" ;; is) echo "Iceland" ;; it) echo "Italy" ;;
|
||||
jp) echo "Japan" ;; ke) echo "Kenya" ;; kg) echo "Kyrgyzstan" ;;
|
||||
kr) echo "South Korea" ;; kz) echo "Kazakhstan" ;;
|
||||
lb) echo "Lebanon" ;; li) echo "Liechtenstein" ;; lt) echo "Lithuania" ;;
|
||||
lu) echo "Luxembourg" ;; lv) echo "Latvia" ;;
|
||||
ma) echo "Morocco" ;; md) echo "Moldova" ;; me) echo "Montenegro" ;; mk) echo "N. Macedonia" ;;
|
||||
mt) echo "Malta" ;; mx) echo "Mexico" ;; my) echo "Malaysia" ;;
|
||||
ng) echo "Nigeria" ;; nl) echo "Netherlands" ;; no) echo "Norway" ;; nz) echo "New Zealand" ;;
|
||||
pa) echo "Panama" ;; pe) echo "Peru" ;; ph) echo "Philippines" ;; pk) echo "Pakistan" ;;
|
||||
pl) echo "Poland" ;; pt) echo "Portugal" ;;
|
||||
ro) echo "Romania" ;; rs) echo "Serbia" ;; ru) echo "Russia" ;;
|
||||
sa) echo "Saudi Arabia" ;; se) echo "Sweden" ;; sg) echo "Singapore" ;; si) echo "Slovenia" ;;
|
||||
sk) echo "Slovakia" ;; th) echo "Thailand" ;; tn) echo "Tunisia" ;; tr) echo "Turkey" ;;
|
||||
tw) echo "Taiwan" ;; ua) echo "Ukraine" ;; us) echo "USA" ;;
|
||||
uy) echo "Uruguay" ;; uz) echo "Uzbekistan" ;; ve) echo "Venezuela" ;;
|
||||
vn) echo "Vietnam" ;; za) echo "South Africa" ;;
|
||||
*) echo "${1^^}" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
|
@ -642,8 +638,8 @@ get_circuit_hops() {
|
|||
|
||||
# Find best BUILT circuit — prefer HS circuits
|
||||
local circuit_line
|
||||
circuit_line=$(echo "$circ_resp" | grep " BUILT " \
|
||||
| grep -E "PURPOSE=HS_SERVICE_INTRO|PURPOSE=HS_CLIENT_REND" | head -1) || true
|
||||
circuit_line=$(echo "$circ_resp" | grep " BUILT " |
|
||||
grep -E "PURPOSE=HS_SERVICE_INTRO|PURPOSE=HS_CLIENT_REND" | head -1) || true
|
||||
[ -z "$circuit_line" ] && circuit_line=$(echo "$circ_resp" | grep " BUILT " | head -1)
|
||||
[ -z "$circuit_line" ] && return 1
|
||||
|
||||
|
|
@ -654,13 +650,15 @@ get_circuit_hops() {
|
|||
|
||||
# Parse relay names and fingerprints
|
||||
local names=() fps=()
|
||||
IFS=',' read -ra relays <<< "$path"
|
||||
IFS=',' read -ra relays <<<"$path"
|
||||
for r in "${relays[@]}"; do
|
||||
local name fp
|
||||
if [[ "$r" == *"~"* ]]; then
|
||||
name="${r#*~}"; fp="${r%%~*}"
|
||||
name="${r#*~}"
|
||||
fp="${r%%~*}"
|
||||
else
|
||||
name="${r:0:8}..."; fp="$r"
|
||||
name="${r:0:8}..."
|
||||
fp="$r"
|
||||
fi
|
||||
names+=("$name")
|
||||
fps+=("${fp#\$}")
|
||||
|
|
@ -681,7 +679,7 @@ get_circuit_hops() {
|
|||
if [ -n "$ns_resp" ]; then
|
||||
while IFS= read -r rline; do
|
||||
ips+=("$(echo "$rline" | awk '{print $7}')")
|
||||
done <<< "$(echo "$ns_resp" | grep '^r ')"
|
||||
done <<<"$(echo "$ns_resp" | grep '^r ')"
|
||||
fi
|
||||
|
||||
# Step 3: Resolve countries for all IPs (single session)
|
||||
|
|
@ -704,7 +702,7 @@ get_circuit_hops() {
|
|||
local cc
|
||||
cc=$(echo "$ccline" | sed 's/.*=//')
|
||||
countries+=("$(cc_to_country "$cc")")
|
||||
done <<< "$(echo "$cc_resp" | grep 'ip-to-country')"
|
||||
done <<<"$(echo "$cc_resp" | grep 'ip-to-country')"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
|
@ -755,7 +753,7 @@ set_shared_secret() {
|
|||
echo ""
|
||||
if [ "$_pass" = "$_pass2" ]; then
|
||||
echo -n "$SHARED_SECRET" | openssl enc -aes-256-cbc -pbkdf2 -iter 100000 \
|
||||
-pass "fd:3" -out "$SECRET_FILE" 3<<< "${_pass}" 2>/dev/null
|
||||
-pass "fd:3" -out "$SECRET_FILE" 3<<<"${_pass}" 2>/dev/null
|
||||
chmod 600 "$SECRET_FILE"
|
||||
log_ok "Shared secret saved (encrypted with passphrase)"
|
||||
return
|
||||
|
|
@ -769,19 +767,18 @@ set_shared_secret() {
|
|||
fi
|
||||
|
||||
# Plaintext fallback
|
||||
echo -n "$SHARED_SECRET" > "$SECRET_FILE"
|
||||
echo -n "$SHARED_SECRET" >"$SECRET_FILE"
|
||||
chmod 600 "$SECRET_FILE"
|
||||
log_ok "Shared secret saved"
|
||||
}
|
||||
|
||||
|
||||
# Encrypt a file
|
||||
encrypt_file() {
|
||||
local infile="$1" outfile="$2"
|
||||
local c="$CIPHER"
|
||||
[ -f "$CIPHER_RUNTIME_FILE" ] && c=$(cat "$CIPHER_RUNTIME_FILE")
|
||||
openssl enc -"${c}" -pbkdf2 -iter 10000 -pass "fd:3" \
|
||||
-in "$infile" -out "$outfile" 3<<< "${SHARED_SECRET}" 2>/dev/null
|
||||
-in "$infile" -out "$outfile" 3<<<"${SHARED_SECRET}" 2>/dev/null
|
||||
}
|
||||
|
||||
# Decrypt a file
|
||||
|
|
@ -790,7 +787,7 @@ decrypt_file() {
|
|||
local c="$CIPHER"
|
||||
[ -f "$CIPHER_RUNTIME_FILE" ] && c=$(cat "$CIPHER_RUNTIME_FILE")
|
||||
openssl enc -d -"${c}" -pbkdf2 -iter 10000 -pass "fd:3" \
|
||||
-in "$infile" -out "$outfile" 3<<< "${SHARED_SECRET}" 2>/dev/null
|
||||
-in "$infile" -out "$outfile" 3<<<"${SHARED_SECRET}" 2>/dev/null
|
||||
}
|
||||
|
||||
#=============================================================================
|
||||
|
|
@ -839,7 +836,7 @@ proto_verify() {
|
|||
if grep -qF "$nonce" "$NONCE_LOG_FILE" 2>/dev/null; then
|
||||
return 1
|
||||
fi
|
||||
echo "$nonce" >> "$NONCE_LOG_FILE" 2>/dev/null
|
||||
echo "$nonce" >>"$NONCE_LOG_FILE" 2>/dev/null
|
||||
# Strip nonce prefix (nonce:message → message)
|
||||
echo "${signed_msg#*:}"
|
||||
return 0
|
||||
|
|
@ -984,9 +981,9 @@ stop_and_send() {
|
|||
if [ -s "$enc_file" ]; then
|
||||
local enc_size
|
||||
enc_size=$(stat -c%s "$enc_file" 2>/dev/null || echo 0)
|
||||
local size_kb=$(( enc_size * 10 / 1024 ))
|
||||
local size_whole=$(( size_kb / 10 ))
|
||||
local size_frac=$(( size_kb % 10 ))
|
||||
local size_kb=$((enc_size * 10 / 1024))
|
||||
local size_whole=$((size_kb / 10))
|
||||
local size_frac=$((size_kb % 10))
|
||||
|
||||
local b64
|
||||
b64=$(base64 -w 0 "$enc_file" 2>/dev/null)
|
||||
|
|
@ -1012,25 +1009,21 @@ audio_play() {
|
|||
fi
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Play an opus file
|
||||
play_chunk() {
|
||||
local opus_file="$1"
|
||||
|
||||
if [ $IS_TERMUX -eq 1 ]; then
|
||||
# Termux: pipe decode directly to sox play (avoids temp file + Android media framework)
|
||||
opusdec --quiet --rate 48000 "$opus_file" - 2>/dev/null | \
|
||||
opusdec --quiet --rate 48000 "$opus_file" - 2>/dev/null |
|
||||
play -q -t raw -r 48000 -e signed -b 16 -c 1 - 2>/dev/null || true
|
||||
else
|
||||
# Linux: pipe decode directly to aplay
|
||||
opusdec --quiet --rate 48000 "$opus_file" - 2>/dev/null | \
|
||||
opusdec --quiet --rate 48000 "$opus_file" - 2>/dev/null |
|
||||
aplay -f S16_LE -r 48000 -c 1 -q 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
|
||||
#=============================================================================
|
||||
# CALL CLEANUP — RESET EVERYTHING TO FRESH STATE
|
||||
#=============================================================================
|
||||
|
|
@ -1161,9 +1154,9 @@ start_vol_monitor() {
|
|||
|
||||
while [ -f "$CONNECTED_FLAG" ]; do
|
||||
local cur_vol
|
||||
cur_vol=$(termux-volume 2>/dev/null \
|
||||
| jq -r '.[] | select(.stream=="music") | .volume' 2>/dev/null \
|
||||
|| echo "")
|
||||
cur_vol=$(termux-volume 2>/dev/null |
|
||||
jq -r '.[] | select(.stream=="music") | .volume' 2>/dev/null ||
|
||||
echo "")
|
||||
|
||||
# Remember the initial volume so we can restore after detection
|
||||
if [ -n "$cur_vol" ] && [ -z "$restore_vol" ]; then
|
||||
|
|
@ -1171,7 +1164,7 @@ start_vol_monitor() {
|
|||
fi
|
||||
|
||||
if [ -n "$cur_vol" ] && [ -n "$last_vol" ]; then
|
||||
local drop=$(( last_vol - cur_vol ))
|
||||
local drop=$((last_vol - cur_vol))
|
||||
|
||||
if [ "$drop" -ge 2 ] 2>/dev/null; then
|
||||
# Rapid double-tap: both presses landed in one poll cycle
|
||||
|
|
@ -1280,7 +1273,7 @@ listen_for_call() {
|
|||
local user_input=""
|
||||
if read -r -t 1 user_input 2>/dev/null; then
|
||||
case "$user_input" in
|
||||
q|Q)
|
||||
q | Q)
|
||||
# Stop all listening (manual + auto), return to menu
|
||||
kill "$socat_pid" 2>/dev/null || true
|
||||
wait "$socat_pid" 2>/dev/null || true
|
||||
|
|
@ -1291,7 +1284,7 @@ listen_for_call() {
|
|||
log_info "Stopped listening."
|
||||
return 0
|
||||
;;
|
||||
b|B)
|
||||
b | B)
|
||||
# Move to background: kill manual socat, enable auto-listen
|
||||
kill "$socat_pid" 2>/dev/null || true
|
||||
wait "$socat_pid" 2>/dev/null || true
|
||||
|
|
@ -1424,8 +1417,10 @@ draw_call_header() {
|
|||
# Snowflake bridge info
|
||||
if [ "$SNOWFLAKE_ENABLED" -eq 1 ]; then
|
||||
local tor_log="$TOR_DIR/tor.log"
|
||||
echo "" >&2; _r=$((_r + 1))
|
||||
echo -e " ${TOR_PURPLE}●${NC} ${BOLD}Snowflake bridge${NC}" >&2; _r=$((_r + 1))
|
||||
echo "" >&2
|
||||
_r=$((_r + 1))
|
||||
echo -e " ${TOR_PURPLE}●${NC} ${BOLD}Snowflake bridge${NC}" >&2
|
||||
_r=$((_r + 1))
|
||||
if [ -f "$tor_log" ]; then
|
||||
local bridge_line=""
|
||||
bridge_line=$(grep "new bridge descriptor" "$tor_log" 2>/dev/null | tail -1 || true)
|
||||
|
|
@ -1463,8 +1458,10 @@ draw_call_header() {
|
|||
local _hop_data
|
||||
_hop_data=$(get_circuit_hops 2>/dev/null) || true
|
||||
if [ -n "$_hop_data" ]; then
|
||||
echo "" >&2; _r=$((_r + 1))
|
||||
echo -e " ${TOR_PURPLE}●${NC} ${BOLD}Circuit${NC}" >&2; _r=$((_r + 1))
|
||||
echo "" >&2
|
||||
_r=$((_r + 1))
|
||||
echo -e " ${TOR_PURPLE}●${NC} ${BOLD}Circuit${NC}" >&2
|
||||
_r=$((_r + 1))
|
||||
CIRCUIT_START_ROW=$_r
|
||||
local _hop_i=0 _hop_total
|
||||
_hop_total=$(echo "$_hop_data" | wc -l)
|
||||
|
|
@ -1475,12 +1472,13 @@ draw_call_header() {
|
|||
[ $_hop_i -eq $_hop_total ] && _hlabel="Rendezvous"
|
||||
printf ' \033[2m%-13s\033[0m \033[1;37m%s\033[0m \033[2m(%s)\033[0m\n' "${_hlabel}:" "$_hname" "$_hcountry" >&2
|
||||
_r=$((_r + 1))
|
||||
done <<< "$_hop_data"
|
||||
done <<<"$_hop_data"
|
||||
CIRCUIT_HOP_COUNT=$_hop_i
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "" >&2; _r=$((_r + 1))
|
||||
echo "" >&2
|
||||
_r=$((_r + 1))
|
||||
|
||||
# Static placeholders — updated in-place via ANSI positioning
|
||||
echo -e " ${DIM}Last sent: --${NC}" >&2
|
||||
|
|
@ -1491,7 +1489,8 @@ draw_call_header() {
|
|||
RECV_INFO_ROW=$_r
|
||||
_r=$((_r + 1))
|
||||
|
||||
echo "" >&2; _r=$((_r + 1))
|
||||
echo "" >&2
|
||||
_r=$((_r + 1))
|
||||
|
||||
# Static status bar
|
||||
if [ $IS_TERMUX -eq 1 ]; then
|
||||
|
|
@ -1528,7 +1527,7 @@ refresh_circuit_display() {
|
|||
local _row=$((CIRCUIT_START_ROW + _hop_i - 1))
|
||||
printf '\033[%d;1H\033[K' "$_row" >&2
|
||||
printf ' \033[2m%-13s\033[0m \033[1;37m%s\033[0m \033[2m(%s)\033[0m' "${_hlabel}:" "$_hname" "$_hcountry" >&2
|
||||
done <<< "$_hop_data"
|
||||
done <<<"$_hop_data"
|
||||
printf '\033[u' >&2 # restore cursor
|
||||
}
|
||||
|
||||
|
|
@ -1563,13 +1562,13 @@ in_call_session() {
|
|||
start_vol_monitor "$vol_trigger_file"
|
||||
|
||||
# Write cipher to runtime file so subshells can track changes
|
||||
echo "$CIPHER" > "$CIPHER_RUNTIME_FILE"
|
||||
echo "$HMAC_AUTH" > "$HMAC_RUNTIME_FILE"
|
||||
: > "$NONCE_LOG_FILE"
|
||||
echo "$CIPHER" >"$CIPHER_RUNTIME_FILE"
|
||||
echo "$HMAC_AUTH" >"$HMAC_RUNTIME_FILE"
|
||||
: >"$NONCE_LOG_FILE"
|
||||
|
||||
# Open persistent file descriptors for the pipes
|
||||
exec 3< "$recv_pipe" # fd 3 = read from remote
|
||||
exec 4> "$send_pipe" # fd 4 = write to remote
|
||||
exec 3<"$recv_pipe" # fd 3 = read from remote
|
||||
exec 4>"$send_pipe" # fd 4 = write to remote
|
||||
|
||||
# Send our onion address and cipher for handshake
|
||||
local my_onion
|
||||
|
|
@ -1594,7 +1593,7 @@ in_call_session() {
|
|||
first_line=$(proto_verify "$first_line") || first_line=""
|
||||
if [[ "$first_line" == ID:* ]]; then
|
||||
remote_display="${first_line#ID:}"
|
||||
echo "$remote_display" > "$remote_id_file"
|
||||
echo "$remote_display" >"$remote_id_file"
|
||||
elif [[ "$first_line" == CIPHER:* ]]; then
|
||||
remote_cipher="${first_line#CIPHER:}"
|
||||
fi
|
||||
|
|
@ -1614,7 +1613,7 @@ in_call_session() {
|
|||
|
||||
# Save remote cipher for later redraws
|
||||
if [ -n "$remote_cipher" ]; then
|
||||
echo "$remote_cipher" > "$remote_cipher_file"
|
||||
echo "$remote_cipher" >"$remote_cipher_file"
|
||||
fi
|
||||
|
||||
# Kill connecting spinner and draw call header
|
||||
|
|
@ -1652,12 +1651,12 @@ in_call_session() {
|
|||
ID:*)
|
||||
# Caller ID received (save but don't print — already in header)
|
||||
local remote_addr="${line#ID:}"
|
||||
echo "$remote_addr" > "$remote_id_file"
|
||||
echo "$remote_addr" >"$remote_id_file"
|
||||
;;
|
||||
CIPHER:*)
|
||||
# Remote side sent/changed their cipher — save and update display
|
||||
local rc="${line#CIPHER:}"
|
||||
echo "$rc" > "$remote_cipher_file" 2>/dev/null || true
|
||||
echo "$rc" >"$remote_cipher_file" 2>/dev/null || true
|
||||
# Read current local cipher from runtime file
|
||||
local _cur_cipher="$CIPHER"
|
||||
[ -f "$CIPHER_RUNTIME_FILE" ] && _cur_cipher=$(cat "$CIPHER_RUNTIME_FILE")
|
||||
|
|
@ -1683,7 +1682,7 @@ in_call_session() {
|
|||
local _mid=$(uid)
|
||||
local msg_enc="$AUDIO_DIR/msg_enc_${_mid}.tmp"
|
||||
local msg_dec="$AUDIO_DIR/msg_dec_${_mid}.tmp"
|
||||
echo "$msg_b64" | base64 -d > "$msg_enc" 2>/dev/null || true
|
||||
echo "$msg_b64" | base64 -d >"$msg_enc" 2>/dev/null || true
|
||||
if [ -s "$msg_enc" ]; then
|
||||
if decrypt_file "$msg_enc" "$msg_dec" 2>/dev/null; then
|
||||
local msg_text
|
||||
|
|
@ -1700,15 +1699,15 @@ in_call_session() {
|
|||
local enc_file="$AUDIO_DIR/recv_enc_${_rid}.tmp"
|
||||
local dec_file="$AUDIO_DIR/recv_dec_${_rid}.tmp"
|
||||
|
||||
echo "$b64_data" | base64 -d > "$enc_file" 2>/dev/null || true
|
||||
echo "$b64_data" | base64 -d >"$enc_file" 2>/dev/null || true
|
||||
if [ -s "$enc_file" ]; then
|
||||
if decrypt_file "$enc_file" "$dec_file" 2>/dev/null; then
|
||||
# Calculate recv size
|
||||
local _enc_sz=0
|
||||
_enc_sz=$(stat -c%s "$enc_file" 2>/dev/null || echo 0)
|
||||
local _sz_kb=$(( _enc_sz * 10 / 1024 ))
|
||||
local _sz_w=$(( _sz_kb / 10 ))
|
||||
local _sz_f=$(( _sz_kb % 10 ))
|
||||
local _sz_kb=$((_enc_sz * 10 / 1024))
|
||||
local _sz_w=$((_sz_kb / 10))
|
||||
local _sz_f=$((_sz_kb % 10))
|
||||
local _recv_info="${_sz_w}.${_sz_f}KB"
|
||||
# Update static "Last recv" row via ANSI positioning
|
||||
printf '\033[s' >&2
|
||||
|
|
@ -1765,7 +1764,8 @@ in_call_session() {
|
|||
# TERMUX: Toggle mode
|
||||
if [ $ptt_active -eq 0 ]; then
|
||||
ptt_active=1
|
||||
printf '\033[s' >&2; printf '\033[%d;1H\033[K' "$STATUS_ROW" >&2
|
||||
printf '\033[s' >&2
|
||||
printf '\033[%d;1H\033[K' "$STATUS_ROW" >&2
|
||||
printf ' \033[41;1;37m \u25cf RECORDING \033[0m \033[2m[SPACE]=Send\033[0m ' >&2
|
||||
printf '\033[u' >&2
|
||||
start_recording
|
||||
|
|
@ -1785,7 +1785,8 @@ in_call_session() {
|
|||
# LINUX: Hold-to-talk
|
||||
if [ $ptt_active -eq 0 ]; then
|
||||
ptt_active=1
|
||||
printf '\033[s' >&2; printf '\033[%d;1H\033[K' "$STATUS_ROW" >&2
|
||||
printf '\033[s' >&2
|
||||
printf '\033[%d;1H\033[K' "$STATUS_ROW" >&2
|
||||
printf ' \033[41;1;37;5m \u25cf RECORDING \033[0m ' >&2
|
||||
printf '\033[u' >&2
|
||||
stty time 5 # longer timeout to span keyboard repeat delay
|
||||
|
|
@ -1839,7 +1840,7 @@ in_call_session() {
|
|||
local _cid=$(uid)
|
||||
local chat_plain="$AUDIO_DIR/chat_${_cid}.tmp"
|
||||
local chat_enc="$AUDIO_DIR/chat_enc_${_cid}.tmp"
|
||||
echo -n "$chat_msg" > "$chat_plain"
|
||||
echo -n "$chat_msg" >"$chat_plain"
|
||||
encrypt_file "$chat_plain" "$chat_enc" 2>/dev/null
|
||||
if [ -s "$chat_enc" ]; then
|
||||
local chat_b64
|
||||
|
|
@ -2170,7 +2171,7 @@ settings_menu() {
|
|||
;;
|
||||
6) settings_tor ;;
|
||||
7) settings_security ;;
|
||||
0|q|Q) return ;;
|
||||
0 | q | Q) return ;;
|
||||
*)
|
||||
echo -e "\n ${RED}Invalid choice${NC}"
|
||||
sleep 1
|
||||
|
|
@ -2248,11 +2249,10 @@ settings_cipher() {
|
|||
read -r cinput
|
||||
|
||||
case "$cinput" in
|
||||
0|q|Q)
|
||||
0 | q | Q)
|
||||
return
|
||||
;;
|
||||
'')
|
||||
;;
|
||||
'') ;;
|
||||
*)
|
||||
if [[ "$cinput" =~ ^[0-9]+$ ]] && [ "$cinput" -ge 1 ] && [ "$cinput" -le "$total" ]; then
|
||||
local selected="${ciphers[$((cinput - 1))]}"
|
||||
|
|
@ -2261,7 +2261,7 @@ settings_cipher() {
|
|||
CIPHER="$selected"
|
||||
save_config
|
||||
# Update runtime file for live mid-call sync
|
||||
[ -f "$CIPHER_RUNTIME_FILE" ] && echo "$CIPHER" > "$CIPHER_RUNTIME_FILE"
|
||||
[ -f "$CIPHER_RUNTIME_FILE" ] && echo "$CIPHER" >"$CIPHER_RUNTIME_FILE"
|
||||
# Notify remote side if in a call
|
||||
if [ "$CALL_ACTIVE" -eq 1 ]; then
|
||||
proto_send "CIPHER:${CIPHER}"
|
||||
|
|
@ -2330,7 +2330,7 @@ settings_opus() {
|
|||
echo -e "\n ${RED}Invalid bitrate. Must be 6–510.${NC}"
|
||||
fi
|
||||
;;
|
||||
0|q|Q)
|
||||
0 | q | Q)
|
||||
return
|
||||
;;
|
||||
*)
|
||||
|
|
@ -2405,7 +2405,7 @@ settings_snowflake() {
|
|||
echo -e " ${DIM}Restart Tor for changes to take effect.${NC}"
|
||||
fi
|
||||
;;
|
||||
0|q|Q) return ;;
|
||||
0 | q | Q) return ;;
|
||||
*)
|
||||
echo -e "\n ${RED}Invalid choice${NC}"
|
||||
;;
|
||||
|
|
@ -2431,7 +2431,7 @@ settings_voice() {
|
|||
|
||||
local i
|
||||
for i in "${!effects[@]}"; do
|
||||
local num=$(( i + 1 ))
|
||||
local num=$((i + 1))
|
||||
local marker=" "
|
||||
if [ "${effects[$i]}" = "$VOICE_EFFECT" ]; then
|
||||
marker="${GREEN}> ${NC}"
|
||||
|
|
@ -2451,10 +2451,11 @@ settings_voice() {
|
|||
4) VOICE_EFFECT="robot" ;;
|
||||
5) VOICE_EFFECT="echo" ;;
|
||||
6) VOICE_EFFECT="whisper" ;;
|
||||
7) VOICE_EFFECT="custom"
|
||||
7)
|
||||
VOICE_EFFECT="custom"
|
||||
settings_voice_custom
|
||||
;;
|
||||
0|q|Q) return ;;
|
||||
0 | q | Q) return ;;
|
||||
*)
|
||||
echo -e "\n ${RED}Invalid choice${NC}"
|
||||
sleep 1
|
||||
|
|
@ -2533,7 +2534,7 @@ settings_voice_custom() {
|
|||
read -r val
|
||||
[[ "$val" =~ ^[0-9]+$ ]] && VOICE_TREMOLO=$val
|
||||
;;
|
||||
0|q|Q)
|
||||
0 | q | Q)
|
||||
save_config
|
||||
return
|
||||
;;
|
||||
|
|
@ -2591,7 +2592,7 @@ settings_tor() {
|
|||
;;
|
||||
2) settings_exclude_nodes ;;
|
||||
3) settings_snowflake ;;
|
||||
0|q|Q) return ;;
|
||||
0 | q | Q) return ;;
|
||||
*)
|
||||
echo -e "\n ${RED}Invalid choice${NC}"
|
||||
sleep 1
|
||||
|
|
@ -2699,7 +2700,7 @@ settings_exclude_nodes() {
|
|||
log_ok "All countries allowed"
|
||||
sleep 1
|
||||
;;
|
||||
0|q|Q) return ;;
|
||||
0 | q | Q) return ;;
|
||||
*)
|
||||
echo -e "\n ${RED}Invalid choice${NC}"
|
||||
sleep 1
|
||||
|
|
@ -2732,7 +2733,7 @@ settings_security() {
|
|||
case "$_sec_choice" in
|
||||
1) settings_cipher ;;
|
||||
2) settings_hmac ;;
|
||||
0|q|Q) return ;;
|
||||
0 | q | Q) return ;;
|
||||
*)
|
||||
echo -e "\n ${RED}Invalid choice${NC}"
|
||||
sleep 1
|
||||
|
|
@ -2806,7 +2807,7 @@ settings_hmac() {
|
|||
fi
|
||||
sleep 1
|
||||
;;
|
||||
0|q|Q) return ;;
|
||||
0 | q | Q) return ;;
|
||||
*)
|
||||
echo -e "\n ${RED}Invalid choice${NC}"
|
||||
sleep 1
|
||||
|
|
@ -2960,15 +2961,18 @@ main_menu() {
|
|||
read -r
|
||||
;;
|
||||
4) set_shared_secret ;;
|
||||
5) test_audio
|
||||
5)
|
||||
test_audio
|
||||
echo -ne " ${DIM}Press Enter to continue...${NC}"
|
||||
read -r
|
||||
;;
|
||||
6) show_status
|
||||
6)
|
||||
show_status
|
||||
echo -ne " ${DIM}Press Enter to continue...${NC}"
|
||||
read -r
|
||||
;;
|
||||
7) install_deps
|
||||
7)
|
||||
install_deps
|
||||
echo -ne "\n ${DIM}Press Enter to continue...${NC}"
|
||||
read -r
|
||||
;;
|
||||
|
|
@ -2998,7 +3002,7 @@ main_menu() {
|
|||
12)
|
||||
settings_menu
|
||||
;;
|
||||
0|q|Q)
|
||||
0 | q | Q)
|
||||
echo -e "\n${GREEN}Goodbye!${NC}"
|
||||
stop_tor
|
||||
cleanup
|
||||
|
|
@ -3029,20 +3033,20 @@ load_config
|
|||
|
||||
# Handle command-line arguments
|
||||
case "${1:-}" in
|
||||
install)
|
||||
install)
|
||||
install_deps
|
||||
;;
|
||||
test)
|
||||
test)
|
||||
test_audio
|
||||
;;
|
||||
status)
|
||||
status)
|
||||
show_status
|
||||
;;
|
||||
listen)
|
||||
listen)
|
||||
load_config
|
||||
listen_for_call
|
||||
;;
|
||||
call)
|
||||
call)
|
||||
load_config
|
||||
if [ -n "${2:-}" ]; then
|
||||
remote_onion="$2"
|
||||
|
|
@ -3055,7 +3059,7 @@ case "${1:-}" in
|
|||
echo "Usage: $0 call <onion-address>"
|
||||
fi
|
||||
;;
|
||||
help|-h|--help)
|
||||
help | -h | --help)
|
||||
echo -e "${BOLD}${APP_NAME} v${VERSION}${NC}"
|
||||
echo ""
|
||||
echo "Usage: $0 [command]"
|
||||
|
|
@ -3069,7 +3073,7 @@ case "${1:-}" in
|
|||
echo " call ADDR Call an onion address"
|
||||
echo " help Show this help"
|
||||
;;
|
||||
*)
|
||||
*)
|
||||
main_menu
|
||||
;;
|
||||
esac
|
||||
|
|
|
|||
Loading…
Reference in a new issue