lastChunkSent time.Time
// Stuff controlled by the local peer.
- Interested bool
+ Interested bool
+ lastBecameInterested time.Time
+ priorInterest time.Duration
+
Choked bool
requests map[request]struct{}
requestsLowWater int
writerCond sync.Cond
}
+func (cn *connection) cumInterest() time.Duration {
+ ret := cn.priorInterest
+ if cn.Interested {
+ ret += time.Since(cn.lastBecameInterested)
+ }
+ return ret
+}
+
func (cn *connection) peerHasAllPieces() (all bool, known bool) {
if cn.peerSentHaveAll {
return true, true
return
}
-func (cn *connection) String() string {
- var buf bytes.Buffer
- cn.WriteStatus(&buf, nil)
- return buf.String()
+// func (cn *connection) String() string {
+// var buf bytes.Buffer
+// cn.WriteStatus(&buf, nil)
+// return buf.String()
+// }
+
+func (cn *connection) downloadRate() float64 {
+ return float64(cn.stats.BytesReadUsefulData) / cn.cumInterest().Seconds()
}
func (cn *connection) WriteStatus(w io.Writer, t *Torrent) {
// \t isn't preserved in <pre> blocks?
- fmt.Fprintf(w, "%-40s: %s-%s\n", cn.PeerID, cn.localAddr(), cn.remoteAddr())
- fmt.Fprintf(w, " last msg: %s, connected: %s, last helpful: %s\n",
+ fmt.Fprintf(w, "%+-55q %s %s-%s\n", cn.PeerID, cn.PeerExtensionBytes, cn.localAddr(), cn.remoteAddr())
+ fmt.Fprintf(w, " last msg: %s, connected: %s, last helpful: %s, itime: %s\n",
eventAgeString(cn.lastMessageReceived),
eventAgeString(cn.completedHandshake),
- eventAgeString(cn.lastHelpful()))
+ eventAgeString(cn.lastHelpful()),
+ cn.cumInterest(),
+ )
fmt.Fprintf(w,
- " %s completed, %d pieces touched, good chunks: %d/%d-%d reqq: %d-%d, flags: %s\n",
+ " %s completed, %d pieces touched, good chunks: %d/%d-%d reqq: (%d,%d,%d]-%d, flags: %s, dr: %.1f KiB/s\n",
cn.completedString(),
len(cn.peerTouchedPieces),
cn.stats.ChunksReadUseful,
- // TODO: Use ChunksRead? Verify that value is the same as this sum?
- cn.stats.ChunksReadUnwanted+cn.stats.ChunksReadUseful,
+ cn.stats.ChunksRead,
cn.stats.ChunksWritten,
+ cn.requestsLowWater,
cn.numLocalRequests(),
+ cn.nominalMaxRequests(),
len(cn.PeerRequests),
cn.statusFlags(),
+ cn.downloadRate()/(1<<10),
)
roi := cn.pieceRequestOrderIter()
fmt.Fprintf(w, " next pieces: %v%s\n",
return true
}
cn.Interested = interested
+ if interested {
+ cn.lastBecameInterested = time.Now()
+ } else if !cn.lastBecameInterested.IsZero() {
+ cn.priorInterest += time.Since(cn.lastBecameInterested)
+ }
// log.Printf("%p: setting interest: %v", cn, interested)
return msg(pp.Message{
Type: func() pp.MessageType {
peerExtensionBytes [8]byte
)
+func (me peerExtensionBytes) String() string {
+ return hex.EncodeToString(me[:])
+}
+
func newPeerExtensionBytes(bits ...ExtensionBit) (ret peerExtensionBytes) {
for _, b := range bits {
ret.SetBit(b)
missinggo.CopyExact(&res.peerExtensionBytes, b[20:28])
missinggo.CopyExact(&res.Hash, b[28:48])
missinggo.CopyExact(&res.PeerID, b[48:68])
- peerExtensions.Add(hex.EncodeToString(res.peerExtensionBytes[:]), 1)
+ peerExtensions.Add(res.peerExtensionBytes.String(), 1)
// TODO: Maybe we can just drop peers here if we're not interested. This
// could prevent them trying to reconnect, falsely believing there was
package torrent
-import (
- "encoding/hex"
-)
-
// Peer client ID.
type PeerID [20]byte
-// Pretty prints the ID as hex, except parts that adher to the Peer ID
-// Conventions of BEP 20.
-func (me PeerID) String() string {
- if me[0] == '-' && me[7] == '-' {
- return string(me[:8]) + hex.EncodeToString(me[8:])
- }
- return hex.EncodeToString(me[:])
-}
+// // Pretty prints the ID as hex, except parts that adher to the Peer ID
+// // Conventions of BEP 20.
+// func (me PeerID) String() string {
+// // if me[0] == '-' && me[7] == '-' {
+// // return string(me[:8]) + hex.EncodeToString(me[8:])
+// // }
+// // return hex.EncodeToString(me[:])
+// return fmt.Sprintf("%+q", me[:])
+// }
package torrent
-import (
- "fmt"
- "testing"
-
- "github.com/anacrolix/missinggo"
- "github.com/stretchr/testify/assert"
-)
-
-func TestPeerIdString(t *testing.T) {
- for _, _case := range []struct {
- id string
- s string
- }{
- {"\x1cNJ}\x9c\xc7\xc4o\x94<\x9b\x8c\xc2!I\x1c\a\xec\x98n", "1c4e4a7d9cc7c46f943c9b8cc221491c07ec986e"},
- {"-FD51W\xe4-LaZMk0N8ZLA7", "-FD51W\xe4-4c615a4d6b304e385a4c4137"},
- } {
- var pi PeerID
- missinggo.CopyExact(&pi, _case.id)
- assert.EqualValues(t, _case.s, pi.String())
- assert.EqualValues(t, fmt.Sprintf("%q", _case.s), fmt.Sprintf("%q", pi))
- }
-}
+// func TestPeerIdString(t *testing.T) {
+// for _, _case := range []struct {
+// id string
+// s string
+// }{
+// {"\x1cNJ}\x9c\xc7\xc4o\x94<\x9b\x8c\xc2!I\x1c\a\xec\x98n", "\"\x1cNJ}\x9c\xc7\xc4o\x94<\x9b\x8c\xc2!I\x1c\a\xec\x98n\""},
+// {"-FD51W\xe4-LaZMk0N8ZLA7", "-FD51W\xe4-LaZMk0N8ZLA7"},
+// } {
+// var pi PeerID
+// missinggo.CopyExact(&pi, _case.id)
+// assert.EqualValues(t, _case.s, pi.String())
+// assert.EqualValues(t, fmt.Sprintf("%q", _case.s), fmt.Sprintf("%q", pi))
+// }
+// }