diff --git a/server/dlna/dlna.go b/server/dlna/dlna.go
index 1465267..9bdd7e4 100644
--- a/server/dlna/dlna.go
+++ b/server/dlna/dlna.go
@@ -13,7 +13,6 @@ import (
"github.com/anacrolix/dms/dlna/dms"
"server/log"
- "server/utils"
"server/web/pages/template"
)
@@ -30,7 +29,7 @@ func Start() {
}
for _, i := range ifaces {
// interface flags seem to always be 0 on Windows
- if runtime.GOOS != "windows" && (i.Flags&net.FlagLoopback != 0 || i.Flags&net.FlagUp == 0 || i.Flags&net.FlagMulticast == 0) || !utils.IsPhysicalInterface(i.HardwareAddr.String()) {
+ if runtime.GOOS != "windows" && (i.Flags&net.FlagLoopback != 0 || i.Flags&net.FlagUp == 0 || i.Flags&net.FlagMulticast == 0) {
continue
}
ifs = append(ifs, i)
@@ -168,7 +167,7 @@ func getDefaultFriendlyName() string {
var list []string
for _, i := range ifaces {
// interface flags seem to always be 0 on Windows
- if runtime.GOOS != "windows" && (i.Flags&net.FlagLoopback != 0 || i.Flags&net.FlagUp == 0 || i.Flags&net.FlagMulticast == 0) || !utils.IsPhysicalInterface(i.HardwareAddr.String()) {
+ if runtime.GOOS != "windows" && (i.Flags&net.FlagLoopback != 0 || i.Flags&net.FlagUp == 0 || i.Flags&net.FlagMulticast == 0) {
continue
}
addrs, _ := i.Addrs()
diff --git a/server/dlna/list.go b/server/dlna/list.go
index 2098bc5..4a4673b 100644
--- a/server/dlna/list.go
+++ b/server/dlna/list.go
@@ -13,6 +13,7 @@ import (
"github.com/anacrolix/dms/upnpav"
"server/log"
+ mt "server/mimetype"
"server/settings"
"server/torr"
"server/torr/state"
@@ -72,7 +73,7 @@ func getTorrents() (ret []interface{}) {
Class: "object.container.storageFolder",
Date: upnpav.Timestamp{Time: time.Now()},
}
- cnt := upnpav.Container{Object: obj, ChildCount: 1}
+ cnt := upnpav.Container{Object: obj, ChildCount: 0}
ret = append(ret, cnt)
}
return
@@ -114,50 +115,6 @@ func getTorrent(path, host string) (ret []interface{}) {
}
func getTorrentMeta(path, host string) (ret interface{}) {
- // https://github.com/1100101/minidlna/blob/ca6dbba18390ad6f8b8d7b7dbcf797dbfd95e2db/upnpsoap.c#L1237-L1243
- if path == "/" {
- rootObj := upnpav.Object{
- ID: "0",
- ParentID: "-1",
- Restricted: 1,
- Searchable: 1,
- Title: "TorrServer",
- Date: upnpav.Timestamp{Time: time.Now()},
- Class: "object.container",
- SearchXML: ` object.container.album.musicAlbum
- object.container.genre.musicGenre
- object.container.person.musicArtist
- object.container.playlistContainer
- object.container.storageFolder
- object.item.audioItem.musicTrack
- object.item.imageItem.photo
- object.container.album
- object.container.genre
- object.container
- object.item.audioItem
- object.item.imageItem
- object.item.videoItem
-`,
- }
- // add Root Object
- meta := upnpav.Container{Object: rootObj}
- return meta
- } else if path == "/TR" {
- // TR Object Meta
- trObj := upnpav.Object{
- ID: "%2FTR",
- ParentID: "0",
- Restricted: 1,
- Searchable: 1,
- Title: "Torrents",
- Date: upnpav.Timestamp{Time: time.Now()},
- Class: "object.container",
- }
- //vol := len(torr.ListTorrent())
- meta := upnpav.Container{Object: trObj}
- return meta
- }
-
// find torrent without load
torrs := torr.ListTorrent()
var torr *torr.Torrent
@@ -172,7 +129,34 @@ func getTorrentMeta(path, host string) (ret interface{}) {
}
// Meta object
- if isHashPath(path) {
+ if path == "/" {
+ // root object meta
+ rootObj := upnpav.Object{
+ ID: "0",
+ ParentID: "-1",
+ Restricted: 1,
+ Searchable: 1,
+ Title: "TorrServer",
+ Date: upnpav.Timestamp{Time: time.Now()},
+ Class: "object.container.storageFolder",
+ }
+ meta := upnpav.Container{Object: rootObj, ChildCount: 1}
+ return meta
+ } else if path == "/TR" {
+ // TR Object Meta
+ trObj := upnpav.Object{
+ ID: "%2FTR",
+ ParentID: "0",
+ Restricted: 1,
+ Searchable: 1,
+ Title: "Torrents",
+ Date: upnpav.Timestamp{Time: time.Now()},
+ Class: "object.container.storageFolder",
+ }
+ vol := len(torrs)
+ meta := upnpav.Container{Object: trObj, ChildCount: vol}
+ return meta
+ } else if isHashPath(path) {
// hash object meta
obj := upnpav.Object{
ID: "%2F" + torr.TorrentSpec.InfoHash.HexString(),
@@ -180,15 +164,11 @@ func getTorrentMeta(path, host string) (ret interface{}) {
Restricted: 1,
Title: torr.Title,
Date: upnpav.Timestamp{Time: time.Now()},
- Class: "object.container",
}
- meta := upnpav.Container{Object: obj}
+ meta := upnpav.Container{Object: obj, ChildCount: 1}
return meta
} else if filepath.Base(path) == "LD" {
parent := url.PathEscape(filepath.Dir(path))
- if settings.BTsets.EnableDebug {
- log.TLogln("getTorrentMeta parent for LD", parent)
- }
// LD object meta
obj := upnpav.Object{
ID: parent + "%2FLD",
@@ -197,17 +177,13 @@ func getTorrentMeta(path, host string) (ret interface{}) {
Searchable: 1,
Title: "Load Torrents",
Date: upnpav.Timestamp{Time: time.Now()},
- Class: "object.container",
}
- meta := upnpav.Container{Object: obj}
+ meta := upnpav.Container{Object: obj, ChildCount: 1}
return meta
} else {
file := filepath.Base(path)
id := url.PathEscape(path)
parent := url.PathEscape(filepath.Dir(path))
- if settings.BTsets.EnableDebug {
- log.TLogln("getTorrentMeta id:", id, "parent:", parent)
- }
// file object meta
obj := upnpav.Object{
ID: id,
@@ -216,12 +192,11 @@ func getTorrentMeta(path, host string) (ret interface{}) {
Searchable: 1,
Title: file,
Date: upnpav.Timestamp{Time: time.Now()},
- Class: "object.container",
}
- meta := upnpav.Container{Object: obj}
+ meta := upnpav.Container{Object: obj, ChildCount: 1}
return meta
}
- // for error response
+
return nil
}
@@ -277,7 +252,7 @@ func getLink(host, path string) string {
func getObjFromTorrent(path, parent, host string, torr *torr.Torrent, file *state.TorrentFileStat) (ret interface{}) {
- mime, err := MimeTypeByPath(file.Path)
+ mime, err := mt.MimeTypeByPath(file.Path)
if err != nil {
if settings.BTsets.EnableDebug {
log.TLogln("Can't detect mime type", err)
diff --git a/server/go.mod b/server/go.mod
index ed0bd58..bca1c92 100644
--- a/server/go.mod
+++ b/server/go.mod
@@ -2,8 +2,7 @@ module server
go 1.17
-replace github.com/anacrolix/dms v1.2.2 => github.com/tsynik/dms v0.0.0-20210913075730-e41ecd88369c
-
+replace github.com/anacrolix/dms v1.2.2 => github.com/tsynik/dms v0.0.0-20210911171915-d3d89ee99163
exclude (
github.com/willf/bitset v1.2.0
@@ -21,7 +20,6 @@ require (
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4
github.com/pkg/errors v0.9.1
go.etcd.io/bbolt v1.3.6
- golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac
)
@@ -92,6 +90,7 @@ require (
golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e // indirect
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
+ golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e // indirect
golang.org/x/text v0.3.6 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/protobuf v1.27.1 // indirect
diff --git a/server/go.sum b/server/go.sum
index 934c142..dec591a 100644
--- a/server/go.sum
+++ b/server/go.sum
@@ -156,6 +156,8 @@ github.com/anacrolix/torrent v1.25.1-0.20210224024805-693c30dd889e/go.mod h1:d4V
github.com/anacrolix/torrent v1.28.1-0.20210622065255-582f0ccd48a0/go.mod h1:15VRIA5/DwqbqETbKo3fzlC4aSbB0iMoo10ng3mzAbE=
github.com/anacrolix/torrent v1.29.0/go.mod h1:40Hf2bWxFqTbTWbrdig57JnmYLCjShbWWjdbB3VN5n4=
github.com/anacrolix/torrent v1.30.2/go.mod h1:vbNxKfaGiNq8edcCaQI1oSNJwh4GMqtMUMF9qOdZ6C0=
+github.com/anacrolix/torrent v1.31.1-0.20210912041407-4691b0b8d194 h1:U1h0guD86azvKs/sepNTrYUacoofSLxRQJwfd54IxgY=
+github.com/anacrolix/torrent v1.31.1-0.20210912041407-4691b0b8d194/go.mod h1:akZJHHFN8aWH2lcPZQ0I3etujnenwYpUvj36HV9uvAI=
github.com/anacrolix/upnp v0.1.1/go.mod h1:LXsbsp5h+WGN7YR+0A7iVXm5BL1LYryDev1zuJMWYQo=
github.com/anacrolix/upnp v0.1.2-0.20200416075019-5e9378ed1425 h1:/Wi6l2ONI1FUFWN4cBwHOO90V4ylp4ud/eov6GUcVFk=
github.com/anacrolix/upnp v0.1.2-0.20200416075019-5e9378ed1425/go.mod h1:Pz94W3kl8rf+wxH3IbCa9Sq+DTJr8OSbV2Q3/y51vYs=
@@ -720,8 +722,8 @@ github.com/tinylib/msgp v1.1.1/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDW
github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
github.com/tinylib/msgp v1.1.5/go.mod h1:eQsjooMTnV42mHu917E26IogZ2930nFyBQdofk10Udg=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
-github.com/tsynik/dms v0.0.0-20210913075730-e41ecd88369c h1:4yU1p5MmRu+233Hs2OhR8Kx9gOWw20KR2AY1py5pLvA=
-github.com/tsynik/dms v0.0.0-20210913075730-e41ecd88369c/go.mod h1:oWW4QbQ9YGl+FJ1X8xcrUYVObfA/KdipoeBuTC4ltG8=
+github.com/tsynik/dms v0.0.0-20210911171915-d3d89ee99163 h1:qBZPOad8wOmvFe6rIx1d0U7VpymFalvbM5kjHeEx8Gs=
+github.com/tsynik/dms v0.0.0-20210911171915-d3d89ee99163/go.mod h1:oWW4QbQ9YGl+FJ1X8xcrUYVObfA/KdipoeBuTC4ltG8=
github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31/go.mod h1:onvgF043R+lC5RZ8IT9rBXDaEDnpnw/Cl+HFiw+v/7Q=
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
diff --git a/server/dlna/mimetype.go b/server/mimetype/mimetype.go
similarity index 99%
rename from server/dlna/mimetype.go
rename to server/mimetype/mimetype.go
index c6f8f1b..ebdf3f8 100644
--- a/server/dlna/mimetype.go
+++ b/server/mimetype/mimetype.go
@@ -1,4 +1,4 @@
-package dlna
+package mimetype
import (
"log"
diff --git a/server/torr/stream.go b/server/torr/stream.go
index da3ca3a..1bfebb3 100644
--- a/server/torr/stream.go
+++ b/server/torr/stream.go
@@ -12,6 +12,7 @@ import (
"github.com/anacrolix/missinggo/httptoo"
"github.com/anacrolix/torrent"
+ mt "server/mimetype"
sets "server/settings"
"server/torr/state"
)
@@ -61,8 +62,12 @@ func (t *Torrent) Stream(fileID int, req *http.Request, resp http.ResponseWriter
resp.Header().Set("Connection", "close")
resp.Header().Set("ETag", httptoo.EncodeQuotedString(fmt.Sprintf("%s/%s", t.Hash().HexString(), file.Path())))
+ // 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,
diff --git a/server/utils/net_interface_filter.go b/server/utils/net_interface_filter.go
deleted file mode 100644
index 23bdb7b..0000000
--- a/server/utils/net_interface_filter.go
+++ /dev/null
@@ -1,38 +0,0 @@
-package utils
-
-import (
- "strings"
-)
-
-type PhysicalInterface struct {
- MACAddress string
- Name string
- FriendlyName string
-}
-
-// Mac Address parts to look for, and identify non physical devices. There may be more, update me!
-var macAddrPartsToFilter []string = []string{
- "00:03:FF", // Microsoft Hyper-V, Virtual Server, Virtual PC
- "0A:00:27", // VirtualBox
- "00:00:00:00:00", // Teredo Tunneling Pseudo-Interface
- "00:50:56", // VMware ESX 3, Server, Workstation, Player
- "00:1C:14", // VMware ESX 3, Server, Workstation, Player
- "00:0C:29", // VMware ESX 3, Server, Workstation, Player
- "00:05:69", // VMware ESX 3, Server, Workstation, Player
- "00:1C:42", // Microsoft Hyper-V, Virtual Server, Virtual PC
- "00:0F:4B", // Virtual Iron 4
- "00:16:3E", // Red Hat Xen, Oracle VM, XenSource, Novell Xen
- "08:00:27", // Sun xVM VirtualBox
- "7A:79", // Hamachi
-}
-
-// Filters the possible physical interface address by comparing it to known popular VM Software adresses
-// and Teredo Tunneling Pseudo-Interface.
-func IsPhysicalInterface(addr string) bool {
- for _, macPart := range macAddrPartsToFilter {
- if strings.HasPrefix(strings.ToLower(addr), strings.ToLower(macPart)) {
- return false
- }
- }
- return true
-}
diff --git a/server/utils/net_interface_filter_nix_darwin.go b/server/utils/net_interface_filter_nix_darwin.go
deleted file mode 100644
index ecebcef..0000000
--- a/server/utils/net_interface_filter_nix_darwin.go
+++ /dev/null
@@ -1,29 +0,0 @@
-//go:build linux || darwin
-// +build linux darwin
-
-package utils
-
-import (
- "fmt"
- "net"
-)
-
-// Gets all physical interfaces based on filter results, ignoring all VM, Loopback and Tunnel interfaces.
-func GetAllPhysicalInterfaces() []PhysicalInterface {
- ifaces, err := net.Interfaces()
-
- if err != nil {
- fmt.Println(err)
- return nil
- }
-
- var outInterfaces []PhysicalInterface
-
- for _, element := range ifaces {
- if element.Flags&net.FlagLoopback == 0 && element.Flags&net.FlagUp == 1 && IsPhysicalInterface(element.HardwareAddr.String()) {
- outInterfaces = append(outInterfaces, PhysicalInterface{MACAddress: element.HardwareAddr.String(), Name: element.Name, FriendlyName: element.Name})
- }
- }
-
- return outInterfaces
-}
diff --git a/server/utils/net_interface_filter_win.go b/server/utils/net_interface_filter_win.go
deleted file mode 100644
index 0620d59..0000000
--- a/server/utils/net_interface_filter_win.go
+++ /dev/null
@@ -1,105 +0,0 @@
-//go:build windows
-// +build windows
-
-package utils
-
-import (
- "os"
- "syscall"
- "unicode/utf16"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-const (
- IfOperStatusUp = 1
- IF_TYPE_SOFTWARE_LOOPBACK = 24
- IF_TYPE_TUNNEL = 131
-)
-
-const hexDigit = "0123456789abcdef"
-
-func adapterAddresses() ([]*windows.IpAdapterAddresses, error) {
- var b []byte
- l := uint32(15000) // recommended initial size
- for {
- b = make([]byte, l)
- err := windows.GetAdaptersAddresses(syscall.AF_UNSPEC, windows.GAA_FLAG_INCLUDE_PREFIX, 0, (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])), &l)
- if err == nil {
- if l == 0 {
- return nil, nil
- }
- break
- }
- if err.(syscall.Errno) != syscall.ERROR_BUFFER_OVERFLOW {
- return nil, os.NewSyscallError("getadaptersaddresses", err)
- }
- if l <= uint32(len(b)) {
- return nil, os.NewSyscallError("getadaptersaddresses", err)
- }
- }
- var aas []*windows.IpAdapterAddresses
- for aa := (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])); aa != nil; aa = aa.Next {
- aas = append(aas, aa)
- }
- return aas, nil
-}
-
-func bytePtrToString(p *uint8) string {
- a := (*[10000]uint8)(unsafe.Pointer(p))
- i := 0
- for a[i] != 0 {
- i++
- }
- return string(a[:i])
-}
-
-func physicalAddrToString(physAddr [8]byte) string {
- if len(physAddr) == 0 {
- return ""
- }
- buf := make([]byte, 0, len(physAddr)*3-1)
- for i, b := range physAddr {
- if i > 0 {
- buf = append(buf, ':')
- }
- buf = append(buf, hexDigit[b>>4])
- buf = append(buf, hexDigit[b&0xF])
- }
- return string(buf)
-}
-
-func cStringToString(cs *uint16) (s string) {
- if cs != nil {
- us := make([]uint16, 0, 256)
- for p := uintptr(unsafe.Pointer(cs)); ; p += 2 {
- u := *(*uint16)(unsafe.Pointer(p))
- if u == 0 {
- return string(utf16.Decode(us))
- }
- us = append(us, u)
- }
- }
- return ""
-}
-
-// Gets all physical interfaces based on filter results, ignoring all VM, Loopback and Tunnel interfaces.
-func GetAllPhysicalInterfaces() []PhysicalInterface {
- aa, _ := adapterAddresses()
-
- var outInterfaces []PhysicalInterface
-
- for _, pa := range aa {
- mac := physicalAddrToString(pa.PhysicalAddress)
- name := "\\Device\\NPF_" + bytePtrToString(pa.AdapterName)
-
- if pa.IfType != uint32(IF_TYPE_SOFTWARE_LOOPBACK) && pa.IfType != uint32(IF_TYPE_TUNNEL) &&
- pa.OperStatus == uint32(IfOperStatusUp) && IsPhysicalInterface(mac) {
-
- outInterfaces = append(outInterfaces, PhysicalInterface{MACAddress: mac, Name: name, FriendlyName: cStringToString(pa.FriendlyName)})
- }
- }
-
- return outInterfaces
-}