From 5501f994cac03f329f692ffb7fc804a94ca8fa2b Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Wed, 2 Nov 2022 23:03:25 +1100 Subject: [PATCH] Move a bunch of stuff into subpackages The core package is very large now, and often only parts of it are needed. --- dialer.go | 34 +++------------- dialer/dialer.go | 34 ++++++++++++++++ metainfo/hash.go | 76 +++--------------------------------- metainfo/info.go | 2 +- misc.go | 6 ++- peerid.go | 13 +------ socket.go | 3 +- test/unix_test.go | 3 +- types/infohash/infohash.go | 80 ++++++++++++++++++++++++++++++++++++++ types/peerid.go | 14 +++++++ 10 files changed, 151 insertions(+), 114 deletions(-) create mode 100644 dialer/dialer.go create mode 100644 types/infohash/infohash.go create mode 100644 types/peerid.go diff --git a/dialer.go b/dialer.go index d499af30..5cdf3fcc 100644 --- a/dialer.go +++ b/dialer.go @@ -1,34 +1,12 @@ package torrent import ( - "context" - "net" + "github.com/anacrolix/torrent/dialer" ) -// Dialers have the network locked in. -type Dialer interface { - Dial(_ context.Context, addr string) (net.Conn, error) - DialerNetwork() string -} +type ( + Dialer = dialer.T + NetworkDialer = dialer.WithNetwork +) -// An interface to ease wrapping dialers that explicitly include a network parameter. -type DialContexter interface { - DialContext(ctx context.Context, network, addr string) (net.Conn, error) -} - -// Used by wrappers of standard library network types. -var DefaultNetDialer = &net.Dialer{} - -// Adapts a DialContexter to the Dial interface in this package. -type NetworkDialer struct { - Network string - Dialer DialContexter -} - -func (me NetworkDialer) DialerNetwork() string { - return me.Network -} - -func (me NetworkDialer) Dial(ctx context.Context, addr string) (_ net.Conn, err error) { - return me.Dialer.DialContext(ctx, me.Network, addr) -} +var DefaultNetDialer = &dialer.Default diff --git a/dialer/dialer.go b/dialer/dialer.go new file mode 100644 index 00000000..5e5dff49 --- /dev/null +++ b/dialer/dialer.go @@ -0,0 +1,34 @@ +package dialer + +import ( + "context" + "net" +) + +// Dialers have the network locked in. +type T interface { + Dial(_ context.Context, addr string) (net.Conn, error) + DialerNetwork() string +} + +// An interface to ease wrapping dialers that explicitly include a network parameter. +type WithContext interface { + DialContext(ctx context.Context, network, addr string) (net.Conn, error) +} + +// Used by wrappers of standard library network types. +var Default = &net.Dialer{} + +// Adapts a WithContext to the Dial interface in this package. +type WithNetwork struct { + Network string + Dialer WithContext +} + +func (me WithNetwork) DialerNetwork() string { + return me.Network +} + +func (me WithNetwork) Dial(ctx context.Context, addr string) (_ net.Conn, err error) { + return me.Dialer.DialContext(ctx, me.Network, addr) +} diff --git a/metainfo/hash.go b/metainfo/hash.go index a1f688a7..39daf6f3 100644 --- a/metainfo/hash.go +++ b/metainfo/hash.go @@ -1,80 +1,16 @@ package metainfo import ( - "crypto/sha1" - "encoding" - "encoding/hex" - "fmt" + "github.com/anacrolix/torrent/types/infohash" ) -const HashSize = 20 +// This type has been moved to allow avoiding importing everything in metainfo to get at it. -// 20-byte SHA1 hash used for info and pieces. -type Hash [HashSize]byte +const HashSize = infohash.Size -var _ fmt.Formatter = (*Hash)(nil) - -func (h Hash) Format(f fmt.State, c rune) { - // TODO: I can't figure out a nice way to just override the 'x' rune, since it's meaningless - // with the "default" 'v', or .String() already returning the hex. - f.Write([]byte(h.HexString())) -} - -func (h Hash) Bytes() []byte { - return h[:] -} - -func (h Hash) AsString() string { - return string(h[:]) -} - -func (h Hash) String() string { - return h.HexString() -} - -func (h Hash) HexString() string { - return fmt.Sprintf("%x", h[:]) -} - -func (h *Hash) FromHexString(s string) (err error) { - if len(s) != 2*HashSize { - err = fmt.Errorf("hash hex string has bad length: %d", len(s)) - return - } - n, err := hex.Decode(h[:], []byte(s)) - if err != nil { - return - } - if n != HashSize { - panic(n) - } - return -} +type Hash = infohash.T var ( - _ encoding.TextUnmarshaler = (*Hash)(nil) - _ encoding.TextMarshaler = Hash{} + NewHashFromHex = infohash.FromHexString + HashBytes = infohash.HashBytes ) - -func (h *Hash) UnmarshalText(b []byte) error { - return h.FromHexString(string(b)) -} - -func (h Hash) MarshalText() (text []byte, err error) { - return []byte(h.HexString()), nil -} - -func NewHashFromHex(s string) (h Hash) { - err := h.FromHexString(s) - if err != nil { - panic(err) - } - return -} - -func HashBytes(b []byte) (ret Hash) { - hasher := sha1.New() - hasher.Write(b) - copy(ret[:], hasher.Sum(nil)) - return -} diff --git a/metainfo/info.go b/metainfo/info.go index bab08af9..1ee2704e 100644 --- a/metainfo/info.go +++ b/metainfo/info.go @@ -8,7 +8,7 @@ import ( "path/filepath" "strings" - "github.com/anacrolix/missinggo/slices" + "github.com/anacrolix/missinggo/v2/slices" ) // The info dictionary. diff --git a/misc.go b/misc.go index 4041b776..6b638a28 100644 --- a/misc.go +++ b/misc.go @@ -7,6 +7,7 @@ import ( "github.com/RoaringBitmap/roaring" "github.com/anacrolix/missinggo/v2" "github.com/anacrolix/torrent/types" + "github.com/anacrolix/torrent/types/infohash" "golang.org/x/time/rate" "github.com/anacrolix/torrent/metainfo" @@ -177,8 +178,9 @@ var unlimited = rate.NewLimiter(rate.Inf, 0) type ( pieceIndex = int - InfoHash = metainfo.Hash - IpPort = missinggo.IpPort + // Deprecated: Use infohash.T directly to avoid unnecessary imports. + InfoHash = infohash.T + IpPort = missinggo.IpPort ) func boolSliceToBitmap(slice []bool) (rb roaring.Bitmap) { diff --git a/peerid.go b/peerid.go index b689d304..301c0e94 100644 --- a/peerid.go +++ b/peerid.go @@ -1,14 +1,5 @@ package torrent -// Peer client ID. -type PeerID [20]byte +import "github.com/anacrolix/torrent/types" -// // Pretty prints the ID as hex, except parts that adher to the PeerInfo ID -// // Conventions of BEP 20. -// func (me PeerID) String() string { -// // if me[0] == '-' && me[7] == '-' { -// // return string(me[:8]) + hex.EncodeToString(me[8:]) -// // } -// // return hex.EncodeToString(me[:]) -// return fmt.Sprintf("%+q", me[:]) -// } +type PeerID = types.PeerID diff --git a/socket.go b/socket.go index d5b690ff..aee11df8 100644 --- a/socket.go +++ b/socket.go @@ -8,6 +8,7 @@ import ( "github.com/anacrolix/log" "github.com/anacrolix/missinggo/perf" "github.com/anacrolix/missinggo/v2" + "github.com/anacrolix/torrent/dialer" "github.com/pkg/errors" ) @@ -42,7 +43,7 @@ func listenTcp(network, address string) (s socket, err error) { Listener: l, NetworkDialer: NetworkDialer{ Network: network, - Dialer: DefaultNetDialer, + Dialer: dialer.Default, }, }, err } diff --git a/test/unix_test.go b/test/unix_test.go index d8a3ff9f..e4ffa7e4 100644 --- a/test/unix_test.go +++ b/test/unix_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/anacrolix/torrent" + "github.com/anacrolix/torrent/dialer" ) func TestUnixConns(t *testing.T) { @@ -24,7 +25,7 @@ func TestUnixConns(t *testing.T) { cfg.Debug = true }, Client: func(cl *torrent.Client) { - cl.AddDialer(torrent.NetworkDialer{Network: "unix", Dialer: torrent.DefaultNetDialer}) + cl.AddDialer(torrent.NetworkDialer{Network: "unix", Dialer: dialer.Default}) l, err := net.Listen("unix", filepath.Join(t.TempDir(), "socket")) if err != nil { panic(err) diff --git a/types/infohash/infohash.go b/types/infohash/infohash.go new file mode 100644 index 00000000..0763b01e --- /dev/null +++ b/types/infohash/infohash.go @@ -0,0 +1,80 @@ +package infohash + +import ( + "crypto/sha1" + "encoding" + "encoding/hex" + "fmt" +) + +const Size = 20 + +// 20-byte SHA1 hash used for info and pieces. +type T [Size]byte + +var _ fmt.Formatter = (*T)(nil) + +func (t T) Format(f fmt.State, c rune) { + // TODO: I can't figure out a nice way to just override the 'x' rune, since it's meaningless + // with the "default" 'v', or .String() already returning the hex. + f.Write([]byte(t.HexString())) +} + +func (t T) Bytes() []byte { + return t[:] +} + +func (t T) AsString() string { + return string(t[:]) +} + +func (t T) String() string { + return t.HexString() +} + +func (t T) HexString() string { + return fmt.Sprintf("%x", t[:]) +} + +func (t *T) FromHexString(s string) (err error) { + if len(s) != 2*Size { + err = fmt.Errorf("hash hex string has bad length: %d", len(s)) + return + } + n, err := hex.Decode(t[:], []byte(s)) + if err != nil { + return + } + if n != Size { + panic(n) + } + return +} + +var ( + _ encoding.TextUnmarshaler = (*T)(nil) + _ encoding.TextMarshaler = T{} +) + +func (t *T) UnmarshalText(b []byte) error { + return t.FromHexString(string(b)) +} + +func (t T) MarshalText() (text []byte, err error) { + return []byte(t.HexString()), nil +} + +func FromHexString(s string) (h T) { + err := h.FromHexString(s) + if err != nil { + panic(err) + } + return +} + +func HashBytes(b []byte) (ret T) { + hasher := sha1.New() + hasher.Write(b) + copy(ret[:], hasher.Sum(nil)) + return +} diff --git a/types/peerid.go b/types/peerid.go new file mode 100644 index 00000000..0e13473e --- /dev/null +++ b/types/peerid.go @@ -0,0 +1,14 @@ +package types + +// Peer client ID. +type PeerID [20]byte + +// // Pretty prints the ID as hex, except parts that adher to the PeerInfo ID +// // Conventions of BEP 20. +// func (me PeerID) String() string { +// // if me[0] == '-' && me[7] == '-' { +// // return string(me[:8]) + hex.EncodeToString(me[8:]) +// // } +// // return hex.EncodeToString(me[:]) +// return fmt.Sprintf("%+q", me[:]) +// }