From 1e5357a1e16f07b9b8f4806d7bda17da00c5f424 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Fri, 2 Aug 2019 16:04:46 -0700 Subject: [PATCH] Update the `ISecureConn` interface following the reference and simplify accordingly --- libp2p/__init__.py | 6 ++-- libp2p/security/insecure/transport.py | 36 ++---------------------- libp2p/security/secure_conn_interface.py | 28 +++++++++++------- libp2p/security/security_multistream.py | 5 +++- libp2p/security/simple/transport.py | 31 ++------------------ libp2p/stream_muxer/mplex/mplex.py | 24 +++++++--------- libp2p/transport/upgrader.py | 13 ++++----- 7 files changed, 45 insertions(+), 98 deletions(-) diff --git a/libp2p/__init__.py b/libp2p/__init__.py index 391897f3..11fa2a9f 100644 --- a/libp2p/__init__.py +++ b/libp2p/__init__.py @@ -92,8 +92,10 @@ def initialize_default_swarm( # TODO TransportUpgrader is not doing anything really # TODO parse muxer and sec to pass into TransportUpgrader muxer = muxer_opt or ["mplex/6.7.0"] - sec = sec_opt or {TProtocol("insecure/1.0.0"): InsecureTransport("insecure")} - upgrader = TransportUpgrader(sec, muxer) + security_transports_by_protocol = sec_opt or { + TProtocol("insecure/1.0.0"): InsecureTransport() + } + upgrader = TransportUpgrader(security_transports_by_protocol, muxer) peerstore = peerstore_opt or PeerStore() # TODO: Initialize discovery if not presented diff --git a/libp2p/security/insecure/transport.py b/libp2p/security/insecure/transport.py index 7e1b77e5..4ec378b8 100644 --- a/libp2p/security/insecure/transport.py +++ b/libp2p/security/insecure/transport.py @@ -1,10 +1,7 @@ -from typing import cast - from libp2p.network.connection.raw_connection_interface import IRawConnection from libp2p.peer.id import ID from libp2p.security.secure_conn_interface import ISecureConn from libp2p.security.secure_transport_interface import ISecureTransport -from libp2p.security.typing import TSecurityDetails class InsecureTransport(ISecureTransport): @@ -13,19 +10,13 @@ class InsecureTransport(ISecureTransport): i.e. the upgraded transport does not add any additional security. """ - transport_id: str - - def __init__(self, transport_id: str) -> None: - self.transport_id = transport_id - async def secure_inbound(self, conn: IRawConnection) -> ISecureConn: """ Secure the connection, either locally or by communicating with opposing node via conn, for an inbound connection (i.e. we are not the initiator) :return: secure connection object (that implements secure_conn_interface) """ - insecure_conn = InsecureConn(conn, self.transport_id) - return insecure_conn + return conn async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureConn: """ @@ -33,27 +24,4 @@ class InsecureTransport(ISecureTransport): for an inbound connection (i.e. we are the initiator) :return: secure connection object (that implements secure_conn_interface) """ - insecure_conn = InsecureConn(conn, self.transport_id) - return insecure_conn - - -class InsecureConn(ISecureConn): - conn: IRawConnection - details: TSecurityDetails - - def __init__(self, conn: IRawConnection, conn_id: str) -> None: - self.conn = conn - self.details = cast(TSecurityDetails, {}) - self.details["id"] = conn_id - - def get_conn(self) -> IRawConnection: - """ - :return: connection object that has been made secure - """ - return self.conn - - def get_security_details(self) -> TSecurityDetails: - """ - :return: map containing details about the connections security - """ - return self.details + return conn diff --git a/libp2p/security/secure_conn_interface.py b/libp2p/security/secure_conn_interface.py index 67d8706e..7b88e802 100644 --- a/libp2p/security/secure_conn_interface.py +++ b/libp2p/security/secure_conn_interface.py @@ -1,7 +1,7 @@ from abc import ABC, abstractmethod +from libp2p.peer.id import ID from libp2p.network.connection.raw_connection_interface import IRawConnection -from libp2p.security.typing import TSecurityDetails """ @@ -12,15 +12,23 @@ Relevant go repo: https://github.com/libp2p/go-conn-security/blob/master/interfa """ -class ISecureConn(ABC): +class AbstractSecureConn(ABC): @abstractmethod - def get_conn(self) -> IRawConnection: - """ - :return: the underlying raw connection - """ + def get_local_peer(self) -> ID: + pass @abstractmethod - def get_security_details(self) -> TSecurityDetails: - """ - :return: map containing details about the connections security - """ + def get_local_private_key(self) -> bytes: + pass + + @abstractmethod + def get_remote_peer(self) -> ID: + pass + + @abstractmethod + def get_remote_public_key(self) -> bytes: + pass + + +class ISecureConn(AbstractSecureConn, IRawConnection): + pass diff --git a/libp2p/security/security_multistream.py b/libp2p/security/security_multistream.py index 9f25fab4..43c5dbf3 100644 --- a/libp2p/security/security_multistream.py +++ b/libp2p/security/security_multistream.py @@ -23,11 +23,14 @@ class SecurityMultistream(ABC): multiselect: Multiselect multiselect_client: MultiselectClient - def __init__(self) -> None: + def __init__(self, secure_transports_by_protocol) -> None: self.transports = {} self.multiselect = Multiselect() self.multiselect_client = MultiselectClient() + for protocol, transport in secure_transports_by_protocol.items(): + self.add_transport(protocol, transport) + def add_transport(self, protocol: TProtocol, transport: ISecureTransport) -> None: self.transports[protocol] = transport diff --git a/libp2p/security/simple/transport.py b/libp2p/security/simple/transport.py index 8860ab57..87883998 100644 --- a/libp2p/security/simple/transport.py +++ b/libp2p/security/simple/transport.py @@ -1,11 +1,9 @@ import asyncio -from typing import cast from libp2p.network.connection.raw_connection_interface import IRawConnection from libp2p.peer.id import ID from libp2p.security.secure_conn_interface import ISecureConn from libp2p.security.secure_transport_interface import ISecureTransport -from libp2p.security.typing import TSecurityDetails class SimpleSecurityTransport(ISecureTransport): @@ -28,8 +26,7 @@ class SimpleSecurityTransport(ISecureTransport): "Key phrase differed between nodes. Expected " + self.key_phrase ) - secure_conn = SimpleSecureConn(conn, self.key_phrase) - return secure_conn + return conn async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureConn: """ @@ -49,28 +46,4 @@ class SimpleSecurityTransport(ISecureTransport): "Key phrase differed between nodes. Expected " + self.key_phrase ) - secure_conn = SimpleSecureConn(conn, self.key_phrase) - return secure_conn - - -class SimpleSecureConn(ISecureConn): - conn: IRawConnection - key_phrase: str - details: TSecurityDetails - - def __init__(self, conn: IRawConnection, key_phrase: str) -> None: - self.conn = conn - self.details = cast(TSecurityDetails, {}) - self.details["key_phrase"] = key_phrase - - def get_conn(self) -> IRawConnection: - """ - :return: connection object that has been made secure - """ - return self.conn - - def get_security_details(self) -> TSecurityDetails: - """ - :return: map containing details about the connections security - """ - return self.details + return conn diff --git a/libp2p/stream_muxer/mplex/mplex.py b/libp2p/stream_muxer/mplex/mplex.py index 16d36134..60db1d2d 100644 --- a/libp2p/stream_muxer/mplex/mplex.py +++ b/libp2p/stream_muxer/mplex/mplex.py @@ -1,13 +1,12 @@ import asyncio from typing import Dict, Tuple -from multiaddr import Multiaddr - from libp2p.network.connection.raw_connection_interface import IRawConnection from libp2p.network.typing import GenericProtocolHandlerFn from libp2p.peer.id import ID from libp2p.security.secure_conn_interface import ISecureConn from libp2p.stream_muxer.abc import IMuxedConn, IMuxedStream +from multiaddr import Multiaddr from .constants import HeaderTags from .mplex_stream import MplexStream @@ -39,11 +38,8 @@ class Mplex(IMuxedConn): for new muxed streams :param peer_id: peer_id of peer the connection is to """ - super().__init__(secured_conn, generic_protocol_handler, peer_id) - - self.secured_conn = secured_conn - self.raw_conn = secured_conn.get_conn() - self.initiator = self.raw_conn.initiator + self.conn = secured_conn + self.initiator = self.conn.initiator # Store generic protocol handler self.generic_protocol_handler = generic_protocol_handler @@ -63,7 +59,7 @@ class Mplex(IMuxedConn): """ close the stream muxer and underlying raw connection """ - self.raw_conn.close() + self.conn.close() def is_closed(self) -> bool: """ @@ -99,7 +95,7 @@ class Mplex(IMuxedConn): :param multi_addr: multi_addr that stream connects to :return: a new stream """ - stream_id = self.raw_conn.next_stream_id() + stream_id = self.conn.next_stream_id() stream = MplexStream(stream_id, multi_addr, self) self.buffers[stream_id] = asyncio.Queue() await self.send_message(HeaderTags.NewStream, None, stream_id) @@ -139,8 +135,8 @@ class Mplex(IMuxedConn): :param _bytes: byte array to write :return: length written """ - self.raw_conn.writer.write(_bytes) - await self.raw_conn.writer.drain() + self.conn.writer.write(_bytes) + await self.conn.writer.drain() return len(_bytes) async def handle_incoming(self) -> None: @@ -177,10 +173,10 @@ class Mplex(IMuxedConn): # loop in handle_incoming timeout = 0.1 try: - header = await decode_uvarint_from_stream(self.raw_conn.reader, timeout) - length = await decode_uvarint_from_stream(self.raw_conn.reader, timeout) + header = await decode_uvarint_from_stream(self.conn.reader, timeout) + length = await decode_uvarint_from_stream(self.conn.reader, timeout) message = await asyncio.wait_for( - self.raw_conn.reader.read(length), timeout=timeout + self.conn.reader.read(length), timeout=timeout ) except asyncio.TimeoutError: return None, None, None diff --git a/libp2p/transport/upgrader.py b/libp2p/transport/upgrader.py index 2aac45ef..f727767c 100644 --- a/libp2p/transport/upgrader.py +++ b/libp2p/transport/upgrader.py @@ -18,14 +18,11 @@ class TransportUpgrader: muxer: Sequence[str] def __init__( - self, secOpt: Mapping[TProtocol, ISecureTransport], muxerOpt: Sequence[str] - ) -> None: - # Store security option - self.security_multistream = SecurityMultistream() - for key in secOpt: - self.security_multistream.add_transport(key, secOpt[key]) - - # Store muxer option + self, + secure_transports_by_protocol: Mapping[TProtocol, ISecureTransport], + muxerOpt: Sequence[str], + ): + self.security_multistream = SecurityMultistream(secure_transports_by_protocol) self.muxer = muxerOpt def upgrade_listener(self, transport: ITransport, listeners: IListener) -> None: