From 8298051c8185dc6cd597fd6215dfbcdb9090d6ac Mon Sep 17 00:00:00 2001 From: liwei Date: Tue, 25 Feb 2020 14:22:17 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8C=85=E5=90=8D=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- down/bt/metainfo/metainfo_test.go | 15 --- down/bt/torrent/torrent_test.go | 32 ------ go.mod | 1 + go.sum | 31 ++++++ main.go | 10 +- {down => protocol}/bt/client.go | 4 +- {down => protocol}/bt/client_test.go | 0 {down => protocol}/bt/metainfo/metainfo.go | 20 ++-- protocol/bt/metainfo/metainfo_test.go | 29 ++++++ {down => protocol}/bt/peer/handshake.go | 0 {down => protocol}/bt/peer/message/message.go | 0 .../bt/peer/message/msg_bitfield.go | 0 .../bt/peer/message/msg_bitfield_test.go | 0 .../bt/peer/message/msg_choke.go | 0 .../bt/peer/message/msg_interested.go | 0 .../bt/peer/message/msg_keepalive.go | 0 .../bt/peer/message/msg_not_interested.go | 0 .../bt/peer/message/msg_piece.go | 0 .../bt/peer/message/msg_request.go | 0 .../bt/peer/message/msg_unchoke.go | 0 {down => protocol}/bt/peer/peer.go | 0 ...rones.S08E05.720p.WEB.H264-MEMENTO.torrent | Bin protocol/bt/testdata/office.torrent | Bin 0 -> 12575 bytes {down => protocol}/bt/torrent/peer_conn.go | 97 +++++++++--------- .../bt/torrent/peer_conn_test.go | 25 ++++- {down => protocol}/bt/torrent/peer_pool.go | 2 +- .../bt/torrent/peer_pool_test.go | 2 +- {down => protocol}/bt/torrent/piece_state.go | 0 {down => protocol}/bt/torrent/torrent.go | 20 ++-- protocol/bt/torrent/torrent_test.go | 44 ++++++++ {down => protocol}/bt/tracker/errors.go | 0 {down => protocol}/bt/tracker/tracker.go | 4 +- {down => protocol}/bt/tracker/tracker_test.go | 2 +- {down => protocol}/http/down.go | 15 +-- {down => protocol}/http/down_test.go | 1 + {down => protocol}/http/request.go | 0 {down => protocol}/http/response.go | 0 37 files changed, 220 insertions(+), 134 deletions(-) delete mode 100644 down/bt/metainfo/metainfo_test.go delete mode 100644 down/bt/torrent/torrent_test.go rename {down => protocol}/bt/client.go (90%) rename {down => protocol}/bt/client_test.go (100%) rename {down => protocol}/bt/metainfo/metainfo.go (88%) create mode 100644 protocol/bt/metainfo/metainfo_test.go rename {down => protocol}/bt/peer/handshake.go (100%) rename {down => protocol}/bt/peer/message/message.go (100%) rename {down => protocol}/bt/peer/message/msg_bitfield.go (100%) rename {down => protocol}/bt/peer/message/msg_bitfield_test.go (100%) rename {down => protocol}/bt/peer/message/msg_choke.go (100%) rename {down => protocol}/bt/peer/message/msg_interested.go (100%) rename {down => protocol}/bt/peer/message/msg_keepalive.go (100%) rename {down => protocol}/bt/peer/message/msg_not_interested.go (100%) rename {down => protocol}/bt/peer/message/msg_piece.go (100%) rename {down => protocol}/bt/peer/message/msg_request.go (100%) rename {down => protocol}/bt/peer/message/msg_unchoke.go (100%) rename {down => protocol}/bt/peer/peer.go (100%) rename {down => protocol}/bt/testdata/Game.of.Thrones.S08E05.720p.WEB.H264-MEMENTO.torrent (100%) create mode 100644 protocol/bt/testdata/office.torrent rename {down => protocol}/bt/torrent/peer_conn.go (83%) rename {down => protocol}/bt/torrent/peer_conn_test.go (84%) rename {down => protocol}/bt/torrent/peer_pool.go (96%) rename {down => protocol}/bt/torrent/peer_pool_test.go (90%) rename {down => protocol}/bt/torrent/piece_state.go (100%) rename {down => protocol}/bt/torrent/torrent.go (81%) create mode 100644 protocol/bt/torrent/torrent_test.go rename {down => protocol}/bt/tracker/errors.go (100%) rename {down => protocol}/bt/tracker/tracker.go (99%) rename {down => protocol}/bt/tracker/tracker_test.go (90%) rename {down => protocol}/http/down.go (92%) rename {down => protocol}/http/down_test.go (99%) rename {down => protocol}/http/request.go (100%) rename {down => protocol}/http/response.go (100%) diff --git a/down/bt/metainfo/metainfo_test.go b/down/bt/metainfo/metainfo_test.go deleted file mode 100644 index 042b09e3..00000000 --- a/down/bt/metainfo/metainfo_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package metainfo - -import ( - "fmt" - "testing" -) - -func TestParseFromFile(t *testing.T) { - metaInfo, err := ParseFromFile("../testdata/Game.of.Thrones.S08E05.720p.WEB.H264-MEMENTO.torrent") - if err != nil { - panic(err) - } - fmt.Printf("%+v\n", metaInfo.AnnounceList) - fmt.Printf("%+v\n", metaInfo.Info.Files) -} diff --git a/down/bt/torrent/torrent_test.go b/down/bt/torrent/torrent_test.go deleted file mode 100644 index 409249f1..00000000 --- a/down/bt/torrent/torrent_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package torrent - -import ( - "github.com/monkeyWie/gopeed/down/bt/metainfo" - "github.com/monkeyWie/gopeed/down/bt/peer" - "testing" -) - -func TestTorrent_Download(t *testing.T) { - torrent := buildTorrent() - torrent.Download("e:/testbt/download") -} - -func buildTorrent() *Torrent { - metaInfo, err := metainfo.ParseFromFile("../testdata/Game.of.Thrones.S08E05.720p.WEB.H264-MEMENTO.torrent") - if err != nil { - panic(err) - } - // metaInfo.Announce = "udp://exodus.desync.com:6969/announce" - // metaInfo.Announce = "udp://tracker.openbittorrent.com:80/announce" - // metaInfo.Announce = "udp://tracker.cyberia.is:6969/announce" - // metaInfo.Announce = "udp://9.rarbg.me:2780/announce" - // metaInfo.Announce = "udp://9.rarbg.to:2760/announce" - // metaInfo.Announce = "udp://tracker.leechers-paradise.org:6969" - metaInfo.AnnounceList = [][]string{} - metaInfo.AnnounceList = append(metaInfo.AnnounceList, []string{ - "udp://exodus.desync.com:6969/announce", - "udp://tracker.openbittorrent.com:80/announce", - "udp://tracker.leechers-paradise.org:6969", - }) - return NewTorrent(peer.GenPeerID(), metaInfo) -} diff --git a/go.mod b/go.mod index f1f60be4..294d22c2 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/monkeyWie/gopeed go 1.13 require ( + github.com/RoaringBitmap/roaring v0.4.21 github.com/cenkalti/mse v0.0.0-20140930130441-6ef65f170972 github.com/marksamman/bencode v0.0.0-20150821143521-dc84f26e086e ) diff --git a/go.sum b/go.sum index 4fb0ab47..d334cd5d 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,35 @@ +github.com/RoaringBitmap/roaring v0.4.21 h1:WJ/zIlNX4wQZ9x8Ey33O1UaD9TCTakYsdLFSBcTwH+8= +github.com/RoaringBitmap/roaring v0.4.21/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo= github.com/cenkalti/mse v0.0.0-20140930130441-6ef65f170972 h1:FvAasVrPm/VUO8M0odLDqA9Y7VbALYq3PRAwmWGPw78= github.com/cenkalti/mse v0.0.0-20140930130441-6ef65f170972/go.mod h1:wGf99xKTJ8f/a8cC1inMqFz9cGEzISLLid5F6i5fI/g= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2 h1:Ujru1hufTHVb++eG6OuNDKMxZnGIvF6o/u8q/8h2+I4= +github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= +github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31 h1:gclg6gY70GLy3PbkQ1AERPfmLMMagS60DKF78eWwLn8= +github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= +github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 h1:twflg0XRTjwKpxb/jFExr4HGq6on2dEOmnL6FV+fgPw= +github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/marksamman/bencode v0.0.0-20150821143521-dc84f26e086e h1:KMs6SK8iDSR1+ZzOK10L5wGPpWDByyvOe5nrqk51g2U= github.com/marksamman/bencode v0.0.0-20150821143521-dc84f26e086e/go.mod h1:+AHfJo5+69p+fjvMJTmYajNP9rFBHQcaTDFmuXRRATI= +github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae h1:VeRdUYdCw49yizlSbMEn2SZ+gT+3IUKx8BqxyQdz+BY= +github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= +github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ= +github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/tinylib/msgp v1.1.0 h1:9fQd+ICuRIu/ue4vxJZu6/LzxN0HwMds2nq/0cFvxHU= +github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= +github.com/willf/bitset v1.1.10 h1:NotGKqX0KwQ72NUzqrjZq5ipPNDQex9lo3WpaS8L2sc= +github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/main.go b/main.go index 69342c01..31489a77 100644 --- a/main.go +++ b/main.go @@ -2,11 +2,11 @@ package main import ( "fmt" - "github.com/monkeyWie/gopeed/down/bt/metainfo" - "github.com/monkeyWie/gopeed/down/bt/peer" - "github.com/monkeyWie/gopeed/down/bt/torrent" - "github.com/monkeyWie/gopeed/down/bt/tracker" - "github.com/monkeyWie/gopeed/down/http" + "github.com/monkeyWie/gopeed/protocol/bt/metainfo" + "github.com/monkeyWie/gopeed/protocol/bt/peer" + "github.com/monkeyWie/gopeed/protocol/bt/torrent" + "github.com/monkeyWie/gopeed/protocol/bt/tracker" + "github.com/monkeyWie/gopeed/protocol/http" ) func main() { diff --git a/down/bt/client.go b/protocol/bt/client.go similarity index 90% rename from down/bt/client.go rename to protocol/bt/client.go index 0d2d368a..d4336ebd 100644 --- a/down/bt/client.go +++ b/protocol/bt/client.go @@ -2,8 +2,8 @@ package bt import ( "crypto/rand" - "github.com/monkeyWie/gopeed/down/bt/metainfo" - "github.com/monkeyWie/gopeed/down/bt/torrent" + "github.com/monkeyWie/gopeed/protocol/bt/metainfo" + "github.com/monkeyWie/gopeed/protocol/bt/torrent" "net/url" ) diff --git a/down/bt/client_test.go b/protocol/bt/client_test.go similarity index 100% rename from down/bt/client_test.go rename to protocol/bt/client_test.go diff --git a/down/bt/metainfo/metainfo.go b/protocol/bt/metainfo/metainfo.go similarity index 88% rename from down/bt/metainfo/metainfo.go rename to protocol/bt/metainfo/metainfo.go index a8df3308..0c10bae5 100644 --- a/down/bt/metainfo/metainfo.go +++ b/protocol/bt/metainfo/metainfo.go @@ -29,10 +29,12 @@ type MetaInfo struct { type Info struct { Name string `json:"name"` - PieceLength uint64 `json:"piece length"` + PieceLength int `json:"piece length"` Pieces [][20]byte - Length uint64 `json:"length"` - Files []File `json:"files"` + // 单个文件时,length为该文件的长度 + Length uint64 `json:"length"` + // 多个文件 + Files []File `json:"files"` } type File struct { @@ -47,6 +49,12 @@ type FileDetail struct { End int64 } +type PieceMapping struct { + file int + begin int64 + end int64 +} + func ParseFromFile(path string) (*MetaInfo, error) { file, err := os.Open(path) if err != nil { @@ -85,12 +93,12 @@ func ParseFromFile(path string) (*MetaInfo, error) { } // 获取某个分片的大小 -func (metaInfo *MetaInfo) GetPieceSize(index int) uint64 { +func (metaInfo *MetaInfo) GetPieceLength(index int) int { // 是否为最后一个分片 if index == len(metaInfo.Info.Pieces)-1 { - size := metaInfo.totalSize % metaInfo.Info.PieceLength + size := metaInfo.totalSize % uint64(metaInfo.Info.PieceLength) if size > 0 { - return size + return int(size) } } return metaInfo.Info.PieceLength diff --git a/protocol/bt/metainfo/metainfo_test.go b/protocol/bt/metainfo/metainfo_test.go new file mode 100644 index 00000000..10a03465 --- /dev/null +++ b/protocol/bt/metainfo/metainfo_test.go @@ -0,0 +1,29 @@ +package metainfo + +import ( + "encoding/hex" + "fmt" + "github.com/RoaringBitmap/roaring" + "testing" +) + +func TestParseFromFile(t *testing.T) { + // metaInfo, err := ParseFromFile("../testdata/Game.of.Thrones.S08E05.720p.WEB.H264-MEMENTO.torrent") + metaInfo, err := ParseFromFile("../testdata/office.torrent") + if err != nil { + panic(err) + } + fmt.Printf("%+v\n", metaInfo.AnnounceList) + fmt.Printf("%+v\n", metaInfo.Info.Files) + fmt.Printf("%+v\n", metaInfo.Info.PieceLength) + fmt.Printf("%+v\n", hex.EncodeToString(metaInfo.infoHash[:])) +} + +func TestParseFromFile2(t *testing.T) { + bitmap := roaring.NewBitmap() + bitmap.AddMany([]uint32{1, 2, 3, 4, 5, 6, 7, 10, 20, 9, 9, 1}) + fmt.Println(bitmap.Contains(1)) + fmt.Println(bitmap.Contains(2)) + fmt.Println(bitmap.Contains(8)) + fmt.Println(bitmap.GetCardinality()) +} diff --git a/down/bt/peer/handshake.go b/protocol/bt/peer/handshake.go similarity index 100% rename from down/bt/peer/handshake.go rename to protocol/bt/peer/handshake.go diff --git a/down/bt/peer/message/message.go b/protocol/bt/peer/message/message.go similarity index 100% rename from down/bt/peer/message/message.go rename to protocol/bt/peer/message/message.go diff --git a/down/bt/peer/message/msg_bitfield.go b/protocol/bt/peer/message/msg_bitfield.go similarity index 100% rename from down/bt/peer/message/msg_bitfield.go rename to protocol/bt/peer/message/msg_bitfield.go diff --git a/down/bt/peer/message/msg_bitfield_test.go b/protocol/bt/peer/message/msg_bitfield_test.go similarity index 100% rename from down/bt/peer/message/msg_bitfield_test.go rename to protocol/bt/peer/message/msg_bitfield_test.go diff --git a/down/bt/peer/message/msg_choke.go b/protocol/bt/peer/message/msg_choke.go similarity index 100% rename from down/bt/peer/message/msg_choke.go rename to protocol/bt/peer/message/msg_choke.go diff --git a/down/bt/peer/message/msg_interested.go b/protocol/bt/peer/message/msg_interested.go similarity index 100% rename from down/bt/peer/message/msg_interested.go rename to protocol/bt/peer/message/msg_interested.go diff --git a/down/bt/peer/message/msg_keepalive.go b/protocol/bt/peer/message/msg_keepalive.go similarity index 100% rename from down/bt/peer/message/msg_keepalive.go rename to protocol/bt/peer/message/msg_keepalive.go diff --git a/down/bt/peer/message/msg_not_interested.go b/protocol/bt/peer/message/msg_not_interested.go similarity index 100% rename from down/bt/peer/message/msg_not_interested.go rename to protocol/bt/peer/message/msg_not_interested.go diff --git a/down/bt/peer/message/msg_piece.go b/protocol/bt/peer/message/msg_piece.go similarity index 100% rename from down/bt/peer/message/msg_piece.go rename to protocol/bt/peer/message/msg_piece.go diff --git a/down/bt/peer/message/msg_request.go b/protocol/bt/peer/message/msg_request.go similarity index 100% rename from down/bt/peer/message/msg_request.go rename to protocol/bt/peer/message/msg_request.go diff --git a/down/bt/peer/message/msg_unchoke.go b/protocol/bt/peer/message/msg_unchoke.go similarity index 100% rename from down/bt/peer/message/msg_unchoke.go rename to protocol/bt/peer/message/msg_unchoke.go diff --git a/down/bt/peer/peer.go b/protocol/bt/peer/peer.go similarity index 100% rename from down/bt/peer/peer.go rename to protocol/bt/peer/peer.go diff --git a/down/bt/testdata/Game.of.Thrones.S08E05.720p.WEB.H264-MEMENTO.torrent b/protocol/bt/testdata/Game.of.Thrones.S08E05.720p.WEB.H264-MEMENTO.torrent similarity index 100% rename from down/bt/testdata/Game.of.Thrones.S08E05.720p.WEB.H264-MEMENTO.torrent rename to protocol/bt/testdata/Game.of.Thrones.S08E05.720p.WEB.H264-MEMENTO.torrent diff --git a/protocol/bt/testdata/office.torrent b/protocol/bt/testdata/office.torrent new file mode 100644 index 0000000000000000000000000000000000000000..15768d09133047c71390ebfd61e7c26903895d23 GIT binary patch literal 12575 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 literal 0 HcmV?d00001 diff --git a/down/bt/torrent/peer_conn.go b/protocol/bt/torrent/peer_conn.go similarity index 83% rename from down/bt/torrent/peer_conn.go rename to protocol/bt/torrent/peer_conn.go index 1af8f463..62b1f1b2 100644 --- a/down/bt/torrent/peer_conn.go +++ b/protocol/bt/torrent/peer_conn.go @@ -7,18 +7,23 @@ import ( "errors" "fmt" "github.com/cenkalti/mse" - "github.com/monkeyWie/gopeed/down/bt/metainfo" - "github.com/monkeyWie/gopeed/down/bt/peer" - "github.com/monkeyWie/gopeed/down/bt/peer/message" + "github.com/monkeyWie/gopeed/protocol/bt/metainfo" + "github.com/monkeyWie/gopeed/protocol/bt/peer" + "github.com/monkeyWie/gopeed/protocol/bt/peer/message" + "path/filepath" + "sync/atomic" + "io" "math" "net" "os" "path" - "sync" "time" ) +// 现在主流客户端的block大小都是16KB +const BlockSize = 2 << 13 + type peerConn struct { torrent *Torrent peer *peer.Peer @@ -32,13 +37,16 @@ type peerConn struct { // peer is interested in this client peerInterested bool - bitfield *message.Bitfield - readyComplete bool - pieceDownloadedCh chan bool + bitfield *message.Bitfield + readyComplete bool + + downloadedCh chan bool + // block个数 + blockCount int + // 已经下载的block个数 + blockDownloadedCount int32 // block下载队列,官方推荐为5 - pieceBlockQueue chan interface{} - // piece上所有的block下载状态 - pieceBlockState sync.Map + blockQueue chan interface{} } func NewPeerConn(torrent *Torrent, peer *peer.Peer) *peerConn { @@ -168,42 +176,49 @@ func (pc *peerConn) ready() error { pc.conn.Close() return err } - pc.pieceBlockQueue = make(chan interface{}, 5) + pc.blockQueue = make(chan interface{}, 5) return nil } // 下载指定piece func (pc *peerConn) downloadPiece(index int) error { - pc.pieceDownloadedCh = make(chan bool) - defer close(pc.pieceDownloadedCh) - pc.pieceBlockState = sync.Map{} - pieceLength := pc.torrent.MetaInfo.GetPieceSize(index) - lastOffset := uint64(0) + pieceLength := pc.torrent.MetaInfo.GetPieceLength(index) + lastOffset := 0 + + pc.blockCount = int(math.Ceil(float64(pieceLength) / BlockSize)) + pc.downloadedCh = make(chan bool) + defer close(pc.downloadedCh) waitDuration := time.Second * 30 timer := time.NewTimer(waitDuration) defer timer.Stop() // 按块下载分片 - for lastOffset < pieceLength { - blockLength := math.Min(2<<13, float64(pieceLength-lastOffset)) + for i := 0; i < pc.blockCount; i++ { + offset := pieceLength * i + var blockLength uint32 + if i == pc.blockCount-1 { + // 最后一个block大小需要计算出来 + blockLength = uint32(pieceLength - offset) + } else { + blockLength = BlockSize + } // 标记block开始下载 - lastOffset32 := uint32(lastOffset) - pc.pieceBlockState.Store(lastOffset32, false) + offset32 := uint32(lastOffset) // block下载排队,并做超时处理 timer.Reset(waitDuration) select { - case pc.pieceBlockQueue <- nil: + case pc.blockQueue <- nil: case <-timer.C: return errors.New("download timeout") } - _, err := pc.conn.Write(message.NewRequest(uint32(index), lastOffset32, uint32(blockLength)).Encode()) + // 发起request,对方会响应piece + _, err := pc.conn.Write(message.NewRequest(uint32(index), offset32, blockLength).Encode()) if err != nil { fmt.Println(err) } - lastOffset += uint64(blockLength) } // 监听是否下载完成 - <-pc.pieceDownloadedCh + <-pc.downloadedCh return nil } @@ -237,7 +252,7 @@ func (pc *peerConn) handleBitfield(buf []byte) { } } -// 处理分片下载响应 +// 处理下载响应,每次接收到响应直接将block写入到对应文件中 func (pc *peerConn) handlePiece(buf []byte) { piece := &message.Piece{} piece.Decode(buf) @@ -246,7 +261,7 @@ func (pc *peerConn) handlePiece(buf []byte) { blockLength := int64(len(piece.Block)) pieceBegin := int64(piece.Index) * int64(info.PieceLength) blockBegin := pieceBegin + int64(piece.Begin) - // 获取对应要的文件 + // 计算block对应要写到的文件偏移 var fileBlocks []fileBlock if len(info.Files) == 0 { // 单文件 @@ -269,7 +284,7 @@ func (pc *peerConn) handlePiece(buf []byte) { // 计算block剩余写入字节数 blockWritable := blockLength - blockSeek fb := fileBlock{ - filepath: f.Path[0], + filepath: filepath.Join(f.Path...), fileSeek: blockFileBegin - f.Begin, blockBegin: blockSeek, } @@ -287,10 +302,10 @@ func (pc *peerConn) handlePiece(buf []byte) { } } } - // fmt.Println(fileBlocks) + // 开始写入文件 for _, f := range fileBlocks { func() { - name := path.Join(pc.torrent.Path, f.filepath) + name := filepath.Join(pc.torrent.Path, f.filepath) file, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE, 0644) if err != nil { panic(err) @@ -298,28 +313,18 @@ func (pc *peerConn) handlePiece(buf []byte) { defer file.Close() _, err = file.WriteAt(piece.Block[f.blockBegin:f.blockEnd], f.fileSeek) if err != nil { - fmt.Println(err) + panic(err) } }() } - pc.pieceBlockState.Store(piece.Begin, true) // 出队 - <-pc.pieceBlockQueue - flag := true - // fmt.Printf("index %d: %v\n", piece.Index, pc.pieceBlockState) - pc.pieceBlockState.Range(func(key, value interface{}) bool { - // 如果有还没下载完的block - if !value.(bool) { - flag = false - return false - } - return true - }) + <-pc.blockQueue + // piece全部下载完 - if flag { + if atomic.AddInt32(&pc.blockDownloadedCount, 1) == int32(pc.blockCount) { // 计算piece对应的文件偏移 sha1 := sha1.New() - pieceLength := pc.torrent.MetaInfo.GetPieceSize(int(piece.Index)) + pieceLength := pc.torrent.MetaInfo.GetPieceLength(int(piece.Index)) writeIndex := getWriteFile(pieceBegin, fds) fileBegin := pieceBegin - fds[writeIndex].Begin for _, fd := range fds[writeIndex:] { @@ -339,7 +344,7 @@ func (pc *peerConn) handlePiece(buf []byte) { panic(err) } } - pieceLength -= uint64(written) + pieceLength -= int(written) }() if pieceLength > 0 { // 继续读下个文件 @@ -357,7 +362,7 @@ func (pc *peerConn) handlePiece(buf []byte) { fmt.Printf("piece %d 校验失败\n", piece.Index) } // piece下载完成 - pc.pieceDownloadedCh <- true + pc.downloadedCh <- true } } diff --git a/down/bt/torrent/peer_conn_test.go b/protocol/bt/torrent/peer_conn_test.go similarity index 84% rename from down/bt/torrent/peer_conn_test.go rename to protocol/bt/torrent/peer_conn_test.go index 09656843..31e41c0e 100644 --- a/down/bt/torrent/peer_conn_test.go +++ b/protocol/bt/torrent/peer_conn_test.go @@ -2,8 +2,9 @@ package torrent import ( "fmt" - "github.com/monkeyWie/gopeed/down/bt/peer" - "github.com/monkeyWie/gopeed/down/bt/tracker" + "github.com/monkeyWie/gopeed/protocol/bt/peer" + "github.com/monkeyWie/gopeed/protocol/bt/tracker" + "os" "sync" "testing" "time" @@ -104,7 +105,6 @@ func getUsablePeerMore() chan *peerConn { if err != nil { panic(err) } - fmt.Printf("Tracker end,peer count:%d\n", len(peers)) ch := make(chan *peerConn) for i := range peers { go peerTest(torrent, &peers[i], ch) @@ -145,3 +145,22 @@ func TestSome(t *testing.T) { fmt.Println("111") } + +func TestSome2(t *testing.T) { + wg := sync.WaitGroup{} + wg.Add(10) + file, err := os.OpenFile("e:/testbt/test.data", os.O_RDWR|os.O_CREATE, 0644) + for i := 0; i < 10; i++ { + go func(i int) { + for j := 0; j < 100; j++ { + if err != nil { + panic(err) + } + _, err = file.WriteAt([]byte{byte(i)}, int64(i*8)) + } + wg.Done() + }(i) + } + wg.Wait() + +} diff --git a/down/bt/torrent/peer_pool.go b/protocol/bt/torrent/peer_pool.go similarity index 96% rename from down/bt/torrent/peer_pool.go rename to protocol/bt/torrent/peer_pool.go index 77dd6231..41e444a1 100644 --- a/down/bt/torrent/peer_pool.go +++ b/protocol/bt/torrent/peer_pool.go @@ -1,7 +1,7 @@ package torrent import ( - "github.com/monkeyWie/gopeed/down/bt/peer" + "github.com/monkeyWie/gopeed/protocol/bt/peer" "sync" ) diff --git a/down/bt/torrent/peer_pool_test.go b/protocol/bt/torrent/peer_pool_test.go similarity index 90% rename from down/bt/torrent/peer_pool_test.go rename to protocol/bt/torrent/peer_pool_test.go index bd35c213..765b4080 100644 --- a/down/bt/torrent/peer_pool_test.go +++ b/protocol/bt/torrent/peer_pool_test.go @@ -2,7 +2,7 @@ package torrent import ( "fmt" - "github.com/monkeyWie/gopeed/down/bt/peer" + "github.com/monkeyWie/gopeed/protocol/bt/peer" "testing" ) diff --git a/down/bt/torrent/piece_state.go b/protocol/bt/torrent/piece_state.go similarity index 100% rename from down/bt/torrent/piece_state.go rename to protocol/bt/torrent/piece_state.go diff --git a/down/bt/torrent/torrent.go b/protocol/bt/torrent/torrent.go similarity index 81% rename from down/bt/torrent/torrent.go rename to protocol/bt/torrent/torrent.go index ae31d32c..6e669348 100644 --- a/down/bt/torrent/torrent.go +++ b/protocol/bt/torrent/torrent.go @@ -2,8 +2,8 @@ package torrent import ( "fmt" - "github.com/monkeyWie/gopeed/down/bt/metainfo" - "github.com/monkeyWie/gopeed/down/bt/tracker" + "github.com/monkeyWie/gopeed/protocol/bt/metainfo" + "github.com/monkeyWie/gopeed/protocol/bt/tracker" "sync" "time" ) @@ -43,7 +43,6 @@ func (t *Torrent) Download(path string) { go func(index int) { peer := t.peerPool.get() if peer == nil { - fmt.Println("no peer") time.Sleep(time.Second * 10) t.PiecesState.setState(index, stateReady) <-taskCh @@ -58,7 +57,12 @@ func (t *Torrent) Download(path string) { fmt.Printf("peer ready:%s,download %d\n", peer.Address(), index) err = pc.downloadPiece(index) if err != nil { - t.PiecesState.setState(index, stateDownloading) + fmt.Println(err) + // 下载失败 + t.PiecesState.setState(index, stateReady) + } else { + // 下载完成 + t.PiecesState.setState(index, stateFinished) } t.peerPool.release(peer) } @@ -73,11 +77,7 @@ func (t *Torrent) fetchPeers() { PeerID: t.PeerID, MetaInfo: t.MetaInfo, } - urls := []string{ - "udp://exodus.desync.com:6969/announce", - "udp://tracker.openbittorrent.com:80/announce", - "udp://tracker.leechers-paradise.org:6969", - } + urls := tracker.MetaInfo.AnnounceList[0] var wg sync.WaitGroup ch := make(chan interface{}) wg.Add(len(urls)) @@ -86,7 +86,7 @@ func (t *Torrent) fetchPeers() { defer wg.Done() peers, err := tracker.DoTracker(url) if err == nil { - fmt.Println("tracker end:" + url) + fmt.Printf("Tracker end,url:%s,count:%d\n", url, len(peers)) ch <- nil t.peerPool.put(peers) } diff --git a/protocol/bt/torrent/torrent_test.go b/protocol/bt/torrent/torrent_test.go new file mode 100644 index 00000000..feb799c9 --- /dev/null +++ b/protocol/bt/torrent/torrent_test.go @@ -0,0 +1,44 @@ +package torrent + +import ( + "github.com/monkeyWie/gopeed/protocol/bt/metainfo" + "github.com/monkeyWie/gopeed/protocol/bt/peer" + "testing" +) + +func TestTorrent_Download(t *testing.T) { + torrent := buildTorrent() + torrent.Download("e:/testbt/download") +} + +func buildTorrent() *Torrent { + // metaInfo, err := metainfo.ParseFromFile("../testdata/Game.of.Thrones.S08E05.720p.WEB.H264-MEMENTO.torrent") + metaInfo, err := metainfo.ParseFromFile("../testdata/office.torrent") + if err != nil { + panic(err) + } + + metaInfo.AnnounceList[0] = append(metaInfo.AnnounceList[0], []string{ + "udp://tracker.coppersurfer.tk:6969/announce", + "udp://tracker.leechers-paradise.org:6969/announce", + "udp://tracker.opentrackr.org:1337/announce", + "udp://p4p.arenabg.com:1337/announce", + "udp://9.rarbg.to:2710/announce", + "udp://9.rarbg.me:2710/announce", + "udp://tracker.internetwarriors.net:1337/announce", + "udp://exodus.desync.com:6969/announce", + "udp://tracker.tiny-vps.com:6969/announce", + "udp://tracker.sbsub.com:2710/announce", + "udp://retracker.lanta-net.ru:2710/announce", + "udp://open.stealth.si:80/announce", + "udp://open.demonii.si:1337/announce", + "udp://tracker.torrent.eu.org:451/announce", + "udp://tracker.moeking.me:6969/announce", + "udp://tracker.cyberia.is:6969/announce", + "udp://denis.stalker.upeer.me:6969/announce", + "udp://ipv4.tracker.harry.lu:80/announce", + "udp://zephir.monocul.us:6969/announce", + "udp://xxxtor.com:2710/announce", + }...) + return NewTorrent(peer.GenPeerID(), metaInfo) +} diff --git a/down/bt/tracker/errors.go b/protocol/bt/tracker/errors.go similarity index 100% rename from down/bt/tracker/errors.go rename to protocol/bt/tracker/errors.go diff --git a/down/bt/tracker/tracker.go b/protocol/bt/tracker/tracker.go similarity index 99% rename from down/bt/tracker/tracker.go rename to protocol/bt/tracker/tracker.go index f652ba35..5dd6f114 100644 --- a/down/bt/tracker/tracker.go +++ b/protocol/bt/tracker/tracker.go @@ -4,8 +4,8 @@ import ( "encoding/binary" "errors" "fmt" - "github.com/monkeyWie/gopeed/down/bt/metainfo" - "github.com/monkeyWie/gopeed/down/bt/peer" + "github.com/monkeyWie/gopeed/protocol/bt/metainfo" + "github.com/monkeyWie/gopeed/protocol/bt/peer" "io" "io/ioutil" "math" diff --git a/down/bt/tracker/tracker_test.go b/protocol/bt/tracker/tracker_test.go similarity index 90% rename from down/bt/tracker/tracker_test.go rename to protocol/bt/tracker/tracker_test.go index 906de0b7..123601b2 100644 --- a/down/bt/tracker/tracker_test.go +++ b/protocol/bt/tracker/tracker_test.go @@ -2,7 +2,7 @@ package tracker import ( "fmt" - "github.com/monkeyWie/gopeed/down/bt/metainfo" + "github.com/monkeyWie/gopeed/protocol/bt/metainfo" "testing" ) diff --git a/down/http/down.go b/protocol/http/down.go similarity index 92% rename from down/http/down.go rename to protocol/http/down.go index 2b405b2a..8dba50aa 100644 --- a/down/http/down.go +++ b/protocol/http/down.go @@ -101,10 +101,7 @@ func Down(request *Request) error { if response.Range { cons := 16 chunkSize := response.Size / int64(cons) - var ( - waitGroup = &sync.WaitGroup{} - fileLock = &sync.Mutex{} - ) + waitGroup := &sync.WaitGroup{} waitGroup.Add(cons) for i := 0; i < cons; i++ { start := int64(i) * chunkSize @@ -112,11 +109,11 @@ func Down(request *Request) error { if i == cons-1 { end = response.Size } - go downChunk(request, file, start, end-1, waitGroup, fileLock) + go downChunk(request, file, start, end-1, waitGroup) } waitGroup.Wait() } else { - downChunk(request, file, 0, response.Size, nil, nil) + downChunk(request, file, 0, response.Size, nil) } return nil } @@ -148,7 +145,7 @@ func BuildHTTPClient() *http.Client { return &http.Client{Jar: jar} } -func downChunk(request *Request, file *os.File, start int64, end int64, waitGroup *sync.WaitGroup, fileLock *sync.Mutex) { +func downChunk(request *Request, file *os.File, start int64, end int64, waitGroup *sync.WaitGroup) { if waitGroup != nil { defer waitGroup.Done() } @@ -163,13 +160,11 @@ func downChunk(request *Request, file *os.File, start int64, end int64, waitGrou } defer httpResponse.Body.Close() buf := make([]byte, 8192) - writeIndex := int64(start) + writeIndex := start for { n, err := httpResponse.Body.Read(buf) if n > 0 { - fileLock.Lock() writeSize, err := file.WriteAt(buf[0:n], writeIndex) - fileLock.Unlock() if err != nil { fmt.Println(err) return diff --git a/down/http/down_test.go b/protocol/http/down_test.go similarity index 99% rename from down/http/down_test.go rename to protocol/http/down_test.go index f644e1c6..30f9b6ed 100644 --- a/down/http/down_test.go +++ b/protocol/http/down_test.go @@ -49,6 +49,7 @@ func TestDown(t *testing.T) { return } downMd5 := fileMd5("favicon.ico") + os.Remove("favicon.ico") if "8de7a6a2e786861013d61b77b2394012" != downMd5 { t.Errorf("error md5= %v", downMd5) return diff --git a/down/http/request.go b/protocol/http/request.go similarity index 100% rename from down/http/request.go rename to protocol/http/request.go diff --git a/down/http/response.go b/protocol/http/response.go similarity index 100% rename from down/http/response.go rename to protocol/http/response.go