com.webstersmalley.tv.sky.MulticastSkyResolverService Maven / Gradle / Ivy
/*
* Copyright 2013 Webster Smalley
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.webstersmalley.tv.sky;
import com.webstersmalley.tv.comms.CachingComms;
import com.webstersmalley.tv.comms.Comms;
import com.webstersmalley.tv.comms.HttpComms;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.annotation.Resource;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.MulticastSocket;
import java.net.URL;
/**
* Created by: Matthew Smalley
* Date: 27/04/13
*/
public class MulticastSkyResolverService implements SkyResolverService {
/* Example multicast response
NOTIFY * HTTP/1.1
HOST: 239.255.255.250:1900
CACHE-CONTROL: max-age=115
LOCATION: http://192.168.1.67:49153/description4.xml
OPT: "http://schemas.upnp.org/upnp/1/0/"; ns=01
01-NLS: effe5fb0-1dd1-11b2-a3c7-e4eb5cb8119e
NT: urn:schemas-nds-com:device:SkyServe:2
NTS: ssdp:alive
SERVER: Linux/2.6.18.8 UPnP/1.0 SKY DLNADOC/1.50
X-User-Agent: redsonic
USN: uuid:444D5376-3247-536B-7953-0019fb7ee677::urn:schemas-nds-com:device:SkyServe:2
*/
private final static String LOCATION_STRING = "LOCATION: ";
private final static String USN_STRING = "USN: uuid:";
private Logger logger = LoggerFactory.getLogger(getClass());
private int maxReceiveLoop = 500;
private String userAgent;
private String serviceName;
public void setUserAgent(String userAgent) {
this.userAgent = userAgent;
}
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
@Resource(name = "comms")
private Comms comms;
private URL skyUrl;
@Override
public URL getSkyURL() {
if (skyUrl == null) {
skyUrl = getSkyURLImpl();
}
return skyUrl;
}
private URL getSkyURLImpl() {
try {
logger.info("Joining multicast group");
MulticastSocket socket = new MulticastSocket(1900);
InetAddress address = InetAddress.getByName("239.255.255.250");
socket.joinGroup(address);
String requestString = "M-SEARCH * HTTP/1.1\r\n" +
"HOST: 239.255.255.250:1900\r\n" +
"MAN: \"ssdp:discover\"\r\n" +
"MX: 10\r\n" +
"ST: ssdp:all\r\n" +
"USER-AGENT: " + userAgent + "\r\n";
byte[] requestBytes = requestString.getBytes();
DatagramPacket requestPacket = new DatagramPacket(requestBytes, requestBytes.length, address, 1900);
socket.send(requestPacket);
DatagramPacket packet;
String hostname = null;
for (int i = 0; i < maxReceiveLoop; i++) {
byte[] buf = new byte[512];
packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
String received = new String(packet.getData(), 0, packet.getLength());
if (received.contains(serviceName)) {
logger.debug("Found service");
logger.debug(received);
hostname = received.substring(received.indexOf(LOCATION_STRING) + LOCATION_STRING.length());
hostname = hostname.substring(0, hostname.indexOf("/description")).trim();
logger.debug("Hostname: {}", hostname);
String usnString = received.substring(received.indexOf(USN_STRING) + USN_STRING.length());
usnString = usnString.substring(0, usnString.indexOf("::urn"));
logger.debug("NLS String: {}", usnString);
return new URL(hostname + "/" + usnString + "SkyBrowse");
}
}
return null;
} catch (Exception e) {
logger.error("Error resolving Sky service", e);
throw new RuntimeException("Error resolving Sky service", e);
}
}
private URL getURL(String hostname) {
try {
URL url = new URL(hostname);
StringBuffer sb = new StringBuffer();
sb.append("GET " + url.toString() + "/description3.xml HTTP/1.1\r\n" +
"Host: " + url.getHost() + ":" + url.getPort() + "\r\n" +
"Connection: keep-alive\r\n" +
"Accept: */*\r\n" +
"Accept-Encoding: gzip, deflate\r\n" +
"Accept-Language: en-us\r\n" +
"Pragma: no-cache\r\n" +
"User-Agent: SKY_skyplus\r\n\r\n");
String response = comms.getResourceByRawHttp(url, sb.toString());
response = response.substring(response.indexOf("