12-05-2011 01:41 PM - last edited on 12-05-2011 01:45 PM
I have an application that establishes an SSL30Connection with a web proxy server. This connection is opened using the ConnectionFactory. In order to enable HTTPS browsing through the web proxy, I am attempting to create an SSL connection to a website (say google.com) that uses the proxy server SSL connection as its "subConnection" (see javadocs for SSL30Connection). When I attempt to do this, I end up with either an EOFException or a ConnectionClosedException.
I am aware of the workaround described here and have tried to use it, but the SSL connection to the remote server still fails.
Does anyone know if this kind of functionality is supported by the BB? Is there a 3rd party API that could accomplish this?
I have opened an issue in the RIM Developer Issue Tracker as well:
https://www.blackberry.com/jira/browse/JAVAAPI-217
Thank you.
Solved! Go to Solution.
12-07-2011 04:22 PM
After further testing I have some additional information to report:
After the SSL connection is made to the proxy server, the application sends a HTTP CONNECT request to the proxy. The app then receives a "200 Connection Established" response. In my testing today, I added a ConnectionCloseListener to the SSL proxy connection. The connectionClosed method of this listener is hit immediately after the app reads the "200 Connection Established" response from the proxy. Afterwards, the app attempts to establish an SSL connection to the remote server through the proxy connection and the EOFException is thrown.
It seems strange that the connection is being closed immediately after I read the proxy's response.
12-14-2011 12:12 PM
Is the connection being made through a BlackBerry Enterprise Server? If so, are you using proxy or end-to-end mode?
These modes are described in further detail here: http://supportforums.blackberry.com/t5/Java-Develo
12-14-2011 12:14 PM
12-20-2011 10:06 AM - last edited on 12-20-2011 10:07 AM
I just tried using a SocketConnection for the initial connection to the proxy server. After the connection was established, I sent the HTTP CONNECT request to the proxy and received the "200 Connection Established" response. At that point, I tried to create an SSL30Connection to the remote server using the following code:
SSL30Connection remoteServerConnection = new SSL30Connection( socketConnectionToProxy, remoteServer:443, true );
An EOFException is thrown in the remoteServerConnection constructor. I can see in the log output that the SSL Client Hello message is being sent:
SSL:->CH
The exception is thrown sometime after this log statement. I should add that I also see this log statement when using an SSL30Connection for the initial connection to the proxy server.
In summary, it does not matter if my proxy connection is SSL. Attempting to make an SSL connection to the remote server using the proxy connection as the "subConnection" parameter always fails. I think this just confirms my previous comment that the root issue is how the connection is being closed after reading the HTTP CONNECT response.
12-23-2011 10:35 AM
Turns out multiple things were going wrong.
1) The proxy was closing the connection after I read the HTTP CONNECT response. The fix for this had two parts:
++ Adding a "Proxy-Connection: keep-alive" header.
++ Modifying the way I was reading the response. Before, I was reading the inputStream in 256b chunks until Ihit a -1. I changed this to simply read until I hit a line return character since the CONNECT response is onlyone linelong.
After making these changes, I was able to make a socket:// connection to the proxy and then make an ssl:// to the remote server with the proxy connection as the ssl subConnection. However, when I tried to make an ssl:// connection to the server, I was still getting the EOFException when opening the ssl:// connection to the remote server. Then... as if Santa Claus himself dropped in to give me an early Christmas gift... I remembered that I had encountered problems with ssl:// connections before; specifically, writing data to an ssl:// connection's OutputStream REQUIRES a call to OutputStream.flush(). If you don't flush, the data is never written (or the buffer is just really big... in any case, adding a flush() fixes it). Remembering this issue led me to the last part of the fix for this problem.
2) I wrapped the ssl proxy connection and its already opened input and output streams in a class that looks like this:
public class ProxyStreamConnectionWrapper implements StreamConnection {
private StreamConnection stream;
private DataInputStream inputStream;
private DataOutputStream outputStream;
public ProxyStreamConnectionWrapper(StreamConnection stream, DataInputStream dataInputStream, DataOutputStream dataOutputStream) {
this.stream = stream;
this.inputStream = dataInputStream;
this.outputStream = dataOutputStream;
}
public DataInputStream openDataInputStream() throws IOException {
return inputStream;
}
public InputStream openInputStream() throws IOException {
return inputStream;
}
public void close() throws IOException {
stream.close();
}
public DataOutputStream openDataOutputStream() throws IOException {
return new DataOutputStream( openOutputStream() );
}
public OutputStream openOutputStream() throws IOException {
return new OutputStream() {
public void write( byte[] b, int off, int len ) throws IOException {
outputStream.write( b, off, len );
outputStream.flush();
}
public void write( byte[] b ) throws IOException {
outputStream.write( b );
outputStream.flush();
}
public void write( int b ) throws IOException {
outputStream.write( b );
outputStream.flush();
}
};
}I got the idea for this wrapper from a previous post that I've already linked to above. The fix is in the openOutputStream() method. Adding the flush() after every write forces the remote server connection's ssl handshake data out over the proxy server's ssl connection.
merry christmas!