| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- #!/bin/sh
- # Shared helpers for client2server hotplug scripts.
- # Source this file from 01-wifi / 02-dhcp / etc.
- #
- # Behavior:
- # - Loads UCI config (SERVER_URL / TOKEN / ROUTER_ID).
- # - Provides send_event() that:
- # 1. Appends the JSON event to a shared on-disk buffer.
- # 2. Wakes the Lua agent via SIGHUP so it flushes ASAP.
- # 3. Falls back to a direct curl POST if the buffer is not writable
- # (e.g. /var/run not yet mounted in early boot).
- #
- # Shared buffer location: /var/run/client2server/buffer
- # - Same format as client2server-unified.lua's buffer file
- # (one JSON event per line, NDJSON).
- # - The Lua agent's buffer.init() reads it on startup, and
- # buffer.flush() drains it on every reconnect / SIGHUP.
- CLIENT2SERVER_DIR="${CLIENT2SERVER_DIR:-/var/run/client2server}"
- BUFFER_FILE="${BUFFER_FILE:-${CLIENT2SERVER_DIR}/buffer}"
- PID_FILE="${PID_FILE:-${CLIENT2SERVER_DIR}/pid}"
- ENV_FILE="${ENV_FILE:-${CLIENT2SERVER_DIR}/env}"
- # Ensure runtime dir exists
- mkdir -p "$CLIENT2SERVER_DIR" 2>/dev/null
- # Load config: prefer env file (set by init.d), fall back to UCI
- if [ -f "$ENV_FILE" ]; then
- # shellcheck disable=SC1090
- . "$ENV_FILE"
- fi
- : "${SERVER_URL:=$(uci get client2server.server.url 2>/dev/null)}"
- : "${ROUTER_ID:=$(uci get client2server.router.id 2>/dev/null)}"
- : "${TOKEN:=$(uci get client2server.server.token 2>/dev/null)}"
- # Final fallbacks
- : "${SERVER_URL:=http://127.0.0.1:3843}"
- : "${ROUTER_ID:=$(cat /proc/sys/kernel/hostname 2>/dev/null || echo unknown)}"
- log_msg() {
- logger -t client2server-hotplug -p user.info "$1"
- }
- log_err() {
- logger -t client2server-hotplug -p user.err "$1"
- }
- # Build a JSON event in the same shape the Lua agent uses.
- # Args: event_type, data_json
- build_event_json() {
- local event_type="$1"
- local data="$2"
- printf '{"router_id":"%s","event":"%s","data":%s}' \
- "$ROUTER_ID" "$event_type" "$data"
- }
- # Append to disk buffer (atomic-ish via mv from a temp file).
- # Returns 0 on success, 1 on failure.
- spool_event() {
- local json="$1"
- local tmp
- tmp=$(mktemp "${BUFFER_FILE}.XXXXXX") || return 1
- if ! printf '%s\n' "$json" >> "$tmp"; then
- rm -f "$tmp" 2>/dev/null
- return 1
- fi
- if ! cat "$tmp" >> "$BUFFER_FILE" 2>/dev/null; then
- rm -f "$tmp" 2>/dev/null
- return 1
- fi
- rm -f "$tmp" 2>/dev/null
- return 0
- }
- # Wake the Lua agent (best-effort).
- # We touch `<state_dir>/wake`; the agent's main loop polls for it
- # and triggers an immediate buffer flush. This is more portable than
- # SIGHUP across Lua 5.1/5.2/LuaJIT builds.
- wake_agent() {
- touch "$CLIENT2SERVER_DIR/wake" 2>/dev/null || true
- # Also try SIGHUP as a fast path (harmless if PID is stale or
- # the agent doesn't install a handler).
- if [ -f "$PID_FILE" ]; then
- local pid
- pid=$(cat "$PID_FILE" 2>/dev/null)
- if [ -n "$pid" ] && [ "$pid" -gt 0 ] 2>/dev/null; then
- kill -HUP "$pid" 2>/dev/null || true
- fi
- fi
- }
- # Direct HTTP POST fallback. Args: json_event
- direct_post() {
- local json="$1"
- if [ -n "$TOKEN" ]; then
- curl -s -m 3 -X POST "$SERVER_URL/api/events" \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer $TOKEN" \
- -d "$json" >/dev/null 2>&1
- else
- curl -s -m 3 -X POST "$SERVER_URL/api/events" \
- -H "Content-Type: application/json" \
- -d "$json" >/dev/null 2>&1
- fi
- }
- # Main entry point. Args: event_type, data_json
- # Behavior:
- # 1. Try to spool to disk + wake agent (preferred: survives outages).
- # 2. If spooling fails, do a one-shot direct POST (best effort, may drop).
- send_event() {
- local event_type="$1"
- local data="$2"
- local json
- json=$(build_event_json "$event_type" "$data")
- if spool_event "$json"; then
- log_msg "Spooled: $event_type"
- wake_agent
- return 0
- fi
- # Fallback: try direct POST (may be lost if offline)
- log_err "Spool failed, falling back to direct POST: $event_type"
- direct_post "$json"
- log_msg "Sent (fallback): $event_type"
- }
|