SSLEngine и закрыть - PullRequest
       39

SSLEngine и закрыть

2 голосов
/ 28 мая 2009

Я реализовал вспомогательный модуль, который позволяет мне получать чистые данные из канала, используемого с SSL, и записывать в него зашифрованные данные: это соответствующий интерфейс (у меня также есть некоторые неабстрактные методы в этом классе, так что не говорите мне, что «DataProvider должен быть интерфейсом»;)):

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);
}

У меня есть реализация этого абстрактного базового класса для SSL. При тестировании этой реализации я написал две функции: в одной я получаю сообщение с SocketChannel, а SSLSocket, используемый для отправки данных, закрывает соединение, в другой я отправляю сообщение с SocketChannel, инициируя закрытие с этим. Проблема в том, что SSLSocket, используемый для получения данных, не закрывается, даже если я выполнил следующие шаги:

  1. engine.closeOutbound ()
  2. engine.wrap ()
  3. channel.write (data) (да, я уверен, что отправил все данные, полученные с помощью wrap ()
  4. выбор канала для чтения входящих сообщений close_notify

Проблема в том, что селектор застрял на 4-м шаге.

В другом тесте (SSLSocket закрывает соединение) у меня нет проблем.

Обратите внимание, что я реализовал mustClose как:

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

поэтому мне нужно входящее close_notify для закрытия, даже если я инициализировал закрытие (я не знаю, правильно ли это: в конце концов я могу изменить его с помощью return engine.isOutboundDone())

Это моя сторона кода SSLSocket:

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());

Последнее утверждение нарушено.

Первоначально я думал, что это потому, что нет никакого "фонового" потока, связанного с toRead, поэтому я должен сделать чтение / запись с ним, чтобы использовать входящий close_notify, а затем, наконец, закрыть сокет, но даже это не помогает.

Есть идеи?

Ответы [ 2 ]

3 голосов
/ 17 июля 2011

Очень поздний ответ, но вам не нужно ждать закрытия close_notify, если вы уже отправили его, см. RFC 2246. Однако вы должны его получить Вы не говорите, как именно вы выбираете на close_notify.

NB Ваш код не имеет смысла. Сокет будет закрыт только если вы закроете его. isClosed() относится к разъему, а не к соединению.

1 голос
/ 04 июня 2009

Я бы предложил добавить is.close(); перед тем, как утверждать кулак.

Обратите внимание, что этот крошечный фрагмент кода, который я предложил, не закрывает сокет. Предполагается закрыть InputStream.

...