Files
i2p.i2p/router/java/src/org/cybergarage/upnp/ControlPoint.java
zzz eb535762c4 UPnP: IPv6 part 2
Add support for storing multiple location URLs in DeviceData
Add methods to prefer IPv6 for location URLs
Prefer IPv6 for POST target to WANIPv6FirewallControl service
Add method to bind local address for POST, needed for security checks when forwarding IPv6
Remove IPv6 checks from XML URL parser
Remove unused call in QueryRequest
2021-02-28 08:08:07 -05:00

1065 lines
28 KiB
Java

/******************************************************************
*
* CyberUPnP for Java
*
* Copyright (C) Satoshi Konno 2002-2004
*
* File: ControlPoint.java
*
* Revision:
*
* 11/18/02
* - first revision.
* 05/13/03
* - Changed to create socket threads each local interfaces.
* (HTTP, SSDPNotiry, SSDPSerachResponse)
* 05/28/03
* - Changed to send m-serach packets from SSDPSearchResponseSocket.
* The socket doesn't bind interface address.
* - SSDPSearchResponsSocketList that binds a port and a interface can't
* send m-serch packets of IPv6 on J2SE v 1.4.1_02 and Redhat 9.
* 07/23/03
* - Suzan Foster (suislief)
* - Fixed a bug. HOST field was missing.
* 07/29/03
* - Synchronized when a device is added by the ssdp message.
* 09/08/03
* - Giordano Sassaroli <sassarol@cefriel.it>
* - Problem : when an event notification message is received and the message
* contains updates on more than one variable, only the first variable update
* is notified.
* - Error : the other xml nodes of the message are ignored
* - Fix : add two methods to the NotifyRequest for extracting the property array
* and modify the httpRequestRecieved method in ControlPoint
* 12/12/03
* - Added a static() to initialize UPnP class.
* 01/06/04
* - Added the following methods to remove expired devices automatically
* removeExpiredDevices()
* setExpiredDeviceMonitoringInterval()/getExpiredDeviceMonitoringInterval()
* setDeviceDisposer()/getDeviceDisposer()
* 04/20/04
* - Added the following methods.
* start(String target, int mx) and start(String target).
* 06/23/04
* - Added setNMPRMode() and isNMPRMode().
* 07/08/04
* - Added renewSubscriberService().
* - Changed start() to create renew subscriber thread when the NMPR mode is true.
* 08/17/04
* - Fixed removeExpiredDevices() to remove using the device array.
* 10/16/04
* - Oliver Newell <newell@media-rush.com>
* - Added this class to allow ControlPoint applications to be notified when
* the ControlPoint base class adds/removes a UPnP device
* 03/30/05
* - Changed addDevice() to use Parser::parse(URL).
* 04/12/06
* - Added setUserData() and getUserData() to set a user original data object.
*
*******************************************************************/
package org.cybergarage.upnp;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Locale;
import org.cybergarage.http.HTTPRequest;
import org.cybergarage.http.HTTPRequestListener;
import org.cybergarage.http.HTTPServerList;
import org.cybergarage.net.HostInterface;
import org.cybergarage.upnp.control.RenewSubscriber;
import org.cybergarage.upnp.device.DeviceChangeListener;
import org.cybergarage.upnp.device.Disposer;
import org.cybergarage.upnp.device.NotifyListener;
import org.cybergarage.upnp.device.ST;
import org.cybergarage.upnp.device.SearchResponseListener;
import org.cybergarage.upnp.device.USN;
import org.cybergarage.upnp.event.EventListener;
import org.cybergarage.upnp.event.NotifyRequest;
import org.cybergarage.upnp.event.Property;
import org.cybergarage.upnp.event.PropertyList;
import org.cybergarage.upnp.event.Subscription;
import org.cybergarage.upnp.event.SubscriptionRequest;
import org.cybergarage.upnp.event.SubscriptionResponse;
import org.cybergarage.upnp.ssdp.SSDP;
import org.cybergarage.upnp.ssdp.SSDPNotifySocketList;
import org.cybergarage.upnp.ssdp.SSDPPacket;
import org.cybergarage.upnp.ssdp.SSDPSearchRequest;
import org.cybergarage.upnp.ssdp.SSDPSearchResponseSocketList;
import org.cybergarage.util.Debug;
import org.cybergarage.util.ListenerList;
import org.cybergarage.util.Mutex;
import org.cybergarage.xml.Node;
import org.cybergarage.xml.NodeList;
import org.cybergarage.xml.Parser;
import org.cybergarage.xml.ParserException;
import net.i2p.util.Addresses;
import net.i2p.router.transport.TransportUtil;
public class ControlPoint implements HTTPRequestListener
{
private final static int DEFAULT_EVENTSUB_PORT = 8058;
private final static int DEFAULT_SSDP_PORT = 8008;
private final static int DEFAULT_EXPIRED_DEVICE_MONITORING_INTERVAL = 60;
private final static String DEFAULT_EVENTSUB_URI = "/evetSub";
// I2P
private static final boolean ALLOW_IPV6_LOCATION = true;
////////////////////////////////////////////////
// Member
////////////////////////////////////////////////
private SSDPNotifySocketList ssdpNotifySocketList;
private SSDPSearchResponseSocketList ssdpSearchResponseSocketList;
/** I2P was private */
protected SSDPNotifySocketList getSSDPNotifySocketList()
{
return ssdpNotifySocketList;
}
/** I2P was private */
protected SSDPSearchResponseSocketList getSSDPSearchResponseSocketList()
{
return ssdpSearchResponseSocketList;
}
////////////////////////////////////////////////
// Initialize
////////////////////////////////////////////////
static
{
UPnP.initialize();
}
////////////////////////////////////////////////
// Constructor
////////////////////////////////////////////////
public ControlPoint(int ssdpPort, int httpPort,InetAddress[] binds){
ssdpNotifySocketList = new SSDPNotifySocketList(binds);
ssdpSearchResponseSocketList = new SSDPSearchResponseSocketList(binds);
setSSDPPort(ssdpPort);
setHTTPPort(httpPort);
setDeviceDisposer(null);
setExpiredDeviceMonitoringInterval(DEFAULT_EXPIRED_DEVICE_MONITORING_INTERVAL);
setRenewSubscriber(null);
setNMPRMode(false);
setRenewSubscriber(null);
}
public ControlPoint(int ssdpPort, int httpPort){
this(ssdpPort,httpPort,null);
}
public ControlPoint()
{
this(DEFAULT_SSDP_PORT, DEFAULT_EVENTSUB_PORT);
}
public void finalize()
{
stop();
}
////////////////////////////////////////////////
// Mutex
////////////////////////////////////////////////
private Mutex mutex = new Mutex();
public void lock()
{
mutex.lock();
}
public void unlock()
{
mutex.unlock();
}
////////////////////////////////////////////////
// Port (SSDP)
////////////////////////////////////////////////
private int ssdpPort = 0;
public int getSSDPPort() {
return ssdpPort;
}
public void setSSDPPort(int port) {
ssdpPort = port;
}
////////////////////////////////////////////////
// Port (EventSub)
////////////////////////////////////////////////
private int httpPort = 0;
public int getHTTPPort() {
return httpPort;
}
public void setHTTPPort(int port) {
httpPort = port;
}
////////////////////////////////////////////////
// NMPR
////////////////////////////////////////////////
private boolean nmprMode;
public void setNMPRMode(boolean flag)
{
nmprMode = flag;
}
public boolean isNMPRMode()
{
return nmprMode;
}
////////////////////////////////////////////////
// Device List
////////////////////////////////////////////////
private NodeList devNodeList = new NodeList();
private void addDevice(Node rootNode)
{
devNodeList.add(rootNode);
}
private synchronized void addDevice(SSDPPacket ssdpPacket)
{
if (ssdpPacket.isRootDevice() == false)
return;
String usn = ssdpPacket.getUSN();
String location = ssdpPacket.getLocation();
try {
URL locationUrl = new URL(location);
// I2P
// Roku fake json port, the real UPnP port is 8060
if (locationUrl.getPort() == 9080) {
String lcusn = usn.toLowerCase(Locale.US);
if (lcusn.contains("rku") || lcusn.contains("roku")) {
Debug.warning("Ignoring Roku at " + location);
return;
}
}
// I2P
// We duplicate all the checks in Parser.parse() because they
// are bypassed for a known device.
// Devices may send two SSDP responses, one with an IPv4 location
// and one with an IPv6 location.
// Do these check BEFORE we call dev.setSSDPPacket() so we don't
// overwrite the SSDPPacket in DeviceData.
// TODO handle multiple locations in DeviceData.
String host = locationUrl.getHost();
if (host == null) {
Debug.warning("Ignoring device with bad URL at " + location);
return;
}
if (host.startsWith("127.")) {
Debug.warning("Ignoring localhost device at " + location);
return;
}
if (host.startsWith("[") && host.endsWith("]")) {
if (!ALLOW_IPV6_LOCATION) {
Debug.warning("Ignoring IPv6 device at " + location);
return;
}
// fixup for valid checks below
host = host.substring(1, host.length() - 1);
}
if (!"http".equals(locationUrl.getProtocol())) {
Debug.warning("Ignoring non-http device at " + location);
return;
}
if (!Addresses.isIPv4Address(host) &&
(!ALLOW_IPV6_LOCATION || !Addresses.isIPv6Address(host))) {
Debug.warning("Ignoring non-IPv4 address at " + location);
return;
}
byte[] ip = Addresses.getIP(host);
if (ip == null) {
Debug.warning("Ignoring bad IP at " + location);
return;
}
if (TransportUtil.isPubliclyRoutable(ip, ALLOW_IPV6_LOCATION)) {
Debug.warning("Ignoring public address at " + location);
return;
}
String udn = USN.getUDN(usn);
Device dev = getDevice(udn);
if (dev != null) {
Debug.warning("Additional SSDP for " + udn + " at " + location);
dev.setSSDPPacket(ssdpPacket);
return;
}
Parser parser = UPnP.getXMLParser();
Node rootNode = parser.parse(locationUrl);
Device rootDev = getDevice(rootNode);
if (rootDev == null)
return;
rootDev.setSSDPPacket(ssdpPacket);
Debug.warning("Add root device at " + location, new Exception("received on " + ssdpPacket.getLocalAddress()));
addDevice(rootNode);
// Thanks for Oliver Newell (2004/10/16)
// After node is added, invoke the AddDeviceListener to notify high-level
// control point application that a new device has been added. (The
// control point application must implement the DeviceChangeListener interface
// to receive the notifications)
performAddDeviceListener( rootDev );
}
catch (MalformedURLException me) {
Debug.warning("Bad location: " + location, me);
}
catch (ParserException pe) {
Debug.warning("Error parsing data at location: " + location, pe);
}
}
private Device getDevice(Node rootNode)
{
if (rootNode == null)
return null;
Node devNode = rootNode.getNode(Device.ELEM_NAME);
if (devNode == null)
return null;
return new Device(rootNode, devNode);
}
public DeviceList getDeviceList()
{
DeviceList devList = new DeviceList();
int nRoots = devNodeList.size();
for (int n=0; n<nRoots; n++) {
// AIOOB was thrown from here, maybe would be better to
// copy the list before traversal?
Node rootNode;
try {
rootNode = devNodeList.getNode(n);
} catch (ArrayIndexOutOfBoundsException aioob) {
break;
}
Device dev = getDevice(rootNode);
if (dev == null)
continue;
devList.add(dev);
}
return devList;
}
public Device getDevice(String name)
{
int nRoots = devNodeList.size();
for (int n=0; n<nRoots; n++) {
// AIOOB was thrown from here, maybe would be better to
// copy the list before traversal?
Node rootNode;
try {
rootNode = devNodeList.getNode(n);
} catch (ArrayIndexOutOfBoundsException aioob) {
break;
}
Device dev = getDevice(rootNode);
if (dev == null)
continue;
if (dev.isDevice(name) == true)
return dev;
Device cdev = dev.getDevice(name);
if (cdev != null)
return cdev;
}
return null;
}
public boolean hasDevice(String name)
{
return (getDevice(name) != null) ? true : false;
}
private void removeDevice(Node rootNode)
{
// Thanks for Oliver Newell (2004/10/16)
// Invoke device removal listener prior to actual removal so Device node
// remains valid for the duration of the listener (application may want
// to access the node)
Device dev = getDevice(rootNode);
if( dev != null && dev.isRootDevice() )
performRemoveDeviceListener( dev );
devNodeList.remove(rootNode);
}
protected void removeDevice(Device dev)
{
if (dev == null)
return;
removeDevice(dev.getRootNode());
}
protected void removeDevice(String name)
{
Device dev = getDevice(name);
removeDevice(dev);
}
private void removeDevice(SSDPPacket packet)
{
if (packet.isByeBye() == false)
return;
String usn = packet.getUSN();
String udn = USN.getUDN(usn);
removeDevice(udn);
}
////////////////////////////////////////////////
// Expired Device
////////////////////////////////////////////////
private Disposer deviceDisposer;
private long expiredDeviceMonitoringInterval;
public void removeExpiredDevices()
{
DeviceList devList = getDeviceList();
int devCnt = devList.size();
Device dev[] = new Device[devCnt];
for (int n=0; n<devCnt; n++)
dev[n] = devList.getDevice(n);
for (int n=0; n<devCnt; n++) {
if (dev[n].isExpired() == true) {
Debug.message("Expired device = " + dev[n].getFriendlyName());
removeDevice(dev[n]);
}
}
}
public void setExpiredDeviceMonitoringInterval(long interval)
{
expiredDeviceMonitoringInterval = interval;
}
public long getExpiredDeviceMonitoringInterval()
{
return expiredDeviceMonitoringInterval;
}
public void setDeviceDisposer(Disposer disposer)
{
deviceDisposer = disposer;
}
public Disposer getDeviceDisposer()
{
return deviceDisposer;
}
////////////////////////////////////////////////
// Notify
////////////////////////////////////////////////
private ListenerList deviceNotifyListenerList = new ListenerList();
public void addNotifyListener(NotifyListener listener)
{
deviceNotifyListenerList.add(listener);
}
public void removeNotifyListener(NotifyListener listener)
{
deviceNotifyListenerList.remove(listener);
}
public void performNotifyListener(SSDPPacket ssdpPacket)
{
int listenerSize = deviceNotifyListenerList.size();
for (int n=0; n<listenerSize; n++) {
NotifyListener listener = (NotifyListener)deviceNotifyListenerList.get(n);
try{
listener.deviceNotifyReceived(ssdpPacket);
}catch(Exception e){
Debug.warning("NotifyListener returned an error:", e);
}
}
}
////////////////////////////////////////////////
// SearchResponse
////////////////////////////////////////////////
private ListenerList deviceSearchResponseListenerList = new ListenerList();
public void addSearchResponseListener(SearchResponseListener listener)
{
deviceSearchResponseListenerList.add(listener);
}
public void removeSearchResponseListener(SearchResponseListener listener)
{
deviceSearchResponseListenerList.remove(listener);
}
public void performSearchResponseListener(SSDPPacket ssdpPacket)
{
int listenerSize = deviceSearchResponseListenerList.size();
for (int n=0; n<listenerSize; n++) {
SearchResponseListener listener = (SearchResponseListener)deviceSearchResponseListenerList.get(n);
try{
listener.deviceSearchResponseReceived(ssdpPacket);
}catch(Exception e){
Debug.warning("SearchResponseListener returned an error:", e);
}
}
}
/////////////////////////////////////////////////////////////////////
// Device status changes (device added or removed)
// Applications that support the DeviceChangeListener interface are
// notified immediately when a device is added to, or removed from,
// the control point.
/////////////////////////////////////////////////////////////////////
ListenerList deviceChangeListenerList = new ListenerList();
public void addDeviceChangeListener(DeviceChangeListener listener)
{
deviceChangeListenerList.add(listener);
}
public void removeDeviceChangeListener(DeviceChangeListener listener)
{
deviceChangeListenerList.remove(listener);
}
public void performAddDeviceListener( Device dev )
{
int listenerSize = deviceChangeListenerList.size();
for (int n=0; n<listenerSize; n++) {
DeviceChangeListener listener = (DeviceChangeListener)deviceChangeListenerList.get(n);
listener.deviceAdded( dev );
}
}
public void performRemoveDeviceListener( Device dev )
{
int listenerSize = deviceChangeListenerList.size();
for (int n=0; n<listenerSize; n++) {
DeviceChangeListener listener = (DeviceChangeListener)deviceChangeListenerList.get(n);
listener.deviceRemoved( dev );
}
}
////////////////////////////////////////////////
// SSDPPacket
////////////////////////////////////////////////
public void notifyReceived(SSDPPacket packet)
{
if (packet.isRootDevice() == true) {
if (packet.isAlive() == true){
addDevice(packet);
}else if (packet.isByeBye() == true){
removeDevice(packet);
}
}
performNotifyListener(packet);
}
public void searchResponseReceived(SSDPPacket packet)
{
if (packet.isRootDevice() == true)
addDevice(packet);
performSearchResponseListener(packet);
}
////////////////////////////////////////////////
// M-SEARCH
////////////////////////////////////////////////
private int searchMx = SSDP.DEFAULT_MSEARCH_MX;
public int getSearchMx()
{
return searchMx;
}
public void setSearchMx(int mx)
{
searchMx = mx;
}
public void search(String target, int mx)
{
SSDPSearchRequest msReq = new SSDPSearchRequest(target, mx);
SSDPSearchResponseSocketList ssdpSearchResponseSocketList = getSSDPSearchResponseSocketList();
ssdpSearchResponseSocketList.post(msReq);
}
public void search(String target)
{
search(target, SSDP.DEFAULT_MSEARCH_MX);
}
public void search()
{
search(ST.ROOT_DEVICE, SSDP.DEFAULT_MSEARCH_MX);
}
////////////////////////////////////////////////
// EventSub HTTPServer
////////////////////////////////////////////////
private HTTPServerList httpServerList = new HTTPServerList();
/** I2P was private */
protected HTTPServerList getHTTPServerList()
{
return httpServerList;
}
public void httpRequestRecieved(HTTPRequest httpReq)
{
if (Debug.isOn() == true)
httpReq.print();
// Thanks for Giordano Sassaroli <sassarol@cefriel.it> (09/08/03)
if (httpReq.isNotifyRequest() == true) {
NotifyRequest notifyReq = new NotifyRequest(httpReq);
String uuid = notifyReq.getSID();
long seq = notifyReq.getSEQ();
PropertyList props = notifyReq.getPropertyList();
int propCnt = props.size();
for (int n = 0; n < propCnt; n++) {
Property prop = props.getProperty(n);
String varName = prop.getName();
String varValue = prop.getValue();
performEventListener(uuid, seq, varName, varValue);
}
httpReq.returnOK();
return;
}
httpReq.returnBadRequest();
}
////////////////////////////////////////////////
// Event Listener
////////////////////////////////////////////////
private ListenerList eventListenerList = new ListenerList();
public void addEventListener(EventListener listener)
{
eventListenerList.add(listener);
}
public void removeEventListener(EventListener listener)
{
eventListenerList.remove(listener);
}
public void performEventListener(String uuid, long seq, String name, String value)
{
int listenerSize = eventListenerList.size();
for (int n=0; n<listenerSize; n++) {
EventListener listener = (EventListener)eventListenerList.get(n);
listener.eventNotifyReceived(uuid, seq, name, value);
}
}
////////////////////////////////////////////////
// Subscription
////////////////////////////////////////////////
private String eventSubURI = DEFAULT_EVENTSUB_URI;
public String getEventSubURI()
{
return eventSubURI;
}
public void setEventSubURI(String url)
{
eventSubURI = url;
}
private String getEventSubCallbackURL(String host)
{
return HostInterface.getHostURL(host, getHTTPPort(), getEventSubURI());
}
public boolean subscribe(Service service, long timeout)
{
if (service.isSubscribed() == true) {
String sid = service.getSID();
return subscribe(service, sid, timeout);
}
Device rootDev = service.getRootDevice();
if (rootDev == null)
return false;
String ifAddress = rootDev.getInterfaceAddress();
SubscriptionRequest subReq = new SubscriptionRequest();
subReq.setSubscribeRequest(service, getEventSubCallbackURL(ifAddress), timeout);
SubscriptionResponse subRes = subReq.post();
if (subRes.isSuccessful() == true) {
service.setSID(subRes.getSID());
service.setTimeout(subRes.getTimeout());
return true;
}
service.clearSID();
return false;
}
public boolean subscribe(Service service)
{
return subscribe(service, Subscription.INFINITE_VALUE);
}
public boolean subscribe(Service service, String uuid, long timeout)
{
SubscriptionRequest subReq = new SubscriptionRequest();
subReq.setRenewRequest(service, uuid, timeout);
if (Debug.isOn() == true)
subReq.print();
SubscriptionResponse subRes = subReq.post();
if (Debug.isOn() == true)
subRes.print();
if (subRes.isSuccessful() == true) {
service.setSID(subRes.getSID());
service.setTimeout(subRes.getTimeout());
return true;
}
service.clearSID();
return false;
}
public boolean subscribe(Service service, String uuid)
{
return subscribe(service, uuid, Subscription.INFINITE_VALUE);
}
public boolean isSubscribed(Service service)
{
if (service == null)
return false;
return service.isSubscribed();
}
public boolean unsubscribe(Service service)
{
SubscriptionRequest subReq = new SubscriptionRequest();
subReq.setUnsubscribeRequest(service);
SubscriptionResponse subRes = subReq.post();
if (subRes.isSuccessful() == true) {
service.clearSID();
return true;
}
return false;
}
public void unsubscribe(Device device)
{
ServiceList serviceList = device.getServiceList();
int serviceCnt = serviceList.size();
for (int n=0; n<serviceCnt; n++) {
Service service = serviceList.getService(n);
if (service.hasSID() == true)
unsubscribe(service);
}
DeviceList childDevList = device.getDeviceList();
int childDevCnt = childDevList.size();
for (int n=0; n<childDevCnt; n++) {
Device cdev = childDevList.getDevice(n);
unsubscribe(cdev);
}
}
public void unsubscribe()
{
DeviceList devList = getDeviceList();
int devCnt = devList.size();
for (int n=0; n<devCnt; n++) {
Device dev = devList.getDevice(n);
unsubscribe(dev);
}
}
////////////////////////////////////////////////
// getSubscriberService
////////////////////////////////////////////////
public Service getSubscriberService(String uuid)
{
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;
}
////////////////////////////////////////////////
// getSubscriberService
////////////////////////////////////////////////
public void renewSubscriberService(Device dev, long timeout)
{
ServiceList serviceList = dev.getServiceList();
int serviceCnt = serviceList.size();
for (int n=0; n<serviceCnt; n++) {
Service service = serviceList.getService(n);
if (service.isSubscribed() == false)
continue;
String sid = service.getSID();
boolean isRenewed = subscribe(service, sid, timeout);
if (isRenewed == false)
subscribe(service, timeout);
}
DeviceList cdevList = dev.getDeviceList();
int cdevCnt = cdevList.size();
for (int n=0; n<cdevCnt; n++) {
Device cdev = cdevList.getDevice(n);
renewSubscriberService(cdev, timeout);
}
}
public void renewSubscriberService(long timeout)
{
DeviceList devList = getDeviceList();
int devCnt = devList.size();
for (int n=0; n<devCnt; n++) {
Device dev = devList.getDevice(n);
renewSubscriberService(dev, timeout);
}
}
public void renewSubscriberService()
{
renewSubscriberService(Subscription.INFINITE_VALUE);
}
////////////////////////////////////////////////
// Subscriber
////////////////////////////////////////////////
private RenewSubscriber renewSubscriber;
public void setRenewSubscriber(RenewSubscriber sub)
{
renewSubscriber = sub;
}
public RenewSubscriber getRenewSubscriber()
{
return renewSubscriber;
}
////////////////////////////////////////////////
// run
////////////////////////////////////////////////
public boolean start(String target, int mx)
{
stop();
////////////////////////////////////////
// HTTP Server
////////////////////////////////////////
int retryCnt = 0;
int bindPort = getHTTPPort();
HTTPServerList httpServerList = getHTTPServerList();
while (httpServerList.open(bindPort) == false) {
retryCnt++;
if (UPnP.SERVER_RETRY_COUNT < retryCnt) {
Debug.warning("Failed to open HTTP event listener port " + bindPort);
// I2P do we really need this, or can we just break ?
return false;
}
// I2P go down not up so we don't run into other I2P things
setHTTPPort(bindPort - 1);
bindPort = getHTTPPort();
}
httpServerList.addRequestListener(this);
httpServerList.start();
////////////////////////////////////////
// Notify Socket
////////////////////////////////////////
SSDPNotifySocketList ssdpNotifySocketList = getSSDPNotifySocketList();
if (ssdpNotifySocketList.open() == false) {
Debug.warning("Failed to open SSDP notify port 1900");
return false;
}
ssdpNotifySocketList.setControlPoint(this);
ssdpNotifySocketList.start();
////////////////////////////////////////
// SeachResponse Socket
////////////////////////////////////////
int ssdpPort = getSSDPPort();
retryCnt = 0;
SSDPSearchResponseSocketList ssdpSearchResponseSocketList = getSSDPSearchResponseSocketList();
while (ssdpSearchResponseSocketList.open(ssdpPort) == false) {
retryCnt++;
if (UPnP.SERVER_RETRY_COUNT < retryCnt) {
Debug.warning("Failed to open SSDP search response port " + ssdpPort);
return false;
}
// I2P go down not up so we don't run into other I2P things
setSSDPPort(ssdpPort - 1);
ssdpPort = getSSDPPort();
}
ssdpSearchResponseSocketList.setControlPoint(this);
ssdpSearchResponseSocketList.start();
////////////////////////////////////////
// search root devices
////////////////////////////////////////
search(target, mx);
////////////////////////////////////////
// Disposer
////////////////////////////////////////
Disposer disposer = new Disposer(this);
setDeviceDisposer(disposer);
disposer.start();
////////////////////////////////////////
// Subscriber
////////////////////////////////////////
if (isNMPRMode() == true) {
RenewSubscriber renewSub = new RenewSubscriber(this);
setRenewSubscriber(renewSub);
renewSub.start();
}
return true;
}
public boolean start(String target)
{
return start(target, SSDP.DEFAULT_MSEARCH_MX);
}
public boolean start()
{
return start(ST.ROOT_DEVICE, SSDP.DEFAULT_MSEARCH_MX);
}
public boolean stop()
{
unsubscribe();
SSDPNotifySocketList ssdpNotifySocketList = getSSDPNotifySocketList();
ssdpNotifySocketList.stop();
ssdpNotifySocketList.close();
ssdpNotifySocketList.clear();
SSDPSearchResponseSocketList ssdpSearchResponseSocketList = getSSDPSearchResponseSocketList();
ssdpSearchResponseSocketList.stop();
ssdpSearchResponseSocketList.close();
ssdpSearchResponseSocketList.clear();
HTTPServerList httpServerList = getHTTPServerList();
httpServerList.stop();
httpServerList.close();
httpServerList.clear();
////////////////////////////////////////
// Disposer
////////////////////////////////////////
Disposer disposer = getDeviceDisposer();
if (disposer != null) {
disposer.stop();
setDeviceDisposer(null);
}
////////////////////////////////////////
// Subscriber
////////////////////////////////////////
RenewSubscriber renewSub = getRenewSubscriber();
if (renewSub != null) {
renewSub.stop();
setRenewSubscriber(null);
}
// I2P so we will re-notify on restart
DeviceList dl = getDeviceList();
for (int i = 0; i < dl.size(); i++) {
removeDevice(dl.getDevice(i));
}
return true;
}
////////////////////////////////////////////////
// userData
////////////////////////////////////////////////
private Object userData = null;
public void setUserData(Object data)
{
userData = data;
}
public Object getUserData()
{
return userData;
}
////////////////////////////////////////////////
// print
////////////////////////////////////////////////
public void print()
{
DeviceList devList = getDeviceList();
int devCnt = devList.size();
Debug.message("Device Num = " + devCnt);
for (int n=0; n<devCnt; n++) {
Device dev = devList.getDevice(n);
Debug.message("[" + n + "] " + dev.getFriendlyName() + ", " + dev.getLeaseTime() + ", " + dev.getElapsedTime());
}
}
}