Skip to content

sdk: replace async-wsocket with yawc - #1477

Closed
ifdario wants to merge 8 commits into
nostrdevkit:masterfrom
ifdario:yawc-websocket
Closed

ifdario wants to merge 8 commits into
nostrdevkit:masterfrom
ifdario:yawc-websocket

Conversation

@ifdario

@ifdario ifdario commented Sep 24, 2026 •

Copy link
Copy Markdown

Description

Replace async-wsocket with yawc for relay connections and local relay server handling. Preserve proxy-side hostname resolution and update TLS feature mappings and changelogs.

Why yawc

  • Zero-copy payload handling: decoded frames use bytes::Bytes split directly from the receive buffer, avoiding an extra payload copy as frames move through the transport.
  • Compression support: yawc implements RFC 7692 permessage-deflate, including configurable compression levels and context takeover. Compression remains opt-in in this PR.

Notes to the reviewers

The local relay now uses Hyper for WebSocket upgrades because yawc expects HTTP upgrade handling on the server side. LocalRelay::take_connection remains unchanged.

Testing

  • just precommit

Checklist

  • I followed the contribution guidelines
  • I updated the relevant CHANGELOG.md (if applicable)
  • I understand and can explain all code in this PR

The relay transport now dials with yawc. The transport sink and stream
carry yawc's `Frame` instead of `Message`, so incoming frames are matched
on `OpCode` rather than on enum variants.

Proxied connections go through yawc's own SOCKS5 client using `socks5h`,
which leaves name resolution to the proxy and keeps `.onion` addresses
reachable.

yawc only offers rustls, so `native-tls`, `native-tls-vendored` and
`rustls-tls-native-roots` are gone. `ring` and `aws_lc_rs` now select
yawc's rustls backends, and `rustls-tls-webpki-roots` stays as a no-op
because yawc always trusts the webpki roots. `nwc` and `nostr-connect`
forward the reduced set.

yawc's own `Stream` impl reports a read failure as the end of the stream,
which would hide a broken connection behind a clean close, so the
transport polls frames directly and keeps the two apart.

The local relay's server side still needs async-wsocket, so that
dependency stays for now, without its TLS features.
yawc's server side is reached through an HTTP upgrade, so the listener now
serves HTTP/1 with hyper and calls `WebSocket::upgrade_with_options`. The
upgraded socket comes back over a channel, which keeps the handshake
timeout and the connection permits where they were.

`LocalRelay::take_connection` is unchanged: `WebSocket::from_stream` wraps
a stream whose handshake someone else performed, so callers that upgrade
the request themselves keep working.

The session's frames are matched on `OpCode`, and the error-reporting
socket wrapper is shared with the client transport so a failed read is
still logged rather than read as a clean close.

With this, async-wsocket is gone.
Record the transport's move to yawc, the frame type that comes with it,
the TLS features that no longer have an equivalent, and the local relay
now serving its handshake over hyper. Note the removed features in the
nwc and nostr-connect changelogs too, since both forwarded them.
The helper's docs still pointed at tungstenite's `from_raw_socket`, which
no longer exists here. Say what the helper is actually for instead.
Pass the pending upgrade through the existing channel and await it after Hyper writes the response. This avoids spawning a task per connection while preserving the original upgrade error.
@TheAwiteb

Copy link
Copy Markdown
Member

yawc looks good, but no thanks

@TheAwiteb TheAwiteb closed this Sep 26, 2026
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.

2 participants