[freenet-cvs] r13325 - trunk/plugins/UPnP

nextgens at freenetproject.org nextgens at freenetproject.org
Wed May 23 00:08:07 UTC 2007


Author: nextgens
Date: 2007-05-23 00:08:07 +0000 (Wed, 23 May 2007)
New Revision: 13325

Modified:
   trunk/plugins/UPnP/UPnP.java
Log:
UPnP: import some working code from Limewire (GPL too) ; now the plugin gets the external ip address \o/

Modified: trunk/plugins/UPnP/UPnP.java
===================================================================
--- trunk/plugins/UPnP/UPnP.java	2007-05-22 23:44:05 UTC (rev 13324)
+++ trunk/plugins/UPnP/UPnP.java	2007-05-23 00:08:07 UTC (rev 13325)
@@ -3,7 +3,7 @@
  * http://www.gnu.org/ for further details of the GPL. */
 package plugins.UPnP;
 
-import java.util.LinkedList;
+import java.util.Iterator;
 
 import plugins.UPnP.org.cybergarage.upnp.Action;
 import plugins.UPnP.org.cybergarage.upnp.ActionList;
@@ -16,7 +16,6 @@
 import plugins.UPnP.org.cybergarage.upnp.ServiceList;
 import plugins.UPnP.org.cybergarage.upnp.ServiceStateTable;
 import plugins.UPnP.org.cybergarage.upnp.StateVariable;
-import plugins.UPnP.org.cybergarage.upnp.control.QueryRequest;
 import plugins.UPnP.org.cybergarage.upnp.device.DeviceChangeListener;
 import plugins.UPnP.org.cybergarage.upnp.xml.StateVariableData;
 import freenet.pluginmanager.FredPlugin;
@@ -31,35 +30,104 @@
  * 
  * @author Florent Daignière <nextgens at freenetproject.org>
  *
+ *
+ * some code has been borrowed from Limewire : @see com.limegroup.gnutella.UPnPManager
+ *
  * @see http://www.upnp.org/
  * @see http://en.wikipedia.org/wiki/Universal_Plug_and_Play
  */ 
