Skip to content
This repository was archived by the owner on Aug 15, 2025. It is now read-only.

Latest commit

 

History

History
216 lines (203 loc) · 18.4 KB

File metadata and controls

216 lines (203 loc) · 18.4 KB

Transport Services Rust Implementation Checklist

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.

Phase 0: Project Setup & Core Abstractions

  • 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.toml to produce a staticlib crate type.
  • Integrate tokio as 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).

Phase 1: Pre-establishment (RFC Section 6, Preestablishment Phase)

  • Implement the Preconnection object and its creation (NewPreconnection) as defined in RFC Section 6.
  • Implement Endpoint specification (RFC Section 6.1, Specifying Endpoints):
    • LocalEndpoint and RemoteEndpoint structs.
    • 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):
    • TransportProperties struct.
    • A Set method for properties, likely using an enum to represent property keys.
    • Implement all Selection Properties with a Preference enum (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):
    • SecurityParameters struct.
    • Functions for disabled and opportunistic security.
    • Set method for parameters like allowedSecurityProtocols (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).

Phase 2: Connection Establishment (RFC Section 7, Establishing Connections)

  • Implement Active Open: Preconnection.Initiate() (RFC Section 7.1, Active Open: Initiate).
    • Return a Connection object.
    • Use tokio::net::TcpStream::connect and other Tokio APIs for the underlying network operations.
    • Implement an event system (e.g., via FFI callbacks) to signal Ready or EstablishmentError.
  • Implement Passive Open: Preconnection.Listen() (RFC Section 7.2, Passive Open: Listen).
    • Return a Listener object.
    • Use tokio::net::TcpListener for asynchronous listening.
    • Emit ConnectionReceived events containing new Connection objects.
    • Implement Listener.Stop().
  • 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 RendezvousDone or EstablishmentError events.
  • 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.

Phase 3: Data Transfer (RFC Section 9, Data Transfer)

  • Implement Message Sending: Connection.Send() (RFC Section 9.2, Sending Data).
    • Handle messageData (e.g., &[u8]) and messageContext.
    • Support partial sends via the endOfMessage boolean 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).
  • 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 minIncompleteLength and maxLength parameters to manage buffering.
  • 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 Framer trait in Rust.
    • Allow adding framer implementations to a Preconnection. This is key for layering application protocols like HTTP over the transport.

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() and Connection.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 ConnectionState enumeration 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)
      • canSend - Can Send Data (8.1.11.2, Can Send Data):
        • Implement Boolean property indicating whether connection can send data
        • Check against direction Selection 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 direction Selection 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 ≤ sendMsgMaxLen property
        • 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

Phase 5: Packaging and Distribution

  • Create build scripts (e.g., build.rs or 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 cbindgen to 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 .a and .h files for iOS and macOS.
    • An Android Archive (AAR) that includes the .so files for different Android ABIs.
    • A NuGet package for Windows developers.
  • 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.
    • 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.
      • 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), where user_data is a pointer passed back to the callback, allowing wrappers to manage state.
    • 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_close to transport_services_connection_close_async(handle, callback, user_data) to properly signal when the graceful close is complete.
      • 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_stop to transport_services_listener_stop_async(handle, callback, user_data).
      • 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 like PathChange, Closed, etc., to the client.
    • Guidance for Language-Specific Wrappers:
      • Swift Wrapper (Swift Package):
        • Use withCheckedThrowingContinuation to wrap callback-based functions into async throws methods.
        • Use AsyncStream to 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 Unmanaged and a custom Deinit class.
      • C# Wrapper (NuGet Package):
        • Use TaskCompletionSource<T> to bridge C callbacks to Task-based async/await.
        • Use IAsyncEnumerable<T> and yield return to expose event streams.
        • Manage callback delegates and context with GCHandle.
      • Python Wrapper (PyO3/CFFI Wheel):
        • Use cffi or ctypes for C interop.
        • Bridge C callbacks to asyncio by using asyncio.Future and loop.call_soon_threadsafe to safely interact with the event loop from the FFI callback thread.
        • Expose async iterators (async for) for event streams.