下面列出了javax.net.ssl.SSLEngine#isOutboundDone ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private void doHandshake(SocketChannel socketChannel, SSLEngine sslEngine, ByteBuffer myNetData, ByteBuffer peerNetData)
throws IOException {
// Create byte buffers to use for holding application data
int appBufferSize = sslEngine.getSession().getApplicationBufferSize();
ByteBuffer myAppData = ByteBuffer.allocate(appBufferSize);
ByteBuffer peerAppData = ByteBuffer.allocate(appBufferSize);
SSLEngineResult.HandshakeStatus hs = sslEngine.getHandshakeStatus();
// Process handshaking message
while (hs != SSLEngineResult.HandshakeStatus.FINISHED && hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
switch (hs) {
case NEED_UNWRAP:
// Receive handshaking data from peer
if (socketChannel.read(peerNetData) < 0) {
throw new SocketException("Channel closed");
}
// Process incoming handshaking data
peerNetData.flip();
SSLEngineResult res = sslEngine.unwrap(peerNetData, peerAppData);
peerNetData.compact();
hs = res.getHandshakeStatus();
// Check status
switch (res.getStatus()) {
case OK:
// Handle OK status
break;
case BUFFER_OVERFLOW:
peerAppData = enlargeBuffer(peerNetData, peerAppData);
break;
case BUFFER_UNDERFLOW:
break;
}
break;
case NEED_WRAP:
// Empty the local network packet buffer.
myNetData.clear();
// Generate handshaking data
res = sslEngine.wrap(myAppData, myNetData);
hs = res.getHandshakeStatus();
// Check status
switch (res.getStatus()) {
case OK:
myNetData.flip();
// Send the handshaking data to peer
while (myNetData.hasRemaining()) {
if (socketChannel.write(myNetData) < 0) {
// Handle closed channel
}
}
break;
case BUFFER_OVERFLOW:
myNetData = enlargeBuffer(myAppData, myNetData);
break;
case BUFFER_UNDERFLOW:
break;
case CLOSED:
if (sslEngine.isOutboundDone()) {
return;
} else {
sslEngine.closeOutbound();
hs = sslEngine.getHandshakeStatus();
break;
}
default:
throw new IOException("Cannot wrap data: " + res.getStatus());
}
break;
case NEED_TASK:
Runnable task;
while ((task = sslEngine.getDelegatedTask()) != null) {
task.run();
}
hs = sslEngine.getHandshakeStatus();
break;
case FINISHED:
return;
}
}
}
/**
* Close engines by sending "close outbound" message from one SSLEngine to
* another.
*
* @param fromEngine - Sending engine.
* @param toEngine - Receiving engine.
* @throws SSLException - thrown on engine errors.
*/
public static void closeEngines(SSLEngine fromEngine,
SSLEngine toEngine) throws SSLException {
String from = null;
String to = null;
ByteBuffer app;
if (fromEngine.getUseClientMode() && !toEngine.getUseClientMode()) {
from = "Client";
to = "Server";
} else if (toEngine.getUseClientMode() &&
!fromEngine.getUseClientMode()) {
from = "Server";
to = "Client";
} else {
throw new Error("Both engines are in the same mode");
}
System.out.println("=============================================");
System.out.println(
"Trying to close engines from " + from + " to " + to);
// Sending close outbound request to peer
fromEngine.closeOutbound();
app = ByteBuffer.allocate(
fromEngine.getSession().getApplicationBufferSize());
net = doWrap(fromEngine, from, 0, app, SSLEngineResult.Status.CLOSED);
doUnWrap(toEngine, to, net, SSLEngineResult.Status.CLOSED);
app = ByteBuffer.allocate(
fromEngine.getSession().getApplicationBufferSize());
net = doWrap(toEngine, to, 0, app, SSLEngineResult.Status.CLOSED);
doUnWrap(fromEngine, from, net, SSLEngineResult.Status.CLOSED);
if (!toEngine.isInboundDone()) {
throw new AssertionError(from + " sent close request to " + to
+ ", but " + to + "did not close inbound.");
}
// Executing close inbound
fromEngine.closeInbound();
app = ByteBuffer.allocate(
fromEngine.getSession().getApplicationBufferSize());
net = doWrap(fromEngine, from, 0, app, SSLEngineResult.Status.CLOSED);
doUnWrap(toEngine, to, net, SSLEngineResult.Status.CLOSED);
if (!toEngine.isOutboundDone()) {
throw new AssertionError(from + "sent close request to " + to
+ ", but " + to + "did not close outbound.");
}
System.out.println("Successful closing from " + from + " to " + to);
}
private static HandshakeHolder doHandshakeUnwrap(final SocketChannel socketChannel, final SSLEngine sslEngine,
ByteBuffer peerAppData, ByteBuffer peerNetData, final int appBufferSize) throws IOException {
if (socketChannel == null || sslEngine == null || peerAppData == null || peerNetData == null || appBufferSize < 0) {
return new HandshakeHolder(peerAppData, peerNetData, false);
}
if (socketChannel.read(peerNetData) < 0) {
if (sslEngine.isInboundDone() && sslEngine.isOutboundDone()) {
return new HandshakeHolder(peerAppData, peerNetData, false);
}
try {
sslEngine.closeInbound();
} catch (SSLException e) {
s_logger.warn("This SSL engine was forced to close inbound due to end of stream.", e);
}
sslEngine.closeOutbound();
// After closeOutbound the engine will be set to WRAP state,
// in order to try to send a close message to the client.
return new HandshakeHolder(peerAppData, peerNetData, true);
}
peerNetData.flip();
SSLEngineResult result = null;
try {
result = sslEngine.unwrap(peerNetData, peerAppData);
peerNetData.compact();
} catch (final SSLException sslException) {
s_logger.error(String.format("SSL error caught during unwrap data: %s, for local address=%s, remote address=%s. The client may have invalid ca-certificates.",
sslException.getMessage(), socketChannel.getLocalAddress(), socketChannel.getRemoteAddress()));
sslEngine.closeOutbound();
return new HandshakeHolder(peerAppData, peerNetData, false);
}
if (result == null) {
return new HandshakeHolder(peerAppData, peerNetData, false);
}
switch (result.getStatus()) {
case OK:
break;
case BUFFER_OVERFLOW:
// Will occur when peerAppData's capacity is smaller than the data derived from peerNetData's unwrap.
peerAppData = enlargeBuffer(peerAppData, appBufferSize);
break;
case BUFFER_UNDERFLOW:
// Will occur either when no data was read from the peer or when the peerNetData buffer
// was too small to hold all peer's data.
peerNetData = handleBufferUnderflow(sslEngine, peerNetData);
break;
case CLOSED:
if (sslEngine.isOutboundDone()) {
return new HandshakeHolder(peerAppData, peerNetData, false);
} else {
sslEngine.closeOutbound();
}
break;
default:
throw new IllegalStateException("Invalid SSL status: " + result.getStatus());
}
return new HandshakeHolder(peerAppData, peerNetData, true);
}