org.xnio.ssl.JsseXnioSsl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xnio-api Show documentation
Show all versions of xnio-api Show documentation
The API JAR of the XNIO project
/*
* JBoss, Home of Professional Open Source.
*
* Copyright 2013 Red Hat, Inc. and/or its affiliates, and individual
* contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.xnio.ssl;
import static java.security.AccessController.doPrivileged;
import static org.xnio.IoUtils.safeClose;
import static org.xnio._private.Messages.msg;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivilegedAction;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import org.xnio.BufferAllocator;
import org.xnio.ByteBufferSlicePool;
import org.xnio.ChannelListener;
import org.xnio.ChannelListeners;
import org.xnio.FutureResult;
import org.xnio.IoFuture;
import org.xnio.IoUtils;
import org.xnio.Option;
import org.xnio.OptionMap;
import org.xnio.Options;
import org.xnio.Pool;
import org.xnio.StreamConnection;
import org.xnio.Xnio;
import org.xnio.XnioExecutor;
import org.xnio.XnioIoThread;
import org.xnio.XnioWorker;
import org.xnio.channels.AcceptingChannel;
import org.xnio.channels.AssembledConnectedSslStreamChannel;
import org.xnio.channels.BoundChannel;
import org.xnio.channels.ConnectedSslStreamChannel;
import org.xnio.channels.ConnectedStreamChannel;
/**
* An XNIO SSL provider based on JSSE. Works with any XNIO provider.
*
* @author David M. Lloyd
* @author Flavia Rainone
*/
public final class JsseXnioSsl extends XnioSsl {
public static final boolean NEW_IMPL = doPrivileged((PrivilegedAction) () -> Boolean.valueOf(Boolean.parseBoolean(System.getProperty("org.xnio.ssl.new", "false")))).booleanValue();
static final Pool bufferPool = new ByteBufferSlicePool(BufferAllocator.DIRECT_BYTE_BUFFER_ALLOCATOR, 21 * 1024, 21 * 1024 * 128);
private final SSLContext sslContext;
/**
* Construct a new instance.
*
* @param xnio the XNIO instance to associate with
* @param optionMap the options for this provider
* @throws NoSuchProviderException if the given SSL provider is not found
* @throws NoSuchAlgorithmException if the given SSL algorithm is not supported
* @throws KeyManagementException if the SSL context could not be initialized
*/
public JsseXnioSsl(final Xnio xnio, final OptionMap optionMap) throws NoSuchProviderException, NoSuchAlgorithmException, KeyManagementException {
this(xnio, optionMap, JsseSslUtils.createSSLContext(optionMap));
}
/**
* Construct a new instance.
*
* @param xnio the XNIO instance to associate with
* @param optionMap the options for this provider
* @param sslContext the SSL context to use for this instance
*/
public JsseXnioSsl(final Xnio xnio, final OptionMap optionMap, final SSLContext sslContext) {
super(xnio, sslContext, optionMap);
this.sslContext = sslContext;
}
/**
* Get the JSSE SSL context for this provider instance.
*
* @return the SSL context
*/
@SuppressWarnings("unused")
public SSLContext getSslContext() {
return sslContext;
}
/**
* Get the SSL engine for a given connection.
*
* @return the SSL engine
*/
public static SSLEngine getSslEngine(SslConnection connection) {
if (connection instanceof JsseSslStreamConnection) {
return ((JsseSslStreamConnection) connection).getEngine();
} else if (connection instanceof JsseSslConnection) {
return ((JsseSslConnection) connection).getEngine();
} else {
throw msg.notFromThisProvider();
}
}
@SuppressWarnings("deprecation")
public IoFuture connectSsl(final XnioWorker worker, final InetSocketAddress bindAddress, final InetSocketAddress destination, final ChannelListener super ConnectedSslStreamChannel> openListener, final ChannelListener super BoundChannel> bindListener, final OptionMap optionMap) {
final FutureResult futureResult = new FutureResult(IoUtils.directExecutor());
final IoFuture futureSslConnection = openSslConnection(worker, bindAddress, destination, new ChannelListener() {
public void handleEvent(final SslConnection sslConnection) {
final ConnectedSslStreamChannel assembledChannel = new AssembledConnectedSslStreamChannel(sslConnection, sslConnection.getSourceChannel(), sslConnection.getSinkChannel());
if (!futureResult.setResult(assembledChannel)) {
safeClose(assembledChannel);
} else {
ChannelListeners.invokeChannelListener(assembledChannel, openListener);
}
}
}, bindListener, optionMap).addNotifier(new IoFuture.HandlingNotifier>() {
public void handleCancelled(final FutureResult result) {
result.setCancelled();
}
public void handleFailed(final IOException exception, final FutureResult result) {
result.setException(exception);
}
}, futureResult);
futureResult.getIoFuture().addNotifier(new IoFuture.HandlingNotifier>() {
public void handleCancelled(final IoFuture result) {
result.cancel();
}
}, futureSslConnection);
futureResult.addCancelHandler(futureSslConnection);
return futureResult.getIoFuture();
}
public IoFuture openSslConnection(final XnioWorker worker, final InetSocketAddress bindAddress, final InetSocketAddress destination, final ChannelListener super SslConnection> openListener, final ChannelListener super BoundChannel> bindListener, final OptionMap optionMap) {
return openSslConnection(worker.getIoThread(), bindAddress, destination, openListener, bindListener, optionMap);
}
public IoFuture openSslConnection(final XnioIoThread ioThread, final InetSocketAddress bindAddress, final InetSocketAddress destination, final ChannelListener super SslConnection> openListener, final ChannelListener super BoundChannel> bindListener, final OptionMap optionMap) {
final FutureResult futureResult = new FutureResult<>(ioThread);
final IoFuture connection = ioThread.openStreamConnection(bindAddress, destination, new ChannelListener() {
public void handleEvent(final StreamConnection connection) {
final SSLEngine sslEngine = JsseSslUtils.createSSLEngine(sslContext, optionMap, destination);
final boolean startTls = optionMap.get(Options.SSL_STARTTLS, false);
final SslConnection wrappedConnection;
try {
wrappedConnection = NEW_IMPL ? new JsseSslConnection(connection, sslEngine, bufferPool, bufferPool) : new JsseSslStreamConnection(connection, sslEngine, bufferPool, bufferPool, startTls);
} catch (RuntimeException e) {
futureResult.setCancelled();
throw e;
}
if (NEW_IMPL && ! startTls) {
try {
wrappedConnection.startHandshake();
} catch (IOException e) {
if (futureResult.setException(e)) {
IoUtils.safeClose(connection);
}
}
}
if (! futureResult.setResult(wrappedConnection)) {
IoUtils.safeClose(connection);
} else {
ChannelListeners.invokeChannelListener(wrappedConnection, openListener);
}
}
}, bindListener, optionMap);
connection.addNotifier(new IoFuture.HandlingNotifier>() {
public void handleCancelled(final FutureResult attachment) {
attachment.setCancelled();
}
public void handleFailed(final IOException exception, final FutureResult attachment) {
attachment.setException(exception);
}
}, futureResult);
futureResult.addCancelHandler(connection);
return futureResult.getIoFuture();
}
@SuppressWarnings("deprecation")
public AcceptingChannel createSslTcpServer(final XnioWorker worker, final InetSocketAddress bindAddress, final ChannelListener super AcceptingChannel> acceptListener, final OptionMap optionMap) throws IOException {
final AcceptingChannel server = createSslConnectionServer(worker, bindAddress, null, optionMap);
final AcceptingChannel acceptingChannel = new AcceptingChannel() {
public ConnectedSslStreamChannel accept() throws IOException {
final SslConnection connection = server.accept();
return connection == null ? null : new AssembledConnectedSslStreamChannel(connection, connection.getSourceChannel(), connection.getSinkChannel());
}
public ChannelListener.Setter extends AcceptingChannel> getAcceptSetter() {
return ChannelListeners.getDelegatingSetter(server.getAcceptSetter(), this);
}
public ChannelListener.Setter extends AcceptingChannel> getCloseSetter() {
return ChannelListeners.getDelegatingSetter(server.getCloseSetter(), this);
}
public SocketAddress getLocalAddress() {
return server.getLocalAddress();
}
public A getLocalAddress(final Class type) {
return server.getLocalAddress(type);
}
public void suspendAccepts() {
server.suspendAccepts();
}
public void resumeAccepts() {
server.resumeAccepts();
}
public boolean isAcceptResumed() {
return server.isAcceptResumed();
}
public void wakeupAccepts() {
server.wakeupAccepts();
}
public void awaitAcceptable() throws IOException {
server.awaitAcceptable();
}
public void awaitAcceptable(final long time, final TimeUnit timeUnit) throws IOException {
server.awaitAcceptable(time, timeUnit);
}
public XnioWorker getWorker() {
return server.getWorker();
}
@Deprecated
public XnioExecutor getAcceptThread() {
return server.getAcceptThread();
}
public XnioIoThread getIoThread() {
return server.getIoThread();
}
public void close() throws IOException {
server.close();
}
public boolean isOpen() {
return server.isOpen();
}
public boolean supportsOption(final Option> option) {
return server.supportsOption(option);
}
public T getOption(final Option option) throws IOException {
return server.getOption(option);
}
public T setOption(final Option option, final T value) throws IllegalArgumentException, IOException {
return server.setOption(option, value);
}
};
acceptingChannel.getAcceptSetter().set(acceptListener);
return acceptingChannel;
}
public AcceptingChannel createSslConnectionServer(final XnioWorker worker, final InetSocketAddress bindAddress, final ChannelListener super AcceptingChannel> acceptListener, final OptionMap optionMap) throws IOException {
final JsseAcceptingSslStreamConnection server = new JsseAcceptingSslStreamConnection(sslContext, worker.createStreamConnectionServer(bindAddress, null, optionMap), optionMap, bufferPool, bufferPool, optionMap.get(Options.SSL_STARTTLS, false));
if (acceptListener != null) server.getAcceptSetter().set(acceptListener);
return server;
}
}