package libp2p

// This file contains all libp2p configuration options (except the defaults,
// those are in defaults.go).

import (
	
	
	
	
	
	

	
	
	
	
	
	
	
	
	
	
	
	bhost 
	
	tptu 
	relayv2 
	
	
	

	ma 
	
)

// ListenAddrStrings configures libp2p to listen on the given (unparsed)
// addresses.
func ( ...string) Option {
	return func( *Config) error {
		for ,  := range  {
			,  := ma.NewMultiaddr()
			if  != nil {
				return 
			}
			.ListenAddrs = append(.ListenAddrs, )
		}
		return nil
	}
}

// ListenAddrs configures libp2p to listen on the given addresses.
func ( ...ma.Multiaddr) Option {
	return func( *Config) error {
		.ListenAddrs = append(.ListenAddrs, ...)
		return nil
	}
}

// Security configures libp2p to use the given security transport (or transport
// constructor).
//
// Name is the protocol name.
//
// The transport can be a constructed security.Transport or a function taking
// any subset of this libp2p node's:
// * Public key
// * Private key
// * Peer ID
// * Host
// * Network
// * Peerstore
func ( string,  interface{}) Option {
	return func( *Config) error {
		if .Insecure {
			return fmt.Errorf("cannot use security transports with an insecure libp2p configuration")
		}
		.SecurityTransports = append(.SecurityTransports, config.Security{ID: protocol.ID(), Constructor: })
		return nil
	}
}

// NoSecurity is an option that completely disables all transport security.
// It's incompatible with all other transport security protocols.
var NoSecurity Option = func( *Config) error {
	if len(.SecurityTransports) > 0 {
		return fmt.Errorf("cannot use security transports with an insecure libp2p configuration")
	}
	.Insecure = true
	return nil
}

// Muxer configures libp2p to use the given stream multiplexer.
// name is the protocol name.
func ( string,  network.Multiplexer) Option {
	return func( *Config) error {
		.Muxers = append(.Muxers, tptu.StreamMuxer{Muxer: , ID: protocol.ID()})
		return nil
	}
}

func ( interface{},  ...quicreuse.Option) Option {
	return func( *Config) error {
		 := `group:"quicreuseopts"`
		 := reflect.ValueOf().Type()
		 := .NumIn()
		 := .IsVariadic()

		if ! && len() > 0 {
			return errors.New("QUICReuse constructor doesn't take any options")
		}

		var  []string
		if  && len() > 0 {
			// If there are options, apply the tag.
			// Since options are variadic, they have to be the last argument of the constructor.
			 = make([]string, )
			[len()-1] = 
		}

		.QUICReuse = append(.QUICReuse, fx.Provide(fx.Annotate(, fx.ParamTags(...))))
		for ,  := range  {
			.QUICReuse = append(.QUICReuse, fx.Supply(fx.Annotate(, fx.ResultTags())))
		}
		return nil
	}
}

// Transport configures libp2p to use the given transport (or transport
// constructor).
//
// The transport can be a constructed transport.Transport or a function taking
// any subset of this libp2p node's:
// * Transport Upgrader (*tptu.Upgrader)
// * Host
// * Stream muxer (muxer.Transport)
// * Security transport (security.Transport)
// * Private network protector (pnet.Protector)
// * Peer ID
// * Private Key
// * Public Key
// * Address filter (filter.Filter)
// * Peerstore
func ( interface{},  ...interface{}) Option {
	return func( *Config) error {
		// generate a random identifier, so that fx can associate the constructor with its options
		 := make([]byte, 8)
		rand.Read()
		 := binary.BigEndian.Uint64()

		 := fmt.Sprintf(`group:"transportopt_%d"`, )

		 := reflect.ValueOf().Type()
		 := .NumIn()
		 := .IsVariadic()

		if ! && len() > 0 {
			return errors.New("transport constructor doesn't take any options")
		}
		if  &&  >= 1 {
			 := .In( - 1).Elem()
			for ,  := range  {
				if  := reflect.TypeOf(); !.AssignableTo() {
					return fmt.Errorf("transport option of type %s not assignable to %s", , )
				}
			}
		}

		var  []string
		if  && len() > 0 {
			// If there are transport options, apply the tag.
			// Since options are variadic, they have to be the last argument of the constructor.
			 = make([]string, )
			[len()-1] = 
		}

		.Transports = append(.Transports, fx.Provide(
			fx.Annotate(
				,
				fx.ParamTags(...),
				fx.As(new(transport.Transport)),
				fx.ResultTags(`group:"transport"`),
			),
		))
		for ,  := range  {
			.Transports = append(.Transports, fx.Supply(
				fx.Annotate(
					,
					fx.ResultTags(),
				),
			))
		}
		return nil
	}
}

