xgfone / go-bt Goto Github PK
View Code? Open in Web Editor NEWAnother pure golang implementation of BitTorrent library.
License: Apache License 2.0
Another pure golang implementation of BitTorrent library.
License: Apache License 2.0
I have actually already added I2P support in my fork of your library, in this tree: https://github.com/eyedeekay/bt/tree/i2p-support however it does require somewhat deep changes to how the library works. I2P is an anonymous peer-to-peer network, unlike Tor, we don't mind if people use bittorrent over I2P. Adding I2P support would allow me to use xfone/bt as an anonymous bittorrent library.
In particular this requires migrating all net.Addr's to interface types and enabling alternate implementations of all Dialers and Listeners in order to connect to I2P and accept I2P connections.
Following the code from this file:
https://github.com/xgfone/bt/blob/master/dht/dht_server_test.go
everything is same, main looks like this:
func main() {
pm := newTestPeerManager()
server1, err := newDHTServer(metainfo.NewRandomHash(), "0.0.0.0:9001", pm)
if err != nil {
fmt.Println(err)
return
}
defer server1.Close()
server2, err := newDHTServer(metainfo.NewRandomHash(), "0.0.0.0:9002", nil)
if err != nil {
fmt.Println(err)
return
}
defer server2.Close()
go server1.Run()
go server2.Run()
time.Sleep(time.Second * 5)
server1.Bootstrap([]string{"router.bittorrent.com:6881"})
server2.Bootstrap([]string{"127.0.0.1:9001"})
infohash := metainfo.NewHashFromString("4a42c5712ec4b810b162460f40cce1c6072b37ad")
for true {
time.Sleep(time.Second * 10)
fmt.Print("Server1 Node4Num: ")
fmt.Println(server1.Node4Num())
fmt.Print("Server2 Node4Num: ")
fmt.Println(server2.Node4Num())
server2.GetPeers(infohash, func(r dht.Result) {
if len(r.Peers) == 0 {
fmt.Printf("no peers for %s\n", infohash)
} else {
for _, peer := range r.Peers {
fmt.Printf("%s: %s\n", infohash, peer.String())
}
}
})
}
}
output:
Server1 Node4Num: 2
Server2 Node4Num: 1
127.0.0.1:9002 is searching 4a42c5712ec4b810b162460f40cce1c6072b37ad
no peers for 4a42c5712ec4b810b162460f40cce1c6072b37ad
no peers for 4a42c5712ec4b810b162460f40cce1c6072b37ad
no peers for 4a42c5712ec4b810b162460f40cce1c6072b37ad
no peers for 4a42c5712ec4b810b162460f40cce1c6072b37ad
no peers for 4a42c5712ec4b810b162460f40cce1c6072b37ad
no peers for 4a42c5712ec4b810b162460f40cce1c6072b37ad
no peers for 4a42c5712ec4b810b162460f40cce1c6072b37ad
no peers for 4a42c5712ec4b810b162460f40cce1c6072b37ad
no peers for 4a42c5712ec4b810b162460f40cce1c6072b37ad
no peers for 4a42c5712ec4b810b162460f40cce1c6072b37ad
no peers for 4a42c5712ec4b810b162460f40cce1c6072b37ad
no peers for 4a42c5712ec4b810b162460f40cce1c6072b37ad
no peers for 4a42c5712ec4b810b162460f40cce1c6072b37ad
2022/07/23 19:54:28 transaction '2' timeout: query=find_node, raddr=34.206.39.153:6881
Server1 Node4Num: 2
Server2 Node4Num: 30
no peers for 4a42c5712ec4b810b162460f40cce1c6072b37ad
no peers for 4a42c5712ec4b810b162460f40cce1c6072b37ad
no peers for 4a42c5712ec4b810b162460f40cce1c6072b37ad
no peers for 4a42c5712ec4b810b162460f40cce1c6072b37ad
no peers for 4a42c5712ec4b810b162460f40cce1c6072b37ad
no peers for 4a42c5712ec4b810b162460f40cce1c6072b37ad
2022/07/23 19:54:38 transaction 'l' timeout: query=get_peers, raddr=36.228.238.179:63962
no peers for 4a42c5712ec4b810b162460f40cce1c6072b37ad
2022/07/23 19:54:38 transaction 'a' timeout: query=get_peers, raddr=125.167.51.189:10758
no peers for 4a42c5712ec4b810b162460f40cce1c6072b37ad
2022/07/23 19:54:38 transaction 'e' timeout: query=get_peers, raddr=176.39.2.120:6881
no peers for 4a42c5712ec4b810b162460f40cce1c6072b37ad
2022/07/23 19:54:38 transaction 'h' timeout: query=get_peers, raddr=87.249.198.3:13426
no peers for 4a42c5712ec4b810b162460f40cce1c6072b37ad
2022/07/23 19:54:38 transaction 'q' timeout: query=get_peers, raddr=37.151.139.67:6881
Two things to note from the above output:
Server2
is not able to connect to other nodes (timeout error). Why?Server1
which was bootstrapped with 1 IP and server2
got added later, remains same. Why?I'm trying to build a router DHT node and expect my server1
to get filled with other nodes. There are plenty of peers for the above infohash
.
I have created a tracker (udp server). My actual code for this service is very small and have mostly used the sample code.
After running the pod for around 7 days. I see memory usage keeps increasing as it processes the requests. When I restart the pod the memory falls back to 2 MB or 3 MB which is expected for this type of small app.
Screenshot from grafana featuring both old and new pod:
While typing this message itself. Memory has increased from 1.2 MB to 5 MB. I guess, there is some variable in the underlying library that is misbehaving or escaping from garbage cleanup.
package tracker
import (
"bytes"
"encoding/json"
"example.com/m/internal/pkg/utils"
"github.com/xgfone/bt/metainfo"
"github.com/xgfone/bt/tracker/udptracker"
"net"
"net/http"
)
var OtherTrackers []string
func UDPTrackerServer(sconn net.PacketConn) {
server := udptracker.NewServer(sconn, testHandler{})
defer server.Close()
server.Run()
}
type testHandler struct{}
func (testHandler) OnConnect(raddr *net.UDPAddr) (err error) { return }
func (testHandler) OnAnnounce(raddr *net.UDPAddr, req udptracker.AnnounceRequest) (r udptracker.AnnounceResponse, err error) {
go addTorrent(req.InfoHash.String())
RedisAdd(req.InfoHash.String(), req.Left, raddr.IP, req.Port)
r = udptracker.AnnounceResponse{
Interval: 120, // 2 mins
Leechers: uint32(int(RedisCount(req.InfoHash.String() + ":incomplete"))),
Seeders: uint32(int(RedisCount(req.InfoHash.String() + ":complete"))),
Addresses: utils.GetPeersFromTrackers(req.PeerID, req.InfoHash, OtherTrackers, RedisGet(req.InfoHash.String())),
}
return
}
func (testHandler) OnScrap(raddr *net.UDPAddr, infohashes []metainfo.Hash) (
rs []udptracker.ScrapeResponse, err error) {
rs = make([]udptracker.ScrapeResponse, len(infohashes))
for i := range infohashes {
rs[i] = udptracker.ScrapeResponse{
Seeders: uint32(int(RedisCount(infohashes[i].String() + ":complete"))),
Leechers: uint32(int(RedisCount(infohashes[i].String() + ":incomplete"))),
Completed: uint32(int(RedisCount(infohashes[i].String() + ":complete"))),
}
}
return
}
var APIServerURL string
func addTorrent(infohash string) {
reqBody, _ := json.Marshal(map[string]string{
"infohash": infohash,
})
_, _ = http.Post(APIServerURL+"/torrents", "application/json", bytes.NewBuffer(reqBody))
}
I'm using Redis to store the peer data and I don't think that should be an issue
Hello.
Sorry for the inconvenience, but I want to propose an idea to implement your own Libtorrent-go repository, built for android applications. I know it sounds weird to propose this, but no one has implemented Libtorrent go for android apps yet.
What do you think?
I am attempting to learn your library and am getting started by writing a .torrent file generation tool for your bttools suite. I am attempting to produce the bytes required to populate the metainfo.MetaInfo.InfoBytes
field by creating the metainfo.Info object using metainfo.NewInfoFromFilePath
function on a directory, then loop over the pieces and concatenate them together. This approach works if I'm creating a single-file torrent, but when I try to create a multi-file torrent from a directory, I get:
error generating pieces: error copying .: read www: is a directory
You can see the code here:
xgfone/bttools@master...eyedeekay:create
func CreateTorrent(ctx *cli.Context) error {
dirs := ctx.Args().Slice()
if len(dirs) > 1 {
return fmt.Errorf("Input invalid, please use only one file or directory at ta time.")
}
info, err := metainfo.NewInfoFromFilePath(dirs[0], int64(ctx.Int("length")))
if err != nil {
return err
}
log.Println(info.CountPieces(), "pieces")
var pieces []byte
for n := 0; n < info.CountPieces(); n++ {
pieces = append(pieces, info.Piece(n).Hash().Bytes()...)
}
meta := &metainfo.MetaInfo{
InfoBytes: pieces,
}
infoc, err := meta.Info()
if err != nil {
return err
}
log.Println("Info generated", infoc.Name)
return nil
}
The documentation says NewInfoFromFilePath returns a new Info from a file or directory
so I think this must be unintentional, or I am misusing the function.
Thanks in advance for your help.
I have an Infohash of a torrent. Looking for a code by which I can get the details of it using DHT only (no tracker involvement).
Can bootstrap using a router DHT node.
From details, I mean MetaInfo
struct
https://github.com/xgfone/bt/blob/master/metainfo/metainfo.go#L95
I tried understanding it from source-code but couldn't
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.