From af0ba287c399dcd320ab7ff214c502c11f0acc77 Mon Sep 17 00:00:00 2001 From: Pari Malam Date: Sat, 27 Jun 2026 10:35:05 +0800 Subject: [PATCH] released v1.3.5 --- setup.sh | 234 +++++++++++++++++++------------ src/RunMe.sh | 388 ++++++++++++++++++--------------------------------- 2 files changed, 281 insertions(+), 341 deletions(-) diff --git a/setup.sh b/setup.sh index 8320dec..ea97bd0 100644 --- a/setup.sh +++ b/setup.sh @@ -1,104 +1,166 @@ #!/usr/bin/env bash # setup.sh – Fully automatic environment setup + launcher # -# Fixed for src/ layout: binary, configs, and RunMe.sh live under src/ -# This script creates the venv at the project root and delegates to src/RunMe.sh +# Creates venv, installs dependencies, verifies structure, then launches. +# All arguments are forwarded to src/RunMe.sh. # # Usage: -# ./setup.sh # o11pro + hls_proxy (default) -# MONITOR=true ./setup.sh # o11pro + hls_proxy + security monitor -# HLS_PROXY=false ./setup.sh # o11pro only -# MONITOR=true HLS_PROXY=false ./setup.sh # o11pro + security monitor only +# ./setup.sh # default port 1337 # ./setup.sh 8080 # custom port # ./setup.sh 8080 4 # custom port + verbose=4 # # Environment variables (pass before or alongside): -# MONITOR=true Enable security monitoring proxy (port 19998) -# MONITOR_PORT=19998 Monitor proxy port -# HLS_PROXY=true Enable HLS rewrite proxy (port 9999) -# HLS_PROXY_PORT=9999 HLS proxy port -# GOMEMLIMIT=4G Override Go memory limit +# MONITOR=true Enable security monitoring proxy (port 1339) +# HLS_PROXY=false Disable HLS rewrite proxy (default: true) +# GOMEMLIMIT=4G Override Go memory limit (default: 2GiB) # MAX_STREAMS=8 Limit concurrent streams -# ADMIN_USER=admin Static admin username -# ADMIN_PASS=secret Static admin password +# ADMIN_USER=admin Static admin username (default: admin) +# ADMIN_PASS=secret Static admin password (default: admin1337) set -euo pipefail SETUP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SRC_DIR="$SETUP_DIR/src" -echo "==========================================" -echo " Automatic setup and launch" -echo " Project root: $SETUP_DIR" -echo " Source dir: $SRC_DIR" -echo "==========================================" - -if ! command -v python3 &> /dev/null; then - echo "Python 3 not found. Installing..." - if command -v apt-get &> /dev/null; then - sudo apt-get update - sudo apt-get install -y python3 python3-venv python3-pip - elif command -v yum &> /dev/null; then - sudo yum install -y python3 python3-pip - else - echo "ERROR: No supported package manager. Please install Python 3 manually." - exit 1 - fi -else - echo "Python 3 is installed: $(python3 --version)" -fi - -VENV_DIR="$SETUP_DIR/venv" -if [ ! -d "$VENV_DIR" ]; then - echo "Creating virtual environment in $VENV_DIR ..." - python3 -m venv "$VENV_DIR" - echo "Virtual environment created." -else - echo "Virtual environment already exists." -fi - -echo "Installing / updating requirements from requirements.txt ..." -"$VENV_DIR/bin/pip" install --upgrade pip -q 2>&1 | tail -1 -if [ -f "$SETUP_DIR/requirements.txt" ]; then - "$VENV_DIR/bin/pip" install -r "$SETUP_DIR/requirements.txt" -q 2>&1 | tail -3 - echo "Dependencies installed." -else - echo "Warning: requirements.txt not found – skipping package installation." -fi - -RUNME="$SRC_DIR/RunMe.sh" -if [ -f "$RUNME" ]; then - # Make it executable - chmod +x "$RUNME" - - echo "RunMe.sh PATH is configured dynamically." -else - echo "ERROR: RunMe.sh not found at $RUNME" - exit 1 -fi - -echo "Checking required files in $SRC_DIR ..." -if [ ! -f "$SRC_DIR/o11pro" ]; then - echo "ERROR: Required file 'src/o11pro' not found." - echo "Please place o11pro binary under src/." - exit 1 -fi -echo "All required files present." - -echo "" -MODE_PARTS=("o11pro :${1:-19999}") # FIX: was $1 (unbound when no args) -if [ "${HLS_PROXY:-true}" = "true" ]; then - MODE_PARTS+=("hls_proxy :${HLS_PROXY_PORT:-9999}") -fi -if [ "${MONITOR:-false}" = "true" ]; then - MODE_PARTS+=("monitoring :${MONITOR_PORT:-19998}") -fi -echo "Launch mode: ${MODE_PARTS[*]}" - -echo "" -echo "==========================================" -echo " Launching RunMe.sh with venv Python" -echo "==========================================" -# cd into src/ so RunMe.sh finds its binary and configs +# Switch to src/ early — venv, scripts, and binary all live here cd "$SRC_DIR" + +# ─── Colors ──────────────────────────────────────────────────────────── +BLD='\033[1m' +DIM='\033[2m' +RED='\033[0;31m' +GRN='\033[0;32m' +YLW='\033[0;33m' +BLU='\033[0;34m' +MAG='\033[0;35m' +CYN='\033[0;36m' +RST='\033[0m' +CHECK="${GRN}\xE2\x9C\x94${RST}" +CROSS="${RED}\xE2\x9C\x98${RST}" +ARROW="${CYN}\xE2\x96\xB6${RST}" + +# ─── Helpers ─────────────────────────────────────────────────────────── +ok() { echo -e " ${CHECK} ${BLD}$1${RST} $2"; } +info() { echo -e " ${ARROW} ${DIM}$1${RST}"; } +warn() { echo -e " ${YLW}\xE2\x9A\xA0${RST} ${BLD}$1${RST} $2"; } +fail() { echo -e " ${CROSS} ${RED}$1${RST}"; } +sep() { echo -e " ${DIM}──────────────────────────────────────────────${RST}"; } +box() { + local s="$1" w=56 + echo -e " ${DIM}\xE2\x95\x94$(printf '\xE2\x95\x90%.0s' $(seq 1 $w))\xE2\x95\x97${RST}" + echo -e " ${DIM}\xE2\x95\x91${RST} ${BLD}$s${RST}" + echo -e " ${DIM}\xE2\x95\x9A$(printf '\xE2\x95\x90%.0s' $(seq 1 $w))\xE2\x95\x9D${RST}" +} + +# ─── Header ──────────────────────────────────────────────────────────── +clear 2>/dev/null || true +echo +box "o11pro – Setup & Launch" +echo + +# ─── Phase 1: Python 3 ───────────────────────────────────────────────── +echo -e " ${BLU}\xE2\x96\xBC${RST} ${BLD}Phase 1${RST} \xE2\x80\x94 Python 3" +echo + +if ! command -v python3 &>/dev/null; then + warn "Python 3 not found" "attempting install..." + if command -v apt-get &>/dev/null; then + sudo apt-get update && sudo apt-get install -y python3 python3-venv python3-pip + elif command -v yum &>/dev/null; then + sudo yum install -y python3 python3-pip + else + fail "No supported package manager. Install Python 3 manually."; exit 1 + fi +fi +ok "Python" "$(python3 --version)" +echo + +# ─── Phase 2: Virtual Environment ────────────────────────────────────── +echo -e " ${BLU}\xE2\x96\xBC${RST} ${BLD}Phase 2${RST} \xE2\x80\x94 Virtual Environment" +echo + +VENV_DIR="$SRC_DIR/venv" +if [ ! -d "$VENV_DIR" ]; then + info "Creating venv at ${DIM}$VENV_DIR${RST}..." + python3 -m venv "$VENV_DIR" + ok "venv" "created" +else + ok "venv" "exists at ${DIM}$VENV_DIR${RST}" +fi +echo + +# ─── Phase 3: Dependencies ───────────────────────────────────────────── +echo -e " ${BLU}\xE2\x96\xBC${RST} ${BLD}Phase 3${RST} \xE2\x80\x94 Python Dependencies" +echo + +"$VENV_DIR/bin/pip" install --upgrade pip -q 2>/dev/null +if [ -f "$SETUP_DIR/requirements.txt" ]; then + REQ_COUNT=$(grep -cEv '^\s*(#|$)' "$SETUP_DIR/requirements.txt" || echo 0) + info "Installing ${REQ_COUNT} packages from ${DIM}requirements.txt${RST}..." + "$VENV_DIR/bin/pip" install -r "$SETUP_DIR/requirements.txt" -q 2>&1 | tail -1 + ok "dependencies" "ready" +else + warn "requirements.txt not found" "\xE2\x80\x94 skipping packages" +fi +echo + +# ─── Phase 4: Project Structure ──────────────────────────────────────── +echo -e " ${BLU}\xE2\x96\xBC${RST} ${BLD}Phase 4${RST} \xE2\x80\x94 Project Structure" +echo + +ok "root" "${DIM}$SETUP_DIR${RST}" + +# Launcher scripts +LAUNCHER_COUNT=$(ls -1 *.sh 2>/dev/null | wc -l) +ok "src/" "${LAUNCHER_COUNT} launcher(s)" + +# Binary +BINARY="" +for b in o11pro o11; do + [ -f "$b" ] && BINARY="$b" && break +done +if [ -n "$BINARY" ]; then + BIN_SIZE=$(stat -c%s "$BINARY" 2>/dev/null | numfmt --to=iec 2>/dev/null || echo "?") + ok "binary" "${DIM}$BINARY${RST} (${BIN_SIZE})" + [ -x "$BINARY" ] || chmod +x "$BINARY" && ok "binary" "made executable" +else + fail "No o11pro binary found in ${DIM}$SRC_DIR${RST}"; exit 1 +fi + +# RunMe.sh +if [ -f "RunMe.sh" ]; then + chmod +x "RunMe.sh" + ok "launcher" "${DIM}RunMe.sh${RST}" +else + fail "RunMe.sh not found in ${DIM}$SRC_DIR${RST}"; exit 1 +fi + +# Provider configs +PROV_DIR="$SETUP_DIR/providers" +PROV_COUNT=0 +if [ -d "$PROV_DIR" ]; then + PROV_COUNT=$(find "$PROV_DIR" -maxdepth 1 -name '*.cfg' 2>/dev/null | wc -l) +fi +if [ "$PROV_COUNT" -gt 0 ]; then + ok "providers/" "${PROV_COUNT} config(s)" +else + info "No provider configs yet — place .cfg files in ${DIM}providers/${RST}" +fi + +# HLS proxy maps +CACHE_DIR="$SETUP_DIR/cache" +ORIG_MAP="$CACHE_DIR/orig_urls.json" +if [ -f "$ORIG_MAP" ]; then + MAP_COUNT=$(python3 -c "import json; print(len(json.load(open('$ORIG_MAP'))))" 2>/dev/null || echo "?") + ok "HLS map" "${MAP_COUNT} channel(s) in ${DIM}cache/orig_urls.json${RST}" +else + info "HLS map will be auto-generated on launch" +fi +echo + +# ─── Phase 5: Launch ─────────────────────────────────────────────────── +echo -e " ${GRN}\xE2\x96\xB6${RST} ${BLD}Starting o11pro${RST} — delegating to src/RunMe.sh" +echo + +export PATH="$VENV_DIR/bin:$PATH" exec ./RunMe.sh "$@" \ No newline at end of file diff --git a/src/RunMe.sh b/src/RunMe.sh index 1a9ff9d..c0a5dde 100644 --- a/src/RunMe.sh +++ b/src/RunMe.sh @@ -1,56 +1,32 @@ -#!/bin/bash +#!/usr/bin/env bash +# RunMe.sh – o11pro launcher # -# RunMe.sh Launcher for o11pro -# -# Incorporates all fixes from the analysis: -# - KID format patch (DRM key lookup) -# - Banner string patches (nulled!! -> Ap0dexMe0) -# - Provider config fixes (StreamsCount, PipeOutputCmdFormated) -# - Memory mitigation (-keep=false, GOMEMLIMIT) -# - Correct PATH for python3.13 dependencies +# Starts the Go binary, HLS proxy, and security monitor. +# Run from inside src/ (setup.sh handles this automatically). # # Usage: -# ./RunMe.sh # Run with defaults (port 1337, verbose=2) -# ./RunMe.sh 8080 # Run on custom port -# ./RunMe.sh 8080 4 # Run on port 8080 with verbose=4 (trace) -# GOMEMLIMIT=4G ./RunMe.sh # Override memory limit -# MAX_STREAMS=8 ./RunMe.sh # Override max concurrent streams -# MONITOR=true ./RunMe.sh # Enable security monitoring proxy -# HLS_PROXY=false ./RunMe.sh # Disable HLS proxy -# -# Files required (in same directory as this script): -# o11pro Patched binary -# keys.txt DRM KID:key pairs (optional) +# ./RunMe.sh # default port 1337 +# ./RunMe.sh 8080 # custom port +# ./RunMe.sh 8080 4 # custom port + verbose=4 +# GOMEMLIMIT=4G ./RunMe.sh # override memory limit +# MAX_STREAMS=8 ./RunMe.sh # limit concurrent streams +# MONITOR=false ./RunMe.sh # disable security monitor +# HLS_PROXY=false ./RunMe.sh # disable HLS proxy set -euo pipefail -# Configuration - -# Security monitor: set to true to run through the HTTP proxy/monitor -# Architecture: Client -> :1339 (proxy/monitor) -> :1337 (real o11 API) +# ─── Config Defaults ─────────────────────────────────────────────────── MONITOR="${MONITOR:-true}" - -# Monitor proxy listen port (only used when MONITOR=true) MONITOR_PORT="${MONITOR_PORT:-1339}" -# FIX: HLS Proxy config was missing entirely -# Architecture: Player -> :1338 (hls_proxy) -> upstream CDN HLS_PROXY="${HLS_PROXY:-true}" HLS_PROXY_PORT="${HLS_PROXY_PORT:-1338}" HLS_PROXY_BIND="${HLS_PROXY_BIND:-127.0.0.1}" -# Path setup: need /usr/bin first so binary spawns python3.13 (has deps) -# instead of venv python3.12 (lacks deps like curl_cffi, cloudscraper) -# VENV_PATCHED KID_PATCH_OFFSET="${KID_PATCH_OFFSET:-0x15625cd}" -# Port for HTTP API and streaming (default 1337, override with $1) PORT="${1:-1337}" - -# FIX: was VERBOSE="${2:-2}" (always defaulted to 2 even when $2 was set) VERBOSE="${2:-2}" - -# Bind address: 127.0.0.1 = all interfaces (use 127.0.0.1 for localhost-only) BIND="${BIND:-127.0.0.1}" GOMEMLIMIT="${GOMEMLIMIT:-2GiB}" @@ -60,279 +36,181 @@ HTTPS="${HTTPS:-false}" ADMIN_USER="${ADMIN_USER:-admin}" ADMIN_PASS="${ADMIN_PASS:-admin1337}" -# Working directory (where binary and configs live) SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -export PATH="$PROJECT_ROOT/venv/bin:/usr/bin:/bin:/usr/local/bin:${PATH:-}" +VENV_DIR="$SCRIPT_DIR/venv" HLS_PROXY_CONFIG="${HLS_PROXY_CONFIG:-$PROJECT_ROOT/cache/orig_urls.json}" + +export PATH="$VENV_DIR/bin:/usr/bin:/bin:/usr/local/bin:${PATH:-}" cd "$SCRIPT_DIR" -# Pre-flight checks +# ─── Colors ──────────────────────────────────────────────────────────── +BLD='\033[1m'; DIM='\033[2m' +RED='\033[0;31m'; GRN='\033[0;32m'; YLW='\033[0;33m'; CYN='\033[0;36m' +RST='\033[0m' +CHECK="${GRN}\xE2\x9C\x94${RST}"; CROSS="${RED}\xE2\x9C\x98${RST}" +ARROW="${CYN}\xE2\x96\xB6${RST}" -echo "==========================================" -echo " o11pro launcher" -echo "==========================================" -echo "" +ok() { echo -e " ${CHECK} ${BLD}$1${RST} $2"; } +info() { echo -e " ${ARROW} ${DIM}$1${RST}"; } +warn() { echo -e " ${YLW}\xE2\x9A\xA0${RST} ${BLD}$1${RST} $2"; } +fail() { echo -e " ${CROSS} ${RED}$1${RST}"; exit 1; } +# ─── Pre-flight ──────────────────────────────────────────────────────── BINARY="o11pro" -if [ ! -f "$BINARY" ]; then - echo "ERROR: Binary '$BINARY' not found in $SCRIPT_DIR" - exit 1 -fi -# Verify the binary has the KID patch (not the original REDA bug) KID_PATCH=$(python3 -c " with open('$BINARY','rb') as f: f.seek($KID_PATCH_OFFSET) b = f.read(4) print('OK' if b == b'%02x' else 'MISSING') " 2>/dev/null || echo "CHECK_FAILED") - -if [ "$KID_PATCH" != "OK" ]; then - echo "WARNING: KID format patch not detected in binary!" - echo "" -fi - -chmod +x "$BINARY" +[ "$KID_PATCH" = "OK" ] || warn "KID patch" "NOT detected" if [ ! -f "keys.txt" ]; then - echo "WARNING: keys.txt not found encrypted streams will fail" - echo "" -else - KEY_COUNT=$(grep -c ':' keys.txt 2>/dev/null || echo 0) - echo "Found keys.txt with $KEY_COUNT KID:key pairs" + touch keys.txt fi +cp keys.txt keys/ 2>/dev/null || true -PYTHON_DEPS_OK=$(python3 -c " -try: - import curl_cffi, cloudscraper, dns, requests, requests_toolbelt, socks - print('OK') -except ImportError as e: - print('MISSING: ' + str(e)) -" 2>/dev/null || echo "CHECK_FAILED") - -if [ "$PYTHON_DEPS_OK" != "OK" ]; then - echo "WARNING: Python dependencies missing: $PYTHON_DEPS_OK" - echo "" -fi - -# Prepare directories - -echo "Preparing directories..." -mkdir -p hls/live keys epg dl manifests offair overlay logos fonts rec scripts logs providers cache - -if [ -f "keys.txt" ] && [ ! -f "keys/keys.txt" ]; then - cp keys.txt keys/ 2>/dev/null || true -fi - -# Build command line +mkdir -p hls/live keys epg dl manifests offair overlay logos fonts \ + rec scripts logs providers cache +# ─── Build Args ──────────────────────────────────────────────────────── ARGS="-c o11.cfg -p $PORT -b $BIND -stdout -v $VERBOSE" if [ "$KEEP_FALSE" = "true" ]; then - ARGS="$ARGS -keep=false" + ARGS="$ARGS -keep=false" fi if [ "$HTTPS" = "true" ]; then - ARGS="$ARGS -https" - if [ ! -f "server.crt" ] || [ ! -f "server.key" ]; then - echo "WARNING: -https requested but server.crt/server.key not found" - fi + ARGS="$ARGS -https" + [ -f "server.crt" ] && [ -f "server.key" ] || warn "HTTPS" "missing certs" fi if [ -n "$ADMIN_USER" ] && [ -n "$ADMIN_PASS" ]; then - ARGS="$ARGS -user $ADMIN_USER -password $ADMIN_PASS" + ARGS="$ARGS -user $ADMIN_USER -password $ADMIN_PASS" fi -# Set Go runtime environment - +GOMEMLIMIT_BYTES=0 if [ -n "$GOMEMLIMIT" ] && [ "$GOMEMLIMIT" != "0" ]; then - GOMEMLIMIT_BYTES=$(python3 -c " + GOMEMLIMIT_BYTES=$(python3 -c " import re s = '$GOMEMLIMIT'.strip() -m = re.match(r'^(\d+(?:\.\d+)?)\s*([KMGT]i?B?|B)?$', s, re.I) -if not m: - print(0) -else: - n = float(m.group(1)) - unit = (m.group(2) or 'B').upper() - mult = {'B':1, 'KB':1000, 'KIB':1024, 'MB':1000000, 'MIB':1048576, - 'GB':1000000000, 'GIB':1073741824, 'TB':1000000000000, 'TIB':1099511627776} - print(int(n * mult.get(unit, 1))) +m = re.match(r'^(\d+(?:\.\d+)?)\s*([KMGT]i?B?|B)?\$', s, re.I) +if not m: print(0); exit() +n = float(m.group(1)) +unit = (m.group(2) or 'B').upper() +mult = {'B':1, 'KB':1000, 'KIB':1024, 'MB':1000000, 'MIB':1048576, + 'GB':1000000000, 'GIB':1073741824, 'TB':1000000000000, 'TIB':1099511627776} +print(int(n * mult.get(unit, 1))) " 2>/dev/null || echo "0") - - if [ "$GOMEMLIMIT_BYTES" -gt 0 ]; then - export GOMEMLIMIT="$GOMEMLIMIT_BYTES" - echo "Go memory limit: $GOMEMLIMIT bytes ($GOMEMLIMIT_BYTES bytes)" - fi fi +[ "$GOMEMLIMIT_BYTES" -gt 0 ] && export GOMEMLIMIT="$GOMEMLIMIT_BYTES" export GOTRACEBACK="${GOTRACEBACK:-0}" -# Kill any existing instance +# ─── Launch ──────────────────────────────────────────────────────────── +# Kill existing instance on our port EXISTING_PID=$(pgrep -f "o11pro.*-p $PORT" 2>/dev/null || true) if [ -n "$EXISTING_PID" ]; then - echo "Killing existing instance on port $PORT (PID $EXISTING_PID)..." - kill "$EXISTING_PID" 2>/dev/null || true - sleep 2 - if kill -0 "$EXISTING_PID" 2>/dev/null; then - kill -9 "$EXISTING_PID" 2>/dev/null || true - sleep 1 - fi + info "Killing existing o11pro on :${PORT} (PID ${EXISTING_PID})..." + kill "$EXISTING_PID" 2>/dev/null || true + sleep 2 + if kill -0 "$EXISTING_PID" 2>/dev/null; then + kill -9 "$EXISTING_PID" 2>/dev/null || true + sleep 1 + fi fi -# Launch +if [ "$MONITOR" != "true" ] && [ "$HLS_PROXY" != "true" ]; then + echo -e " ${GRN}\xE2\x96\xB6${RST} ${BLD}o11pro${RST} on :${PORT}" + exec "./$BINARY" $ARGS +fi -echo "" -echo "==========================================" -echo " Launching o11pro" -echo "==========================================" -echo " Port: $PORT" -echo " Bind: $BIND" -echo " Verbose: $VERBOSE" -echo " Keep files: false (memory-safe mode)" -echo " Memory cap: ${GOMEMLIMIT:-none}" -echo " Max streams: ${MAX_STREAMS:-unlimited}" -echo " HTTPS: $HTTPS" -echo " HLS Proxy: $HLS_PROXY${HLS_PROXY:+ (port $HLS_PROXY_PORT)}" -echo " Security mon: $MONITOR${MONITOR:+ (port $MONITOR_PORT)}" -echo "==========================================" -echo "" -echo "Service endpoints:" -if [ "$MONITOR" = "true" ]; then - echo " Web UI (monitored): http://$BIND:$MONITOR_PORT (-> o11 :$PORT)" -else - echo " Web UI (direct): http://$BIND:$PORT" -fi -if [ "$HLS_PROXY" = "true" ]; then - echo " HLS Proxy: http://$HLS_PROXY_BIND:$HLS_PROXY_PORT" - echo " Channel manifest: http://$HLS_PROXY_BIND:$HLS_PROXY_PORT/channel/{name}/master.m3u8" -fi -if [ "$MONITOR" = "true" ]; then - echo " Audit log: logs/audit.log" - echo " Alert log: logs/audit_alerts.log" -fi -echo ".++===========================================================================================++." -echo "" - -# FIX: Unified background PID tracking + cleanup (replaces separate handlers) +# ── Background mode ───────────────────────────────────────────────── _BG_PIDS="" cleanup_all() { - echo "" - echo "Shutting down..." - for pid in $_BG_PIDS; do - kill "$pid" 2>/dev/null || true - done - for pid in $_BG_PIDS; do - wait "$pid" 2>/dev/null || true - done - echo "All processes stopped" + echo + echo -e " ${YLW}\xE2\x96\xA0${RST} ${BLD}Shutting down${RST}..." + for pid in $_BG_PIDS; do kill "$pid" 2>/dev/null || true; done + for pid in $_BG_PIDS; do wait "$pid" 2>/dev/null || true; done + ok "done" "" } +trap cleanup_all EXIT INT TERM -if [ "$MONITOR" = "true" ] || [ "$HLS_PROXY" = "true" ]; then - # FIX: Background mode for both HLS_PROXY and MONITOR (were separate) - trap cleanup_all EXIT INT TERM +echo -e " ${GRN}\xE2\x96\xB6${RST} ${BLD}Starting o11pro${RST} on :${PORT}..." +"./$BINARY" $ARGS & +O11_PID=$! +_BG_PIDS="$O11_PID" - # Start o11pro in background - echo "Starting o11pro in background..." - "./$BINARY" $ARGS & # FIX: was "$BINARY" (not in PATH) - O11_PID=$! - _BG_PIDS="$O11_PID" - echo "o11pro started (PID $O11_PID)" +info "Waiting for port ${PORT}..." +_O11_TRIES=0 +while [ $_O11_TRIES -lt 30 ]; do + _O11_TRIES=$((_O11_TRIES + 1)) + if python3 -c "import socket; s=socket.socket(); s.settimeout(1); s.connect(('127.0.0.1',$PORT)); s.close()" 2>/dev/null; then + ok "ready" ":${PORT}" + break + fi + [ $_O11_TRIES -eq 30 ] && fail "o11pro did not start within 30s" + sleep 1 +done - # Wait for o11pro to be ready - echo "Waiting for o11pro to be ready on port $PORT..." - _O11_TRIES=0 - while [ $_O11_TRIES -lt 30 ]; do - _O11_TRIES=$((_O11_TRIES + 1)) - if python3 -c "import socket; s=socket.socket(); s.settimeout(1); s.connect(('127.0.0.1',$PORT)); s.close()" 2>/dev/null; then - echo ".++===========================================================================================++." - break - fi - if [ $_O11_TRIES -eq 30 ]; then - echo "ERROR: o11pro did not start in time" - kill "$O11_PID" 2>/dev/null || true - exit 1 - fi - sleep 1 - done - - # Start HLS Proxy if enabled - if [ "$HLS_PROXY" = "true" ]; then - if [ ! -f "modules/hls_proxy.py" ]; then - echo "WARNING: modules/hls_proxy.py not found skipping HLS proxy" - else - # Auto-generate orig_urls.json from provider .cfg files - if [ -f "modules/generate_orig_urls.py" ]; then - echo "Generating HLS proxy config from providers..." - python3 modules/generate_orig_urls.py \ - --dir "$PROJECT_ROOT/providers" \ - --output "$HLS_PROXY_CONFIG" || true - fi - if [ ! -f "$HLS_PROXY_CONFIG" ]; then - echo "WARNING: HLS proxy config not found at $HLS_PROXY_CONFIG skipping HLS proxy" - else - echo "Starting HLS Proxy on port $HLS_PROXY_PORT..." - python3 modules/hls_proxy.py \ - --config "$HLS_PROXY_CONFIG" \ - --port "$HLS_PROXY_PORT" \ - --bind "$HLS_PROXY_BIND" & - HLS_PID=$! - _BG_PIDS="$_BG_PIDS $HLS_PID" - echo "HLS Proxy started (PID $HLS_PID)" - fi - fi +# HLS Proxy +if [ "$HLS_PROXY" = "true" ]; then + if [ ! -f "modules/hls_proxy.py" ]; then + warn "HLS proxy" "not found — skipping" + else + if [ -f "modules/generate_orig_urls.py" ]; then + python3 modules/generate_orig_urls.py \ + --dir "$PROJECT_ROOT/providers" \ + --output "$HLS_PROXY_CONFIG" 2>/dev/null || true fi - # Start security monitor if enabled - if [ "$MONITOR" = "true" ]; then - if [ ! -f "modules/monitoring.py" ]; then - echo "ERROR: modules/monitoring.py not found cannot start monitor" - exit 1 - fi - - # FIX: Build monitor command array with explicit --pid (avoids flaky auto-detection) - # FIX: Log to persistent logs/ directory instead of /tmp - MONITOR_CMD=( - python3 modules/monitoring.py - --proxy-mode - --proxy-port "$MONITOR_PORT" - --target-port "$PORT" - --log "logs/audit.log" - --alerts "logs/audit_alerts.log" - ) - if [ -n "$O11_PID" ] && kill -0 "$O11_PID" 2>/dev/null; then - MONITOR_CMD+=(--pid "$O11_PID") - fi - if [ -n "${MONITOR_ARGS:-}" ]; then - MONITOR_CMD+=($MONITOR_ARGS) - fi - - echo "Security monitor enabled" - echo " Proxy port: $MONITOR_PORT (-> o11 API :$PORT)" - echo " Process scan: PID $O11_PID" - echo " File watch: keys.txt, providers/, logs/, hls/" - echo " Audit log: logs/audit.log" - echo " Alert log: logs/audit_alerts.log" - echo "" - echo "Starting security monitor on port $MONITOR_PORT..." - echo "Press Ctrl+C to stop" - echo "" - - exec "${MONITOR_CMD[@]}" + if [ ! -f "$HLS_PROXY_CONFIG" ]; then + warn "HLS proxy" "config missing — skipping" else - # No foreground monitor keep the script alive - echo "" - echo "All services running. Press Ctrl+C to stop." - echo "" - wait -n 2>/dev/null || wait + echo -e " ${GRN}\xE2\x96\xB6${RST} ${BLD}HLS proxy${RST} on :${HLS_PROXY_PORT}..." + python3 modules/hls_proxy.py \ + --config "$HLS_PROXY_CONFIG" \ + --port "$HLS_PROXY_PORT" \ + --bind "$HLS_PROXY_BIND" & + _BG_PIDS="$_BG_PIDS $!" + ok "HLS proxy" "PID $!" fi + fi +fi -else - # Direct mode: run o11pro directly (no proxies) - echo "Press Ctrl+C to stop" - echo "" - exec "./$BINARY" $ARGS # FIX: was "$BINARY" (not in PATH) -fi \ No newline at end of file +# Security monitor +if [ "$MONITOR" = "true" ]; then + [ -f "modules/monitoring.py" ] || fail "monitoring.py not found" + + MONITOR_CMD=( + python3 modules/monitoring.py + --proxy-mode + --proxy-port "$MONITOR_PORT" + --target-port "$PORT" + --log "logs/audit.log" + --alerts "logs/audit_alerts.log" + ) + if [ -n "$O11_PID" ] && kill -0 "$O11_PID" 2>/dev/null; then + MONITOR_CMD+=(--pid "$O11_PID") + fi + [ -n "${MONITOR_ARGS:-}" ] && MONITOR_CMD+=($MONITOR_ARGS) + + echo + echo -e " ${GRN}\xE2\x96\xB6${RST} ${BLD}Security monitor${RST} on :${MONITOR_PORT}" + echo -e " ${DIM} Web UI http://${BIND}:${MONITOR_PORT}${RST}" + echo -e " ${DIM} Audit log logs/audit.log${RST}" + echo + echo -e " ${DIM}Press Ctrl+C to stop all services${RST}" + echo + + exec "${MONITOR_CMD[@]}" +fi + +echo +echo -e " ${DIM}All services running. Press Ctrl+C to stop.${RST}" +echo +wait -n 2>/dev/null || wait \ No newline at end of file