portmappinglistener.java

来自「android_UPNP_DLNA_控制点」· Java 代码 · 共 197 行

JAVA
197
字号
/* * Copyright (C) 2010 Teleal GmbH, Switzerland * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program.  If not, see <http://www.gnu.org/licenses/>. */package org.teleal.cling.support.igd;import org.teleal.cling.model.action.ActionInvocation;import org.teleal.cling.model.message.UpnpResponse;import org.teleal.cling.model.meta.Device;import org.teleal.cling.model.meta.Service;import org.teleal.cling.model.types.DeviceType;import org.teleal.cling.model.types.ServiceType;import org.teleal.cling.model.types.UDADeviceType;import org.teleal.cling.model.types.UDAServiceType;import org.teleal.cling.registry.DefaultRegistryListener;import org.teleal.cling.registry.Registry;import org.teleal.cling.support.igd.callback.PortMappingAdd;import org.teleal.cling.support.igd.callback.PortMappingDelete;import org.teleal.cling.support.model.PortMapping;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.logging.Logger;/** * Maintains UPnP port mappings on an InternetGatewayDevice automatically. * <p> * This listener will wait for discovered devices which support either * {@code WANIPConnection} or the {@code WANPPPConnection} service. As soon as any such * service is discovered, the desired port mapping will be created. When the UPnP service * is shutting down, all previously established port mappings with all services will * be deleted. * </p> * <p> * The following listener maps external WAN TCP port 8123 to internal host 10.0.0.2: * </p> * <pre>{@code * upnpService.getRegistry().addListener( *newPortMappingListener(newPortMapping(8123, "10.0.0.2",PortMapping.Protocol.TCP)) * );}</pre> * <p> * If all you need from the Cling UPnP stack is NAT port mapping, use the following idiom: * </p> * <pre>{@code * UpnpService upnpService = new UpnpServiceImpl( *     new PortMappingListener(new PortMapping(8123, "10.0.0.2", PortMapping.Protocol.TCP)) * ); * <p/> * upnpService.getControlPoint().search(new STAllHeader()); // Search for all devices * <p/> * upnpService.shutdown(); // When you no longer need the port mapping * }</pre> * * @author Christian Bauer */public class PortMappingListener extends DefaultRegistryListener {    private static final Logger log = Logger.getLogger(PortMappingListener.class.getName());    public static final DeviceType IGD_DEVICE_TYPE = new UDADeviceType("InternetGatewayDevice", 1);    public static final DeviceType CONNECTION_DEVICE_TYPE = new UDADeviceType("WANConnectionDevice", 1);    public static final ServiceType IP_SERVICE_TYPE = new UDAServiceType("WANIPConnection", 1);    public static final ServiceType PPP_SERVICE_TYPE = new UDAServiceType("WANPPPConnection", 1);    protected PortMapping[] portMappings;    // The key of the map is Service and equality is object identity, this is by-design    protected Map<Service, List<PortMapping>> activePortMappings = new HashMap();    public PortMappingListener(PortMapping portMapping) {        this(new PortMapping[]{portMapping});    }    public PortMappingListener(PortMapping[] portMappings) {        this.portMappings = portMappings;    }    @Override    synchronized public void deviceAdded(Registry registry, Device device) {        Service connectionService;        if ((connectionService = discoverConnectionService(device)) == null) return;        log.fine("Activating port mappings on: " + connectionService);        final List<PortMapping> activeForService = new ArrayList();        for (final PortMapping pm : portMappings) {            new PortMappingAdd(connectionService, registry.getUpnpService().getControlPoint(), pm) {                @Override                public void success(ActionInvocation invocation) {                    log.fine("Port mapping added: " + pm);                    activeForService.add(pm);                }                @Override                public void failure(ActionInvocation invocation, UpnpResponse operation, String defaultMsg) {                    handleFailureMessage("Failed to add port mapping: " + pm);                    handleFailureMessage("Reason: " + defaultMsg);                }            }.run(); // Synchronous!        }        activePortMappings.put(connectionService, activeForService);    }    @Override    synchronized public void deviceRemoved(Registry registry, Device device) {        for (Service service : device.findServices()) {            Iterator<Map.Entry<Service, List<PortMapping>>> it = activePortMappings.entrySet().iterator();            while (it.hasNext()) {                Map.Entry<Service, List<PortMapping>> activeEntry = it.next();                if (!activeEntry.getKey().equals(service)) continue;                if (activeEntry.getValue().size() > 0)                    handleFailureMessage("Device disappeared, couldn't delete port mappings: " + activeEntry.getValue().size());                it.remove();            }        }    }    @Override    synchronized public void beforeShutdown(Registry registry) {        for (Map.Entry<Service, List<PortMapping>> activeEntry : activePortMappings.entrySet()) {            final Iterator<PortMapping> it = activeEntry.getValue().iterator();            while (it.hasNext()) {                final PortMapping pm = it.next();                log.fine("Trying to delete port mapping on IGD: " + pm);                new PortMappingDelete(activeEntry.getKey(), registry.getUpnpService().getControlPoint(), pm) {                    @Override                    public void success(ActionInvocation invocation) {                        log.fine("Port mapping deleted: " + pm);                        it.remove();                    }                    @Override                    public void failure(ActionInvocation invocation, UpnpResponse operation, String defaultMsg) {                        handleFailureMessage("Failed to delete port mapping: " + pm);                        handleFailureMessage("Reason: " + defaultMsg);                    }                }.run(); // Synchronous!            }        }    }    protected Service discoverConnectionService(Device device) {        if (!device.getType().equals(IGD_DEVICE_TYPE)) {            return null;        }        Device[] connectionDevices = device.findDevices(CONNECTION_DEVICE_TYPE);        if (connectionDevices.length == 0) {            log.fine("IGD doesn't support '" + CONNECTION_DEVICE_TYPE + "': " + device);            return null;        }        Device connectionDevice = connectionDevices[0];        log.fine("Using first discovered WAN connection device: " + connectionDevice);        Service ipConnectionService = connectionDevice.findService(IP_SERVICE_TYPE);        Service pppConnectionService = connectionDevice.findService(PPP_SERVICE_TYPE);        if (ipConnectionService == null && pppConnectionService == null) {            log.fine("IGD doesn't support IP or PPP WAN connection service: " + device);        }        return ipConnectionService != null ? ipConnectionService : pppConnectionService;    }    protected void handleFailureMessage(String s) {        log.warning(s);    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?