Core I/O components for Eclipse Jetty providing essential I/O utilities, buffer management, and network connection handling
—
Jetty IO provides comprehensive SSL/TLS support including secure connections, handshake management, and Application Layer Protocol Negotiation (ALPN) for modern protocol negotiation.
SSL/TLS connection wrapper that provides encryption layer over an existing EndPoint.
/**
* SSL/TLS connection wrapper providing encryption layer
*/
class SslConnection extends AbstractConnection implements Connection.UpgradeTo {
public SslConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, SSLEngine sslEngine);
public SslConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, SSLEngine sslEngine, boolean useInputDirectByteBuffers, boolean useOutputDirectByteBuffers);
// SSL engine access
public SSLEngine getSSLEngine();
// SSL session information
public String getProtocol();
public String getCipherSuite();
public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException;
public Principal getPeerPrincipal() throws SSLPeerUnverifiedException;
public Principal getLocalPrincipal();
// Connection state
public boolean isHandshaking();
public boolean isHandshakeComplete();
public boolean isOpen();
// Buffer configuration
public boolean isUseInputDirectByteBuffers();
public boolean isUseOutputDirectByteBuffers();
public void setUseInputDirectByteBuffers(boolean useInputDirectByteBuffers);
public void setUseOutputDirectByteBuffers(boolean useOutputDirectByteBuffers);
// Renegotiation
public void beginHandshake() throws SSLException;
public CompletableFuture<Void> handshake();
// Lifecycle
public void onOpen();
public void onClose(Throwable cause);
public void onFillable();
public boolean onIdleExpired(TimeoutException timeoutException);
// Connection upgrade support
public void onUpgradeTo(ByteBuffer prefilled);
// Statistics
public long getBytesIn();
public long getBytesOut();
public long getEncryptedBytesIn();
public long getEncryptedBytesOut();
}Usage Examples:
// Create SSL connection
SSLEngine sslEngine = sslContextFactory.newSSLEngine("example.com", 443);
sslEngine.setUseClientMode(true);
sslEngine.setWantClientAuth(false);
SslConnection sslConnection = new SslConnection(
byteBufferPool,
executor,
tcpEndPoint,
sslEngine
);
// Configure buffer usage (direct buffers can be more efficient for SSL)
sslConnection.setUseInputDirectByteBuffers(true);
sslConnection.setUseOutputDirectByteBuffers(true);
// Perform handshake
CompletableFuture<Void> handshakeFuture = sslConnection.handshake();
handshakeFuture.thenRun(() -> {
System.out.println("SSL handshake completed");
System.out.println("Protocol: " + sslConnection.getProtocol());
System.out.println("Cipher suite: " + sslConnection.getCipherSuite());
try {
Certificate[] peerCerts = sslConnection.getPeerCertificates();
System.out.println("Peer certificate count: " + peerCerts.length);
} catch (SSLPeerUnverifiedException e) {
System.out.println("Peer certificate not verified");
}
}).exceptionally(throwable -> {
System.err.println("SSL handshake failed: " + throwable.getMessage());
return null;
});
// Monitor SSL traffic
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.printf("SSL Traffic - Plain: %d/%d bytes, Encrypted: %d/%d bytes%n",
sslConnection.getBytesIn(), sslConnection.getBytesOut(),
sslConnection.getEncryptedBytesIn(), sslConnection.getEncryptedBytesOut());
}
}, 0, 10000);
// Manual renegotiation
if (sslConnection.isHandshakeComplete() && !sslConnection.isHandshaking()) {
try {
sslConnection.beginHandshake();
System.out.println("SSL renegotiation initiated");
} catch (SSLException e) {
System.err.println("Failed to initiate renegotiation: " + e.getMessage());
}
}Factory for creating SSL client connections with automatic SSL context configuration.
/**
* Creates SSL client connections
*/
class SslClientConnectionFactory implements ClientConnectionFactory {
public SslClientConnectionFactory(SslContextFactory.Client sslContextFactory, ClientConnectionFactory connectionFactory);
public SslClientConnectionFactory(SslContextFactory.Client sslContextFactory, String nextProtocol);
public Connection newConnection(EndPoint endPoint, Map<String, Object> context) throws IOException;
public Connection customize(Connection connection, Map<String, Object> context);
// Configuration
public SslContextFactory.Client getSslContextFactory();
public ClientConnectionFactory getClientConnectionFactory();
public String getNextProtocol();
// Direct buffer configuration
public boolean isDirectBuffersForEncryption();
public void setDirectBuffersForEncryption(boolean direct);
public boolean isDirectBuffersForDecryption();
public void setDirectBuffersForDecryption(boolean direct);
}Usage Examples:
// SSL context factory configuration
SslContextFactory.Client sslContextFactory = new SslContextFactory.Client();
sslContextFactory.setTrustAll(false); // Verify server certificates
sslContextFactory.setEndpointIdentificationAlgorithm("HTTPS"); // Enable hostname verification
sslContextFactory.setProtocol("TLS"); // Use TLS protocol
sslContextFactory.setIncludeCipherSuites("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384");
sslContextFactory.setExcludeCipherSuites("SSL_RSA_WITH_DES_CBC_SHA");
// HTTP/1.1 over SSL
ClientConnectionFactory http11Factory = new HttpClientConnectionFactory();
SslClientConnectionFactory sslFactory = new SslClientConnectionFactory(sslContextFactory, http11Factory);
// Direct SSL factory for specific protocol
SslClientConnectionFactory directSslFactory = new SslClientConnectionFactory(sslContextFactory, "http/1.1");
// Configure direct buffers for better performance
sslFactory.setDirectBuffersForEncryption(true);
sslFactory.setDirectBuffersForDecryption(true);
// Create SSL connection
Map<String, Object> context = new HashMap<>();
context.put(ClientConnectionFactory.CLIENT_CONTEXT_KEY, httpClient);
context.put(SslClientConnectionFactory.SSL_CONTEXT_FACTORY_CONTEXT_KEY, sslContextFactory);
Connection sslConnection = sslFactory.newConnection(tcpEndPoint, context);
// Chain multiple factories for protocol layering
ClientConnectionFactory http2Factory = new HTTP2ClientConnectionFactory();
SslClientConnectionFactory http2SslFactory = new SslClientConnectionFactory(sslContextFactory, http2Factory);
// ALPN negotiation factory
ALPNClientConnectionFactory alpnFactory = new ALPNClientConnectionFactory(
executor, http2SslFactory, "h2", "http/1.1");
SslClientConnectionFactory alpnSslFactory = new SslClientConnectionFactory(sslContextFactory, alpnFactory);Event listener for monitoring SSL/TLS handshake process and outcomes.
/**
* Listener for SSL handshake events
*/
interface SslHandshakeListener extends EventListener {
/** Called when SSL handshake succeeds */
default void handshakeSucceeded(Event event) {}
/** Called when SSL handshake fails */
default void handshakeFailed(Event event, Throwable failure) {}
class Event {
private final SSLEngine sslEngine;
public Event(SSLEngine sslEngine);
public SSLEngine getSSLEngine();
public String getProtocol();
public String getCipherSuite();
public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException;
public Principal getPeerPrincipal() throws SSLPeerUnverifiedException;
public Principal getLocalPrincipal();
}
}Usage Examples:
// SSL handshake monitoring
SslHandshakeListener handshakeMonitor = new SslHandshakeListener() {
@Override
public void handshakeSucceeded(Event event) {
System.out.println("SSL handshake succeeded:");
System.out.println(" Protocol: " + event.getProtocol());
System.out.println(" Cipher: " + event.getCipherSuite());
try {
Certificate[] certs = event.getPeerCertificates();
if (certs.length > 0 && certs[0] instanceof X509Certificate) {
X509Certificate x509 = (X509Certificate) certs[0];
System.out.println(" Subject: " + x509.getSubjectDN());
System.out.println(" Issuer: " + x509.getIssuerDN());
System.out.println(" Valid until: " + x509.getNotAfter());
}
} catch (SSLPeerUnverifiedException e) {
System.out.println(" Peer not verified: " + e.getMessage());
}
}
@Override
public void handshakeFailed(Event event, Throwable failure) {
System.err.println("SSL handshake failed: " + failure.getMessage());
if (failure instanceof SSLException) {
SSLException sslEx = (SSLException) failure;
System.err.println("SSL error details: " + sslEx.toString());
}
}
};
// Add listener to SSL context factory
sslContextFactory.addEventListener(handshakeMonitor);
// Certificate validation listener
SslHandshakeListener certValidator = new SslHandshakeListener() {
@Override
public void handshakeSucceeded(Event event) {
try {
Certificate[] certs = event.getPeerCertificates();
validateCertificateChain(certs);
} catch (Exception e) {
System.err.println("Certificate validation failed: " + e.getMessage());
}
}
private void validateCertificateChain(Certificate[] certs) throws Exception {
// Custom certificate validation logic
if (certs.length == 0) {
throw new SSLException("No certificates provided");
}
X509Certificate serverCert = (X509Certificate) certs[0];
// Check certificate validity period
serverCert.checkValidity();
// Check certificate purpose
List<String> extKeyUsage = serverCert.getExtendedKeyUsage();
if (extKeyUsage != null && !extKeyUsage.contains("1.3.6.1.5.5.7.3.1")) { // Server authentication
throw new SSLException("Certificate not valid for server authentication");
}
System.out.println("Certificate validation passed");
}
};Interface for handling Application Layer Protocol Negotiation (ALPN) during SSL handshake.
/**
* Interface for ALPN (Application Layer Protocol Negotiation) processing
*/
interface ALPNProcessor {
/**
* Process ALPN negotiation result
* @param sslEngine the SSL engine
* @param protocols list of protocols offered by client
* @param selected the protocol selected by server
*/
void process(SSLEngine sslEngine, List<String> protocols, String selected);
// Server-side ALPN processor
abstract class Server implements ALPNProcessor {
/** Select protocol from client's list */
public abstract String select(List<String> protocols);
public void process(SSLEngine sslEngine, List<String> protocols, String selected);
}
// Client-side ALPN processor
abstract class Client implements ALPNProcessor {
private final List<String> protocols;
protected Client(String... protocols);
/** Handle selected protocol */
public abstract void selected(String protocol);
public List<String> getProtocols();
public void process(SSLEngine sslEngine, List<String> protocols, String selected);
}
}ALPN Usage Examples:
// Server-side ALPN processor
ALPNProcessor.Server serverALPN = new ALPNProcessor.Server() {
@Override
public String select(List<String> protocols) {
System.out.println("Client offered protocols: " + protocols);
// Prefer HTTP/2, fallback to HTTP/1.1
if (protocols.contains("h2")) {
return "h2";
} else if (protocols.contains("http/1.1")) {
return "http/1.1";
}
return null; // No supported protocol
}
@Override
public void process(SSLEngine sslEngine, List<String> protocols, String selected) {
System.out.println("Selected protocol: " + selected);
super.process(sslEngine, protocols, selected);
}
};
// Client-side ALPN processor
ALPNProcessor.Client clientALPN = new ALPNProcessor.Client("h2", "http/1.1") {
@Override
public void selected(String protocol) {
System.out.println("Server selected protocol: " + protocol);
switch (protocol) {
case "h2":
// Configure for HTTP/2
configureHTTP2();
break;
case "http/1.1":
// Configure for HTTP/1.1
configureHTTP11();
break;
default:
System.err.println("Unexpected protocol selected: " + protocol);
}
}
private void configureHTTP2() {
System.out.println("Initializing HTTP/2 configuration");
// HTTP/2 specific setup
}
private void configureHTTP11() {
System.out.println("Initializing HTTP/1.1 configuration");
// HTTP/1.1 specific setup
}
};
// Register ALPN processors with SSL context factory
sslContextFactory.addBean(serverALPN); // Server side
sslContextFactory.addBean(clientALPN); // Client side
// Custom ALPN processor for protocol-specific handling
ALPNProcessor customProcessor = new ALPNProcessor() {
@Override
public void process(SSLEngine sslEngine, List<String> protocols, String selected) {
System.out.println("ALPN negotiation completed");
System.out.println("Offered: " + protocols);
System.out.println("Selected: " + selected);
// Store selected protocol for later use
sslEngine.setHandshakeApplicationProtocolSelector((sslEngine1, protocols1) -> {
// Custom protocol selection logic
return selectCustomProtocol(protocols1);
});
}
private String selectCustomProtocol(List<String> protocols) {
// Custom protocol selection algorithm
for (String protocol : protocols) {
if (protocol.startsWith("custom-")) {
return protocol;
}
}
return protocols.isEmpty() ? null : protocols.get(0);
}
};/**
* SSL context factory configuration examples
*/
class SSLConfigurationExamples {
public static SslContextFactory.Client createSecureClient() {
SslContextFactory.Client factory = new SslContextFactory.Client();
// Security settings
factory.setTrustAll(false); // Always verify certificates
factory.setEndpointIdentificationAlgorithm("HTTPS"); // Enable hostname verification
factory.setRenegotiationAllowed(false); // Disable renegotiation for security
// Protocol configuration
factory.setProtocol("TLS");
factory.setIncludeProtocols("TLSv1.2", "TLSv1.3");
factory.setExcludeProtocols("SSLv2", "SSLv3", "TLSv1", "TLSv1.1");
// Cipher suite configuration
factory.setIncludeCipherSuites(
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"
);
factory.setExcludeCipherSuites(
".*_DES_.*", ".*_RC4_.*", ".*_MD5$", ".*_SHA$"
);
return factory;
}
public static SslContextFactory.Server createSecureServer(Path keystorePath, String keystorePassword) {
SslContextFactory.Server factory = new SslContextFactory.Server();
// Keystore configuration
factory.setKeyStorePath(keystorePath.toString());
factory.setKeyStorePassword(keystorePassword);
factory.setKeyStoreType("PKCS12");
// Client authentication
factory.setWantClientAuth(true); // Request client certificates
factory.setNeedClientAuth(false); // But don't require them
// Security settings
factory.setRenegotiationAllowed(false);
factory.setSessionCachingEnabled(true);
factory.setSessionTimeout(3600); // 1 hour session timeout
// Protocol and cipher configuration (same as client)
factory.setProtocol("TLS");
factory.setIncludeProtocols("TLSv1.2", "TLSv1.3");
// ... cipher suites as above
return factory;
}
}Configuration Usage:
// Secure client configuration
SslContextFactory.Client clientSSL = SSLConfigurationExamples.createSecureClient();
// Custom truststore for client
clientSSL.setTrustStorePath("/path/to/truststore.p12");
clientSSL.setTrustStorePassword("truststore-password");
clientSSL.setTrustStoreType("PKCS12");
// Client certificate authentication
clientSSL.setKeyStorePath("/path/to/client-keystore.p12");
clientSSL.setKeyStorePassword("client-keystore-password");
// SNI (Server Name Indication) configuration
clientSSL.setSNIMatchers(
new SNIMatcher(StandardConstants.SNI_HOST_NAME) {
@Override
public boolean matches(SNIServerName serverName) {
return serverName.getAsciiName().endsWith(".example.com");
}
}
);
// Start SSL context factory
clientSSL.start();
// Create SSL connection factory
ClientConnectionFactory httpFactory = new HttpClientConnectionFactory();
SslClientConnectionFactory sslFactory = new SslClientConnectionFactory(clientSSL, httpFactory);Install with Tessl CLI
npx tessl i tessl/maven-org-eclipse-jetty--jetty-io