package org.glassfish.grizzly.http2;
import java.util.logging.Logger;
import org.glassfish.grizzly.Grizzly;
import org.glassfish.grizzly.Transport;
import org.glassfish.grizzly.filterchain.FilterChainBuilder;
import org.glassfish.grizzly.http.server.AddOn;
import org.glassfish.grizzly.http.server.NetworkListener;
import org.glassfish.grizzly.nio.transport.TCPNIOTransport;
import org.glassfish.grizzly.ssl.SSLBaseFilter;
import org.glassfish.grizzly.ssl.SSLFilter;
public class Http2AddOn implements AddOn {
private static final Logger LOGGER = Grizzly.logger(Http2AddOn.class);
private final Http2Configuration http2Configuration;
public Http2AddOn() {
this(Http2Configuration.builder().build());
}
public Http2AddOn(final Http2Configuration http2Configuration) {
this.http2Configuration = http2Configuration;
}
@Override
public void setup(NetworkListener networkListener, FilterChainBuilder builder) {
LOGGER.config(() -> String.format("setup(networkListener=%s, builder=%s)", networkListener, builder));
final TCPNIOTransport transport = networkListener.getTransport();
if (networkListener.isSecure() && !AlpnSupport.isEnabled()) {
LOGGER.warning("TLS ALPN (Application-Layer Protocol Negotiation) support is not available."
+ " HTTP/2 support will not be enabled.");
return;
}
final Http2ServerFilter http2Filter = updateFilterChain(builder);
if (networkListener.isSecure()) {
configureAlpn(transport, http2Filter, builder);
}
}
public Http2Configuration getConfiguration() {
return http2Configuration;
}
private Http2ServerFilter updateFilterChain(final FilterChainBuilder builder) {
final int codecFilterIdx = builder.indexOfType(org.glassfish.grizzly.http.HttpServerFilter.class);
final Http2ServerFilter http2HandlerFilter = new Http2ServerFilter(http2Configuration);
http2HandlerFilter.setLocalMaxFramePayloadSize(http2Configuration.getMaxFramePayloadSize());
builder.add(codecFilterIdx + 1, http2HandlerFilter);
return http2HandlerFilter;
}
private static void configureAlpn(final Transport transport,
final Http2ServerFilter http2Filter,
final FilterChainBuilder builder) {
LOGGER.finest(() -> String.format("configureAlpn(transport=%s, http2Filter=%s, builder=%s)",
transport, http2Filter, builder));
final int idx = builder.indexOfType(SSLBaseFilter.class);
if (idx == -1) {
LOGGER.warning("No usable SSLBaseFilter found!");
return;
}
final SSLBaseFilter sslFilter = (SSLBaseFilter) builder.get(idx);
AlpnSupport.getInstance().configure(sslFilter);
AlpnSupport.getInstance().setServerSideNegotiator(transport, new AlpnServerNegotiatorImpl(http2Filter));
}
}