| package com.trilead.ssh2.transport; |
| |
| import com.trilead.ssh2.HTTPProxyData; |
| import com.trilead.ssh2.HTTPProxyException; |
| import com.trilead.ssh2.ProxyData; |
| import com.trilead.ssh2.SelfConnectionProxyData; |
| import com.trilead.ssh2.crypto.Base64; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.net.InetAddress; |
| import java.net.InetSocketAddress; |
| import java.net.Socket; |
| |
| public class SocketFactory { |
| public static Socket open(final String hostname, final int port, final ProxyData proxyData, final int connectTimeout) throws IOException { |
| final Socket sock = new Socket(); |
| if (proxyData == null) |
| { |
| InetAddress addr = TransportManager.createInetAddress(hostname); |
| sock.connect(new InetSocketAddress(addr, port), connectTimeout); |
| sock.setSoTimeout(0); |
| return sock; |
| } |
| |
| if (proxyData instanceof SelfConnectionProxyData) { |
| // already connected |
| return ((SelfConnectionProxyData) proxyData).connect(); |
| } |
| |
| if (proxyData instanceof HTTPProxyData) |
| { |
| HTTPProxyData pd = (HTTPProxyData) proxyData; |
| |
| /* At the moment, we only support HTTP proxies */ |
| |
| InetAddress addr = TransportManager.createInetAddress(pd.proxyHost); |
| sock.connect(new InetSocketAddress(addr, pd.proxyPort), connectTimeout); |
| sock.setSoTimeout(0); |
| |
| /* OK, now tell the proxy where we actually want to connect to */ |
| |
| StringBuffer sb = new StringBuffer(); |
| |
| sb.append("CONNECT "); |
| sb.append(hostname); |
| sb.append(':'); |
| sb.append(port); |
| sb.append(" HTTP/1.0\r\n"); |
| |
| if ((pd.proxyUser != null) && (pd.proxyPass != null)) |
| { |
| String credentials = pd.proxyUser + ":" + pd.proxyPass; |
| char[] encoded = Base64.encode(credentials.getBytes("ISO-8859-1")); |
| sb.append("Proxy-Authorization: Basic "); |
| sb.append(encoded); |
| sb.append("\r\n"); |
| } |
| |
| if (pd.requestHeaderLines != null) |
| { |
| for (int i = 0; i < pd.requestHeaderLines.length; i++) |
| { |
| if (pd.requestHeaderLines[i] != null) |
| { |
| sb.append(pd.requestHeaderLines[i]); |
| sb.append("\r\n"); |
| } |
| } |
| } |
| |
| sb.append("\r\n"); |
| |
| OutputStream out = sock.getOutputStream(); |
| |
| out.write(sb.toString().getBytes("ISO-8859-1")); |
| out.flush(); |
| |
| /* Now parse the HTTP response */ |
| |
| byte[] buffer = new byte[1024]; |
| InputStream in = sock.getInputStream(); |
| |
| int len = ClientServerHello.readLineRN(in, buffer); |
| |
| String httpReponse = new String(buffer, 0, len, "ISO-8859-1"); |
| |
| if (httpReponse.startsWith("HTTP/") == false) |
| throw new IOException("The proxy did not send back a valid HTTP response."); |
| |
| /* "HTTP/1.X XYZ X" => 14 characters minimum */ |
| |
| if ((httpReponse.length() < 14) || (httpReponse.charAt(8) != ' ') || (httpReponse.charAt(12) != ' ')) |
| throw new IOException("The proxy did not send back a valid HTTP response."); |
| |
| int errorCode = 0; |
| |
| try |
| { |
| errorCode = Integer.parseInt(httpReponse.substring(9, 12)); |
| } |
| catch (NumberFormatException ignore) |
| { |
| throw new IOException("The proxy did not send back a valid HTTP response."); |
| } |
| |
| if ((errorCode < 0) || (errorCode > 999)) |
| throw new IOException("The proxy did not send back a valid HTTP response."); |
| |
| if (errorCode != 200) |
| { |
| throw new HTTPProxyException(httpReponse.substring(13), errorCode); |
| } |
| |
| /* OK, read until empty line */ |
| |
| while (true) |
| { |
| len = ClientServerHello.readLineRN(in, buffer); |
| if (len == 0) |
| break; |
| } |
| return sock; |
| } |
| |
| throw new IOException("Unsupported ProxyData"); |
| } |
| } |