Skip to content

Commit

Permalink
BitTorrent HTTP、UDP tracker impl(50%)
Browse files Browse the repository at this point in the history
  • Loading branch information
monkeyWie committed May 17, 2019
1 parent 8080350 commit 41ff983
Show file tree
Hide file tree
Showing 16 changed files with 600 additions and 25 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@
# Output of the go coverage tool, specifically when used with LiteIDE
*.out

debug
debug

.idea/
18 changes: 12 additions & 6 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
{
"go.formatTool": "goimports",
"go.useLanguageServer": true,
"go.alternateTools": {
"go-langserver": "gopls"
},
"go.languageServerExperimentalFeatures": {
"format": false,
"autoComplete": true
"diagnostics": true // for diagnostics as you type
},
"[go]": {
"editor.snippetSuggestions": "none",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true
}
},
"gopls": {
"usePlaceholders": true, // add parameter placeholders when completing a function
"enhancedHover": true // experimental to improve quality of hover (will be on by default soon)
}
}
21 changes: 21 additions & 0 deletions cmd/bt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package main

import (
"gopeed/down/bt"
)

func main() {
metaInfo, _ := bt.ParseFromFile("e:/Game.of.Thrones.S08E05.720p.WEB.H264-MEMENTO.torrent")
// metaInfo, _ := down.ParseFromFile("e:/test.torrent")
if len(metaInfo.AnnounceList) > 0 {
for _, announceArr := range metaInfo.AnnounceList {
if len(announceArr) > 0 {
for _, announce := range announceArr {
bt.DoTracker(announce, metaInfo)
}
}
}
} else {
bt.DoTracker(metaInfo.Announce, metaInfo)
}
}
9 changes: 9 additions & 0 deletions cmd/test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package main

import "fmt"

func main() {
var b = -1
var n = uint32(b)
fmt.Println(n)
}
21 changes: 21 additions & 0 deletions cmd/udpclient.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package main

import (
"fmt"
"net"
)

func main() {
ip := net.ParseIP("127.0.0.1")
srcAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0}
dstAddr := &net.UDPAddr{IP: ip, Port: 9981}
conn, err := net.DialUDP("udp", srcAddr, dstAddr)
if err != nil {
fmt.Println(err)
}
defer conn.Close()
conn.Write([]byte("hello"))
conn.Write([]byte("test"))
conn.Read([]byte{})
fmt.Printf("<%s>\n", conn.RemoteAddr())
}
27 changes: 27 additions & 0 deletions cmd/udpserver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package main

import (
"fmt"
"net"
)

func main() {
conn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 9981})
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("Local: <%s> \n", conn.LocalAddr().String())
data := make([]byte, 1024)
for {
n, remoteAddr, err := conn.ReadFromUDP(data)
if err != nil {
fmt.Printf("error during read: %s", err)
}
fmt.Printf("<%s> %s\n", remoteAddr, data[:n])
_, err = conn.WriteToUDP([]byte("world"), remoteAddr)
if err != nil {
fmt.Printf(err.Error())
}
}
}
1 change: 1 addition & 0 deletions down/bt/bittorrent.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package bt
95 changes: 95 additions & 0 deletions down/bt/metainfo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package bt

import (
"crypto/sha1"
"encoding/json"
"github.com/marksamman/bencode"
"os"
)

type MetaInfo struct {
// tracker URL
// http://bittorrent.org/beps/bep_0003.html#metainfo-files
Announce string `json:"announce"`

// tracker URL
// http://bittorrent.org/beps/bep_0012.html
AnnounceList [][]string `json:"announce-list"`

Comment string `json:"comment"`

CreatedBy string `json:"created by"`

CreationDate int64 `json:"creation date"`

Encoding string `json:"encoding"`

// http://bittorrent.org/beps/bep_0019.html
UrlList []string `json:"url-list"`

Info *Info `json:"info"`
InfoHash [20]byte `json:"-"`
}

type Info struct {
Name string `json:"name"`
PieceLength uint64 `json:"piece length"`
Pieces []string
Length uint64 `json:"length"`
Files []File `json:"files"`
}

type File struct {
Length uint64 `json:"length"`
Path string `json:"path"`
}

func (metaInfo *MetaInfo) GetTotalSize() uint64 {
if metaInfo.Info != nil {
if len(metaInfo.Info.Files) > 0 {
var length uint64
for _, f := range metaInfo.Info.Files {
length += f.Length
}
return length
} else {
return metaInfo.Info.Length
}
}
return 0
}

func ParseFromFile(path string) (*MetaInfo, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
// http://bittorrent.org/beps/bep_0003.html#bencoding
btDecode, err := bencode.Decode(file)
if err != nil {
return nil, err
}
bytes, err := json.Marshal(btDecode)
if err != nil {
return nil, err
}
var metaInfo MetaInfo
json.Unmarshal(bytes, &metaInfo)
if metaInfo.Info != nil {
// Encode info hash
info := btDecode["info"].(map[string]interface{})
infoBtEncode := bencode.Encode(info)
metaInfo.InfoHash = sha1.Sum(infoBtEncode[:])
// Split pieces hash
pieces := info["pieces"].(string)
if pieces != "" {
metaInfo.Info.Pieces = make([]string, len(pieces)/20)
// pieces parse
for i := range metaInfo.Info.Pieces {
begin := i * 20
metaInfo.Info.Pieces[i] = pieces[begin : begin+20]
}
}
}
return &metaInfo, nil
}
Loading

0 comments on commit 41ff983

Please sign in to comment.