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 } } );