All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.github.yawenok.apns.http2.impl.initializer.Http2ClientInitializer Maven / Gradle / Ivy
package io.github.yawenok.apns.http2.impl.initializer;
import io.github.yawenok.apns.http2.impl.handler.HttpResponseHandler;
import io.github.yawenok.apns.http2.impl.model.ResponseFuture;
import io.github.yawenok.apns.http2.config.ProxyConfig;
import io.github.yawenok.apns.http2.impl.NettyHelper;
import io.github.yawenok.apns.http2.impl.handler.Http2PingHandler;
import io.github.yawenok.apns.http2.impl.handler.Http2SettingsHandler;
import io.github.yawenok.apns.http2.impl.model.ResponseFutureCallback;
import io.netty.channel.*;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http2.*;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.proxy.ProxyHandler;
import io.netty.handler.ssl.ApplicationProtocolNames;
import io.netty.handler.ssl.ApplicationProtocolNegotiationHandler;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.handler.timeout.IdleStateHandler;
import java.util.concurrent.TimeUnit;
public class Http2ClientInitializer extends ChannelInitializer {
private SslContext sslContext;
private ProxyConfig proxyConfig;
private HttpResponseHandler responseHandler = new HttpResponseHandler();
private Http2SettingsHandler settingsHandler;
public Http2ClientInitializer(SslContext sslContext, ProxyConfig proxyConfig) {
if (sslContext == null) {
throw new IllegalArgumentException("sslContext can not be null!");
}
this.sslContext = sslContext;
this.proxyConfig = proxyConfig;
}
public ResponseFuture putResponseFuture(final String apnsId, final ResponseFuture responseFuture) {
return responseHandler.putResponseFuture(apnsId, responseFuture);
}
public ResponseFutureCallback putResponseFutureCallback(final String apnsId, final ResponseFutureCallback responseFutureCallback) {
return responseHandler.putResponseFutureCallback(apnsId, responseFutureCallback);
}
public Object cleanApns(final String apnsId) {
return responseHandler.cleanApns(apnsId);
}
public void awaitSettings(final long timeout, final TimeUnit unit) {
settingsHandler.awaitSettings(timeout, unit);
}
@Override
public void initChannel(final SocketChannel channel) throws Exception {
ProxyHandler proxyHandler = null;
if (proxyConfig != null) {
proxyHandler = NettyHelper.getProxyHandler(proxyConfig);
}
settingsHandler = new Http2SettingsHandler(channel.newPromise());
// 将Http2转化为Http1协议进行解析
Http2Connection connection = new DefaultHttp2Connection(false);
InboundHttp2ToHttpAdapter adapter = new InboundHttp2ToHttpAdapterBuilder(connection).maxContentLength(Integer.MAX_VALUE).propagateSettings(true).build();
HttpToHttp2ConnectionHandlerBuilder builder = new HttpToHttp2ConnectionHandlerBuilder();
builder.frameListener(new DelegatingDecompressorFrameListener(connection, adapter));
builder.frameLogger(new Http2FrameLogger(LogLevel.TRACE, "Apns Http2 Logger"));
HttpToHttp2ConnectionHandler connectionHandler = builder.connection(connection).build();
Http2PingHandler pingHandler = new Http2PingHandler(connectionHandler.encoder());
configureSSL(sslContext, channel, proxyHandler, connectionHandler, settingsHandler, pingHandler, responseHandler);
}
/**
* Configure the pipeline for TLS NPN negotiation to HTTP/2.
*/
private void configureSSL(final SslContext sslContext,
final SocketChannel channel,
final ProxyHandler proxyHandler,
final HttpToHttp2ConnectionHandler connectionHandler,
final Http2SettingsHandler settingsHandler,
final Http2PingHandler pingHandler,
final HttpResponseHandler responseHandler) {
ChannelPipeline pipeline = channel.pipeline();
if (proxyHandler != null) {
pipeline.addFirst(proxyHandler);
}
pipeline.addLast(sslContext.newHandler(channel.alloc()));
pipeline.addLast(new ProtocolNegotiationHandler("", connectionHandler, settingsHandler, pingHandler, responseHandler));
// Http2 can keep a connection
pipeline.addLast(new IdleStateHandler(0, pingHandler.getMaxIdle(), 0));
pipeline.addLast(new IdleUserHandler());
}
/**
* We must wait for the handshake to finish and the protocol to be negotiated before configuring the HTTP/2 components of the pipeline.
*/
private final class ProtocolNegotiationHandler extends ApplicationProtocolNegotiationHandler {
private final HttpToHttp2ConnectionHandler connectionHandler;
private final Http2SettingsHandler settingsHandler;
private final Http2PingHandler pingHandler;
private final HttpResponseHandler responseHandler;
/**
* Creates a new instance with the specified fallback protocol name.
*
* @param fallbackProtocol the name of the protocol to use when
* ALPN/NPN negotiation fails or the client does not support ALPN/NPN
*/
public ProtocolNegotiationHandler(String fallbackProtocol,
HttpToHttp2ConnectionHandler connectionHandler,
Http2SettingsHandler settingsHandler,
Http2PingHandler pingHandler,
HttpResponseHandler responseHandler) {
super(fallbackProtocol);
this.connectionHandler = connectionHandler;
this.settingsHandler = settingsHandler;
this.pingHandler = pingHandler;
this.responseHandler = responseHandler;
}
@Override
protected void configurePipeline(ChannelHandlerContext ctx, String protocol) throws Exception {
if (ApplicationProtocolNames.HTTP_2.equals(protocol)) {
ChannelPipeline pipeline = ctx.pipeline();
pipeline.addLast(connectionHandler);
pipeline.addLast(settingsHandler, pingHandler, responseHandler);
return;
}
ctx.close();
throw new IllegalStateException("Unknown protocol: " + protocol);
}
}
/**
* Handle idle event
*/
private final class IdleUserHandler extends ChannelInboundHandlerAdapter {
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
super.userEventTriggered(ctx, evt);
if (IdleStateEvent.class.isAssignableFrom(evt.getClass())) {
IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
if (idleStateEvent.state() == IdleState.WRITER_IDLE) {
// 发送Ping消息
ctx.channel().write(Http2PingHandler.PING);
}
}
}
}
}