diff --git a/bittorrent/bittorrent.go b/bittorrent/bittorrent.go index fc9c1fc..dff7d1c 100644 --- a/bittorrent/bittorrent.go +++ b/bittorrent/bittorrent.go @@ -13,7 +13,6 @@ import ( ) // PeerID represents a peer ID. -// TODO: check if torrentV2 also changed this field size type PeerID [20]byte // PeerIDFromBytes creates a PeerID from a byte slice. @@ -61,17 +60,14 @@ const( ) var invalidHashSize = errors.New("InfoHash must be either 20 (for torrent V1) or 32 (V2) bytes") -var isNotV1Hash = errors.New("InfoHash is not V1 (SHA1)") // BytesV1 returns 20-bytes length array of the corresponding InfoHash. -// If InfoHash is not 20-bytes long (is torrent V2 hash) zeroed array and error returned -func (i InfoHash) BytesV1() ([InfoHashV1Len]byte, error){ +// If InfoHash is V2 (32 bytes), it will be truncated to 20 bytes +// according to BEP52. +func (i InfoHash) BytesV1() [InfoHashV1Len]byte{ var bb [InfoHashV1Len]byte - if len(i) != InfoHashV1Len { - return bb, isNotV1Hash - } copy(bb[:], i) - return bb, nil + return bb } // ValidateInfoHash validates input bytes size and returns it diff --git a/bittorrent/client_id.go b/bittorrent/client_id.go deleted file mode 100644 index 840fd75..0000000 --- a/bittorrent/client_id.go +++ /dev/null @@ -1,22 +0,0 @@ -package bittorrent - -// ClientID represents the part of a PeerID that identifies a Peer's client -// software. -type ClientID [6]byte - -// NewClientID parses a ClientID from a PeerID. -func NewClientID(pid PeerID) ClientID { - var cid ClientID - length := len(pid) - if length >= 6 { - if pid[0] == '-' { - if length >= 7 { - copy(cid[:], pid[1:7]) - } - } else { - copy(cid[:], pid[:6]) - } - } - - return cid -} diff --git a/middleware/clientapproval/client_id.go b/middleware/clientapproval/client_id.go new file mode 100644 index 0000000..0e03b1d --- /dev/null +++ b/middleware/clientapproval/client_id.go @@ -0,0 +1,27 @@ +// Package clientapproval XXX: implementation is broken, client ID is NOT 6 static bytes +// refer: +// - https://wiki.theory.org/BitTorrentSpecification#peer_id +// - https://github.com/webtorrent/bittorrent-peerid/blob/master/lib/utils.js +package clientapproval + +import "github.com/chihaya/chihaya/bittorrent" + +// ClientID represents the part of a PeerID that identifies a Peer's client +// software. +type ClientID [6]byte + +// NewClientID parses a ClientID from a PeerID. +func NewClientID(pid bittorrent.PeerID) ClientID { + var cid ClientID + if pid[0] == '-' { + copy(cid[:], pid[1:7]) + } else { + copy(cid[:], pid[:6]) + } + + return cid +} + +func (cid ClientID) String() string { + return string(cid[:]) +} diff --git a/bittorrent/client_id_test.go b/middleware/clientapproval/client_id_test.go similarity index 91% rename from bittorrent/client_id_test.go rename to middleware/clientapproval/client_id_test.go index c618143..3f9f408 100644 --- a/bittorrent/client_id_test.go +++ b/middleware/clientapproval/client_id_test.go @@ -1,6 +1,7 @@ -package bittorrent +package clientapproval import ( + "github.com/chihaya/chihaya/bittorrent" "testing" ) @@ -45,8 +46,8 @@ func TestClientID(t *testing.T) { for _, tt := range clientTable { t.Run(tt.peerID, func(t *testing.T) { var clientID ClientID - copy(clientID[:], []byte(tt.clientID)) - parsedID := NewClientID(PeerIDFromString(tt.peerID)) + copy(clientID[:], tt.clientID) + parsedID := NewClientID(bittorrent.PeerIDFromString(tt.peerID)) if parsedID != clientID { t.Error("Incorrectly parsed peer ID", tt.peerID, "as", parsedID) } diff --git a/middleware/clientapproval/clientapproval.go b/middleware/clientapproval/clientapproval.go index 6e08d7f..a1b4fb5 100644 --- a/middleware/clientapproval/clientapproval.go +++ b/middleware/clientapproval/clientapproval.go @@ -44,15 +44,15 @@ type Config struct { } type hook struct { - approved map[bittorrent.ClientID]struct{} - unapproved map[bittorrent.ClientID]struct{} + approved map[ClientID]struct{} + unapproved map[ClientID]struct{} } // NewHook returns an instance of the client approval middleware. func NewHook(cfg Config) (middleware.Hook, error) { h := &hook{ - approved: make(map[bittorrent.ClientID]struct{}), - unapproved: make(map[bittorrent.ClientID]struct{}), + approved: make(map[ClientID]struct{}), + unapproved: make(map[ClientID]struct{}), } if len(cfg.Whitelist) > 0 && len(cfg.Blacklist) > 0 { @@ -64,7 +64,7 @@ func NewHook(cfg Config) (middleware.Hook, error) { if len(cidBytes) != 6 { return nil, errors.New("client ID " + cidString + " must be 6 bytes") } - var cid bittorrent.ClientID + var cid ClientID copy(cid[:], cidBytes) h.approved[cid] = struct{}{} } @@ -74,7 +74,7 @@ func NewHook(cfg Config) (middleware.Hook, error) { if len(cidBytes) != 6 { return nil, errors.New("client ID " + cidString + " must be 6 bytes") } - var cid bittorrent.ClientID + var cid ClientID copy(cid[:], cidBytes) h.unapproved[cid] = struct{}{} } @@ -83,7 +83,7 @@ func NewHook(cfg Config) (middleware.Hook, error) { } func (h *hook) HandleAnnounce(ctx context.Context, req *bittorrent.AnnounceRequest, resp *bittorrent.AnnounceResponse) (context.Context, error) { - clientID := bittorrent.NewClientID(req.Peer.ID) + clientID := NewClientID(req.Peer.ID) if len(h.approved) > 0 { if _, found := h.approved[clientID]; !found { diff --git a/storage/storage_bench.go b/storage/storage_bench.go index 5f8e8ce..10d56ff 100644 --- a/storage/storage_bench.go +++ b/storage/storage_bench.go @@ -16,14 +16,10 @@ type benchData struct { } func generateInfohashes() (a [1000]bittorrent.InfoHash) { - r := rand.New(rand.NewSource(0)) for i := range a { - b := [20]byte{} - n, err := r.Read(b[:]) - if err != nil || n != 20 { - panic("unable to create random bytes") - } - a[i] = bittorrent.InfoHash(b) + b := make([]byte, 20) + rand.Read(b) + a[i], _ = bittorrent.InfoHashFromBytes(b) } return @@ -44,7 +40,7 @@ func generatePeers() (a [1000]bittorrent.Peer) { } port := uint16(r.Uint32()) a[i] = bittorrent.Peer{ - ID: bittorrent.PeerID(id), + ID: id, IP: bittorrent.IP{IP: net.IP(ip), AddressFamily: bittorrent.IPv4}, Port: port, }