SSLEngine 并关闭

发布于 2024-07-23 11:14:56 字数 2218 浏览 1 评论 0原文

我已经实现了一个帮助程序模块,它允许我从与 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)(是的,我确信我已将使用wrapp()获得的所有数据发送到
  4. 用于读取入站close_notify的通道的选择

问题是选择器卡在第四步中

(SSLSocket关闭连接)我不这样做。有一个问题。

请注意,我已经将 shouldClose 实现为:

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,然后最终关闭套接字,但即使这样也无济于事。

任何想法?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

妖妓 2024-07-30 11:14:56

很晚的答案,但如果您已经发送了一个,则不需要等待 close_notify,请参阅 RFC 2246。但是您应该收到一个。 您没有说明您在 close_notify 上选择的具体情况。

注意您的代码没有意义。 仅当关闭套接字时,该套接字才会被关闭。 isClosed() 指的是套接字,而不是连接。

Very late answer but you don't need wait for the close_notify if you have already sent one, see RFC 2246. However you should get one. You don't say how exactly you are selecting on close_notify.

NB Your code doesn't make sense. The socket will only be closed if you close it. isClosed() refers to the socket, not the connection.

失眠症患者 2024-07-30 11:14:56

我建议在第一个断言之前添加 is.close();

请注意,我建议的这段小代码不会关闭套接字。 它应该关闭输入流。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文