// Peerstore configures libp2p to use the given peerstore.
func ( peerstore.Peerstore) Option {
	return func( *Config) error {
		if .Peerstore != nil {
			return fmt.Errorf("cannot specify multiple peerstore options")
		}

		.Peerstore = 
		return nil
	}
}

// PrivateNetwork configures libp2p to use the given private network protector.
func ( pnet.PSK) Option {
	return func( *Config) error {
		if .PSK != nil {
			return fmt.Errorf("cannot specify multiple private network options")
		}

		.PSK = 
		return nil
	}
}

// BandwidthReporter configures libp2p to use the given bandwidth reporter.
func ( metrics.Reporter) Option {
	return func( *Config) error {
		if .Reporter != nil {
			return fmt.Errorf("cannot specify multiple bandwidth reporter options")
		}

		.Reporter = 
		return nil
	}
}

// Identity configures libp2p to use the given private key to identify itself.
func ( crypto.PrivKey) Option {
	return func( *Config) error {
		if .PeerKey != nil {
			return fmt.Errorf("cannot specify multiple identities")
		}

		.PeerKey = 
		return nil
	}
}

// ConnectionManager configures libp2p to use the given connection manager.
//
// The current "standard" connection manager lives in github.com/libp2p/go-libp2p-connmgr. See
// https://pkg.go.dev/github.com/libp2p/go-libp2p-connmgr?utm_source=godoc#NewConnManager.
func ( connmgr.ConnManager) Option {
	return func( *Config) error {
		if .ConnManager != nil {
			return fmt.Errorf("cannot specify multiple connection managers")
		}
		.ConnManager = 
		return nil
	}
}

// AddrsFactory configures libp2p to use the given address factory.
func ( config.AddrsFactory) Option {
	return func( *Config) error {
		if .AddrsFactory != nil {
			return fmt.Errorf("cannot specify multiple address factories")
		}
		.AddrsFactory = 
		return nil
	}
}

// EnableRelay configures libp2p to enable the relay transport.
// This option only configures libp2p to accept inbound connections from relays
// and make outbound connections_through_ relays when requested by the remote peer.
// This option supports both circuit v1 and v2 connections.
// (default: enabled)
func () Option {
	return func( *Config) error {
		.RelayCustom = true
		.Relay = true
		return nil
	}
}

// DisableRelay configures libp2p to disable the relay transport.
func () Option {
	return func( *Config) error {
		.RelayCustom = true
		.Relay = false
		return nil
	}
}

// EnableRelayService configures libp2p to run a circuit v2 relay,
// if we detect that we're publicly reachable.
func ( ...relayv2.Option) Option {
	return func( *Config) error {
		.EnableRelayService = true
		.RelayServiceOpts = 
		return nil
	}
}

// EnableAutoRelay configures libp2p to enable the AutoRelay subsystem.
//
// Dependencies:
//   - Relay (enabled by default)
//   - Either:
//     1. A list of static relays
//     2. A PeerSource function that provides a chan of relays. See `autorelay.WithPeerSource`
//
// This subsystem performs automatic address rewriting to advertise relay addresses when it
// detects that the node is publicly unreachable (e.g. behind a NAT).
//
// Deprecated: Use EnableAutoRelayWithStaticRelays or EnableAutoRelayWithPeerSource
func ( ...autorelay.Option) Option {
	return func( *Config) error {
		.EnableAutoRelay = true
		.AutoRelayOpts = 
		return nil
	}
}

// EnableAutoRelayWithStaticRelays configures libp2p to enable the AutoRelay subsystem using
// the provided relays as relay candidates.
// This subsystem performs automatic address rewriting to advertise relay addresses when it
// detects that the node is publicly unreachable (e.g. behind a NAT).
func ( []peer.AddrInfo,  ...autorelay.Option) Option {
	return func( *Config) error {
		.EnableAutoRelay = true
		.AutoRelayOpts = append([]autorelay.Option{autorelay.WithStaticRelays()}, ...)
		return nil
	}
}

// EnableAutoRelayWithPeerSource configures libp2p to enable the AutoRelay
// subsystem using the provided PeerSource callback to get more relay
// candidates.  This subsystem performs automatic address rewriting to advertise
// relay addresses when it detects that the node is publicly unreachable (e.g.
// behind a NAT).
func ( autorelay.PeerSource,  ...autorelay.Option) Option {
	return func( *Config) error {
		.EnableAutoRelay = true
		.AutoRelayOpts = append([]autorelay.Option{autorelay.WithPeerSource()}, ...)
		return nil
	}
}

// ForceReachabilityPublic overrides automatic reachability detection in the AutoNAT subsystem,
// forcing the local node to believe it is reachable externally.
func () Option {
	return func( *Config) error {
		 := network.ReachabilityPublic
		.AutoNATConfig.ForceReachability = &
		return nil
	}
}