-public class UPnP implements FredPluginHTTP, FredPlugin, FredPluginThreadless, DeviceChangeListener {
-	private ControlPoint upnpControlPoint;
-	private final LinkedList igdList = new LinkedList();
+public class UPnP extends ControlPoint implements FredPluginHTTP, FredPlugin, FredPluginThreadless, DeviceChangeListener {
+	
+	/** some schemas */
+	private static final String ROUTER_DEVICE = "urn:schemas-upnp-org:device:InternetGatewayDevice:1";
+	private static final String WAN_DEVICE = "urn:schemas-upnp-org:device:WANDevice:1";
+	private static final String WANCON_DEVICE = "urn:schemas-upnp-org:device:WANConnectionDevice:1";
+	private static final String WAN_IP_CONNECTION = "urn:schemas-upnp-org:service:WANIPConnection:1";
 
+	private volatile Device _router;
+	private volatile Service _service;
+	private final Object lock = new Object();
+	
+	public UPnP() {
+		super();
+		addDeviceChangeListener(this);
+	}
+	
 	public void runPlugin(PluginRespirator pr) {
-		upnpControlPoint = new ControlPoint();
-		upnpControlPoint.addDeviceChangeListener(this);
-		upnpControlPoint.start();
+		start();
 	}
 
 	public void terminate() {
-		upnpControlPoint.stop();
+		stop();
 	}
 	
-	public void deviceAdded(Device dev ){
-		if(!"InternetGatewayDevice".equals(dev.getDeviceType()))
-			return;
-		
-		System.out.println("##################Detected a new gateway ! "+dev.getFriendlyName());
-		igdList.add(dev);
+	public void deviceAdded(Device dev ) {
+		synchronized (lock) {
+			if(isNATPresent())
+				return; // We don't handle more than one IGD.
+			
+			if(!ROUTER_DEVICE.equals(dev.getDeviceType()) || !dev.isRootDevice())
+				return;
+			_router = dev;
+			discoverService();
+		}
 	}
 	
+	/**
+	 * Traverses the structure of the router device looking for the port mapping service.
+	 */
+	private void discoverService() {
+		synchronized (lock) {
+			for (Iterator iter = _router.getDeviceList().iterator();iter.hasNext();) {
+				Device current = (Device)iter.next();
+				if (!current.getDeviceType().equals(WAN_DEVICE))
+					continue;
+
+				DeviceList l = current.getDeviceList();
+				for (int i=0;i<current.getDeviceList().size();i++) {
+					Device current2 = l.getDevice(i);
+
+					if (!current2.getDeviceType().equals(WANCON_DEVICE))
+						continue;
+
+					_service = current2.getService(WAN_IP_CONNECTION);
+					return;
+				}
+			}
+		}
+	}
+	
 	public void deviceRemoved(Device dev ){
-		igdList.remove(dev);
+		synchronized (lock) {
+			if(_router.equals(dev)) {
+				_router = null;
+				_service = null;
+			}
+		}
 	}
 	
+	/**
+	 * @return whether we are behind an UPnP-enabled NAT/router
+	 */
+	public boolean isNATPresent() {
+	    return _router != null && _service != null;
+	}
+
+	/**
+	 * @return the external address the NAT thinks we have.  Blocking.
+	 * null if we can't find it.
+	 */
+	public String getNATAddress() {
+        if (!isNATPresent())
+            return null;
+        
+        Action getIP = _service.getAction("GetExternalIPAddress");
+		if(getIP == null || !getIP.postControlAction())
+			return null;
+		
+		return ((Argument)getIP.getOutputArgumentList().getArgument("NewExternalIPAddress")).getValue();
+	}
+	
 	private void listStateTable(Service serv, StringBuffer sb) {
 		ServiceStateTable table = serv.getServiceStateTable();
 		sb.append("<div><small>");
@@ -94,6 +162,15 @@
 		return (data == null ? "null" : data.getValue());
 	}
 	
+	private String toString(String action, String Argument, Service serv) {
+		Action getIP = serv.getAction(action);
+		if(getIP == null || !getIP.postControlAction())
+			return null;
+		
+		Argument ret = getIP.getOutputArgumentList().getArgument(Argument);
+		return ret.getValue();
+	}
+	
 	private void listSubServices(Device dev, StringBuffer sb) {
 		ServiceList sl = dev.getServiceList();
 		for(int i=0; i<sl.size(); i++) {
@@ -134,15 +211,11 @@
 				StateVariable defaultConnectionService = serv.getStateVariable("DefaultConnectionService");
 				if(defaultConnectionService != null)
 					sb.append("DefaultConnectionService: " + toString(defaultConnectionService.getStateVariableData()));
-			}else if("urn:schemas-upnp-org:service:WANIPConnection:1".equals(serv.getServiceType())){
-				StateVariable linkStatus = serv.getStateVariable("ConnectionStatus");
-				StateVariable externalIPAddress = serv.getStateVariable("ExternalIPAddress");
-				
+			}else if(WAN_IP_CONNECTION.equals(serv.getServiceType())){
 				sb.append("WANIPConnection");
-				if(linkStatus != null)
-					sb.append(" status: " + toString(linkStatus.getStateVariableData()));
-				if(externalIPAddress != null)
-					sb.append(" external IP: " + toString(externalIPAddress.getStateVariableData()) + "<br>");
+				sb.append(" status: " + toString("GetStatusInfo", "NewConnectionStatus", serv));
+				sb.append(" type: " + toString("GetConnectionTypeInfo", "NewConnectionType", serv));
+				sb.append(" external IP: " + toString("GetExternalIPAddress", "NewExternalIPAddress", serv) + "<br>");
 			}else if("urn:schemas-upnp-org:service:WANEthernetLinkConfig:1".equals(serv.getServiceType())){
 				StateVariable linkStatus = serv.getStateVariable("EthernetLinkStatus");
 				
@@ -185,14 +258,13 @@
 	public String handleHTTPGet(HTTPRequest request) throws PluginHTTPException {
 		StringBuffer sb = new StringBuffer();
 		sb.append("<html><body>");
-		sb.append(igdList.size() + "<br>");
-		DeviceList rootDevList = upnpControlPoint.getDeviceList();
 		
-		for(int i=0; i<rootDevList.size(); i++) {
-			Device dev = rootDevList.getDevice(i);
-			if(!"urn:schemas-upnp-org:device:InternetGatewayDevice:1".equals(dev.getDeviceType())) continue;
-			listSubDev("WANDevice", dev, sb);
-		}
+		sb.append("<h2>Our current ip address is : " + getNATAddress() + "</h2>");
+		
+		if(_router != null)
+			listSubDev("WANDevice", _router, sb);
+		else
+			sb.append("No UPnP aware device has been found!");
 
 		sb.append("</body></html>");
 		return sb.toString();
@@ -208,4 +280,4 @@
 		// TODO Auto-generated method stub
 		return null;
 	}
-}
+}
\ No newline at end of file




More information about the cvs mailing list