options.go 13.6 KB
Newer Older
tavit ohanian's avatar
tavit ohanian committed
1
package p2p
Steven Allen's avatar
Steven Allen committed
2

tavit ohanian's avatar
tavit ohanian committed
3
// This file contains all p2p configuration options (except the defaults,
Vasco Santos's avatar
Vasco Santos committed
4
// those are in defaults.go).
Steven Allen's avatar
Steven Allen committed
5 6

import (
7
	"errors"
Steven Allen's avatar
Steven Allen committed
8 9
	"fmt"
	"net"
Will Scott's avatar
Will Scott committed
10
	"time"
Steven Allen's avatar
Steven Allen committed
11

tavit ohanian's avatar
tavit ohanian committed
12 13 14 15 16 17 18 19
	circuit "gitlab.dms3.io/p2p/go-p2p-circuit"
	"gitlab.dms3.io/p2p/go-p2p-core/connmgr"
	"gitlab.dms3.io/p2p/go-p2p-core/crypto"
	"gitlab.dms3.io/p2p/go-p2p-core/metrics"
	"gitlab.dms3.io/p2p/go-p2p-core/network"
	"gitlab.dms3.io/p2p/go-p2p-core/peer"
	"gitlab.dms3.io/p2p/go-p2p-core/peerstore"
	"gitlab.dms3.io/p2p/go-p2p-core/pnet"
20

tavit ohanian's avatar
tavit ohanian committed
21 22 23
	"gitlab.dms3.io/p2p/go-p2p/config"
	bhost "gitlab.dms3.io/p2p/go-p2p/p2p/host/basic"
	autorelay "gitlab.dms3.io/p2p/go-p2p/p2p/host/relay"
Steven Allen's avatar
Steven Allen committed
24

25
	ma "gitlab.dms3.io/mf/go-multiaddr"
Steven Allen's avatar
Steven Allen committed
26 27
)

tavit ohanian's avatar
tavit ohanian committed
28
// ListenAddrStrings configures p2p to listen on the given (unparsed)
Steven Allen's avatar
Steven Allen committed
29 30 31 32 33 34 35 36 37 38 39 40 41 42
// addresses.
func ListenAddrStrings(s ...string) Option {
	return func(cfg *Config) error {
		for _, addrstr := range s {
			a, err := ma.NewMultiaddr(addrstr)
			if err != nil {
				return err
			}
			cfg.ListenAddrs = append(cfg.ListenAddrs, a)
		}
		return nil
	}
}

tavit ohanian's avatar
tavit ohanian committed
43
// ListenAddrs configures p2p to listen on the given addresses.
Steven Allen's avatar
Steven Allen committed
44 45 46 47 48 49 50
func ListenAddrs(addrs ...ma.Multiaddr) Option {
	return func(cfg *Config) error {
		cfg.ListenAddrs = append(cfg.ListenAddrs, addrs...)
		return nil
	}
}

