cmd/torrent/main.go | 9 +++++++++ config.go | 11 ++++++----- tracker/http/http.go | 9 ++++++++- version/version.go | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/cmd/torrent/main.go b/cmd/torrent/main.go index bd5d6f7a80497f2a9c0e005f1dc08933bff1b752..61fd2ab2791cafc5ec80d2f5249181b02fe82f5e 100644 --- a/cmd/torrent/main.go +++ b/cmd/torrent/main.go @@ -18,6 +18,7 @@ "github.com/alexflint/go-arg" "github.com/anacrolix/envpprof" "github.com/anacrolix/missinggo/v2" "github.com/anacrolix/torrent/bencode" + "github.com/anacrolix/torrent/version" "github.com/davecgh/go-spew/spew" "github.com/dustin/go-humanize" "golang.org/x/xerrors" @@ -164,7 +165,10 @@ *DownloadCmd `arg:"subcommand:download"` *ListFilesCmd `arg:"subcommand:list-files"` *SpewBencodingCmd `arg:"subcommand:spew-bencoding"` *AnnounceCmd `arg:"subcommand:announce"` + *VersionCmd `arg:"subcommand:version"` } + +type VersionCmd struct{} type SpewBencodingCmd struct{} @@ -267,6 +271,11 @@ return fmt.Errorf("decoding message index %d: %w", i, err) } spew.Dump(v) } + return nil + case flags.VersionCmd != nil: + fmt.Printf("HTTP User-Agent: %q\n", version.DefaultHttpUserAgent) + fmt.Printf("Torrent client version: %q\n", version.DefaultExtendedHandshakeClientVersion) + fmt.Printf("Torrent version prefix: %q\n", version.DefaultBep20Prefix) return nil default: p.Fail(fmt.Sprintf("unexpected subcommand: %v", p.Subcommand())) diff --git a/config.go b/config.go index 03d85c06eb4d0d53cc4ab68f20b91acde85382b8..c7720a0d5ea9f0191e8f7dd5284dbde6d693679a 100644 --- a/config.go +++ b/config.go @@ -9,8 +9,9 @@ "github.com/anacrolix/dht/v2" "github.com/anacrolix/dht/v2/krpc" "github.com/anacrolix/log" + "github.com/anacrolix/missinggo/expect" "github.com/anacrolix/missinggo/v2" - "github.com/anacrolix/missinggo/expect" + "github.com/anacrolix/torrent/version" "golang.org/x/time/rate" "github.com/anacrolix/torrent/iplist" @@ -157,10 +158,10 @@ } func NewDefaultClientConfig() *ClientConfig { cc := &ClientConfig{ - HTTPUserAgent: "Go-Torrent/1.0", - ExtendedHandshakeClientVersion: "go.torrent dev 20181121", - Bep20: "-GT0002-", - UpnpID: "anacrolix/torrent", + HTTPUserAgent: version.DefaultHttpUserAgent, + ExtendedHandshakeClientVersion: version.DefaultExtendedHandshakeClientVersion, + Bep20: version.DefaultBep20Prefix, + UpnpID: version.DefaultUpnpId, NominalDialTimeout: 20 * time.Second, MinDialTimeout: 3 * time.Second, EstablishedConnsPerTorrent: 50, diff --git a/tracker/http/http.go b/tracker/http/http.go index c4f2fac4463e3a679240e94b98088286f0555b9b..15306ca974eaa0656318ab4eab533dbd9ad4f35c 100644 --- a/tracker/http/http.go +++ b/tracker/http/http.go @@ -16,6 +16,7 @@ "github.com/anacrolix/missinggo/httptoo" "github.com/anacrolix/torrent/bencode" "github.com/anacrolix/torrent/tracker/shared" "github.com/anacrolix/torrent/tracker/udp" + "github.com/anacrolix/torrent/version" ) var vars = expvar.NewMap("tracker/http") @@ -76,7 +77,13 @@ func (cl Client) Announce(ctx context.Context, ar AnnounceRequest, opt AnnounceOpt) (ret AnnounceResponse, err error) { _url := httptoo.CopyURL(cl.url_) setAnnounceParams(_url, &ar, opt) req, err := http.NewRequestWithContext(ctx, http.MethodGet, _url.String(), nil) - req.Header.Set("User-Agent", opt.UserAgent) + userAgent := opt.UserAgent + if userAgent == "" { + userAgent = version.DefaultHttpUserAgent + } + if userAgent != "" { + req.Header.Set("User-Agent", userAgent) + } req.Host = opt.HostHeader resp, err := cl.hc.Do(req) if err != nil { diff --git a/version/version.go b/version/version.go new file mode 100644 index 0000000000000000000000000000000000000000..3d3ae550f89c3c1fe09f14d61f17a10269ae4c6a --- /dev/null +++ b/version/version.go @@ -0,0 +1,58 @@ +// Package version provides default versions, user-agents etc. for client identification. +package version + +import ( + "fmt" + "reflect" + "runtime/debug" +) + +var ( + DefaultExtendedHandshakeClientVersion string + // This should be updated when client behaviour changes in a way that other peers could care + // about. + DefaultBep20Prefix = "-GT0003-" + DefaultHttpUserAgent string + DefaultUpnpId string +) + +func init() { + const ( + longNamespace = "anacrolix" + longPackageName = "torrent" + ) + type Newtype struct{} + var newtype Newtype + thisPkg := reflect.TypeOf(newtype).PkgPath() + var ( + mainPath = "unknown" + mainVersion = "unknown" + torrentVersion = "unknown" + ) + if buildInfo, ok := debug.ReadBuildInfo(); ok { + mainPath = buildInfo.Main.Path + mainVersion = buildInfo.Main.Version + // Note that if the main module is the same as this module, we get a version of "(devel)". + for _, dep := range append(buildInfo.Deps, &buildInfo.Main) { + if dep.Path == thisPkg { + torrentVersion = dep.Version + } + } + } + DefaultExtendedHandshakeClientVersion = fmt.Sprintf( + "%v %v (%v/%v %v)", + mainPath, + mainVersion, + longNamespace, + longPackageName, + torrentVersion, + ) + DefaultUpnpId = fmt.Sprintf("%v %v", mainPath, mainVersion) + // Per https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent#library_and_net_tool_ua_strings + DefaultHttpUserAgent = fmt.Sprintf( + "%v-%v/%v", + longNamespace, + longPackageName, + torrentVersion, + ) +}