# 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/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)

```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 | 3843 | HTTP | Same port as WS; serves `/api/*` + `/health` |
| 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 :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

```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 + WS | 3843 | HTTP + WS | Unified port |
| 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
```