Skip to content

feat: Add multiplexed RPC stream transport message handling - #40

Merged
huangdijia merged 2 commits into
mainfrom
10969/upgrade-multiplexrpc-transporter
Jun 22, 2026
Merged

feat: Add multiplexed RPC stream transport message handling #40
huangdijia merged 2 commits into
mainfrom
10969/upgrade-multiplexrpc-transporter

Conversation

@xuanyanwow

@xuanyanwowxuanyanwow commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features
    • Added multiplexed RPC message handling for stream-based transport, including frame length validation, non-blocking reads, timeout-aware byte fetching, and resilient connection failure behavior.
    • Automatically filters out ping/pong control frames while passing through regular messages.
  • Documentation
    • Updated PHPDoc type annotations across the codebase (e.g., nullability/union ordering) to improve accuracy for static analysis and IDEs.

@coderabbitai

coderabbitaiBot commented Jun 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a new MultiplexRpcTransporter class extending StreamSocketTransporter with a receive() method that reads length-prefixed frames, skips ping/pong control frames, and returns data frame payloads. A private readBytes() helper accumulates bytes via stream_select/fread, mapping I/O edge cases to specific exceptions. Additionally standardizes nullable type annotation ordering across the codebase to use null|Type convention.

Changes

MultiplexRpcTransporter

Layer / File(s)Summary
Class, constants, and receive() frame loop
src/Transporter/MultiplexRpcTransporter.php
Declares MultiplexRpcTransporter extending StreamSocketTransporter with PING/PONG constants; receive() reads a 4-byte big-endian length header, validates it, reads the body, loops past control frames, and returns the concatenated header+body payload.
readBytes() byte-accumulation helper
src/Transporter/MultiplexRpcTransporter.php
Private readBytes(int $length) loops with stream_select and fread to assemble exactly the requested byte count, throwing RuntimeException on select failure, RecvFailedException on timeout or bad reads, and ConnectionException on peer-closed (feof).

PHPDoc nullable type standardization

Layer / File(s)Summary
Nullable type annotation reordering
src/ClientFactory.php, src/Consul/Response.php, src/Contract/RegistryInterface.php, src/Functions.php, src/MetadataManager.php, src/Support/Arr.php, src/Support/UserAgent.php, src/Transporter/AbstractTransporter.php, src/Transporter/GrpcTransporter.php, src/Transporter/StreamSocketTransporter.php
Standardizes PHPDoc type annotations across ten files to use `null

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 Hop, hop, four bytes I spy,
A length-prefixed frame goes flying by.
Ping and pong? I skip those right,
stream_select loops through the night.
Each byte arrives, assembled neat —
And types now null before they greet! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 66.67% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Title check✅ PassedThe title 'feat: Add multiplexed RPC stream transport message handling' accurately describes the main change—introducing the new MultiplexRpcTransporter class that implements multiplexing RPC receive logic. The title is clear, concise, and highlights the primary feature addition.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 10969/upgrade-multiplexrpc-transporter

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/Transporter/MultiplexRpcTransporter.php`:
- Around line 25-31: Add a maximum frame-size validation check in the
MultiplexRpcTransporter.php file after unpacking the length and the existing
check for length < 4. Before calling readBytes with the $length value, add an
additional condition that validates the length does not exceed a protocol-safe
maximum threshold. If the length exceeds this maximum, throw a
RecvFailedException with an appropriate error message indicating the frame size
is too large. This prevents malicious or buggy peers from forcing excessive
memory consumption by advertising unreasonably large frame sizes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ce7594d9-ef51-4036-8d67-39ce5c2e3182

📥 Commits

Reviewing files that changed from the base of the PR and between eecfabe and 47668b3.

📒 Files selected for processing (1)
  • src/Transporter/MultiplexRpcTransporter.php

Comment on lines +25 to +31
$unpacked = unpack('Nlength', $header);
$length = $unpacked['length'];

if ($length < 4) {
throw new RecvFailedException(sprintf('Invalid package length: %d', $length));
}
$body = $this->readBytes($length);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add a maximum frame-size guard before reading the body.

Line 31 reads a peer-declared $length with no upper bound. A malicious or buggy peer can advertise a huge size and force excessive memory/read pressure before failure. Please reject frames above a protocol-safe max.

Suggested patch
 class MultiplexRpcTransporter extends StreamSocketTransporter
{
public const PING = 'ping';
public const PONG = 'pong';
+ private const MAX_FRAME_LENGTH = 8 * 1024 * 1024; // adjust to protocol limit
@@
$unpacked = unpack('Nlength', $header);
$length = $unpacked['length'];
if ($length < 4) {
throw new RecvFailedException(sprintf('Invalid package length: %d', $length));
}
+ if ($length > self::MAX_FRAME_LENGTH) {+ throw new RecvFailedException(sprintf('Package too large: %d', $length));+ }
$body = $this->readBytes($length);
📝 Committable suggestion

‼️IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
$unpacked = unpack('Nlength', $header);
$length = $unpacked['length'];
if ($length < 4) {
thrownewRecvFailedException(sprintf('Invalid package length: %d', $length));
}
$body = $this->readBytes($length);
class MultiplexRpcTransporter extends StreamSocketTransporter
{
publicconstPING = 'ping';
publicconstPONG = 'pong';
privateconstMAX_FRAME_LENGTH = 8 * 1024 * 1024; // adjust to protocol limit
// ... other class members ...
// In the receive() method or equivalent:
$unpacked = unpack('Nlength', $header);
$length = $unpacked['length'];
if ($length < 4) {
thrownewRecvFailedException(sprintf('Invalid package length: %d', $length));
}
if ($length > self::MAX_FRAME_LENGTH) {
thrownewRecvFailedException(sprintf('Package too large: %d', $length));
}
$body = $this->readBytes($length);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/Transporter/MultiplexRpcTransporter.php` around lines 25 - 31, Add a
maximum frame-size validation check in the MultiplexRpcTransporter.php file
after unpacking the length and the existing check for length < 4. Before calling
readBytes with the $length value, add an additional condition that validates the
length does not exceed a protocol-safe maximum threshold. If the length exceeds
this maximum, throw a RecvFailedException with an appropriate error message
indicating the frame size is too large. This prevents malicious or buggy peers
from forcing excessive memory consumption by advertising unreasonably large
frame sizes.

@xuanyanwowxuanyanwow changed the title Create MultiplexRpcTransporter.phpfeat: Add multiplexed RPC stream transport message handling Jun 22, 2026
@huangdijia
huangdijia merged commit 694aed3 into mainJun 22, 2026
1 check passed
@huangdijia
huangdijia deleted the 10969/upgrade-multiplexrpc-transporter branch June 22, 2026 07:59
@coderabbitaicoderabbitaiBot mentioned this pull request Jun 22, 2026
huangdijia added a commit that referenced this pull request Jun 23, 2026
Co-Authored-By: siam <hzh@addcn.com>
Co-Authored-By: Deeka Wong <8337659+huangdijia@users.noreply.github.com>
Sign up for freeto 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

@xuanyanwow@huangdijia