Files
i2p.itoopie/router/java/src/org/cybergarage/upnp/Device.java

1810 lines
45 KiB
Java
Raw Normal View History

2009-02-19 21:42:59 +00:00
/******************************************************************
*
* CyberLink for Java
*
* Copyright (C) Satoshi Konno 2002-2004
*
* File: Device.java
*
* Revision:
*
* 11/28/02
* - first revision.
* 02/26/03
* - URLBase is updated automatically.
* - Description of a root device is returned from the XML node tree.
* 05/13/03
* - URLBase is updated when the request is received.
* - Changed to create socket threads each local interfaces.
* (HTTP, SSDPSearch)
* 06/17/03
* - Added notify all state variables when a new subscription is received.
* 06/18/03
* - Fixed a announce bug when the bind address is null on J2SE v 1.4.1_02 and Redhat 9.
* 09/02/03
* - Giordano Sassaroli <sassarol@cefriel.it>
* - Problem : bad request response sent even with successful subscriptions
* - Error : a return statement is missing in the httpRequestRecieved method
* 10/21/03
* - Updated a udn field by a original uuid.
* 10/22/03
* - Added setActionListener().
* - Added setQueryListener().
* 12/12/03
* - Added a static() to initialize UPnP class.
* 12/25/03
* - Added advertiser functions.
* 01/05/04
* - Added isExpired().
* 03/23/04
* - Oliver Newell <newell@media-rush.com>
* - Changed to update the UDN only when the field is null.
* 04/21/04
* - Added isDeviceType().
* 06/18/04
* - Added setNMPRMode() and isNMPRMode().
* - Changed getDescriptionData() to update only when the NMPR mode is false.
* 06/21/04
* - Changed start() to send a bye-bye before the announce.
* - Changed annouce(), byebye() and deviceSearchReceived() to send the SSDP
* messsage four times when the NMPR and the Wireless mode are true.
* 07/02/04
* - Fixed announce() and byebye() to send the upnp::rootdevice message despite embedded devices.
* - Fixed getRootNode() to return the root node when the device is embedded.
* 07/24/04
* - Thanks for Stefano Lenzi <kismet-sl@users.sourceforge.net>
* - Added getParentDevice().
* 10/20/04
* - Brent Hills <bhills@openshores.com>
* - Changed postSearchResponse() to add MYNAME header.
* 11/19/04
* - Theo Beisch <theo.beisch@gmx.de>
* - Added getStateVariable(String serviceType, String name).
* 03/22/05
* - Changed httpPostRequestRecieved() to return the bad request when the post request isn't the soap action.
* 03/23/05
* - Added loadDescription(String) to load the description from memory.
* 03/30/05
* - Added getDeviceByDescriptionURI().
* - Added getServiceBySCPDURL().
* 03/31/05
* - Changed httpGetRequestRecieved() to return the description stream using
* Device::getDescriptionData() and Service::getSCPDData() at first.
* 04/25/05
* - Thanks for Mikael Hakman <mhakman@dkab.net>
* Changed announce() and byebye() to close the socket after the posting.
* 04/25/05
* - Thanks for Mikael Hakman <mhakman@dkab.net>
* Changed deviceSearchResponse() answer with USN:UDN::<device-type> when request ST is device type.
* 04/25/05
* - Thanks for Mikael Hakman <mhakman@dkab.net>
* - Changed getDescriptionData() to add a XML declaration at first line.
* 04/25/05
* - Thanks for Mikael Hakman <mhakman@dkab.net>
* - Added a new setActionListener() and serQueryListner() to include the sub devices.
*
******************************************************************/
package org.cybergarage.upnp;
import java.net.*;
import java.io.*;
import java.util.*;
import org.cybergarage.net.*;
import org.cybergarage.http.*;
import org.cybergarage.util.*;
import org.cybergarage.xml.*;
import org.cybergarage.soap.*;
import org.cybergarage.upnp.ssdp.*;
import org.cybergarage.upnp.device.*;
import org.cybergarage.upnp.control.*;
import org.cybergarage.upnp.event.*;
import org.cybergarage.upnp.xml.*;
public class Device implements org.cybergarage.http.HTTPRequestListener, SearchListener
{
////////////////////////////////////////////////
// Constants
////////////////////////////////////////////////
public final static String ELEM_NAME = "device";
public final static String UPNP_ROOTDEVICE = "upnp:rootdevice";
public final static int DEFAULT_STARTUP_WAIT_TIME = 1000;
public final static int DEFAULT_DISCOVERY_WAIT_TIME = 300;
public final static int DEFAULT_LEASE_TIME = 30 * 60;
public final static int HTTP_DEFAULT_PORT = 4004;
public final static String DEFAULT_DESCRIPTION_URI = "/description.xml";
////////////////////////////////////////////////
// Member
////////////////////////////////////////////////
private Node rootNode;
private Node deviceNode;
public Node getRootNode()
{
if (rootNode != null)
return rootNode;
if (deviceNode == null)
return null;
return deviceNode.getRootNode();
}
public Node getDeviceNode()
{
return deviceNode;
}
public void setRootNode(Node node)
{
rootNode = node;
}
public void setDeviceNode(Node node)
{
deviceNode = node;
}
////////////////////////////////////////////////
// Initialize
////////////////////////////////////////////////
static
{
UPnP.initialize();
}
////////////////////////////////////////////////
// Constructor
////////////////////////////////////////////////
public Device(Node root, Node device)
{
rootNode = root;
deviceNode = device;
setUUID(UPnP.createUUID());
setWirelessMode(false);
}
public Device()
{
this(null, null);
}
public Device(Node device)
{
this(null, device);
}
public Device(File descriptionFile) throws InvalidDescriptionException
{
this(null, null);
loadDescription(descriptionFile);
}
public Device(String descriptionFileName) throws InvalidDescriptionException
{
this(new File(descriptionFileName));
}
////////////////////////////////////////////////
// Mutex
////////////////////////////////////////////////
private Mutex mutex = new Mutex();
public void lock()
{
mutex.lock();
}
public void unlock()
{
mutex.unlock();
}
////////////////////////////////////////////////
// NMPR
////////////////////////////////////////////////
public void setNMPRMode(boolean flag)
{
Node devNode = getDeviceNode();
if (devNode == null)
return;
if (flag == true) {
devNode.setNode(UPnP.INMPR03, UPnP.INMPR03_VERSION);
devNode.removeNode(Device.URLBASE_NAME);
}
else {
devNode.removeNode(UPnP.INMPR03);
}
}
public boolean isNMPRMode()
{
Node devNode = getDeviceNode();
if (devNode == null)
return false;
return (devNode.getNode(UPnP.INMPR03) != null) ? true : false;
}
////////////////////////////////////////////////
// Wireless
////////////////////////////////////////////////
private boolean wirelessMode;
public void setWirelessMode(boolean flag)
{
wirelessMode = flag;
}
public boolean isWirelessMode()
{
return wirelessMode;
}
public int getSSDPAnnounceCount()
{
if (isNMPRMode() == true && isWirelessMode() == true)
return UPnP.INMPR03_DISCOVERY_OVER_WIRELESS_COUNT;
return 1;
}
////////////////////////////////////////////////
// Device UUID
////////////////////////////////////////////////
private String devUUID;
private void setUUID(String uuid)
{
devUUID = uuid;
}
private String getUUID()
{
return devUUID;
}
private void updateUDN()
{
setUDN("uuid:" + getUUID());
}
////////////////////////////////////////////////
// Root Device
////////////////////////////////////////////////
public Device getRootDevice()
{
Node rootNode = getRootNode();
if (rootNode == null)
return null;
Node devNode = rootNode.getNode(Device.ELEM_NAME);
if (devNode == null)
return null;
return new Device(rootNode, devNode);
}
////////////////////////////////////////////////
// Parent Device
////////////////////////////////////////////////
// Thanks for Stefano Lenzi (07/24/04)
public Device getParentDevice()
{
if(isRootDevice())
return null;
Node devNode = getDeviceNode();
//<device><deviceList><device>
devNode = devNode.getParentNode().getParentNode().getNode(Device.ELEM_NAME);
return new Device(devNode);
}
////////////////////////////////////////////////
// UserData
////////////////////////////////////////////////
private DeviceData getDeviceData()
{
Node node = getDeviceNode();
DeviceData userData = (DeviceData)node.getUserData();
if (userData == null) {
userData = new DeviceData();
node.setUserData(userData);
userData.setNode(node);
}
return userData;
}
////////////////////////////////////////////////
// Description
////////////////////////////////////////////////
private void setDescriptionFile(File file)
{
getDeviceData().setDescriptionFile(file);
}
public File getDescriptionFile()
{
return getDeviceData().getDescriptionFile();
}
private void setDescriptionURI(String uri)
{
getDeviceData().setDescriptionURI(uri);
}
private String getDescriptionURI()
{
return getDeviceData().getDescriptionURI();
}
private boolean isDescriptionURI(String uri)
{
String descriptionURI = getDescriptionURI();
if (uri == null || descriptionURI == null)
return false;
return descriptionURI.equals(uri);
}
public String getDescriptionFilePath()
{
File descriptionFile = getDescriptionFile();
if (descriptionFile == null)
return "";
return descriptionFile.getAbsoluteFile().getParent();
}
public boolean loadDescription(String descString) throws InvalidDescriptionException
{
try {
Parser parser = UPnP.getXMLParser();
rootNode = parser.parse(descString);
if (rootNode == null)
throw new InvalidDescriptionException(Description.NOROOT_EXCEPTION);
deviceNode = rootNode.getNode(Device.ELEM_NAME);
if (deviceNode == null)
throw new InvalidDescriptionException(Description.NOROOTDEVICE_EXCEPTION);
}
catch (ParserException e) {
throw new InvalidDescriptionException(e);
}
if (initializeLoadedDescription() == false)
return false;
setDescriptionFile(null);
return true;
}
public boolean loadDescription(File file) throws InvalidDescriptionException
{
try {
Parser parser = UPnP.getXMLParser();
rootNode = parser.parse(file);
if (rootNode == null)
throw new InvalidDescriptionException(Description.NOROOT_EXCEPTION, file);
deviceNode = rootNode.getNode(Device.ELEM_NAME);
if (deviceNode == null)
throw new InvalidDescriptionException(Description.NOROOTDEVICE_EXCEPTION, file);
}
catch (ParserException e) {
throw new InvalidDescriptionException(e);
}
if (initializeLoadedDescription() == false)
return false;
setDescriptionFile(file);
return true;
}
private boolean initializeLoadedDescription()
{
setDescriptionURI(DEFAULT_DESCRIPTION_URI);
setLeaseTime(DEFAULT_LEASE_TIME);
setHTTPPort(HTTP_DEFAULT_PORT);
// Thanks for Oliver Newell (03/23/04)
if (hasUDN() == false)
updateUDN();
return true;
}
////////////////////////////////////////////////
// isDeviceNode
////////////////////////////////////////////////
public static boolean isDeviceNode(Node node)
{
return Device.ELEM_NAME.equals(node.getName());
}
////////////////////////////////////////////////
// Root Device
////////////////////////////////////////////////
public boolean isRootDevice()
{
return (getRootNode() != null) ? true : false;
}
////////////////////////////////////////////////
// Root Device
////////////////////////////////////////////////
public void setSSDPPacket(SSDPPacket packet)
{
getDeviceData().setSSDPPacket(packet);
}
public SSDPPacket getSSDPPacket()
{
if (isRootDevice() == false)
return null;
return getDeviceData().getSSDPPacket();
}
////////////////////////////////////////////////
// Location
////////////////////////////////////////////////
public void setLocation(String value)
{
getDeviceData().setLocation(value);
}
public String getLocation()
{
SSDPPacket packet = getSSDPPacket();
if (packet != null)
return packet.getLocation();
return getDeviceData().getLocation();
}
////////////////////////////////////////////////
// LeaseTime
////////////////////////////////////////////////
public void setLeaseTime(int value)
{
getDeviceData().setLeaseTime(value);
Advertiser adv = getAdvertiser();
if (adv != null) {
announce();
adv.restart();
}
}
public int getLeaseTime()
{
SSDPPacket packet = getSSDPPacket();
if (packet != null)
return packet.getLeaseTime();
return getDeviceData().getLeaseTime();
}
////////////////////////////////////////////////
// TimeStamp
////////////////////////////////////////////////
public long getTimeStamp()
{
SSDPPacket packet = getSSDPPacket();
if (packet != null)
return packet.getTimeStamp();
return 0;
}
public long getElapsedTime()
{
return (System.currentTimeMillis() - getTimeStamp()) / 1000;
}
public boolean isExpired()
{
long elipsedTime = getElapsedTime();
long leaseTime = getLeaseTime() + UPnP.DEFAULT_EXPIRED_DEVICE_EXTRA_TIME;
if (leaseTime < elipsedTime)
return true;
return false;
}
////////////////////////////////////////////////
// URL Base
////////////////////////////////////////////////
private final static String URLBASE_NAME = "URLBase";
private void setURLBase(String value)
{
if (isRootDevice() == true) {
Node node = getRootNode().getNode(URLBASE_NAME);
if (node != null) {
node.setValue(value);
return;
}
node = new Node(URLBASE_NAME);
node.setValue(value);
int index = 1;
if (getRootNode().hasNodes() == false)
index = 1;
getRootNode().insertNode(node, index);
}
}
private void updateURLBase(String host)
{
String urlBase = HostInterface.getHostURL(host, getHTTPPort(), "");
setURLBase(urlBase);
}
public String getURLBase()
{
if (isRootDevice() == true)
return getRootNode().getNodeValue(URLBASE_NAME);
return "";
}
////////////////////////////////////////////////
// deviceType
////////////////////////////////////////////////
private final static String DEVICE_TYPE = "deviceType";
public void setDeviceType(String value)
{
getDeviceNode().setNode(DEVICE_TYPE, value);
}
public String getDeviceType()
{
return getDeviceNode().getNodeValue(DEVICE_TYPE);
}
public boolean isDeviceType(String value)
{
if (value == null)
return false;
return value.equals(getDeviceType());
}
////////////////////////////////////////////////
// friendlyName
////////////////////////////////////////////////
private final static String FRIENDLY_NAME = "friendlyName";
public void setFriendlyName(String value)
{
getDeviceNode().setNode(FRIENDLY_NAME, value);
}
public String getFriendlyName()
{
return getDeviceNode().getNodeValue(FRIENDLY_NAME);
}
////////////////////////////////////////////////
// manufacture
////////////////////////////////////////////////
private final static String MANUFACTURE = "manufacture";
public void setManufacture(String value)
{
getDeviceNode().setNode(MANUFACTURE, value);
}
public String getManufacture()
{
return getDeviceNode().getNodeValue(MANUFACTURE);
}
////////////////////////////////////////////////
// manufactureURL
////////////////////////////////////////////////
private final static String MANUFACTURE_URL = "manufactureURL";
public void setManufactureURL(String value)
{
getDeviceNode().setNode(MANUFACTURE_URL, value);
}
public String getManufactureURL()
{
return getDeviceNode().getNodeValue(MANUFACTURE_URL);
}
////////////////////////////////////////////////
// modelDescription
////////////////////////////////////////////////
private final static String MODEL_DESCRIPTION = "modelDescription";
public void setModelDescription(String value)
{
getDeviceNode().setNode(MODEL_DESCRIPTION, value);
}
public String getModelDescription()
{
return getDeviceNode().getNodeValue(MODEL_DESCRIPTION);
}
////////////////////////////////////////////////
// modelName
////////////////////////////////////////////////
private final static String MODEL_NAME = "modelName";
public void setModelName(String value)
{
getDeviceNode().setNode(MODEL_NAME, value);
}
public String getModelName()
{
return getDeviceNode().getNodeValue(MODEL_NAME);
}
////////////////////////////////////////////////
// modelNumber
////////////////////////////////////////////////
private final static String MODEL_NUMBER = "modelNumber";
public void setModelNumber(String value)
{
getDeviceNode().setNode(MODEL_NUMBER, value);
}
public String getModelNumber()
{
return getDeviceNode().getNodeValue(MODEL_NUMBER);
}
////////////////////////////////////////////////
// modelURL
////////////////////////////////////////////////
private final static String MODEL_URL = "modelURL";
public void setModelURL(String value)
{
getDeviceNode().setNode(MODEL_URL, value);
}
public String getModelURL()
{
return getDeviceNode().getNodeValue(MODEL_URL);
}
////////////////////////////////////////////////
// serialNumber
////////////////////////////////////////////////
private final static String SERIAL_NUMBER = "serialNumber";
public void setSerialNumber(String value)
{
getDeviceNode().setNode(SERIAL_NUMBER, value);
}
public String getSerialNumber()
{
return getDeviceNode().getNodeValue(SERIAL_NUMBER);
}
////////////////////////////////////////////////
// UDN
////////////////////////////////////////////////
private final static String UDN = "UDN";
public void setUDN(String value)
{
getDeviceNode().setNode(UDN, value);
}
public String getUDN()
{
return getDeviceNode().getNodeValue(UDN);
}
public boolean hasUDN()
{
String udn = getUDN();
if (udn == null || udn.length() <= 0)
return false;
return true;
}
////////////////////////////////////////////////
// UPC
////////////////////////////////////////////////
private final static String UPC = "UPC";
public void setUPC(String value)
{
getDeviceNode().setNode(UPC, value);
}
public String getUPC()
{
return getDeviceNode().getNodeValue(UPC);
}
////////////////////////////////////////////////
// presentationURL
////////////////////////////////////////////////
private final static String presentationURL = "presentationURL";
public void setPresentationURL(String value)
{
getDeviceNode().setNode(presentationURL, value);
}
public String getPresentationURL()
{
return getDeviceNode().getNodeValue(presentationURL);
}
////////////////////////////////////////////////
// deviceList
////////////////////////////////////////////////
public DeviceList getDeviceList()
{
DeviceList devList = new DeviceList();
Node devListNode = getDeviceNode().getNode(DeviceList.ELEM_NAME);
if (devListNode == null)
return devList;
int nNode = devListNode.getNNodes();
for (int n=0; n<nNode; n++) {
Node node = devListNode.getNode(n);
if (Device.isDeviceNode(node) == false)
continue;
Device dev = new Device(node);
devList.add(dev);
}
return devList;
}
public boolean isDevice(String name)
{
if (name == null)
return false;
if (name.endsWith(getUDN()) == true)
return true;
if (name.equals(getFriendlyName()) == true)
return true;
if (name.endsWith(getDeviceType()) == true)
return true;
return false;
}
public Device getDevice(String name)
{
DeviceList devList = getDeviceList();
int devCnt = devList.size();
for (int n=0; n<devCnt; n++) {
Device dev = devList.getDevice(n);
if (dev.isDevice(name) == true)
return dev;
Device cdev = dev.getDevice(name);
if (cdev != null)
return cdev;
}
return null;
}
public Device getDeviceByDescriptionURI(String uri)
{
DeviceList devList = getDeviceList();
int devCnt = devList.size();
for (int n=0; n<devCnt; n++) {
Device dev = devList.getDevice(n);
if (dev.isDescriptionURI(uri) == true)
return dev;
Device cdev = dev.getDeviceByDescriptionURI(uri);
if (cdev != null)
return cdev;
}
return null;
}
////////////////////////////////////////////////
// serviceList
////////////////////////////////////////////////
public ServiceList getServiceList()
{
ServiceList serviceList = new ServiceList();
Node serviceListNode = getDeviceNode().getNode(ServiceList.ELEM_NAME);
if (serviceListNode == null)
return serviceList;
int nNode = serviceListNode.getNNodes();
for (int n=0; n<nNode; n++) {
Node node = serviceListNode.getNode(n);
if (Service.isServiceNode(node) == false)
continue;
Service service = new Service(node);
serviceList.add(service);
}
return serviceList;
}
public Service getService(String name)
{
ServiceList serviceList = getServiceList();
int serviceCnt = serviceList.size();
for (int n=0; n<serviceCnt; n++) {
Service service = serviceList.getService(n);
if (service.isService(name) == true)
return service;
}
DeviceList devList = getDeviceList();
int devCnt = devList.size();
for (int n=0; n<devCnt; n++) {
Device dev = devList.getDevice(n);
Service service = dev.getService(name);
if (service != null)
return service;
}
return null;
}
public Service getServiceBySCPDURL(String searchUrl)
{
ServiceList serviceList = getServiceList();
int serviceCnt = serviceList.size();
for (int n=0; n<serviceCnt; n++) {
Service service = serviceList.getService(n);
if (service.isSCPDURL(searchUrl) == true)
return service;
}
DeviceList devList = getDeviceList();
int devCnt = devList.size();
for (int n=0; n<devCnt; n++) {
Device dev = devList.getDevice(n);
Service service = dev.getServiceBySCPDURL(searchUrl);
if (service != null)
return service;
}
return null;
}
public Service getServiceByControlURL(String searchUrl)
{
ServiceList serviceList = getServiceList();
int serviceCnt = serviceList.size();
for (int n=0; n<serviceCnt; n++) {
Service service = serviceList.getService(n);
if (service.isControlURL(searchUrl) == true)
return service;
}
DeviceList devList = getDeviceList();
int devCnt = devList.size();
for (int n=0; n<devCnt; n++) {
Device dev = devList.getDevice(n);
Service service = dev.getServiceByControlURL(searchUrl);
if (service != null)
return service;
}
return null;
}
public Service getServiceByEventSubURL(String searchUrl)
{
ServiceList serviceList = getServiceList();
int serviceCnt = serviceList.size();
for (int n=0; n<serviceCnt; n++) {
Service service = serviceList.getService(n);
if (service.isEventSubURL(searchUrl) == true)
return service;
}
DeviceList devList = getDeviceList();
int devCnt = devList.size();
for (int n=0; n<devCnt; n++) {
Device dev = devList.getDevice(n);
Service service = dev.getServiceByEventSubURL(searchUrl);
if (service != null)
return service;
}
return null;
}
public Service getSubscriberService(String uuid)
{
ServiceList serviceList = getServiceList();
int serviceCnt = serviceList.size();
for (int n=0; n<serviceCnt; n++) {
Service service = serviceList.getService(n);
String sid = service.getSID();
if (uuid.equals(sid) == true)
return service;
}
DeviceList devList = getDeviceList();
int devCnt = devList.size();
for (int n=0; n<devCnt; n++) {
Device dev = devList.getDevice(n);
Service service = dev.getSubscriberService(uuid);
if (service != null)
return service;
}
return null;
}
////////////////////////////////////////////////
// StateVariable
////////////////////////////////////////////////
public StateVariable getStateVariable(String serviceType, String name)
{
if (serviceType == null && name == null)
return null;
ServiceList serviceList = getServiceList();
int serviceCnt = serviceList.size();
for (int n=0; n<serviceCnt; n++) {
Service service = serviceList.getService(n);
// Thanks for Theo Beisch (11/09/04)
if (serviceType != null) {
if (service.getServiceType().equals(serviceType) == false)
continue;
}
StateVariable stateVar = service.getStateVariable(name);
if (stateVar != null)
return stateVar;
}
DeviceList devList = getDeviceList();
int devCnt = devList.size();
for (int n=0; n<devCnt; n++) {
Device dev = devList.getDevice(n);
StateVariable stateVar = dev.getStateVariable(serviceType, name);
if (stateVar != null)
return stateVar;
}
return null;
}
public StateVariable getStateVariable(String name)
{
return getStateVariable(null, name);
}
////////////////////////////////////////////////
// Action
////////////////////////////////////////////////
public Action getAction(String name)
{
ServiceList serviceList = getServiceList();
int serviceCnt = serviceList.size();
for (int n=0; n<serviceCnt; n++) {
Service service = serviceList.getService(n);
ActionList actionList = service.getActionList();
int actionCnt = actionList.size();
for (int i=0; i<actionCnt; i++) {
Action action = (Action)actionList.getAction(i);
String actionName = action.getName();
if (actionName == null)
continue;
if (actionName.equals(name) == true)
return action;
}
}
DeviceList devList = getDeviceList();
int devCnt = devList.size();
for (int n=0; n<devCnt; n++) {
Device dev = devList.getDevice(n);
Action action = dev.getAction(name);
if (action != null)
return action;
}
return null;
}
////////////////////////////////////////////////
// iconList
////////////////////////////////////////////////
public IconList getIconList()
{
IconList iconList = new IconList();
Node iconListNode = getDeviceNode().getNode(IconList.ELEM_NAME);
if (iconListNode == null)
return iconList;
int nNode = iconListNode.getNNodes();
for (int n=0; n<nNode; n++) {
Node node = iconListNode.getNode(n);
if (Icon.isIconNode(node) == false)
continue;
Icon icon = new Icon(node);
iconList.add(icon);
}
return iconList;
}
public Icon getIcon(int n)
{
IconList iconList = getIconList();
if (n < 0 && (iconList.size()-1) < n)
return null;
return iconList.getIcon(n);
}
////////////////////////////////////////////////
// Notify
////////////////////////////////////////////////
public String getLocationURL(String host)
{
return HostInterface.getHostURL(host, getHTTPPort(), getDescriptionURI());
}
private String getNotifyDeviceNT()
{
if (isRootDevice() == false)
return getUDN();
return UPNP_ROOTDEVICE;
}
private String getNotifyDeviceUSN()
{
if (isRootDevice() == false)
return getUDN();
return getUDN() + "::" + UPNP_ROOTDEVICE;
}
private String getNotifyDeviceTypeNT()
{
return getDeviceType();
}
private String getNotifyDeviceTypeUSN()
{
return getUDN() + "::" + getDeviceType();
}
public final static void notifyWait()
{
TimerUtil.waitRandom(DEFAULT_DISCOVERY_WAIT_TIME);
}
public void announce(String bindAddr)
{
String devLocation = getLocationURL(bindAddr);
SSDPNotifySocket ssdpSock = new SSDPNotifySocket(bindAddr);
SSDPNotifyRequest ssdpReq = new SSDPNotifyRequest();
ssdpReq.setServer(UPnP.getServerName());
ssdpReq.setLeaseTime(getLeaseTime());
ssdpReq.setLocation(devLocation);
ssdpReq.setNTS(NTS.ALIVE);
// uuid:device-UUID(::upnp:rootdevice)*
if (isRootDevice() == true) {
String devNT = getNotifyDeviceNT();
String devUSN = getNotifyDeviceUSN();
ssdpReq.setNT(devNT);
ssdpReq.setUSN(devUSN);
ssdpSock.post(ssdpReq);
}
// uuid:device-UUID::urn:schemas-upnp-org:device:deviceType:v
String devNT = getNotifyDeviceTypeNT();
String devUSN = getNotifyDeviceTypeUSN();
ssdpReq.setNT(devNT);
ssdpReq.setUSN(devUSN);
ssdpSock.post(ssdpReq);
// Thanks for Mikael Hakman (04/25/05)
ssdpSock.close();
ServiceList serviceList = getServiceList();
int serviceCnt = serviceList.size();
for (int n=0; n<serviceCnt; n++) {
Service service = serviceList.getService(n);
service.announce(bindAddr);
}
DeviceList childDeviceList = getDeviceList();
int childDeviceCnt = childDeviceList.size();
for (int n=0; n<childDeviceCnt; n++) {
Device childDevice = childDeviceList.getDevice(n);
childDevice.announce(bindAddr);
}
}
public void announce()
{
notifyWait();
int nHostAddrs = HostInterface.getNHostAddresses();
for (int n=0; n<nHostAddrs; n++) {
String bindAddr = HostInterface.getHostAddress(n);
if (bindAddr == null || bindAddr.length() <= 0)
continue;
int ssdpCount = getSSDPAnnounceCount();
for (int i=0; i<ssdpCount; i++)
announce(bindAddr);
}
}
public void byebye(String bindAddr)
{
SSDPNotifySocket ssdpSock = new SSDPNotifySocket(bindAddr);
SSDPNotifyRequest ssdpReq = new SSDPNotifyRequest();
ssdpReq.setNTS(NTS.BYEBYE);
// uuid:device-UUID(::upnp:rootdevice)*
if (isRootDevice() == true) {
String devNT = getNotifyDeviceNT();
String devUSN = getNotifyDeviceUSN();
ssdpReq.setNT(devNT);
ssdpReq.setUSN(devUSN);
ssdpSock.post(ssdpReq);
}
// uuid:device-UUID::urn:schemas-upnp-org:device:deviceType:v
String devNT = getNotifyDeviceTypeNT();
String devUSN = getNotifyDeviceTypeUSN();
ssdpReq.setNT(devNT);
ssdpReq.setUSN(devUSN);
ssdpSock.post(ssdpReq);
// Thanks for Mikael Hakman (04/25/05)
ssdpSock.close();
ServiceList serviceList = getServiceList();
int serviceCnt = serviceList.size();
for (int n=0; n<serviceCnt; n++) {
Service service = serviceList.getService(n);
service.byebye(bindAddr);
}
DeviceList childDeviceList = getDeviceList();
int childDeviceCnt = childDeviceList.size();
for (int n=0; n<childDeviceCnt; n++) {
Device childDevice = childDeviceList.getDevice(n);
childDevice.byebye(bindAddr);
}
}
public void byebye()
{
int nHostAddrs = HostInterface.getNHostAddresses();
for (int n=0; n<nHostAddrs; n++) {
String bindAddr = HostInterface.getHostAddress(n);
if (bindAddr == null || bindAddr.length() <= 0)
continue;
int ssdpCount = getSSDPAnnounceCount();
for (int i=0; i<ssdpCount; i++)
byebye(bindAddr);
}
}
////////////////////////////////////////////////
// Search
////////////////////////////////////////////////
public boolean postSearchResponse(SSDPPacket ssdpPacket, String st, String usn)
{
String localAddr = ssdpPacket.getLocalAddress();
Device rootDev = getRootDevice();
String rootDevLocation = rootDev.getLocationURL(localAddr);
SSDPSearchResponse ssdpRes = new SSDPSearchResponse();
ssdpRes.setLeaseTime(getLeaseTime());
ssdpRes.setDate(Calendar.getInstance());
ssdpRes.setST(st);
ssdpRes.setUSN(usn);
ssdpRes.setLocation(rootDevLocation);
// Thanks for Brent Hills (10/20/04)
ssdpRes.setMYNAME(getFriendlyName());
int mx = ssdpPacket.getMX();
TimerUtil.waitRandom(mx * 1000);
String remoteAddr = ssdpPacket.getRemoteAddress();
int remotePort = ssdpPacket.getRemotePort();
SSDPSearchResponseSocket ssdpResSock = new SSDPSearchResponseSocket();
if (Debug.isOn() == true)
ssdpRes.print();
int ssdpCount = getSSDPAnnounceCount();
for (int i=0; i<ssdpCount; i++)
ssdpResSock.post(remoteAddr, remotePort, ssdpRes);
return true;
}
public void deviceSearchResponse(SSDPPacket ssdpPacket)
{
String ssdpST = ssdpPacket.getST();
if (ssdpST == null)
return;
boolean isRootDevice = isRootDevice();
String devUSN = getUDN();
if (isRootDevice == true)
devUSN += "::" + USN.ROOTDEVICE;
if (ST.isAllDevice(ssdpST) == true) {
String devNT = getNotifyDeviceNT();
int repeatCnt = (isRootDevice == true) ? 3 : 2;
for (int n=0; n<repeatCnt; n++)
postSearchResponse(ssdpPacket, devNT, devUSN);
}
else if (ST.isRootDevice(ssdpST) == true) {
if (isRootDevice == true)
postSearchResponse(ssdpPacket, ST.ROOT_DEVICE, devUSN);
}
else if (ST.isUUIDDevice(ssdpST) == true) {
String devUDN = getUDN();
if (ssdpST.equals(devUDN) == true)
postSearchResponse(ssdpPacket, devUDN, devUSN);
}
else if (ST.isURNDevice(ssdpST) == true) {
String devType= getDeviceType();
if (ssdpST.equals(devType) == true) {
// Thanks for Mikael Hakman (04/25/05)
devUSN = getUDN() + "::" + devType;
postSearchResponse(ssdpPacket, devType, devUSN);
}
}
ServiceList serviceList = getServiceList();
int serviceCnt = serviceList.size();
for (int n=0; n<serviceCnt; n++) {
Service service = serviceList.getService(n);
service.serviceSearchResponse(ssdpPacket);
}
DeviceList childDeviceList = getDeviceList();
int childDeviceCnt = childDeviceList.size();
for (int n=0; n<childDeviceCnt; n++) {
Device childDevice = childDeviceList.getDevice(n);
childDevice.deviceSearchResponse(ssdpPacket);
}
}
public void deviceSearchReceived(SSDPPacket ssdpPacket)
{
deviceSearchResponse(ssdpPacket);
}
////////////////////////////////////////////////
// HTTP Server
////////////////////////////////////////////////
public void setHTTPPort(int port)
{
getDeviceData().setHTTPPort(port);
}
public int getHTTPPort()
{
return getDeviceData().getHTTPPort();
}
public void httpRequestRecieved(HTTPRequest httpReq)
{
if (Debug.isOn() == true)
httpReq.print();
if (httpReq.isGetRequest() == true) {
httpGetRequestRecieved(httpReq);
return;
}
if (httpReq.isPostRequest() == true) {
httpPostRequestRecieved(httpReq);
return;
}
if (httpReq.isSubscribeRequest() == true || httpReq.isUnsubscribeRequest() == true) {
SubscriptionRequest subReq = new SubscriptionRequest(httpReq);
deviceEventSubscriptionRecieved(subReq);
return;
}
httpReq.returnBadRequest();
}
private synchronized byte[] getDescriptionData(String host)
{
if (isNMPRMode() == false)
updateURLBase(host);
Node rootNode = getRootNode();
if (rootNode == null)
return new byte[0];
// Thanks for Mikael Hakman (04/25/05)
String desc = new String();
desc += UPnP.XML_DECLARATION;
desc += "\n";
desc += rootNode.toString();
return desc.getBytes();
}
private void httpGetRequestRecieved(HTTPRequest httpReq)
{
String uri = httpReq.getURI();
Debug.message("httpGetRequestRecieved = " + uri);
if (uri == null) {
httpReq.returnBadRequest();
return;
}
Device embDev;
Service embService;
byte fileByte[] = new byte[0];
if (isDescriptionURI(uri) == true) {
String localAddr = httpReq.getLocalAddress();
fileByte = getDescriptionData(localAddr);
}
else if ((embDev = getDeviceByDescriptionURI(uri)) != null) {
String localAddr = httpReq.getLocalAddress();
fileByte = embDev.getDescriptionData(localAddr);
}
else if ((embService = getServiceBySCPDURL(uri)) != null) {
fileByte = embService.getSCPDData();
}
else {
httpReq.returnBadRequest();
return;
}
HTTPResponse httpRes = new HTTPResponse();
if (FileUtil.isXMLFileName(uri) == true)
httpRes.setContentType(XML.CONTENT_TYPE);
httpRes.setStatusCode(HTTPStatus.OK);
httpRes.setContent(fileByte);
httpReq.post(httpRes);
}
private void httpPostRequestRecieved(HTTPRequest httpReq)
{
if (httpReq.isSOAPAction() == true) {
//SOAPRequest soapReq = new SOAPRequest(httpReq);
soapActionRecieved(httpReq);
return;
}
httpReq.returnBadRequest();
}
////////////////////////////////////////////////
// SOAP
////////////////////////////////////////////////
private void soapBadActionRecieved(HTTPRequest soapReq)
{
SOAPResponse soapRes = new SOAPResponse();
soapRes.setStatusCode(HTTPStatus.BAD_REQUEST);
soapReq.post(soapRes);
}
private void soapActionRecieved(HTTPRequest soapReq)
{
String uri = soapReq.getURI();
Service ctlService = getServiceByControlURL(uri);
if (ctlService != null) {
ActionRequest crlReq = new ActionRequest(soapReq);
deviceControlRequestRecieved(crlReq, ctlService);
return;
}
soapBadActionRecieved(soapReq);
}
////////////////////////////////////////////////
// controlAction
////////////////////////////////////////////////
private void deviceControlRequestRecieved(ControlRequest ctlReq, Service service)
{
if (ctlReq.isQueryControl() == true)
deviceQueryControlRecieved(new QueryRequest(ctlReq), service);
else
deviceActionControlRecieved(new ActionRequest(ctlReq), service);
}
private void invalidActionControlRecieved(ControlRequest ctlReq)
{
ControlResponse actRes = new ActionResponse();
actRes.setFaultResponse(UPnPStatus.INVALID_ACTION);
ctlReq.post(actRes);
}
private void deviceActionControlRecieved(ActionRequest ctlReq, Service service)
{
if (Debug.isOn() == true)
ctlReq.print();
String actionName = ctlReq.getActionName();
Action action = service.getAction(actionName);
if (action == null) {
invalidActionControlRecieved(ctlReq);
return;
}
ArgumentList actionArgList = action.getArgumentList();
ArgumentList reqArgList = ctlReq.getArgumentList();
actionArgList.set(reqArgList);
if (action.performActionListener(ctlReq) == false)
invalidActionControlRecieved(ctlReq);
}
private void deviceQueryControlRecieved(QueryRequest ctlReq, Service service)
{
if (Debug.isOn() == true)
ctlReq.print();
String varName = ctlReq.getVarName();
if (service.hasStateVariable(varName) == false) {
invalidActionControlRecieved(ctlReq);
return;
}
StateVariable stateVar = getStateVariable(varName);
if (stateVar.performQueryListener(ctlReq) == false)
invalidActionControlRecieved(ctlReq);
}
////////////////////////////////////////////////
// eventSubscribe
////////////////////////////////////////////////
private void upnpBadSubscriptionRecieved(SubscriptionRequest subReq, int code)
{
SubscriptionResponse subRes = new SubscriptionResponse();
subRes.setErrorResponse(code);
subReq.post(subRes);
}
private void deviceEventSubscriptionRecieved(SubscriptionRequest subReq)
{
String uri = subReq.getURI();
Service service = getServiceByEventSubURL(uri);
if (service == null) {
subReq.returnBadRequest();
return;
}
if (subReq.hasCallback() == false && subReq.hasSID() == false) {
upnpBadSubscriptionRecieved(subReq, HTTPStatus.PRECONDITION_FAILED);
return;
}
// UNSUBSCRIBE
if (subReq.isUnsubscribeRequest() == true) {
deviceEventUnsubscriptionRecieved(service, subReq);
return;
}
// SUBSCRIBE (NEW)
if (subReq.hasCallback() == true) {
deviceEventNewSubscriptionRecieved(service, subReq);
return;
}
// SUBSCRIBE (RENEW)
if (subReq.hasSID() == true) {
deviceEventRenewSubscriptionRecieved(service, subReq);
return;
}
upnpBadSubscriptionRecieved(subReq, HTTPStatus.PRECONDITION_FAILED);
}
private void deviceEventNewSubscriptionRecieved(Service service, SubscriptionRequest subReq)
{
String callback = subReq.getCallback();
try {
new URL(callback);
}
catch (Exception e) {
upnpBadSubscriptionRecieved(subReq, HTTPStatus.PRECONDITION_FAILED);
return;
}
long timeOut = subReq.getTimeout();
String sid = Subscription.createSID();
Subscriber sub = new Subscriber();
sub.setDeliveryURL(callback);
sub.setTimeOut(timeOut);
sub.setSID(sid);
service.addSubscriber(sub);
SubscriptionResponse subRes = new SubscriptionResponse();
subRes.setStatusCode(HTTPStatus.OK);
subRes.setSID(sid);
subRes.setTimeout(timeOut);
if (Debug.isOn() == true)
subRes.print();
subReq.post(subRes);
if (Debug.isOn() == true)
subRes.print();
service.notifyAllStateVariables();
}
private void deviceEventRenewSubscriptionRecieved(Service service, SubscriptionRequest subReq)
{
String sid = subReq.getSID();
Subscriber sub = service.getSubscriber(sid);
if (sub == null) {
upnpBadSubscriptionRecieved(subReq, HTTPStatus.PRECONDITION_FAILED);
return;
}
long timeOut = subReq.getTimeout();
sub.setTimeOut(timeOut);
sub.renew();
SubscriptionResponse subRes = new SubscriptionResponse();
subRes.setStatusCode(HTTPStatus.OK);
subRes.setSID(sid);
subRes.setTimeout(timeOut);
subReq.post(subRes);
if (Debug.isOn() == true)
subRes.print();
}
private void deviceEventUnsubscriptionRecieved(Service service, SubscriptionRequest subReq)
{
String sid = subReq.getSID();
Subscriber sub = service.getSubscriber(sid);
if (sub == null) {
upnpBadSubscriptionRecieved(subReq, HTTPStatus.PRECONDITION_FAILED);
return;
}
service.removeSubscriber(sub);
SubscriptionResponse subRes = new SubscriptionResponse();
subRes.setStatusCode(HTTPStatus.OK);
subReq.post(subRes);
if (Debug.isOn() == true)
subRes.print();
}
////////////////////////////////////////////////
// Thread
////////////////////////////////////////////////
private HTTPServerList getHTTPServerList()
{
return getDeviceData().getHTTPServerList();
}
private SSDPSearchSocketList getSSDPSearchSocketList()
{
return getDeviceData().getSSDPSearchSocketList();
}
private void setAdvertiser(Advertiser adv)
{
getDeviceData().setAdvertiser(adv);
}
private Advertiser getAdvertiser()
{
return getDeviceData().getAdvertiser();
}
public boolean start()
{
stop(true);
////////////////////////////////////////
// HTTP Server
////////////////////////////////////////
int retryCnt = 0;
int bindPort = getHTTPPort();
HTTPServerList httpServerList = getHTTPServerList();
while (httpServerList.open(bindPort) == false) {
retryCnt++;
if (UPnP.SERVER_RETRY_COUNT < retryCnt)
return false;
setHTTPPort(bindPort + 1);
bindPort = getHTTPPort();
}
httpServerList.addRequestListener(this);
httpServerList.start();
////////////////////////////////////////
// SSDP Seach Socket
////////////////////////////////////////
SSDPSearchSocketList ssdpSearchSockList = getSSDPSearchSocketList();
if (ssdpSearchSockList.open() == false)
return false;
ssdpSearchSockList.addSearchListener(this);
ssdpSearchSockList.start();
////////////////////////////////////////
// Announce
////////////////////////////////////////
announce();
////////////////////////////////////////
// Advertiser
////////////////////////////////////////
Advertiser adv = new Advertiser(this);
setAdvertiser(adv);
adv.start();
return true;
}
private boolean stop(boolean doByeBye)
{
if (doByeBye == true)
byebye();
HTTPServerList httpServerList = getHTTPServerList();
httpServerList.stop();
httpServerList.close();
httpServerList.clear();
SSDPSearchSocketList ssdpSearchSockList = getSSDPSearchSocketList();
ssdpSearchSockList.stop();
ssdpSearchSockList.close();
ssdpSearchSockList.clear();
Advertiser adv = getAdvertiser();
if (adv != null) {
adv.stop();
setAdvertiser(null);
}
return true;
}
public boolean stop()
{
return stop(true);
}
////////////////////////////////////////////////
// Interface Address
////////////////////////////////////////////////
public String getInterfaceAddress()
{
SSDPPacket ssdpPacket = getSSDPPacket();
if (ssdpPacket == null)
return "";
return ssdpPacket.getLocalAddress();
}
////////////////////////////////////////////////
// Acion/QueryListener
////////////////////////////////////////////////
public void setActionListener(ActionListener listener)
{
ServiceList serviceList = getServiceList();
int nServices = serviceList.size();
for (int n=0; n<nServices; n++) {
Service service = serviceList.getService(n);
service.setActionListener(listener);
}
}
public void setQueryListener(QueryListener listener)
{
ServiceList serviceList = getServiceList();
int nServices = serviceList.size();
for (int n=0; n<nServices; n++) {
Service service = serviceList.getService(n);
service.setQueryListener(listener);
}
}
////////////////////////////////////////////////
// Acion/QueryListener (includeSubDevices)
////////////////////////////////////////////////
// Thanks for Mikael Hakman (04/25/05)
public void setActionListener(ActionListener listener, boolean includeSubDevices)
{
setActionListener(listener);
if (includeSubDevices == true) {
DeviceList devList = getDeviceList();
int devCnt = devList.size();
for (int n = 0; n < devCnt; n++) {
Device dev = devList.getDevice(n);
dev.setActionListener(listener, true);
}
}
}
// Thanks for Mikael Hakman (04/25/05)
public void setQueryListener(QueryListener listener, boolean includeSubDevices)
{
setQueryListener(listener);
if (includeSubDevices == true) {
DeviceList devList = getDeviceList();
int devCnt = devList.size();
for (int n = 0; n < devCnt; n++) {
Device dev = devList.getDevice(n);
dev.setQueryListener(listener, true);
}
}
}
////////////////////////////////////////////////
// output
////////////////////////////////////////////////
/*
public void output(PrintWriter ps)
{
ps.println("deviceType = " + getDeviceType());
ps.println("freindlyName = " + getFriendlyName());
ps.println("presentationURL = " + getPresentationURL());
DeviceList devList = getDeviceList();
ps.println("devList = " + devList.size());
ServiceList serviceList = getServiceList();
ps.println("serviceList = " + serviceList.size());
IconList iconList = getIconList();
ps.println("iconList = " + iconList.size());
}
public void print()
{
PrintWriter pr = new PrintWriter(System.out);
output(pr);
pr.flush();
}
*/
}