diff --git a/config/config.go b/config/config.go index 3bb51bf1f7..01bcb6af42 100644 --- a/config/config.go +++ b/config/config.go @@ -44,6 +44,8 @@ type RoutingC func(host.Host) (routing.PeerRouting, error) // This is *not* a stable interface. Use the options defined in the root // package. type Config struct { + UserAgent string + PeerKey crypto.PrivKey Transports []TptC diff --git a/options.go b/options.go index 6d310f1aa3..c5ef639ebe 100644 --- a/options.go +++ b/options.go @@ -319,3 +319,11 @@ var NoTransports = func(cfg *Config) error { cfg.Transports = []config.TptC{} return nil } + +// UserAgent sets the libp2p user-agent sent along with the identify protocol +func UserAgent(userAgent string) Option { + return func(cfg *Config) error { + cfg.UserAgent = userAgent + return nil + } +} diff --git a/p2p/host/basic/basic_host.go b/p2p/host/basic/basic_host.go index 2d965bdae1..92946c5d7c 100644 --- a/p2p/host/basic/basic_host.go +++ b/p2p/host/basic/basic_host.go @@ -100,10 +100,6 @@ type HostOpts struct { // If below 0, timeouts on streams will be deactivated. NegotiationTimeout time.Duration - // IdentifyService holds an implementation of the /ipfs/id/ protocol. - // If omitted, a new *identify.IDService will be used. - IdentifyService *identify.IDService - // AddrsFactory holds a function which can be used to override or filter the result of Addrs. // If omitted, there's no override or filtering, and the results of Addrs and AllAddrs are the same. AddrsFactory AddrsFactory @@ -121,6 +117,9 @@ type HostOpts struct { // EnablePing indicates whether to instantiate the ping service EnablePing bool + + // UserAgent sets the user-agent for the host. Defaults to ClientVersion. + UserAgent string } // NewHost constructs a new *BasicHost and activates it by attaching its stream and connection handlers to the given inet.Network. @@ -154,12 +153,12 @@ func NewHost(ctx context.Context, net network.Network, opts *HostOpts) (*BasicHo h.mux = opts.MultistreamMuxer } - if opts.IdentifyService != nil { - h.ids = opts.IdentifyService - } else { - // we can't set this as a default above because it depends on the *BasicHost. - h.ids = identify.NewIDService(goprocessctx.WithProcessClosing(ctx, h.proc), h) - } + // we can't set this as a default above because it depends on the *BasicHost. + h.ids = identify.NewIDService( + goprocessctx.WithProcessClosing(ctx, h.proc), + h, + identify.UserAgent(opts.UserAgent), + ) if uint64(opts.NegotiationTimeout) != 0 { h.negtimeout = opts.NegotiationTimeout diff --git a/p2p/protocol/identify/id.go b/p2p/protocol/identify/id.go index 1fa2bcf1f6..39390d1f9d 100644 --- a/p2p/protocol/identify/id.go +++ b/p2p/protocol/identify/id.go @@ -47,7 +47,8 @@ const transientTTL = 10 * time.Second // * Our IPFS Agent Version // * Our public Listen Addresses type IDService struct { - Host host.Host + Host host.Host + UserAgent string ctx context.Context @@ -70,9 +71,21 @@ type IDService struct { // NewIDService constructs a new *IDService and activates it by // attaching its stream handler to the given host.Host. -func NewIDService(ctx context.Context, h host.Host) *IDService { +func NewIDService(ctx context.Context, h host.Host, opts ...Option) *IDService { + var cfg config + for _, opt := range opts { + opt(&cfg) + } + + userAgent := ClientVersion + if cfg.userAgent != "" { + userAgent = cfg.userAgent + } + s := &IDService{ - Host: h, + Host: h, + UserAgent: userAgent, + ctx: ctx, currid: make(map[network.Conn]chan struct{}), observedAddrs: NewObservedAddrSet(ctx), @@ -306,7 +319,7 @@ func (ids *IDService) populateMessage(mes *pb.Identify, c network.Conn) { // set protocol versions pv := LibP2PVersion - av := ClientVersion + av := ids.UserAgent mes.ProtocolVersion = &pv mes.AgentVersion = &av } diff --git a/p2p/protocol/identify/opts.go b/p2p/protocol/identify/opts.go new file mode 100644 index 0000000000..94be5b786c --- /dev/null +++ b/p2p/protocol/identify/opts.go @@ -0,0 +1,13 @@ +package identify + +type config struct { + userAgent string +} + +type Option func(*config) + +func UserAgent(ua string) Option { + return func(cfg *config) { + cfg.userAgent = ua + } +}