func main() { flag.Parse() cl, err := torrent.NewClient(nil) if err != nil { log.Fatalf("error creating client: %s", err) } wg := sync.WaitGroup{} for _, arg := range flag.Args() { t, err := cl.AddMagnet(arg) if err != nil { log.Fatalf("error adding magnet to client: %s", err) } wg.Add(1) go func() { defer wg.Done() <-t.GotInfo() mi := t.Metainfo() t.Drop() f, err := os.Create(mi.Info.Name + ".torrent") if err != nil { log.Fatalf("error creating torrent metainfo file: %s", err) } defer f.Close() err = bencode.NewEncoder(f).Encode(mi) if err != nil { log.Fatalf("error writing torrent metainfo file: %s", err) } }() } wg.Wait() }
func (b *Batch) write_torrent(w io.Writer) error { var td MetaInfo // Either announce or node lists are allowed - not both if len(b.announce_list) != 0 { td.Announce = b.announce_list[0][0] if len(b.announce_list) != 1 || len(b.announce_list[0]) != 1 { td.AnnounceList = b.announce_list } } if len(b.node_list) != 0 { td.Nodes = b.node_list } td.CreationDate = b.creation_date.Unix() td.Comment = b.comment td.CreatedBy = b.created_by td.Encoding = b.encoding switch { case len(b.urls) == 0: case len(b.urls) == 1: td.URLList = b.urls[0] default: td.URLList = b.urls } td.Info.PieceLength = b.piece_length td.Info.Pieces = b.pieces if b.name == "" { td.Info.Name = b.default_name } else { td.Info.Name = b.name } if len(b.files) == 1 { td.Info.Length = b.files[0].size } else { td.Info.Files = make([]FileInfo, len(b.files)) for i, f := range b.files { td.Info.Files[i] = FileInfo{ Path: f.splitpath, Length: f.size, } } } td.Info.Private = b.private e := bencode.NewEncoder(w) return e.Encode(&td) }
// Encode to bencoded form. func (mi *MetaInfo) Write(w io.Writer) error { return bencode.NewEncoder(w).Encode(mi) }
func (d *delugeProcess) Start() error { cmd := exec.Command("deluged", "-d", "-i", d.ip.String()) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err := cmd.Start() if err != nil { return err } d.Process = cmd.Process //starts a super minimal bittorrent tracker that only returns peers go func() { torrents := map[string]map[string]peer{} log.Printf("Starting tracker on '%s'...", d.trackerBind) err = http.ListenAndServe(d.trackerBind, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { //map[ipv6:[fe80::226:bbff:fe0a:e12b] info_hash:[?0FA??c??N???] left:[100000000] key:[B22982B1] event:[started] numwant:[200] compact:[1] no_peer_id:[1] peer_id:[-UM1870-{??qCzVB<ur] port:[40959] uploaded:[0] downloaded:[0] corrupt:[0]] err := r.ParseForm() if err != nil { log.Printf("Failed to parse announce form data: %s", err) return } host, port, err := net.SplitHostPort(r.RemoteAddr) if err != nil { log.Printf("Failed to parse remote host and port: %s", err) return } if r.Form.Get("peer_id") == "" { //@todo sometimes peer_id is empty? return } //add announcing peer to peerlist of torrent log.Printf("Torrent Client (peer_id: '%s', compact: %s) announces from %s:%s, port set to %s for info_hash '%x'", r.Form.Get("peer_id"), r.Form.Get("compact"), host, port, r.Form.Get("port"), r.Form.Get("info_hash")) peerlist, ok := torrents[r.Form.Get("info_hash")] if !ok { peerlist = map[string]peer{} torrents[r.Form.Get("info_hash")] = peerlist } peerlist[r.Form.Get("peer_id")] = peer{ PeerID: r.Form.Get("peer_id"), IP: host, Port: r.Form.Get("port"), } peers := []peer{} for _, p := range peerlist { peers = append(peers, p) } if r.Form.Get("compact") == "1" { buff := bytes.NewBuffer(nil) err = d.writeCompactPeers(buff, peers) if err != nil { log.Printf("Error: %s", err) return } log.Printf("compact: '% x'", buff.Bytes()) data := struct { Peers []byte `bencode:"peers"` }{ Peers: buff.Bytes(), } //encode response log.Printf("Returning announce with: %+v", data) w.Header().Set("Content-Type", "text/plain") enc := bencode.NewEncoder(w) err = enc.Encode(data) if err != nil { log.Printf("Failed to bencode: %s", err) return } } else { data := struct { Peers []peer `bencode:"peers"` }{ Peers: peers, } //encode response log.Printf("Returning announce with: %+v", data) w.Header().Set("Content-Type", "text/plain") enc := bencode.NewEncoder(w) err = enc.Encode(data) if err != nil { log.Printf("Failed to bencode: %s", err) return } } })) log.Printf("Tracker exited") if err != nil { log.Printf("Tracker failed: %s", err) } }() log.Printf("Torrent files can be downloaded at: '%s'", d.filesBind) go func() { log.Fatal(http.ListenAndServe(d.filesBind, http.FileServer(http.Dir(d.torrentPath)))) }() return nil }