// ForceReachabilityPrivate overrides automatic reachability detection in the AutoNAT subsystem,
// forceing the local node to believe it is behind a NAT and not reachable externally.
func () Option {
	return func( *Config) error {
		 := network.ReachabilityPrivate
		.AutoNATConfig.ForceReachability = &
		return nil
	}
}

// EnableNATService configures libp2p to provide a service to peers for determining
// their reachability status. When enabled, the host will attempt to dial back
// to peers, and then tell them if it was successful in making such connections.
func () Option {
	return func( *Config) error {
		.AutoNATConfig.EnableService = true
		return nil
	}
}

// AutoNATServiceRateLimit changes the default rate limiting configured in helping
// other peers determine their reachability status. When set, the host will limit
// the number of requests it responds to in each 60 second period to the set
// numbers. A value of '0' disables throttling.
func (,  int,  time.Duration) Option {
	return func( *Config) error {
		.AutoNATConfig.ThrottleGlobalLimit = 
		.AutoNATConfig.ThrottlePeerLimit = 
		.AutoNATConfig.ThrottleInterval = 
		return nil
	}
}

// ConnectionGater configures libp2p to use the given ConnectionGater
// to actively reject inbound/outbound connections based on the lifecycle stage
// of the connection.
//
// For more information, refer to go-libp2p/core.ConnectionGater.
func ( connmgr.ConnectionGater) Option {
	return func( *Config) error {
		if .ConnectionGater != nil {
			return errors.New("cannot configure multiple connection gaters, or cannot configure both Filters and ConnectionGater")
		}
		.ConnectionGater = 
		return nil
	}
}

// ResourceManager configures libp2p to use the given ResourceManager.
// When using the p2p/host/resource-manager implementation of the ResourceManager interface,
// it is recommended to set limits for libp2p protocol by calling SetDefaultServiceLimits.
func ( network.ResourceManager) Option {
	return func( *Config) error {
		if .ResourceManager != nil {
			return errors.New("cannot configure multiple resource managers")
		}
		.ResourceManager = 
		return nil
	}
}

// NATPortMap configures libp2p to use the default NATManager. The default
// NATManager will attempt to open a port in your network's firewall using UPnP.
func () Option {
	return NATManager(bhost.NewNATManager)
}

// NATManager will configure libp2p to use the requested NATManager. This
// function should be passed a NATManager *constructor* that takes a libp2p Network.
func ( config.NATManagerC) Option {
	return func( *Config) error {
		if .NATManager != nil {
			return fmt.Errorf("cannot specify multiple NATManagers")
		}
		.NATManager = 
		return nil
	}
}

// Ping will configure libp2p to support the ping service; enable by default.
func ( bool) Option {
	return func( *Config) error {
		.DisablePing = !
		return nil
	}
}

// Routing will configure libp2p to use routing.
func ( config.RoutingC) Option {
	return func( *Config) error {
		if .Routing != nil {
			return fmt.Errorf("cannot specify multiple routing options")
		}
		.Routing = 
		return nil
	}
}

// NoListenAddrs will configure libp2p to not listen by default.
//
// This will both clear any configured listen addrs and prevent libp2p from
// applying the default listen address option. It also disables relay, unless the
// user explicitly specifies with an option, as the transport creates an implicit
// listen address that would make the node dialable through any relay it was connected to.
var NoListenAddrs = func( *Config) error {
	.ListenAddrs = []ma.Multiaddr{}
	if !.RelayCustom {
		.RelayCustom = true
		.Relay = false
	}
	return nil
}

// NoTransports will configure libp2p to not enable any transports.
//
// This will both clear any configured transports (specified in prior libp2p
// options) and prevent libp2p from applying the default transports.
var NoTransports = func( *Config) error {
	.Transports = []fx.Option{}
	return nil
}

// ProtocolVersion sets the protocolVersion string required by the
// libp2p Identify protocol.
func ( string) Option {
	return func( *Config) error {
		.ProtocolVersion = 
		return nil
	}
}

// UserAgent sets the libp2p user-agent sent along with the identify protocol
func ( string) Option {
	return func( *Config) error {
		.UserAgent = 
		return nil
	}
}

// MultiaddrResolver sets the libp2p dns resolver
func ( network.MultiaddrDNSResolver) Option {
	return func( *Config) error {
		.MultiaddrResolver = 
		return nil
	}
}

