in httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java [150:259]
public SSLIOSession(
final NamedEndpoint targetEndpoint,
final IOSession session,
final SSLMode sslMode,
final SSLContext sslContext,
final SSLBufferMode sslBufferMode,
final SSLSessionInitializer initializer,
final SSLSessionVerifier verifier,
final Timeout handshakeTimeout,
final Callback<SSLIOSession> sessionStartCallback,
final Callback<SSLIOSession> sessionEndCallback,
final FutureCallback<SSLSession> resultCallback) {
super();
Args.notNull(session, "IO session");
Args.notNull(sslContext, "SSL context");
this.targetEndpoint = targetEndpoint;
this.session = session;
this.sslMode = sslMode;
this.initializer = initializer;
this.verifier = verifier;
this.sessionStartCallback = sessionStartCallback;
this.sessionEndCallback = sessionEndCallback;
this.handshakeCallbackRef = new AtomicReference<>(resultCallback);
this.appEventMask = session.getEventMask();
if (this.sslMode == SSLMode.CLIENT && targetEndpoint != null) {
this.sslEngine = sslContext.createSSLEngine(targetEndpoint.getHostName(), targetEndpoint.getPort());
} else {
this.sslEngine = sslContext.createSSLEngine();
}
final SSLSession sslSession = this.sslEngine.getSession();
// Allocate buffers for network (encrypted) data
this.packetBufferSize = sslSession.getPacketBufferSize();
this.inEncrypted = SSLManagedBuffer.create(sslBufferMode, packetBufferSize);
this.outEncrypted = SSLManagedBuffer.create(sslBufferMode, packetBufferSize);
// Allocate buffers for application (unencrypted) data
final int appBufferSize = sslSession.getApplicationBufferSize();
this.inPlain = SSLManagedBuffer.create(sslBufferMode, appBufferSize);
this.outboundClosedCount = new AtomicInteger(0);
this.handshakeStateRef = new AtomicReference<>(TLSHandShakeState.READY);
this.handshakeTimeout = handshakeTimeout;
this.internalEventHandler = new IOEventHandler() {
@Override
public void connected(final IOSession protocolSession) throws IOException {
beginHandshake(protocolSession);
}
@Override
public void inputReady(final IOSession protocolSession, final ByteBuffer src) throws IOException {
receiveEncryptedData();
doHandshake(protocolSession);
decryptData(protocolSession);
updateEventMask();
}
@Override
public void outputReady(final IOSession protocolSession) throws IOException {
encryptData(protocolSession);
sendEncryptedData();
doHandshake(protocolSession);
updateEventMask();
}
@Override
public void timeout(final IOSession protocolSession, final Timeout timeout) throws IOException {
if (sslEngine.isInboundDone() && !sslEngine.isInboundDone()) {
// The session failed to terminate cleanly
close(CloseMode.IMMEDIATE);
}
if (handshakeStateRef.get() != TLSHandShakeState.COMPLETE) {
exception(protocolSession, SocketTimeoutExceptionFactory.create(handshakeTimeout));
} else {
ensureHandler().timeout(protocolSession, timeout);
}
}
@Override
public void exception(final IOSession protocolSession, final Exception cause) {
final FutureCallback<SSLSession> resultCallback = handshakeCallbackRef.getAndSet(null);
if (resultCallback != null) {
resultCallback.failed(cause);
}
final IOEventHandler handler = session.getHandler();
if (handshakeStateRef.get() != TLSHandShakeState.COMPLETE) {
if (cause instanceof SSLHandshakeException) {
close(CloseMode.GRACEFUL);
} else {
session.close(CloseMode.GRACEFUL);
close(CloseMode.IMMEDIATE);
}
}
if (handler != null) {
handler.exception(protocolSession, cause);
}
}
@Override
public void disconnected(final IOSession protocolSession) {
final IOEventHandler handler = session.getHandler();
if (handler != null) {
handler.disconnected(protocolSession);
}
}
};
}