Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JENKINS-59094] Jenkins connection failure with tunneling #345

Merged
merged 9 commits into from
Sep 6, 2019
27 changes: 19 additions & 8 deletions src/main/java/org/jenkinsci/remoting/engine/HostPort.java
Original file line number Diff line number Diff line change
@@ -1,28 +1,38 @@
package org.jenkinsci.remoting.engine;

class HostPort {

private static final int PORT_MIN = 0;
private static final int PORT_MAX = (1 << 16) -1;
jeffret-b marked this conversation as resolved.
Show resolved Hide resolved

private String host;
private int port;

public HostPort(String value) {
splitHostPort(value);
public HostPort(String value, String defaultHost, int defaultPort) {
oleg-nenashev marked this conversation as resolved.
Show resolved Hide resolved
splitHostPort(value, defaultHost, defaultPort);
}

private void splitHostPort(String value) {
private void splitHostPort(String value, String defaultHost, int defaultPort) {
String hostPortValue = value.trim();
if (hostPortValue.charAt(0) == '[') {
extractIPv6(hostPortValue);
return;
}
int portSeparator = hostPortValue.lastIndexOf(':');
if (portSeparator <= 0) {
if (portSeparator < 0) {
throw new IllegalArgumentException("Invalid HOST:PORT value: " + value);
}
host = hostPortValue.substring(0, portSeparator).trim();
if (host.isEmpty()) {
throw new IllegalArgumentException("Invalid HOST:PORT value: " + value);
String hostValue = hostPortValue.substring(0, portSeparator).trim();
host = hostValue.length() > 0 ? hostValue : defaultHost;
String portString = hostPortValue.substring(portSeparator + 1).trim();
if (portString.length() > 0) {
port = Integer.parseInt(portString);
jeffret-b marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unhandled NumberFormatException

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NumberFormatException was unhandled in prior versions as well. I checked it by running 3.33 (before any of these changes) with a port value that is not a number. The agent fails on startup with the NumberFormatException.

Do you think we should change that behavior here now? Should it throw a different exception? Or log and ignore the error?

if (port <= PORT_MIN || port > PORT_MAX) {
throw new IllegalArgumentException("Invalid port value: " + value);
jeffret-b marked this conversation as resolved.
Show resolved Hide resolved
}
} else {
port = defaultPort;
}
port = Integer.parseInt(hostPortValue.substring(portSeparator + 1).trim());
}

private void extractIPv6(String hostPortValue) {
Expand All @@ -45,4 +55,5 @@ public String getHost() {
public int getPort() {
return port;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public JnlpAgentEndpoint resolve() throws IOException {
} catch (InvalidKeySpecException e) {
throw new IOException("Invalid instanceIdentity.");
}
HostPort hostPort = new HostPort(directionConnection);
HostPort hostPort = new HostPort(directionConnection, null, 0);

return new JnlpAgentEndpoint(hostPort.getHost(), hostPort.getPort(), identity, protocols);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ public int compare(String o1, String o2) {
}
});
if (tunnel != null) {
HostPort hostPort = new HostPort(tunnel);
HostPort hostPort = new HostPort(tunnel, host, port);
host = hostPort.getHost();
port = hostPort.getPort();
}
Expand Down
65 changes: 45 additions & 20 deletions src/test/java/org/jenkinsci/remoting/engine/HostPortTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,91 +9,116 @@ public class HostPortTest {

@Test
public void testHostname() {
HostPort hostPort = new HostPort("hostname:5555");
HostPort hostPort = new HostPort("hostname:5555", null, -1);
assertThat(hostPort.getHost(), is("hostname"));
assertThat(hostPort.getPort(), is(5555));
}

@Test
public void testFqdn() {
HostPort hostPort = new HostPort("hostname.example.com:5555");
HostPort hostPort = new HostPort("hostname.example.com:5555", null, -1);
assertThat(hostPort.getHost(), is("hostname.example.com"));
assertThat(hostPort.getPort(), is(5555));
}

@Test
public void testIPv4() {
HostPort hostPort = new HostPort("1.2.3.4:5555");
HostPort hostPort = new HostPort("1.2.3.4:5555", null, -1);
assertThat(hostPort.getHost(), is("1.2.3.4"));
assertThat(hostPort.getPort(), is(5555));
}

@Test
public void testHostWhitespace() {
HostPort hostPort = new HostPort(" 1.2.3.4 :5555");
HostPort hostPort = new HostPort(" 1.2.3.4 :5555", null, -1);
assertThat(hostPort.getHost(), is("1.2.3.4"));
assertThat(hostPort.getPort(), is(5555));
}

@Test
public void testPortWhitespace() {
HostPort hostPort = new HostPort("1.2.3.4: 5555 ");
HostPort hostPort = new HostPort("1.2.3.4: 5555 ", null, -1);
assertThat(hostPort.getHost(), is("1.2.3.4"));
assertThat(hostPort.getPort(), is(5555));
}

@Test
public void testIPv6() {
HostPort hostPort = new HostPort("[1:2::3:4]:5555");
HostPort hostPort = new HostPort("[1:2::3:4]:5555", null, -1);
assertThat(hostPort.getHost(), is("1:2::3:4"));
assertThat(hostPort.getPort(), is(5555));
}

@Test
public void testIPv6Whitespace() {
HostPort hostPort = new HostPort("[ 1:2::3:4 ]:5555");
HostPort hostPort = new HostPort("[ 1:2::3:4 ]:5555", null, -1);
assertThat(hostPort.getHost(), is("1:2::3:4"));
assertThat(hostPort.getPort(), is(5555));
}

@Test(expected = IllegalArgumentException.class)
public void testIPv6NoPort() {
new HostPort("[1:2::3:4]");
new HostPort("[1:2::3:4]", null, -1);
}

@Test(expected = IllegalArgumentException.class)
public void testUnclosedIPv6() {
new HostPort("[1:2::3:4:5555");
new HostPort("[1:2::3:4:5555", null, -1);
}

@Test(expected = IllegalArgumentException.class)
public void testInvalidPort() {
new HostPort("[1:2::3:4]:host");
new HostPort("[1:2::3:4]:host", null, -1);
}

@Test(expected = IllegalArgumentException.class)
public void testNoPort() {
new HostPort("hostname");
public void testNoSeparator() {
new HostPort("hostname", null, -1);
}

@Test(expected = IllegalArgumentException.class)
@Test
public void testNoHost() {
new HostPort(":5555");
HostPort hostPort = new HostPort(":5555", "hostname", -1);
assertThat(hostPort.getHost(), is("hostname"));
assertThat(hostPort.getPort(), is(5555));
}

@Test(expected = IllegalArgumentException.class)
@Test
public void testEmptyHost() {
new HostPort(" :5555");
HostPort hostPort = new HostPort(" :5555", "hostname", -1);
assertThat(hostPort.getHost(), is("hostname"));
assertThat(hostPort.getPort(), is(5555));
}

@Test(expected = IllegalArgumentException.class)
@Test
public void testEmptyPort() {
new HostPort("hostname: ");
HostPort hostPort = new HostPort("hostname: ", null, 7777);
assertThat(hostPort.getHost(), is("hostname"));
assertThat(hostPort.getPort(), is(7777));
}

@Test(expected = IllegalArgumentException.class)
@Test
public void testSeparatorNoPort() {
new HostPort("hostname:");
HostPort hostPort = new HostPort("hostname:", null, 7777);
assertThat(hostPort.getHost(), is("hostname"));
assertThat(hostPort.getPort(), is( 7777));
}

@Test(expected = IllegalArgumentException.class)
public void testNegativePort() {
new HostPort("hostname:-4", null, -1);
}

@Test(expected = IllegalArgumentException.class)
public void testPortTooHigh() {
new HostPort("hostname:100000", null, -1);
}

@Test
public void testOnlySeparator() {
HostPort hostPort = new HostPort(":", "hostname", 7777);
assertThat(hostPort.getHost(), is("hostname"));
assertThat(hostPort.getPort(), is( 7777));
}

}