Browse Source

Merge pull request #702 from libp2p/feat/user-agent

better user-agent handling
pull/717/head
Steven Allen 5 years ago
committed by GitHub
parent
commit
51950e41c2
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .travis.yml
  2. 4
      README.md
  3. 7
      config/config.go
  4. 8
      options.go
  5. 19
      p2p/host/basic/basic_host.go
  6. 43
      p2p/protocol/identify/id.go
  7. 38
      p2p/protocol/identify/id_test.go
  8. 15
      p2p/protocol/identify/opts.go

2
.travis.yml

@ -4,7 +4,7 @@ os:
language: go
go:
- 1.11.x
- 1.12.x
env:
global:

4
README.md

@ -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.:

7
config/config.go

@ -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
@ -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 {

8
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
}
}

19
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

43
p2p/protocol/identify/id.go

@ -2,6 +2,8 @@ package identify
import (
"context"
"fmt"
"runtime/debug"
"sync"
"time"
@ -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
@ -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
@ -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),
@ -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
}

38
p2p/protocol/identify/id_test.go

@ -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"
@ -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
p2p/protocol/identify/opts.go

@ -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
}
}
Loading…
Cancel
Save