tavit ohanian's avatar
tavit ohanian committed
51
// Security configures p2p to use the given security transport (or transport
Steven Allen's avatar
Steven Allen committed
52 53 54 55 56
// constructor).
//
// Name is the protocol name.
//
// The transport can be a constructed security.Transport or a function taking
tavit ohanian's avatar
tavit ohanian committed
57
// any subset of this p2p node's:
Steven Allen's avatar
Steven Allen committed
58 59 60 61 62 63 64 65 66 67 68 69 70 71
// * Public key
// * Private key
// * Peer ID
// * Host
// * Network
// * Peerstore
func Security(name string, tpt interface{}) Option {
	stpt, err := config.SecurityConstructor(tpt)
	err = traceError(err, 1)
	return func(cfg *Config) error {
		if err != nil {
			return err
		}
		if cfg.Insecure {
tavit ohanian's avatar
tavit ohanian committed
72
			return fmt.Errorf("cannot use security transports with an insecure p2p configuration")
Steven Allen's avatar
Steven Allen committed
73 74 75 76 77 78 79 80 81 82
		}
		cfg.SecurityTransports = append(cfg.SecurityTransports, config.MsSecC{SecC: stpt, ID: name})
		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(cfg *Config) error {
	if len(cfg.SecurityTransports) > 0 {
tavit ohanian's avatar
tavit ohanian committed
83
		return fmt.Errorf("cannot use security transports with an insecure p2p configuration")
Steven Allen's avatar
Steven Allen committed
84 85 86 87 88
	}
	cfg.Insecure = true
	return nil
}

tavit ohanian's avatar
tavit ohanian committed
89
// Muxer configures p2p to use the given stream multiplexer (or stream
Steven Allen's avatar
Steven Allen committed
90 91 92 93 94
// multiplexer constructor).
//
// Name is the protocol name.
//
// The transport can be a constructed mux.Transport or a function taking any
tavit ohanian's avatar
tavit ohanian committed
95
// subset of this p2p node's:
Steven Allen's avatar
Steven Allen committed
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
// * Peer ID
// * Host
// * Network
// * Peerstore
func Muxer(name string, tpt interface{}) Option {
	mtpt, err := config.MuxerConstructor(tpt)
	err = traceError(err, 1)
	return func(cfg *Config) error {
		if err != nil {
			return err
		}
		cfg.Muxers = append(cfg.Muxers, config.MsMuxC{MuxC: mtpt, ID: name})
		return nil
	}
}

tavit ohanian's avatar
tavit ohanian committed
112
// Transport configures p2p to use the given transport (or transport
Steven Allen's avatar
Steven Allen committed
113 114 115
// constructor).
//
// The transport can be a constructed transport.Transport or a function taking
tavit ohanian's avatar
tavit ohanian committed
116
// any subset of this p2p node's:
Steven Allen's avatar
Steven Allen committed
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
// * 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 Transport(tpt interface{}) Option {
	tptc, err := config.TransportConstructor(tpt)
	err = traceError(err, 1)
	return func(cfg *Config) error {
		if err != nil {
			return err
		}
		cfg.Transports = append(cfg.Transports, tptc)
		return nil
	}
}

tavit ohanian's avatar
tavit ohanian committed
139
// Peerstore configures p2p to use the given peerstore.
140
func Peerstore(ps peerstore.Peerstore) Option {
Steven Allen's avatar
Steven Allen committed
141 142 143 144 145 146 147 148 149 150
	return func(cfg *Config) error {
		if cfg.Peerstore != nil {
			return fmt.Errorf("cannot specify multiple peerstore options")
		}

		cfg.Peerstore = ps
		return nil
	}
}

tavit ohanian's avatar
tavit ohanian committed
151
// PrivateNetwork configures p2p to use the given private network protector.
152
func PrivateNetwork(psk pnet.PSK) Option {
Steven Allen's avatar
Steven Allen committed
153
	return func(cfg *Config) error {
154
		if cfg.PSK != nil {
Steven Allen's avatar
Steven Allen committed
155 156 157
			return fmt.Errorf("cannot specify multiple private network options")
		}

158
		cfg.PSK = psk
Steven Allen's avatar
Steven Allen committed
159 160 161 162
		return nil
	}
}

tavit ohanian's avatar
tavit ohanian committed
163
// BandwidthReporter configures p2p to use the given bandwidth reporter.
Steven Allen's avatar
Steven Allen committed
164 165 166 167 168 169 170 171 172 173 174
func BandwidthReporter(rep metrics.Reporter) Option {
	return func(cfg *Config) error {
		if cfg.Reporter != nil {
			return fmt.Errorf("cannot specify multiple bandwidth reporter options")
		}

		cfg.Reporter = rep
		return nil
	}
}

tavit ohanian's avatar
tavit ohanian committed
175
// Identity configures p2p to use the given private key to identify itself.
Steven Allen's avatar
Steven Allen committed
176 177 178 179 180 181 182 183 184 185 186
func Identity(sk crypto.PrivKey) Option {
	return func(cfg *Config) error {
		if cfg.PeerKey != nil {
			return fmt.Errorf("cannot specify multiple identities")
		}

		cfg.PeerKey = sk
		return nil
	}
}

tavit ohanian's avatar
tavit ohanian committed
187
// ConnectionManager configures p2p to use the given connection manager.
188
func ConnectionManager(connman connmgr.ConnManager) Option {
Steven Allen's avatar
Steven Allen committed
189 190 191 192 193 194 195 196 197
	return func(cfg *Config) error {
		if cfg.ConnManager != nil {
			return fmt.Errorf("cannot specify multiple connection managers")
		}
		cfg.ConnManager = connman
		return nil
	}
}

tavit ohanian's avatar
tavit ohanian committed
198
// AddrsFactory configures p2p to use the given address factory.
Steven Allen's avatar
Steven Allen committed
199 200 201 202 203 204 205 206 207 208
func AddrsFactory(factory config.AddrsFactory) Option {
	return func(cfg *Config) error {
		if cfg.AddrsFactory != nil {
			return fmt.Errorf("cannot specify multiple address factories")
		}
		cfg.AddrsFactory = factory
		return nil
	}
}

tavit ohanian's avatar
tavit ohanian committed
209 210
// EnableRelay configures p2p to enable the relay transport with
// configuration options. By default, this option only configures p2p to
Steven Allen's avatar
Steven Allen committed
211 212 213 214
// accept inbound connections from relays and make outbound connections
// _through_ relays when requested by the remote peer. (default: enabled)
//
// To _act_ as a relay, pass the circuit.OptHop option.
Steven Allen's avatar
Steven Allen committed
215 216
func EnableRelay(options ...circuit.RelayOpt) Option {
	return func(cfg *Config) error {
vyzo's avatar
vyzo committed
217
		cfg.RelayCustom = true
Steven Allen's avatar
Steven Allen committed
218 219 220 221 222 223
		cfg.Relay = true
		cfg.RelayOpts = options
		return nil
	}
}

tavit ohanian's avatar
tavit ohanian committed
224
// DisableRelay configures p2p to disable the relay transport.
vyzo's avatar
vyzo committed
225 226 227 228 229 230 231 232
func DisableRelay() Option {
	return func(cfg *Config) error {
		cfg.RelayCustom = true
		cfg.Relay = false
		return nil
	}
}

tavit ohanian's avatar
tavit ohanian committed
233
// EnableAutoRelay configures p2p to enable the AutoRelay subsystem.
234 235 236 237
//
// Dependencies:
//  * Relay (enabled by default)
//  * Routing (to find relays), or StaticRelays/DefaultStaticRelays.
Steven Allen's avatar
Steven Allen committed
238 239 240
//
// This subsystem performs two functions:
//
tavit ohanian's avatar
tavit ohanian committed
241
// 1. When this p2p node is configured to act as a relay "hop"
Steven Allen's avatar
Steven Allen committed
242 243
//    (circuit.OptHop is passed to EnableRelay), this node will advertise itself
//    as a public relay using the provided routing system.
tavit ohanian's avatar
tavit ohanian committed
244
// 2. When this p2p node is _not_ configured as a relay "hop", it will
vyzo's avatar
vyzo committed
245
//    automatically detect if it is unreachable (e.g., behind a NAT). If so, it will
Steven Allen's avatar
Steven Allen committed
246
//    find, configure, and announce a set of public relays.
vyzo's avatar
vyzo committed
247 248 249 250 251 252 253
func EnableAutoRelay() Option {
	return func(cfg *Config) error {
		cfg.EnableAutoRelay = true
		return nil
	}
}

254 255
// StaticRelays configures known relays for autorelay; when this option is enabled
// then the system will use the configured relays instead of querying the DHT to
Vasco Santos's avatar
Vasco Santos committed
256
// discover relays.
257 258
func StaticRelays(relays []peer.AddrInfo) Option {
	return func(cfg *Config) error {
259
		cfg.StaticRelays = append(cfg.StaticRelays, relays...)
260 261 262 263
		return nil
	}
}

Vasco Santos's avatar
Vasco Santos committed
264
// DefaultStaticRelays configures the static relays to use the known PL-operated relays.
265
func DefaultStaticRelays() Option {
266
	return func(cfg *Config) error {
267
		for _, addr := range autorelay.DefaultRelays {
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
			a, err := ma.NewMultiaddr(addr)
			if err != nil {
				return err
			}
			pi, err := peer.AddrInfoFromP2pAddr(a)
			if err != nil {
				return err
			}
			cfg.StaticRelays = append(cfg.StaticRelays, *pi)
		}

		return nil
	}
}

283 284 285
// ForceReachabilityPublic overrides automatic reachability detection in the AutoNAT subsystem,
// forcing the local node to believe it is reachable externally.
func ForceReachabilityPublic() Option {
286
	return func(cfg *Config) error {
Will Scott's avatar
Will Scott committed
287 288
		public := network.Reachability(network.ReachabilityPublic)
		cfg.AutoNATConfig.ForceReachability = &public
289 290 291 292 293 294 295 296
		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 ForceReachabilityPrivate() Option {
	return func(cfg *Config) error {
Will Scott's avatar
Will Scott committed
297 298
		private := network.Reachability(network.ReachabilityPrivate)
		cfg.AutoNATConfig.ForceReachability = &private
299 300 301 302
		return nil
	}
}

tavit ohanian's avatar
tavit ohanian committed
303
// EnableNATService configures p2p to provide a service to peers for determining
304 305 306 307
// 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 EnableNATService() Option {
	return func(cfg *Config) error {
Will Scott's avatar
Will Scott committed
308
		cfg.AutoNATConfig.EnableService = true
309 310 311 312
		return nil
	}
}

Will Scott's avatar
Will Scott committed
313
// AutoNATServiceRateLimit changes the default rate limiting configured in helping
314 315 316
// 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.
Will Scott's avatar
Will Scott committed
317
func AutoNATServiceRateLimit(global, perPeer int, interval time.Duration) Option {
318
	return func(cfg *Config) error {
Will Scott's avatar
Will Scott committed
319 320 321
		cfg.AutoNATConfig.ThrottleGlobalLimit = global
		cfg.AutoNATConfig.ThrottlePeerLimit = perPeer
		cfg.AutoNATConfig.ThrottleInterval = interval
322 323 324 325
		return nil
	}
}

tavit ohanian's avatar
tavit ohanian committed
326
// FilterAddresses configures p2p to never dial nor accept connections from
Alex Browne's avatar
Alex Browne committed
327 328
// the given addresses. FilterAddresses should be used for cases where the
// addresses you want to deny are known ahead of time.
329 330 331 332 333
//
// Note: Using Filter + FilterAddresses at the same time is fine, but you cannot
// configure a both ConnectionGater and filtered addresses.
//
// Deprecated: Please use ConnectionGater() instead.
Steven Allen's avatar
Steven Allen committed
334 335
func FilterAddresses(addrs ...*net.IPNet) Option {
	return func(cfg *Config) error {
336
		var f *filtersConnectionGater
337 338

		// preserve backwards compatibility.
339
		// if we have a connection gater, try to cast it to a *filtersConnectionGater.
340 341
		if cfg.ConnectionGater != nil {
			var ok bool
342
			if f, ok = cfg.ConnectionGater.(*filtersConnectionGater); !ok {
343 344 345
				return errors.New("cannot configure both Filters and Connection Gater. " +
					"\n Please consider configuring just a ConnectionGater instead.")
			}
Steven Allen's avatar
Steven Allen committed
346
		}
347 348

		if f == nil {
349
			f = (*filtersConnectionGater)(ma.NewFilters())
350 351 352
			cfg.ConnectionGater = f
		}

Steven Allen's avatar
Steven Allen committed
353
		for _, addr := range addrs {
354
			(*ma.Filters)(f).AddFilter(*addr, ma.ActionDeny)
Steven Allen's avatar
Steven Allen committed
355
		}
356

Steven Allen's avatar
Steven Allen committed
357 358 359 360
		return nil
	}
}

tavit ohanian's avatar
tavit ohanian committed
361
// Filters configures p2p to use the given filters for accepting/denying
Vasco Santos's avatar
Vasco Santos committed
362
// certain addresses. Filters offers more control and should be used when the
Alex Browne's avatar
Alex Browne committed
363 364
// addresses you want to accept/deny are not known ahead of time and can
// dynamically change.
365 366 367 368 369 370 371 372 373 374 375 376
//
// Note: You cannot configure both a ConnectionGater and a Filter at the same
// time. Under the hood, the Filters object is converted to a ConnectionGater.
//
// Deprecated: use ConnectionGater() instead.
func Filters(filters *ma.Filters) Option {
	return func(cfg *Config) error {
		if cfg.ConnectionGater != nil {
			return errors.New("cannot configure both Filters and Connection Gater. " +
				"\n Please consider configuring just a ConnectionGater instead.")

		}
377
		cfg.ConnectionGater = (*filtersConnectionGater)(filters)
378 379 380 381
		return nil
	}
}

tavit ohanian's avatar
tavit ohanian committed
382
// ConnectionGater configures p2p to use the given ConnectionGater
383 384 385
// to actively reject inbound/outbound connections based on the lifecycle stage
// of the connection.
//
tavit ohanian's avatar
tavit ohanian committed
386
// For more information, refer to go-p2p-core.ConnectionGater.
387
func ConnectionGater(cg connmgr.ConnectionGater) Option {
Alex Browne's avatar
Alex Browne committed
388
	return func(cfg *Config) error {
389 390 391 392
		if cfg.ConnectionGater != nil {
			return errors.New("cannot configure multiple connection gaters, or cannot configure both Filters and ConnectionGater")
		}
		cfg.ConnectionGater = cg
Alex Browne's avatar
Alex Browne committed
393 394 395 396
		return nil
	}
}

tavit ohanian's avatar
tavit ohanian committed
397
// NATPortMap configures p2p to use the default NATManager. The default
Steven Allen's avatar
Steven Allen committed
398 399 400 401 402
// NATManager will attempt to open a port in your network's firewall using UPnP.
func NATPortMap() Option {
	return NATManager(bhost.NewNATManager)
}

tavit ohanian's avatar
tavit ohanian committed
403 404
// NATManager will configure p2p to use the requested NATManager. This
// function should be passed a NATManager *constructor* that takes a p2p Network.
Steven Allen's avatar
Steven Allen committed
405 406 407 408 409 410 411 412 413
func NATManager(nm config.NATManagerC) Option {
	return func(cfg *Config) error {
		if cfg.NATManager != nil {
			return fmt.Errorf("cannot specify multiple NATManagers")
		}
		cfg.NATManager = nm
		return nil
	}
}
414

tavit ohanian's avatar
tavit ohanian committed
415
// Ping will configure p2p to support the ping service; enable by default.
416 417
func Ping(enable bool) Option {
	return func(cfg *Config) error {
418
		cfg.DisablePing = !enable
419 420 421 422
		return nil
	}
}

tavit ohanian's avatar
tavit ohanian committed
423
// Routing will configure p2p to use routing.
424 425 426
func Routing(rt config.RoutingC) Option {
	return func(cfg *Config) error {
		if cfg.Routing != nil {
vyzo's avatar
vyzo committed
427
			return fmt.Errorf("cannot specify multiple routing options")
428 429 430 431 432 433
		}
		cfg.Routing = rt
		return nil
	}
}

tavit ohanian's avatar
tavit ohanian committed
434
// NoListenAddrs will configure p2p to not listen by default.
435
//
tavit ohanian's avatar
tavit ohanian committed
436
// This will both clear any configured listen addrs and prevent p2p from
vyzo's avatar
vyzo committed
437 438
// applying the default listen address option. It also disables relay, unless the
// user explicitly specifies with an option, as the transport creates an implicit
vyzo's avatar
vyzo committed
439
// listen address that would make the node dialable through any relay it was connected to.
440
var NoListenAddrs = func(cfg *Config) error {
441
	cfg.ListenAddrs = []ma.Multiaddr{}
vyzo's avatar
vyzo committed
442 443 444 445
	if !cfg.RelayCustom {
		cfg.RelayCustom = true
		cfg.Relay = false
	}
446 447 448
	return nil
}

tavit ohanian's avatar
tavit ohanian committed
449
// NoTransports will configure p2p to not enable any transports.
450
//
tavit ohanian's avatar
tavit ohanian committed
451 452
// This will both clear any configured transports (specified in prior p2p
// options) and prevent p2p from applying the default transports.
453 454 455 456
var NoTransports = func(cfg *Config) error {
	cfg.Transports = []config.TptC{}
	return nil
}
457

tavit ohanian's avatar
tavit ohanian committed
458
// UserAgent sets the p2p user-agent sent along with the identify protocol
459 460 461 462 463 464
func UserAgent(userAgent string) Option {
	return func(cfg *Config) error {
		cfg.UserAgent = userAgent
		return nil
	}
}