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
