Skip to content

Commit

Permalink
Added support for HTTP CONNECT proxies by implementing custom Socket (F…
Browse files Browse the repository at this point in the history
…ixes #170)
  • Loading branch information
hierynomus committed Mar 30, 2015
1 parent 8398b6e commit ace09fa
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 29 deletions.
13 changes: 13 additions & 0 deletions src/main/java/com/hierynomus/sshj/backport/JavaVersion.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.hierynomus.sshj.backport;

import java.math.BigDecimal;

public class JavaVersion {
public static boolean isJava7OrEarlier() {
String property = System.getProperty("java.specification.version");
float diff = Float.parseFloat(property) - 1.7f;

return diff < 0.01;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.hierynomus.sshj.backport;

import java.io.IOException;
import java.io.InputStream;
import java.net.*;
import java.nio.charset.Charset;

public class Jdk7HttpProxySocket extends Socket {

private Proxy httpProxy = null;

public Jdk7HttpProxySocket(Proxy proxy) {
super(proxy.type() == Proxy.Type.HTTP ? Proxy.NO_PROXY : proxy);
if (proxy.type() == Proxy.Type.HTTP) {
this.httpProxy = proxy;
}
}

@Override
public void connect(SocketAddress endpoint, int timeout) throws IOException {
if (httpProxy != null) {
connectHttpProxy(endpoint, timeout);
} else {
super.connect(endpoint, timeout);
}
}

private void connectHttpProxy(SocketAddress endpoint, int timeout) throws IOException {
super.connect(httpProxy.address(), timeout);

if (!(endpoint instanceof InetSocketAddress)) {
throw new SocketException("Expected an InetSocketAddress to connect to, got: " + endpoint);
}
InetSocketAddress isa = (InetSocketAddress) endpoint;
String httpConnect = "CONNECT " + isa.getHostName() + ":" + isa.getPort() + " HTTP/1.0\n\n";
getOutputStream().write(httpConnect.getBytes(Charset.forName("UTF-8")));
checkAndFlushProxyResponse();
}

private void checkAndFlushProxyResponse()throws IOException {
InputStream socketInput = getInputStream();
byte[] tmpBuffer = new byte[512];
int len = socketInput.read(tmpBuffer, 0, tmpBuffer.length);

if (len == 0) {
throw new SocketException("Empty response from proxy");
}

String proxyResponse = new String(tmpBuffer, 0, len, "UTF-8");

// Expecting HTTP/1.x 200 OK
if (proxyResponse.contains("200")) {
// Flush any outstanding message in buffer
if (socketInput.available() > 0) {
socketInput.skip(socketInput.available());
}
// Proxy Connect Successful
} else {
throw new SocketException("Fail to create Socket\nResponse was:" + proxyResponse);
}
}
}
54 changes: 25 additions & 29 deletions src/main/java/net/schmizz/sshj/SocketClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
*/
package net.schmizz.sshj;

import com.hierynomus.sshj.backport.JavaVersion;
import com.hierynomus.sshj.backport.Jdk7HttpProxySocket;

import javax.net.SocketFactory;
import java.io.IOException;
import java.io.InputStream;
Expand Down Expand Up @@ -45,70 +48,64 @@ public abstract class SocketClient {
this.defaultPort = defaultPort;
}

public void connect(InetAddress host, int port)
throws IOException {
public void connect(InetAddress host, int port) throws IOException {
socket = socketFactory.createSocket();
socket.connect(new InetSocketAddress(host, port), connectTimeout);
onConnect();
}

public void connect(InetAddress host, int port, Proxy proxy)
throws IOException {
socket = new Socket(proxy);

public void connect(InetAddress host, int port, Proxy proxy) throws IOException {
if (JavaVersion.isJava7OrEarlier() && proxy.type() == Proxy.Type.HTTP) {
// Java7 and earlier have no support for HTTP Connect proxies, return our custom socket.
socket = new Jdk7HttpProxySocket(proxy);
} else {
socket = new Socket(proxy);
}
socket.connect(new InetSocketAddress(host, port), connectTimeout);
onConnect();
}

public void connect(String hostname, int port)
throws IOException {
public void connect(String hostname, int port) throws IOException {
this.hostname = hostname;
connect(InetAddress.getByName(hostname), port);
}

public void connect(String hostname, int port, Proxy proxy)
throws IOException {
public void connect(String hostname, int port, Proxy proxy) throws IOException {
this.hostname = hostname;
connect(InetAddress.getByName(hostname), port, proxy);
}

public void connect(InetAddress host, int port,
InetAddress localAddr, int localPort)
public void connect(InetAddress host, int port, InetAddress localAddr, int localPort)
throws IOException {
socket = socketFactory.createSocket();
socket.bind(new InetSocketAddress(localAddr, localPort));
socket.connect(new InetSocketAddress(host, port), connectTimeout);
onConnect();
}

public void connect(String hostname, int port,
InetAddress localAddr, int localPort)
throws IOException {
public void connect(String hostname, int port, InetAddress localAddr, int localPort) throws IOException {
this.hostname = hostname;
connect(InetAddress.getByName(hostname), port, localAddr, localPort);
}

public void connect(InetAddress host)
throws IOException {
public void connect(InetAddress host) throws IOException {
connect(host, defaultPort);
}

public void connect(String hostname)
throws IOException {
public void connect(String hostname) throws IOException {
connect(hostname, defaultPort);
}

public void connect(InetAddress host, Proxy proxy)
throws IOException {
public void connect(InetAddress host, Proxy proxy) throws IOException {
connect(host, defaultPort, proxy);
}

public void connect(String hostname, Proxy proxy)
throws IOException {
public void connect(String hostname, Proxy proxy) throws IOException {
connect(hostname, defaultPort, proxy);
}

public void disconnect()
throws IOException {
public void disconnect() throws IOException {
if (socket != null) {
socket.close();
socket = null;
Expand All @@ -131,7 +128,6 @@ public int getLocalPort() {
return socket.getLocalPort();
}


public InetAddress getLocalAddress() {
return socket.getLocalAddress();
}
Expand All @@ -149,10 +145,11 @@ public InetAddress getRemoteAddress() {
}

public void setSocketFactory(SocketFactory factory) {
if (factory == null)
if (factory == null) {
socketFactory = SocketFactory.getDefault();
else
} else {
socketFactory = factory;
}
}

public SocketFactory getSocketFactory() {
Expand Down Expand Up @@ -187,8 +184,7 @@ OutputStream getOutputStream() {
return output;
}

void onConnect()
throws IOException {
void onConnect() throws IOException {
socket.setSoTimeout(timeout);
input = socket.getInputStream();
output = socket.getOutputStream();
Expand Down

0 comments on commit ace09fa

Please sign in to comment.