From c92bade8151e4c99b97cae6f57f7e9b8fb08d61b Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Tue, 24 Sep 2019 17:19:22 -0700 Subject: [PATCH 1/4] Add "default protocols" that all hosts have by default --- libp2p/host/basic_host.py | 14 +++++++++++--- libp2p/host/defaults.py | 7 +++++++ libp2p/protocol_muxer/multiselect.py | 4 ++-- 3 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 libp2p/host/defaults.py diff --git a/libp2p/host/basic_host.py b/libp2p/host/basic_host.py index b26dd3c7..7b01d4bc 100644 --- a/libp2p/host/basic_host.py +++ b/libp2p/host/basic_host.py @@ -1,8 +1,9 @@ import logging -from typing import List, Sequence +from typing import TYPE_CHECKING, List, Sequence import multiaddr +from libp2p.host.defaults import DEFAULT_HOST_PROTOCOLS from libp2p.host.exceptions import StreamFailure from libp2p.network.network_interface import INetwork from libp2p.network.stream.net_stream_interface import INetStream @@ -17,6 +18,9 @@ from libp2p.typing import StreamHandlerFn, TProtocol from .host_interface import IHost +if TYPE_CHECKING: + from collections import OrderedDict + # Upon host creation, host takes in options, # including the list of addresses on which to listen. # Host then parses these options and delegates to its Network instance, @@ -38,12 +42,16 @@ class BasicHost(IHost): multiselect: Multiselect multiselect_client: MultiselectClient - def __init__(self, network: INetwork) -> None: + def __init__( + self, + network: INetwork, + default_protocols: "OrderedDict[TProtocol, StreamHandlerFn]" = DEFAULT_HOST_PROTOCOLS, + ) -> None: self._network = network self._network.set_stream_handler(self._swarm_stream_handler) self.peerstore = self._network.peerstore # Protocol muxing - self.multiselect = Multiselect() + self.multiselect = Multiselect(default_protocols) self.multiselect_client = MultiselectClient() def get_id(self) -> ID: diff --git a/libp2p/host/defaults.py b/libp2p/host/defaults.py new file mode 100644 index 00000000..ce9b6d64 --- /dev/null +++ b/libp2p/host/defaults.py @@ -0,0 +1,7 @@ +from collections import OrderedDict +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from libp2p.typing import TProtocol, StreamHandlerFn + +DEFAULT_HOST_PROTOCOLS: "OrderedDict[TProtocol, StreamHandlerFn]" = OrderedDict() diff --git a/libp2p/protocol_muxer/multiselect.py b/libp2p/protocol_muxer/multiselect.py index 88f7e37e..72279c65 100644 --- a/libp2p/protocol_muxer/multiselect.py +++ b/libp2p/protocol_muxer/multiselect.py @@ -19,8 +19,8 @@ class Multiselect(IMultiselectMuxer): handlers: Dict[TProtocol, StreamHandlerFn] - def __init__(self) -> None: - self.handlers = {} + def __init__(self, default_handlers: Dict[TProtocol, StreamHandlerFn] = {}) -> None: + self.handlers = default_handlers def add_handler(self, protocol: TProtocol, handler: StreamHandlerFn) -> None: """ From d0c8b7d8af02490c7eab293bed27ebb1da397dbc Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Tue, 24 Sep 2019 19:12:04 -0700 Subject: [PATCH 2/4] Avoid sharing default dictionary argument across all instances of class --- libp2p/protocol_muxer/multiselect.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libp2p/protocol_muxer/multiselect.py b/libp2p/protocol_muxer/multiselect.py index 72279c65..06e268af 100644 --- a/libp2p/protocol_muxer/multiselect.py +++ b/libp2p/protocol_muxer/multiselect.py @@ -19,7 +19,11 @@ class Multiselect(IMultiselectMuxer): handlers: Dict[TProtocol, StreamHandlerFn] - def __init__(self, default_handlers: Dict[TProtocol, StreamHandlerFn] = {}) -> None: + def __init__( + self, default_handlers: Dict[TProtocol, StreamHandlerFn] = None + ) -> None: + if not default_handlers: + default_handlers = {} self.handlers = default_handlers def add_handler(self, protocol: TProtocol, handler: StreamHandlerFn) -> None: From 15cabb1c339e8a00b2cfb4d329c8753446838bfa Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Thu, 24 Oct 2019 17:27:15 +0900 Subject: [PATCH 3/4] Copy default data to avoid undesirable mutations --- libp2p/host/basic_host.py | 5 +++-- libp2p/host/defaults.py | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/libp2p/host/basic_host.py b/libp2p/host/basic_host.py index 7b01d4bc..66e36e09 100644 --- a/libp2p/host/basic_host.py +++ b/libp2p/host/basic_host.py @@ -3,7 +3,7 @@ from typing import TYPE_CHECKING, List, Sequence import multiaddr -from libp2p.host.defaults import DEFAULT_HOST_PROTOCOLS +from libp2p.host.defaults import get_default_protocols from libp2p.host.exceptions import StreamFailure from libp2p.network.network_interface import INetwork from libp2p.network.stream.net_stream_interface import INetStream @@ -45,12 +45,13 @@ class BasicHost(IHost): def __init__( self, network: INetwork, - default_protocols: "OrderedDict[TProtocol, StreamHandlerFn]" = DEFAULT_HOST_PROTOCOLS, + default_protocols: "OrderedDict[TProtocol, StreamHandlerFn]" = None, ) -> None: self._network = network self._network.set_stream_handler(self._swarm_stream_handler) self.peerstore = self._network.peerstore # Protocol muxing + default_protocols = default_protocols or get_default_protocols() self.multiselect = Multiselect(default_protocols) self.multiselect_client = MultiselectClient() diff --git a/libp2p/host/defaults.py b/libp2p/host/defaults.py index ce9b6d64..ab5952fc 100644 --- a/libp2p/host/defaults.py +++ b/libp2p/host/defaults.py @@ -5,3 +5,7 @@ if TYPE_CHECKING: from libp2p.typing import TProtocol, StreamHandlerFn DEFAULT_HOST_PROTOCOLS: "OrderedDict[TProtocol, StreamHandlerFn]" = OrderedDict() + + +def get_default_protocols() -> "OrderedDict[TProtocol, StreamHandlerFn]": + return DEFAULT_HOST_PROTOCOLS.copy() From 1bf0c31d1f579240fd7c3832e9bbae1dafcbc86a Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Thu, 24 Oct 2019 17:36:34 +0900 Subject: [PATCH 4/4] add basic test for default protocols --- tests/host/test_basic_host.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tests/host/test_basic_host.py diff --git a/tests/host/test_basic_host.py b/tests/host/test_basic_host.py new file mode 100644 index 00000000..5718b6de --- /dev/null +++ b/tests/host/test_basic_host.py @@ -0,0 +1,14 @@ +from libp2p import initialize_default_swarm +from libp2p.crypto.rsa import create_new_key_pair +from libp2p.host.basic_host import BasicHost +from libp2p.host.defaults import get_default_protocols + + +def test_default_protocols(): + key_pair = create_new_key_pair() + swarm = initialize_default_swarm(key_pair) + host = BasicHost(swarm) + + mux = host.get_mux() + handlers = mux.handlers + assert handlers == get_default_protocols()