示例#1
0
func RunTorrents(flags *TorrentFlags, torrentFiles []string) (err error) {
	conChan, listenPort, err := ListenForPeerConnections(flags)
	if err != nil {
		log.Println("Couldn't listen for peers connection: ", err)
		return
	}
	quitChan := listenSigInt()

	createChan := make(chan string, flags.MaxActive)
	startChan := make(chan *TorrentSession, 1)
	doneChan := make(chan *TorrentSession, 1)

	var dhtNode dht.DHT
	if flags.UseDHT {
		dhtNode = *startDHT(flags.Port)
	}

	torrentSessions := make(map[string]*TorrentSession)

	go func() {
		for torrentFile := range createChan {
			ts, err := NewTorrentSession(flags, torrentFile, uint16(listenPort))
			if err != nil {
				log.Println("Couldn't create torrent session for "+torrentFile+" .", err)
				doneChan <- &TorrentSession{}
			} else {
				log.Printf("Created torrent session for %s", ts.M.Info.Name)
				startChan <- ts
			}
		}
	}()

	torrentQueue := []string{}
	if len(torrentFiles) > flags.MaxActive {
		torrentQueue = torrentFiles[flags.MaxActive:]
	}

	for i, torrentFile := range torrentFiles {
		if i < flags.MaxActive {
			createChan <- torrentFile
		} else {
			break
		}
	}

	lpd := &Announcer{}
	if flags.UseLPD {
		lpd, err = NewAnnouncer(uint16(listenPort))
		if err != nil {
			log.Println("Couldn't listen for Local Peer Discoveries: ", err)
			flags.UseLPD = false
		}
	}

	theWorldisEnding := false
mainLoop:
	for {
		select {
		case ts := <-startChan:
			if !theWorldisEnding {
				ts.dht = &dhtNode
				if flags.UseLPD {
					lpd.Announce(ts.M.InfoHash)
				}
				torrentSessions[ts.M.InfoHash] = ts
				log.Printf("Starting torrent session for %s", ts.M.Info.Name)
				go func(t *TorrentSession) {
					t.DoTorrent()
					doneChan <- t
				}(ts)
			}
		case ts := <-doneChan:
			if ts.M != nil {
				delete(torrentSessions, ts.M.InfoHash)
				if flags.UseLPD {
					lpd.StopAnnouncing(ts.M.InfoHash)
				}
			}
			if !theWorldisEnding && len(torrentQueue) > 0 {
				createChan <- torrentQueue[0]
				torrentQueue = torrentQueue[1:]
				continue mainLoop
			}

			if len(torrentSessions) == 0 {
				break mainLoop
			}
		case <-quitChan:
			theWorldisEnding = true
			for _, ts := range torrentSessions {
				go ts.Quit()
			}
		case c := <-conChan:
			//	log.Printf("New bt connection for ih %x", c.Infohash)
			if ts, ok := torrentSessions[c.Infohash]; ok {
				ts.AcceptNewPeer(c)
			}
		case dhtPeers := <-dhtNode.PeersRequestResults:
			for key, peers := range dhtPeers {
				if ts, ok := torrentSessions[string(key)]; ok {
					// log.Printf("Received %d DHT peers for torrent session %x\n", len(peers), []byte(key))
					for _, peer := range peers {
						peer = dht.DecodePeerAddress(peer)
						ts.HintNewPeer(peer)
					}
				} else {
					log.Printf("Received DHT peer for an unknown torrent session %x\n", []byte(key))
				}
			}
		case announce := <-lpd.Announces:
			hexhash, err := hex.DecodeString(announce.Infohash)
			if err != nil {
				log.Println("Err with hex-decoding:", err)
			}
			if ts, ok := torrentSessions[string(hexhash)]; ok {
				// log.Printf("Received LPD announce for ih %s", announce.Infohash)
				ts.HintNewPeer(announce.Peer)
			}
		}
	}
	if flags.UseDHT {
		dhtNode.Stop()
	}
	return
}