The issue I have is that my Sony LCD TV seems to be very picky regarding the UPnP/DLNA protocol when playing media from a control point to the television. The Android App BubbleUPnP does a good job here as playing music works out of the box. Initial tests with the Cling Java library to play music does not work out of the box. Therefore I wanted to debug the HTTP SOAP protocol in order to see where the differences are.
The UPnP inspector tools discover all UPnP devices on the network, but they cannot monitor the traffic between the devices as the communication is happening directly (service discovery is via multicast):
Because of a switched network the traffic does not go through my OpenWRT router either, so sniffing on the WLAN-LAN bridge br-lan does not work either. That means the only chance to get a hook into the communication channel was to use arpspoof, part of the dsniff networking tool-chain, together with tcpdump and wireshark for sniffing and visualization.
“ARP spoofing[1] is a computer hacking technique whereby an attacker sends fake (“spoofed”) Address Resolution Protocol (ARP) messages onto a Local Area Network. Generally, the aim is to associate the attacker’s MAC address with the IP address of another host (such as the default gateway), causing any traffic meant for that IP address to be sent to the attacker instead.” (See http://en.wikipedia.org/wiki/ARP_spoofing)
On my Ubuntu desktop the following packages need to be installed to get started:
sudo apt-get install dsniff wireshark tcpdump
Three devices are part of the show:
- Android Phone - 192.168.0.107
- Sony LCD TV - 192.168.0.77
- Desktop PC - 192.168.0.17
Before spoofing can be set up we need to make sure that IP packages are forwarded on the desktop machine:
sudo “echo 1 > /proc/sys/net/ipv4/ip_forward”
We need to tell the Android Phone that we are the Sony LCD TV:
sudo arpspoof -i eth0 -t 192.168.0.107 192.168.0.77
and the Sony LCD TV that we are the Android Phone:
sudo arpspoof -i eth0 -t 192.168.0.77 192.168.0.107
Then the sniffing can be started with the following command
sudo "tcpdump not arp -s0 -w - | wireshark -k -i -"
In Wireshark you can simply search for the String “AVTransportURI”
(Edit / Find packet… / Find By: String “AVTransportURI” / Search In: Packet Bytes) to find the
HTTP request that informs the LCD TV which song to play.
Right click on the selected line and choose “Decode as…” from the context menu. Then swith to the
“Transport” tab and select “HTTP” from the list. Finally click on “OK” to decode the packet as HTTP.
POST /upnp/control/AVTransport HTTP/1.1
Content-type: text/xml;charset="utf-8"
Soapaction: "urn:schemas-upnp-org:service:AVTransport:1#SetAVTransportURI"
Content-Length: 1493
Host: 192.168.0.77:52323
Connection: Keep-Alive
User-Agent: Android/4.1.1 UPnP/1.0 BubbleUPnP/1.5.4
<?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.107:57645/external/audio/media/10839.mp3</CurrentURI>
<CurrentURIMetaData>
<DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dlna="urn:schemas-dlna-org:metadata-1-0/">
<item id="/external/audio/albums/6/10839" parentID="/external/audio/albums/6" restricted="1">
<upnp:class>object.item.audioItem.musicTrack</upnp:class>
<dc:title>Blind Willie</dc:title>
<dc:creator>Rob Towns</dc:creator>
<upnp:artist>Rob Towns</upnp:artist>
<upnp:albumArtURI>http://192.168.0.107:57645/external/audio/albums/6.jpg</upnp:albumArtURI>
<upnp:album>media</upnp:album><dc:date>2001-01-01</dc:date>
<res protocolInfo="http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_CI=0" size="2703360" duration="0:02:15.000">http://192.168.0.107:57645/external/audio/media/10839.mp3</res></item>
</DIDL-Lite>
</CurrentURIMetaData>
</u:SetAVTransportURI>
</s:Body>
</s:Envelope>
With this method it will be easily possible to tweak a Cling Java client to speak to the Sony LCD TV.
