All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.ipokerface.aps.channel.ChannelFactory Maven / Gradle / Ivy

The newest version!
package cn.ipokerface.aps.channel;

import cn.ipokerface.aps.Constant;
import cn.ipokerface.aps.ObjectFactory;
import cn.ipokerface.aps.auth.ApnsSignKey;
import cn.ipokerface.aps.handler.ApnsClientChannelHandler;
import cn.ipokerface.aps.handler.TokenAuthenticationClientChannelHandler;
import cn.ipokerface.aps.utils.ClientChannelClassUtil;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http2.Http2FrameLogger;
import io.netty.handler.flush.FlushConsolidationHandler;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.resolver.AddressResolverGroup;
import io.netty.util.ReferenceCounted;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.Promise;
import io.netty.util.concurrent.PromiseNotifier;

import java.io.Closeable;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

/**
 * Created by       PokerFace
 * Create Date      2020-08-24.
 * Email:           [email protected]
 * Version          1.0.0
 * 

* Description: */ public class ChannelFactory implements ObjectFactory, Closeable { private static final long MIN_CONNECT_DELAY_SECONDS = 1; private static final long MAX_CONNECT_DELAY_SECONDS = 60; private SslContext sslContext; private Bootstrap bootstrap; private EventLoopGroup eventLoopGroup; private AddressResolverGroup addressResolverGroup; private Duration connectTimeout; private InetSocketAddress remoteAddress; private final AtomicLong currentDelaySeconds = new AtomicLong(0); private final AtomicBoolean releasedSslContenxt = new AtomicBoolean(false); public ChannelFactory(InetSocketAddress address,EventLoopGroup eventLoopGroup, SslContext sslContext, ApnsSignKey signKey, Duration tokenExpiration, Duration connectTimeout, Duration idleInterval, Http2FrameLogger logger, String defaultTopic) { this.remoteAddress = address; this.sslContext = sslContext; if (this.sslContext instanceof ReferenceCounted) { ((ReferenceCounted) this.sslContext).retain(); } this.eventLoopGroup = eventLoopGroup; // this.addressResolverGroup = new RoundRobinDnsAddressResolverGroup( // ClientChannelClassUtil.getDatagramChannelClass(eventLoopGroup), // DefaultDnsServerAddressStreamProvider.INSTANCE); this.bootstrap = new Bootstrap() .option(ChannelOption.TCP_NODELAY, true) // .option(ChannelOption.SO_KEEPALIVE, true) // .resolver(addressResolverGroup) .remoteAddress(remoteAddress) .group(eventLoopGroup); if (connectTimeout != null) { this.bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, (int) connectTimeout.toMillis()); } this.bootstrap.handler(new ChannelInitializer() { @Override protected void initChannel(SocketChannel channel) { final SslHandler sslHandler = ChannelFactory.this.sslContext.newHandler(channel.alloc()); final ApnsClientChannelHandler handler; final String authority = address.getHostName(); final ApnsClientChannelHandler.ApnsClientChannelHandlerBuilder builder; if (signKey != null) { builder = new TokenAuthenticationClientChannelHandler.TokenAuthenticationApnsClientHandlerBuilder() .signingKey(signKey) .tokenExpiration(tokenExpiration) .authority(authority) .defaultTopic(defaultTopic) .idleInterval(idleInterval); } else { builder = new ApnsClientChannelHandler.ApnsClientChannelHandlerBuilder() .authority(authority) .defaultTopic(defaultTopic) .idleInterval(idleInterval); } if (logger != null) { builder.frameLogger(logger); } handler = builder.build(); final ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(sslHandler); pipeline.addLast(new FlushConsolidationHandler(FlushConsolidationHandler.DEFAULT_EXPLICIT_FLUSH_AFTER_FLUSHES, true)); pipeline.addLast(new IdleStateHandler(idleInterval.toMillis(), 0, 0, TimeUnit.MILLISECONDS)); pipeline.addLast(handler); } }); } @Override public Future create(Promise promise) { final long delay = this.currentDelaySeconds.get(); promise.addListener(future -> { final long updatedDelay = future.isSuccess() ? 0 : Math.max(Math.min(delay * 2, MAX_CONNECT_DELAY_SECONDS), MIN_CONNECT_DELAY_SECONDS); ChannelFactory.this.currentDelaySeconds.compareAndSet(delay, updatedDelay); }); this.bootstrap.config().group().schedule(() -> { final Bootstrap bootstrap = ChannelFactory.this.bootstrap.clone() .channelFactory(new AugmentingReflectiveChannelFactory( ClientChannelClassUtil.getSocketChannelClass(ChannelFactory.this.bootstrap.config().group()), Constant.channel_ready_promise_attribute_key, promise)); final ChannelFuture connectFuture = bootstrap.connect(); connectFuture.addListener(future -> { if (!future.isSuccess()) { promise.tryFailure(future.cause()); } }); }, delay, TimeUnit.SECONDS); return promise; } @Override public Future destroy(Channel channel, Promise promise) { channel.close().addListener(new PromiseNotifier<>(promise)); return promise; } @Override public void close() { try { this.addressResolverGroup.close(); } finally { if (this.sslContext instanceof ReferenceCounted) { if (this.releasedSslContenxt.compareAndSet(false, true)) { ((ReferenceCounted) this.sslContext).release(); } } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy