#!/bin/sh set -eu find_janus_config() { for candidate in \ /usr/local/etc/janus/janus.jcfg \ /etc/janus/janus.jcfg do if [ -f "$candidate" ]; then printf '%s\n' "$candidate" return 0 fi done return 1 } find_signaling_config() { for candidate in \ /conf/signaling.conf do if [ -f "$candidate" ]; then printf '%s\n' "$candidate" return 0 fi done return 1 } find_eturnal_vm_args() { for candidate in /opt/eturnal/releases/*/vm.args; do if [ -f "$candidate" ]; then printf '%s\n' "$candidate" return 0 fi done return 1 } find_eturnal_epmd_override_files() { find /opt/eturnal /etc -type f 2>/dev/null \ | while IFS= read -r candidate; do if [ "$candidate" = "/usr/local/bin/qni-talk-entrypoint.sh" ] || [ "$candidate" = "$0" ]; then continue fi if [ ! -w "$candidate" ]; then continue fi if grep -Iq . "$candidate" 2>/dev/null && grep -q -- '-erl_epmd_port' "$candidate" 2>/dev/null; then printf '%s\n' "$candidate" fi done } apply_janus_stun_patch() { config_path="$1" stun_server="$2" stun_port="$3" tmp_path="$(mktemp)" awk -v stun_server="$stun_server" -v stun_port="$stun_port" ' BEGIN { in_nat = 0 nat_found = 0 server_written = 0 port_written = 0 } /^[[:space:]]*nat[[:space:]]*:[[:space:]]*\{/ { print in_nat = 1 nat_found = 1 next } in_nat && /^[[:space:]]*stun_server[[:space:]]*=/ { if (!server_written) { print " stun_server = \"" stun_server "\"" server_written = 1 } next } in_nat && /^[[:space:]]*stun_port[[:space:]]*=/ { if (!port_written) { print " stun_port = " stun_port port_written = 1 } next } in_nat && /^[[:space:]]*\}/ { if (!server_written) { print " stun_server = \"" stun_server "\"" server_written = 1 } if (!port_written) { print " stun_port = " stun_port port_written = 1 } print in_nat = 0 next } { print } END { if (!nat_found) { print "" print "nat: {" print " stun_server = \"" stun_server "\"" print " stun_port = " stun_port print "}" } } ' "$config_path" > "$tmp_path" cat "$tmp_path" > "$config_path" rm -f "$tmp_path" } apply_signaling_port_patch() { config_path="$1" listen_host="$2" listen_port="$3" tmp_path="$(mktemp)" awk -v listen_host="$listen_host" -v listen_port="$listen_port" ' BEGIN { in_http = 0 http_found = 0 listen_written = 0 } /^[[:space:]]*\[http\][[:space:]]*$/ { print in_http = 1 http_found = 1 next } in_http && /^[[:space:]]*\[/ { if (!listen_written) { print "listen = " listen_host ":" listen_port listen_written = 1 } print in_http = 0 next } in_http && /^[[:space:]]*listen[[:space:]]*=/ { if (!listen_written) { print "listen = " listen_host ":" listen_port listen_written = 1 } next } { print } END { if (in_http && !listen_written) { print "listen = " listen_host ":" listen_port listen_written = 1 } if (!http_found) { print "" print "[http]" print "listen = " listen_host ":" listen_port } } ' "$config_path" > "$tmp_path" cat "$tmp_path" > "$config_path" rm -f "$tmp_path" } apply_eturnal_epmd_patch() { config_path="$1" epmd_port="$2" tmp_path="$(mktemp)" if [ ! -w "$config_path" ]; then echo "Warning: eturnal EPMD patch target is not writable: ${config_path}" >&2 rm -f "$tmp_path" return 1 fi awk -v epmd_port="$epmd_port" ' { line = $0 # Literal port usage. gsub(/-erl_epmd_port[[:space:]]+[0-9]+/, "-erl_epmd_port " epmd_port, line) # Shell-expanded defaults commonly used by release scripts. gsub(/-erl_epmd_port[[:space:]]+\$\{ERL_EPMD_PORT:-[0-9]+\}/, "-erl_epmd_port " epmd_port, line) gsub(/-erl_epmd_port[[:space:]]+\$\{EPMD_PORT:-[0-9]+\}/, "-erl_epmd_port " epmd_port, line) gsub(/ERL_EPMD_PORT:-[0-9]+/, "ERL_EPMD_PORT:-" epmd_port, line) gsub(/EPMD_PORT:-[0-9]+/, "EPMD_PORT:-" epmd_port, line) print line } ' "$config_path" > "$tmp_path" cat "$tmp_path" > "$config_path" rm -f "$tmp_path" } apply_eturnal_epmd_patch_all() { epmd_port="$1" patched_any="0" overrides_list="$(mktemp)" if eturnal_vm_args_path="$(find_eturnal_vm_args)"; then echo "Applying eturnal EPMD patch: port=${epmd_port} config=${eturnal_vm_args_path}" if apply_eturnal_epmd_patch "$eturnal_vm_args_path" "$epmd_port"; then patched_any="1" fi else echo "Warning: eturnal vm.args file not found; cannot apply EPMD vm.args patch." >&2 fi find_eturnal_epmd_override_files > "$overrides_list" while IFS= read -r override_path; do if [ -n "$override_path" ] && [ "$override_path" != "${eturnal_vm_args_path:-}" ]; then echo "Applying eturnal EPMD override patch: port=${epmd_port} file=${override_path}" if apply_eturnal_epmd_patch "$override_path" "$epmd_port"; then patched_any="1" fi fi done < "$overrides_list" rm -f "$overrides_list" if [ "$patched_any" != "1" ]; then echo "Warning: no eturnal files containing -erl_epmd_port were patched." >&2 fi } restart_signaling_supervisor_programs() { if ! command -v supervisorctl >/dev/null 2>&1; then return 0 fi program_names="$( supervisorctl status 2>/dev/null | awk ' { name = $1 lowered = tolower(name) if (lowered ~ /signal/ || lowered ~ /spreed/) { print name } } ' | sort -u )" if [ -n "$program_names" ]; then echo "Restarting signaling supervisor programs: $(echo "$program_names" | tr '\n' ' ')" echo "$program_names" | while IFS= read -r program_name; do if [ -n "$program_name" ]; then supervisorctl restart "$program_name" >/dev/null 2>&1 || true fi done return 0 fi supervisorctl restart all >/dev/null 2>&1 || true } ensure_signaling_port_after_startup() { desired_listen="$1:$2" attempts="${3:-30}" while [ "$attempts" -gt 0 ]; do if signaling_config_path="$(find_signaling_config)"; then current_listen="$( awk ' /^[[:space:]]*\[http\][[:space:]]*$/ { in_http = 1; next } in_http && /^[[:space:]]*\[/ { in_http = 0 } in_http && /^[[:space:]]*listen[[:space:]]*=/ { sub(/^[[:space:]]*listen[[:space:]]*=[[:space:]]*/, "", $0) print $0 exit } ' "$signaling_config_path" 2>/dev/null )" if [ "$current_listen" = "$desired_listen" ]; then return 0 fi if [ -n "$current_listen" ]; then echo "Re-applying signaling listen patch after base startup: current=${current_listen} desired=${desired_listen}" apply_signaling_port_patch "$signaling_config_path" "$1" "$2" restart_signaling_supervisor_programs return 0 fi fi attempts=$((attempts - 1)) sleep 1 done echo "Warning: signaling config did not become patchable after startup; desired listen=${desired_listen}" >&2 return 1 } janus_stun_server="${TALK_JANUS_STUN_SERVER:-${TALK_STUN_SERVER:-${TALK_TURN_HOST:-}}}" janus_stun_server="${janus_stun_server%%:*}" janus_stun_port="${TALK_JANUS_STUN_PORT:-${TALK_TURN_PORT:-3478}}" signaling_port="${TALK_SIGNALING_PORT:-8081}" signaling_bind_host="${TALK_SIGNALING_BIND_HOST:-0.0.0.0}" eturnal_epmd_port="${TALK_ETURNAL_EPMD_PORT:-3470}" if [ -n "$eturnal_epmd_port" ]; then # Some eturnal launcher scripts expand ERL_EPMD_PORT defaults at runtime # (e.g. ${ERL_EPMD_PORT:-3470}). Exporting here ensures the runtime value wins # even if upstream startup scripts are regenerated after our file patches. export ERL_EPMD_PORT="$eturnal_epmd_port" export EPMD_PORT="$eturnal_epmd_port" echo "Applying eturnal runtime env: ERL_EPMD_PORT=${ERL_EPMD_PORT}" fi if [ -n "$janus_stun_server" ]; then if janus_config_path="$(find_janus_config)"; then echo "Applying Janus STUN patch: server=${janus_stun_server} port=${janus_stun_port} config=${janus_config_path}" apply_janus_stun_patch "$janus_config_path" "$janus_stun_server" "$janus_stun_port" else echo "Warning: Janus config file not found; cannot apply STUN patch." >&2 fi else echo "Janus STUN patch skipped: TALK_JANUS_STUN_SERVER/TALK_STUN_SERVER/TALK_TURN_HOST not set." fi if [ -n "$signaling_port" ]; then if signaling_config_path="$(find_signaling_config)"; then echo "Applying signaling listen patch: listen=${signaling_bind_host}:${signaling_port} config=${signaling_config_path}" apply_signaling_port_patch "$signaling_config_path" "$signaling_bind_host" "$signaling_port" else echo "Warning: signaling config file not found; cannot apply signaling listen patch." >&2 fi fi if [ -n "$eturnal_epmd_port" ]; then apply_eturnal_epmd_patch_all "$eturnal_epmd_port" fi if [ "$#" -eq 0 ]; then set -- /start.sh supervisord -c /supervisord.conf fi if [ "$1" = "/start.sh" ]; then "$@" & main_pid="$!" if [ -n "$signaling_port" ]; then ensure_signaling_port_after_startup "$signaling_bind_host" "$signaling_port" 45 || true fi wait "$main_pid" exit $? fi exec "$@"