Skip to content

fix(rsocket-core): Pass fragmentation config to server-side responder streams #306

Description

@Niteesh

Description

Bug

RSocketServer accepts a fragmentation.maxOutboundFragmentSize config, but it only applies to
the requester side (server-initiated requests). The responder side (server responses to client
requests) always uses fragmentSize=0, meaning responses are never fragmented.

This causes a crash when the server tries to send a response larger than 16MB (the RSocket frame
length field is 24-bit, max 16,777,215 bytes), because writeUInt24BE overflows:

RangeError: The value of "value" is out of range. It must be >= 0 and <= 255.
    at writeUInt24BE (rsocket-core/src/Codecs.ts:80)
    at serializeFrameWithLength (rsocket-core/src/Codecs.ts:161)

Root Cause

Two issues in packages/rsocket-core/src/RSocketServer.ts:

  1. Constructor doesn't store fragmentation: The fragmentation field from ServerConfig is
    never assigned to this, so this.fragmentation is always undefined.

  2. DefaultStreamRequestHandler hardcodes fragmentSize=0: Even if this.fragmentation were
    stored, the stream handler is created with fragmentSize=0 instead of using the configured value.

Fix

 constructor(config: ServerConfig) {
     this.acceptor = config.acceptor;
     this.transport = config.transport;
     this.lease = config.lease;
+    this.fragmentation = config.fragmentation;
     this.serverSideKeepAlive = config.serverSideKeepAlive;
-const streamsHandler = new DefaultStreamRequestHandler(responder, 0);
+const streamsHandler = new DefaultStreamRequestHandler(
+    responder,
+    this.fragmentation?.maxOutboundFragmentSize ?? 0,
+);

Impact

Without this fix, any RSocket server using rsocket-core v1 cannot send responses larger than ~16MB.
The fragmentation infrastructure (Fragmenter.ts, RequestResponseResponderStream.onNext) already
exists and works correctly — it just never receives a non-zero fragmentSize.

Reproduction

const server = new RSocketServer({
    transport: new TcpServerTransport({ listenOptions: { port: 9090 } }),
    fragmentation: { maxOutboundFragmentSize: (1 << 24) - 1 - 9 }, // This is ignored!
    acceptor: {
        async accept() {
            return {
                requestResponse(payload, responder) {
                    // This crashes if payload response > 16MB
                    responder.onNext({ data: Buffer.alloc(20_000_000) }, true);
                    return { cancel() {}, onExtension() {} };
                },
            };
        },
    },
});

Files Changed

  • packages/rsocket-core/src/RSocketServer.ts (2 lines)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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