forked from YouROK/TorrServer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
stream.go
95 lines (83 loc) · 2.38 KB
/
stream.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package torr
import (
"encoding/hex"
"errors"
"fmt"
"log"
"net"
"net/http"
"time"
"github.com/anacrolix/dms/dlna"
"github.com/anacrolix/missinggo/v2/httptoo"
"github.com/anacrolix/torrent"
mt "github.com/Terisback/TorrServer/server/mimetype"
sets "github.com/Terisback/TorrServer/server/settings"
"github.com/Terisback/TorrServer/server/torr/state"
)
func (t *Torrent) Stream(fileID int, req *http.Request, resp http.ResponseWriter) error {
if !t.GotInfo() {
http.NotFound(resp, req)
return errors.New("torrent don't get info")
}
st := t.Status()
var stFile *state.TorrentFileStat
for _, fileStat := range st.FileStats {
if fileStat.Id == fileID {
stFile = fileStat
break
}
}
if stFile == nil {
return fmt.Errorf("file with id %v not found", fileID)
}
files := t.Files()
var file *torrent.File
for _, tfile := range files {
if tfile.Path() == stFile.Path {
file = tfile
break
}
}
if file == nil {
return fmt.Errorf("file with id %v not found", fileID)
}
if int64(sets.MaxSize) > 0 && file.Length() > int64(sets.MaxSize) {
log.Println("file", file.DisplayPath(), "size exceeded max allowed", sets.MaxSize, "bytes")
return fmt.Errorf("file size exceeded max allowed %d bytes", sets.MaxSize)
}
reader := t.NewReader(file)
host, port, err := net.SplitHostPort(req.RemoteAddr)
if sets.BTsets.EnableDebug {
if err != nil {
log.Println("Connect client")
} else {
log.Println("Connect client", host, port)
}
}
sets.SetViewed(&sets.Viewed{Hash: t.Hash().HexString(), FileIndex: fileID})
resp.Header().Set("Connection", "close")
etag := hex.EncodeToString([]byte(fmt.Sprintf("%s/%s", t.Hash().HexString(), file.Path())))
resp.Header().Set("ETag", httptoo.EncodeQuotedString(etag))
// DLNA headers
resp.Header().Set("transferMode.dlna.org", "Streaming")
mime, err := mt.MimeTypeByPath(file.Path())
if err == nil && mime.IsMedia() {
resp.Header().Set("content-type", mime.String())
}
if req.Header.Get("getContentFeatures.dlna.org") != "" {
resp.Header().Set("contentFeatures.dlna.org", dlna.ContentFeatures{
SupportRange: true,
SupportTimeSeek: true,
}.String())
}
http.ServeContent(resp, req, file.Path(), time.Unix(t.Timestamp, 0), reader)
t.CloseReader(reader)
if sets.BTsets.EnableDebug {
if err != nil {
log.Println("Disconnect client")
} else {
log.Println("Disconnect client", host, port)
}
}
return nil
}