libp2p / libp2p/unified-testing

nim-v1.14 / python-v0.x WebSocket protocol negotiation failure

Open
#17 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

nim python
Dominant language
Shell
Stars
7
Forks
19
PR merge metrics
No merged PRs in 30d

Description

Repos:

Transport: ws, Secure: noise

Summary

nim-v1.14 and python-v0.x fail WebSocket interop in both directions. When nim is the dialer, the protocol upgrade fails with "Incorrect message received!" during multistream-select. When python is the dialer, the connection succeeds and ping stream is created, but the muxed stream closes prematurely during the ping response read, causing a MuxedStreamEOF.

Failing tests (4)

  • nim-v1.14 x python-v0.x (ws, noise, mplex)
  • nim-v1.14 x python-v0.x (ws, noise, yamux)
  • python-v0.x x nim-v1.14 (ws, noise, mplex)
  • python-v0.x x nim-v1.14 (ws, noise, yamux)

Error output (nim as dialer)

ERR Unexpected error  description="Failed to finish outgoing upgrade in internalConnect:
Incorrect message received!"

Error output (python as dialer)

The connection and stream creation succeed, but the ping response read fails with a stream EOF:

Connected successfully
Creating ping stream
Ping stream created successfully
Performing ping test
sending ping to 12D3KooW...
error occurred:
Dialer error: Exceptions from Trio nursery (1 sub-exception)
  ...
    | libp2p.stream_muxer.exceptions.MuxedStreamEOF: Stream closed
    |
    | The above exception was the direct cause of the following exception:
    |
    |   File "/app/ping_test.py", line 520, in send_ping
    |     response = await stream.read(PING_LENGTH)
    | libp2p.network.stream.exceptions.StreamEOF

The nim listener appears to close the muxed stream after receiving the ping data but before the python dialer reads the response.

Notes

  • When nim is the dialer, the failure is in multistream-select framing: the two implementations disagree on protocol negotiation framing over WebSocket (e.g., length-prefixed vs raw framing).
  • When python is the dialer, the TCP/noise/muxer negotiation succeeds but the ping protocol fails. The stream is closed by the nim side prematurely, suggesting nim's ping handler may not properly hold the stream open for the response.
  • Both implementations work with other peers (go, rust, js) over ws, so the issue is specific to nim-python interop.
  • Both mplex and yamux muxers are affected in both directions, confirming the issue is not muxer-specific.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the four listed WebSocket/noise interop tests and compare multistream-select framing when Nim dials with the ping stream lifecycle when Python dials. Inspect the Nim and Python implementations around protocol negotiation and ping handling; done means all four combinations pass for both mplex and yamux.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
distributed-systems, networking
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.