use std::num::NonZeroU8;
use libp2p_core::{connection::Endpoint, multiaddr::Protocol, transport::PortUse, Multiaddr};
use libp2p_identity::PeerId;
use crate::ConnectionId;
macro_rules! fn_override_role {
() => {
pub fn override_role(mut self) -> Self {
self.role_override = Endpoint::Listener;
self
}
};
}
macro_rules! fn_allocate_new_port {
() => {
pub fn allocate_new_port(mut self) -> Self {
self.port_use = PortUse::New;
self
}
};
}
#[derive(Debug)]
pub struct DialOpts {
peer_id: Option<PeerId>,
condition: PeerCondition,
addresses: Vec<Multiaddr>,
extend_addresses_through_behaviour: bool,
role_override: Endpoint,
dial_concurrency_factor_override: Option<NonZeroU8>,
connection_id: ConnectionId,
port_use: PortUse,
}
impl DialOpts {
pub fn peer_id(peer_id: PeerId) -> WithPeerId {
WithPeerId {
peer_id,
condition: Default::default(),
role_override: Endpoint::Dialer,
dial_concurrency_factor_override: Default::default(),
port_use: PortUse::Reuse,
}
}
pub fn unknown_peer_id() -> WithoutPeerId {
WithoutPeerId {}
}
pub fn get_peer_id(&self) -> Option<PeerId> {
if let Some(peer_id) = self.peer_id {
return Some(peer_id);
}
let first_address = self.addresses.first()?;
let last_protocol = first_address.iter().last()?;
if let Protocol::P2p(p) = last_protocol {
return Some(p);
}
None
}
pub fn connection_id(&self) -> ConnectionId {
self.connection_id
}
pub(crate) fn get_addresses(&self) -> Vec<Multiaddr> {
self.addresses.clone()
}
pub(crate) fn extend_addresses_through_behaviour(&self) -> bool {
self.extend_addresses_through_behaviour
}
pub(crate) fn peer_condition(&self) -> PeerCondition {
self.condition
}
pub(crate) fn dial_concurrency_override(&self) -> Option<NonZeroU8> {
self.dial_concurrency_factor_override
}
pub(crate) fn role_override(&self) -> Endpoint {
self.role_override
}
pub(crate) fn port_use(&self) -> PortUse {
self.port_use
}
}
impl From<Multiaddr> for DialOpts {
fn from(address: Multiaddr) -> Self {
DialOpts::unknown_peer_id().address(address).build()
}
}
impl From<PeerId> for DialOpts {
fn from(peer_id: PeerId) -> Self {
DialOpts::peer_id(peer_id).build()
}
}
#[derive(Debug)]
pub struct WithPeerId {
peer_id: PeerId,
condition: PeerCondition,
role_override: Endpoint,
dial_concurrency_factor_override: Option<NonZeroU8>,
port_use: PortUse,
}
impl WithPeerId {
pub fn condition(mut self, condition: PeerCondition) -> Self {
self.condition = condition;
self
}
pub fn override_dial_concurrency_factor(mut self, factor: NonZeroU8) -> Self {
self.dial_concurrency_factor_override = Some(factor);
self
}
pub fn addresses(self, addresses: Vec<Multiaddr>) -> WithPeerIdWithAddresses {
WithPeerIdWithAddresses {
peer_id: self.peer_id,
condition: self.condition,
addresses,
extend_addresses_through_behaviour: false,
role_override: self.role_override,
dial_concurrency_factor_override: self.dial_concurrency_factor_override,
port_use: self.port_use,
}
}
fn_override_role!();
fn_allocate_new_port!();
pub fn build(self) -> DialOpts {
DialOpts {
peer_id: Some(self.peer_id),
condition: self.condition,
addresses: vec![],
extend_addresses_through_behaviour: true,
role_override: self.role_override,
dial_concurrency_factor_override: self.dial_concurrency_factor_override,
connection_id: ConnectionId::next(),
port_use: self.port_use,
}
}
}
#[derive(Debug)]
pub struct WithPeerIdWithAddresses {
peer_id: PeerId,
condition: PeerCondition,
addresses: Vec<Multiaddr>,
extend_addresses_through_behaviour: bool,
role_override: Endpoint,
dial_concurrency_factor_override: Option<NonZeroU8>,
port_use: PortUse,
}
impl WithPeerIdWithAddresses {
pub fn condition(mut self, condition: PeerCondition) -> Self {
self.condition = condition;
self
}
pub fn extend_addresses_through_behaviour(mut self) -> Self {
self.extend_addresses_through_behaviour = true;
self
}
fn_override_role!();
fn_allocate_new_port!();
pub fn override_dial_concurrency_factor(mut self, factor: NonZeroU8) -> Self {
self.dial_concurrency_factor_override = Some(factor);
self
}
pub fn build(self) -> DialOpts {
DialOpts {
peer_id: Some(self.peer_id),
condition: self.condition,
addresses: self.addresses,
extend_addresses_through_behaviour: self.extend_addresses_through_behaviour,
role_override: self.role_override,
dial_concurrency_factor_override: self.dial_concurrency_factor_override,
connection_id: ConnectionId::next(),
port_use: self.port_use,
}
}
}
#[derive(Debug)]
pub struct WithoutPeerId {}
impl WithoutPeerId {
pub fn address(self, address: Multiaddr) -> WithoutPeerIdWithAddress {
WithoutPeerIdWithAddress {
address,
role_override: Endpoint::Dialer,
port_use: PortUse::Reuse,
}
}
}
#[derive(Debug)]
pub struct WithoutPeerIdWithAddress {
address: Multiaddr,
role_override: Endpoint,
port_use: PortUse,
}
impl WithoutPeerIdWithAddress {
fn_override_role!();
fn_allocate_new_port!();
pub fn build(self) -> DialOpts {
DialOpts {
peer_id: None,
condition: PeerCondition::Always,
addresses: vec![self.address],
extend_addresses_through_behaviour: false,
role_override: self.role_override,
dial_concurrency_factor_override: None,
connection_id: ConnectionId::next(),
port_use: self.port_use,
}
}
}
#[derive(Debug, Copy, Clone, Default)]
pub enum PeerCondition {
Disconnected,
NotDialing,
#[default]
DisconnectedAndNotDialing,
Always,
}