Haiku Network Notifications: Watchers and State Reconciliation
Subscribe to Haiku interface, link, and WLAN notifications with explicit watcher lifetime, message validation, coalescing, and fresh roster snapshots.
Haiku’s Network Kit can notify an application when network interfaces, links, or WLAN state change. The notification API is useful for keeping a settings panel or service monitor responsive without polling every few seconds. Notifications are events that tell the application to refresh its model; they are not a durable event log, a complete state snapshot, or a guarantee that every intermediate transition will be observed.
The robust pattern is subscribe, validate, reconcile, and unsubscribe. Subscribe a stable BMessenger target to the event classes the feature needs. When a message arrives, validate its code and fields, mark the local network model dirty, and refresh current state through BNetworkRoster and related APIs. Coalesce bursts so a flurry of link changes does not trigger redundant full scans.
Subscribe to only relevant event classes
start_watching_network(flags, target) supports combinations of interface-change, link-change, and WLAN-change flags. Interface notifications include added, removed, and changed events. Link notifications report device link changes. WLAN notifications include joined, left, scanned, and integrity-failure events. Use the narrowest mask that supports the user-visible feature.
The API documents flags == 0 as stopping notifications for the target; stop_watching_network() is a named convenience. Preserve the exact target BMessenger identity when stopping. If the handler or looper has gone away, handle failure and still tear down local state. Start watching after the target is valid and stop before destroying it.
Check the return status. The current public documentation includes B_NOT_SUPPORTED when the network notifications facility is unavailable. A program should fall back to manual refresh or a clear unavailable indicator rather than assuming no messages means no changes.
Validate message code and fields
The public header defines the message code B_NETWORK_MONITOR. The opcode identifies an event. Current stack implementation uses fields such as interface for interface events, and device, media, link speed, and link quality for a link event; some interface-change messages include old and new flag fields. WLAN event payloads may have event-specific details. Validate what exists before using it and tolerate additional fields.
Do not assume the field device is always present for an interface event, or that an interface name is a permanent identifier. Names can be reused after a device is removed. A notification is a hint to query current state, not permission to apply a delta to a possibly stale UI row.
The API’s C++ BNetworkRoster offers StartWatching() and StopWatching() wrappers. Choose one abstraction consistently. The roster wrapper is convenient when the application already uses it for interface enumeration; the C function can be appropriate for code organized around BMessenger. Do not register through both mechanisms for the same target unless duplicate notifications are intentionally handled.
The notification implementation uses a fixed message code and carries an integer opcode. Current kernel stack code adds an interface string for interface events and a device string plus media, speed, and quality fields for link events; interface flag changes can include old and new flag values. Keep parsing tolerant: a missing optional field should make a row less detailed, not crash the monitor. Treat these field names as the documented current Haiku message contract and verify them again when targeting a different release.
Reconcile instead of replaying deltas
Message delivery can be delayed relative to device changes. Several state transitions may occur before a window processes them. Rather than reconstructing the entire interface table by applying every message in arrival order, mark the model dirty and perform a fresh roster scan. Coalesce duplicate dirty marks into one scheduled refresh. This converges to observed state even if an intermediate notification is missed.
Treat the refresh result separately from the notification. A successful event delivery does not mean the refresh will succeed; a device may vanish between the two. Preserve the last known good model if the roster call fails, mark it stale, and retry with bounded backoff. Do not show “no network” as a conclusion when the query actually failed.
For a link-change event, refresh both the device’s link information and affected interface data before updating a health indicator. A link-up event does not mean DHCP completed, a default route exists, DNS works, or the Internet is reachable. A WLAN joined event does not prove application-layer reachability. Keep these as separate layers in the UI.
Notifications should not be interpreted as a sequence number or a durable queue. If the app is suspended, its target is temporarily busy, or a service restarts, the local view can miss context. On application resume, perform a full refresh even if no event arrived. A periodic, low-frequency reconciliation can be reasonable for a monitor that must recover from missed transitions, but it should be a fallback with a backoff, not a fast poll that duplicates every event.
Use separate model fields for observed link state, address configuration, route availability, name resolution, and application reachability. Update only the layer that a query actually verified. For example, a fresh interface enumeration can confirm the interface exists, while a route query separately confirms a candidate path. This avoids a single green “connected” label that combines unrelated assumptions.
Avoid blocking the handler
The handler should do minimal work: inspect message identity and fields, update a dirty flag, and schedule a refresh. Do not synchronously resolve DNS, scan for WLAN networks, or perform an HTTP request inside a window’s MessageReceived() callback. Use a worker for slower checks and send a result message back with a generation number so an older refresh cannot overwrite a newer state.
If the application receives a burst of B_NETWORK_WLAN_SCANNED messages, avoid rebuilding a large UI for each one. Use a short debounce interval and keep scanning state separate from connected state. For repeated integrity-failure messages, aggregate a count and timestamp rather than flooding logs with sensitive network details.
Scope and limits of the API
The current public NetworkNotifications.h explicitly lists interface, link, and WLAN event groups. Its source comment notes that routes and stack load/unload are not yet events in that interface. Do not write an observer that assumes route changes produce a notification. If route changes matter, refresh routes after an interface or DHCP transition, or use an appropriate configuration event source documented for the target release.
The notifications are also not a packet-capture or key-logging API. They describe device and network state. Application traffic and input activity belong to different APIs. Keep a network monitor focused on the state users expect it to report.
Choose the subscription mask as a resource decision. Listening for WLAN scan events can produce a different cadence from rare interface add/remove events, so a UI that only needs connectivity should not subscribe to every category. If the product needs detailed scan results, keep result processing bounded and avoid rebuilding all interface rows for each scan completion. On shutdown, remove the watcher even if the UI panel is hidden; visibility is not the same as object lifetime.
Example: register and retire one watcher
An application can register a messenger for the categories it consumes:
const uint32 flags = B_WATCH_NETWORK_INTERFACE_CHANGES
| B_WATCH_NETWORK_LINK_CHANGES;
status_t status = start_watching_network(flags, watcherMessenger);
if (status != B_OK)
ShowWatcherUnavailable(status);
At shutdown, call stop_watching_network(watcherMessenger) before its handler or looper is destroyed. The handler should check message->what == B_NETWORK_MONITOR, read opcode as an integer, and validate event-specific fields. It should then request a state reconciliation rather than assume the payload is a complete snapshot.
Test and diagnose
Test add, remove, and change of interfaces; cable unplug/replug; DHCP renewal; WLAN join/leave/scan; service-not-supported behavior; handler teardown; and a burst of events while the UI is busy. Verify the watcher stops when requested and that a late message is harmless. Add a generation counter to prove stale asynchronous scans cannot replace a newer result.
Record event what, opcode, received time, known name, refresh start/end, roster status, and resulting state generation. Redact SSIDs and network identifiers where appropriate. Keep a manual “refresh now” action so users can recover if an event source is unavailable.
Acceptance means subscriptions match the feature, the target lifetime is explicit, the handler remains nonblocking, messages are validated, and a fresh state query is authoritative. With that design, Haiku network notifications improve responsiveness without turning transient messages into false certainty about connectivity.
Related:
- Haiku Network Interfaces: Enumerating State Without Guessing
- Fixing Networking and DHCP Issues on Haiku
Sources: