Skip to content

Commit 2535305

Browse files
authored
Merge pull request #838 from unniznd/fix_multiselect_negotiate_type
fix: Added multiselect type consistency in negotiate method
2 parents 93fe070 + 9df542f commit 2535305

File tree

5 files changed

+49
-2
lines changed

5 files changed

+49
-2
lines changed

libp2p/host/basic_host.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,11 @@ async def _swarm_stream_handler(self, net_stream: INetStream) -> None:
297297
protocol, handler = await self.multiselect.negotiate(
298298
MultiselectCommunicator(net_stream), self.negotiate_timeout
299299
)
300+
if protocol is None:
301+
await net_stream.reset()
302+
raise StreamFailure(
303+
"Failed to negotiate protocol: no protocol selected"
304+
)
300305
except MultiselectError as error:
301306
peer_id = net_stream.muxed_conn.peer_id
302307
logger.debug(

libp2p/security/security_multistream.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ async def select_transport(
118118
# Select protocol if non-initiator
119119
protocol, _ = await self.multiselect.negotiate(communicator)
120120
if protocol is None:
121-
raise MultiselectError("fail to negotiate a security protocol")
121+
raise MultiselectError(
122+
"Failed to negotiate a security protocol: no protocol selected"
123+
)
122124
# Return transport from protocol
123125
return self.transports[protocol]

libp2p/stream_muxer/muxer_multistream.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ async def select_transport(self, conn: IRawConnection) -> TMuxerClass:
8585
else:
8686
protocol, _ = await self.multiselect.negotiate(communicator)
8787
if protocol is None:
88-
raise MultiselectError("fail to negotiate a stream muxer protocol")
88+
raise MultiselectError(
89+
"Fail to negotiate a stream muxer protocol: no protocol selected"
90+
)
8991
return self.transports[protocol]
9092

9193
async def new_conn(self, conn: ISecureConn, peer_id: ID) -> IMuxedConn:

newsfragments/837.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added multiselect type consistency in negotiate method. Updates all the usages of the method.

tests/core/host/test_basic_host.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
from unittest.mock import (
2+
AsyncMock,
3+
MagicMock,
4+
)
5+
6+
import pytest
7+
18
from libp2p import (
29
new_swarm,
310
)
@@ -10,6 +17,9 @@
1017
from libp2p.host.defaults import (
1118
get_default_protocols,
1219
)
20+
from libp2p.host.exceptions import (
21+
StreamFailure,
22+
)
1323

1424

1525
def test_default_protocols():
@@ -22,3 +32,30 @@ def test_default_protocols():
2232
# NOTE: comparing keys for equality as handlers may be closures that do not compare
2333
# in the way this test is concerned with
2434
assert handlers.keys() == get_default_protocols(host).keys()
35+
36+
37+
@pytest.mark.trio
38+
async def test_swarm_stream_handler_no_protocol_selected(monkeypatch):
39+
key_pair = create_new_key_pair()
40+
swarm = new_swarm(key_pair)
41+
host = BasicHost(swarm)
42+
43+
# Create a mock net_stream
44+
net_stream = MagicMock()
45+
net_stream.reset = AsyncMock()
46+
net_stream.muxed_conn.peer_id = "peer-test"
47+
48+
# Monkeypatch negotiate to simulate "no protocol selected"
49+
async def fake_negotiate(comm, timeout):
50+
return None, None
51+
52+
monkeypatch.setattr(host.multiselect, "negotiate", fake_negotiate)
53+
54+
# Now run the handler and expect StreamFailure
55+
with pytest.raises(
56+
StreamFailure, match="Failed to negotiate protocol: no protocol selected"
57+
):
58+
await host._swarm_stream_handler(net_stream)
59+
60+
# Ensure reset was called since negotiation failed
61+
net_stream.reset.assert_awaited()

0 commit comments

Comments
 (0)