class_docstr: This class is responsible for establishing peer-to-peer connections through NAT and/or firewalls.
  It creates and manages a libp2p daemon (https://libp2p.io) in a background process,
  then terminates it when P2P is shut down. In order to communicate, a P2P instance should
  either use one or more initial_peers that will connect it to the rest of the swarm or
  use the public IPFS network (https://ipfs.io).
  
  For incoming connections, P2P instances add RPC handlers that may be accessed by other peers:
    - `P2P.add_protobuf_handler` accepts a protobuf message and returns another protobuf
    - `P2P.add_binary_stream_handler` transfers raw data using bi-directional streaming interface
  
  To access these handlers, a P2P instance can `P2P.call_protobuf_handler`/`P2P.call_binary_stream_handler`,
  using the recipient's unique `P2P.peer_id` and the name of the corresponding handler.
code: def _start_listening(self) -> None:
      async def listen() -> None:
          async with self._client.listen():
              await asyncio.Future()  # Wait until this task will be cancelled in _terminate()
  
      self._listen_task = asyncio.create_task(listen())
  
imports: import asyncio
  import json
  import logging
  import os
  import secrets
  import warnings
  from collections.abc import AsyncIterable
  from contextlib import closing, suppress
  from dataclasses import dataclass
  from datetime import datetime
  from importlib.resources import path
  from typing import Any, AsyncIterator, Awaitable, Callable, List, Optional, Sequence, Tuple, Type, TypeVar, Union
  from google.protobuf.message import Message
  from multiaddr import Multiaddr
  import hivemind.hivemind_cli
  import hivemind.p2p.p2p_daemon_bindings.p2pclient
  from hivemind.p2p.p2p_daemon_bindings.control import DEFAULT_MAX_MSG_SIZE, P2PDaemonError, P2PHandlerError
  from hivemind.p2p.p2p_daemon_bindings.datastructures import PeerID, PeerInfo, StreamInfo
  from hivemind.p2p.p2p_daemon_bindings.utils import ControlFailure
  from hivemind.proto import crypto_pb2
  from hivemind.proto.p2pd_pb2 import RPCError
  from hivemind.utils.asyncio import as_aiter, asingle
  from hivemind.utils.crypto import RSAPrivateKey
  from hivemind.utils.logging import get_logger, golog_level_to_python, loglevel, python_level_to_golog
label_desc: Use image node_id 4 for calling the P2P obj's underlying member method code with example usage: obj._start_listening() without return types