Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
196d625
update strom dependency which fixes disable remote fingerprint verifi…
timwu20 Oct 7, 2025
b875bbd
change str0m to 0.11.1
timwu20 Oct 20, 2025
925caa9
fix lint
timwu20 Oct 21, 2025
4200246
set and listen on ChannelBufferedAmountLow after stream closure
timwu20 Oct 20, 2025
85fae21
fix: multistream-select negotiation for outbound webrtc substreams
haikoschol Oct 27, 2025
2ec539b
close data channel immediately when substream is closed
haikoschol Nov 12, 2025
4e4a2d3
remove setting of buffered amount low threshold in str0m
haikoschol Nov 12, 2025
7947bf6
remove special case of receiving None instead of a SubstreamEvent
haikoschol Nov 12, 2025
3765d52
move handling of trailing newline to webrtc_listener_negotiate()
haikoschol Nov 12, 2025
fdedc4f
cover all negotiation responses included in tests
haikoschol Nov 13, 2025
1cd945b
Merge branch 'master' into haiko-webrtc-outbound-multistream-nego-fix
haikoschol Nov 13, 2025
6dcb15d
address review feedback
haikoschol Nov 13, 2025
9621e3c
extract loop to drain_trailing_protocols()
haikoschol Nov 13, 2025
daa8f71
fmt
haikoschol Nov 19, 2025
afd44c8
Merge branch 'master' into haiko-webrtc-outbound-multistream-nego-fix
haikoschol Nov 19, 2025
99f6547
consider truncated multistream messages invalid data
haikoschol Nov 19, 2025
c9a0140
Merge branch 'master' into haiko-webrtc-outbound-multistream-nego-fix
haikoschol Nov 25, 2025
90f0c86
Apply suggestions from code review
haikoschol Nov 26, 2025
c0a44c0
avoid Message::Protocols in webrtc_listener_negotiate()
haikoschol Nov 26, 2025
c27930a
remove handling of Event::ChannelBufferedAmountLow
haikoschol Dec 2, 2025
4ed539e
Merge branch 'master' into haiko-webrtc-outbound-multistream-nego-fix
haikoschol Dec 2, 2025
12801fd
Merge branch 'master' into haiko-webrtc-outbound-multistream-nego-fix
haikoschol Dec 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 38 additions & 12 deletions src/multistream_select/dialer_select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@

use crate::{
codec::unsigned_varint::UnsignedVarint,
error::{self, Error, ParseError},
error::{self, Error, ParseError, SubstreamError},
multistream_select::{
protocol::{
webrtc_encode_multistream_message, HeaderLine, Message, MessageIO, Protocol,
ProtocolError,
ProtocolError, PROTO_MULTISTREAM_1_0
},
Negotiated, NegotiationError, Version,
},
Expand All @@ -41,7 +41,6 @@ use std::{
pin::Pin,
task::{Context, Poll},
};
use crate::error::SubstreamError;

const LOG_TARGET: &str = "litep2p::multistream-select";

Expand Down Expand Up @@ -358,20 +357,32 @@ impl WebRtcDialerState {
&mut self,
payload: Vec<u8>,
) -> Result<HandshakeResult, crate::error::NegotiationError> {
let header = Protocol::try_from(&b"/multistream/1.0.0"[..])
.expect("valid multitstream-select header");

// All multistream-select messages are length-prefixed. Since this code path is not using
// multistream_select::protocol::MessageIO, we need to decode and remove the length here.
let mut remaining: &[u8] = &payload;
let (len, tail) = unsigned_varint::decode::usize(remaining).
map_err(|_| error::NegotiationError::ParseError(ParseError::InvalidData))?;
map_err(|error| {
tracing::debug!(
target: LOG_TARGET,
?error,
message = ?payload,
"Failed to decode length-prefix in multistream message");
error::NegotiationError::ParseError(ParseError::InvalidData)
})?;

let payload = tail[..len].to_vec();

let mut protocols = match Message::decode(payload.into()) {
let message = Message::decode(payload.into());

tracing::trace!(
target: LOG_TARGET,
?message,
"Decoded message while registering response",
);

let mut protocols = match message {
Ok(Message::Header(HeaderLine::V1)) => {
vec![header.clone()]
vec![PROTO_MULTISTREAM_1_0]
}
Ok(Message::Protocol(protocol)) => vec![protocol],
Ok(Message::Protocols(protocols)) => protocols,
Expand All @@ -396,7 +407,14 @@ impl WebRtcDialerState {
}

let (len, tail) = unsigned_varint::decode::usize(remaining).
map_err(|_| error::NegotiationError::ParseError(ParseError::InvalidData))?;
map_err(|error| {
tracing::debug!(
target: LOG_TARGET,
?error,
message = ?remaining,
"Failed to decode length-prefix in multistream message");
error::NegotiationError::ParseError(ParseError::InvalidData)
})?;

if len > tail.len() {
break;
Expand All @@ -406,7 +424,15 @@ impl WebRtcDialerState {

match Message::decode(payload.into()) {
Ok(Message::Protocol(protocol)) => protocols.push(protocol),
Err(_) => return Err(error::NegotiationError::ParseError(ParseError::InvalidData)),
Err(error) => {
tracing::debug!(
target: LOG_TARGET,
?error,
message = ?tail[..len],
"Failed to decode multistream message",
);
return Err(error::NegotiationError::ParseError(ParseError::InvalidData))
},
_ => return Err(error::NegotiationError::StateMismatch),
}

Expand All @@ -419,7 +445,7 @@ impl WebRtcDialerState {
(HandshakeState::WaitingResponse, None) =>
return Err(crate::error::NegotiationError::StateMismatch),
(HandshakeState::WaitingResponse, Some(protocol)) => {
if protocol == header {
if protocol == PROTO_MULTISTREAM_1_0 {
self.state = HandshakeState::WaitingProtocol;
} else {
return Err(crate::error::NegotiationError::MultistreamSelectError(
Expand Down
2 changes: 2 additions & 0 deletions src/multistream_select/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ pub const MSG_MULTISTREAM_1_0: &[u8] = b"/multistream/1.0.0\n";
const MSG_PROTOCOL_NA: &[u8] = b"na\n";
/// The encoded form of a multistream-select 'ls' message.
const MSG_LS: &[u8] = b"ls\n";
/// A Protocol instance for the `/multistream/1.0.0` header line.
pub const PROTO_MULTISTREAM_1_0: Protocol = Protocol(Bytes::from_static(MSG_MULTISTREAM_1_0));
/// Logging target.
const LOG_TARGET: &str = "litep2p::multistream-select";

Expand Down