Expand description
§networkframework-rs
Safe Rust bindings for Apple’s Network.framework, backed by a Swift bridge plus an opt-in raw FFI surface.
SDK coverage: 500 / 500 SDK symbols verified, macOS 26.2 SDK.
See COVERAGE.md for the logical-area map and
COVERAGE_AUDIT.md for the symbol-by-symbol audit.
§Why this crate
- Broad transport coverage: TCP clients and listeners, UDP, TLS, QUIC, WebSocket, and Bonjour discovery/advertising all live in one safe crate.
- More than sockets: endpoints, connection parameters, path monitoring, content contexts, framers, connection groups, privacy contexts, and resolver / proxy configuration are part of the public safe API.
- Async where it helps: this is the Tier 1 crate with a native
async/awaitstory for Network.framework event streams. - Runtime-gated APIs handled for you: newer framework features stay safe, and unsupported runtime combinations surface as Rust errors instead of raw Objective-C / C state leaking upward.
- Escape hatch available: enable
raw-ffiwhen you need direct bridge access beyond the safe wrappers.
§Feature flags
- Default: safe blocking + callback-oriented API.
async: enablesnetworkframework::async_apistream wrappers.raw-ffi: exposesnetworkframework::raw_ffi::*.
§Installation
[dependencies]
networkframework = "0.13.1"Enable async support explicitly when you want awaitable event streams:
[dependencies]
networkframework = { version = "0.13.1", features = ["async"] }§Async usage
The networkframework::async_api module turns callback-based
Network.framework notifications into executor-agnostic Rust futures/streams.
It does not lock you into Tokio, async-std, or any other runtime-specific
public API. Instead, the crate uses doom-fish-utils async primitives
(doom_fish_utils::completion helpers plus the stream-based next().await
surface) so the same types compose with whatever executor your application
already uses.
Today the async surface includes:
ConnectionStateStreamConnectionViabilityStreamConnectionBetterPathStreamConnectionPathChangedStreamListenerEventStreamPathUpdateStreamBrowserEventStream
A minimal async round trip can use an awaitable listener stream while keeping
transport I/O on the same TcpClient / accepted-connection types as the sync
API:
use networkframework::async_api::{ListenerEvent, ListenerEventStream};
use networkframework::{TcpClient, TcpListener};
async fn run() -> Result<(), networkframework::NetworkError> {
let listener = TcpListener::bind(0)?;
let port = listener.local_port();
let events = ListenerEventStream::subscribe(&listener, 8);
let client = TcpClient::connect("127.0.0.1", port)?;
client.send(b"ping")?;
while let Some(event) = events.next().await {
match event {
ListenerEvent::NewConnection(server) => {
let request = server.receive(1024)?;
assert_eq!(request, b"ping");
server.send(b"pong")?;
break;
}
ListenerEvent::State { .. } => {}
}
}
let reply = client.receive(1024)?;
assert_eq!(reply, b"pong");
Ok(())
}For tiny binaries, pollster::block_on(run()) is often enough. In larger
applications, just await the same stream types from your existing runtime.
The bundled 07_async_streams example shows
PathUpdateStream and ConnectionStateStream in practice.
§Sync / callback usage
The original API remains small and direct for request / response flows. If you prefer a blocking round trip, the same TCP primitives work without any feature flags:
use networkframework::{TcpClient, TcpListener};
fn main() -> Result<(), networkframework::NetworkError> {
let listener = TcpListener::bind(0)?;
let port = listener.local_port();
let server = std::thread::spawn(move || -> Result<(), networkframework::NetworkError> {
let connection = listener.accept()?;
let request = connection.receive(1024)?;
assert_eq!(request, b"ping");
connection.send(b"pong")?;
Ok(())
});
let client = TcpClient::connect("127.0.0.1", port)?;
client.send(b"ping")?;
let reply = client.receive(1024)?;
assert_eq!(reply, b"pong");
server.join().expect("server thread")?;
Ok(())
}Callback-oriented APIs are still available for long-lived observers and
framework-managed events. Common entry points include
start_path_monitor, start_browser_with_descriptor,
start_browser_results_with_descriptor, advertise_with_descriptor, and the
various set_*_handler hooks on connection, group, and protocol types.
§Examples
The repository ships runnable examples across the main areas of the crate:
01_get_example— local TCP listener/client round trip.02_tls_get—ConnectionParameterspolicy tuning and protocol stacking.03_udp_and_path— UDP parameters, endpoint construction, and path monitor snapshots.04_bonjour— Bonjour browse descriptors and browser events.05_websocket— WebSocket protocol definitions plus QUIC option inspection.06_bonjour_advertise— Bonjour advertising with TXT records.07_async_streams— async stream subscriptions for path and connection events (--features async).framer_length_prefix— custom length-prefixed framer wiring.interface_list— enumerating local network interfaces.connection_group— multicast connection groups and state callbacks.content_context_overview— content-context identifiers, priorities, and antecedents.resolver_overview— DNS-over-HTTPS and DNS-over-TLS resolver configs.privacy_context_overview— encrypted name resolution plus proxy policy.quic_options— QUIC transport tuning and ALPN setup.
Run any example directly:
cargo run --example 01_get_example
cargo run --example 07_async_streams --features async§Coverage and audit
COVERAGE.md— logical-area coverage map, example links, and test references.COVERAGE_AUDIT.md— full audited SDK symbol table for the macOS 26.2 headers.
§Availability notes
Some Apple APIs are runtime-gated by the operating system:
- Application-service browsing / advertising / parameters: macOS 13+
- Relay and Oblivious HTTP proxy configuration: macOS 14+
- Ultra-constrained path / parameter flags and link quality: newer SDK/runtime combinations
The safe wrappers return NetworkError::InvalidArgument when a requested API
is unavailable at runtime.
§Validation
cargo build --all-features
cargo clippy --all-targets --all-features -- -D warnings§Status
Actively developed. Targets macOS and tracks the audited Network.framework SDK surface closely.
§License
Licensed under either of:
- MIT license (
LICENSE-MIT) - Apache License 2.0 (
LICENSE-APACHE)
at your option.
§API documentation
Re-exports§
pub use advertise_descriptor::advertise_with_descriptor;pub use advertise_descriptor::AdvertiseDescriptor;pub use advertise_descriptor::Advertiser;pub use browser::advertise_bonjour_service;pub use browser::start_browser;pub use browser::start_browser_results_with_descriptor;pub use browser::start_browser_with_descriptor;pub use browser::BonjourAdvertiser;pub use browser::BrowseDescriptor;pub use browser::BrowseResult;pub use browser::BrowseResultChange;pub use browser::BrowseResultsBrowser;pub use browser::Browser;pub use browser::BrowserEvent;pub use browser::BrowserState;pub use browser::DiscoveredService;pub use client::ContentContext;pub use client::ReceivedContent;pub use client::TcpClient;pub use connection::Connection;pub use connection_group::ConnectionGroup;pub use connection_group::ConnectionGroupDescriptor;pub use connection_group::ConnectionGroupMessage;pub use connection_group::ConnectionGroupState;pub use connection_report::DataTransferPathReport;pub use connection_report::DataTransferReport;pub use connection_report::DataTransferReportState;pub use connection_report::EstablishmentProtocol;pub use connection_report::EstablishmentReport;pub use connection_report::ResolutionProtocol;pub use connection_report::ResolutionReport;pub use connection_report::ResolutionSource;pub use connection_report::ResolutionStep;pub use endpoint::Endpoint;pub use endpoint::EndpointType;pub use error::ErrorDomain;pub use error::FrameworkError;pub use error::NetworkError;pub use ethernet_channel::EthernetChannel;pub use ethernet_channel::EthernetChannelState;pub use ethernet_channel::EthernetFrame;pub use framer::Framer;pub use framer::FramerContext;pub use framer::FramerDefinition;pub use framer::FramerMessage;pub use framer::FramerMessageView;pub use framer::FramerOptions;pub use framer::FramerStart;pub use group::Group;pub use group::GroupDescriptor;pub use group::GroupMessage;pub use group::GroupState;pub use interface::list_interfaces;pub use interface::InterfaceType;pub use interface::NetworkInterface;pub use listener::TcpListener;pub use parameters::ConnectionParameters;pub use parameters::ParametersAttribution;pub use path::LinkQuality;pub use path::Path;pub use path::PathStatus;pub use path::PathUnsatisfiedReason;pub use path_monitor::start_path_monitor;pub use path_monitor::start_path_monitor_for_ethernet_channel;pub use path_monitor::start_path_monitor_with_type;pub use path_monitor::PathMonitor;pub use path_monitor::PathUpdate;pub use privacy::PrivacyContext;pub use privacy::ProxyConfig;pub use privacy::RelayHop;pub use privacy::ResolverConfig;pub use privacy::UrlSessionConfiguration;pub use protocol::IpEcnFlag;pub use protocol::IpLocalAddressPreference;pub use protocol::IpVersion;pub use protocol::ProtocolDefinition;pub use protocol::ProtocolMetadata;pub use protocol::ProtocolOptions;pub use protocol::TcpMultipathVersion;pub use quic::QuicConnection;pub use quic::QuicOptions;pub use txt_record::TxtRecord;pub use txt_record::TxtRecordEntry;pub use txt_record::TxtRecordFindResult;pub use txt_record::TxtRecordLookup;pub use udp::UdpClient;pub use websocket::Opcode;pub use websocket::WebSocket;pub use websocket::WsCloseCode;pub use websocket::WsMessage;pub use websocket::WsRequest;pub use websocket::WsResponse;pub use websocket::WsResponseStatus;pub use websocket::WsVersion;
Modules§
- advertise_
descriptor - Advertise-descriptor helpers.
- async_
api async - Async stream wrappers for Network.framework callback-based APIs.
- browser
Browser— Bonjour and application-service discovery vianw_browser.- client
TcpClient— synchronous outbound TCP connection via Network.framework.- connection
- Connection-oriented helpers and aliases.
- connection_
group - Connection groups built on
nw_connection_group_*. - connection_
report - Connection establishment and data-transfer reports.
- content_
context - Content-context aliases.
- endpoint
- Endpoint helpers backed by
nw_endpoint_t. - error
- Errors raised by
networkframework. - ethernet_
channel - Ethernet channel wrappers.
- framer
- Custom protocol framers built on
nw_framer_*. - group
- Connection-group aliases.
- interface
- Network interface enumeration helpers.
- listener
TcpListener— synchronous TCP listener via Network.framework.- parameters
- Configurable
nw_parameterswrappers for advanced connections. - path
- Path snapshots backed by
nw_path_t. - path_
monitor PathMonitor— observe network reachability and interface changes vianw_path_monitor.- prelude
- Common imports.
- privacy
- Privacy contexts, proxy configuration, and encrypted resolver settings.
- privacy_
context - Privacy-context aliases.
- protocol
- Protocol definitions and options.
- proxy_
config - Proxy-configuration aliases.
- quic
- QUIC helpers backed by Network.framework.
- raw_ffi
raw-ffi - Raw FFI ABI surface for advanced callers.
- resolver
- Resolver aliases.
- txt_
record - TXT-record helper APIs.
- udp
UdpClient— connected-mode UDP via Network.framework.- websocket
WebSocket— RFC 6455 WebSocket client over Network.framework.
Structs§
- Protocol
Stack - Mutable wrapper around
nw_protocol_stack_t. - Quic
Metadata - QUIC protocol metadata attached to a connection or content context.
- Security
Protocol Metadata - Opaque
sec_protocol_metadata_textracted from QUIC metadata. - Security
Protocol Options - Opaque
sec_protocol_options_textracted from QUIC options.
Enums§
- Expired
DnsBehavior - Policy controlling whether expired DNS answers may be used.
- Interface
Radio Type - Radio technology reported for an interface path sample.
- Multipath
Service - Multipath policy applied to new connections.
- Quic
Stream Type - QUIC stream direction or datagram mode.
- Service
Class - Connection service class applied to new paths.