Nethermind.Libp2p.Protocols.RequestResponse 1.1.1

dotnet add package Nethermind.Libp2p.Protocols.RequestResponse --version 1.1.1
                    
NuGet\Install-Package Nethermind.Libp2p.Protocols.RequestResponse -Version 1.1.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Nethermind.Libp2p.Protocols.RequestResponse" Version="1.1.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Nethermind.Libp2p.Protocols.RequestResponse" Version="1.1.1" />
                    
Directory.Packages.props
<PackageReference Include="Nethermind.Libp2p.Protocols.RequestResponse" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Nethermind.Libp2p.Protocols.RequestResponse --version 1.1.1
                    
#r "nuget: Nethermind.Libp2p.Protocols.RequestResponse, 1.1.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Nethermind.Libp2p.Protocols.RequestResponse@1.1.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Nethermind.Libp2p.Protocols.RequestResponse&version=1.1.1
                    
Install as a Cake Addin
#tool nuget:?package=Nethermind.Libp2p.Protocols.RequestResponse&version=1.1.1
                    
Install as a Cake Tool

RequestResponse Protocol

The RequestResponse Protocol provides a generic, type-safe implementation of request-response pattern in libp2p. It enables peers to exchange structured data using Protocol Buffers serialization with automatic message parsing and error handling.

Overview

The RequestResponseProtocol<TRequest, TResponse> class implements the ISessionProtocol<TRequest, TResponse> interface, providing:

  • Type Safety: Strongly typed request and response messages
  • Protocol Buffers: Automatic serialization/deserialization using Google.Protobuf
  • Error Handling: Comprehensive logging and exception management
  • Bidirectional Communication: Support for both client (dial) and server (listen) operations

Usage

Register the Protocol

Use the extension method to register your protocol with the peer factory:

using Nethermind.Libp2p.Protocols;

// Register the protocol with a handler function
var peerFactory = new PeerFactoryBuilder()
    .AddRequestResponseProtocol<ExampleRequest, ExampleResponse>(
        protocolId: "/example/1.0.0",
        handler: HandleExampleRequest,
        isExposed: true)
    .Build();

// Handler function implementation
private static async Task<ExampleResponse> HandleExampleRequest(
    ExampleRequest request,
    ISessionContext context)
{
    // Process the request
    var results = ProcessQuery(request.Query, request.Limit);

    return new ExampleResponse
    {
        Results = { results },
        Success = true
    };
}

Read deadlines

Existing constructors and builder overloads use a 30-second read timeout. To configure it, use an overload with TimeSpan readTimeout before the protocol ID (or before the cancellation-aware handler):

builder.AddRequestResponseProtocol<ExampleRequest, ExampleResponse>(
    TimeSpan.FromSeconds(15), "/example/1.0.0", HandleExampleRequest);

The timeout covers the entire length prefix and protobuf body, including fragmented reads. The dialer starts it after transmitting the request. The timer is disposed after deserialization; handlers and response writes have no new deadline. One-way dialing starts no response timer. Channel closure also cancels reads, and cancellation-aware handlers retain the channel lifetime token.

Timeouts must be positive, finite, and at most TimeSpan.FromMilliseconds(uint.MaxValue - 1). Both handler forms accept an optional TimeProvider in the new overloads; builder extensions also resolve it from DI. Builders supporting IProtocolFactoryBuilder resolve the clock from the final services at Build(), including services added after protocol registration. An explicit TimeProvider takes precedence over DI. Builders without protocol factories resolve the clock from their current service provider during registration. Routine channel closure, aborts, duplicate sessions, and expected read cancellations are logged at Debug. Other stream failures are logged at Warning with the exception attached. Exceptions continue to propagate to the stream owner.

The dotnet-libp2p meter exposes libp2p.request_response.read_timeouts, a counter of failed reads whose deadline expired while channel cancellation was not requested. It has protocol (the registered protocol ID) and direction (inbound for request reads, outbound for response reads) tags. Ordinary hangups, channel cancellation, size/parse failures, successful reads, and one-way dialing do not increment it. Deadline failures remain at Debug; this counter makes them observable without enabling Debug logging. The existing OpenTelemetry AddMetrics integration exports this meter.

