3.0.ipv8.messaging.anonymization.community ========================================== .. py:module:: 3.0.ipv8.messaging.anonymization.community .. autoapi-nested-parse:: The tunnel community. Author(s): Egbert Bouman Classes ------- .. autoapisummary:: 3.0.ipv8.messaging.anonymization.community.TunnelSettings 3.0.ipv8.messaging.anonymization.community.TunnelCommunity Functions --------- .. autoapisummary:: 3.0.ipv8.messaging.anonymization.community.unpack_cell Module Contents --------------- .. py:function:: unpack_cell(payload_cls: type[3.0.ipv8.messaging.serialization.Serializable]) -> Callable[Ellipsis, Callable[[TunnelCommunity, 3.0.ipv8.types.Address, bytes, int | None], None]] This function wrapper will unpack the normal payload for you, and handle a singular circuit_id parameter at the end of the parameter list You can now write your non-authenticated and signed functions as follows: :: @unpack_cell(DataPayload) def on_message(source_address, payload): ''' :type source_address: str :type payload: DataPayload ''' pass. .. py:class:: TunnelSettings Bases: :py:obj:`3.0.ipv8.community.CommunitySettings` Settings to forward to the TunnelCommunity. .. py:attribute:: min_circuits :value: 1 .. py:attribute:: max_circuits :value: 8 .. py:attribute:: max_joined_circuits :value: 100 .. py:attribute:: max_time .. py:attribute:: max_time_ip .. py:attribute:: max_time_inactive :value: 20 .. py:attribute:: max_traffic .. py:attribute:: circuit_timeout :value: 60 .. py:attribute:: unstable_timeout :value: 60 .. py:attribute:: next_hop_timeout :value: 10 .. py:attribute:: swarm_lookup_interval :value: 30 .. py:attribute:: swarm_connection_limit :value: 15 .. py:attribute:: remove_tunnel_delay :value: 5 .. py:attribute:: _peer_flags :type: set[int] .. py:attribute:: _max_relay_early :value: 8 .. py:attribute:: dht_provider :type: 3.0.ipv8.dht.provider.DHTCommunityProvider | None :value: None .. py:property:: max_relay_early :type: int Return the maximum number of relay_early cells that are allowed to pass a relay. .. py:property:: peer_flags :type: set[int] Return the peer flags. .. py:class:: TunnelCommunity(settings: TunnelSettings) Bases: :py:obj:`3.0.ipv8.community.Community` Community to create circuits of intermediate peers (hops) that send data into (exit) and receive from the Internet. .. py:attribute:: version :value: b'\x02' .. py:attribute:: community_id .. py:attribute:: settings_class .. py:attribute:: settings .. py:attribute:: dht_provider .. py:attribute:: request_cache .. py:attribute:: decode_map_private :type: dict[int, Callable[[TunnelCommunity, 3.0.ipv8.types.Address, bytes, int | None], None] | Callable[[3.0.ipv8.types.Address, bytes, int | None], None]] .. py:attribute:: circuits_needed :type: dict[int, int] .. py:attribute:: candidates :type: dict[3.0.ipv8.peer.Peer, list[int]] .. py:attribute:: crypto :type: 3.0.ipv8.messaging.anonymization.crypto.TunnelCrypto .. py:attribute:: crypto_endpoint .. py:attribute:: circuits .. py:attribute:: relay_from_to .. py:attribute:: exit_sockets .. py:method:: unload() -> None :async: Remove all circuits/relays/exitsockets. .. py:method:: get_serializer() -> 3.0.ipv8.messaging.serialization.Serializer Extend our serializer with the ability to (un)pack exit node flags. .. py:method:: add_cell_handler(payload_cls: type[3.0.ipv8.messaging.lazy_payload.VariablePayloadWID], handler: Callable[[TunnelCommunity, 3.0.ipv8.types.Address, bytes, int | None], None] | Callable[[3.0.ipv8.types.Address, bytes, int | None], None]) -> None Handler for messages that are exclusively tunneled (i.e., never handled plaintext). .. py:method:: _generate_circuit_id() -> int .. py:method:: do_circuits() -> None Check if we have sufficient circuits and attempt to create new circuits if we have too little. .. py:method:: build_tunnels(hops: int) -> None Signal that we want circuits of a given number of hops. The number of circuits created for this hop count is dictated by the ``max_circuits`` setting. .. py:method:: tunnels_ready(hops: int) -> float Fraction of circuits that are available for the given hop count. .. py:method:: do_remove() -> None Remove all circuits that are inactive, old or overused and remove old peers from our candidate list. .. py:method:: get_candidates(*requested_flags: int) -> list[3.0.ipv8.peer.Peer] Get all the peers that we can create circuits with. .. py:method:: get_max_time(circuit_id: int) -> float Get the maximum time (in seconds) that the given circuit is allowed to exist. .. py:method:: find_circuits(ctype: str | None = CIRCUIT_TYPE_DATA, state: str | None = CIRCUIT_STATE_READY, exit_flags: collections.abc.Collection[int] | None = None, hops: int | None = None) -> list[Circuit] Get circuits of the given type and state (and potentially exit flags and a given number of hops). .. py:method:: create_circuit(goal_hops: int, ctype: str = CIRCUIT_TYPE_DATA, exit_flags: collections.abc.Collection[int] | None = None, required_exit: 3.0.ipv8.peer.Peer | None = None, info_hash: bytes | None = None) -> Circuit | None Create a circuit of a given number of hops. The circuit will be created immediately but not be available for transmission of data immediately. Note that not all circuits exist to send data. :return: None if we are supposed to find an exit node and know of none. .. py:method:: send_initial_create(circuit: Circuit, candidate_peers: list[3.0.ipv8.peer.Peer], max_tries: int) -> None Attempt to establish the first hop in a Circuit. .. py:method:: remove_circuit(circuit_id: int, additional_info: str = '', remove_now: bool = False, destroy: bool | int = False) -> None :async: Remove a circuit and optionally send a destroy message. .. py:method:: remove_relay(circuit_id: int, additional_info: str = '', remove_now: bool = False, destroy: bool = False) -> 3.0.ipv8.messaging.anonymization.tunnel.RelayRoute | None :async: Remove a relay and all information associated with the relay. Return the relays that have been removed. .. py:method:: remove_exit_socket(circuit_id: int, additional_info: str = '', remove_now: bool = False, destroy: bool = False) -> 3.0.ipv8.messaging.anonymization.exit_socket.TunnelExitSocket | None :async: Remove an exit socket. Send a destroy message if necessary. .. py:method:: destroy_circuit(circuit: Circuit, reason: int = 0) -> None Send a destroy message over a circuit. Note that the circuit will still exist. .. py:method:: destroy_relay(circuit_id: int, reason: int = 0) -> None Destroy our relay circuit upon request and forward a destroy message. Note that the relay route will still exist. .. py:method:: destroy_exit_socket(exit_socket: 3.0.ipv8.messaging.anonymization.exit_socket.TunnelExitSocket, reason: int = 0) -> None Destroy an exit socket. Note that the exit socket will still exist. .. py:method:: send_cell(target_addr: 3.0.ipv8.types.Address, payload: CellablePayload) -> None Send the given payload DIRECTLY to the given peer with the appropriate encryption rules. .. py:method:: send_data(target: 3.0.ipv8.types.Address, circuit_id: int, dest_address: 3.0.ipv8.types.Address, source_address: 3.0.ipv8.types.Address, data: bytes) -> None Pack the given binary data and forward it to the given peer. .. py:method:: send_packet(target: 3.0.ipv8.types.Address, packet: bytes) -> int Send raw data over the socket to a given peer and return the length of the sent data. .. py:method:: send_destroy(target: 3.0.ipv8.types.Address, circuit_id: int, reason: int) -> None Send a destroy message directly to the given peer. .. py:method:: _ours_on_created_extended(circuit_id: int, payload: CreatedPayload | ExtendedPayload) -> None .. py:method:: send_extend(circuit: Circuit, candidates: list[bytes], max_tries: int) -> None Extend a circuit by choosing one of the given candidates. .. py:method:: extract_peer_flags(extra_bytes: bytes) -> list[int] Convert piggybacked introduction bytes to a list of peer flags. .. py:method:: introduction_request_callback(peer: 3.0.ipv8.peer.Peer, dist: 3.0.ipv8.messaging.payload_headers.GlobalTimeDistributionPayload, payload: 3.0.ipv8.messaging.payload.IntroductionRequestPayload | 3.0.ipv8.messaging.payload.NewIntroductionRequestPayload) -> None Try to extract piggybacked data from the introduction request. .. py:method:: introduction_response_callback(peer: 3.0.ipv8.peer.Peer, dist: 3.0.ipv8.messaging.payload_headers.GlobalTimeDistributionPayload, payload: 3.0.ipv8.messaging.payload.IntroductionResponsePayload | 3.0.ipv8.messaging.payload.NewIntroductionResponsePayload) -> None Try to extract piggybacked data from the introduction response. .. py:method:: create_introduction_request(socket_address: 3.0.ipv8.types.Address, extra_bytes: bytes = b'', new_style: bool = False, prefix: bytes | None = None) -> bytes Add peer flags to our introduction requests. .. py:method:: create_introduction_response(lan_socket_address: 3.0.ipv8.types.Address, socket_address: 3.0.ipv8.types.Address, identifier: int, introduction: 3.0.ipv8.peer.Peer | None = None, extra_bytes: bytes = b'', prefix: bytes | None = None, new_style: bool = False) -> bytes Add peer flags to our introduction responses. .. py:method:: on_cell(source_address: 3.0.ipv8.types.Address, data: bytes) -> None Process an incoming cell, originating from a given address. .. py:method:: on_packet_from_circuit(source_address: 3.0.ipv8.types.Address, data: bytes, circuit_id: int) -> None Process incoming raw data, assumed to be an IPv8 packet, originating from a given address. .. py:method:: should_join_circuit(create_payload: CreatePayload, previous_node_address: 3.0.ipv8.types.Address) -> bool :async: Check whether we should join a circuit. Note that this method is intended to be overwritten and, therefore, has unused arguments. .. py:method:: join_circuit(create_payload: CreatePayload, previous_node_address: 3.0.ipv8.types.Address) -> None Actively join a circuit and send a created message back. .. py:method:: on_create(source_address: 3.0.ipv8.types.Address, payload: CreatePayload, _: int | None) -> None :async: Process a request to join someone's circuit. .. py:method:: on_created(source_address: 3.0.ipv8.types.Address, payload: CreatedPayload, _: int | None) -> None Callback for when another peer signals that they have joined our circuit. .. py:method:: on_extend(source_address: 3.0.ipv8.types.Address, payload: ExtendPayload, _: int | None) -> None :async: Callback for when a peer asks us to extend for their circuit. .. py:method:: on_extended(source_address: 3.0.ipv8.types.Address, payload: ExtendedPayload, _: int | None) -> None Callback for when a peer signals that they have extended our circuit. .. py:method:: on_raw_data(circuit: Circuit, origin: 3.0.ipv8.types.Address, data: bytes) -> None Handle data, coming from a specific circuit and origin. This method is usually implemented in subclasses of this community. .. py:method:: on_data(sock_addr: 3.0.ipv8.types.Address, data: bytes, _: int | None) -> None Callback for when we receive a DataPayload out of a circuit. Data is readable only if this handler is (a) an exit node or (b) the one that created the circuit. .. py:method:: on_ping(source_address: 3.0.ipv8.types.Address, payload: PingPayload, _: int | None) -> None Callback for when we received a tunneled ping message. .. py:method:: on_pong(source_address: 3.0.ipv8.types.Address, payload: PongPayload, _: int | None) -> None Callback for when we received a tunneled pong (response) message. .. py:method:: do_ping(exclude: list[int] | None = None) -> None Ping circuits. Pings are only sent to the first hop, subsequent hops will relay the ping. .. py:method:: on_destroy(peer: 3.0.ipv8.peer.Peer, payload: DestroyPayload) -> None Callback for when we received a destroy message. .. py:method:: exit_data(circuit_id: int, sock_addr: 3.0.ipv8.types.Address, destination: 3.0.ipv8.types.Address, data: bytes) -> None Exit data (to the destination) out of the exit socket associated with the given circuit id. .. py:method:: dht_peer_lookup(mid: bytes, peer: 3.0.ipv8.peer.Peer | None = None) -> None :async: Perform a DHT lookup for a given SHA-1 hash of a public key. Note that connections (if any) will be performed in the background. Query for results manually later. .. py:method:: send_test_request(circuit: Circuit, request_size: int = 0, response_size: int = 0) -> Future[tuple[bytes, float]] Send a speed test request and wait for a (data, RTT time in seconds) tuple to be recorded. .. py:method:: on_test_request(source_address: 3.0.ipv8.types.Address, data: bytes, circuit_id: int | None) -> None Callback for when we receive a speed test request. .. py:method:: on_test_response(source_address: 3.0.ipv8.types.Address, data: bytes, circuit_id: int | None) -> None Callback for when we received a test response. We record the data that the response contained and the time since we sent the original request.