Skip to content

Commit

Permalink
[JENKINS-6167] Support JNLP slave connection via HTTP proxy
Browse files Browse the repository at this point in the history
We get proxy setting from http.proxyHost property or http_proxy
environment variable.
  • Loading branch information
shirosaki committed Oct 20, 2014
1 parent 8227da4 commit 8c875cb
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 3 deletions.
44 changes: 42 additions & 2 deletions src/main/java/hudson/remoting/Engine.java
Expand Up @@ -33,8 +33,12 @@
import java.io.InputStream;
import java.io.ByteArrayOutputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.URL;
import java.net.MalformedURLException;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
Expand Down Expand Up @@ -183,7 +187,7 @@ public void run() {
URL salURL = new URL(s+"tcpSlaveAgentListener/");

// find out the TCP port
HttpURLConnection con = (HttpURLConnection)salURL.openConnection();
HttpURLConnection con = (HttpURLConnection)Util.openURLConnection(salURL);
if (con instanceof HttpURLConnection) {
if (credentials != null) {
// TODO /tcpSlaveAgentListener is unprotected so why do we need to pass any credentials?
Expand Down Expand Up @@ -350,14 +354,50 @@ private Socket connect(String port) throws IOException, InterruptedException {
int retry = 1;
while(true) {
try {
Socket s = new Socket(host, Integer.parseInt(port));
boolean isProxy = false;
Socket s = null;
if (System.getProperty("http.proxyHost") != null) {
String proxyHost = System.getProperty("http.proxyHost");
String proxyPort = System.getProperty("http.proxyPort", "80");
s = new Socket(proxyHost, Integer.parseInt(proxyPort));
isProxy = true;
} else {
String httpProxy = System.getenv("http_proxy");
if (httpProxy != null) {
try {
URL url = new URL(httpProxy);
s = new Socket(url.getHost(), url.getPort());
isProxy = true;
} catch (MalformedURLException e) {
System.err.println("Not use http_proxy environment variable which is invalid: "+e.getMessage());
s = new Socket(host, Integer.parseInt(port));
}
} else {
s = new Socket(host, Integer.parseInt(port));
}
}

s.setTcpNoDelay(true); // we'll do buffering by ourselves

// set read time out to avoid infinite hang. the time out should be long enough so as not
// to interfere with normal operation. the main purpose of this is that when the other peer dies
// abruptly, we shouldn't hang forever, and at some point we should notice that the connection
// is gone.
s.setSoTimeout(30*60*1000); // 30 mins. See PingThread for the ping interval

if (isProxy) {
String connectCommand = String.format("CONNECT %s:%s HTTP/1.1\r\nHost: %s\r\n\r\n", host, port, host);
s.getOutputStream().write(connectCommand.getBytes());

BufferedInputStream is = new BufferedInputStream(s.getInputStream());
String line = readLine(is);
String[] responseLineParts = line.split(" ");
if(responseLineParts.length < 2 || !responseLineParts[1].equals("200"))
throw new IOException("Got a bad response from proxy: " + line);
while(!(line = readLine(is)).isEmpty()) {
// Do nothing, scrolling through headers returned from proxy
}
}
return s;
} catch (IOException e) {
if(retry++>10)
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/hudson/remoting/Launcher.java
Expand Up @@ -253,7 +253,7 @@ public List<String> parseJnlpArguments() throws ParserConfigurationException, SA
}
while (true) {
try {
URLConnection con = slaveJnlpURL.openConnection();
URLConnection con = Util.openURLConnection(slaveJnlpURL);
if (con instanceof HttpURLConnection) {
HttpURLConnection http = (HttpURLConnection) con;
if (slaveJnlpCredentials != null) {
Expand Down
34 changes: 34 additions & 0 deletions src/main/java/hudson/remoting/Util.java
Expand Up @@ -6,6 +6,13 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.URL;

/**
* Misc. I/O utilities
Expand Down Expand Up @@ -97,4 +104,31 @@ static void deleteDirectoryOnExit(final File dir) {
static String indent(String s) {
return " " + s.trim().replace("\n", "\n ");
}

/**
* Gets URL connection.
* If http_proxy environment variable exists, the connection uses the proxy.
*/
static URLConnection openURLConnection(URL url) throws IOException {
String httpProxy = null;
// If http.proxyHost property exists, openConnection() uses it.
if (System.getProperty("http.proxyHost") == null) {
httpProxy = System.getenv("http_proxy");
}
URLConnection con = null;
if (httpProxy != null && "http".equals(url.getProtocol())) {
try {
URL proxyUrl = new URL(httpProxy);
SocketAddress addr = new InetSocketAddress(proxyUrl.getHost(), proxyUrl.getPort());
Proxy proxy = new Proxy(Proxy.Type.HTTP, addr);
con = url.openConnection(proxy);
} catch (MalformedURLException e) {
System.err.println("Not use http_proxy property or environment variable which is invalid: "+e.getMessage());
con = url.openConnection();
}
} else {
con = url.openConnection();
}
return con;
}
}

0 comments on commit 8c875cb

Please sign in to comment.