2121from libp2p .protocol_muxer .exceptions import (
2222 MultiselectError ,
2323)
24+ from libp2p .protocol_muxer .generic_selector import (
25+ GenericMultistreamSelector ,
26+ )
2427from libp2p .protocol_muxer .multiselect import (
2528 DEFAULT_NEGOTIATE_TIMEOUT ,
2629 Multiselect ,
2730)
2831from libp2p .protocol_muxer .multiselect_client import (
2932 MultiselectClient ,
3033)
31- from libp2p .protocol_muxer .multiselect_communicator import (
32- MultiselectCommunicator ,
33- )
3434from libp2p .stream_muxer .yamux .yamux import (
3535 PROTOCOL_ID ,
3636 Yamux ,
@@ -46,24 +46,31 @@ class MuxerMultistream:
4646 go implementation: github.com/libp2p/go-stream-muxer-multistream/multistream.go
4747 """
4848
49- # NOTE: Can be changed to `typing.OrderedDict` since Python 3.7.2.
50- transports : "OrderedDict[TProtocol, TMuxerClass]"
51- multiselect : Multiselect
52- multiselect_client : MultiselectClient
49+ _selector : "GenericMultistreamSelector[TMuxerClass]"
5350 negotiate_timeout : int
5451
5552 def __init__ (
5653 self ,
5754 muxer_transports_by_protocol : TMuxerOptions ,
5855 negotiate_timeout : int = DEFAULT_NEGOTIATE_TIMEOUT ,
5956 ) -> None :
60- self .transports = OrderedDict ()
61- self .multiselect = Multiselect ()
62- self .multistream_client = MultiselectClient ()
57+ self ._selector = GenericMultistreamSelector ()
6358 self .negotiate_timeout = negotiate_timeout
6459 for protocol , transport in muxer_transports_by_protocol .items ():
6560 self .add_transport (protocol , transport )
6661
62+ @property
63+ def transports (self ) -> "OrderedDict[TProtocol, TMuxerClass]" :
64+ return self ._selector .handlers
65+
66+ @property
67+ def multiselect (self ) -> Multiselect :
68+ return self ._selector .multiselect
69+
70+ @property
71+ def multiselect_client (self ) -> MultiselectClient :
72+ return self ._selector .multiselect_client
73+
6774 def add_transport (self , protocol : TProtocol , transport : TMuxerClass ) -> None :
6875 """
6976 Add a protocol and its corresponding transport to multistream-
@@ -73,10 +80,7 @@ def add_transport(self, protocol: TProtocol, transport: TMuxerClass) -> None:
7380 :param protocol: the protocol name, which is negotiated in multiselect.
7481 :param transport: the corresponding transportation to the ``protocol``.
7582 """
76- # If protocol is already added before, remove it and add it again.
77- self .transports .pop (protocol , None )
78- self .transports [protocol ] = transport
79- self .multiselect .add_handler (protocol , None )
83+ self ._selector .add_handler (protocol , transport )
8084
8185 async def select_transport (self , conn : IRawConnection ) -> TMuxerClass :
8286 """
@@ -86,48 +90,26 @@ async def select_transport(self, conn: IRawConnection) -> TMuxerClass:
8690 :param conn: conn to choose a transport over
8791 :return: selected muxer transport
8892 """
89- protocol : TProtocol | None
90- communicator = MultiselectCommunicator (conn )
91- if conn .is_initiator :
92- protocol = await self .multiselect_client .select_one_of (
93- tuple (self .transports .keys ()), communicator , self .negotiate_timeout
94- )
95- else :
96- protocol , _ = await self .multiselect .negotiate (
97- communicator , self .negotiate_timeout
93+ try :
94+ _ , transport = await self ._selector .select (
95+ conn , conn .is_initiator , self .negotiate_timeout
9896 )
99- if protocol is None :
97+ except MultiselectError :
10098 raise MultiselectError (
10199 "Fail to negotiate a stream muxer protocol: no protocol selected"
102100 )
103- return self . transports [ protocol ]
101+ return transport
104102
105103 async def new_conn (self , conn : ISecureConn , peer_id : ID ) -> IMuxedConn :
106- communicator = MultiselectCommunicator (conn )
107104 logger .debug (
108105 "MuxerMultistream: muxer negotiation peer=%s initiator=%s" ,
109106 peer_id ,
110107 conn .is_initiator ,
111108 )
112-
113- # Use appropriate multiselect based on role:
114- # - Initiator (client/dialer) uses multiselect_client to select a protocol
115- # - Non-initiator (server/listener) uses multiselect to negotiate with client
116- if conn .is_initiator :
117- protocol = await self .multistream_client .select_one_of (
118- tuple (self .transports .keys ()), communicator , self .negotiate_timeout
119- )
120- else :
121- negotiated_protocol , _ = await self .multiselect .negotiate (
122- communicator , self .negotiate_timeout
123- )
124- if negotiated_protocol is None :
125- raise MultiselectError (
126- "Fail to negotiate a stream muxer protocol: no protocol selected"
127- )
128- protocol = negotiated_protocol
109+ protocol , transport_class = await self ._selector .select (
110+ conn , conn .is_initiator , self .negotiate_timeout
111+ )
129112 logger .debug ("MuxerMultistream new_conn: negotiated protocol %s" , protocol )
130- transport_class = self .transports [protocol ]
131113 if protocol == PROTOCOL_ID :
132114 async with trio .open_nursery ():
133115
0 commit comments