An InternetGatewayDevice connects a LAN to a WAN, and through UPnP supports the monitoring and configuration of LAN and WAN interfaces. Typically this functionality is used for NAT port mapping: A client application on the LAN wants to receive network connections from a WAN host, so it has to create a port forwarding and mapping on the LAN router.
Cling Support contains all the neccessary functionality, creating a port mapping on all NAT routers on a network requires only three lines of code:
PortMapping desiredMapping =
new PortMapping(
8123,
"192.168.0.123",
PortMapping.Protocol.TCP,
"My Port Mapping"
);
UpnpService upnpService =
new UpnpServiceImpl(
new PortMappingListener(desiredMapping)
);
upnpService.getControlPoint().search();
The first line creates a port mapping configuration with the external/internal port, an internal host IP, the protocol and an optional description.
The second line starts the UPnP service with a special listener. This listener
will add the port mapping on any InternetGatewayDevice with a WANIPConnection
or a WANPPPConnection service as soon as it is discovered. You should immediately start
a ControlPoint#search() for all devices on your network, this triggers a response
and discovery of all NAT routers, activating the port mapping.
The listener will also delete the port mapping when you stop the UPnP stack through
UpnpService#shutdown(), usually before your application quits. If you forget
to shutdown the stack the port mapping will remain on the InternetGatewayDevice
- the default lease duration is 0!
If anything goes wrong, log messages with WARNING level will be created on the
category org.fourthline.cling.support.igd.PortMappingListener. You can override the
PortMappingListener#handleFailureMessage(String) method to customize this behavior.
Alternatively, you can manually add and delete port mappings on an already discovered device with the following ready-to-use action callbacks:
Service service = device.findService(new UDAServiceId("WANIPConnection"));
upnpService.getControlPoint().execute(
new PortMappingAdd(service, desiredMapping) {
@Override
public void success(ActionInvocation invocation) {
// All OK
}
@Override
public void failure(ActionInvocation invocation,
UpnpResponse operation,
String defaultMsg) {
// Something is wrong
}
}
);
assertEquals(mapping[0].getInternalClient(), "192.168.0.123");
assertEquals(mapping[0].getInternalPort().getValue().longValue(), 8123);
assertTrue(mapping[0].isEnabled());
upnpService.getControlPoint().execute(
new PortMappingDelete(service, desiredMapping) {
@Override
public void success(ActionInvocation invocation) {
// All OK
}
@Override
public void failure(ActionInvocation invocation,
UpnpResponse operation,
String defaultMsg) {
// Something is wrong
}
}
);
The current connection information, including status, uptime, and last error message can be retrieved from a WAN*Connection service with the following callback:
Service service = device.findService(new UDAServiceId("WANIPConnection"));
upnpService.getControlPoint().execute(
new GetStatusInfo(service) {
@Override
protected void success(Connection.StatusInfo statusInfo) {
assertEquals(statusInfo.getStatus(), Connection.Status.Connected);
assertEquals(statusInfo.getUptimeSeconds(), 1000);
assertEquals(statusInfo.getLastError(), Connection.Error.ERROR_NONE);
}
@Override
public void failure(ActionInvocation invocation,
UpnpResponse operation,
String defaultMsg) {
// Something is wrong
}
}
);
Additionally, a callback for obtaining the external IP address of a connection is available:
Service service = device.findService(new UDAServiceId("WANIPConnection"));
upnpService.getControlPoint().execute(
new GetExternalIP(service) {
@Override
protected void success(String externalIPAddress) {
assertEquals(externalIPAddress, "123.123.123.123");
}
@Override
public void failure(ActionInvocation invocation,
UpnpResponse operation,
String defaultMsg) {
// Something is wrong
}
}
);