Skip to content

Commit

Permalink
Merge pull request #27
Browse files Browse the repository at this point in the history
Conflicts:
	src/main/java/hudson/remoting/Engine.java
  • Loading branch information
kohsuke committed Mar 20, 2015
2 parents 4172008 + 8c875cb commit 08b910c
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 6 deletions.
51 changes: 47 additions & 4 deletions src/main/java/hudson/remoting/Engine.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
package hudson.remoting;

import hudson.remoting.Channel.Mode;
import org.jenkinsci.remoting.engine.EngineUtil;
import org.jenkinsci.remoting.engine.JnlpProtocol;
import org.jenkinsci.remoting.engine.JnlpProtocolFactory;

Expand All @@ -33,16 +34,22 @@
import java.io.File;
import java.io.IOException;
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.util.Collections;
import java.util.List;
import java.net.MalformedURLException;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.logging.Logger;

import static java.util.logging.Level.INFO;
import static org.jenkinsci.remoting.engine.EngineUtil.readLine;

/**
* Slave agent engine that proactively connects to Jenkins master.
Expand Down Expand Up @@ -179,16 +186,16 @@ 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 (credentials != null) {
// TODO /tcpSlaveAgentListener is unprotected so why do we need to pass any credentials?
String encoding = Base64.encode(credentials.getBytes("UTF-8"));
con.setRequestProperty("Authorization", "Basic " + encoding);
}

if (proxyCredentials != null) {
String encoding = Base64.encode(proxyCredentials.getBytes("UTF-8"));
con.setRequestProperty("Proxy-Authorization", "Basic " + encoding);
String encoding = Base64.encode(proxyCredentials.getBytes("UTF-8"));
con.setRequestProperty("Proxy-Authorization", "Basic " + encoding);
}
try {
try {
Expand Down Expand Up @@ -308,14 +315,50 @@ private Socket connect(String host, String port) throws IOException, Interrupted
int retry = 1;
while(true) {
try {
Socket s = new Socket(host, Integer.parseInt(port));
boolean isProxy = false;
Socket s;
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(!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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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;
}
}
4 changes: 3 additions & 1 deletion src/main/java/org/jenkinsci/remoting/engine/EngineUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@

/**
* Engine utility methods.
*
* Internal class. DO NOT USE FROM OUTSIDE.
*
* @author Akshay Dayal
*/
Expand All @@ -43,7 +45,7 @@ public class EngineUtil {
* @return The line read.
* @throws IOException
*/
protected static String readLine(InputStream inputStream) throws IOException {
public static String readLine(InputStream inputStream) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
while (true) {
int ch = inputStream.read();
Expand Down

0 comments on commit 08b910c

Please sign in to comment.