diff --git a/src/peerbook/libp2p_peer.erl b/src/peerbook/libp2p_peer.erl index d56ed3cc..0f51a6a9 100644 --- a/src/peerbook/libp2p_peer.erl +++ b/src/peerbook/libp2p_peer.erl @@ -9,7 +9,8 @@ nat_type => nat_type(), network_id => binary(), associations => association_map(), - signed_metadata => #{binary() => binary()} + signed_metadata => #{binary() => binary()}, + relaying_for => [binary()] }. -type peer() :: #libp2p_signed_peer_pb{}. -type association() :: #libp2p_association_pb{}. @@ -18,7 +19,7 @@ -export_type([peer/0, association/0, peer_map/0, nat_type/0]). -export([from_map/2, encode/1, decode/1, decode_unsafe/1, encode_list/1, decode_list/1, verify/1, - pubkey_bin/1, listen_addrs/1, connected_peers/1, nat_type/1, timestamp/1, + pubkey_bin/1, listen_addrs/1, connected_peers/1, relaying_for_peers/1, nat_type/1, timestamp/1, supersedes/2, is_stale/2, is_similar/2, network_id/1, network_id_allowable/2, has_public_ip/1, is_dialable/1]). %% associations @@ -55,7 +56,8 @@ from_map(Map, SigFun) -> network_id=maps:get(network_id, Map, <<>>), timestamp=Timestamp, associations=Assocs, - signed_metadata=encode_map(maps:get(signed_metadata, Map, #{})) + signed_metadata=encode_map(maps:get(signed_metadata, Map, #{})), + relaying_for = maps:get(relaying_for, Map) }, sign_peer(Peer, SigFun). @@ -76,6 +78,12 @@ listen_addrs(#libp2p_signed_peer_pb{peer=#libp2p_peer_pb{listen_addrs=Addrs}}) - connected_peers(#libp2p_signed_peer_pb{peer=#libp2p_peer_pb{connected=Conns}}) -> Conns. +%% @doc Gets the list of peer crypto addresses that the given peer was last +%% known to be relaying for. +-spec relaying_for_peers(peer()) -> [libp2p_crypto:pubkey_bin()]. +relaying_for_peers(#libp2p_signed_peer_pb{peer=#libp2p_peer_pb{relaying_for=Conns}}) -> + Conns. + %% @doc Gets the NAT type of the given peer. -spec nat_type(peer()) -> nat_type(). nat_type(#libp2p_signed_peer_pb{peer=#libp2p_peer_pb{nat_type=NatType}}) -> diff --git a/src/peerbook/libp2p_peer.proto b/src/peerbook/libp2p_peer.proto index 0af2023c..39553766 100644 --- a/src/peerbook/libp2p_peer.proto +++ b/src/peerbook/libp2p_peer.proto @@ -17,6 +17,7 @@ message peer { map associations = 6; bytes network_id = 7; map signed_metadata = 8; + repeated bytes relaying_for = 9; } message metadata_value { diff --git a/src/peerbook/libp2p_peerbook.erl b/src/peerbook/libp2p_peerbook.erl index ecdd2b5c..4cf2e172 100644 --- a/src/peerbook/libp2p_peerbook.erl +++ b/src/peerbook/libp2p_peerbook.erl @@ -147,7 +147,7 @@ register_session(#peerbook{tid=TID}, SessionPid, Identify) -> unregister_session(#peerbook{tid=TID}, SessionPid) -> gen_server:cast(libp2p_swarm:peerbook_pid(TID), {unregister_session, SessionPid}). -changed_listener(#peerbook{tid=TID}) ->% +changed_listener(#peerbook{tid=TID}) -> gen_server:cast(libp2p_swarm:peerbook_pid(TID), changed_listener). -spec update_nat_type(peerbook(), libp2p_peer:nat_type()) -> ok. @@ -318,11 +318,23 @@ terminate(_Reason, _State) -> %% -spec mk_this_peer(libp2p_peer:peer() | undefined, #state{}) -> {ok, libp2p_peer:peer()} | {error, term()}. -mk_this_peer(CurrentPeer, State=#state{tid=TID}) -> +mk_this_peer(CurrentPeer, #state{tid=TID, peerbook=PeerBook, sessions=Sessions}=State) -> SwarmAddr = libp2p_swarm:pubkey_bin(TID), ListenAddrs = libp2p_config:listen_addrs(TID), NetworkID = libp2p_swarm:network_id(TID), - ConnectedAddrs = sets:to_list(sets:from_list([Addr || {Addr, _} <- State#state.sessions])), + ConnectedAddrs = sets:to_list(sets:from_list([Addr || {Addr, _} <- Sessions])), + RelayUsingAddrs = lists:filter( + fun(PubKeyBin) -> + case ?MODULE:get(PeerBook, PubKeyBin) of + {error, _} -> + false; + {ok, Peer} -> + ListenAddresses = libp2p_peer:listen_addrs(Peer), + lists:any(fun libp2p_relay:is_p2p_circuit/1, ListenAddresses) + end + end, + ConnectedAddrs + ), %% Copy data from current peer case CurrentPeer of undefined -> @@ -339,13 +351,14 @@ mk_this_peer(CurrentPeer, State=#state{tid=TID}) -> catch _:_ -> #{} end, - libp2p_peer:from_map(#{ pubkey => SwarmAddr, - listen_addrs => ListenAddrs, - connected => ConnectedAddrs, - nat_type => State#state.nat_type, - network_id => NetworkID, - associations => Associations, - signed_metadata => MetaData}, + libp2p_peer:from_map(#{pubkey => SwarmAddr, + listen_addrs => ListenAddrs, + connected => ConnectedAddrs -- RelayUsingAddrs, + nat_type => State#state.nat_type, + network_id => NetworkID, + associations => Associations, + signed_metadata => MetaData, + relaying_for => RelayUsingAddrs}, State#state.sigfun). -spec update_this_peer(#state{}) -> #state{}. diff --git a/src/relay/libp2p_relay.erl b/src/relay/libp2p_relay.erl index 46cb1c4d..ab0a9e84 100644 --- a/src/relay/libp2p_relay.erl +++ b/src/relay/libp2p_relay.erl @@ -111,7 +111,7 @@ is_valid_peer(Swarm, PubKeyBin) -> Error; {ok, Peer} -> StaleTime = libp2p_peerbook:stale_time(PeerBook), - ConnectedPeers = libp2p_peer:connected_peers(Peer), + ConnectedPeers = libp2p_peer:relaying_for_peers(Peer), not libp2p_peer:is_stale(Peer, StaleTime) andalso libp2p_peer:has_public_ip(Peer) andalso lists:member(libp2p_swarm:pubkey_bin(Swarm), ConnectedPeers) diff --git a/src/relay/libp2p_transport_relay.erl b/src/relay/libp2p_transport_relay.erl index 59f80357..b009a3b8 100644 --- a/src/relay/libp2p_transport_relay.erl +++ b/src/relay/libp2p_transport_relay.erl @@ -123,7 +123,7 @@ check_peerbook(TID, MAddr) -> ServerAddress = libp2p_crypto:p2p_to_pubkey_bin(SAddress), case libp2p_peerbook:get(Peerbook, RelayAddress) of {ok, Peer} -> - lists:member(ServerAddress, libp2p_peer:connected_peers(Peer)); + lists:member(ServerAddress, libp2p_peer:relaying_for_peers(Peer)); Error -> Error end.