A(nother) Bittorrent client written in the go programming language

Taipei Torrent

This is a simple command-line-interface BitTorrent client coded in the go programming language.

Build Status

Features:

  • Supports multiple torrent files
  • Magnet links
  • DHT
  • IPv6
  • UDP trackers
  • UPnP / NAT-PMP automatic firewall configuration
  • Socks5 proxy support

Additional Features:

  • It can act as a tracker if you start it with the --createTracker flag
  • SFTP file system proxying enables torrenting large torrents on systems with limited local file storage.

FAQ:

Q: Why is it named Taipei Torrent?

A: I started writing it while visiting beautiful Taipei, Taiwan

Q: What is the license?

A: See the LICENSE file.

Current Status

  • Tested on Go 1.4.2 and tip.
  • Tested on Windows, Linux and Mac OS X.
  • People tell me they've run it on Android, too.

Development Roadmap

  • Full UPnP support (need to be able to search for an unused listener port, detect we have already acquired the port, defend the report against router reboots, release the listener port when we quit.)
  • Clean up source code
  • Deal with TODOs
  • Perhaps a web-based status UI.

Download, Install, and Build Instructions

  1. Download and install the Go tools from http://golang.org

  2. Use the "go" command to download, install, and build the Taipei-Torrent app:

    go get github.com/jackpal/Taipei-Torrent

Usage Instructions

Taipei-Torrent mydownload.torrent
Taipei-Torrent --useDHT "magnet:?xt=urn:btih:bbb6db69965af769f664b6636e7914f8735141b3"

or

Taipei-Torrent -help

Third-party Packages

https://github.com/jackpal/bencode-go - Bencode encoder/decoder

http://github.com/jackpal/gateway - LAN gateway discovery

http://github.com/jackpal/go-nat-pmp - NAT-PMP firewall client

https://github.com/nictuku/dht - Distributed Hash Table

https://github.com/nictuku/nettools - Network utilities

https://github.com/pkg/sftp - SFTP protocol

Google+ Community

https://plus.google.com/u/0/communities/100997865549971977580

Other Notable Go BitTorrent Implementations

I haven't used these, but they may be worth checking out:

https://github.com/anacrolix/torrent