// Experimental
// EnableHolePunching enables NAT traversal by enabling NATT'd peers to both initiate and respond to hole punching attempts
// to create direct/NAT-traversed connections with other peers. (default: disabled)
//
// Dependencies:
//   - Relay (enabled by default)
//
// This subsystem performs two functions:
//
//  1. On receiving an inbound Relay connection, it attempts to create a direct connection with the remote peer
//     by initiating and co-ordinating a hole punch over the Relayed connection.
//  2. If a peer sees a request to co-ordinate a hole punch on an outbound Relay connection,
//     it will participate in the hole-punch to create a direct connection with the remote peer.
//
// If the hole punch is successful, all new streams will thereafter be created on the hole-punched connection.
// The Relayed connection will eventually be closed after a grace period.
//
// All existing indefinite long-lived streams on the Relayed connection will have to re-opened on the hole-punched connection by the user.
// Users can make use of the `Connected`/`Disconnected` notifications emitted by the Network for this purpose.
//
// It is not mandatory but nice to also enable the `AutoRelay` option (See `EnableAutoRelay`)
// so the peer can discover and connect to Relay servers  if it discovers that it is NATT'd and has private reachability via AutoNAT.
// This will then enable it to advertise Relay addresses which can be used to accept inbound Relay connections to then co-ordinate
// a hole punch.
//
// If `EnableAutoRelay` is configured and the user is confident that the peer has private reachability/is NATT'd,
// the `ForceReachabilityPrivate` option can be configured to short-circuit reachability discovery via AutoNAT
// so the peer can immediately start connecting to Relay servers.
//
// If `EnableAutoRelay` is configured, the `StaticRelays` option can be used to configure a static set of Relay servers
// for `AutoRelay` to connect to so that it does not need to discover Relay servers via Routing.
func ( ...holepunch.Option) Option {
	return func( *Config) error {
		.EnableHolePunching = true
		.HolePunchingOptions = 
		return nil
	}
}

func ( time.Duration) Option {
	return func( *Config) error {
		if  <= 0 {
			return errors.New("dial timeout needs to be non-negative")
		}
		.DialTimeout = 
		return nil
	}
}

// DisableMetrics configures libp2p to disable prometheus metrics
func () Option {
	return func( *Config) error {
		.DisableMetrics = true
		return nil
	}
}

// PrometheusRegisterer configures libp2p to use reg as the Registerer for all metrics subsystems
func ( prometheus.Registerer) Option {
	return func( *Config) error {
		if .DisableMetrics {
			return errors.New("cannot set registerer when metrics are disabled")
		}
		if .PrometheusRegisterer != nil {
			return errors.New("registerer already set")
		}
		if  == nil {
			return errors.New("registerer cannot be nil")
		}
		.PrometheusRegisterer = 
		return nil
	}
}

// DialRanker configures libp2p to use d as the dial ranker. To enable smart
// dialing use `swarm.DefaultDialRanker`. use `swarm.NoDelayDialRanker` to
// disable smart dialing.
//
// Deprecated: use SwarmOpts(swarm.WithDialRanker(d)) instead
func ( network.DialRanker) Option {
	return func( *Config) error {
		if .DialRanker != nil {
			return errors.New("dial ranker already configured")
		}
		.DialRanker = 
		return nil
	}
}

// SwarmOpts configures libp2p to use swarm with opts
func ( ...swarm.Option) Option {
	return func( *Config) error {
		.SwarmOpts = 
		return nil
	}
}

// DisableIdentifyAddressDiscovery disables address discovery using peer provided observed addresses
// in identify. If you know your public addresses upfront, the recommended way is to use
// AddressFactory to provide the external adddress to the host and use this option to disable
// discovery from identify.
func () Option {
	return func( *Config) error {
		.DisableIdentifyAddressDiscovery = true
		return nil
	}
}

// EnableAutoNATv2 enables autonat v2
func () Option {
	return func( *Config) error {
		.EnableAutoNATv2 = true
		return nil
	}
}

// UDPBlackHoleSuccessCounter configures libp2p to use f as the black hole filter for UDP addrs
func ( *swarm.BlackHoleSuccessCounter) Option {
	return func( *Config) error {
		.UDPBlackHoleSuccessCounter = 
		.CustomUDPBlackHoleSuccessCounter = true
		return nil
	}
}

// IPv6BlackHoleSuccessCounter configures libp2p to use f as the black hole filter for IPv6 addrs
func ( *swarm.BlackHoleSuccessCounter) Option {
	return func( *Config) error {
		.IPv6BlackHoleSuccessCounter = 
		.CustomIPv6BlackHoleSuccessCounter = true
		return nil
	}
}

// WithFxOption adds a user provided fx.Option to the libp2p constructor.
// Experimental: This option is subject to change or removal.
func ( ...fx.Option) Option {
	return func( *Config) error {
		.UserFxOptions = append(.UserFxOptions, ...)
		return nil
	}
}

// ShareTCPListener shares the same listen address between TCP and Websocket
// transports. This lets both transports use the same TCP port.
//
// Currently this behavior is Opt-in. In a future release this will be the
// default, and this option will be removed.
func () Option {
	return func( *Config) error {
		.ShareTCPListener = true
		return nil
	}
}