This document outlines the phases and steps required to implement the TAPS (Transport Services) API in a Rust crate named TransportServices, as specified in RFC 9622. The primary goal is to produce a static library compatible with iOS, macOS, Linux, Android, and Windows, using Tokio for asynchronous operations.
- Initialize a new Rust library crate named
TransportServices. - Define core data structures based on RFC Section 1.1 (Terminology and Notation) (e.g., custom types for
Preference,EndpointIdentifier, etc.). - Define the primary public objects as Rust structs (RFC Section 3, API Summary):
Preconnection,Connection,Listener,Message,MessageContext. - Set up cross-compilation toolchains and targets in
rustup:-
aarch64-apple-ios -
aarch64-apple-darwin(Apple Silicon macOS) -
x86_64-unknown-linux-gnu -
aarch64-unknown-linux-gnu -
aarch64-linux-android -
x86_64-pc-windows-msvc -
aarch64-pc-windows-msvc
-
- Configure
Cargo.tomlto produce astaticlibcrate type. - Integrate
tokioas the core asynchronous runtime. - Design a C-compatible Foreign Function Interface (FFI) layer for the public API to ensure interoperability with Swift, Kotlin/JNI, and C++ (RFC Appendix A, Implementation Mapping).
- Implement the
Preconnectionobject and its creation (NewPreconnection) as defined in RFC Section 6. - Implement Endpoint specification (RFC Section 6.1, Specifying Endpoints):
-
LocalEndpointandRemoteEndpointstructs. - Builder methods for setting identifiers:
WithHostName,WithPort,WithService,WithIPAddress,WithInterface. - Support for Multicast endpoints (RFC Section 6.1.1, Using Multicast Endpoints).
- Support for Protocol-Specific endpoints (RFC Section 6.1.3, Protocol-Specific Endpoints).
-
- Implement Transport Properties specification (RFC Section 4, Transport Properties & 6.2, Specifying Transport Properties):
-
TransportPropertiesstruct. - A
Setmethod for properties, likely using an enum to represent property keys. - Implement all Selection Properties with a
Preferenceenum (Require, Prefer, Avoid, Prohibit, NoPreference) as defined in RFC Section 6.2:-
reliability(6.2.1, Reliable Data Transfer (Connection)) -
preserveMsgBoundaries(6.2.2, Preservation of Message Boundaries) -
perMsgReliability(6.2.3, Configure Per-Message Reliability) -
preserveOrder(6.2.4, Preservation of Data Ordering) -
zeroRttMsg(6.2.5, Use 0-RTT Session Establishment with a Safely Replayable Message) -
multistreaming(6.2.6, Multistream Connections in a Group) -
fullChecksumSend/fullChecksumRecv(6.2.7, Full Checksum Coverage on Sending, 6.2.8, Full Checksum Coverage on Receiving) -
congestionControl(6.2.9, Congestion Control) -
keepAlive(6.2.10, Keep-Alive Packets) -
interface(6.2.11, Interface Instance or Type) -
pvd(6.2.12, Provisioning Domain Instance or Type) -
useTemporaryLocalAddress(6.2.13, Use Temporary Local Address) -
multipath(6.2.14, Multipath Transport) -
advertisesAltaddr(6.2.15, Advertisement of Alternative Addresses) -
direction(6.2.16, Direction of Communication) -
softErrorNotify(6.2.17, Notification of ICMP Soft Error Message Arrival) -
activeReadBeforeSend(6.2.18, Initiating Side Is Not the First to Write)
-
-
- Implement Security Parameters specification (RFC Section 6.3, Specifying Security Parameters and Callbacks):
-
SecurityParametersstruct. - Functions for disabled and opportunistic security.
-
Setmethod for parameters likeallowedSecurityProtocols(6.3.1, Allowed Security Protocols), certificates (6.3.2, Certificate Bundles), ALPN (6.3.4, Application-Layer Protocol Negotiation), etc. - Implement callback mechanisms for trust verification and identity challenges using function pointers (
extern "C" fn) in the FFI layer (6.3.8, Connection Establishment Callbacks).
-
- Implement Active Open:
Preconnection.Initiate()(RFC Section 7.1, Active Open: Initiate).- Return a
Connectionobject. - Use
tokio::net::TcpStream::connectand other Tokio APIs for the underlying network operations. - Implement an event system (e.g., via FFI callbacks) to signal
ReadyorEstablishmentError.
- Return a
- Implement Passive Open:
Preconnection.Listen()(RFC Section 7.2, Passive Open: Listen).- Return a
Listenerobject. - Use
tokio::net::TcpListenerfor asynchronous listening. - Emit
ConnectionReceivedevents containing newConnectionobjects. - Implement
Listener.Stop().
- Return a
- Implement Peer-to-Peer Establishment:
Preconnection.Rendezvous()(RFC Section 7.3, Peer-to-Peer Establishment: Rendezvous).- This is a complex feature. Plan for a phased implementation, potentially starting with basic cases and later adding full NAT traversal (ICE-like) logic.
- Implement
Preconnection.Resolve()to gather candidates. - Emit
RendezvousDoneorEstablishmentErrorevents.
- Implement Connection Groups:
Connection.Clone()(RFC Section 7.4, Connection Groups).- Ensure shared properties are handled correctly between cloned connections.
- Investigate mapping to underlying multistreaming protocols like QUIC if available.
- Implement Message Sending:
Connection.Send()(RFC Section 9.2, Sending Data).- Handle
messageData(e.g.,&[u8]) andmessageContext. - Support partial sends via the
endOfMessageboolean flag (9.2.3, Partial Sends). - Support send batching (
StartBatch/EndBatch) (9.2.4, Batching Sends). - Implement
InitiateWithSend(9.2.5, Send on Active Open: InitiateWithSend).
- Handle
- Implement Send Events via the event callback system (RFC Section 9.2.2, Send Events):
-
Sent(9.2.2.1, Sent) -
Expired(9.2.2.2, Expired) -
SendError(9.2.2.3, SendError)
-
- Implement Message Properties (RFC Section 9.1.3, Message Properties):
-
msgLifetime(9.1.3.1, Lifetime) -
msgPriority(9.1.3.2, Priority) -
msgOrdered(9.1.3.3, Ordered) -
safelyReplayable(9.1.3.4, Safely Replayable) -
final(9.1.3.5, Final) -
msgChecksumLen(9.1.3.6, Sending Corruption Protection Length) -
msgReliable(9.1.3.7, Reliable Data Transfer (Message)) -
msgCapacityProfile(9.1.3.8, Message Capacity Profile Override) -
noFragmentation/noSegmentation(9.1.3.9, No Network-Layer Fragmentation, 9.1.3.10, No Segmentation)
-
- Implement Message Receiving:
Connection.Receive()(RFC Section 9.3.1, Enqueuing Receives).- Handle
minIncompleteLengthandmaxLengthparameters to manage buffering.
- Handle
- Implement Receive Events via the event callback system (RFC Section 9.3.2, Receive Events):
-
Received(for complete messages) (9.3.2.1, Received). -
ReceivedPartial(for partial messages) (9.3.2.2, ReceivedPartial). -
ReceiveError(9.3.2.3, ReceiveError)
-
- Implement a Message Framer system (RFC Section 9.1.2, Message Framers):
- Define a
Framertrait in Rust. - Allow adding framer implementations to a
Preconnection. This is key for layering application protocols like HTTP over the transport.
- Define a
Phase 4: Connection Management & Termination (RFC Section 8, Managing Connections & 10, Connection Termination)
- Implement Connection Property management (RFC Section 8.1, Generic Connection Properties):
-
Connection.SetProperty()andConnection.GetProperties()methods. - Implement settable generic connection properties:
-
recvChecksumLen- Required Minimum Corruption Protection Coverage for Receiving (8.1.1, Required Minimum Corruption Protection Coverage for Receiving) -
connPriority- Connection Priority (8.1.2, Connection Priority) -
connTimeout- Timeout for Aborting Connection (8.1.3, Timeout for Aborting Connection) -
keepAliveTimeout- Timeout for Keep-Alive Packets (8.1.4, Timeout for Keep-Alive Packets) -
connScheduler- Connection Group Transmission Scheduler (8.1.5, Connection Group Transmission Scheduler) -
connCapacityProfile- Capacity Profile (8.1.6, Capacity Profile) -
multipathPolicy- Policy for Using Multipath Transports (8.1.7, Policy for Using Multipath Transports) -
minSendRate/minRecvRate/maxSendRate/maxRecvRate- Bounds on Send or Receive Rate (8.1.8, Bounds on Send or Receive Rate) -
groupConnLimit- Group Connection Limit (8.1.9, Group Connection Limit) -
isolateSession- Isolate Session (8.1.10, Isolate Session)
-
- Implement read-only generic connection properties (RFC Section 8.1.11, Read-Only Connection Properties):
-
connState- Connection State (8.1.11.1, Connection State):- Implement
ConnectionStateenumeration with values:Establishing,Established,Closing,Closed - Expose current connection state through
Connection.GetProperties() - Update connection state during connection lifecycle transitions (see RFC Section 11, Connection State and Ordering of Operations and Events)
- Ensure state is properly synchronized with connection events (Ready, EstablishmentError, Closed, ConnectionError)
- Implement
-
canSend- Can Send Data (8.1.11.2, Can Send Data):- Implement Boolean property indicating whether connection can send data
- Check against
directionSelection Property (unidirectional receive blocks sending) - Check if a Message marked as Final was previously sent (blocks further sending)
- Update dynamically based on connection state and protocol capabilities
-
canReceive- Can Receive Data (8.1.11.3, Can Receive Data):- Implement Boolean property indicating whether connection can receive data
- Check against
directionSelection Property (unidirectional send blocks receiving) - Check if a Message marked as Final was received (may block further receiving for some protocols like TCP half-closed connections)
- Update dynamically based on connection state and protocol capabilities
-
singularTransmissionMsgMaxLen- Maximum Message Size Before Fragmentation or Segmentation (8.1.11.4, Maximum Message Size Before Fragmentation or Segmentation):- Implement property returning Integer (non-negative) or "Not applicable" special value
- Calculate based on Maximum Packet Size (MPS) from underlying protocol stack
- Ensure value is ≤
sendMsgMaxLenproperty - Support dynamic updates via Datagram Packetization Layer Path MTU Discovery (DPLPMTUD) as referenced in RFC 8899
- Handle "Not applicable" case for protocols where fragmentation/segmentation info is unavailable
- Use this value to prevent SendError events for oversized messages
-
sendMsgMaxLen- Maximum Message Size on Send (8.1.11.5, Maximum Message Size on Send):- Implement property returning Integer (non-negative) representing max sendable message size in bytes
- Return 0 when sending is not possible (e.g., unidirectional receive connection)
- Base calculation on underlying transport protocol limitations (e.g., UDP datagram size limits)
- Update dynamically based on connection state and transport stack capabilities
-
recvMsgMaxLen- Maximum Message Size on Receive (8.1.11.6, Maximum Message Size on Receive):- Implement property returning Integer (non-negative) representing max receivable message size in bytes
- Return 0 when receiving is not possible (e.g., unidirectional send connection)
- Base calculation on underlying transport protocol limitations and available buffer space
- Update dynamically based on connection state and transport stack capabilities
-
- Implement TCP-specific properties (RFC Section 8.2, TCP-Specific Properties: User Timeout Option (UTO)):
-
tcp.userTimeoutValue- Advertised User Timeout (8.2.1, Advertised User Timeout) -
tcp.userTimeoutEnabled- User Timeout Enabled (8.2.2, User Timeout Enabled) -
tcp.userTimeoutChangeable- Timeout Changeable (8.2.3, Timeout Changeable)
-
-
- Implement Connection Lifecycle Events via the event callback system (RFC Section 8.3, Connection Lifecycle Events):
-
SoftError(8.3.1, Soft Errors) -
PathChange(8.3.2, Path Change)
-
- Implement Connection Termination actions (RFC Section 10, Connection Termination):
-
Connection.Close() -
Connection.Abort() -
Connection.CloseGroup() -
Connection.AbortGroup()
-
- Implement Termination Events via the event callback system (RFC Section 10):
-
Closed -
ConnectionError
-
- Create build scripts (e.g.,
build.rsor shell scripts) to automate the cross-compilation for all target platforms. - Automate the generation of static libraries (
libtransport_services.a,transport_services.lib) for each target architecture. - Use
cbindgento automatically generate a C header file (transport_services.h) from the FFI layer. - Create wrapper packages for easy integration into platform-native projects:
- A Swift Package that bundles the
.aand.hfiles for iOS and macOS. - An Android Archive (AAR) that includes the
.sofiles for different Android ABIs. - A NuGet package for Windows developers.
- A Swift Package that bundles the
- Provide comprehensive documentation and examples for using the library on each target platform.
- Phase 5.1: FFI Enhancements for Cross-Platform Async Bindings
- Goal: Refine the C-FFI to provide a robust foundation for creating ergonomic,
async/await-native wrappers in Swift, C#, and Python. - High-Level Strategy:
- Maintain a pure
extern "C"API as the stable, core interface. - Implement language-specific wrapper libraries (Swift Package, NuGet, Python Wheel) that translate the C-FFI into idiomatic async patterns for each language.
- Maintain a pure
- Core FFI Architectural Improvements:
- Centralize Tokio Runtime:
- Implement
transport_services_init_runtime()to create a single, shared, multi-threaded Tokio runtime. - Implement
transport_services_shutdown_runtime()to gracefully shut down the shared runtime. - Refactor all FFI functions to use the shared runtime instead of creating new runtimes and threads per call. This eliminates major performance bottlenecks and potential deadlocks.
- Implement
- Adopt a Consistent Async Pattern:
- Ensure all operations that perform I/O are non-blocking and use callbacks.
- The standard pattern should be:
function(..., callback, user_data), whereuser_datais a pointer passed back to the callback, allowing wrappers to manage state.
- Centralize Tokio Runtime:
- Specific FFI Function Modifications and Additions:
- Connection API:
- Add Async Receive: Implement
transport_services_connection_receive(handle: *mut Handle, message_callback: fn(*const Message), error_callback: fn(Error), user_data: *mut c_void). This is the most critical missing piece for async data handling. - Make Close Async: Change
transport_services_connection_closetotransport_services_connection_close_async(handle, callback, user_data)to properly signal when the graceful close is complete.
- Add Async Receive: Implement
- Listener API:
- Add Connection Callback: Implement
transport_services_listener_set_callbacks(handle, connection_received_callback, error_callback, user_data)to handle incoming connections asynchronously instead of requiring polling. - Make Stop Async: Change
transport_services_listener_stoptotransport_services_listener_stop_async(handle, callback, user_data).
- Add Connection Callback: Implement
- Event Handling:
- Replace Polling with Callbacks: Deprecate
transport_services_connection_poll_event. - Implement Event Callback Setter: Add
transport_services_connection_set_event_callback(handle, event_callback, user_data)to push events likePathChange,Closed, etc., to the client.
- Replace Polling with Callbacks: Deprecate
- Connection API:
- Guidance for Language-Specific Wrappers:
- Swift Wrapper (Swift Package):
- Use
withCheckedThrowingContinuationto wrap callback-based functions intoasync throwsmethods. - Use
AsyncStreamto wrap the event and listener callbacks, providing an idiomatic way to iterate over events and incoming connections (for await event in connection.events). - Manage object lifetimes with
Unmanagedand a customDeinitclass.
- Use
- C# Wrapper (NuGet Package):
- Use
TaskCompletionSource<T>to bridge C callbacks toTask-basedasync/await. - Use
IAsyncEnumerable<T>andyield returnto expose event streams. - Manage callback delegates and context with
GCHandle.
- Use
- Python Wrapper (PyO3/CFFI Wheel):
- Use
cffiorctypesfor C interop. - Bridge C callbacks to
asyncioby usingasyncio.Futureandloop.call_soon_threadsafeto safely interact with the event loop from the FFI callback thread. - Expose async iterators (
async for) for event streams.
- Use
- Swift Wrapper (Swift Package):
- Goal: Refine the C-FFI to provide a robust foundation for creating ergonomic,