KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > matuschek > http > connection > HttpsHelper


1 package net.matuschek.http.connection;
2
3 /*********************************************
4     Copyright (c) 2002 by Daniel Matuschek
5 *********************************************/

6
7 import java.io.IOException JavaDoc;
8 import java.io.InputStream JavaDoc;
9 import java.io.OutputStream JavaDoc;
10 import java.io.UnsupportedEncodingException JavaDoc;
11 import java.net.InetAddress JavaDoc;
12 import java.net.Socket JavaDoc;
13
14 import javax.net.ssl.SSLSocket;
15 import javax.net.ssl.SSLSocketFactory;
16
17 /*
18  * How to use SSL with a proxy:
19  * - http://java.sun.com/j2se/1.4/docs/guide/security/jsse/
20  * samples/sockets/client/SSLSocketClientWithTunneling.java
21  */

22
23
24 /**
25  * An helper class to provide SSL connections with and without proxy
26  *
27  * @author Daniel Matuschek <daniel@matuschek.net>
28  * @version $Id: HttpsHelper.java,v 1.5 2002/09/06 13:03:52 matuschd Exp $
29  */

30 public class HttpsHelper {
31
32   /** should it use a proxy server ? */
33   boolean useProxy = false;
34
35   /** Proxy host */
36   InetAddress JavaDoc proxyHost = null;
37
38   /** Proxy port */
39   int proxyPort = 0;
40
41   
42
43   /**
44    * Simple costructor that initialized an HttpsHelper
45    */

46   public HttpsHelper() {
47   }
48
49
50   /**
51    * Constructor that initializes the HttpsHelper an
52    * also sets the proxy settings.
53    */

54   public HttpsHelper(InetAddress JavaDoc proxyHost, int proxyPort, boolean useProxy) {
55     this.proxyHost = proxyHost;
56     this.proxyPort = proxyPort;
57     this.useProxy = useProxy;
58   }
59
60
61
62   /**
63    * Creates a new HTTPS connection to the defined host/port
64    *
65    * @param host full qualified hostname or ip address of the host
66    * to contact
67    * @param port destination prot on the server to connect
68    *
69    * @exception IOException, if the connection cannot be established
70    *
71    * @return an HttpConnection object with the established conection
72    */

73   public HttpConnection createHttpsConnection(String JavaDoc host, int port)
74     throws IOException JavaDoc
75   {
76     HttpConnection connection = null;
77     SSLSocketFactory factory = (SSLSocketFactory)SSLSocketFactory.getDefault();
78     SSLSocket socket = null;
79
80     if (! useProxy) {
81       
82       socket = (SSLSocket)factory.createSocket(host,port);
83
84     } else {
85       
86       Socket JavaDoc tunnel = new Socket JavaDoc(proxyHost, proxyPort);
87       doTunnelHandshake(tunnel, host, port);
88       
89       /*
90        * Ok, let's overlay the tunnel socket with SSL.
91        */

92       socket = (SSLSocket)factory.createSocket(tunnel, host, port, true);
93       
94       /*
95        * send http request
96        *
97        * See SSLSocketClient.java for more information about why
98        * there is a forced handshake here when using PrintWriters.
99        */

100       socket.startHandshake();
101     }
102
103     connection = new HttpConnection(socket);
104
105     return connection;
106
107   }
108
109
110   /**
111    * Tell our tunnel where we want to CONNECT, and look for the
112    * right reply. Throw IOException if anything goes wrong.
113    */

114   private void doTunnelHandshake(Socket JavaDoc tunnel, String JavaDoc host, int port)
115     throws IOException JavaDoc
116   {
117     OutputStream JavaDoc out = tunnel.getOutputStream();
118     String JavaDoc msg = "CONNECT " + host + ":" + port + " HTTP/1.0\n"
119       + "User-Agent: JoBo/1.4beta"
120       + "\r\n\r\n";
121     byte[] b;
122     try {
123       /*
124        * We really do want ASCII7 -- the http protocol doesn't change
125        * with locale.
126        */

127       b = msg.getBytes("ASCII7");
128     } catch (UnsupportedEncodingException JavaDoc ignored) {
129       /*
130        * If ASCII7 isn't there, something serious is wrong, but
131        * Paranoia Is Good (tm)
132        */

133       b = msg.getBytes();
134     }
135     out.write(b);
136     out.flush();
137     
138     /*
139      * We need to store the reply so we can create a detailed
140      * error message to the user.
141      */

142     byte[] reply = new byte[200];
143     int replyLen = 0;
144     int newlinesSeen = 0;
145     boolean headerDone = false; /* Done on first newline */
146     
147     InputStream JavaDoc in = tunnel.getInputStream();
148     while (newlinesSeen < 2) {
149       int i = in.read();
150       if (i < 0) {
151     throw new IOException JavaDoc("Unexpected EOF from proxy");
152       }
153       if (i == '\n') {
154     headerDone = true;
155     ++newlinesSeen;
156       } else if (i != '\r') {
157     newlinesSeen = 0;
158     if (!headerDone && replyLen < reply.length) {
159       reply[replyLen++] = (byte) i;
160     }
161       }
162     }
163     
164     /*
165      * Converting the byte array to a string is slightly wasteful
166      * in the case where the connection was successful, but it's
167      * insignificant compared to the network overhead.
168      */

169     String JavaDoc replyStr;
170     try {
171       replyStr = new String JavaDoc(reply, 0, replyLen, "ASCII7");
172     } catch (UnsupportedEncodingException JavaDoc ignored) {
173       replyStr = new String JavaDoc(reply, 0, replyLen);
174     }
175     
176     /* We asked for HTTP/1.0, so we should get that back */
177     if (!replyStr.startsWith("HTTP/1.0 200")) {
178       throw new IOException JavaDoc("Unable to tunnel through proxy"
179                 + ". Proxy returns \"" + replyStr + "\"");
180     }
181     
182     /* tunneling Handshake was successful! */
183   }
184   
185
186
187 }
188
Popular Tags