Beispiel #1
0
func (sess *Session) GetShareId() id.Id {
	var wrs, rs, s string
	err := sess.db.QueryRow(`SELECT wrs, rs, s FROM meta`).Scan(&wrs, &rs, &s)
	if err != nil {
		return id.Id{}
	}
	var ret id.Id
	switch {
	case wrs != "":
		ret, _ = id.NewFromString(wrs)
	case rs != "":
		ret, _ = id.NewFromString(rs)
	case s != "":
		ret, _ = id.NewFromString(s)
	}

	return ret
}
Beispiel #2
0
func Share(cliId string, workDir string, cliTarget string, trackers []string, useLPD bool, manualPeers []string) {
	shareID, err := id.NewFromString(cliId)
	if err != nil {
		fmt.Printf("Couldn't generate shareId: %s\n", err)
		return
	}
	sessionName := hex.EncodeToString(shareID.Infohash) + ".sql"
	session, err := sharesession.New(filepath.Join(workDir, sessionName))
	if err != nil {
		log.Fatal("Couldn't open session file: ", err)
	}

	fmt.Printf("WriteReadStore:\t%s\n     ReadStore:\t%s\n         Store:\t%s\n",
		shareID.WRS(), shareID.RS(), shareID.S())

	target := session.GetTarget()
	if target == "" {
		if cliTarget == "" {
			fmt.Println("Need a folder to share!")
			return
		}
		target = cliTarget
		session.SaveSession(target, shareID)
	} else if cliTarget != "" {
		fmt.Printf("Can't override folder already set to %s\n", target)
	}
	_, err = os.Stat(target)
	if err != nil {
		if os.IsNotExist(err) {
			os.MkdirAll(target, 0744)
		} else {
			fmt.Printf("%s is an invalid dir: %s\n", target, err)
			os.Exit(1)
		}
	}

	// Watcher
	watcher := &Watcher{
		PingNewTorrent: make(chan string),
	}
	if shareID.CanWrite() {
		watcher, err = NewWatcher(session, filepath.Clean(target))
		if err != nil {
			log.Fatal("Couldn't start watcher: ", err)
		}
	} else {
		watcher.PingNewTorrent = make(chan string, 1)
		watcher.PingNewTorrent <- session.GetCurrentInfohash()
	}

	// External listener
	conChan, listenPort, err := listenForPeerConnections([]byte(shareID.Psk[:]))
	if err != nil {
		log.Fatal("Couldn't listen for peers connection: ", err)
	}

	var currentSession TorrentSessionI = EmptyTorrent{}

	// quitChan
	quitChan := listenSigInt()

	// LPD
	lpd := &Announcer{announces: make(chan *Announce)}
	if useLPD {
		lpd, err = NewAnnouncer(listenPort)
		if err != nil {
			log.Fatal("Couldn't listen for Local Peer Discoveries: ", err)
		}
	}

	// Control session
	controlSession, err := NewControlSession(shareID, listenPort, session, trackers)
	if err != nil {
		log.Fatal(err)
	}
	if useLPD {
		lpd.Announce(string(shareID.Infohash))
	}
	for _, peer := range manualPeers {
		controlSession.backoffHintNewPeer(peer)
	}

	peers := session.GetPeers()
	for _, p := range peers {
		log.Printf("Feeding with known peer: %s\n", p)
		controlSession.backoffHintNewPeer(p)
	}

	log.Println("Starting.")

mainLoop:
	for {
		select {
		case <-quitChan:
			err := currentSession.Quit()
			if err != nil {
				log.Println("Failed: ", err)
			} else {
				log.Println("Done")
			}
			break mainLoop
		case c := <-conChan:
			if currentSession.Matches(c.infohash) {
				currentSession.AcceptNewPeer(c)
			} else if controlSession.Matches(c.infohash) {
				controlSession.AcceptNewPeer(c)
			}
		case announce := <-lpd.announces:
			hexhash, err := hex.DecodeString(announce.infohash)
			if err != nil {
				log.Println("Err with hex-decoding:", err)
				break
			}
			if controlSession.Matches(string(hexhash)) {
				controlSession.backoffHintNewPeer(announce.peer)
			}
		case ih := <-watcher.PingNewTorrent:
			if ih == controlSession.currentIH && !currentSession.IsEmpty() {
				break
			}
			err := controlSession.SetCurrent(ih)
			if err != nil {
				log.Fatal("Error setting new current infohash:", err)
			}

			currentSession.Quit()

			torrentFile := session.GetCurrentTorrent()
			tentativeSession, err := NewTorrentSession(shareID, target, torrentFile, listenPort)
			if err != nil {
				if !os.IsNotExist(err) {
					log.Println("Couldn't start new session from watched dir: ", err)
				}

				// Fallback to an emptytorrent, because the previous one is
				// invalid; hope it will be ok next time !
				currentSession = EmptyTorrent{}
				break
			}
			currentSession = tentativeSession
			go currentSession.DoTorrent()

			for _, peer := range controlSession.peers.All() {
				currentSession.hintNewPeer(peer.address)
			}
		case announce := <-controlSession.Torrents:
			if controlSession.currentIH == announce.infohash && !currentSession.IsEmpty() {
				break
			}
			err := controlSession.SetCurrent(announce.infohash)
			if err != nil {
				log.Fatal("Error setting new current infohash:", err)
			}

			currentSession.Quit()

			log.Println("Opening new torrent session")
			magnet := fmt.Sprintf("magnet:?xt=urn:btih:%x", announce.infohash)
			tentativeSession, err := NewTorrentSession(shareID, target, magnet, listenPort)
			if err != nil {
				log.Println("Couldn't start new session from announce: ", err)
				currentSession = EmptyTorrent{}
				break
			}
			currentSession = tentativeSession
			go currentSession.DoTorrent()
			currentSession.hintNewPeer(announce.peer)
		case peer := <-controlSession.NewPeers:
			if currentSession.IsEmpty() {
				magnet := fmt.Sprintf("magnet:?xt=urn:btih:%x", controlSession.currentIH)
				tentativeSession, err := NewTorrentSession(shareID, target, magnet, listenPort)
				if err != nil {
					log.Printf("Couldn't start new session with new peer: %s\n", err)
					break
				}
				currentSession = tentativeSession
				go currentSession.DoTorrent()
			}
			currentSession.hintNewPeer(peer)
		case meta := <-currentSession.NewMetaInfo():
			var buf bytes.Buffer
			err := bencode.NewEncoder(&buf).Encode(meta)
			if err != nil {
				log.Println(err)
				break
			}
			session.SaveTorrent(buf.Bytes(), meta.InfoHash, time.Now().Format(time.RFC3339))
		}
	}
}