V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
工单节点使用指南
• 请用平和的语言准确描述你所遇到的问题
• 厂商的技术支持和你一样也是有喜怒哀乐的普通人类,尊重是相互的
• 如果是关于 V2EX 本身的问题反馈,请使用 反馈 节点
ihipop
V2EX  ›  全球工单系统

YAMBY 的 DLNA 请求对 URL 的编码有些问题

  •  
  •   ihipop · 34 天前 · 489 次点击
    这是一个创建于 34 天前的主题,其中的信息可能已经有所发展或是发生改变。

    不知道怎么联系作者就发这里吧. @Kivy

    最近有机会接触三星的 Tizen TV 系统,发现 Yamby 的 DLNA 投屏功能对三星设备上某些功能不可用(无法播放),但是可以在 KODI 上正常使用,经过各种抓包测试,并且查阅了一些 DLNA 的上古文档,发现问题出在媒体文件的 metadata 上

    YAMBY 的 DLNA 报文是这样的

    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
      <s:Body>
        <u:SetAVTransportURI xmlns:u="urn:schemas-upnp-org:service:AVTransport:1">
          <InstanceID>0</InstanceID>
          <CurrentURI>http://192.168.0.214:9091/original.mp4?x=y&amp;z=z</CurrentURI>
          <CurrentURIMetaData>&lt;?xml version="1.0"?>&lt;DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/">&lt;item id="original.mp4" parentID="-1" restricted="1">&lt;dc:title>original.mp4&lt;/dc:title>&lt;upnp:class>object.item.videoItem&lt;/upnp:class>&lt;res protocolInfo="http-get:*:video/mp4:*;DLNA.ORG_OP=01;">http://192.168.0.214:9091/original.mp4?x=y&amp;z=z&lt;/res>&lt;/item>&lt;/DIDL-Lite></CurrentURIMetaData>
        </u:SetAVTransportURI>
      </s:Body>
    </s:Envelope>
    

    对于现代的 DLNA 设备来说 重点需要关注 CurrentURIMetaData

    把他解码 是这样的内容

    <?xml version="1.0"?>
    <DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/">
      <item id="original.mp4" parentID="-1" restricted="1">
        <dc:title>original.mp4</dc:title>
        <upnp:class>object.item.videoItem</upnp:class>
        <res protocolInfo="http-get:*:video/mp4:*;DLNA.ORG_OP=01;">http://192.168.0.214:9091/original.mp4?x=y&z=z</res>
      </item>
    </DIDL-Lite>
    

    然后就会得到三丧电视答复如下内容

    <?xml version="1.0" encoding="utf-8"?>
    <s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
      <s:Body>
        <s:Fault>
          <faultcode>s:Client</faultcode>
          <faultstring>UPnPError</faultstring>
          <detail>
            <UPnPError xmlns="urn:schemas-upnp-org:control-1-0">
              <errorCode>402</errorCode>
              <errorDescription>Invalid Args</errorDescription>
            </UPnPError>
          </detail>
        </s:Fault>
      </s:Body>
    </s:Envelope>
    

    其根本原因是因为, 在 XML 节点内的 URL 是需要进行 html 实体转义的, 也就是

    CurrentURIMetaData 本身就是一个 html 实体转义后的 XML

    其内的 URL 也必须是经过 html 实体转义的, 因为 XML 对某些字符(如 <, >, &, " 等)有严格的限制, 我们使用 YAMBY 主要的场景就是 EMBY 的 stream 拉流播放, 这个接口会通过 Query String 里面传递很多查询参数, 使用了大量的 &, 如果不进行实体转义, 就会对设备的解析造成问题

    所以其实是 URL 转义以后的写入 DIDL-Lite ,然后 DIDL-Lite 再转义一次变成上面的样子, 其实就是 URL 被转义了两次.

    所以如果一开始报文改成这样, 三星设备就会正确响应

    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
      <s:Body>
        <u:SetAVTransportURI xmlns:u="urn:schemas-upnp-org:service:AVTransport:1">
          <InstanceID>0</InstanceID>
          <CurrentURI>http://192.168.0.214:9091/original.mp4?x=y&amp;z=z</CurrentURI>
          <CurrentURIMetaData>&lt;?xml version="1.0"?>&lt;DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/">&lt;item id="original.mp4" parentID="-1" restricted="1">&lt;dc:title>original.mp4&lt;/dc:title>&lt;upnp:class>object.item.videoItem&lt;/upnp:class>&lt;res protocolInfo="http-get:*:video/mp4:*;DLNA.ORG_OP=01;">http://192.168.0.214:9091/original.mkv?x=y&amp;amp;z=z&lt;/res>&lt;/item>&lt;/DIDL-Lite></CurrentURIMetaData>
        </u:SetAVTransportURI>
      </s:Body>
    </s:Envelope>
    

    另外这版的 Tizen 还有一个问题, 就是如果是 https 的 URL 不可以带端口号, 也就是, 报文里面写 https://example.com:443/example.mp4 是不可以的, 服务器会收到消息和完整的请求, 但是电视会显示错误信息, 并且拒绝播放.

    很不幸, YAMBY 就是会带上端口号,哪怕是默认的(比如 https 的 默认端口是 443), 导致无法投屏

    目前尚无回复
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   839 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 20:49 · PVG 04:49 · LAX 13:49 · JFK 16:49
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.