org.cybergarage.upnp.ssdp.SSDPNotifySocket Maven / Gradle / Ivy
/******************************************************************
*
* CyberUPnP for Java
*
* Copyright (C) Satoshi Konno 2002-2003
*
* File: SSDPNotifySocket.java
*
* Revision;
*
* 11/20/02
* - first revision.
* 05/13/03
* - Added support for IPv6.
* 02/20/04
* - Inma Marin Lopez
* - Added a multicast filter using the SSDP pakcet.
* 04/20/05
* - Mikael Hakman
* - Handle receive() returning null.
* - Added close() in stop().
* 08/23/07
* - Thanks for Kazuyuki Shudo
* - Changed run() to catch IOException of HTTPMUSocket::receive().
* 01/31/08
* - Changed start() not to abort when the interface infomation is null on Android m3-rc37a.
*
******************************************************************/
package org.cybergarage.upnp.ssdp;
import java.net.*;
import java.io.IOException;
import org.cybergarage.net.*;
import org.cybergarage.http.*;
import org.cybergarage.upnp.*;
import org.cybergarage.util.Debug;
/**
*
* This class identifies a SSDP socket only for notifing packet.
*
* @author Satoshi "skonno" Konno
* @author Stefano "Kismet" Lenzi
* @version 1.8
*
*/
public class SSDPNotifySocket extends HTTPMUSocket implements Runnable
{
private boolean useIPv6Address;
////////////////////////////////////////////////
// Constructor
////////////////////////////////////////////////
public SSDPNotifySocket(String bindAddr) throws IOException
{
String addr = SSDP.ADDRESS;
useIPv6Address = false;
if (HostInterface.isIPv6Address(bindAddr) == true) {
addr = SSDP.getIPv6Address();
useIPv6Address = true;
}
boolean ok = open(addr, SSDP.PORT, bindAddr);
if (!ok)
throw new IOException("Bind to " + bindAddr + " failed");
Debug.message("Opened SSDP notify socket at " + bindAddr + ':' + SSDP.PORT);
setControlPoint(null);
}
////////////////////////////////////////////////
// ControlPoint
////////////////////////////////////////////////
private ControlPoint controlPoint = null;
public void setControlPoint(ControlPoint ctrlp)
{
this.controlPoint = ctrlp;
}
public ControlPoint getControlPoint()
{
return controlPoint;
}
/**
* This method send a {@link SSDPNotifyRequest} over {@link SSDPNotifySocket}
*
* @param req the {@link SSDPNotifyRequest} to send
* @return true if and only if the trasmission succeced
* Because it rely on UDP doesn't mean that it's also recieved
*/
public boolean post(SSDPNotifyRequest req)
{
String ssdpAddr = SSDP.ADDRESS;
if (useIPv6Address == true)
ssdpAddr = SSDP.getIPv6Address();
req.setHost(ssdpAddr, SSDP.PORT);
return post((HTTPRequest)req);
}
////////////////////////////////////////////////
// run
////////////////////////////////////////////////
private Thread deviceNotifyThread = null;
public void run()
{
Thread thisThread = Thread.currentThread();
ControlPoint ctrlPoint = getControlPoint();
while (deviceNotifyThread == thisThread) {
Thread.yield();
// Thanks for Kazuyuki Shudo (08/23/07)
SSDPPacket packet = null;
try {
packet = receive();
}
catch (IOException e) {
break;
}
// Thanks for Mikael Hakman (04/20/05)
if (packet == null)
continue;
// Thanks for Inma (02/20/04)
InetAddress maddr = getMulticastInetAddress();
InetAddress pmaddr = packet.getHostInetAddress();
if (maddr.equals(pmaddr) == false) {
// I2P
//Debug.warning("Invalidate Multicast Recieved : " + maddr + "," + pmaddr);
continue;
}
//TODO Must be performed on a different Thread in order to prevent UDP packet losses.
if (ctrlPoint != null)
ctrlPoint.notifyReceived(packet);
}
}
public void start(){
StringBuffer name = new StringBuffer("Cyber.SSDPNotifySocket/");
String localAddr = this.getLocalAddress();
// localAddr is null on Android m3-rc37a (01/30/08)
if (localAddr != null && 0 < localAddr.length()) {
// I2P hide address from thread dumps
//name.append(this.getLocalAddress()).append(':');
//name.append(this.getLocalPort()).append(" -> ");
name.append(this.getMulticastAddress()).append(':');
name.append(this.getMulticastPort());
}
deviceNotifyThread = new Thread(this,name.toString());
deviceNotifyThread.start();
}
public void stop()
{
// Thanks for Mikael Hakman (04/20/05)
close();
deviceNotifyThread = null;
}
}