Using the Protocol

As a Client (Dialing)
// Connect to a remote peer
ISession session = await localPeer.DialAsync(remoteAddress);

// Send a request and receive a response
var request = new ExampleRequest
{
    Query = "search term",
    Limit = 10
};

var response = await session.DialAsync<RequestResponseProtocol<ExampleRequest, ExampleResponse>,
                                      ExampleRequest,
                                      ExampleResponse>(request);

Console.WriteLine($"Success: {response.Success}");
Console.WriteLine($"Results: {string.Join(", ", response.Results)}");
As a Server (Listening)

The server-side handling is automatic when you register the protocol with a handler function. The protocol will:

  1. Listen for incoming connections
  2. Deserialize the request message
  3. Call your handler function
  4. Serialize and send the response
  5. Close the connection

Protocol Implementation Details

RequestResponseProtocol<TRequest, TResponse>

The core protocol class provides:

  • Constructor Parameters:

    • protocolId: Unique identifier for the protocol (e.g., "/my-app/1.0.0")
    • handler: Async function to process requests and generate responses
    • loggerFactory: Optional logger factory for debugging
    • expectsResponse: Optional predicate for protocols that mix requests and one-way messages. Defaults to expecting a response.
  • Key Methods:

    • ListenAsync(): Handles incoming requests from remote peers
    • DialAsync(): Sends requests to remote peers and waits for responses

When expectsResponse returns false, DialAsync() completes after a successful write and returns an empty TResponse; this is not a remote acknowledgement. ListenAsync() still invokes the handler but does not send its response.

Handler cancellation and graceful admission shutdown

The cancellation-aware handler overload receives the application channel's lifetime token. Closing or resetting that channel cancels the token; a request-side FIN alone leaves the reply direction open. Before sending a response, the protocol checks that token again, including when a handler ignores cancellation and returns normally. Cancellation of that token propagates without an ordinary error log or a response acknowledging the operation.

This is also the contract when integrating Yamux's graceful GoAway behavior from PR #419: GoAway/OK stops admission of new streams while existing channels and their handlers continue. It must not be treated as cancellation of every handler. Actual stream termination, fatal connection shutdown, or transport loss still cancels affected channel tokens. RequestResponse keeps the channel token and cancellation propagation; it does not substitute a token for stream admission or suppress cancellation after a channel has closed.

RequestResponseExtensions

The extension class provides a convenient builder method:

public static IPeerFactoryBuilder AddRequestResponseProtocol<TRequest, TResponse>(
    this IPeerFactoryBuilder builder,
    string protocolId,
    Func<TRequest, ISessionContext, Task<TResponse>> handler,
    bool isExposed = true,
    Func<TRequest, bool>? expectsResponse = null)

Parameters:

  • builder: The peer factory builder to extend
  • protocolId: Unique protocol identifier
  • handler: Function to handle incoming requests
  • isExposed: Whether the protocol should be advertised to other peers
  • expectsResponse: Whether each request expects a wire response

Type Constraints

Both TRequest and TResponse must satisfy:

where TRequest : class, IMessage<TRequest>, new()
where TResponse : class, IMessage<TResponse>, new()
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on Nethermind.Libp2p.Protocols.RequestResponse:

Package Downloads
Nethermind.Libp2p

A libp2p implementation for .NET

Libp2p.Protocols.KadDht

A libp2p implementation for .NET

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.1 105 11/2/2026
1.1.0 1,676 10/20/2026
1.0.5 115 10/19/2026
1.0.4 121 10/15/2026
1.0.3 316 10/6/2026
1.0.2 118 10/3/2026
1.0.1 117 10/2/2026
1.0.0 126 10/1/2026
1.0.0-preview.51 6,479 11/11/2025
1.0.0-preview.50 180 11/7/2025