Support IGD v2 port mappings (#367) · jupnp/jupnp@1e77668 · GitHub
Skip to content

Commit 1e77668

Browse files
Support IGD v2 port mappings (#367)
Handle newer gateways and routers that describe ports differently. Fixes #366 Signed-off-by: Giovanni Menzano <giovanni.menzano@gmail.com>
1 parent b7b8729 commit 1e77668

5 files changed

Lines changed: 197 additions & 4 deletions

File tree

‎bundles/org.jupnp.support/src/main/java/org/jupnp/support/igd/PortMappingListener.java‎

Lines changed: 1 addition & 1 deletion

‎bundles/org.jupnp.support/src/main/java/org/jupnp/support/igd/callback/PortMappingAdd.java‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package org.jupnp.support.igd.callback;
1717

18+
import java.util.Objects;
19+
1820
import org.jupnp.controlpoint.ActionCallback;
1921
import org.jupnp.controlpoint.ControlPoint;
2022
import org.jupnp.model.action.ActionInvocation;
@@ -38,10 +40,10 @@ protected PortMappingAdd(Service<?, ?> service, ControlPoint controlPoint, PortM
3840

3941
this.portMapping = portMapping;
4042

41-
getActionInvocation().setInput("NewExternalPort", portMapping.getExternalPort());
43+
getActionInvocation().setInput("NewExternalPort", Objects.toString(portMapping.getExternalPort(), null));
4244
getActionInvocation().setInput("NewProtocol", portMapping.getProtocol());
4345
getActionInvocation().setInput("NewInternalClient", portMapping.getInternalClient());
44-
getActionInvocation().setInput("NewInternalPort", portMapping.getInternalPort());
46+
getActionInvocation().setInput("NewInternalPort", Objects.toString(portMapping.getInternalPort(), null));
4547
getActionInvocation().setInput("NewLeaseDuration", portMapping.getLeaseDurationSeconds());
4648
getActionInvocation().setInput("NewEnabled", portMapping.isEnabled());
4749
if (portMapping.hasRemoteHost()) {

‎bundles/org.jupnp.support/src/main/java/org/jupnp/support/igd/callback/PortMappingDelete.java‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package org.jupnp.support.igd.callback;
1717

18+
import java.util.Objects;
19+
1820
import org.jupnp.controlpoint.ActionCallback;
1921
import org.jupnp.controlpoint.ControlPoint;
2022
import org.jupnp.model.action.ActionInvocation;
@@ -38,7 +40,7 @@ protected PortMappingDelete(Service<?, ?> service, ControlPoint controlPoint, Po
3840

3941
this.portMapping = portMapping;
4042

41-
getActionInvocation().setInput("NewExternalPort", portMapping.getExternalPort());
43+
getActionInvocation().setInput("NewExternalPort", Objects.toString(portMapping.getExternalPort(), null));
4244
getActionInvocation().setInput("NewProtocol", portMapping.getProtocol());
4345
if (portMapping.hasRemoteHost()) {
4446
getActionInvocation().setInput("NewRemoteHost", portMapping.getRemoteHost());
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright (C) 2011-2026 4th Line GmbH, Switzerland and others
3+
*
4+
* The contents of this file are subject to the terms of the
5+
* Common Development and Distribution License Version 1 or later
6+
* ("CDDL") (collectively, the "License"). You may not use this file
7+
* except in compliance with the License. See LICENSE.txt for more
8+
* information.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13+
*
14+
* SPDX-License-Identifier: CDDL-1.0
15+
*/
16+
package org.jupnp.support.igd;
17+
18+
import static org.junit.jupiter.api.Assertions.assertSame;
19+
20+
import java.net.InetAddress;
21+
import java.net.URI;
22+
import java.net.URL;
23+
24+
import org.junit.jupiter.api.Test;
25+
import org.jupnp.model.meta.DeviceDetails;
26+
import org.jupnp.model.meta.RemoteDevice;
27+
import org.jupnp.model.meta.RemoteDeviceIdentity;
28+
import org.jupnp.model.meta.RemoteService;
29+
import org.jupnp.model.meta.Service;
30+
import org.jupnp.model.types.UDADeviceType;
31+
import org.jupnp.model.types.UDAServiceId;
32+
import org.jupnp.model.types.UDAServiceType;
33+
import org.jupnp.model.types.UDN;
34+
import org.jupnp.support.model.PortMapping;
35+
36+
class PortMappingListenerTest {
37+
38+
@Test
39+
void discoversVersionTwoInternetGatewayDevice() throws Exception {
40+
final RemoteService connectionService = new RemoteService(new UDAServiceType("WANIPConnection", 2),
41+
new UDAServiceId("WANIPConnection"), URI.create("service.xml"), URI.create("control"),
42+
URI.create("events"));
43+
final RemoteDevice connectionDevice = new RemoteDevice(identity("connection"),
44+
new UDADeviceType("WANConnectionDevice", 2), new DeviceDetails("WAN connection"),
45+
new RemoteService[] { connectionService });
46+
final RemoteDevice wanDevice = new RemoteDevice(identity("wan"), new UDADeviceType("WANDevice", 2),
47+
new DeviceDetails("WAN device"), new RemoteService[0], new RemoteDevice[] { connectionDevice });
48+
final RemoteDevice gateway = new RemoteDevice(identity("gateway"),
49+
new UDADeviceType("InternetGatewayDevice", 2), new DeviceDetails("Internet gateway"),
50+
new RemoteService[0], new RemoteDevice[] { wanDevice });
51+
52+
final Service<?, ?> discovered = new PortMappingListener(new PortMapping()).discoverConnectionService(gateway);
53+
54+
assertSame(connectionService, discovered);
55+
}
56+
57+
private RemoteDeviceIdentity identity(final String name) throws Exception {
58+
final URL descriptorUrl = new URL("http://127.0.0.1/" + name + ".xml");
59+
final InetAddress localAddress = InetAddress.getLoopbackAddress();
60+
return new RemoteDeviceIdentity(new UDN("uuid:" + name), 1800, descriptorUrl, null, localAddress);
61+
}
62+
}
Lines changed: 127 additions & 0 deletions

0 commit comments

Comments
 (0)