Skip to content

Commit

Permalink
Merge pull request #702 from libp2p/feat/user-agent
Browse files Browse the repository at this point in the history
better user-agent handling
  • Loading branch information
Stebalien authored Aug 28, 2019
2 parents a3c39ad + 9cf6af4 commit 51950e4
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 18 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ os:
language: go

go:
- 1.11.x
- 1.12.x

env:
global:
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ libp2p is the product of a long, and arduous quest of understanding -- a deep di
## Usage

This repository (`go-libp2p`) serves as the entrypoint to the universe of modules that compose the Go implementation of the libp2p stack.
This repository (`go-libp2p`) serves as the entrypoint to the universe of modules that compose the Go implementation of the libp2p stack. Libp2p requires go 1.12+.

We mainly use [Go modules](https://github.com/golang/go/wiki/Modules) for our dependency and release management (and thus require go >= 1.11). In order to get the best developer experience, we recommend you do too. Otherwise, you may ocassionally encounter a breaking build as you'll be running off master (which, by definition, is not guaranteed to be stable).
We mainly use [Go modules](https://github.com/golang/go/wiki/Modules) for our dependency and release management (and thus require go >= 1.12+). In order to get the best developer experience, we recommend you do too. Otherwise, you may ocassionally encounter a breaking build as you'll be running off master (which, by definition, is not guaranteed to be stable).

You can start using go-libp2p in your Go application simply by adding imports from our repos, e.g.:

Expand Down
7 changes: 7 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ 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 is the identifier this node will send to other peers when
// identifying itself, e.g. via the identify protocol.
//
// Set it via the UserAgent option function.
UserAgent string

PeerKey crypto.PrivKey

Transports []TptC
Expand Down Expand Up @@ -118,6 +124,7 @@ func (cfg *Config) NewNode(ctx context.Context) (host.Host, error) {
AddrsFactory: cfg.AddrsFactory,
NATManager: cfg.NATManager,
EnablePing: !cfg.DisablePing,
UserAgent: cfg.UserAgent,
})

if err != nil {
Expand Down
8 changes: 8 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
19 changes: 9 additions & 10 deletions p2p/host/basic/basic_host.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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
Expand Down
43 changes: 38 additions & 5 deletions p2p/protocol/identify/id.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package identify

import (
"context"
"fmt"
"runtime/debug"
"sync"
"time"

Expand Down Expand Up @@ -31,9 +33,27 @@ const ID = "/ipfs/id/1.0.0"

// LibP2PVersion holds the current protocol version for a client running this code
// TODO(jbenet): fix the versioning mess.
// XXX: Don't change this till 2020. You'll break all go-ipfs versions prior to
// 0.4.17 which asserted an exact version match.
const LibP2PVersion = "ipfs/0.1.0"

var ClientVersion = "go-libp2p/3.3.4"
// ClientVersion is the default user agent.
//
// Deprecated: Set this with the UserAgent option.
var ClientVersion = "github.com/libp2p/go-libp2p"

func init() {
bi, ok := debug.ReadBuildInfo()
if !ok {
return
}
version := bi.Main.Version
if version == "(devel)" {
ClientVersion = bi.Main.Path
} else {
ClientVersion = fmt.Sprintf("%s@%s", bi.Main.Path, bi.Main.Version)
}
}

// transientTTL is a short ttl for invalidated previously connected addrs
const transientTTL = 10 * time.Second
Expand All @@ -47,7 +67,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

Expand All @@ -70,9 +91,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),
Expand Down Expand Up @@ -306,7 +339,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
}
Expand Down
38 changes: 38 additions & 0 deletions p2p/protocol/identify/id_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"time"

"github.com/libp2p/go-eventbus"
libp2p "github.com/libp2p/go-libp2p"
ic "github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/event"
"github.com/libp2p/go-libp2p-core/helpers"
Expand Down Expand Up @@ -367,3 +368,40 @@ func TestIdentifyDeltaWhileIdentifyingConn(t *testing.T) {
t.Fatalf("timed out while waiting for an event for the protocol changes in h2")
}
}

func TestUserAgent(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

h1, err := libp2p.New(
ctx,
libp2p.UserAgent("foo"),
libp2p.ListenAddrStrings("/ip4/127.0.0.1/tcp/0"),
)
if err != nil {
t.Fatal(err)
}
defer h1.Close()

h2, err := libp2p.New(
ctx,
libp2p.UserAgent("bar"),
libp2p.ListenAddrStrings("/ip4/127.0.0.1/tcp/0"),
)
if err != nil {
t.Fatal(err)
}
defer h2.Close()

err = h1.Connect(ctx, peer.AddrInfo{ID: h2.ID(), Addrs: h2.Addrs()})
if err != nil {
t.Fatal(err)
}
av, err := h1.Peerstore().Get(h2.ID(), "AgentVersion")
if err != nil {
t.Fatal(err)
}
if ver, ok := av.(string); !ok || ver != "bar" {
t.Errorf("expected agent version %q, got %q", "bar", av)
}
}
15 changes: 15 additions & 0 deletions p2p/protocol/identify/opts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package identify

type config struct {
userAgent string
}

// Option is an option function for identify.
type Option func(*config)

// UserAgent sets the user agent this node will identify itself with to peers.
func UserAgent(ua string) Option {
return func(cfg *config) {
cfg.userAgent = ua
}
}

0 comments on commit 51950e4

Please sign in to comment.