NAME

Protocol::HAP::Server - the sans-IO HAP accessory-server engine

SYNOPSIS

use Protocol::HAP::Server;
use Protocol::HAP::Store::Memory;

my $engine = Protocol::HAP::Server->new(
    name   => 'My Bridge',
    pin    => '123-45-678',
    store  => Protocol::HAP::Store::Memory->new,
    output => sub ($session, $bytes) { ... },
);

# One session per connection
my $session = $engine->session_open;

# Feed it what the socket produced; responses arrive through
# the output contract
$engine->receive($session, $bytes)
    or close_the_connection();

# On disconnect
$engine->session_close($session);

DESCRIPTION

This module is the HAP accessory server as a sans-IO engine: it consumes bytes and emits bytes. The host owns sockets, timers, logging, and persistence, injected through the contracts that Protocol::HAP documents. The engine owns everything that is protocol: the read buffer and its 64 KB bound, decryption, HTTP parsing, the endpoint dispatch, the pairing state machines, the accessory database, and event delivery.

The endpoints are /pair-setup, /pair-verify, /identify, /pairings (add, remove, list), /accessories, /characteristics GET and PUT, and /prepare.

CONSTRUCTOR

new takes the identity arguments name, pin, setup_id, and category (default 2, a bridge), and the host contracts:

store

Required. An object with the twelve methods of Protocol/HAP/Store.pod. The engine loads or generates the accessory identity through it.

output

Required. A code reference sub ($session, $bytes). The engine sends every write through it: responses and EVENT notifications alike. The host writes the bytes to the connection that it filed the session under.

logger

Optional. The default is the null logger of Protocol::HAP.

after and cancel

Optional code references for one-shot timers, used for event coalescing. after($seconds, $code) returns a handle; cancel($handle) revokes it. Without them, the host calls flush_events itself.

on_pairing_changed

Optional. A code reference sub ($paired). The engine calls it when the paired state flips, so the host can re-advertise its mDNS TXT record.

THE CONNECTION CONTRACT

session_open()

Return a new Protocol::HAP::Session. The engine allocates session ids from an instance counter; the host files the session beside the connection it belongs to.

receive($session, $bytes)

Consume what the host read from the connection: decrypt, buffer, parse, dispatch, and emit every response through output. The method returns 1, or undef on a fatal condition - a failed decryption or an over-limit request. On undef the host closes the connection.

session_close($session)

Release the pairing lock and the event subscriptions that the session holds.

EVENTS

queue_event($aid, $iid, $value, $originator) queues a notification; the value changes of /characteristics PUT and the device-side notify_change path call it. Without a $value, the current value of the characteristic goes out. Events coalesce for 250 ms through the after/cancel contract. flush_events sends every queued event now; a host without the timer contract calls it directly. send_event delivers one event to the subscribed sessions through output, excluding the originator.

IDENTITY AND DISCOVERY

is_paired, get_config_number, update_config_number, get_device_id, and mdns_txt_records expose what a host needs to advertise the accessory. mdns_txt_records returns a hash reference; the wire format of the TXT string belongs to the host's mDNS responder, not to HAP.

add_accessory and get_bridged_accessories pass through to the bridge, for the host and its device loader.

SEE ALSO

Protocol::HAP, Protocol::HAP::Session, Protocol::HAP::Pairing, Protocol/HAP/Store.pod, spec/HAP-HTTP.md