ARCHITECTURE.md 7.7 KB

client2server Architecture

Complete system architecture for bidirectional event forwarding between OpenWrt routers and central server.

System Overview

flowchart TB
    subgraph Router["OpenWrt Router"]
        direction TB
        Lua[("client2server-unified.lua")]
        DHCP[("DHCP Monitor")]
        WAN[("WAN Monitor")]
        CMD[("Command Executor")]
        Link[("Link Monitor")]
    end
    
    subgraph Cloud["Cloud"]
        subgraph CaddyLB["Caddy Load Balancer :3843"]
            WS[("WebSocket")]
            API[("HTTP/WS :3843")]
        end
        
        subgraph Server["Go Servers (x2)"]
            S1[("server1")]
            S2[("server2")]
        end
        
        subgraph Redpanda["Redpanda"]
            Events[("router-events")]
            Commands[("router-commands")]
        end
        
        subgraph Backend["LuIS Backend"]
            API2[("API Server")]
            DB[(Database)]
        end
    end
    
    Router -->|WS| CaddyLB
    CaddyLB --> WS
    WS <-->|lb| S1
    WS <-->|lb| S2
    S1 -->|publish| Events
    S2 -->|publish| Commands
    Events --> Redpanda
    Commands --> Redpanda
    Redpanda --> API2
    API2 --> DB

Data Flows

Event Flow (Router → Server)

sequenceDiagram
    participant R as Router
    participant C as Caddy
    participant S as Go Server
    participant K as Redpanda
    participant L as LuIS

    Note over R,L: DHCP Event Example
    
    R->>C: WebSocket connect → :3843
    activate C
    C->>S: Proxy to server1
    activate S
    S->>K: Produce → router-events
    activate K
    K-->>S: ACK
    deactivate K
    S-->>C: ACK
    deactivate S
    C-->>R: Connected!
    deactivate C
    
    Note over R,L: Later - New DHCP Lease
    R->>C: Event: dhcp_lease_new
    C->>S: Forward event
    S->>K: Publish event
    S->>R: ACK
    
    Note over R,L: LuIS Dashboard consumes
    L->>K: Consume router-events
    K-->>L: Event data

Command Flow (Server → Router)

sequenceDiagram
    participant L as LuIS
    participant S as Go Server
    participant K as Redpanda
    participant R as Router
    
    Note over L,R: Server sends command to router
    L->>S: POST /api/command
    S->>K: Publish → router-commands
    K-->>S: ACK
    S-->>L: command_id
    
    Note over R,R: Router receives via WebSocket
    R->>R: Listen for commands
    R->>R: Execute: uci set network.lan.ipaddr='192.168.1.1'
    R->>R: Commit: uci commit network
    R->>S: Return result
    S->>K: Publish result (optional)

Component Architecture

flowchart LR
    subgraph Router["Router (OpenWrt)"]
        WSCli[("WebSocket Client")]
        Buf[("Buffer File
/tmp/event_buffer")]
        Events[("Event Sources")] 
        CMD[("Command Executor")]
        
        Events -->|new| WSCli
        WSCli -->|offline| Buf
        Buf -->|flush| WSCli
    end
    
    subgraph Server["Go Server"]
        WSHan[("WS Handler")]
        RedProd[("Producer")]
        RedCons[("Consumer")]
        Routers[("Router State")]
        CMDServ[("Command Service")]
    end
    
    WSCli -->|connect| WSHan
    WSHan --> RedProd
    RedProd -->|topics| Redpanda["Redpanda"]
    Redpanda --> RedCons
    RedCons --> CMDServ
    CMDServ --> Routers

Port Mappings

| Service | Port | Protocol | Purpose | |---------|------|----------|--------|| | Caddy WS | 3843 | WebSocket | Router connections | | Caddy HTTP | 3843 | HTTP | Same port as WS; serves /api/* + /health | | Redpanda | 9092 | Kafka | Event storage | | Redpanda REST | 8082 | HTTP | Schema registry |

Configuration

# docker-compose.yml
environment:
  REDPANDA_BROKERS: redpanda:9092
  TOKEN: ***
  PORT: 3843

Build Targets

flowchart LR
    A[("Source")] --> B[("Build")]
    B --> C[("Package")]
    B --> D[("Docker")]
    B --> E[("IPK")]
    
    C -->|Go| D[("server binary")]
    C -->|Lua| E[("OpenWrt ipk")]
    
    subgraph Build["Builds"]
        direction TB
        F[("docker-compose up")]
        G[("./scripts/feeds")]
    end

Topics (Redpanda)

Topic Partitions Retention Purpose
router-events 3 7 days All router events
router-commands 3 1 hour Commands to routers

Error Handling

flowchart TD
    A[("Connection Lost")] --> B{Router Online?}
    B -->|Yes| C[("Buffer Events")]
    C --> D[("Retry Every 5s")]
    D --> E{Connected?}
    E -->|Yes| F[("Flush Buffer")]
    E -->|No| D
    B -->|No| G[("Wait")]
    G --> H[("Timer Reset")]
    H --> A

System Overview

flowchart TB
    subgraph Router["OpenWrt Router"]
        direction TB
        Lua[("client2server-unified.lua")]
        DHCP[("DHCP Monitor")]
        WAN[("WAN Monitor")]
        CMD[("Command Executor")]
    end
    
    subgraph CaddyLB["Caddy Load Balancer"]
        WS["WebSocket :3843"]
        API["HTTP API :3843"]
    end
    
    subgraph Server["Go Servers"]
        S1["server1"]
        S2["server2"]
    end
    
    subgraph Redpanda["Redpanda Cluster"]
        Events[("router-events")]
        Commands[("router-commands")]
    end
    
    subgraph Backend["LuIS Backend"]
        API2[("API Server")]
        DB[(Database)]
    end
    
    Router -->|WebSocket| CaddyLB
    CaddyLB --> WS
    WS --> S1
    WS --> S2
    S1 --> Events
    S2 --> Commands
    Events --> Redpanda
    Commands --> Redpanda
    Redpanda --> API2
    API2 --> DB

Data Flow

sequenceDiagram
    participant R as Router
    participant C as Caddy
    participant S as Go Server
    participant K as Redpanda
    participant L as LuIS

    Note over R,L: Event Flow
    
    R->>C: WebSocket connect :3843
    C->>S: Proxy to server1
    S->>K: Publish to router-events
    
    Note over R,L: Command Flow
    
    L->>K: Publish command
    K->>S: Consume from router-commands
    S->>R: WebSocket send command
    R->>R: Execute (uci_set, shell, etc)
    R->>S: Ack result
    S->>K: Publish result
    K->>L: Result stored

Component Details

flowchart LR
    subgraph Lua["Lua Client"]
        WS[("WebSocket")]
        Buf[("Buffer")]
        DHCP[("DHCP")]
        WAN[("WAN")]
        CMD[("Commands")]
    end
    
    subgraph GoServer["Go Server"]
        Handler[("Handler")]
        Redpanda[("Redpanda")]
        RouterMgr[("Router State")]
    end
    
    WS -->|buffer when offline| Buf
    Buf -->|flush on reconnect| Handler
    DHCP -->|events| Handler
    WAN -->|events| Handler
    Handler --> Redpanda
    Redpanda --> RouterMgr

Ports

Service Port Protocol
WebSocket LB 3843 WS
HTTP API + WS 3843 HTTP + WS
Redpanda Kafka 9092 Kafka
Redpanda REST 8082 HTTP

Config

# Environment
TOKEN: ***              # Auth token
REDPANDA_BROKERS: redpanda:9092   # Redpanda address
PORT: 3843             # Listening port

Commands

Command Example Response
uci_set {"config":"network", "section":"lan", "option":"ipaddr", "value":"192.168.1.1"} Success
shell {"command":"reboot"} Output
reboot {} Scheduled
wifi_restart {} Network restart
status {} JSON status

Events

Event Source Payload
dhcp_lease_new dnsmasq mac, ip, hostname
dhcp_lease_expire dnsmasq mac, old_ip
wan_link_up /sys/class/net/* device
wan_link_down /sys/class/net/* device
wan_dhcp_new ubus new_ip
wan_dhcp_changed ubus old_ip, new_ip

Docker Run

TOKEN=*** docker-compose up -d

IPK Build

# With OpenWrt SDK
make package/client2server-unified/compile
make package/client2server-unified/ipk