> For the complete documentation index, see [llms.txt](https://adaptix-framework.gitbook.io/adaptix-framework/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://adaptix-framework.gitbook.io/adaptix-framework/development/extenders/listener-plugin-in-dev.md).

# Listener extender

External Listener accepts connections from agents directly over the network (HTTP/HTTPS, DNS, etc.).

### Flow Diagram

<figure><img src="https://2104178602-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FS8p8XLFtLmf0NkofQvoa%2Fuploads%2FnhtxeKgyiBx2raISDUjb%2F02.png?alt=media&amp;token=5a44605a-0e2f-46da-b9fc-ee3b0b998720" alt=""><figcaption></figcaption></figure>

```
┌──────────────────────────────────────────────────────────────────────────────────┐
│                          EXTERNAL LISTENER FLOW                                  │
├──────────────────────────────────────────────────────────────────────────────────┤
│                                                                                  │
│  ╔════════════════════════════════════════════════════════════════════════════╗  │
│  ║                          CREATE LISTENER                                   ║  │
│  ╚════════════════════════════════════════════════════════════════════════════╝  │
│                                                                                  │
│  GUI ──> POST /listener/create                                                   │
│                   │                                                              │
│                   V                                                              │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │ TEAMSERVER                                                                  │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  TsListenerCreate(listenerType, name, config)                               │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  ┌───────────────────────────────────────────────────────────────────────┐  │ │
│  │  │ EXTENDER                                                              │  │ │
│  │  │         │                                                             │  │ │
│  │  │         V                                                             │  │ │
│  │  │  PluginListener.Create(name, config, customData)                      │  │ │
│  │  │         │                                                             │  │ │
│  │  │         ├──> Configuration validation                                 │  │ │
│  │  │         └──> return ExtenderListener, ListenerData, customData        │  │ │
│  │  │                                                                       │  │ │
│  │  └───────────────────────────────────────────────────────────────────────┘  │ │
│  │         │                                                                   │ │
│  │         └──> Save to DBMS, broadcast to clients                             │ │
│  │                                                                             │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                  │
│  ╔════════════════════════════════════════════════════════════════════════════╗  │
│  ║                          START LISTENER                                    ║  │
│  ╚════════════════════════════════════════════════════════════════════════════╝  │
│                                                                                  │
│  (automatically after Create)                                                    │
│                   │                                                              │
│                   V                                                              │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │ TEAMSERVER                                                                  │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  TsListenerStart(listenerName)                                              │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  ┌───────────────────────────────────────────────────────────────────────┐  │ │
│  │  │ EXTENDER                                                              │  │ │
│  │  │         │                                                             │  │ │
│  │  │         V                                                             │  │ │
│  │  │  ExtenderListener.Start()                                             │  │ │
│  │  │         │                                                             │  │ │
│  │  │         └──> Start HTTP/DNS server                                    │  │ │
│  │  │                                                                       │  │ │
│  │  └───────────────────────────────────────────────────────────────────────┘  │ │
│  │                                                                             │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                  │
│  ╔════════════════════════════════════════════════════════════════════════════╗  │
│  ║                          AGENT CONNECTION                                  ║  │
│  ╚════════════════════════════════════════════════════════════════════════════╝  │
│                                                                                  │
│  Agent ──> [HTTP] Request to Listener                                            │
│                       │                                                          │
│                       V                                                          │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │ EXTENDER ([HTTP] Handler)                                                   │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  [processRequest(ctx)]                                                      │ │
│  │         │                                                                   │ │
│  │         ├──> Extract AgentID and data                                       │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  ┌───────────────────────────────────────────────────────────────────────┐  │ │
│  │  │ TEAMSERVER API calls                                                  │  │ │
│  │  │         │                                                             │  │ │
│  │  │         ├──> if !TsAgentIsExists(agentId):                            │  │ │
│  │  │         │       TsAgentCreate(agentCrc, agentId, data, listener, IP)  │  │ │
│  │  │         │                                                             │  │ │
│  │  │         ├──> TsAgentSetTick(agentId, listener) - last tick update     │  │ │
│  │  │         │                                                             │  │ │
│  │  │         ├──> TsAgentProcessData(agentId, bodyData) - process data     │  │ │
│  │  │         │                                                             │  │ │
│  │  │         └──> TsAgentGetHostedAll(agentId, maxSize) - send tasks       │  │ │
│  │  │                                                                       │  │ │
│  │  └───────────────────────────────────────────────────────────────────────┘  │ │
│  │         │                                                                   │ │
│  │         └──> return [HTTP] response to agent                                │ │
│  │                                                                             │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                  │
│  ╔════════════════════════════════════════════════════════════════════════════╗  │
│  ║                          STOP LISTENER                                     ║  │
│  ╚════════════════════════════════════════════════════════════════════════════╝  │
│                                                                                  │
│  GUI ──> POST /listener/stop                                                     │
│                   │                                                              │
│                   V                                                              │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │ TEAMSERVER                                                                  │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  TsListenerStop(listenerName)                                               │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  ┌───────────────────────────────────────────────────────────────────────┐  │ │
│  │  │ EXTENDER                                                              │  │ │
│  │  │         │                                                             │  │ │
│  │  │         V                                                             │  │ │
│  │  │  ExtenderListener.Stop()                                              │  │ │
│  │  │         │                                                             │  │ │
│  │  │         └──> Stop server, cleanup resources                           │  │ │
│  │  │                                                                       │  │ │
│  │  └───────────────────────────────────────────────────────────────────────┘  │ │
│  │                                                                             │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                  │
└──────────────────────────────────────────────────────────────────────────────────┘
```

***

### Listener Config (config.yaml)

```yaml
extender_type: "listener"
extender_file: "listener.so"
ax_file: "ax_config.axs"

listener_name: "LISTENER_NAME"
listener_type: "external"   # or "internal"
protocol: "protocol here"
```

### PluginListener Interface

`InitPlugin` for a listener is `func InitPlugin(ts any, moduleDir string, listenerDir string) adaptix.PluginListener`.

```go
type PluginListener interface {
    Create(name, config string, customData []byte) (ExtenderListener, ListenerData, []byte, error)
    Call(operator string, listenerName string, function string, args string)
}

type ExtenderListener interface {
    Start() error
    Edit(config string) (ListenerData, []byte, error)
    Stop() error
    GetProfile() ([]byte, error)
    InternalHandler(data []byte) (int64, error)
}
```

`InternalHandler` returns the child agent id. An external listener returns `0, nil`.&#x20;

### AxScript for Listener (ax\_config.axs)

The `.axs` file defines the UI for creating/editing listeners in the GUI.

**Required function:**

```javascript
function ListenerUI(mode_create) {
    // mode_create: true = create, false = edit
    
    // Create UI elements
    let labelHost = form.create_label("Host:");
    let comboHost = form.create_combo();
    comboHost.setEnabled(mode_create);  // Non-editable fields when editing
    
    let spinPort = form.create_spin();
    spinPort.setRange(1, 65535);
    spinPort.setValue(443);
    
    // Layout
    let layout = form.create_gridlayout();
    layout.addWidget(labelHost, 0, 0, 1, 1);
    layout.addWidget(comboHost, 0, 1, 1, 1);
    
    // Container for retrieving values
    let container = form.create_container();
    container.put("host_bind", comboHost);
    container.put("port_bind", spinPort);
    
    let panel = form.create_panel();
    panel.setLayout(layout);
    
    // Required return
    return {
        ui_panel: panel,        // Panel with UI
        ui_container: container, // Container for retrieving values
        ui_height: 400,         // Dialog height
        ui_width: 500           // Dialog width
    }
}
```
