views:

362

answers:

2

Hi,

I've implemented an helper module that lets me obtain clean data from a channel used with SSL and write encrypted data into it: this is the relevant interface (I've also some non-abstract methods in that class, so doesn't say to me that "DataProvider should be an interface" ;)):

public abstract class DataProvider {
    // Notify the bytes read from the net
    public abstract void readFromNet(ByteBuffer b);
    // Gets the bytes to write into the net
    public abstract void writeToNet(ByteBuffer b);
    // Add a message to send
    public abstract boolean addMessage(byte[] data);
    // Obtains the application data received
    public abstract byte[] getReceivedApplicationData();
    // True if there is something to actually send over the wire
    public abstract boolean dataToSend();
    // True if we should close the channel
    public abstract boolean shouldClose();
    // Notify our intention to shut down the connection
    public abstract void shutDown(SelectionKey sk);
    // Set the interest op set for the channel
    public abstract void setInterestOps(SelectionKey sk);
}

I've an implementation of that abstract base class for SSL. While testing that implementation, I've wrote two function: in one I receive a message with a SocketChannel and the SSLSocket used to send data closes the connection, in the other I send a message with the SocketChannel initiate the closing with that. Now, the problem is that the SSLSocket used to receive the data doesn't close, even if I've issued those steps:

  1. engine.closeOutbound()
  2. engine.wrap()
  3. channel.write(data) (yes, I'm sure I've sent all the data obtained with the wrap()
  4. a select of the channel for reading the inbound close_notify

The problem is that the selector is stuck in the 4th step.

In the other test (SSLSocket closes the connection) I don't have a problem.

Note that I've implemented the shouldClose as:

return engine.isOutboundDone() && engine.isInboundDone();

so I need an incoming close_notify in order to close, even if I've initialized the close (I don't know if this is correct: eventually I can change it with return engine.isOutboundDone())

This is my SSLSocket side of the code:

Socket toRead = socket.accept();
toRead.setSoTimeout(0);
InputStream is = toRead.getInputStream();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
String read = "";
byte[] barray = new byte[1024];
while (read.length() < toSend.length() * 2) {
 int bytesRead = is.read(barray);
 bos.write(barray, 0, bytesRead);
 read = new String(bos.toByteArray());
}
assertEquals(toSend + toSend, read);
assertTrue(toRead.isClosed());

The last assert is violated.

Initially I've thinked that this is because there is no "background" thread associated with toRead, so I should do a read/write with it in order to consume the incoming close_notify and then finally get the socket close, but even that doesn't help.

Any idea?

+1  A: 

I would suggest adding is.close(); before the fist assert.

Please note that this tiny piece of code I suggested doesn't close the socket. It's supposed to close the InputStream.

QuickRecipesOnSymbianOS
I can't close the socket: I've to receive the SSL's notify_end.
akappa
If you close the InputStream of Socket, you close the channel.Since the documentation of SSLSocket doesn't "override" that information, I assume that the effect is the same.Given the fact that I want to test if I've implemented the SSL close in a correct manner, I can't close the SSLSocket because I just want that it closes "for itself" at the receive of the ssl_close. I'm wondering why it doen't happens: this really is my question.
akappa
A: 

No right answer for the bounty.

akappa