mirror of
https://github.com/ap-pauloafonso/ratio-spoof.git
synced 2026-04-21 16:41:57 +00:00
initial clean up
This commit is contained in:
parent
fe5c6bde7a
commit
bcd8f91ebb
4 changed files with 159 additions and 161 deletions
|
|
@ -1,17 +1,110 @@
|
||||||
package beencode
|
package beencode
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha1"
|
||||||
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
dictToken = byte('d')
|
dictToken = byte('d')
|
||||||
numberToken = byte('i')
|
numberToken = byte('i')
|
||||||
listToken = byte('l')
|
listToken = byte('l')
|
||||||
endOfCollectionToken = byte('e')
|
endOfCollectionToken = byte('e')
|
||||||
lengthValueStringSeparator = byte(':')
|
lengthValueStringSeparatorToken = byte(':')
|
||||||
|
|
||||||
|
torrentInfoKey = "info"
|
||||||
|
torrentNameKey = "name"
|
||||||
|
torrentPieceLengthKey = "piece length"
|
||||||
|
torrentLengthKey = "length"
|
||||||
|
torrentFilesKey = "files"
|
||||||
|
mainAnnounceKey = "announce"
|
||||||
|
announceListKey = "announce-list"
|
||||||
|
torrentDictOffsetsKey = "byte_offsets"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TorrentInfo contains all relevant information extracted from a beencode file
|
||||||
|
type TorrentInfo struct {
|
||||||
|
Name string
|
||||||
|
PieceSize int
|
||||||
|
TotalSize int
|
||||||
|
TrackerInfo *TrackerInfo
|
||||||
|
InfoHashURLEncoded string
|
||||||
|
}
|
||||||
|
|
||||||
|
//TrackerInfo contains http urls from the tracker
|
||||||
|
type TrackerInfo struct {
|
||||||
|
Main string
|
||||||
|
Urls []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type torrentDict struct {
|
||||||
|
resultMap map[string]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TorrentDictParse decodes the beencoded bytes and builds the torrentInfo file
|
||||||
|
func TorrentDictParse(dat []byte) (*TorrentInfo, error) {
|
||||||
|
dict, _ := mapParse(0, &dat)
|
||||||
|
torrentMap := torrentDict{resultMap: dict}
|
||||||
|
return &TorrentInfo{
|
||||||
|
Name: torrentMap.resultMap[torrentInfoKey].(map[string]interface{})[torrentNameKey].(string),
|
||||||
|
PieceSize: torrentMap.resultMap[torrentInfoKey].(map[string]interface{})[torrentPieceLengthKey].(int),
|
||||||
|
TotalSize: torrentMap.extractTotalSize(),
|
||||||
|
TrackerInfo: torrentMap.extractTrackerInfo(),
|
||||||
|
InfoHashURLEncoded: torrentMap.extractInfoHashURLEncoded(dat),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (T *torrentDict) extractInfoHashURLEncoded(rawData []byte) string {
|
||||||
|
byteOffsets := T.resultMap[torrentInfoKey].(map[string]interface{})[torrentDictOffsetsKey].([]int)
|
||||||
|
h := sha1.New()
|
||||||
|
h.Write([]byte(rawData[byteOffsets[0]:byteOffsets[1]]))
|
||||||
|
ret := h.Sum(nil)
|
||||||
|
return url.QueryEscape(string(ret))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (T *torrentDict) extractTotalSize() int {
|
||||||
|
if value, ok := T.resultMap[torrentInfoKey].(map[string]interface{})[torrentLengthKey]; ok {
|
||||||
|
return value.(int)
|
||||||
|
}
|
||||||
|
var total int
|
||||||
|
|
||||||
|
for _, file := range T.resultMap[torrentInfoKey].(map[string]interface{})[torrentFilesKey].([]interface{}) {
|
||||||
|
total += file.(map[string]interface{})[torrentLengthKey].(int)
|
||||||
|
}
|
||||||
|
return total
|
||||||
|
}
|
||||||
|
|
||||||
|
func (T *torrentDict) extractTrackerInfo() *TrackerInfo {
|
||||||
|
uniqueUrls := make(map[string]int)
|
||||||
|
currentCount := 0
|
||||||
|
if main, ok := T.resultMap[mainAnnounceKey]; ok {
|
||||||
|
if _, found := uniqueUrls[main.(string)]; !found {
|
||||||
|
uniqueUrls[main.(string)] = currentCount
|
||||||
|
currentCount++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if list, ok := T.resultMap[announceListKey]; ok {
|
||||||
|
for _, innerList := range list.([]interface{}) {
|
||||||
|
for _, item := range innerList.([]interface{}) {
|
||||||
|
if _, found := uniqueUrls[item.(string)]; !found {
|
||||||
|
uniqueUrls[item.(string)] = currentCount
|
||||||
|
currentCount++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
trackerInfo := TrackerInfo{Urls: make([]string, len(uniqueUrls))}
|
||||||
|
for key, value := range uniqueUrls {
|
||||||
|
trackerInfo.Urls[value] = key
|
||||||
|
}
|
||||||
|
|
||||||
|
trackerInfo.Main = trackerInfo.Urls[0]
|
||||||
|
return &trackerInfo
|
||||||
|
}
|
||||||
|
|
||||||
//Decode accepts a byte slice and returns a map with information parsed.(panic if it fails)
|
//Decode accepts a byte slice and returns a map with information parsed.(panic if it fails)
|
||||||
func Decode(data []byte) map[string]interface{} {
|
func Decode(data []byte) map[string]interface{} {
|
||||||
result, _ := findParse(0, &data)
|
result, _ := findParse(0, &data)
|
||||||
|
|
@ -76,7 +169,7 @@ func numberParse(startIdx int, data *[]byte) (result int, nextIdx int) {
|
||||||
|
|
||||||
func stringParse(startIdx int, data *[]byte) (result string, nextIdx int) {
|
func stringParse(startIdx int, data *[]byte) (result string, nextIdx int) {
|
||||||
current := startIdx
|
current := startIdx
|
||||||
for (*data)[current : current+1][0] != lengthValueStringSeparator {
|
for (*data)[current : current+1][0] != lengthValueStringSeparatorToken {
|
||||||
current++
|
current++
|
||||||
}
|
}
|
||||||
sizeStr, _ := strconv.Atoi(string(((*data)[startIdx:current])))
|
sizeStr, _ := strconv.Atoi(string(((*data)[startIdx:current])))
|
||||||
|
|
|
||||||
|
|
@ -5,38 +5,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGenerateRandomPeerId(T *testing.T) {
|
|
||||||
T.Run("PeerIds are different", func(t *testing.T) {
|
|
||||||
keys := make(map[string]bool)
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
obj := NewQbitTorrent()
|
|
||||||
key := obj.PeerID()
|
|
||||||
t.Log(key)
|
|
||||||
if _, ok := keys[key]; ok {
|
|
||||||
t.Error("peerId must be random")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
keys[key] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGenerateRandomKey(T *testing.T) {
|
func TestGenerateRandomKey(T *testing.T) {
|
||||||
T.Run("Keys are different", func(t *testing.T) {
|
|
||||||
keys := make(map[string]bool)
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
obj := NewQbitTorrent()
|
|
||||||
key := obj.Key()
|
|
||||||
t.Log(key)
|
|
||||||
if _, ok := keys[key]; ok {
|
|
||||||
t.Error("Keys must be random")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
keys[key] = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
T.Run("Key has 8 length", func(t *testing.T) {
|
T.Run("Key has 8 length", func(t *testing.T) {
|
||||||
obj := NewQbitTorrent()
|
obj := NewQbitTorrent()
|
||||||
key := obj.Key()
|
key := obj.Key()
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ func (R *ratioSpoofState) PrintState(exitedCH <-chan string) {
|
||||||
if R.retryAttempt > 0 {
|
if R.retryAttempt > 0 {
|
||||||
retryStr = fmt.Sprintf("(*Retry %v - check your connection)", R.retryAttempt)
|
retryStr = fmt.Sprintf("(*Retry %v - check your connection)", R.retryAttempt)
|
||||||
}
|
}
|
||||||
fmt.Println(center(" RATIO-SPOOF ", width-len(" RATIO-SPOOF "), "#"))
|
fmt.Printf("%s\n", center(" RATIO-SPOOF ", width-len(" RATIO-SPOOF "), "#"))
|
||||||
fmt.Printf(`
|
fmt.Printf(`
|
||||||
Torrent: %v
|
Torrent: %v
|
||||||
Tracker: %v
|
Tracker: %v
|
||||||
|
|
@ -47,20 +47,15 @@ func (R *ratioSpoofState) PrintState(exitedCH <-chan string) {
|
||||||
Download Speed: %v/s
|
Download Speed: %v/s
|
||||||
Upload Speed: %v/s
|
Upload Speed: %v/s
|
||||||
Size: %v
|
Size: %v
|
||||||
Emulation: %v | Port: %v`, R.torrentInfo.name, R.torrentInfo.trackerInfo.main, seedersStr, leechersStr, humanReadableSize(float64(R.input.downloadSpeed)),
|
Emulation: %v | Port: %v`, R.torrentInfo.Name, R.torrentInfo.TrackerInfo.Main, seedersStr, leechersStr, humanReadableSize(float64(R.input.downloadSpeed)),
|
||||||
humanReadableSize(float64(R.input.uploadSpeed)), humanReadableSize(float64(R.torrentInfo.totalSize)), R.bitTorrentClient.Name(), R.input.port)
|
humanReadableSize(float64(R.input.uploadSpeed)), humanReadableSize(float64(R.torrentInfo.TotalSize)), R.bitTorrentClient.Name(), R.input.port)
|
||||||
fmt.Println()
|
fmt.Printf("\n\n%s\n\n", center(" GITHUB.COM/AP-PAULOAFONSO/RATIO-SPOOF ", width-len(" GITHUB.COM/AP-PAULOAFONSO/RATIO-SPOOF "), "#"))
|
||||||
fmt.Println()
|
|
||||||
fmt.Println(center(" GITHUB.COM/AP-PAULOAFONSO/RATIO-SPOOF ", width-len(" GITHUB.COM/AP-PAULOAFONSO/RATIO-SPOOF "), "#"))
|
|
||||||
fmt.Println()
|
|
||||||
for i := 0; i <= R.announceHistory.Len()-2; i++ {
|
for i := 0; i <= R.announceHistory.Len()-2; i++ {
|
||||||
dequeItem := R.announceHistory.At(i).(announceEntry)
|
dequeItem := R.announceHistory.At(i).(announceEntry)
|
||||||
fmt.Printf("#%v downloaded: %v(%.2f%%) | left: %v | uploaded: %v | announced", dequeItem.count, humanReadableSize(float64(dequeItem.downloaded)), dequeItem.percentDownloaded, humanReadableSize(float64(dequeItem.left)), humanReadableSize(float64(dequeItem.uploaded)))
|
fmt.Printf("#%v downloaded: %v(%.2f%%) | left: %v | uploaded: %v | announced\n", dequeItem.count, humanReadableSize(float64(dequeItem.downloaded)), dequeItem.percentDownloaded, humanReadableSize(float64(dequeItem.left)), humanReadableSize(float64(dequeItem.uploaded)))
|
||||||
fmt.Println()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
lastDequeItem := R.announceHistory.At(R.announceHistory.Len() - 1).(announceEntry)
|
lastDequeItem := R.announceHistory.At(R.announceHistory.Len() - 1).(announceEntry)
|
||||||
fmt.Printf("#%v downloaded: %v(%.2f%%) | left: %v | uploaded: %v | next announce in: %v %v", lastDequeItem.count,
|
fmt.Printf("#%v downloaded: %v(%.2f%%) | left: %v | uploaded: %v | next announce in: %v %v\n", lastDequeItem.count,
|
||||||
humanReadableSize(float64(lastDequeItem.downloaded)),
|
humanReadableSize(float64(lastDequeItem.downloaded)),
|
||||||
lastDequeItem.percentDownloaded,
|
lastDequeItem.percentDownloaded,
|
||||||
humanReadableSize(float64(lastDequeItem.left)),
|
humanReadableSize(float64(lastDequeItem.left)),
|
||||||
|
|
@ -69,14 +64,8 @@ func (R *ratioSpoofState) PrintState(exitedCH <-chan string) {
|
||||||
retryStr)
|
retryStr)
|
||||||
|
|
||||||
if R.input.debug {
|
if R.input.debug {
|
||||||
fmt.Println()
|
fmt.Printf("\n%s\n", center(" DEBUG ", width-len(" DEBUG "), "#"))
|
||||||
fmt.Println()
|
fmt.Printf("\n%s\n\n%s", R.lastAnounceRequest, R.lastTackerResponse)
|
||||||
fmt.Println(center(" DEBUG ", width-len(" DEBUG "), "#"))
|
|
||||||
fmt.Println()
|
|
||||||
fmt.Print(R.lastAnounceRequest)
|
|
||||||
fmt.Println()
|
|
||||||
fmt.Println()
|
|
||||||
fmt.Print(R.lastTackerResponse)
|
|
||||||
}
|
}
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,12 @@ package ratiospoof
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"crypto/sha1"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math"
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
@ -33,8 +31,9 @@ var validSpeedSufixes = [...]string{"kbps", "mbps"}
|
||||||
type ratioSpoofState struct {
|
type ratioSpoofState struct {
|
||||||
mutex *sync.Mutex
|
mutex *sync.Mutex
|
||||||
httpClient HttpClient
|
httpClient HttpClient
|
||||||
torrentInfo *torrentInfo
|
torrentInfo *beencode.TorrentInfo
|
||||||
input *inputParsed
|
input *inputParsed
|
||||||
|
trackerState *httpTracker
|
||||||
bitTorrentClient TorrentClientEmulation
|
bitTorrentClient TorrentClientEmulation
|
||||||
currentAnnounceTimer int
|
currentAnnounceTimer int
|
||||||
announceInterval int
|
announceInterval int
|
||||||
|
|
@ -48,6 +47,30 @@ type ratioSpoofState struct {
|
||||||
lastTackerResponse string
|
lastTackerResponse string
|
||||||
retryAttempt int
|
retryAttempt int
|
||||||
}
|
}
|
||||||
|
type httpTracker struct {
|
||||||
|
urls []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newHttpTracker(torrentInfo *beencode.TorrentInfo) (*httpTracker, error) {
|
||||||
|
|
||||||
|
var result []string
|
||||||
|
for _, url := range torrentInfo.TrackerInfo.Urls {
|
||||||
|
if strings.HasPrefix(url, "http") {
|
||||||
|
result = append(result, url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(result) == 0 {
|
||||||
|
return nil, errors.New("No tcp/http tracker url announce found")
|
||||||
|
}
|
||||||
|
return &httpTracker{urls: torrentInfo.TrackerInfo.Urls}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (T *httpTracker) SwapFirst(currentIdx int) {
|
||||||
|
aux := T.urls[0]
|
||||||
|
T.urls[0] = T.urls[currentIdx]
|
||||||
|
T.urls[currentIdx] = aux
|
||||||
|
}
|
||||||
|
|
||||||
type InputArgs struct {
|
type InputArgs struct {
|
||||||
TorrentPath string
|
TorrentPath string
|
||||||
InitialDownloaded string
|
InitialDownloaded string
|
||||||
|
|
@ -68,34 +91,12 @@ type inputParsed struct {
|
||||||
debug bool
|
debug bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type torrentInfo struct {
|
func (I *InputArgs) parseInput(torrentInfo *beencode.TorrentInfo) (*inputParsed, error) {
|
||||||
name string
|
downloaded, err := extractInputInitialByteCount(I.InitialDownloaded, torrentInfo.TotalSize, true)
|
||||||
pieceSize int
|
|
||||||
totalSize int
|
|
||||||
trackerInfo trackerInfo
|
|
||||||
infoHashURLEncoded string
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractTorrentInfo(torrentPath string) (*torrentInfo, error) {
|
|
||||||
dat, err := ioutil.ReadFile(torrentPath)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
torrentMap := beencode.Decode(dat)
|
uploaded, err := extractInputInitialByteCount(I.InitialUploaded, torrentInfo.TotalSize, false)
|
||||||
return &torrentInfo{
|
|
||||||
name: torrentMap["info"].(map[string]interface{})["name"].(string),
|
|
||||||
pieceSize: torrentMap["info"].(map[string]interface{})["piece length"].(int),
|
|
||||||
totalSize: extractTotalSize(torrentMap),
|
|
||||||
trackerInfo: extractTrackerInfo(torrentMap),
|
|
||||||
infoHashURLEncoded: extractInfoHashURLEncoded(dat, torrentMap),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
func (I *InputArgs) parseInput(torrentInfo *torrentInfo) (*inputParsed, error) {
|
|
||||||
downloaded, err := extractInputInitialByteCount(I.InitialDownloaded, torrentInfo.totalSize, true)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
uploaded, err := extractInputInitialByteCount(I.InitialUploaded, torrentInfo.totalSize, false)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -123,7 +124,17 @@ func (I *InputArgs) parseInput(torrentInfo *torrentInfo) (*inputParsed, error) {
|
||||||
|
|
||||||
func NewRatioSPoofState(input InputArgs, torrentClient TorrentClientEmulation, httpclient HttpClient) (*ratioSpoofState, error) {
|
func NewRatioSPoofState(input InputArgs, torrentClient TorrentClientEmulation, httpclient HttpClient) (*ratioSpoofState, error) {
|
||||||
|
|
||||||
torrentInfo, err := extractTorrentInfo(input.TorrentPath)
|
dat, err := ioutil.ReadFile(input.TorrentPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
torrentInfo, err := beencode.TorrentDictParse(dat)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
httpTracker, err := newHttpTracker(torrentInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
@ -137,6 +148,7 @@ func NewRatioSPoofState(input InputArgs, torrentClient TorrentClientEmulation, h
|
||||||
bitTorrentClient: torrentClient,
|
bitTorrentClient: torrentClient,
|
||||||
httpClient: httpclient,
|
httpClient: httpclient,
|
||||||
torrentInfo: torrentInfo,
|
torrentInfo: torrentInfo,
|
||||||
|
trackerState: httpTracker,
|
||||||
input: inputParsed,
|
input: inputParsed,
|
||||||
numWant: 200,
|
numWant: 200,
|
||||||
status: "started",
|
status: "started",
|
||||||
|
|
@ -183,17 +195,6 @@ func extractInputByteSpeed(initialSpeedInput string) (int, error) {
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type trackerInfo struct {
|
|
||||||
main string
|
|
||||||
urls []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (T *trackerInfo) SwapFirst(currentIdx int) {
|
|
||||||
aux := T.urls[0]
|
|
||||||
T.urls[0] = T.urls[currentIdx]
|
|
||||||
T.urls[currentIdx] = aux
|
|
||||||
}
|
|
||||||
|
|
||||||
type trackerResponse struct {
|
type trackerResponse struct {
|
||||||
minInterval int
|
minInterval int
|
||||||
interval int
|
interval int
|
||||||
|
|
@ -261,7 +262,7 @@ func (R *ratioSpoofState) Run() {
|
||||||
}
|
}
|
||||||
func (R *ratioSpoofState) firstAnnounce() {
|
func (R *ratioSpoofState) firstAnnounce() {
|
||||||
println("Trying to connect to the tracker...")
|
println("Trying to connect to the tracker...")
|
||||||
R.addAnnounce(R.input.initialDownloaded, R.input.initialUploaded, calculateBytesLeft(R.input.initialDownloaded, R.torrentInfo.totalSize), (float32(R.input.initialDownloaded)/float32(R.torrentInfo.totalSize))*100)
|
R.addAnnounce(R.input.initialDownloaded, R.input.initialUploaded, calculateBytesLeft(R.input.initialDownloaded, R.torrentInfo.TotalSize), (float32(R.input.initialDownloaded)/float32(R.torrentInfo.TotalSize))*100)
|
||||||
R.fireAnnounce(false)
|
R.fireAnnounce(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -283,7 +284,7 @@ func (R *ratioSpoofState) addAnnounce(currentDownloaded, currentUploaded, curren
|
||||||
}
|
}
|
||||||
func (R *ratioSpoofState) fireAnnounce(retry bool) {
|
func (R *ratioSpoofState) fireAnnounce(retry bool) {
|
||||||
lastAnnounce := R.announceHistory.Back().(announceEntry)
|
lastAnnounce := R.announceHistory.Back().(announceEntry)
|
||||||
replacer := strings.NewReplacer("{infohash}", R.torrentInfo.infoHashURLEncoded,
|
replacer := strings.NewReplacer("{infohash}", R.torrentInfo.InfoHashURLEncoded,
|
||||||
"{port}", fmt.Sprint(R.input.port),
|
"{port}", fmt.Sprint(R.input.port),
|
||||||
"{peerid}", R.bitTorrentClient.PeerID(),
|
"{peerid}", R.bitTorrentClient.PeerID(),
|
||||||
"{uploaded}", fmt.Sprint(lastAnnounce.uploaded),
|
"{uploaded}", fmt.Sprint(lastAnnounce.uploaded),
|
||||||
|
|
@ -334,20 +335,20 @@ func (R *ratioSpoofState) generateNextAnnounce() {
|
||||||
currentDownloaded := lastAnnounce.downloaded
|
currentDownloaded := lastAnnounce.downloaded
|
||||||
var downloadCandidate int
|
var downloadCandidate int
|
||||||
|
|
||||||
if currentDownloaded < R.torrentInfo.totalSize {
|
if currentDownloaded < R.torrentInfo.TotalSize {
|
||||||
downloadCandidate = calculateNextTotalSizeByte(R.input.downloadSpeed, currentDownloaded, R.torrentInfo.pieceSize, R.currentAnnounceTimer, R.torrentInfo.totalSize)
|
downloadCandidate = calculateNextTotalSizeByte(R.input.downloadSpeed, currentDownloaded, R.torrentInfo.PieceSize, R.currentAnnounceTimer, R.torrentInfo.TotalSize)
|
||||||
} else {
|
} else {
|
||||||
downloadCandidate = R.torrentInfo.totalSize
|
downloadCandidate = R.torrentInfo.TotalSize
|
||||||
}
|
}
|
||||||
|
|
||||||
currentUploaded := lastAnnounce.uploaded
|
currentUploaded := lastAnnounce.uploaded
|
||||||
uploadCandidate := calculateNextTotalSizeByte(R.input.uploadSpeed, currentUploaded, R.torrentInfo.pieceSize, R.currentAnnounceTimer, 0)
|
uploadCandidate := calculateNextTotalSizeByte(R.input.uploadSpeed, currentUploaded, R.torrentInfo.PieceSize, R.currentAnnounceTimer, 0)
|
||||||
|
|
||||||
leftCandidate := calculateBytesLeft(downloadCandidate, R.torrentInfo.totalSize)
|
leftCandidate := calculateBytesLeft(downloadCandidate, R.torrentInfo.TotalSize)
|
||||||
|
|
||||||
d, u, l := R.bitTorrentClient.NextAmountReport(downloadCandidate, uploadCandidate, leftCandidate, R.torrentInfo.pieceSize)
|
d, u, l := R.bitTorrentClient.NextAmountReport(downloadCandidate, uploadCandidate, leftCandidate, R.torrentInfo.PieceSize)
|
||||||
|
|
||||||
R.addAnnounce(d, u, l, (float32(d)/float32(R.torrentInfo.totalSize))*100)
|
R.addAnnounce(d, u, l, (float32(d)/float32(R.torrentInfo.TotalSize))*100)
|
||||||
}
|
}
|
||||||
func (R *ratioSpoofState) decreaseTimer() {
|
func (R *ratioSpoofState) decreaseTimer() {
|
||||||
for {
|
for {
|
||||||
|
|
@ -367,7 +368,7 @@ func (R *ratioSpoofState) changeCurrentTimer(newAnnounceRate int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (R *ratioSpoofState) tryMakeRequest(query string) *trackerResponse {
|
func (R *ratioSpoofState) tryMakeRequest(query string) *trackerResponse {
|
||||||
for idx, url := range R.torrentInfo.trackerInfo.urls {
|
for idx, url := range R.torrentInfo.TrackerInfo.Urls {
|
||||||
completeURL := url + "?" + strings.TrimLeft(query, "?")
|
completeURL := url + "?" + strings.TrimLeft(query, "?")
|
||||||
R.lastAnounceRequest = completeURL
|
R.lastAnounceRequest = completeURL
|
||||||
req, _ := http.NewRequest("GET", completeURL, nil)
|
req, _ := http.NewRequest("GET", completeURL, nil)
|
||||||
|
|
@ -390,7 +391,7 @@ func (R *ratioSpoofState) tryMakeRequest(query string) *trackerResponse {
|
||||||
R.lastTackerResponse = string(bytesR)
|
R.lastTackerResponse = string(bytesR)
|
||||||
decodedResp := beencode.Decode(bytesR)
|
decodedResp := beencode.Decode(bytesR)
|
||||||
if idx != 0 {
|
if idx != 0 {
|
||||||
R.torrentInfo.trackerInfo.SwapFirst(idx)
|
R.trackerState.SwapFirst(idx)
|
||||||
}
|
}
|
||||||
ret := extractTrackerResponse(decodedResp)
|
ret := extractTrackerResponse(decodedResp)
|
||||||
return &ret
|
return &ret
|
||||||
|
|
@ -416,60 +417,6 @@ func calculateNextTotalSizeByte(speedBytePerSecond, currentByte, pieceSizeByte,
|
||||||
return totalCandidate
|
return totalCandidate
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractInfoHashURLEncoded(rawData []byte, torrentData map[string]interface{}) string {
|
|
||||||
byteOffsets := torrentData["info"].(map[string]interface{})["byte_offsets"].([]int)
|
|
||||||
h := sha1.New()
|
|
||||||
h.Write([]byte(rawData[byteOffsets[0]:byteOffsets[1]]))
|
|
||||||
ret := h.Sum(nil)
|
|
||||||
return url.QueryEscape(string(ret))
|
|
||||||
|
|
||||||
}
|
|
||||||
func extractTotalSize(torrentData map[string]interface{}) int {
|
|
||||||
if value, ok := torrentData["info"].(map[string]interface{})["length"]; ok {
|
|
||||||
return value.(int)
|
|
||||||
}
|
|
||||||
|
|
||||||
var total int
|
|
||||||
|
|
||||||
for _, file := range torrentData["info"].(map[string]interface{})["files"].([]interface{}) {
|
|
||||||
total += file.(map[string]interface{})["length"].(int)
|
|
||||||
}
|
|
||||||
return total
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractTrackerInfo(torrentData map[string]interface{}) trackerInfo {
|
|
||||||
uniqueUrls := make(map[string]int)
|
|
||||||
currentCount := 0
|
|
||||||
if main, ok := torrentData["announce"]; ok && strings.HasPrefix(main.(string), "http") {
|
|
||||||
if _, found := uniqueUrls[main.(string)]; !found {
|
|
||||||
uniqueUrls[main.(string)] = currentCount
|
|
||||||
currentCount++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if list, ok := torrentData["announce-list"]; ok {
|
|
||||||
for _, innerList := range list.([]interface{}) {
|
|
||||||
for _, item := range innerList.([]interface{}) {
|
|
||||||
if _, found := uniqueUrls[item.(string)]; !found && strings.HasPrefix(item.(string), "http") {
|
|
||||||
uniqueUrls[item.(string)] = currentCount
|
|
||||||
currentCount++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
trackerInfo := trackerInfo{urls: make([]string, len(uniqueUrls))}
|
|
||||||
for key, value := range uniqueUrls {
|
|
||||||
trackerInfo.urls[value] = key
|
|
||||||
}
|
|
||||||
|
|
||||||
trackerInfo.main = trackerInfo.urls[0]
|
|
||||||
|
|
||||||
if len(trackerInfo.urls) == 0 {
|
|
||||||
panic("No tcp/http tracker url announce found'")
|
|
||||||
}
|
|
||||||
return trackerInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractTrackerResponse(datatrackerResponse map[string]interface{}) trackerResponse {
|
func extractTrackerResponse(datatrackerResponse map[string]interface{}) trackerResponse {
|
||||||
var result trackerResponse
|
var result trackerResponse
|
||||||
if v, ok := datatrackerResponse["failure reason"].(string); ok && len(v) > 0 {
|
if v, ok := datatrackerResponse["failure reason"].(string); ok && len(v) > 0 {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue