mirror of
https://github.com/rclone/rclone.git
synced 2024-11-22 15:30:06 +08:00
dlna: fake out implementation of X_MS_MediaReceiverRegistrar
Using the same responses as minidlna. Fixes #3502.
This commit is contained in:
parent
2f10472df3
commit
5f07bbf8ce
|
@ -116,6 +116,9 @@ func newServer(f fs.Fs, opt *dlnaflags.Options) *server {
|
|||
"ConnectionManager": &connectionManagerService{
|
||||
server: s,
|
||||
},
|
||||
"X_MS_MediaReceiverRegistrar": &mediaReceiverRegistrarService{
|
||||
server: s,
|
||||
},
|
||||
}
|
||||
|
||||
// Setup the various http routes.
|
||||
|
@ -248,7 +251,7 @@ func (s *server) rootDescHandler(w http.ResponseWriter, r *http.Request) {
|
|||
// Handle a service control HTTP request.
|
||||
func (s *server) serviceControlHandler(w http.ResponseWriter, r *http.Request) {
|
||||
soapActionString := r.Header.Get("SOAPACTION")
|
||||
soapAction, err := upnp.ParseActionHTTPHeader(soapActionString)
|
||||
soapAction, err := parseActionHTTPHeader(soapActionString)
|
||||
if err != nil {
|
||||
serveError(s, w, "Could not parse SOAPACTION header", err)
|
||||
return
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package dlna
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"html"
|
||||
|
@ -11,6 +12,8 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/anacrolix/dms/soap"
|
||||
|
||||
"github.com/rclone/rclone/vfs"
|
||||
|
||||
_ "github.com/rclone/rclone/backend/local"
|
||||
|
@ -125,3 +128,21 @@ func TestContentDirectoryBrowseMetadata(t *testing.T) {
|
|||
// with a non-zero childCount
|
||||
require.Contains(t, string(body), html.EscapeString(`childCount="1"`))
|
||||
}
|
||||
|
||||
// Check that the X_MS_MediaReceiverRegistrar is faked out properly.
|
||||
func TestMediaReceiverRegistrarService(t *testing.T) {
|
||||
env := soap.Envelope{
|
||||
Body: soap.Body{
|
||||
Action: []byte("RegisterDevice"),
|
||||
},
|
||||
}
|
||||
req, err := http.NewRequest("POST", testURL+"ctl", bytes.NewReader(mustMarshalXML(env)))
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("SOAPACTION", `"urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1#RegisterDevice"`)
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
require.Contains(t, string(body), "<RegistrationRespMsg>")
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package dlna
|
|||
import (
|
||||
"crypto/md5"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
|
@ -11,6 +12,9 @@ import (
|
|||
"net/http/httptest"
|
||||
"net/http/httputil"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/anacrolix/dms/soap"
|
||||
"github.com/anacrolix/dms/upnp"
|
||||
|
@ -85,6 +89,36 @@ func marshalSOAPResponse(sa upnp.SoapAction, args map[string]string) []byte {
|
|||
sa.Action, sa.ServiceURN.String(), mustMarshalXML(soapArgs)))
|
||||
}
|
||||
|
||||
var serviceURNRegexp = regexp.MustCompile(`:service:(\w+):(\d+)$`)
|
||||
|
||||
func parseServiceType(s string) (ret upnp.ServiceURN, err error) {
|
||||
matches := serviceURNRegexp.FindStringSubmatch(s)
|
||||
if matches == nil {
|
||||
err = errors.New(s)
|
||||
return
|
||||
}
|
||||
if len(matches) != 3 {
|
||||
log.Panicf("Invalid serviceURNRegexp ?")
|
||||
}
|
||||
ret.Type = matches[1]
|
||||
ret.Version, err = strconv.ParseUint(matches[2], 0, 0)
|
||||
return
|
||||
}
|
||||
|
||||
func parseActionHTTPHeader(s string) (ret upnp.SoapAction, err error) {
|
||||
if s[0] != '"' || s[len(s)-1] != '"' {
|
||||
return
|
||||
}
|
||||
s = s[1 : len(s)-1]
|
||||
hashIndex := strings.LastIndex(s, "#")
|
||||
if hashIndex == -1 {
|
||||
return
|
||||
}
|
||||
ret.Action = s[hashIndex+1:]
|
||||
ret.ServiceURN, err = parseServiceType(s[:hashIndex])
|
||||
return
|
||||
}
|
||||
|
||||
type loggingResponseWriter struct {
|
||||
http.ResponseWriter
|
||||
request *http.Request
|
||||
|
|
27
cmd/serve/dlna/mrrs.go
Normal file
27
cmd/serve/dlna/mrrs.go
Normal file
|
@ -0,0 +1,27 @@
|
|||
package dlna
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/anacrolix/dms/upnp"
|
||||
)
|
||||
|
||||
type mediaReceiverRegistrarService struct {
|
||||
*server
|
||||
upnp.Eventing
|
||||
}
|
||||
|
||||
func (mrrs *mediaReceiverRegistrarService) Handle(action string, argsXML []byte, r *http.Request) (map[string]string, error) {
|
||||
switch action {
|
||||
case "IsAuthorized", "IsValidated":
|
||||
return map[string]string{
|
||||
"Result": "1",
|
||||
}, nil
|
||||
case "RegisterDevice":
|
||||
return map[string]string{
|
||||
"RegistrationRespMsg": mrrs.RootDeviceUUID,
|
||||
}, nil
|
||||
default:
|
||||
return nil, upnp.InvalidActionError
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user