func findAuthenticatedPeers(port, appPort, minPeers int, passphrase []byte, c chan Peer) { defer close(c) ih, err := infoHash(passphrase) if err != nil { log.Println("Could not calculate infohash for the provided passphrase", err) return } announce := false if appPort > 0 { announce = true if _, err = listenAuth(port, appPort, passphrase); err != nil { log.Println("Could not open listener:", err) return } } // Connect to the DHT network. d, err := dht.NewDHTNode(port, minPeers, announce) if err != nil { log.Println("Could not create the DHT node:", err) return } d.AddNode("213.239.195.138:40000") go d.DoDHT() // Sends authenticated peers to channel c. go obtainPeers(d, passphrase, c) for { // Keeps requesting for the infohash. This is a no-op if the // DHT is satisfied with the number of peers it has found. d.PeersRequest(string(ih), true) time.Sleep(5 * time.Second) } }
func main() { flag.Parse() // Change to l4g.DEBUG to see *lots* of debugging information. l4g.AddFilter("stdout", l4g.WARNING, l4g.NewConsoleLogWriter()) if len(flag.Args()) != 1 { fmt.Fprintf(os.Stderr, "Usage: %v <infohash>\n\n", os.Args[0]) fmt.Fprintf(os.Stderr, "Example infohash: d1c5676ae7ac98e8b19f63565905105e3c4c37a2\n") flag.PrintDefaults() os.Exit(1) } ih, err := dht.DecodeInfoHash(flag.Args()[0]) if err != nil { l4g.Critical("DecodeInfoHash error: %v\n", err) os.Exit(1) } // This is a hint to the DHT of the minimum number of peers it will try to // find for the given node. This is not a reliable limit. In the future this // might be moved to "PeersRequest()", so the controlling client can have // different targets at different moments or for different infohashes. targetNumPeers := 5 d, err := dht.NewDHTNode(dhtPortUDP, targetNumPeers, false) if err != nil { l4g.Critical("NewDHTNode error: %v", err) os.Exit(1) } // For debugging. go http.ListenAndServe(fmt.Sprintf(":%d", httpPortTCP), nil) go d.DoDHT() go drainresults(d) for { // Give the DHT some time to "warm-up" its routing table. time.Sleep(5 * time.Second) d.PeersRequest(string(ih), false) } }
func NewTorrentSession(torrent string) (ts *TorrentSession, err error) { var listenPort int if listenPort, err = chooseListenPort(); err != nil { log.Println("Could not choose listen port.") log.Println("Peer connectivity will be affected.") } t := &TorrentSession{peers: make(map[string]*peerState), peerMessageChan: make(chan peerMessage), activePieces: make(map[int]*ActivePiece)} t.m, err = getMetaInfo(torrent) if err != nil { return } log.Printf("Tracker: %v, Comment: %v, InfoHash: %x, Encoding: %v, Private: %v", t.m.Announce, t.m.Comment, t.m.InfoHash, t.m.Encoding, t.m.Info.Private) if e := t.m.Encoding; e != "" && e != "UTF-8" { return nil, errors.New(fmt.Sprintf("Unknown encoding %s", e)) } ext := ".torrent" dir := fileDir if len(t.m.Info.Files) != 0 { dir += "/" + filepath.Base(torrent) if dir[len(dir)-len(ext):] == ext { dir = dir[:len(dir)-len(ext)] } } t.fileStore, t.totalSize, err = NewFileStore(&t.m.Info, dir) if err != nil { return } t.lastPieceLength = int(t.totalSize % t.m.Info.PieceLength) start := time.Now() good, bad, pieceSet, err := checkPieces(t.fileStore, t.totalSize, t.m) end := time.Now() log.Printf("Computed missing pieces (%.2f seconds)", end.Sub(start).Seconds()) if err != nil { return } t.pieceSet = pieceSet t.totalPieces = good + bad t.goodPieces = good log.Println("Good pieces:", good, "Bad pieces:", bad) left := int64(bad) * int64(t.m.Info.PieceLength) if !t.pieceSet.IsSet(t.totalPieces - 1) { left = left - t.m.Info.PieceLength + int64(t.lastPieceLength) } t.si = &SessionInfo{PeerId: peerId(), Port: listenPort, Left: left} if useDHT { // TODO: UPnP UDP port mapping. if t.dht, err = dht.NewDHTNode(listenPort, TARGET_NUM_PEERS, true); err != nil { log.Println("DHT node creation error", err) return } go t.dht.DoDHT() } return t, err }
func NewTorrentSession(torrent string) (ts *TorrentSession, err error) { var listenPort int if listenPort, err = chooseListenPort(); err != nil { log.Println("Could not choose listen port.") log.Println("Peer connectivity will be affected.") } t := &TorrentSession{peers: make(map[string]*peerState), peerMessageChan: make(chan peerMessage, 100), activePieces: make(map[int]*ActivePiece), history: make(map[string]*DownloadUpload), ioRequestChan: make(chan *IoArgs, 100), ioResponceChan: make(chan interface{}, 100), } t.cache = cache.NewLRUCache(10 * 1024 *1024) t.m, err = getMetaInfo(torrent) if err != nil { return } log.Printf("Tracker: %v, Comment: %v, InfoHash: %x, Encoding: %v, Private: %v", t.m.Announce, t.m.Comment, t.m.InfoHash, t.m.Encoding, t.m.Info.Private) if e := t.m.Encoding; e != "" && e != "UTF-8" { return nil, errors.New(fmt.Sprintf("Unknown encoding %s", e)) } ext := ".torrent" dir := cfg.fileDir if len(t.m.Info.Files) != 0 { dir += "/" + filepath.Base(torrent) if dir[len(dir)-len(ext):] == ext { dir = dir[:len(dir)-len(ext)] } } t.fileStore, t.totalSize, err = NewFileStore(&t.m.Info, dir) if err != nil { return } t.lastPieceLength = int(t.totalSize % t.m.Info.PieceLength) start := time.Now() var good, bad int var pieceSet *Bitset if cfg.noCheckSum{ //todo: refactor to function t.fastResumeFile = torrent + ".fastResume" if f, err := os.OpenFile(t.fastResumeFile, os.O_CREATE | os.O_RDWR | O_BINARY, 0); err != nil { panic("can not open fast resume file") }else{ defer f.Close() set, _ := ioutil.ReadAll(f) totalPieceCount := int((t.totalSize + int64(t.m.Info.PieceLength) - 1) / int64(t.m.Info.PieceLength)) if len(set) != totalPieceCount { log.Println("warning, invalid fast resume file") good, bad, pieceSet, err = checkPieces(t.fileStore, t.totalSize, t.m) }else{ pieceSet = NewBitset(totalPieceCount) for i := 0; i < totalPieceCount; i++ { if set[i] == 1 { pieceSet.Set(i) good++ }else{ bad++ } } } } }else{ good, bad, pieceSet, err = checkPieces(t.fileStore, t.totalSize, t.m) } end := time.Now() log.Printf("Computed missing pieces (%.2f seconds)", end.Sub(start).Seconds()) if err != nil { return } t.pieceSet = pieceSet t.totalPieces = good + bad t.goodPieces = good log.Println("Good pieces:", good, "Bad pieces:", bad) left := int64(bad) * int64(t.m.Info.PieceLength) if !t.pieceSet.IsSet(t.totalPieces - 1) { left = left - t.m.Info.PieceLength + int64(t.lastPieceLength) } t.si = &SessionInfo{PeerId: peerId(), Port: listenPort, Left: left} if cfg.useDHT { // TODO: UPnP UDP port mapping. if t.dht, err = dht.NewDHTNode(listenPort, cfg.TARGET_NUM_PEERS, true); err != nil { log.Println("DHT node creation error", err) return } go t.dht.DoDHT() } go IoRoutine(t.ioRequestChan, t.ioResponceChan) return t, err }
func main() { var numTargetPeers int var sendAnnouncements bool var file *os.File var num int var shalist [64]string var err error var part []byte l4g.AddFilter("stdout", l4g.DEBUG, l4g.NewConsoleLogWriter()) if file, err = os.Open("hops.log"); err != nil { return } reader := bufio.NewReader(file) num = 0 for { if part, _, err = reader.ReadLine(); err != nil { break } if err == io.EOF { err = nil } hasher := sha1.New() hasher.Write(part) shalist[num] = string(hasher.Sum(nil)) num = num + 1 } sendAnnouncements = true numTargetPeers = 64 port := 42345 l4g.Error("used port %d", port) dht, err := dht.NewDHTNode(port, numTargetPeers, false) if err != nil { l4g.Error("DHT node creation error", err) return } go dht.DoDHT() go drainresults(dht) queryTick := time.Tick(20 * time.Second) go http.ListenAndServe(fmt.Sprintf(":%d", httpPort), nil) for { select { case <-queryTick: // trying the manual method from dht_test in case I have the format // wrong fmt.Printf("TICK ************************************\n") fmt.Printf("TICK ************************************\n") fmt.Printf("TICK ************************************\n") fmt.Printf("TICK ************************************\n") fmt.Printf("TICK ************************************\n") fmt.Printf("TICK ************************************\n") for i := 0; i < num; i++ { l4g.Info("querying for infoHash: %x", shalist[i]) dht.PeersRequest(shalist[i], sendAnnouncements) time.Sleep(10 * time.Second) } } } }