Comments
  • DHT won't work without torrent?

    DHT won't work without torrent?

    I've noticed TT only connects to peers found using the DHT if we already have the torrent file. But what if we don't have the torrent file and only the infohash?

    eg of the restriction: https://github.com/jackpal/Taipei-Torrent/blob/master/torrent/torrent.go#L520

    Even if I remove all such restrictions like this (I think there are 2 more of them), I still can't download using just an infohash, for example "magnet:?xt=urn:btih:deca7a89a1dbdc4b213de1c0d5351e92582f31fb", even though I can connect to peers found over the dht for it (and there are several).

    What's the deal?

  • Implement lpd

    Implement lpd

    As should be defined in BEP-0014 (still TBD)

    Basically, for each torrent we are in, a HTTP-like message is sent to 239.192.152.143:6771. This message is an announcement that we are in the swarm.

    When a Taipei-Torrent peer receives such a message, it will automatically connect unless it's already connected.

    Tested successfully with aria2c and transmission.

  • Swarms of size 20,50,100 don't complete

    Swarms of size 20,50,100 don't complete

    Repro: Uncomment the commented-out-tests in tracker_test.go

    Might be some sort of OS-level resource starvation or race condition. Tested on OSX. Fails reproducibly. (Which tends to indicate that it's not a race condition.)

  • Prettify display

    Prettify display

    This makes the output more useful (particularly because I'm interested in making TT faster). Here's an example output line:

    2015/04/21 22:35:36 [ dsl-4.4.10.iso ] Peers: 9 downloaded: 19349504 (624.00 kB/s) uploaded: 0 ratio: 0.000000 pieces: 35/100
    
  • Fix crash when using DHT.

    Fix crash when using DHT.

    t.M needs to be populated before we can refer to it.

    2014/05/04 21:20:03 Starting. 2014/05/04 21:20:03 Listening for peers on port: 7777 panic: runtime error: invalid memory address or nil pointer dereference [signal 0xb code=0x1 addr=0x18 pc=0x3fa6f]

    goroutine 16 [running]: runtime.panic(0x335860, 0x551524) /usr/local/go/src/pkg/runtime/panic.c:279 +0xf5 github.com/jackpal/Taipei-Torrent/torrent.NewTorrentSession(0x7fff5fbffb5f, 0x14f, 0x1e61, 0x0, 0x0, 0x0) /Users/yves/go/src/github.com/jackpal/Taipei-Torrent/torrent/torrent.go:169 +0x14f main.main() /Users/yves/go/src/github.com/jackpal/Taipei-Torrent/main.go:62 +0x523

  • bencode can't unmarshal nested dictionaries?

    bencode can't unmarshal nested dictionaries?

    I can't make the bencode code unmarshal strings like:

    d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe

    I tried this for hours already, thinking I was doing something wrong, but couldn't find a solution. I'm thinking this might be a bug, but I'm not sure. I would appreciate any help.

    Unit test to reproduce it:

    $ git diff --cached bencode_test.go 
    diff --git a/bencode/bencode_test.go b/bencode/bencode_test.go
    index cb683af..b48fc79 100644
    --- a/bencode/bencode_test.go
    +++ b/bencode/bencode_test.go
    @@ -3,7 +3,7 @@ package bencode
     import (
            "bytes"
            "fmt"
    -//     "jackpal/bencode"
    +       //      "jackpal/bencode"
            "os"
            "reflect"
            "testing"
    @@ -206,6 +206,15 @@ type SVPair struct {
            v any
     }
     
    +var x = map[string]string{"id": "abcdefghij0123456789"}
    +var y = map[string]any{
    +       "t": "aa",
    +       "y": "q",
    +       "q": "ping",
    +       "a": x,
    +}
    +
    func TestDecode(t *testing.T) {
            tests := []SVPair{
                    SVPair{"i0e", int64(0)},
    @@ -221,6 +230,7 @@ func TestDecode(t *testing.T) {
                    SVPair{"li42e3:abce", []any{42, "abc"}},
                    SVPair{"de", map[string]any{}},
                    SVPair{"d3:cati1e3:dogi2ee", map[string]any{"cat": 1, "dog": 2}},
    +               SVPair{"d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe", y},
            }
            for _, sv := range tests {
                    if err := check(sv.s, sv.v); err != nil {
    @@ -250,6 +260,7 @@ func TestUnmarshal(t *testing.T) {
                    SVPair{"de", map[string]any{}},
                    SVPair{"d3:cati1e3:dogi2ee", map[string]any{"cat": 1, "dog": 2}},
                    SVPair{"d1:ai10e1:b3:fooe", structA{10, "foo"}},
    +               SVPair{"d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe", y},
            }
            for _, sv := range tests {
                    if err := checkUnmarshal(sv.s, sv.v); err != nil {
    
  • Metadata downloader conflicts with the deadlock detector

    Metadata downloader conflicts with the deadlock detector

    See the discussion in #63. The metadata downloader triggers a load() and a checkPieces() call that gets stuck for a while. This makes the deadlock detector unhappy.

    I don't know how to fix this without doing some surgery on the detector.

    Should we maybe make the deadlock detector print a stackdump without throwing a panic?

  • Separate code into package 'taipei'

    Separate code into package 'taipei'

    This is the first step towards making Taipei-Torrent available as a library. I've moved all of the files (besides main.go) into the taipei subdirectory, and changedthem to use the taipei package.

    There are a lot of changes in the PR, because it's necessary to capitalize the names of all fields used in main.go, since none of them were exported. Later, we can decide what fields really should be exported.

  • Add default bitfield for new peerstates

    Add default bitfield for new peerstates

    By default, a new peer has no pieces, so it doesn't send a BITFIELD. Only when it has some (or all) pieces does it send a BITFIELD. In the current implementation we only build peerstates' have when receiving BITFIELD. This fix makes sure there is always a have by default.

  • Toy WebGui.

    Toy WebGui.

    Fair warning; this is just a proof of concept I'd been thinking about for a bit, and then decided to try when I discovered gowut (Go Web UI Toolkit) earlier this afternoon.

    Basically, I've added a struct/API (TorrentControl) for the use of "Torrent Managers" that might be embedded into Taipei-Torrent. Examples of possible managers include a native gui, a webgui, a seedbox remote-control, etc. For now, TorrentControl is almost completely unimplemented, but as an example I've included a toy webgui (super-simple, extremely ugly) that uses it to list the currently running torrents and their percentage of completion (updated every 1 second).

    Obviously this is nowhere near ready to merge, but I thought I'd bring it up to get some feedback/suggestions on the idea, and just in case there's a huge fatal flaw in the design that I'm not seeing.

    Best Regards.

  • Improve UPnP support

    Improve UPnP support

    This PR changes the UPnP code so it doesn't try to exactly match the URN used by a router, as there can be slight differences. Also, it renames getStatusInfo to getExternalIPAddress, and makes it correctly get the external IP address from the router.

    The commit is pretty big, so I can split it up if you want.

  • 
Fix function comments based on best practices from Effective Go

    Fix function comments based on best practices from Effective Go

    Every exported function in a program should have a doc comment. The first sentence should be a summary that starts with the name being declared. From effective go.

    PR generated by CodeLingo. Install here to drive Continuous Higher Standards.

  • sorry for a problem

    sorry for a problem

    I have made 4 pull requests, but I find an error with the first pulling with title"fix error in downloading pieces continue ". And I do not know have to undo the pulling. So I make another pull again.

  • fixing error in closing peer

    fixing error in closing peer

    Taipei-Torrent should close peer when err != io.EOF, otherwise, as in the original codes, it will close peer when err ==io.EOF. But this will happen every time when it can not receive a piece by function "err = ts.RequestBlock2(p, k, false)". Because this function will return io.EOF when its peers do not have the pieces it needs. After closing, it can not download pieces from the peer because there is no connection between them anymore, even though the peer have the pieces it need again. I have tested this for one day to find the reasons that Taipei-Torrent can not receive pieces after it do not get piece one time and set to "UNINTERESTED" to the peer.

  • Usually have

    Usually have "send a bad piece" error

    When I use Taipei-Torrent to download file, I have 1 seeder and 10 leechers. I usually meet the problem "Closing peer that sent a bad piece 9 -tt15217_12515306877 reference sha1: [217 254 129 37 191 21 13 134 0 108 169 60 11 41 131 173 232 147 204 164] != piece sha1: [179 220 206 190 193 88 161 163 18 120 145 202 124 252 13 151 217 222 148 52]". What is the reason?

BitTorrent client in Go

wgo - Simple BitTorrent client in Go Roger Pau Monné (2010 - 2011) Introduction This project is based on the previous work of jackpal, Taipei-Torrent:

Jan 2, 2020
BitTorrent DHT Protocol && DHT Spider.
BitTorrent DHT Protocol && DHT Spider.

See the video on the Youtube. 中文版README Introduction DHT implements the bittorrent DHT protocol in Go. Now it includes: BEP-3 (part) BEP-5 BEP-9 BEP-1

Dec 20, 2022
Simple temporary file upload and transfer web application coding with Go language.

Temp File Transfer Web Application Simple temporary file upload and transfer web application coding with Go language. Explore the Golang » Live Demo T

Dec 2, 2022
Handshake Query is a cross-platform library to trustlessly resolve and verify Handshake names using a p2p light client

Handshake Query ⚠️ Usage of this library is not currently recommended in your application as the API will likely change. Handshake Query is a cross-pl

Dec 22, 2022
a ed2k link crawler written in Go / golang

Install/Run Example $ git clone git://github.com/kevinwatt/ed2kcrawler.git Build ed2kcrawler $ make Create an config.cfg file [GenSetting] OThread =

Aug 24, 2022
T# Programming Language. Something like Porth, Forth but written in Go. Stack-oriented programming language.

The T# Programming Language WARNING! THIS LANGUAGE IS A WORK IN PROGRESS! ANYTHING CAN CHANGE AT ANY MOMENT WITHOUT ANY NOTICE! Something like Forth a

Jun 29, 2022
Floppa programming language inspired by the brainf*ck programming language. Created just for fun and you can convert your brainf*ck code to floppa code.

Floppa Programming Language Created just for fun. But if you want to contribute, why not? Floppa p.l. inspired by the brainf*ck programming language.

Oct 20, 2022
Yayx programming language is begginer friendly programming language.
Yayx programming language is begginer friendly programming language.

Yayx Yayx programming language is begginer friendly programming language. What have yayx: Easy syntax Dynamic types Can be compiled to outhers program

Dec 27, 2021
Yayx programming language is begginer friendly programming language.

Yayx Yayx programming language is begginer friendly programming language. What have yayx: Easy syntax Dynamic types Can be compiled to outhers program

May 20, 2022
A Go language binding for encodeing and decoding data in the bencode format that is used by the BitTorrent peer-to-peer file sharing protocol.

bencode-go A Go language binding for encoding and decoding data in the bencode format that is used by the BitTorrent peer-to-peer file sharing protoco

Nov 27, 2022
🌧 BitTorrent client and library in Go
🌧 BitTorrent client and library in Go

rain BitTorrent client and library in Go. Running in production at put.io. Features Core protocol Fast extension Magnet links Multiple trackers UDP tr

Dec 28, 2022
Full-featured BitTorrent client package and utilities

torrent This repository implements BitTorrent-related packages and command-line utilities in Go. The emphasis is on use as a library from other projec

Jan 4, 2023
🌧 BitTorrent client and library in Go
🌧 BitTorrent client and library in Go

rain BitTorrent client and library in Go. Running in production at put.io. Features Core protocol Fast extension Magnet links Multiple trackers UDP tr

Jan 5, 2023
BitTorrent client in Go

wgo - Simple BitTorrent client in Go Roger Pau Monné (2010 - 2011) Introduction This project is based on the previous work of jackpal, Taipei-Torrent:

Jan 2, 2020
Full-featured BitTorrent client package and utilities

torrent This repository implements BitTorrent-related packages and command-line utilities in Go. The emphasis is on use as a library from other projec

Jan 2, 2023
🌧 BitTorrent client and library in Go
🌧 BitTorrent client and library in Go

rain BitTorrent client and library in Go. Running in production at put.io. Features Core protocol Fast extension Magnet links Multiple trackers UDP tr

Jan 1, 2023
Your Fluffy and Neighbourly Bittorrent Client

Totorrent: A Fluffy and Neighbourly Bittorrent Client This is a WIP bittorrent client I've been working on for a couple of months. I think it's in a v

Jul 28, 2021
BitTorrent client and library in Go. Running in production at put.io.
BitTorrent client and library in Go. Running in production at put.io.

rain BitTorrent client and library in Go. Running in production at put.io. Integration of embedded gRPC framework (All APIs translated to gRPC Server-

Apr 11, 2022
Advent of Code is an Advent calendar of small programming puzzles for a variety of skill sets and skill levels that can be solved in any programming language you like.

Advent of Code 2021 Advent of Code is an Advent calendar of small programming puzzles for a variety of skill sets and skill levels that can be solved

Dec 2, 2021
Jan 4, 2022