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 }
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)) } } }