Skip to content

bug: yamux sends SYN/ACK/FIN/RST as TYPE_DATA instead of TYPE_WINDOW_UPDATE #1271

@asabya

Description

@asabya

Summary

The yamux stream muxer sends SYN, ACK, FIN, and RST control frames with TYPE_DATA (0) instead of TYPE_WINDOW_UPDATE (1). This violates the yamux spec and breaks interop with go-yamux, which expects control frames as TYPE_WINDOW_UPDATE.

Additionally, the length field in SYN/ACK frames should carry the window size (not 0), matching go-yamux behavior.

Impact

  • Go interop broken: Go peers reject or misinterpret control frames sent as TYPE_DATA
  • Frame interleaving: Without write serialization, concurrent writes can corrupt frames on the wire

Root Cause

In libp2p/stream_muxer/yamux/yamux.py:

  • open_stream() sends SYN with TYPE_DATA — should be TYPE_WINDOW_UPDATE with length=DEFAULT_WINDOW_SIZE
  • close() sends FIN with TYPE_DATA — should be TYPE_WINDOW_UPDATE
  • reset() sends RST with TYPE_DATA — should be TYPE_WINDOW_UPDATE
  • ACK responses use TYPE_DATA — should be TYPE_WINDOW_UPDATE with length=DEFAULT_WINDOW_SIZE
  • No write lock — concurrent frame writes can interleave

Fix

A working fix is available at asabya/py-libp2p#1:

  • Changed all control frames to TYPE_WINDOW_UPDATE
  • Added _write_lock (trio.Lock) to serialize all frame writes
  • SYN/ACK now include DEFAULT_WINDOW_SIZE in the length field

Ref: go-yamux stream.go, session.go, const.go

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions