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
<PackageReference Include="Nethermind.Libp2p.Protocols.RequestResponse" Version="1.1.1" />
<PackageVersion Include="Nethermind.Libp2p.Protocols.RequestResponse" Version="1.1.1" />
<PackageReference Include="Nethermind.Libp2p.Protocols.RequestResponse" />
paket add Nethermind.Libp2p.Protocols.RequestResponse --version 1.1.1
#r "nuget: Nethermind.Libp2p.Protocols.RequestResponse, 1.1.1"
#:package Nethermind.Libp2p.Protocols.RequestResponse@1.1.1
#addin nuget:?package=Nethermind.Libp2p.Protocols.RequestResponse&version=1.1.1
#tool nuget:?package=Nethermind.Libp2p.Protocols.RequestResponse&version=1.1.1
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:
- Listen for incoming connections
- Deserialize the request message
- Call your handler function
- Serialize and send the response
- 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 responsesloggerFactory: Optional logger factory for debuggingexpectsResponse: Optional predicate for protocols that mix requests and one-way messages. Defaults to expecting a response.
Key Methods:
ListenAsync(): Handles incoming requests from remote peersDialAsync(): 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 extendprotocolId: Unique protocol identifierhandler: Function to handle incoming requestsisExposed: Whether the protocol should be advertised to other peersexpectsResponse: 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 | Versions 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. |
-
net10.0
- Google.Protobuf (>= 3.33.1)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.11)
- Nethermind.Libp2p.Core (>= 1.1.1)
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 |