torrentfs: Write client status to HTTP port
This commit is contained in:
parent
809aabe531
commit
cf31465904
|
@ -109,6 +109,15 @@ type Client struct {
|
|||
dataWaiter chan struct{}
|
||||
}
|
||||
|
||||
func (cl *Client) WriteStatus(w io.Writer) {
|
||||
cl.mu.Lock()
|
||||
defer cl.mu.Unlock()
|
||||
for _, t := range cl.torrents {
|
||||
fmt.Fprintf(w, "%s: %f%%\n", t.MetaInfo.Name, 100*(1-float32(t.BytesLeft())/float32(t.Length())))
|
||||
t.WriteStatus(w)
|
||||
}
|
||||
}
|
||||
|
||||
// Read torrent data at the given offset. Returns ErrDataNotReady if the data
|
||||
// isn't available.
|
||||
func (cl *Client) TorrentReadAt(ih InfoHash, off int64, p []byte) (n int, err error) {
|
||||
|
|
|
@ -26,7 +26,7 @@ var (
|
|||
mountDir string
|
||||
disableTrackers = flag.Bool("disableTrackers", false, "disables trackers")
|
||||
testPeer = flag.String("testPeer", "", "the address for a test peer")
|
||||
pprofAddr = flag.String("pprofAddr", "", "pprof HTTP server bind address")
|
||||
httpAddr = flag.String("httpAddr", "", "HTTP server bind address")
|
||||
readaheadBytes = flag.Int("readaheadBytes", 10*1024*1024, "bytes to readahead in each torrent from the last read piece")
|
||||
testPeerAddr *net.TCPAddr
|
||||
)
|
||||
|
@ -120,8 +120,8 @@ func main() {
|
|||
os.Exit(2)
|
||||
}
|
||||
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
||||
if *pprofAddr != "" {
|
||||
go http.ListenAndServe(*pprofAddr, nil)
|
||||
if *httpAddr != "" {
|
||||
go http.ListenAndServe(*httpAddr, nil)
|
||||
}
|
||||
conn, err := fuse.Mount(mountDir)
|
||||
if err != nil {
|
||||
|
@ -136,6 +136,9 @@ func main() {
|
|||
DisableTrackers: *disableTrackers,
|
||||
DownloadStrategy: &torrent.ResponsiveDownloadStrategy{*readaheadBytes},
|
||||
}
|
||||
http.DefaultServeMux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
|
||||
client.WriteStatus(w)
|
||||
})
|
||||
client.Start()
|
||||
addTorrentDir(client, torrentPath)
|
||||
resolveTestPeerAddr()
|
||||
|
|
|
@ -3,6 +3,8 @@ package torrent
|
|||
import (
|
||||
"container/list"
|
||||
"encoding"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"sync"
|
||||
|
@ -34,6 +36,47 @@ type connection struct {
|
|||
PeerMaxRequests int // Maximum pending requests the peer allows.
|
||||
}
|
||||
|
||||
func (cn *connection) completedString() string {
|
||||
if cn.PeerPieces == nil {
|
||||
return "?"
|
||||
}
|
||||
f := float32(cn.piecesPeerHasCount()) / float32(cn.totalPiecesCount())
|
||||
return fmt.Sprintf("%d%%", int(f*100))
|
||||
}
|
||||
|
||||
func (cn *connection) totalPiecesCount() int {
|
||||
return len(cn.PeerPieces)
|
||||
}
|
||||
|
||||
func (cn *connection) piecesPeerHasCount() (count int) {
|
||||
for _, has := range cn.PeerPieces {
|
||||
if has {
|
||||
count++
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (cn *connection) WriteStatus(w io.Writer) {
|
||||
fmt.Fprintf(w, "%q: %s-%s: %s completed: ", cn.PeerId, cn.Socket.LocalAddr(), cn.Socket.RemoteAddr(), cn.completedString())
|
||||
c := func(b byte) {
|
||||
fmt.Fprintf(w, "%c", b)
|
||||
}
|
||||
// https://trac.transmissionbt.com/wiki/PeerStatusText
|
||||
if len(cn.Requests) != 0 {
|
||||
c('D')
|
||||
} else if cn.Interested {
|
||||
c('d')
|
||||
}
|
||||
if !cn.PeerChoked && !cn.Interested {
|
||||
c('K')
|
||||
}
|
||||
if !cn.Choked && !cn.PeerInterested {
|
||||
c('?')
|
||||
}
|
||||
fmt.Fprintln(w)
|
||||
}
|
||||
|
||||
func (c *connection) Close() {
|
||||
c.mu.Lock()
|
||||
if c.closed {
|
||||
|
|
36
torrent.go
36
torrent.go
|
@ -3,6 +3,7 @@ package torrent
|
|||
import (
|
||||
"container/list"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"sort"
|
||||
|
||||
|
@ -38,6 +39,37 @@ type torrent struct {
|
|||
lastReadPiece int
|
||||
}
|
||||
|
||||
func (t *torrent) pieceStatusChar(index int) byte {
|
||||
p := t.Pieces[index]
|
||||
switch {
|
||||
case p.Complete():
|
||||
return 'C'
|
||||
case p.QueuedForHash:
|
||||
return 'Q'
|
||||
case p.Hashing:
|
||||
return 'H'
|
||||
case t.PiecePartiallyDownloaded(index):
|
||||
return 'P'
|
||||
default:
|
||||
return '.'
|
||||
}
|
||||
}
|
||||
|
||||
func (t *torrent) WriteStatus(w io.Writer) {
|
||||
fmt.Fprint(w, "Pieces: ")
|
||||
for index := range t.Pieces {
|
||||
fmt.Fprintf(w, "%c", t.pieceStatusChar(index))
|
||||
}
|
||||
fmt.Fprintln(w)
|
||||
fmt.Fprintln(w, "Priorities: ")
|
||||
for e := t.Priorities.Front(); e != nil; e = e.Next() {
|
||||
fmt.Fprintf(w, "\t%v\n", e.Value)
|
||||
}
|
||||
for _, c := range t.Conns {
|
||||
c.WriteStatus(w)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *torrent) String() string {
|
||||
return t.MetaInfo.Name
|
||||
}
|
||||
|
@ -49,6 +81,10 @@ func (t *torrent) BytesLeft() (left int64) {
|
|||
return
|
||||
}
|
||||
|
||||
func (t *torrent) PiecePartiallyDownloaded(index int) bool {
|
||||
return t.PieceNumPendingBytes(pp.Integer(index)) != t.PieceLength(pp.Integer(index))
|
||||
}
|
||||
|
||||
func NumChunksForPiece(chunkSize int, pieceSize int) int {
|
||||
return (pieceSize + chunkSize - 1) / chunkSize
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue