NetworkTransport drops a JSON message when a TCP receive contains a heartbeat followed by the message

Đang mở
#322 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 2 ngày

@bbdu3 đang làm issue này rồi.

Từ ngày 6/11/2026.

  • #323 của @bbdu3 — đang mở

Đánh giá

Độ khó
3/5
Thời gian dự kiến
1-2 ngày
Mức phù hợp với người mới
25/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Đình trệ
Công nghệ
swift
Lĩnh vực
networking

Hướng nghiên cứu

Read NetworkTransport.receiveLoop() and the heartbeat framing logic to see how received bytes are buffered and consumed. Then inspect the transport tests for a way to deliver multiple frames in one chunk; done means a heartbeat followed by a JSON-RPC response and a later response are both delivered in order. A linked open pull request is already addressing this issue.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

bug

NetworkTransport.receiveLoop() skips an entire received data chunk when Heartbeat.isHeartbeat(newData) returns true. This check only examines the first four bytes, so a chunk containing a heartbeat followed by a JSON-RPC message is treated entirely as a heartbeat.

How to trigger

The sender writes a 12-byte heartbeat, followed by a newline-delimited JSON-RPC message. TCP can deliver these two writes together in one receive callback:

[heartbeat][{"jsonrpc":"2.0","id":1,"result":{}}\n]

The receiver recognizes the heartbeat prefix and executes continue before reaching buffer.append(newData). The JSON-RPC message following the heartbeat is therefore discarded.

I validated this using a Python model of the relevant receive-loop logic, with a second response as a marker:

Separate chunks: heartbeat, response 1, response 2
Delivered response IDs: [1, 2]

Combined chunk: heartbeat + response 1, followed by response 2
Delivered response IDs: [2]

I also tested two separate writes over Linux TCP loopback. In 20 trials, the heartbeat and first response arrived together in one recv() call, with all bytes intact.

These checks establish that the input arrangement can occur over TCP and that the modeled receive logic drops the trailing message. I have not run the Swift SDK or Network.framework on macOS.

Impact

A JSON-RPC message following a heartbeat in the same receive chunk is not delivered through the transport’s receive stream. If it is a response, its pending request can remain unresolved until cancellation, disconnection, or an application-level timeout.

This report is limited to TCP and the case of a complete heartbeat followed by a complete JSON-RPC message in one receive callback.

my fix thought

The receiver should parse frames from buffered bytes instead of treating each receive callback as a complete application message. After identifying a complete heartbeat, it should consume only those 12 bytes and continue processing any remaining bytes.

A regression test could queue heartbeat + response 1 as one chunk, then response 2 as another, and assert that both responses are delivered in order. The same assertion should pass when the heartbeat and responses arrive separately.

If my repair strategy is right, I will open a PR to fix it.

Ngôn ngữ chính
Swift
Star
1.6k
Fork
270
Merge trung bình
2 ngày 7 giờ
Pull request đã merge (30 ngày)
15

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của modelcontextprotocol/swift-sdk

Tất cả issue của modelcontextprotocol/swift-sdk

Issue tương tự

Thêm issue về Swift

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.