# client2server Architecture > Complete system architecture for bidirectional event forwarding between OpenWrt routers and central server. ## System Overview ```mermaid 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 :3844")] 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) ```mermaid 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) ```mermaid 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 ```mermaid 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 | 3844 | HTTP | REST API | | Redpanda | 9092 | Kafka | Event storage | | Redpanda REST | 8082 | HTTP | Schema registry | ## Configuration ```yaml # docker-compose.yml environment: REDPANDA_BROKERS: redpanda:9092 TOKEN: *** PORT: 3843 ``` ## Build Targets ```mermaid 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 ```mermaid 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 ```mermaid 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 :3844"] 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 ```mermaid 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 ```mermaid 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 | 3844 | HTTP | | Redpanda Kafka | 9092 | Kafka | | Redpanda REST | 8082 | HTTP | ## Config ```yaml # 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 ```bash TOKEN=*** docker-compose up -d ``` ## IPK Build ```bash # With OpenWrt SDK make package/client2server-unified/compile make package/client2server-unified/ipk ```