Esempio n. 1
0
func List(workDir string) []share {
	dir, err := os.Open(workDir)
	if err != nil {
		log.Fatal(err)
	}
	names, err := dir.Readdirnames(-1)
	if err != nil {
		log.Fatal(err)
	}

	shares := make([]share, 0, len(names))
	for _, n := range names {
		if !strings.HasSuffix(n, ".sql") {
			continue
		}
		session, err := sharesession.New(filepath.Join(workDir, n))
		if err != nil {
			continue
		}
		id := session.GetShareId()

		shares = append(shares, share{
			sessionFile: filepath.Join(workDir, n),
			folder:      session.GetTarget(),
			wrs:         id.WRS(),
			rs:          id.RS(),
			s:           id.S(),
		})
	}

	return shares
}
Esempio n. 2
0
func Generate(target, workDir string) error {
	tmpId, err := id.New()
	if err != nil {
		return err
	}
	fmt.Printf("WriteReadStore:\t%s\n     ReadStore:\t%s\n         Store:\t%s\n",
		tmpId.WRS(), tmpId.RS(), tmpId.S())

	dbFile := filepath.Join(workDir, hex.EncodeToString(tmpId.Infohash)+".sql")
	session, err := sharesession.New(dbFile)
	if err != nil {
		return err
	}

	target, err = filepath.Abs(target)
	if err != nil {
		return err
	}
	return session.SaveSession(target, tmpId)
}
Esempio n. 3
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))
		}
	}
}