Esempio n. 1
0
func downloadManager(d *dht.DHT, filesToDownload <-chan string, finished chan<- bool) {
	currentDownloads := make(map[dht.InfoHash]chan []string)
	downloadEvents := make(chan downloadEvent)

	for {
		select {
		case newInfoHashString := <-filesToDownload:
			newFile, err := dht.DecodeInfoHash(newInfoHashString)
			if err != nil {
				//TODO: better error handling
				log.Errorf("WINSTON: DecodeInfoHash error: %v\n", err)
			}

			if _, ok := currentDownloads[newFile]; ok {
				log.V(3).Infof("WINSTON: File %x is already downloading, skipping...\n", newFile)
				continue
			}
			log.V(3).Infof("WINSTON: Accepted %x for download...\n", newFile)

			// Create a channel for all the found peers
			currentDownloads[newFile] = make(chan []string)

			bufferedPeerChannel := makePeerBuffer(currentDownloads[newFile])

			// Ask that nice DHT fellow to find those peers :)
			d.PeersRequest(string(newFile), false)

			// Create a new gorouite that manages the download for the specific file
			go downloadFile(newFile, bufferedPeerChannel, downloadEvents)

		case newEvent := <-downloadEvents:
			if newEvent.eventType == eventSucessfulDownload {
				log.V(1).Infof("WINSTON: Download of %x completed :)\n", newEvent.infoHash)
			} else if newEvent.eventType == eventTimeout {
				log.V(1).Infof("WINSTON: Download of %x failed: time out :(\n", newEvent.infoHash)
			}
			close(currentDownloads[newEvent.infoHash])
			delete(currentDownloads, newEvent.infoHash)
			if len(currentDownloads) == 0 {
				finished <- true
			}

		case newPeers, chanOk := <-d.PeersRequestResults:
			if !chanOk {
				// Something went wrong, mayday, mayday!
				panic("WINSTON: BORK!\n")
			}

			for ih, peers := range newPeers {
				// Check if download is still active
				if currentPeersChan, ok := currentDownloads[ih]; ok {
					log.V(3).Infof("WINSTON: Received %d new peers for file %x\n", len(peers), ih)
					currentPeersChan <- peers
				} else {
					log.V(3).Infof("WINSTON: Received %d peers for non-current file %x (probably completed or timed out)\n", len(peers), ih)
				}
			}
		}
	}
}
Esempio n. 2
0
func main() {
	ipv6Address := flag.String("v6", "", "Address to bind to IPv6 interface")
	flag.Parse()
	// To see logs, use the -logtostderr flag and change the verbosity with
	// -v 0 (less verbose) up to -v 5 (more verbose).
	if len(flag.Args()) != 1 {
		fmt.Fprintf(os.Stderr, "Usage: %v <infohash>\n\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "Example infohash: %v\n", exampleIH)
		flag.PrintDefaults()
		os.Exit(1)
	}
	ih, err := dht.DecodeInfoHash(flag.Args()[0])
	if err != nil {
		fmt.Fprintf(os.Stderr, "DecodeInfoHash error: %v\n", err)
		os.Exit(1)
	}

	conf4 := dht.NewConfig()
	conf4.UDPProto = "udp4"
	conf4.Port = 8445
	// standard IPv4 bootstrap nodes = dht.transmissionbt.com
	// router.utorrent.com router.bittorrent.com
	conf6 := dht.NewConfig()
	conf6.UDPProto = "udp6"
	conf6.Port = 8445
	conf6.Address = *ipv6Address
	// Starts a DHT node with the default options. It picks a random UDP port. To change this, see dht.NewConfig.
	d4, err := dht.New(conf4)
	if err != nil {
		fmt.Fprintf(os.Stderr, "New DHT error: %v", err)
		os.Exit(1)
	}
	var d6 *dht.DHT
	if len(*ipv6Address) > 1 {
		fmt.Printf("Tring to bind to IPv6=%s\n", *ipv6Address)
		d6, err = dht.New(conf6)
		if err != nil {
			fmt.Fprintf(os.Stderr, "New DHT error: %v", err)
			os.Exit(1)
		}
		if err = d6.Start(); err != nil {
			fmt.Fprintf(os.Stderr, "DHT start error: %v", err)
			os.Exit(1)
		}
		go drainresults(d6)
	} else {
		fmt.Fprintf(os.Stderr, "Not binding to IPv6 interface.  If desired pass -v6=[address] for the\n")
		fmt.Fprintf(os.Stderr, "address you want the DHT to bind to.  Privacy addresses are not recommended\n")
		fmt.Fprintf(os.Stderr, "Since they can expire and connections will fail\n\n")
	}

	// For debugging.
	go http.ListenAndServe(fmt.Sprintf(":%d", httpPortTCP), nil)

	if err = d4.Start(); err != nil {
		fmt.Fprintf(os.Stderr, "DHT start error: %v", err)
		os.Exit(1)
	}
	go drainresults(d4)
	for {
		d4.PeersRequest(string(ih), true)
		if len(*ipv6Address) > 1 {
			d6.PeersRequest(string(ih), true)
		}
		time.Sleep(5 * time.Second)
	}
}