/**
* UPnP PortMapper - A tool for managing port forwardings via UPnP
* Copyright (C) 2015 Christoph Pirkl <christoph at users.sourceforge.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.chris.portmapper.router.cling;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
import org.fourthline.cling.model.meta.Device;
import org.fourthline.cling.model.meta.Service;
import org.fourthline.cling.model.types.DeviceType;
import org.fourthline.cling.model.types.ServiceType;
import org.fourthline.cling.model.types.UDADeviceType;
import org.fourthline.cling.model.types.UDAServiceType;
import org.fourthline.cling.registry.DefaultRegistryListener;
import org.fourthline.cling.registry.Registry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ClingRegistryListener extends DefaultRegistryListener {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
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);
private final SynchronousQueue<Service<?, ?>> foundServices;
public ClingRegistryListener() {
this.foundServices = new SynchronousQueue<>();
}
public Service<?, ?> waitForServiceFound(final long timeout, final TimeUnit unit) {
try {
return foundServices.poll(timeout, unit);
} catch (final InterruptedException e) {
logger.warn("Interrupted when waiting for a service");
return null;
}
}
@Override
public void deviceAdded(final Registry registry, @SuppressWarnings("rawtypes") final Device device) {
@SuppressWarnings("unchecked")
final Service<?, ?> connectionService = discoverConnectionService(device);
if (connectionService == null) {
return;
}
logger.debug("Found connection service {}", connectionService);
foundServices.offer(connectionService);
}
protected Service<?, ?> discoverConnectionService(@SuppressWarnings("rawtypes") final Device<?, Device, ?> device) {
if (!device.getType().equals(IGD_DEVICE_TYPE)) {
logger.debug("Found service of wrong type {}, expected {}.", device.getType(), IGD_DEVICE_TYPE);
return null;
}
@SuppressWarnings("rawtypes")
final Device[] connectionDevices = device.findDevices(CONNECTION_DEVICE_TYPE);
if (connectionDevices.length == 0) {
logger.debug("IGD doesn't support '{}': {}", CONNECTION_DEVICE_TYPE, device);
return null;
}
logger.debug("Found {} devices", connectionDevices.length);
return findConnectionService(connectionDevices);
}
@SuppressWarnings("rawtypes")
private Service<?, ?> findConnectionService(final Device[] connectionDevices) {
for (final Device connectionDevice : connectionDevices) {
final Service ipConnectionService = connectionDevice.findService(IP_SERVICE_TYPE);
final Service pppConnectionService = connectionDevice.findService(PPP_SERVICE_TYPE);
if (ipConnectionService != null) {
logger.debug("Device {} supports ip service type: {}", connectionDevice, ipConnectionService);
return ipConnectionService;
}
if (pppConnectionService != null) {
logger.debug("Device {} supports ppp service type: {}", connectionDevice, pppConnectionService);
return pppConnectionService;
}
logger.debug("IGD {} doesn't support IP or PPP WAN connection service", connectionDevice);
}
logger.debug("None of the {} devices supports IP or PPP WAN connections", connectionDevices.length);
return null;
}
}