mirror of
https://github.com/Ernous/TorrServerJellyfin.git
synced 2025-12-19 21:46:11 +05:00
Merge branch 'master' into new-torrent
This commit is contained in:
12
gen_web.go
12
gen_web.go
@@ -90,11 +90,11 @@ func RouteWebPages(route *gin.RouterGroup) {
|
|||||||
mime.AddExtensionType(".map", "application/json")
|
mime.AddExtensionType(".map", "application/json")
|
||||||
mime.AddExtensionType(".webmanifest", "application/manifest+json")
|
mime.AddExtensionType(".webmanifest", "application/manifest+json")
|
||||||
// sort fmap
|
// sort fmap
|
||||||
keys := make([]string, 0, len(fmap))
|
keys := make([]string, 0, len(fmap))
|
||||||
for key := range fmap {
|
for key := range fmap {
|
||||||
keys = append(keys, key)
|
keys = append(keys, key)
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
for _, link := range keys {
|
for _, link := range keys {
|
||||||
fmime := mime.TypeByExtension(filepath.Ext(link))
|
fmime := mime.TypeByExtension(filepath.Ext(link))
|
||||||
embedStr += `
|
embedStr += `
|
||||||
@@ -103,7 +103,7 @@ func RouteWebPages(route *gin.RouterGroup) {
|
|||||||
})
|
})
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
embedStr += "}"
|
embedStr += "}\n"
|
||||||
|
|
||||||
ff.WriteString(embedStr)
|
ff.WriteString(embedStr)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/anacrolix/dms/dlna/dms"
|
"github.com/anacrolix/dms/dlna/dms"
|
||||||
"github.com/anacrolix/dms/upnpav"
|
|
||||||
|
|
||||||
"server/log"
|
"server/log"
|
||||||
|
"server/utils"
|
||||||
"server/web/pages/template"
|
"server/web/pages/template"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -22,11 +22,16 @@ func Start() {
|
|||||||
dmsServer = &dms.Server{
|
dmsServer = &dms.Server{
|
||||||
Interfaces: func() (ifs []net.Interface) {
|
Interfaces: func() (ifs []net.Interface) {
|
||||||
var err error
|
var err error
|
||||||
ifs, err = net.Interfaces()
|
ifaces, err := net.Interfaces()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.TLogln(err)
|
log.TLogln(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
for _, element := range ifaces {
|
||||||
|
if element.Flags&net.FlagLoopback == 0 && element.Flags&net.FlagUp == net.FlagUp && element.Flags&net.FlagMulticast == net.FlagMulticast && utils.IsPhysicalInterface(element.HardwareAddr.String()) {
|
||||||
|
ifs = append(ifs, element)
|
||||||
|
}
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}(),
|
}(),
|
||||||
HTTPConn: func() net.Listener {
|
HTTPConn: func() net.Listener {
|
||||||
@@ -120,22 +125,10 @@ func onBrowse(path, rootObjectPath, host, userAgent string) (ret []interface{},
|
|||||||
}
|
}
|
||||||
|
|
||||||
func onBrowseMeta(path string, rootObjectPath string, host, userAgent string) (ret interface{}, err error) {
|
func onBrowseMeta(path string, rootObjectPath string, host, userAgent string) (ret interface{}, err error) {
|
||||||
if path == "/" {
|
ret = getTorrentMeta(path, host)
|
||||||
// Root Object Meta
|
if ret == nil {
|
||||||
rootObj := upnpav.Object{
|
err = fmt.Errorf("meta not found")
|
||||||
ID: "0",
|
|
||||||
ParentID: "-1",
|
|
||||||
Restricted: 1,
|
|
||||||
Searchable: 1,
|
|
||||||
Title: "TorrServer",
|
|
||||||
Date: upnpav.Timestamp{Time: time.Now()},
|
|
||||||
Class: "object.container.storageFolder",
|
|
||||||
}
|
|
||||||
// add Root Object
|
|
||||||
ret = upnpav.Container{Object: rootObj, ChildCount: 1}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
err = fmt.Errorf("not implemented")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,7 +165,7 @@ func getDefaultFriendlyName() string {
|
|||||||
var list []string
|
var list []string
|
||||||
for _, i := range ifaces {
|
for _, i := range ifaces {
|
||||||
addrs, _ := i.Addrs()
|
addrs, _ := i.Addrs()
|
||||||
if i.Flags&net.FlagUp == net.FlagUp {
|
if i.Flags&net.FlagLoopback == 0 && i.Flags&net.FlagUp == net.FlagUp && i.Flags&net.FlagMulticast == net.FlagMulticast && utils.IsPhysicalInterface(i.HardwareAddr.String()) {
|
||||||
for _, addr := range addrs {
|
for _, addr := range addrs {
|
||||||
var ip net.IP
|
var ip net.IP
|
||||||
switch v := addr.(type) {
|
switch v := addr.(type) {
|
||||||
|
|||||||
@@ -113,6 +113,104 @@ func getTorrent(path, host string) (ret []interface{}) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getTorrentMeta(path, host string) (ret interface{}) {
|
||||||
|
|
||||||
|
if path == "/" {
|
||||||
|
rootObj := upnpav.Object{
|
||||||
|
ID: "0",
|
||||||
|
ParentID: "-1",
|
||||||
|
Restricted: 1,
|
||||||
|
Searchable: 1,
|
||||||
|
Title: "TorrServer",
|
||||||
|
Date: upnpav.Timestamp{Time: time.Now()},
|
||||||
|
Class: "object.container",
|
||||||
|
}
|
||||||
|
// 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
|
||||||
|
for _, t := range torrs {
|
||||||
|
if strings.Contains(path, t.TorrentSpec.InfoHash.HexString()) {
|
||||||
|
torr = t
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if torr == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Meta object
|
||||||
|
if isHashPath(path) {
|
||||||
|
// hash object meta
|
||||||
|
obj := upnpav.Object{
|
||||||
|
ID: "%2F" + torr.TorrentSpec.InfoHash.HexString(),
|
||||||
|
ParentID: "%2FTR",
|
||||||
|
Restricted: 1,
|
||||||
|
Title: torr.Title,
|
||||||
|
Date: upnpav.Timestamp{Time: time.Now()},
|
||||||
|
Class: "object.container",
|
||||||
|
}
|
||||||
|
meta := upnpav.Container{Object: obj}
|
||||||
|
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",
|
||||||
|
ParentID: parent,
|
||||||
|
Restricted: 1,
|
||||||
|
Searchable: 1,
|
||||||
|
Title: "Load Torrents",
|
||||||
|
Date: upnpav.Timestamp{Time: time.Now()},
|
||||||
|
Class: "object.container",
|
||||||
|
}
|
||||||
|
meta := upnpav.Container{Object: obj}
|
||||||
|
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,
|
||||||
|
ParentID: parent,
|
||||||
|
Restricted: 1,
|
||||||
|
Searchable: 1,
|
||||||
|
Title: file,
|
||||||
|
Date: upnpav.Timestamp{Time: time.Now()},
|
||||||
|
Class: "object.container",
|
||||||
|
}
|
||||||
|
meta := upnpav.Container{Object: obj}
|
||||||
|
return meta
|
||||||
|
}
|
||||||
|
// for error response
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func loadTorrent(path, host string) (ret []interface{}) {
|
func loadTorrent(path, host string) (ret []interface{}) {
|
||||||
hash := filepath.Base(filepath.Dir(path))
|
hash := filepath.Base(filepath.Dir(path))
|
||||||
if hash == "/" {
|
if hash == "/" {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ module server
|
|||||||
|
|
||||||
go 1.17
|
go 1.17
|
||||||
|
|
||||||
replace github.com/anacrolix/dms v1.2.2 => github.com/tsynik/dms v0.0.0-20210909053938-38af4173d4ac
|
replace github.com/anacrolix/dms v1.2.2 => github.com/tsynik/dms v0.0.0-20210911200354-fd999256e04d
|
||||||
|
|
||||||
exclude (
|
exclude (
|
||||||
github.com/willf/bitset v1.2.0
|
github.com/willf/bitset v1.2.0
|
||||||
|
|||||||
@@ -719,8 +719,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.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||||
github.com/tinylib/msgp v1.1.5/go.mod h1:eQsjooMTnV42mHu917E26IogZ2930nFyBQdofk10Udg=
|
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/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
github.com/tsynik/dms v0.0.0-20210909053938-38af4173d4ac h1:1JLBJz2aGJhQ6ZR+zJWl68/0DLJkr+E3E74HEzOFOjw=
|
github.com/tsynik/dms v0.0.0-20210911200354-fd999256e04d h1:YFNG0P4SKHxOvHM3Ae+FI1/kRnhi/qyvblHOKzDgRPE=
|
||||||
github.com/tsynik/dms v0.0.0-20210909053938-38af4173d4ac/go.mod h1:oWW4QbQ9YGl+FJ1X8xcrUYVObfA/KdipoeBuTC4ltG8=
|
github.com/tsynik/dms v0.0.0-20210911200354-fd999256e04d/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/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/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
|
||||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||||
|
|||||||
38
server/utils/net_interface_filter.go
Normal file
38
server/utils/net_interface_filter.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
29
server/utils/net_interface_filter_nix_darwin.go
Normal file
29
server/utils/net_interface_filter_nix_darwin.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
//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
|
||||||
|
}
|
||||||
105
server/utils/net_interface_filter_win.go
Normal file
105
server/utils/net_interface_filter_win.go
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
//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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user