Skip to content

handshake: an async handshake, and AsyncConnection::connect_with/accept_with - #65

Merged
Kinflou merged 1 commit into
mainfrom
handshake/async-handshake
Oct 31, 2026
Merged

Kinflou merged 1 commit into
mainfrom
handshake/async-handshake

Conversation

@Kinflou

@Kinflou Kinflou commented Oct 31, 2026 •

Copy link
Copy Markdown
Member

Lets a custom (namespaced) handshake run on an async connection. Until now Handshake worked only over the blocking Transport, and AsyncConnection could run only comline@1 or skip the handshake (new_unverified).

API

// comline_runtime::handshake, feature `async`
pub trait AsyncHandshake {
    fn name(&self) -> &str;
    fn initiate<T: AsyncTransport>(&mut self, transport: &mut T, local: &Facts<'_>)
        -> impl Future<Output = Result<(), RuntimeError>> + Send;
    fn respond<T: AsyncTransport>(&mut self, transport: &mut T, local: &Facts<'_>)
        -> impl Future<Output = Result<(), RuntimeError>> + Send;
}

impl<T: AsyncTransport, W, F> AsyncConnection<T, W, F> {
    pub async fn connect_with<H: AsyncHandshake>(transport: T, format: W, framing: F, handshake: &mut H, ir_hash: u64) -> Result<Self, RuntimeError>;
    pub async fn accept_with<H: AsyncHandshake>(transport: T, format: W, framing: F, handshake: &mut H, ir_hash: u64) -> Result<Self, RuntimeError>;
}
  • The shapes match the blocking Handshake and Connection::connect_with/accept_with. Nothing from an executor is needed (the futures crates only, as with AsyncDispatch), and implementors write async fns.
  • ComlineHandshake and NoHandshake implement it. comline@1 builds and checks its frame with the same code the blocking exchange uses, so it sends the same bytes.
  • AsyncConnection::connect, accept and handshake now run through connect_with/accept_with with ComlineHandshake. Their behaviour is unchanged.
  • Documented in the handshake and async_connection module docs.

Tests

The new tests/async_handshake.rs covers:

  • A custom handshake (com.acme.hello@1-style) runs on both ends of an async connection, and a call goes through after it. A mismatch refuses both ends.
  • ComlineHandshake and NoHandshake work through the _with constructors.
  • Wire bytes: for every conformance vector in conformance/vectors/handshake.json, comline@1 sends exactly that vector's bytes, both over async (initiate and respond) and blocking. The async exchange also refuses each reject vector. The vectors are unchanged.

All of these pass locally: cargo test, cargo test -p comline-runtime --features tokio, the --no-default-features --features alloc and alloc,jsonrpc tests, and cargo metadata --locked.

Unblocks the async half of comline-rust#81's mapped handshakes.

…pt_with

A custom (namespaced) handshake could only run on a blocking connection:
`Handshake` is over the blocking `Transport`, and `AsyncConnection` had only
`comline@1` (`connect`/`accept`/`handshake`) and `new_unverified`.

- `handshake::AsyncHandshake` (feature `async`): `name`, `initiate`,
  `respond`, the latter two returning `Send` futures over an
  `AsyncTransport`. No executor dependency; implementors write `async fn`s.
- `ComlineHandshake` and `NoHandshake` implement it. `comline@1` builds and
  checks its frame with the same code as the blocking exchange, so the bytes
  are the same.
- `AsyncConnection::connect_with` / `accept_with`, shaped like the blocking
  `Connection`'s: (transport, format, framing, &mut handshake, ir_hash).
  `connect`, `accept` and `handshake` now go through them with
  `ComlineHandshake`.

Tests (tests/async_handshake.rs): a custom handshake runs on both ends and
a call goes through after it; one that refuses refuses both ends; the
official handshakes through the `_with` constructors; and `comline@1` over
async sends exactly each conformance vector's bytes (initiate and respond,
checked against the blocking exchange too) and refuses each reject vector.
@Kinflou
Kinflou merged commit 37082de into main Oct 31, 2026
24 checks passed
@Kinflou
Kinflou deleted the handshake/async-handshake branch October 31, 2026 15:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant