Skip to content

Expose SendMessages on NetworkingSockets and support connection lanes #302

@caniko

Description

@caniko

Problem

ISteamNetworkingSockets::SendMessages() is a top-level interface method in the C++ SDK that works with any connection handle, but the Rust bindings only expose it as ListenSocket::send_messages(). This means:

  1. P2P dial-side connections (from connect_p2p()) have no way to call SendMessages — the dialer never gets a ListenSocket, only a NetConnection.
  2. NetConnection::send_message() (singular, wrapping SendMessageToConnection) does not accept a channel/lane parameter, so it always sends on lane 0.

Together, these make it impossible to use connection lanes (ConfigureConnectionLanes) from the dial side — you can configure lanes but can't actually send on them.

Requested Changes

1. Expose SendMessages on NetworkingSockets

The C++ ISteamNetworkingSockets::SendMessages() is not tied to a listen socket. It takes an array of SteamNetworkingMessage_t* where each message has its own m_conn field. The current Rust binding already sets m_conn correctly via NetworkingMessage::set_connection(), so exposing send_messages on NetworkingSockets directly would work:

impl NetworkingSockets {
    pub fn send_messages(
        &self,
        messages: impl IntoIterator<Item = NetworkingMessage>,
    ) -> Vec<SResult<MessageNumber>> {
        // Same implementation as ListenSocket::send_messages,
        // using self.sockets as the ISteamNetworkingSockets pointer
    }
}

This would allow both listeners and dialers to use the efficient batched send path with per-message channel tagging.

2. Add channel parameter to NetConnection::send_message() (optional)

Currently NetConnection::send_message() wraps SendMessageToConnection which doesn't support channels. As a convenience, a send_message_on_channel() variant could allocate a NetworkingMessage, set the channel, and call SendMessages:

impl NetConnection {
    pub fn send_message_on_channel(
        &self,
        data: &[u8],
        send_flags: SendFlags,
        channel: i32,
    ) -> SResult<MessageNumber> { ... }
}

This is lower priority since users can achieve the same thing manually with allocate_message() + set_channel() + send_messages().

Use Case: Connection Lanes

Steam's ConfigureConnectionLanes enables head-of-line blocking prevention and priority-based bandwidth allocation:

sockets.configure_connection_lanes(&connection, 3, &[100, 50, 10], &[1, 4, 1])?;

To actually send on lanes 1+, you need NetworkingMessage::set_channel(lane) followed by SendMessages. The current API makes this impossible for P2P connections where only the listener side has a ListenSocket.

Current Workaround

None clean — the sockets field on ListenSocket is pub(crate), and the raw FFI function SteamAPI_ISteamNetworkingSockets_SendMessages requires the *mut ISteamNetworkingSockets pointer which is also pub(crate) on NetworkingSockets.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions