List of usage examples for io.netty.channel ChannelFuture cause
Throwable cause();
From source file:com.relayrides.pushy.apns.ApnsConnection.java
License:Open Source License
/** * Asynchronously connects to the APNs gateway in this connection's environment. The outcome of the connection * attempt is reported via this connection's listener. * * @see ApnsConnectionListener#handleConnectionSuccess(ApnsConnection) * @see ApnsConnectionListener#handleConnectionFailure(ApnsConnection, Throwable) *//*from w w w .j ava 2s .c o m*/ @SuppressWarnings("deprecation") public synchronized void connect() { final ApnsConnection<T> apnsConnection = this; if (this.connectFuture != null) { throw new IllegalStateException(String.format("%s already started a connection attempt.", this.name)); } final Bootstrap bootstrap = new Bootstrap(); bootstrap.group(this.eventLoopGroup); bootstrap.channel(NioSocketChannel.class); bootstrap.option(ChannelOption.SO_KEEPALIVE, true); bootstrap.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT); // TODO Remove this when Netty 5 is available bootstrap.option(ChannelOption.AUTO_CLOSE, false); bootstrap.handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(final SocketChannel channel) { final ChannelPipeline pipeline = channel.pipeline(); final SSLEngine sslEngine = apnsConnection.sslContext.createSSLEngine(); sslEngine.setUseClientMode(true); pipeline.addLast("ssl", new SslHandler(sslEngine)); pipeline.addLast("decoder", new RejectedNotificationDecoder()); pipeline.addLast("encoder", new ApnsPushNotificationEncoder()); pipeline.addLast("handler", new ApnsConnectionHandler(apnsConnection)); } }); log.debug("{} beginning connection process.", apnsConnection.name); this.connectFuture = bootstrap.connect(this.environment.getApnsGatewayHost(), this.environment.getApnsGatewayPort()); this.connectFuture.addListener(new GenericFutureListener<ChannelFuture>() { public void operationComplete(final ChannelFuture connectFuture) { if (connectFuture.isSuccess()) { log.debug("{} connected; waiting for TLS handshake.", apnsConnection.name); final SslHandler sslHandler = connectFuture.channel().pipeline().get(SslHandler.class); try { sslHandler.handshakeFuture().addListener(new GenericFutureListener<Future<Channel>>() { public void operationComplete(final Future<Channel> handshakeFuture) { if (handshakeFuture.isSuccess()) { log.debug("{} successfully completed TLS handshake.", apnsConnection.name); apnsConnection.handshakeCompleted = true; apnsConnection.listener.handleConnectionSuccess(apnsConnection); } else { log.debug("{} failed to complete TLS handshake with APNs gateway.", apnsConnection.name, handshakeFuture.cause()); connectFuture.channel().close(); apnsConnection.listener.handleConnectionFailure(apnsConnection, handshakeFuture.cause()); } } }); } catch (NullPointerException e) { log.warn("{} failed to get SSL handler and could not wait for a TLS handshake.", apnsConnection.name); connectFuture.channel().close(); apnsConnection.listener.handleConnectionFailure(apnsConnection, e); } } else { log.debug("{} failed to connect to APNs gateway.", apnsConnection.name, connectFuture.cause()); apnsConnection.listener.handleConnectionFailure(apnsConnection, connectFuture.cause()); } } }); }
From source file:com.relayrides.pushy.apns.ApnsConnection.java
License:Open Source License
/** * Asynchronously sends a push notification to the connected APNs gateway. Successful notifications are * <strong>not</strong> acknowledged by the APNs gateway; failed attempts to write push notifications to the * outbound buffer and notification rejections are reported via this connection's listener. * * @param notification the notification to send * * @see ApnsConnectionListener#handleWriteFailure(ApnsConnection, ApnsPushNotification, Throwable) * @see ApnsConnectionListener#handleRejectedNotification(ApnsConnection, ApnsPushNotification, RejectedNotificationReason) *///from w ww . j a v a 2 s . c o m public synchronized void sendNotification(final T notification) { final ApnsConnection<T> apnsConnection = this; if (!this.handshakeCompleted) { throw new IllegalStateException(String.format("%s has not completed handshake.", this.name)); } this.connectFuture.channel().eventLoop().execute(new Runnable() { public void run() { final SendableApnsPushNotification<T> sendableNotification = new SendableApnsPushNotification<T>( notification, apnsConnection.sequenceNumber++); log.trace("{} sending {}", apnsConnection.name, sendableNotification); apnsConnection.pendingWriteCount += 1; apnsConnection.connectFuture.channel().writeAndFlush(sendableNotification) .addListener(new GenericFutureListener<ChannelFuture>() { public void operationComplete(final ChannelFuture writeFuture) { if (writeFuture.isSuccess()) { log.trace("{} successfully wrote notification {}", apnsConnection.name, sendableNotification.getSequenceNumber()); if (apnsConnection.rejectionReceived) { // Even though the write succeeded, we know for sure that this notification was never // processed by the gateway because it had already rejected another notification from // this connection. apnsConnection.listener.handleUnprocessedNotifications(apnsConnection, java.util.Collections.singletonList(notification)); } else { apnsConnection.sentNotificationBuffer .addSentNotification(sendableNotification); } } else { log.trace("{} failed to write notification {}", apnsConnection.name, sendableNotification, writeFuture.cause()); // Assume this is a temporary failure (we know it's not a permanent rejection because we didn't // even manage to write the notification to the wire) and re-enqueue for another send attempt. apnsConnection.listener.handleWriteFailure(apnsConnection, notification, writeFuture.cause()); } apnsConnection.pendingWriteCount -= 1; assert apnsConnection.pendingWriteCount >= 0; if (apnsConnection.pendingWriteCount == 0) { synchronized (apnsConnection.pendingWriteMonitor) { apnsConnection.pendingWriteMonitor.notifyAll(); } } } }); } }); }
From source file:com.relayrides.pushy.apns.ApnsConnection.java
License:Open Source License
/** * <p>Gracefully and asynchronously shuts down this connection. Graceful disconnection is triggered by sending a * known-bad notification to the APNs gateway; when the gateway rejects the notification, it is guaranteed that * preceding notifications were processed successfully and that all following notifications were not processed at * all. The gateway will close the connection after rejecting the notification, and this connection's listener will * be notified when the connection is closed.</p> * * <p>Note that if/when the known-bad notification is rejected by the APNs gateway, this connection's listener will * <em>not</em> be notified of the rejection.</p> * * <p>Calling this method before establishing a connection with the APNs gateway or while a graceful shutdown * attempt is already in progress has no effect.</p> * * @see ApnsConnectionListener#handleRejectedNotification(ApnsConnection, ApnsPushNotification, RejectedNotificationReason) * @see ApnsConnectionListener#handleConnectionClosure(ApnsConnection) */// w w w . j ava 2s . c om public synchronized void shutdownGracefully() { final ApnsConnection<T> apnsConnection = this; // We only need to send a known-bad notification if we were ever connected in the first place and if we're // still connected. if (this.handshakeCompleted && this.connectFuture.channel().isActive()) { this.connectFuture.channel().eventLoop().execute(new Runnable() { public void run() { // Don't send a second shutdown notification if we've already started the graceful shutdown process. if (apnsConnection.shutdownNotification == null) { log.debug("{} sending known-bad notification to shut down.", apnsConnection.name); apnsConnection.shutdownNotification = new SendableApnsPushNotification<KnownBadPushNotification>( new KnownBadPushNotification(), apnsConnection.sequenceNumber++); apnsConnection.pendingWriteCount += 1; apnsConnection.connectFuture.channel().writeAndFlush(apnsConnection.shutdownNotification) .addListener(new GenericFutureListener<ChannelFuture>() { public void operationComplete(final ChannelFuture future) { if (future.isSuccess()) { log.trace("{} successfully wrote known-bad notification {}", apnsConnection.name, apnsConnection.shutdownNotification.getSequenceNumber()); } else { log.trace("{} failed to write known-bad notification {}", apnsConnection.name, apnsConnection.shutdownNotification, future.cause()); // Try again! apnsConnection.shutdownNotification = null; apnsConnection.shutdownGracefully(); } apnsConnection.pendingWriteCount -= 1; assert apnsConnection.pendingWriteCount >= 0; if (apnsConnection.pendingWriteCount == 0) { synchronized (apnsConnection.pendingWriteMonitor) { apnsConnection.pendingWriteMonitor.notifyAll(); } } } }); } } }); } else { // While we can't guarantee that the handshake won't complete in another thread, we CAN guarantee that no // new notifications will be sent until shutdownImmediately happens because everything is synchronized. this.shutdownImmediately(); } }
From source file:com.relayrides.pushy.apns.FeedbackServiceClient.java
License:Open Source License
/** * <p>Retrieves a list of expired tokens from the APNs feedback service. Be warned that this is a * <strong>destructive operation</strong>. According to Apple's documentation:</p> * * <blockquote>The feedback service's list is cleared after you read it. Each time you connect to the feedback * service, the information it returns lists only the failures that have happened since you last * connected.</blockquote>/*from w w w. jav a 2 s .com*/ * * @param timeout the time after the last received data after which the connection to the feedback service should * be closed * @param timeoutUnit the unit of time in which the given {@code timeout} is measured * * @return a list of tokens that have expired since the last connection to the feedback service * * @throws InterruptedException if interrupted while waiting for a response from the feedback service * @throws FeedbackConnectionException if the connection to the feedback service failed for any reason */ public synchronized List<ExpiredToken> getExpiredTokens(final long timeout, final TimeUnit timeoutUnit) throws InterruptedException, FeedbackConnectionException { this.expiredTokens.clear(); final Bootstrap bootstrap = new Bootstrap(); bootstrap.group(this.eventLoopGroup); bootstrap.channel(NioSocketChannel.class); final FeedbackServiceClient feedbackClient = this; bootstrap.handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(final SocketChannel channel) throws Exception { final ChannelPipeline pipeline = channel.pipeline(); final SSLEngine sslEngine = feedbackClient.sslContext.createSSLEngine(); sslEngine.setUseClientMode(true); pipeline.addLast("ssl", new SslHandler(sslEngine)); pipeline.addLast("readTimeoutHandler", new ReadTimeoutHandler(timeout, timeoutUnit)); pipeline.addLast("decoder", new ExpiredTokenDecoder()); pipeline.addLast("handler", new FeedbackClientHandler(feedbackClient)); } }); final ChannelFuture connectFuture = bootstrap .connect(this.environment.getFeedbackHost(), this.environment.getFeedbackPort()).await(); if (connectFuture.isSuccess()) { log.debug("Connected to feedback service."); final SslHandler sslHandler = connectFuture.channel().pipeline().get(SslHandler.class); if (sslHandler != null) { final Future<Channel> handshakeFuture = sslHandler.handshakeFuture().await(); if (handshakeFuture.isSuccess()) { log.debug("Completed TLS handshake with feedback service."); // The feedback service will send us a list of device tokens as soon as we complete the SSL // handshake, then hang up. While we're waiting to sync with the connection closure, we'll be // receiving messages from the feedback service from another thread. connectFuture.channel().closeFuture().await(); } else { log.debug("Failed to complete TLS handshake with feedback service.", handshakeFuture.cause()); connectFuture.channel().close().await(); throw new FeedbackConnectionException(handshakeFuture.cause()); } } else { log.warn("Feedback client failed to get SSL handler and could not wait for TLS handshake."); connectFuture.channel().close().await(); throw new FeedbackConnectionException(null); } } else { log.debug("Failed to connect to feedback service.", connectFuture.cause()); throw new FeedbackConnectionException(connectFuture.cause()); } return new ArrayList<ExpiredToken>(this.expiredTokens); }
From source file:com.relayrides.pushy.apns.FeedbackServiceConnection.java
License:Open Source License
/** * <p>Connects to the APNs feedback service and waits for expired tokens to arrive. Be warned that this is a * <strong>destructive operation</strong>. According to Apple's documentation:</p> * * <blockquote>The feedback service's list is cleared after you read it. Each time you connect to the feedback * service, the information it returns lists only the failures that have happened since you last * connected.</blockquote>/*from w w w . j a v a 2 s . c o m*/ */ public synchronized void connect() { if (this.connectFuture != null) { throw new IllegalStateException(String.format("%s already started a connection attempt.", this.name)); } final Bootstrap bootstrap = new Bootstrap(); bootstrap.group(this.eventLoopGroup); bootstrap.channel(NioSocketChannel.class); final FeedbackServiceConnection feedbackConnection = this; bootstrap.handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(final SocketChannel channel) throws Exception { final ChannelPipeline pipeline = channel.pipeline(); final SSLEngine sslEngine = feedbackConnection.sslContext.createSSLEngine(); sslEngine.setUseClientMode(true); pipeline.addLast("ssl", new SslHandler(sslEngine)); pipeline.addLast("readTimeoutHandler", new ReadTimeoutHandler(feedbackConnection.configuration.getReadTimeout())); pipeline.addLast("decoder", new ExpiredTokenDecoder()); pipeline.addLast("handler", new FeedbackClientHandler(feedbackConnection)); } }); this.connectFuture = bootstrap.connect(this.environment.getFeedbackHost(), this.environment.getFeedbackPort()); this.connectFuture.addListener(new GenericFutureListener<ChannelFuture>() { @Override public void operationComplete(final ChannelFuture connectFuture) { if (connectFuture.isSuccess()) { log.debug("{} connected; waiting for TLS handshake.", feedbackConnection.name); final SslHandler sslHandler = connectFuture.channel().pipeline().get(SslHandler.class); try { sslHandler.handshakeFuture().addListener(new GenericFutureListener<Future<Channel>>() { @Override public void operationComplete(final Future<Channel> handshakeFuture) { if (handshakeFuture.isSuccess()) { log.debug("{} successfully completed TLS handshake.", feedbackConnection.name); if (feedbackConnection.listener != null) { feedbackConnection.listener.handleConnectionSuccess(feedbackConnection); } } else { log.debug("{} failed to complete TLS handshake with APNs feedback service.", feedbackConnection.name, handshakeFuture.cause()); connectFuture.channel().close(); if (feedbackConnection.listener != null) { feedbackConnection.listener.handleConnectionFailure(feedbackConnection, handshakeFuture.cause()); } } } }); } catch (NullPointerException e) { log.warn("{} failed to get SSL handler and could not wait for a TLS handshake.", feedbackConnection.name); connectFuture.channel().close(); if (feedbackConnection.listener != null) { feedbackConnection.listener.handleConnectionFailure(feedbackConnection, e); } } } else { log.debug("{} failed to connect to APNs feedback service.", feedbackConnection.name, connectFuture.cause()); if (feedbackConnection.listener != null) { feedbackConnection.listener.handleConnectionFailure(feedbackConnection, connectFuture.cause()); } } } }); }
From source file:com.spotify.ffwd.debug.NettyDebugServer.java
License:Apache License
public AsyncFuture<Void> start() { final ResolvableFuture<Void> future = async.future(); final ServerBootstrap s = new ServerBootstrap(); s.channel(NioServerSocketChannel.class); s.group(boss, worker);/*from w w w.ja v a 2 s . c o m*/ s.childHandler(new ChannelInitializer<Channel>() { @Override protected void initChannel(final Channel ch) throws Exception { connected.add(ch); log.info("Connected {}", ch); ch.closeFuture().addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { connected.remove(ch); log.info("Disconnected {}", ch); } }); } }); s.bind(localAddress).addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture f) throws Exception { if (!f.isSuccess()) { future.fail(f.cause()); return; } log.info("Bound to {}", localAddress); if (!server.compareAndSet(null, f.channel())) { f.channel().close(); future.fail(new IllegalStateException("server already started")); return; } future.resolve(null); } }); return future; }
From source file:com.spotify.ffwd.debug.NettyDebugServer.java
License:Apache License
public AsyncFuture<Void> stop() { final Channel server = this.server.getAndSet(null); if (server == null) { throw new IllegalStateException("server not started"); }/*from ww w. j a v a 2s . com*/ final ResolvableFuture<Void> serverClose = async.future(); server.close().addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture f) throws Exception { if (!f.isSuccess()) { serverClose.fail(f.cause()); return; } serverClose.resolve(null); } }); final ResolvableFuture<Void> channelGroupClose = async.future(); connected.close().addListener(new ChannelGroupFutureListener() { @Override public void operationComplete(ChannelGroupFuture f) throws Exception { if (!f.isSuccess()) { channelGroupClose.fail(f.cause()); return; } channelGroupClose.resolve(null); } }); return async.collectAndDiscard(ImmutableList.<AsyncFuture<Void>>of(serverClose, channelGroupClose)); }
From source file:com.spotify.ffwd.protocol.RetryingProtocolConnection.java
License:Apache License
private void trySetup(final int attempt) { log.info("Attempt {}", action); final ChannelFuture connect = action.setup(); connect.addListener(new ChannelFutureListener() { @Override/*from ww w .jav a 2 s .c om*/ public void operationComplete(ChannelFuture future) throws Exception { if (future.isSuccess()) { log.info("Successful {}", action); setChannel(future.channel()); return; } final long delay = policy.delay(attempt); log.warn("Failed {} (attempt: {}), retrying in {}s: {}", action, attempt + 1, TimeUnit.SECONDS.convert(delay, TimeUnit.MILLISECONDS), future.cause().getMessage()); timer.newTimeout(new TimerTask() { @Override public void run(Timeout timeout) throws Exception { if (stopped.get()) { return; } trySetup(attempt + 1); } }, delay, TimeUnit.MILLISECONDS); } }); }
From source file:com.spotify.ffwd.protocol.RetryingProtocolConnection.java
License:Apache License
@Override public void send(Object message) { final Channel c = channel.get(); if (c == null) { return;/*from w ww. j a v a2 s .c o m*/ } c.writeAndFlush(message).addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { if (!future.isSuccess()) { log.error("failed to send metric", future.cause()); } } }); }
From source file:com.spotify.folsom.client.DefaultRawMemcacheClient.java
License:Apache License
public static ListenableFuture<RawMemcacheClient> connect(final HostAndPort address, final int outstandingRequestLimit, final boolean binary, final Executor executor, final long timeoutMillis) { final ChannelInboundHandler decoder; if (binary) { decoder = new BinaryMemcacheDecoder(); } else {// w w w . j a v a2 s .c om decoder = new AsciiMemcacheDecoder(); } final ChannelHandler initializer = new ChannelInitializer<Channel>() { @Override protected void initChannel(final Channel ch) throws Exception { ch.pipeline().addLast(new TcpTuningHandler(), decoder, // Downstream new MemcacheEncoder()); } }; final SettableFuture<RawMemcacheClient> clientFuture = SettableFuture.create(); final Bootstrap bootstrap = new Bootstrap().group(EVENT_LOOP_GROUP).handler(initializer) .channel(NioSocketChannel.class) .option(ChannelOption.MESSAGE_SIZE_ESTIMATOR, SimpleSizeEstimator.INSTANCE); final ChannelFuture connectFuture = bootstrap .connect(new InetSocketAddress(address.getHostText(), address.getPort())); connectFuture.addListener(new ChannelFutureListener() { @Override public void operationComplete(final ChannelFuture future) throws Exception { if (future.isSuccess()) { // Create client final RawMemcacheClient client = new DefaultRawMemcacheClient(address, future.channel(), outstandingRequestLimit, executor, timeoutMillis); clientFuture.set(client); } else { clientFuture.setException(future.cause()); } } }); return onExecutor(clientFuture, executor); }