CMLabs · Psyclone AIOS

4. Custom Interfaces

Services and interfaces: the built-in PsyProbe and Console endpoints, custom HTTP/Telnet/Message ports, protocol autodetection — and what is honestly stubbed.

Services vs interfaces

Psyclone separates what is served (a service) from where and how it is reachable (an interface). Two of each are created automatically unless disabled — the implicit defaults are equivalent to:

<service name="PsyProbe" root="../html" />
<service name="Console" />
<interface name="PsyProbe" protocol="HTTP" service="PsyProbe" />
<interface name="Console" protocol="Telnet" service="Console" />

To disable a built-in endpoint (a common hardening step — see Security & SSL):

<interface protocol="HTTP" service="none" />
<interface protocol="Telnet" service="none" />

The Telnet console

The built-in Console service listens on the main port via protocol autodetect: telnet host 10000 gives an interactive text console into the running system. Because it shares the main port, no extra firewall hole is needed — but conversely, anyone who can reach the main port can reach the console. Disable it (above) or bind it behind an SSL/firewalled port in production.

<interface> reference

<interface name="MyWebInterface" node="Node0" port="1234"
           protocol="HTTP" service="MyWebService"
           timeout="3000" default="yes" />
AttributeMeaningDefault
nameInterface name (required; parse fails without)—
serviceTarget service name (required)—
portTCP/UDP port (required)—
protocolMessage | HTTP | Telnet | RAW (anything else = parse failure)—
nodeNode the interface listens onlocal
timeoutAutodetect timeout, msunset
defaultyes = assumed protocol when autodetect times outno
ipUDP selects UDP (use with protocol="Message"; may share the port number with a TCP interface); otherwise TCPTCP
allowselfsigned, cafile, capathPer-interface SSL verification overrides — see Security & SSL Shippedinherit global

Custom services

A custom service is a component that owns the <post>/<trigger> subscription declared inside it and bridges network clients to the message bus; no module opens a socket. The User Guide explains the four shapes (file hosting, HTTP ingestion, HTTP request/reply, WebSocket/UDP streams) with examples. This section covers running them.

Status. Shipped HTTP, WebSocket, UDP and TCP Message custom services. Not wired yet: custom Telnet services; instances is parsed only (one handler per interface). Engine tests: test=httpservice, test=wsservice, test=udpservice.

A typical deployment: one port number, three ways in

<!-- PsyProbe stays on the node's main port (operators); devices get their own port -->
<service name="Phone">
  <post name="AudioFrame" type="Mimir.Audio.Frame" ttl="10000" />
  <post name="Report"     type="Mimir.Device.Report" />
  <trigger name="Playout" type="Mimir.Playout.Chunk" />
</service>
<interface name="PhoneTCP" port="18600" protocol="HTTP" service="Phone" />               <!-- HTTP + WebSocket -->
<interface name="PhoneUDP" port="18600" ip="UDP" protocol="Message" service="Phone" />  <!-- datagrams -->
  • Ports. Keep PsyProbe and the console on the node's main port, firewalled to operators, and give device traffic its own interface port. HTTP and WebSocket share a TCP interface (the WebSocket upgrade is per connection). A UDP interface may use the same port number, since UDP and TCP ports are separate. Open both TCP and UDP for that port in the firewall or cloud security group.
  • TLS. For wss:// and https:// either build with SSL and use an SSL interface, or terminate TLS in a reverse proxy (Caddy, nginx) in front of a loopback-only HTTP interface. UDP is not encrypted by the service.
  • NAT and mobile networks. A UDP service replies from its own port, the port the device sent to, which is what carrier-grade NAT lets back through. Each datagram refreshes the device's current address, so a phone that changes network is followed without reconnecting. Devices should send a stable PsyDevice entry; without one, each new source address counts as a new device.
  • Receive buffer. UDP service sockets ask for a 4 MB receive buffer (about two minutes of 10 ms audio frames), so a device draining its backlog after an outage is not dropped by the kernel. Linux caps the request at net.core.rmem_max; if that is lower, raise it (for example sysctl -w net.core.rmem_max=4194304). Kernel drops show up as UdpRcvbufErrors in nstat -az UdpRcvbufErrors.
  • Datagram size. One DataMessage per datagram, under 64 KB (keep it under about 1200 bytes to avoid IP fragmentation on mobile links). Larger payloads must be chunked by the sending module.
  • Timeouts. timeout on a request/reply service is the reply deadline (default 5000 ms); a client gets 504 when it passes. Ingestion services answer at once and are unaffected.
  • No loss recovery. Services deliver what arrives and do not retransmit. Reliability (serials, acknowledgements, resending) is the job of the modules on each end.

Checking a service

# HTTP ingestion / request-reply (the reply status tells you which path ran)
curl -s -w ' [%{http_code} %{time_total}s]\n' "http://host:18600/report?probe=1"

# Is the UDP socket bound, and is the kernel dropping datagrams?
ss -lunp | grep 18600
nstat -az UdpRcvbufErrors

# Engine self-tests on a build machine
./Psyclone test=httpservice ; ./Psyclone test=wsservice ; ./Psyclone test=udpservice

In PsyProbe the service appears as a component: its posts show the incoming traffic (with PsyService, PsyServiceConnection and, for UDP, PsyPeerAddress) and its triggers show what went out.

Protocol autodetection: several protocols on one port

Multiple interfaces may share one port; Psyclone sniffs the first bytes to pick the protocol, and after timeout ms with nothing conclusive it assumes the interface marked default="yes":

<interface name="MyWebInterface" port="1234" protocol="HTTP"    service="MyWebService" timeout="3000" default="yes" />
<interface name="MyTelnet"       port="1234" protocol="Telnet"  service="MyTelnetService" />
<interface name="MyMessaging"    port="1234" protocol="Message" service="MyMsgService" />

This is exactly how the main port serves PsyProbe (HTTP), the Console (Telnet) and node-to-node Message traffic simultaneously.

Authentication and encryption attributes Stub

The spec format reserves an <authentication> child on interfaces, and interface-level encryption attributes (SSL/AES256) appear in the newer spec documentation. Both are currently parsed but not acted on: the authentication parser body is empty and returns success, and the encryption attributes have no wiring. Do not rely on them for security. What is shipped is SSL transport with certificate verification for connections — the subject of the next chapter.

Psyclone AIOS · CMLabs