Exemplo n.º 1
0
    async def stream_reader_writer_to_connection(
        self,
        swrt: Tuple[asyncio.StreamReader, asyncio.StreamWriter, OnConnectFunc],
        server_port: int,
    ) -> Connection:
        """
        Maps a tuple of (StreamReader, StreamWriter, on_connect) to a Connection object,
        which also stores the type of connection (str). It is also added to the global list.
        """
        sr, sw, on_connect = swrt
        con = Connection(self._local_type, None, sr, sw, server_port, on_connect)

        self.log.info(f"Connection with {con.get_peername()} established")
        return con
Exemplo n.º 2
0
    async def perform_handshake(
            self, connection: Connection) -> AsyncGenerator[Connection, None]:
        """
        Performs handshake with this new connection, and yields the connection. If the handshake
        is unsuccessful, or we already have a connection with this peer, the connection is closed,
        and nothing is yielded.
        """
        # Send handshake message
        outbound_handshake = Message(
            "handshake",
            Handshake(
                config["network_id"],
                protocol_version,
                self._node_id,
                uint16(self._port),
                self._local_type,
            ),
        )

        try:
            await connection.send(outbound_handshake)

            # Read handshake message
            full_message = await connection.read_one_message()
            inbound_handshake = Handshake(**full_message.data)
            if (full_message.function != "handshake" or not inbound_handshake
                    or not inbound_handshake.node_type):
                raise InvalidHandshake("Invalid handshake")

            if inbound_handshake.node_id == self._node_id:
                raise InvalidHandshake(
                    f"Should not connect to ourselves, aborting handshake.")

            # Makes sure that we only start one connection with each peer
            connection.node_id = inbound_handshake.node_id
            connection.peer_server_port = int(inbound_handshake.server_port)
            connection.connection_type = inbound_handshake.node_type
            if not self.global_connections.add(connection):
                raise InvalidHandshake(f"Duplicate connection to {connection}")

            # Send Ack message
            await connection.send(Message("handshake_ack", HandshakeAck()))

            # Read Ack message
            full_message = await connection.read_one_message()
            if full_message.function != "handshake_ack":
                raise InvalidAck("Invalid ack")

            if inbound_handshake.version != protocol_version:
                raise IncompatibleProtocolVersion(
                    f"Our node version {protocol_version} is not compatible with peer\
                        {connection} version {inbound_handshake.version}")

            log.info((
                f"Handshake with {NodeType(connection.connection_type).name} {connection.get_peername()} "
                f"{connection.node_id}"
                f" established"))
            # Only yield a connection if the handshake is succesful and the connection is not a duplicate.
            yield connection
        except (
                IncompatibleProtocolVersion,
                InvalidAck,
                InvalidHandshake,
                asyncio.IncompleteReadError,
                ConnectionResetError,
                Exception,
        ) as e:
            log.warning(
                f"{e}, handshake not completed. Connection not created.")
            # Make sure to close the connection even if it's not in global connections
            connection.close()
            # Remove the conenction from global connections
            self.global_connections.close(connection)
Exemplo n.º 3
0
    async def perform_handshake(
            self, connection: Connection) -> AsyncGenerator[Connection, None]:
        """
        Performs handshake with this new connection, and yields the connection. If the handshake
        is unsuccessful, or we already have a connection with this peer, the connection is closed,
        and nothing is yielded.
        """
        # Send handshake message
        outbound_handshake = Message(
            "handshake",
            Handshake(
                self._network_id,
                protocol_version,
                self._node_id,
                uint16(self._port),
                self._local_type,
            ),
        )

        try:
            await connection.send(outbound_handshake)

            # Read handshake message
            full_message = await connection.read_one_message()
            inbound_handshake = Handshake(**full_message.data)
            if (full_message.function != "handshake" or not inbound_handshake
                    or not inbound_handshake.node_type):
                raise ProtocolError(Err.INVALID_HANDSHAKE)

            if inbound_handshake.node_id == self._node_id:
                raise ProtocolError(Err.SELF_CONNECTION)

            # Makes sure that we only start one connection with each peer
            connection.node_id = inbound_handshake.node_id
            connection.peer_server_port = int(inbound_handshake.server_port)
            connection.connection_type = inbound_handshake.node_type
            if not self.global_connections.add(connection):
                raise ProtocolError(Err.DUPLICATE_CONNECTION, [False])

            # Send Ack message
            await connection.send(Message("handshake_ack", HandshakeAck()))

            # Read Ack message
            full_message = await connection.read_one_message()
            if full_message.function != "handshake_ack":
                raise ProtocolError(Err.INVALID_ACK)

            if inbound_handshake.version != protocol_version:
                raise ProtocolError(
                    Err.INCOMPATIBLE_PROTOCOL_VERSION,
                    [protocol_version, inbound_handshake.version],
                )

            self.log.info((
                f"Handshake with {NodeType(connection.connection_type).name} {connection.get_peername()} "
                f"{connection.node_id}"
                f" established"))
            # Only yield a connection if the handshake is succesful and the connection is not a duplicate.
            yield connection
        except (
                ProtocolError,
                asyncio.IncompleteReadError,
                OSError,
                Exception,
        ) as e:
            self.log.warning(
                f"{e}, handshake not completed. Connection not created.")
            # Make sure to close the connection even if it's not in global connections
            connection.close()
            # Remove the conenction from global connections
            self.global_connections.close(connection)