]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Support seeding
authorMatt Joiner <anacrolix@gmail.com>
Thu, 14 May 2015 22:39:53 +0000 (08:39 +1000)
committerMatt Joiner <anacrolix@gmail.com>
Thu, 14 May 2015 22:39:53 +0000 (08:39 +1000)
client.go
cmd/torrent/main.go
config.go
connection.go

index f5ecac7cfb45282828ee6465a4ba5b82794e6a66..1e8755f10438d8ef78c6fd2835c64aebf7966e86 100644 (file)
--- a/client.go
+++ b/client.go
@@ -1167,14 +1167,7 @@ func (me *Client) sendInitialMessages(conn *connection, torrent *torrent) {
                                        }(),
                                        "v": extendedHandshakeClientVersion,
                                        // No upload queue is implemented yet.
-                                       "reqq": func() int {
-                                               if me.config.NoUpload {
-                                                       // No need to look strange if it costs us nothing.
-                                                       return 250
-                                               } else {
-                                                       return 1
-                                               }
-                                       }(),
+                                       "reqq": 64,
                                }
                                if !me.config.DisableEncryption {
                                        d["e"] = 1
@@ -1454,13 +1447,13 @@ func (me *Client) connectionLoop(t *torrent, c *connection) error {
                        if me.config.NoUpload {
                                break
                        }
-                       if c.PeerRequests == nil {
-                               c.PeerRequests = make(map[request]struct{}, maxRequests)
-                       }
                        request := newRequest(msg.Index, msg.Begin, msg.Length)
                        // TODO: Requests should be satisfied from a dedicated upload
                        // routine.
                        // c.PeerRequests[request] = struct{}{}
+                       // if c.PeerRequests == nil {
+                       //      c.PeerRequests = make(map[request]struct{}, maxRequests)
+                       // }
                        p := make([]byte, msg.Length)
                        n, err := dataReadAt(t.data, p, int64(t.pieceLength(0))*int64(msg.Index)+int64(msg.Begin))
                        if err != nil {
@@ -1476,6 +1469,7 @@ func (me *Client) connectionLoop(t *torrent, c *connection) error {
                                Piece: p,
                        })
                        uploadChunksPosted.Add(1)
+                       c.chunksSent++
                case pp.Cancel:
                        req := newRequest(msg.Index, msg.Begin, msg.Length)
                        if !c.PeerCancel(req) {
@@ -2196,9 +2190,13 @@ func (cl *Client) waitWantPeers(t *torrent) bool {
                        return false
                default:
                }
-               if len(t.Peers) < torrentPeersLowWater && t.needData() {
+               if len(t.Peers) > torrentPeersLowWater {
+                       goto wait
+               }
+               if t.needData() || cl.seeding(t) {
                        return true
                }
+       wait:
                cl.mu.Unlock()
                t.wantPeers.Wait()
                t.stateMu.Unlock()
@@ -2207,6 +2205,11 @@ func (cl *Client) waitWantPeers(t *torrent) bool {
        }
 }
 
+// Returns whether the client should make effort to seed the torrent.
+func (cl *Client) seeding(t *torrent) bool {
+       return cl.config.Seed && !cl.config.NoUpload
+}
+
 func (cl *Client) announceTorrentDHT(t *torrent, impliedPort bool) {
        for cl.waitWantPeers(t) {
                log.Printf("getting peers for %q from DHT", t)
index d81d219ed8ceb65cc13e0cf533c882b2146b9eb4..8f8b67ecd0859a148ae31f9557c127cb68f9943a 100644 (file)
@@ -73,7 +73,6 @@ func main() {
        log.SetFlags(log.LstdFlags | log.Lshortfile)
        var rootGroup struct {
                Client    torrent.Config `group:"Client Options"`
-               Seed      bool           `long:"seed" description:"continue seeding torrents after completed"`
                TestPeers []string       `long:"test-peer" description:"address of peer to inject to every torrent"`
        }
        // Don't pass flags.PrintError because it's inconsistent with printing.
@@ -151,7 +150,7 @@ waitDone:
                        os.Stdout.WriteString(progressLine(client))
                }
        }
-       if rootGroup.Seed {
+       if rootGroup.Client.Seed {
                select {}
        }
 }
index 56081998900b273dc867dd2e22e56ffedac23417..b6921182a2fd6416e05cbc44baa68646fe7aa446 100644 (file)
--- a/config.go
+++ b/config.go
@@ -20,8 +20,11 @@ type Config struct {
        NoDHT bool `long:"disable-dht"`
        // Overrides the default DHT configuration.
        DHTConfig *dht.ServerConfig
-       // Don't send chunks to peers.
+       // Don't ever send chunks to peers.
        NoUpload bool `long:"no-upload"`
+       // Upload even after there's nothing in it for us. By default uploading is
+       // not altruistic.
+       Seed bool `long:"seed"`
        // User-provided Client peer ID. If not present, one is generated automatically.
        PeerID string
        // For the bittorrent protocol.
index 1913298d608245614f64bc64d9b0f87803eb9094..ed94626ff3a890b1b0d1242045374fa0708f548c 100644 (file)
@@ -46,6 +46,7 @@ type connection struct {
 
        UnwantedChunksReceived int
        UsefulChunksReceived   int
+       chunksSent             int
 
        lastMessageReceived     time.Time
        completedHandshake      time.Time
@@ -237,13 +238,16 @@ func (cn *connection) WriteStatus(w io.Writer, t *torrent) {
                eventAgeString(cn.lastMessageReceived),
                eventAgeString(cn.completedHandshake),
                eventAgeString(cn.lastUsefulChunkReceived))
-       fmt.Fprintf(w, "    %s completed, good chunks: %d/%d reqs: %d-%d, flags: %s\n",
+       fmt.Fprintf(w,
+               "    %s completed, good chunks: %d/%d-%d reqq: %d-%d, flags: %s\n",
                cn.completedString(t),
                cn.UsefulChunksReceived,
                cn.UnwantedChunksReceived+cn.UsefulChunksReceived,
+               cn.chunksSent,
                len(cn.Requests),
                len(cn.PeerRequests),
-               cn.statusFlags())
+               cn.statusFlags(),
+       )
 }
 
 func (c *connection) Close() {