#!/bin/sh # Factory Mesh Services - Aggregated service discovery across mesh # CGI endpoint for distributed service panel echo "Content-Type: application/json" echo "Access-Control-Allow-Origin: *" echo "Access-Control-Allow-Methods: GET, OPTIONS" echo "" # Handle CORS preflight if [ "$REQUEST_METHOD" = "OPTIONS" ]; then exit 0 fi # Get local node ID P2P_STATE_DIR="/var/run/secubox-p2p" LOCAL_NODE_ID=$(cat "$P2P_STATE_DIR/node.id" 2>/dev/null || hostname) LOCAL_NODE_NAME=$(uci -q get system.@system[0].hostname || hostname) # Get local services get_local_services() { local services_json=$(/usr/sbin/secubox-p2p services 2>/dev/null) if [ -z "$services_json" ]; then echo '{"services":[]}' return fi echo "$services_json" } # Get services from a peer get_peer_services() { local peer_addr="$1" local peer_name="$2" # Query peer's services endpoint with timeout local peer_services=$(curl -s --connect-timeout 3 --max-time 5 "http://$peer_addr:7331/api/services" 2>/dev/null) if [ -n "$peer_services" ] && echo "$peer_services" | grep -q "services"; then echo "$peer_services" else echo '{"services":[],"error":"unreachable"}' fi } # Build aggregated mesh services build_mesh_services() { local result='{"nodes":[' local first_node=1 # Add local node local local_services=$(get_local_services) local local_svc_list=$(echo "$local_services" | jsonfilter -e '@.services[*]' 2>/dev/null) local local_svc_count=$(echo "$local_services" | jsonfilter -e '@.services[*]' 2>/dev/null | wc -l) result="$result{\"node_id\":\"$LOCAL_NODE_ID\",\"node_name\":\"$LOCAL_NODE_NAME\",\"is_local\":true,\"status\":\"online\"," result="$result\"services\":[" local i=0 while [ $i -lt $local_svc_count ]; do local svc_name=$(echo "$local_services" | jsonfilter -e "@.services[$i].name" 2>/dev/null) local svc_status=$(echo "$local_services" | jsonfilter -e "@.services[$i].status" 2>/dev/null) local svc_enabled=$(echo "$local_services" | jsonfilter -e "@.services[$i].enabled" 2>/dev/null) local svc_port=$(echo "$local_services" | jsonfilter -e "@.services[$i].port" 2>/dev/null) [ $i -gt 0 ] && result="$result," result="$result{\"name\":\"$svc_name\",\"status\":\"$svc_status\",\"enabled\":$svc_enabled,\"port\":\"$svc_port\"}" i=$((i + 1)) done result="$result]}" first_node=0 # Get peer services local peers_file="/tmp/secubox-p2p-peers.json" if [ -f "$peers_file" ]; then local peer_count=$(jsonfilter -i "$peers_file" -e '@.peers[*]' 2>/dev/null | wc -l) local p=0 while [ $p -lt $peer_count ]; do local peer_addr=$(jsonfilter -i "$peers_file" -e "@.peers[$p].address" 2>/dev/null) local peer_name=$(jsonfilter -i "$peers_file" -e "@.peers[$p].name" 2>/dev/null) local peer_id=$(jsonfilter -i "$peers_file" -e "@.peers[$p].id" 2>/dev/null) local is_local=$(jsonfilter -i "$peers_file" -e "@.peers[$p].is_local" 2>/dev/null) # Skip local node in peers list if [ "$is_local" != "true" ] && [ -n "$peer_addr" ]; then local peer_services=$(get_peer_services "$peer_addr" "$peer_name") local peer_status="offline" local peer_error="" if echo "$peer_services" | grep -q '"error"'; then peer_error=$(echo "$peer_services" | jsonfilter -e '@.error' 2>/dev/null) else peer_status="online" fi result="$result,{\"node_id\":\"${peer_id:-$peer_addr}\",\"node_name\":\"${peer_name:-$peer_addr}\",\"address\":\"$peer_addr\",\"is_local\":false,\"status\":\"$peer_status\"," if [ "$peer_status" = "online" ]; then # Parse peer services local peer_svc_count=$(echo "$peer_services" | jsonfilter -e '@.services[*]' 2>/dev/null | wc -l) result="$result\"services\":[" local j=0 while [ $j -lt $peer_svc_count ]; do local svc_name=$(echo "$peer_services" | jsonfilter -e "@.services[$j].name" 2>/dev/null) local svc_status=$(echo "$peer_services" | jsonfilter -e "@.services[$j].status" 2>/dev/null) local svc_enabled=$(echo "$peer_services" | jsonfilter -e "@.services[$j].enabled" 2>/dev/null) local svc_port=$(echo "$peer_services" | jsonfilter -e "@.services[$j].port" 2>/dev/null) [ $j -gt 0 ] && result="$result," result="$result{\"name\":\"$svc_name\",\"status\":\"$svc_status\",\"enabled\":${svc_enabled:-0},\"port\":\"$svc_port\"}" j=$((j + 1)) done result="$result]}" else result="$result\"services\":[],\"error\":\"$peer_error\"}" fi fi p=$((p + 1)) done fi result="$result]," # Add summary stats result="$result\"summary\":{\"total_nodes\":0,\"online_nodes\":0,\"total_services\":0,\"running_services\":0}}" echo "$result" } # Output aggregated mesh services build_mesh_services