From c1a86a8091dec4f09d1ca686d656dfe503e3e321 Mon Sep 17 00:00:00 2001 From: ap-pauloafonso Date: Fri, 12 Mar 2021 23:15:18 -0300 Subject: [PATCH] initial multiple-client build --- build.sh | 17 ----- cmd/main.go | 11 +-- go.mod | 6 +- go.sum | 27 ++++++++ internal/emulation/emulation.go | 84 +++++++++++++++++++++++ internal/emulation/emulation_test.go | 74 ++++++++++++++++++++ internal/emulation/qbittorrent.go | 83 ---------------------- internal/emulation/qbittorrent_test.go | 26 ------- internal/emulation/static/qbit-4.0.3.json | 17 +++++ internal/emulation/static/qbit-4.3.2.json | 17 +++++ internal/generator/key.go | 27 ++++++++ internal/generator/peerId.go | 25 +++++++ internal/generator/rouding.go | 20 ++++++ internal/generator/rounding_test.go | 21 ++++++ internal/input/input.go | 1 + internal/printer/printer.go | 2 +- internal/ratiospoof/ratiospoof.go | 31 ++++----- makefile | 15 ++++ 18 files changed, 354 insertions(+), 150 deletions(-) delete mode 100755 build.sh create mode 100644 internal/emulation/emulation.go create mode 100644 internal/emulation/emulation_test.go delete mode 100644 internal/emulation/qbittorrent.go delete mode 100644 internal/emulation/qbittorrent_test.go create mode 100644 internal/emulation/static/qbit-4.0.3.json create mode 100644 internal/emulation/static/qbit-4.3.2.json create mode 100644 internal/generator/key.go create mode 100644 internal/generator/peerId.go create mode 100644 internal/generator/rouding.go create mode 100644 internal/generator/rounding_test.go create mode 100644 makefile diff --git a/build.sh b/build.sh deleted file mode 100755 index 465b186..0000000 --- a/build.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh - -version=$1 - -if [ -z "$version" ]; then - echo "usage: $0 " - exit 1 -fi - -rm -rf ./out - -env GOOS=darwin GOARCH=amd64 go build -v -o ./out/mac/ratio-spoof github.com/ap-pauloafonso/ratio-spoof/cmd -env GOOS=linux GOARCH=amd64 go build -v -o ./out/linux/ratio-spoof github.com/ap-pauloafonso/ratio-spoof/cmd -env GOOS=windows GOARCH=amd64 go build -v -o ./out/windows/ratio-spoof.exe github.com/ap-pauloafonso/ratio-spoof/cmd - -cd out/ -zip ratio-spoof-$version\(linux-mac-windows\).zip -r . \ No newline at end of file diff --git a/cmd/main.go b/cmd/main.go index ba476f3..1b7e365 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -6,7 +6,6 @@ import ( "log" "os" - "github.com/ap-pauloafonso/ratio-spoof/internal/emulation" "github.com/ap-pauloafonso/ratio-spoof/internal/input" "github.com/ap-pauloafonso/ratio-spoof/internal/printer" "github.com/ap-pauloafonso/ratio-spoof/internal/ratiospoof" @@ -24,13 +23,15 @@ func main() { //optional port := flag.Int("p", 8999, "a PORT") debug := flag.Bool("debug", false, "") + client := flag.String("c", "qbit-4.0.3", "emulated client") flag.Usage = func() { fmt.Printf("usage: %s -t -d -ds -u -us \n", os.Args[0]) fmt.Print(` optional arguments: -h show this help message and exit - -p [PORT] change the port number, the default is 8999 + -p [PORT] change the port number, default: 8999 + -c [CLIENT_CODE] change the client emulation, default: qbit-4.0.3 required arguments: -t @@ -41,6 +42,7 @@ required arguments: and must be in %, b, kb, mb, gb, tb and must be in kbps, mbps +[CLIENT_CODE] options: qbit-4.0.3, qbit-4.3.2 `) } @@ -51,7 +53,6 @@ required arguments: return } - qbit := emulation.NewQbitTorrent() r, err := ratiospoof.NewRatioSpoofState( input.InputArgs{ TorrentPath: *torrentPath, @@ -61,8 +62,8 @@ required arguments: UploadSpeed: *uploadSpeed, Port: *port, Debug: *debug, - }, - qbit) + Client: *client, + }) if err != nil { log.Fatalln(err) diff --git a/go.mod b/go.mod index b742036..51b6bb5 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,13 @@ module github.com/ap-pauloafonso/ratio-spoof -go 1.15 +go 1.16 require ( github.com/gammazero/deque v0.0.0-20201010052221-3932da5530cc + github.com/google/gxui v0.0.0-20151028112939-f85e0a97b3a4 // indirect github.com/olekukonko/ts v0.0.0-20171002115256-78ecb04241c0 + github.com/smartystreets/goconvey v1.6.4 // indirect + github.com/stretchr/testify v1.7.0 // indirect + github.com/zach-klippenstein/goregen v0.0.0-20160303162051-795b5e3961ea golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 // indirect ) diff --git a/go.sum b/go.sum index ab6ce33..c235bf8 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,33 @@ +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/gammazero/deque v0.0.0-20201010052221-3932da5530cc h1:F7BbnLACph7UYiz9ZHi6npcROwKaZUyviDjsNERsoMM= github.com/gammazero/deque v0.0.0-20201010052221-3932da5530cc/go.mod h1:IlBLfYXnuw9sspy1XS6ctu5exGb6WHGKQsyo4s7bOEA= +github.com/google/gxui v0.0.0-20151028112939-f85e0a97b3a4 h1:OL2d27ueTKnlQJoqLW2fc9pWYulFnJYLWzomGV7HqZo= +github.com/google/gxui v0.0.0-20151028112939-f85e0a97b3a4/go.mod h1:Pw1H1OjSNHiqeuxAduB1BKYXIwFtsyrY47nEqSgEiCM= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/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/olekukonko/ts v0.0.0-20171002115256-78ecb04241c0 h1:LiZB1h0GIcudcDci2bxbqI6DXV8bF8POAnArqvRrIyw= github.com/olekukonko/ts v0.0.0-20171002115256-78ecb04241c0/go.mod h1:F/7q8/HZz+TXjlsoZQQKVYvXTZaFH4QRa3y+j1p7MS0= +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/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/zach-klippenstein/goregen v0.0.0-20160303162051-795b5e3961ea h1:CyhwejzVGvZ3Q2PSbQ4NRRYn+ZWv5eS1vlaEusT+bAI= +github.com/zach-klippenstein/goregen v0.0.0-20160303162051-795b5e3961ea/go.mod h1:eNr558nEUjP8acGw8FFjTeWvSgU1stO7FAO6eknhHe4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/emulation/emulation.go b/internal/emulation/emulation.go new file mode 100644 index 0000000..ded8134 --- /dev/null +++ b/internal/emulation/emulation.go @@ -0,0 +1,84 @@ +package emulation + +import ( + "embed" + "encoding/json" + "io/ioutil" + + "github.com/ap-pauloafonso/ratio-spoof/internal/generator" +) + +type ClientInfo struct { + Name string `json:"name"` + PeerID struct { + Generator string `json:"generator"` + Regex string `json:"regex"` + } `json:"peerId"` + Key struct { + Generator string `json:"generator"` + Regex string `json:"regex"` + } `json:"key"` + Rounding struct { + Generator string `json:"generator"` + Regex string `json:"regex"` + } `json:"rounding"` + Query string `json:"query"` + Headers map[string]string `json:"headers"` +} + +type Emulation struct { + PeerIdGenerator generator.PeerIdGenerator + KeyGenerator generator.KeyGenerator + Query string + Name string + Headers map[string]string + RoudingGenerator generator.RoundingGenerator +} + +func NewEmulation(code string) (*Emulation, error) { + c, err := extractClient(code) + if err != nil { + return nil, err + } + + peerG, err := generator.NewPeerIdGenerator(c.PeerID.Generator, c.PeerID.Regex) + if err != nil { + return nil, err + } + + keyG, err := generator.NewKeyGenerator(c.Key.Generator) + if err != nil { + return nil, err + } + + roudingG, err := generator.NewRoundingGenerator(c.Rounding.Generator) + if err != nil { + return nil, err + } + + return &Emulation{PeerIdGenerator: peerG, KeyGenerator: keyG, RoudingGenerator: roudingG, + Headers: c.Headers, Name: c.Name, Query: c.Query}, nil + +} + +//go:embed static +var staticFiles embed.FS + +func extractClient(code string) (*ClientInfo, error) { + + f, err := staticFiles.Open("static/" + code + ".json") + if err != nil { + return nil, err + } + + bytes, err := ioutil.ReadAll(f) + if err != nil { + return nil, err + } + + var client ClientInfo + + json.Unmarshal(bytes, &client) + + return &client, nil +} diff --git a/internal/emulation/emulation_test.go b/internal/emulation/emulation_test.go new file mode 100644 index 0000000..51c01c6 --- /dev/null +++ b/internal/emulation/emulation_test.go @@ -0,0 +1,74 @@ +package emulation + +import ( + "io/fs" + "strings" + "testing" +) + +func TestNewEmulation(t *testing.T) { + var counter int + fs.WalkDir(staticFiles, ".", func(path string, d fs.DirEntry, err error) error { + if counter > 1 { + code := strings.TrimRight(strings.TrimLeft(path, "static/"), ".json") + e, err := NewEmulation(code) + if err != nil { + t.Error("should not return error ") + } + + peerId := e.PeerIdGenerator.PeerId() + key := e.KeyGenerator.Key() + + d, u, l := e.RoudingGenerator.NextAmountReport(2*1024*1024*1024, 1024*1024*1024, 3*1024*1024*1024, 1024) + + if peerId == "" { + t.Errorf("%s.json should be able to generate PeerId", code) + } + if key == "" { + t.Errorf("%s.json should be able to generate Key", code) + } + if d <= 0 || u <= 0 || l <= 0 { + t.Errorf("%s.json should be able to round candidates", code) + } + } + counter++ + return nil + }) + +} +func TestExtractClient(t *testing.T) { + var counter int + fs.WalkDir(staticFiles, ".", func(path string, d fs.DirEntry, err error) error { + if counter > 1 { + code := strings.TrimRight(strings.TrimLeft(path, "static/"), ".json") + c, e := extractClient(code) + if e != nil || err != nil { + t.Error("should not return error") + } + + if c.Key.Generator == "" && c.Key.Regex == "" { + t.Errorf("%s.json should have key generator properties", code) + } + if c.PeerID.Generator == "" && c.PeerID.Regex == "" { + t.Errorf("%s.json should have PeerId generator properties", code) + } + + if c.Rounding.Generator == "" && c.Rounding.Regex == "" { + t.Errorf("%s.json should have rouding generator properties", code) + } + + if c.Name == "" { + t.Errorf("%s.json should have a name", code) + } + if c.Query == "" { + t.Errorf("%s.json should have a query", code) + } + if len(c.Headers) == 0 { + t.Errorf("%s.json should have headers", code) + } + } + counter++ + return nil + }) + +} diff --git a/internal/emulation/qbittorrent.go b/internal/emulation/qbittorrent.go deleted file mode 100644 index 62f859d..0000000 --- a/internal/emulation/qbittorrent.go +++ /dev/null @@ -1,83 +0,0 @@ -package emulation - -import ( - "encoding/hex" - "math/rand" - "strings" - "time" -) - -const ( - letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_" - name = "qBittorrent v4.03" - query = "info_hash={infohash}&peer_id={peerid}&port={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}&corrupt=0&key={key}&event={event}&numwant={numwant}&compact=1&no_peer_id=1&supportcrypto=1&redundant=0" -) - -func init() { - rand.Seed(time.Now().UnixNano()) -} - -type qbitTorrent struct { - name string - query string - dictHeaders map[string]string - key string - peerID string -} - -func NewQbitTorrent() *qbitTorrent { - return &qbitTorrent{ - name: name, - query: query, - dictHeaders: generateHeaders(), - key: generateKey(), - peerID: generatePeerID(), - } -} - -func (qb *qbitTorrent) Name() string { - return qb.name -} -func (qb *qbitTorrent) PeerID() string { - return qb.peerID -} - -func (qb *qbitTorrent) Key() string { - return qb.key -} - -func (qb *qbitTorrent) Query() string { - return query -} -func (qb *qbitTorrent) Headers() map[string]string { - return qb.dictHeaders -} -func (qb *qbitTorrent) NextAmountReport(downloadCandidateNextAmount, uploadCandidateNextAmount, leftCandidateNextAmount, pieceSize int) (downloaded, uploaded, left int) { - - d := downloadCandidateNextAmount - u := uploadCandidateNextAmount - (uploadCandidateNextAmount % (16 * 1024)) - l := leftCandidateNextAmount - (leftCandidateNextAmount % pieceSize) - return d, u, l -} - -func generateHeaders() map[string]string { - return map[string]string{"User-Agent": "qBittorrent/4.0.3", "Accept-Encoding": "gzip"} -} - -func generatePeerID() string { - return "-qB4030-" + randStringBytes(12) -} - -func randStringBytes(n int) string { - b := make([]byte, n) - for i := range b { - b[i] = letterBytes[rand.Intn(len(letterBytes))] - } - return string(b) -} -func generateKey() string { - randomBytes := make([]byte, 4) - rand.Read(randomBytes) - str := hex.EncodeToString(randomBytes) - return strings.ToUpper(str) -} diff --git a/internal/emulation/qbittorrent_test.go b/internal/emulation/qbittorrent_test.go deleted file mode 100644 index 5a7184e..0000000 --- a/internal/emulation/qbittorrent_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package emulation - -import ( - "strings" - "testing" -) - -func TestGenerateRandomKey(T *testing.T) { - T.Run("Key has 8 length", func(t *testing.T) { - obj := NewQbitTorrent() - key := obj.Key() - if len(key) != 8 { - t.Error("Keys must have length of 8") - } - - }) - T.Run("Key must be uppercase", func(t *testing.T) { - obj := NewQbitTorrent() - key := obj.Key() - if strings.ToUpper(key) != key { - t.Error("Keys must be uppercase") - } - - }) - -} diff --git a/internal/emulation/static/qbit-4.0.3.json b/internal/emulation/static/qbit-4.0.3.json new file mode 100644 index 0000000..894cad6 --- /dev/null +++ b/internal/emulation/static/qbit-4.0.3.json @@ -0,0 +1,17 @@ +{ + "name":"qBittorrent v4.0.3", + "peerId":{ + "regex":"-qB4030-[A-Za-z0-9_~\\(\\)\\!\\.\\*-]{12}" + }, + "key": { + "generator":"defaultKeyGenerator" + }, + "rounding": { + "generator":"defaultRoudingGenerator" + }, + "query":"info_hash={infohash}&peer_id={peerid}&port={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}&corrupt=0&key={key}&event={event}&numwant={numwant}&compact=1&no_peer_id=1&supportcrypto=1&redundant=0", + "headers":{ + "User-Agent" :"qBittorrent/4.0.3", + "Accept-Encoding": "gzip" + } +} \ No newline at end of file diff --git a/internal/emulation/static/qbit-4.3.2.json b/internal/emulation/static/qbit-4.3.2.json new file mode 100644 index 0000000..3431fac --- /dev/null +++ b/internal/emulation/static/qbit-4.3.2.json @@ -0,0 +1,17 @@ +{ + "name":"qBittorrent v4.3.2", + "peerId":{ + "regex":"-qB4320-[A-Za-z0-9_~\\(\\)\\!\\.\\*-]{12}" + }, + "key": { + "generator":"defaultKeyGenerator" + }, + "rounding": { + "generator":"defaultRoudingGenerator" + }, + "query":"info_hash={infohash}&peer_id={peerid}&port={port}&uploaded={uploaded}&downloaded={downloaded}&left={left}&corrupt=0&key={key}&event={event}&numwant={numwant}&compact=1&no_peer_id=1&supportcrypto=1&redundant=0", + "headers":{ + "User-Agent" :"qBittorrent/4.3.2", + "Accept-Encoding": "gzip" + } +} \ No newline at end of file diff --git a/internal/generator/key.go b/internal/generator/key.go new file mode 100644 index 0000000..dc834d3 --- /dev/null +++ b/internal/generator/key.go @@ -0,0 +1,27 @@ +package generator + +import ( + "crypto/rand" + "encoding/hex" + "strings" +) + +type KeyGenerator interface { + Key() string +} + +func NewKeyGenerator(generatorCode string) (KeyGenerator, error) { + randomBytes := make([]byte, 4) + rand.Read(randomBytes) + str := hex.EncodeToString(randomBytes) + result := strings.ToUpper(str) + return &DefaultKeyGenerator{generated: result}, nil +} + +type DefaultKeyGenerator struct { + generated string +} + +func (d *DefaultKeyGenerator) Key() string { + return d.generated +} diff --git a/internal/generator/peerId.go b/internal/generator/peerId.go new file mode 100644 index 0000000..51b33fb --- /dev/null +++ b/internal/generator/peerId.go @@ -0,0 +1,25 @@ +package generator + +import ( + regen "github.com/zach-klippenstein/goregen" +) + +type PeerIdGenerator interface { + PeerId() string +} + +type RegexPeerIdGenerator struct { + generated string +} + +func NewPeerIdGenerator(generatorCode, pattern string) (PeerIdGenerator, error) { + result, err := regen.Generate(pattern) + if err != nil { + return nil, err + } + return &RegexPeerIdGenerator{generated: result}, nil +} + +func (d *RegexPeerIdGenerator) PeerId() string { + return d.generated +} diff --git a/internal/generator/rouding.go b/internal/generator/rouding.go new file mode 100644 index 0000000..e099020 --- /dev/null +++ b/internal/generator/rouding.go @@ -0,0 +1,20 @@ +package generator + +type RoundingGenerator interface { + NextAmountReport(downloadCandidateNextAmount, uploadCandidateNextAmount, leftCandidateNextAmount, pieceSize int) (downloaded, uploaded, left int) +} + +func NewRoundingGenerator(code string) (RoundingGenerator, error) { + return &DefaultRoundingGenerator{}, nil + +} + +type DefaultRoundingGenerator struct{} + +func (d *DefaultRoundingGenerator) NextAmountReport(downloadCandidateNextAmount, uploadCandidateNextAmount, leftCandidateNextAmount, pieceSize int) (downloaded, uploaded, left int) { + + down := downloadCandidateNextAmount + up := uploadCandidateNextAmount - (uploadCandidateNextAmount % (16 * 1024)) + l := leftCandidateNextAmount - (leftCandidateNextAmount % pieceSize) + return down, up, l +} diff --git a/internal/generator/rounding_test.go b/internal/generator/rounding_test.go new file mode 100644 index 0000000..3c15e2b --- /dev/null +++ b/internal/generator/rounding_test.go @@ -0,0 +1,21 @@ +package generator + +import "testing" + +func TestNextAmountReport(t *testing.T) { + r, _ := NewRoundingGenerator("") + + d, u, l := r.NextAmountReport(656497856, 46479878, 7879879, 1024) + //same + if d != 656497856 { + t.Errorf("[download]got %v want %v", d, 656497856) + } + //16kb round + if u != 46465024 { + t.Errorf("[upload]got %v want %v", u, 46465024) + } + //piece size round + if l != 7879680 { + t.Errorf("[left]got %v want %v", l, 7879680) + } +} diff --git a/internal/input/input.go b/internal/input/input.go index f565a68..366c1c6 100644 --- a/internal/input/input.go +++ b/internal/input/input.go @@ -21,6 +21,7 @@ type InputArgs struct { InitialDownloaded string DownloadSpeed string InitialUploaded string + Client string UploadSpeed string Port int Debug bool diff --git a/internal/printer/printer.go b/internal/printer/printer.go index d73144e..ae5c41f 100644 --- a/internal/printer/printer.go +++ b/internal/printer/printer.go @@ -55,7 +55,7 @@ func PrintState(state *ratiospoof.RatioSpoof) { Upload Speed: %v/s Size: %v Emulation: %v | Port: %v`, state.TorrentInfo.Name, state.TorrentInfo.TrackerInfo.Main, seedersStr, leechersStr, humanReadableSize(float64(state.Input.DownloadSpeed)), - humanReadableSize(float64(state.Input.UploadSpeed)), humanReadableSize(float64(state.TorrentInfo.TotalSize)), state.BitTorrentClient.Name(), state.Input.Port) + humanReadableSize(float64(state.Input.UploadSpeed)), humanReadableSize(float64(state.TorrentInfo.TotalSize)), state.BitTorrentClient.Name, state.Input.Port) fmt.Printf("\n\n%s\n\n", center(" GITHUB.COM/AP-PAULOAFONSO/RATIO-SPOOF ", width-len(" GITHUB.COM/AP-PAULOAFONSO/RATIO-SPOOF "), "#")) for i := 0; i <= state.AnnounceHistory.Len()-2; i++ { dequeItem := state.AnnounceHistory.At(i).(ratiospoof.AnnounceEntry) diff --git a/internal/ratiospoof/ratiospoof.go b/internal/ratiospoof/ratiospoof.go index fde81c3..f15e1b1 100644 --- a/internal/ratiospoof/ratiospoof.go +++ b/internal/ratiospoof/ratiospoof.go @@ -14,6 +14,7 @@ import ( "time" "github.com/ap-pauloafonso/ratio-spoof/internal/bencode" + "github.com/ap-pauloafonso/ratio-spoof/internal/emulation" "github.com/ap-pauloafonso/ratio-spoof/internal/input" "github.com/ap-pauloafonso/ratio-spoof/internal/tracker" "github.com/gammazero/deque" @@ -28,7 +29,7 @@ type RatioSpoof struct { TorrentInfo *bencode.TorrentInfo Input *input.InputParsed Tracker *tracker.HttpTracker - BitTorrentClient TorrentClientEmulation + BitTorrentClient *emulation.Emulation AnnounceInterval int EstimatedTimeToAnnounce time.Time EstimatedTimeToAnnounceUpdateCh chan int @@ -41,15 +42,6 @@ type RatioSpoof struct { StopPrintCH chan interface{} } -type TorrentClientEmulation interface { - PeerID() string - Key() string - Query() string - Name() string - Headers() map[string]string - NextAmountReport(DownloadCandidateNextAmount, UploadCandidateNextAmount, leftCandidateNextAmount, pieceSize int) (downloaded, uploaded, left int) -} - type AnnounceEntry struct { Count int Downloaded int @@ -62,7 +54,7 @@ type announceHistory struct { deque.Deque } -func NewRatioSpoofState(input input.InputArgs, torrentClient TorrentClientEmulation) (*RatioSpoof, error) { +func NewRatioSpoofState(input input.InputArgs) (*RatioSpoof, error) { EstimatedTimeToAnnounceUpdateCh := make(chan int) stopPrintCh := make(chan interface{}) dat, err := ioutil.ReadFile(input.TorrentPath) @@ -70,6 +62,11 @@ func NewRatioSpoofState(input input.InputArgs, torrentClient TorrentClientEmulat return nil, err } + client, err := emulation.NewEmulation(input.Client) + if err != nil { + return nil, errors.New("Error building the emulated client with the code") + } + torrentInfo, err := bencode.TorrentDictParse(dat) if err != nil { return nil, errors.New("failed to parse the torrent file") @@ -86,7 +83,7 @@ func NewRatioSpoofState(input input.InputArgs, torrentClient TorrentClientEmulat } return &RatioSpoof{ - BitTorrentClient: torrentClient, + BitTorrentClient: client, TorrentInfo: torrentInfo, Tracker: httpTracker, Input: inputParsed, @@ -171,15 +168,15 @@ func (R *RatioSpoof) fireAnnounce(retry bool) error { lastAnnounce := R.AnnounceHistory.Back().(AnnounceEntry) replacer := strings.NewReplacer("{infohash}", R.TorrentInfo.InfoHashURLEncoded, "{port}", fmt.Sprint(R.Input.Port), - "{peerid}", R.BitTorrentClient.PeerID(), + "{peerid}", R.BitTorrentClient.PeerIdGenerator.PeerId(), "{uploaded}", fmt.Sprint(lastAnnounce.Uploaded), "{downloaded}", fmt.Sprint(lastAnnounce.Downloaded), "{left}", fmt.Sprint(lastAnnounce.Left), - "{key}", R.BitTorrentClient.Key(), + "{key}", R.BitTorrentClient.KeyGenerator.Key(), "{event}", R.Status, "{numwant}", fmt.Sprint(R.NumWant)) - query := replacer.Replace(R.BitTorrentClient.Query()) - trackerResp, err := R.Tracker.Announce(query, R.BitTorrentClient.Headers(), retry, R.EstimatedTimeToAnnounceUpdateCh) + query := replacer.Replace(R.BitTorrentClient.Query) + trackerResp, err := R.Tracker.Announce(query, R.BitTorrentClient.Headers, retry, R.EstimatedTimeToAnnounceUpdateCh) if err != nil { log.Fatalf("failed to reach the tracker:\n%s ", err.Error()) } @@ -206,7 +203,7 @@ func (R *RatioSpoof) generateNextAnnounce() { leftCandidate := calculateBytesLeft(downloadCandidate, R.TorrentInfo.TotalSize) - d, u, l := R.BitTorrentClient.NextAmountReport(downloadCandidate, uploadCandidate, leftCandidate, R.TorrentInfo.PieceSize) + d, u, l := R.BitTorrentClient.RoudingGenerator.NextAmountReport(downloadCandidate, uploadCandidate, leftCandidate, R.TorrentInfo.PieceSize) R.addAnnounce(d, u, l, (float32(d)/float32(R.TorrentInfo.TotalSize))*100) } diff --git a/makefile b/makefile new file mode 100644 index 0000000..1a18093 --- /dev/null +++ b/makefile @@ -0,0 +1,15 @@ +test: + go test ./... --cover + +torrent-test: + go run cmd/main.go -c qbit-4.3.2 -t internal/bencode/torrent_files_test/Fedora-Workstation-Live-x86_64-33.torrent -d 0% -ds 100kbps -u 0% -us 100kbps -debug + +release: + @if test -z "$(rsversion)"; then echo "usage: make release rsversion=v1.2"; exit 1; fi + rm -rf ./out + + env GOOS=darwin GOARCH=amd64 go build -v -o ./out/mac/ratio-spoof github.com/ap-pauloafonso/ratio-spoof/cmd + env GOOS=linux GOARCH=amd64 go build -v -o ./out/linux/ratio-spoof github.com/ap-pauloafonso/ratio-spoof/cmd + env GOOS=windows GOARCH=amd64 go build -v -o ./out/windows/ratio-spoof.exe github.com/ap-pauloafonso/ratio-spoof/cmd + + cd out/ ; zip ratio-spoof-$(rsversion)\(linux-mac-windows\).zip -r . \ No newline at end of file