Skip to content

Commit

Permalink
change files/file-stats api; expose via rpc
Browse files Browse the repository at this point in the history
  • Loading branch information
cenkalti committed Sep 18, 2024
1 parent 08f1d72 commit 77f2e4f
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 33 deletions.
32 changes: 32 additions & 0 deletions internal/rpctypes/rpctypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,18 @@ type Tracker struct {
NextAnnounce Time
}

// File inside a Torrent.
type File struct {
Path string
Length int64
}

// FileStats contains statistics about a File in a Torrent.
type FileStats struct {
File File
BytesCompleted int64
}

// SessionStats contains statistics about a Session.
type SessionStats struct {
Uptime int
Expand Down Expand Up @@ -273,6 +285,26 @@ type GetTorrentWebseedsResponse struct {
Webseeds []Webseed
}

// GetTorrentFilesRequest contains request arguments for Session.GetTorrentFiles method.
type GetTorrentFilesRequest struct {
ID string
}

// GetTorrentFilesResponse contains response arguments for Session.GetTorrentFiles method.
type GetTorrentFilesResponse struct {
Files []File
}

// GetTorrentFileStatsRequest contains request arguments for Session.GetTorrentFileStats method.
type GetTorrentFileStatsRequest struct {
ID string
}

// GetTorrentFileStatsResponse contains response arguments for Session.GetTorrentFileStats method.
type GetTorrentFileStatsResponse struct {
FileStats []FileStats
}

// StartTorrentRequest contains request arguments for Session.StartTorrent method.
type StartTorrentRequest struct {
ID string
Expand Down
52 changes: 52 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,30 @@ func main() {
},
},
},
{
Name: "files",
Usage: "get file list of torrent",
Category: "Getters",
Action: handleFiles,
Flags: []cli.Flag{
cli.StringFlag{
Name: "id",
Required: true,
},
},
},
{
Name: "file-stats",
Usage: "get stats of files in torrent",
Category: "Getters",
Action: handleFileStats,
Flags: []cli.Flag{
cli.StringFlag{
Name: "id",
Required: true,
},
},
},
{
Name: "peers",
Usage: "get peers of torrent",
Expand Down Expand Up @@ -1007,6 +1031,34 @@ func handleWebseeds(c *cli.Context) error {
return nil
}

func handleFiles(c *cli.Context) error {
resp, err := clt.GetTorrentFiles(c.String("id"))
if err != nil {
return err
}
b, err := prettyjson.Marshal(resp)
if err != nil {
return err
}
_, _ = os.Stdout.Write(b)
_, _ = os.Stdout.WriteString("\n")
return nil
}

func handleFileStats(c *cli.Context) error {
resp, err := clt.GetTorrentFileStats(c.String("id"))
if err != nil {
return err
}
b, err := prettyjson.Marshal(resp)
if err != nil {
return err
}
_, _ = os.Stdout.Write(b)
_, _ = os.Stdout.WriteString("\n")
return nil
}

func handlePeers(c *cli.Context) error {
resp, err := clt.GetTorrentPeers(c.String("id"))
if err != nil {
Expand Down
12 changes: 12 additions & 0 deletions rainrpc/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,18 @@ func (c *Client) GetTorrentWebseeds(id string) ([]rpctypes.Webseed, error) {
return reply.Webseeds, c.client.Call("Session.GetTorrentWebseeds", args, &reply)
}

func (c *Client) GetTorrentFiles(id string) ([]rpctypes.File, error) {
args := rpctypes.GetTorrentFilesRequest{ID: id}
var reply rpctypes.GetTorrentFilesResponse
return reply.Files, c.client.Call("Session.GetTorrentFiles", args, &reply)
}

func (c *Client) GetTorrentFileStats(id string) ([]rpctypes.FileStats, error) {
args := rpctypes.GetTorrentFileStatsRequest{ID: id}
var reply rpctypes.GetTorrentFileStatsResponse
return reply.FileStats, c.client.Call("Session.GetTorrentFileStats", args, &reply)
}

// StartTorrent starts the torrent.
func (c *Client) StartTorrent(id string) error {
args := rpctypes.StartTorrentRequest{ID: id}
Expand Down
41 changes: 41 additions & 0 deletions torrent/session_rpc_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,47 @@ func (h *rpcHandler) GetTorrentWebseeds(args *rpctypes.GetTorrentWebseedsRequest
return nil
}

func (h *rpcHandler) GetTorrentFiles(args *rpctypes.GetTorrentFilesRequest, reply *rpctypes.GetTorrentFilesResponse) error {
t := h.session.GetTorrent(args.ID)
if t == nil {
return errTorrentNotFound
}
files, err := t.Files()
if err != nil {
return err
}
reply.Files = make([]rpctypes.File, len(files))
for i, f := range files {
reply.Files[i] = rpctypes.File{
Path: f.Path(),
Length: f.Length(),
}
}
return nil
}

func (h *rpcHandler) GetTorrentFileStats(args *rpctypes.GetTorrentFileStatsRequest, reply *rpctypes.GetTorrentFileStatsResponse) error {
t := h.session.GetTorrent(args.ID)
if t == nil {
return errTorrentNotFound
}
stats, err := t.FileStats()
if err != nil {
return err
}
reply.FileStats = make([]rpctypes.FileStats, len(stats))
for i, s := range stats {
reply.FileStats[i] = rpctypes.FileStats{
File: rpctypes.File{
Path: s.File.Path(),
Length: s.File.Length(),
},
BytesCompleted: s.BytesCompleted,
}
}
return nil
}

func (h *rpcHandler) StartTorrent(args *rpctypes.StartTorrentRequest, reply *rpctypes.StartTorrentResponse) error {
t := h.session.GetTorrent(args.ID)
if t == nil {
Expand Down
14 changes: 6 additions & 8 deletions torrent/session_torrent.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,16 @@ func (t *Torrent) RootDirectory() string {
return t.torrent.RootDirectory()
}

// The files in the torrent.
// The paths of the files are relative to the root directory.
func (t *Torrent) FilePaths() ([]string, error) {
return t.torrent.FilePaths()
}

// The files in the torrent with completion info. An error is returned
// when metainfo isn't ready.
// Files in the torrent. An error is returned when metainfo isn't ready.
func (t *Torrent) Files() ([]File, error) {
return t.torrent.Files()
}

// FileStats returns statistics about each file in the torrent. An error is returned when torrent is not running.
func (t *Torrent) FileStats() ([]FileStats, error) {
return t.torrent.FileStats()
}

// InfoHash returns the hash of the info dictionary of torrent file.
// Two different torrents may have the same info hash.
func (t *Torrent) InfoHash() InfoHash {
Expand Down
53 changes: 28 additions & 25 deletions torrent/torrent.go
Original file line number Diff line number Diff line change
Expand Up @@ -418,25 +418,33 @@ func (t *torrent) RootDirectory() string {
return t.storage.RootDir()
}

func (t *torrent) FilePaths() ([]string, error) {
func (t *torrent) Files() ([]File, error) {
if t.info == nil {
return nil, errors.New("torrent metadata not ready")
}

var filePaths []string
files := make([]File, 0, len(t.info.Files))
for _, f := range t.info.Files {
if !f.Padding {
filePaths = append(filePaths, f.Path)
files = append(files, File{
path: f.Path,
length: f.Length,
})
}
}
return filePaths, nil
return files, nil
}

func (t *torrent) Files() ([]File, error) {
if t.info == nil || len(t.pieces) == 0 {
func (t *torrent) FileStats() ([]FileStats, error) {
if len(t.pieces) == 0 {
return nil, errors.New("torrent not running so file stats unavailable")
}

files, err := t.Files()
if err != nil {
return nil, err
}

// calculate bytes completed for each file
fileComp := make(map[string]int64)
for _, p := range t.pieces {
if p.Done {
Expand All @@ -448,39 +456,34 @@ func (t *torrent) Files() ([]File, error) {
}
}

var files []File
for _, f := range t.info.Files {
if !f.Padding {
files = append(files,
File{
path: f.Path,
stats: FileStats{
BytesTotal: f.Length,
BytesCompleted: fileComp[f.Path],
},
})
}
stats := make([]FileStats, 0, len(files))
for _, f := range files {
stats = append(stats,
FileStats{
File: f,
BytesCompleted: fileComp[f.path],
})
}

return files, nil
return stats, nil
}

type FileStats struct {
BytesTotal int64
File
BytesCompleted int64
}

type File struct {
path string
stats FileStats
path string
length int64
}

func (f File) Path() string {
return f.path
}

func (f File) Stats() FileStats {
return f.stats
func (f File) Length() int64 {
return f.length
}

func (t *torrent) announceDHT() {
Expand Down

0 comments on commit 77f2e4f

Please sign in to comment.