Beispiel #1
0
func main() {
	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)
	}
	// Starts a DHT node with the default options. It picks a random UDP port. To change this, see dht.NewConfig.
	d, err := dht.New(nil)
	if err != nil {
		fmt.Fprintf(os.Stderr, "New DHT error: %v", err)
		os.Exit(1)

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

	go d.Run()
	go drainresults(d)

	for {
		d.PeersRequest(string(ih), false)
		time.Sleep(5 * time.Second)
	}
}
Beispiel #2
0
// Sets up the DHT node for peer bootstrapping
func (self *DHT) Init() error {
	sum := sha1.Sum([]byte(self.Config.Info))
	// Create a hex encoded sha1 sum of a string to be used for DH
	infoHash, err := dht.DecodeInfoHash(hex.EncodeToString(sum[:]))
	if err != nil {
		return err
	}
	cfg := dht.NewConfig()
	cfg.Port = self.Config.port
	cfg.NumTargetPeers = self.Config.DesiredPeers
	d, err := dht.New(cfg)
	if err != nil {
		return err
	}
	self.InfoHash = infoHash
	self.DHT = d

	if self.Config.Disabled {
		// We have to initialize the DHT anyway because daemon loop needs
		// to read from its initialized chans. As long as Start() is prevented,
		// the DHT will not run.
		logger.Info("DHT is disabled")
	} else {
		logger.Info("Init DHT on port %d", self.Config.port)
	}
	return nil
}
func DiscoverPeers(cm *network.ConnectionManager, address string) {
	// Hex encoded string: "The Distributed Bay!"
	ih, err := dht.DecodeInfoHash("5468652044697374726962757465642042617921")
	if err != nil {
		log.Fatalf("DHT DecodeInfoHash error: %v\n", err)
	}

	_, portStr, err := net.SplitHostPort(address)
	if err != nil {
		log.Fatal("Bind address error!", err)
	}
	port, err := strconv.Atoi(portStr)
	if err != nil {
		log.Fatal(err)
	}

	config := dht.NewConfig()
	config.Port = port
	config.NumTargetPeers = 10
	node, err := dht.New(config)
	if err != nil {
		log.Fatal("Error creating DHT node!")
	}

	go node.Run()
	go checkPeers(node, cm)

	log.Println("Requesting peers from the DHT!")

	for {
		node.PeersRequest(string(ih), true)
		time.Sleep(15 * time.Second)
	}

}
Beispiel #4
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)
				}
			}
		}
	}
}
Beispiel #5
0
func NewMetaInfoFromMagnet(torrent string) (m *MetaInfo, err error) {
	magnet, err := parseMagnet(torrent)
	if err != nil {
		log.Println("Couldn't parse magnet: ", err)
		return
	}

	ih, err := dht.DecodeInfoHash(magnet.InfoHashes[0])
	if err != nil {
		return
	}

	m = &MetaInfo{InfoHash: string(ih)}
	return

}
Beispiel #6
0
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)
	}
}
Beispiel #7
0
func main() {
	// randomly generated hash: AE6D4306F4AE6D4306F4AE6D4306F4AE6D4306F4
	// ubuntu-12.04.4-desktop-amd64.iso: deca7a89a1dbdc4b213de1c0d5351e92582f31fb
	ih, err := dht.DecodeInfoHash("AE6D4306F4AE6D4306F4AE6D4306F4AE6D4306F4")
	if err != nil {
		fmt.Fprintf(os.Stderr, "DecodeInfoHash error: %v\n", err)
		os.Exit(1)
	}
	// Starts a DHT node with the default options. It picks a random UDP port. To change this, see dht.NewConfig.
	d, err := dht.New(nil)
	if err != nil {
		fmt.Fprintf(os.Stderr, "New DHT error: %v", err)
		os.Exit(1)
	}
	go d.Run()
	go drain(d)

	for {
		d.PeersRequest(string(ih), false)
		time.Sleep(5 * time.Second)
	}
}
Beispiel #8
0
func (d *DiscoveryDHT) Run() error {
	var err error

	d.ih, err = dht.DecodeInfoHash(d.localNode.Config().NetworkID)
	if err != nil {
		return fmt.Errorf("decode infohash err: %s", err)
	}
	config := dht.NewConfig()
	config.Port = d.localNode.State().ListenPort
	d.node, err = dht.New(config)
	if err != nil {
		return fmt.Errorf("new dht init err: %s", err)
	}
	if err = d.node.Start(); err != nil {
		return fmt.Errorf("dht start err: %s", err)
	}
	d.waitGroup.Add(2)
	go d.process()
	go d.awaitPeers()
	d.waitGroup.Wait()
	return nil
}
Beispiel #9
0
// Requests peers from the DHT
func (self *DHT) RequestPeers(infoHashString string) {
	if self.Config.Disabled {
		return
	}

	sum := sha1.Sum([]byte(infoHashString))
	// Create a hex encoded sha1 sum of a string to be used for DH
	infoHash, err := dht.DecodeInfoHash(hex.EncodeToString(sum[:]))
	if err != nil {
		log.Panic()
	}

	ih := string(infoHash)
	if ih == "" {
		log.Panic("InfoHash is not initialized")
		return
	}

	self.InfoHashes[ih] = infoHashString

	logger.Info("Requesting DHT Peers: infoHashString= %s", infoHashString)
	self.DHT.PeersRequest(ih, true)
}
Beispiel #10
0
func getMetaInfo(torrent string) (metaInfo *MetaInfo, err error) {
	var input io.ReadCloser
	if strings.HasPrefix(torrent, "http:") {
		r, err := proxyHttpGet(torrent)
		if err != nil {
			return nil, err
		}
		input = r.Body
	} else if strings.HasPrefix(torrent, "magnet:") {
		magnet, err := parseMagnet(torrent)
		if err != nil {
			log.Println("Couldn't parse magnet: ", err)
			return nil, err
		}

		ih, err := dht.DecodeInfoHash(magnet.InfoHashes[0])
		if err != nil {
			return nil, err
		}

		metaInfo = &MetaInfo{InfoHash: string(ih)}
		return metaInfo, err

	} else {
		if input, err = os.Open(torrent); err != nil {
			return
		}
	}

	// We need to calcuate the sha1 of the Info map, including every value in the
	// map. The easiest way to do this is to read the data using the Decode
	// API, and then pick through it manually.
	var m interface{}
	m, err = bencode.Decode(input)
	input.Close()
	if err != nil {
		err = errors.New("Couldn't parse torrent file phase 1: " + err.Error())
		return
	}

	topMap, ok := m.(map[string]interface{})
	if !ok {
		err = errors.New("Couldn't parse torrent file phase 2.")
		return
	}

	infoMap, ok := topMap["info"]
	if !ok {
		err = errors.New("Couldn't parse torrent file. info")
		return
	}
	var b bytes.Buffer
	if err = bencode.Marshal(&b, infoMap); err != nil {
		return
	}
	hash := sha1.New()
	hash.Write(b.Bytes())

	var m2 MetaInfo
	err = bencode.Unmarshal(&b, &m2.Info)
	if err != nil {
		return
	}

	m2.InfoHash = string(hash.Sum(nil))
	m2.Announce = getString(topMap, "announce")
	m2.AnnounceList = getSliceSliceString(topMap, "announce-list")
	m2.CreationDate = getString(topMap, "creation date")
	m2.Comment = getString(topMap, "comment")
	m2.CreatedBy = getString(topMap, "created by")
	m2.Encoding = getString(topMap, "encoding")

	metaInfo = &m2
	return
}
Beispiel #11
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)
	}
}