List of usage examples for io.netty.channel ChannelPromise channel
@Override Channel channel();
From source file:com.relayrides.pushy.apns.ApnsClient.java
License:Open Source License
/** * <p>Sends a push notification to the APNs gateway.</p> * * <p>This method returns a {@code Future} that indicates whether the notification was accepted or rejected by the * gateway. If the notification was accepted, it may be delivered to its destination device at some time in the * future, but final delivery is not guaranteed. Rejections should be considered permanent failures, and callers * should <em>not</em> attempt to re-send the notification.</p> * * <p>The returned {@code Future} may fail with an exception if the notification could not be sent. Failures to * <em>send</em> a notification to the gatewayi.e. those that fail with exceptionsshould generally be considered * non-permanent, and callers should attempt to re-send the notification when the underlying problem has been * resolved.</p>// w ww . j ava2s . co m * * <p>In particular, attempts to send a notification when the client is not connected will fail with a * {@link ClientNotConnectedException}. If the client was previously connected and has not been explicitly * disconnected (via the {@link ApnsClient#disconnect()} method), the client will attempt to reconnect * automatically. Callers may wait for a reconnection attempt to complete by waiting for the {@code Future} returned * by the {@link ApnsClient#getReconnectionFuture()} method.</p> * * @param notification the notification to send to the APNs gateway * * @param <T> the type of notification to be sent * * @return a {@code Future} that will complete when the notification has been either accepted or rejected by the * APNs gateway * * @since 0.8 */ @SuppressWarnings({ "rawtypes", "unchecked" }) public <T extends ApnsPushNotification> Future<PushNotificationResponse<T>> sendNotification( final T notification) { final Future<PushNotificationResponse<T>> responseFuture; final long notificationId = this.nextNotificationId.getAndIncrement(); // Instead of synchronizing here, we keep a final reference to the connection ready promise. We can get away // with this because we're not changing the state of the connection or its promises. Keeping a reference ensures // we won't suddenly "lose" the channel and get a NullPointerException, but risks sending a notification after // things have shut down. In that case, though, the returned futures should fail quickly, and the benefit of // not synchronizing for every write seems worth it. final ChannelPromise connectionReadyPromise = this.connectionReadyPromise; if (connectionReadyPromise != null && connectionReadyPromise.isSuccess() && connectionReadyPromise.channel().isActive()) { final Channel channel = connectionReadyPromise.channel(); final Promise<PushNotificationResponse<ApnsPushNotification>> responsePromise = new DefaultPromise( channel.eventLoop()); channel.writeAndFlush(new PushNotificationAndResponsePromise(notification, responsePromise)) .addListener(new GenericFutureListener<ChannelFuture>() { @Override public void operationComplete(final ChannelFuture future) throws Exception { if (future.isSuccess()) { ApnsClient.this.metricsListener.handleNotificationSent(ApnsClient.this, notificationId); } else { responsePromise.tryFailure(future.cause()); } } }); responseFuture = (Future) responsePromise; } else { log.debug("Failed to send push notification because client is not connected: {}", notification); responseFuture = new FailedFuture<>(GlobalEventExecutor.INSTANCE, NOT_CONNECTED_EXCEPTION); } responseFuture.addListener(new GenericFutureListener<Future<PushNotificationResponse<T>>>() { @Override public void operationComplete(final Future<PushNotificationResponse<T>> future) throws Exception { if (future.isSuccess()) { final PushNotificationResponse<T> response = future.getNow(); if (response.isAccepted()) { ApnsClient.this.metricsListener.handleNotificationAccepted(ApnsClient.this, notificationId); } else { ApnsClient.this.metricsListener.handleNotificationRejected(ApnsClient.this, notificationId); } } else { ApnsClient.this.metricsListener.handleWriteFailure(ApnsClient.this, notificationId); } } }); return responseFuture; }
From source file:dorkbox.network.connection.registration.remote.RegistrationRemoteHandler.java
License:Apache License
final void cleanupPipeline(final MetaChannel metaChannel, final Runnable onConnectFinishRunnable) { final int idleTimeout = this.registrationWrapper.getIdleTimeout(); try {/* w w w . ja v a 2 s .co m*/ // REMOVE our channel wrapper (only used for encryption) with the actual connection ChannelHandler handler = metaChannel.connection = ((ConnectionRegistrationImpl) metaChannel.connection).connection; Channel channel; if (metaChannel.tcpChannel != null) { channel = metaChannel.tcpChannel; } else { channel = metaChannel.udpChannel; } // channel should NEVER == null! (we will always have TCP or UDP!) // we also ONLY want to add this to a single cleanup, NOT BOTH, because this must only run once!! final ChannelPromise channelPromise = channel.newPromise(); channelPromise.addListener(new FutureListener<Void>() { @Override public void operationComplete(final Future<Void> future) throws Exception { EventLoop loop = channelPromise.channel().eventLoop(); loop.execute(new Runnable() { @Override public void run() { logger.trace("Notify Connection"); // safe cast, because it's always this way... registrationWrapper.connectionConnected0((ConnectionImpl) metaChannel.connection); // run things AFTER the onConnect() method is called... // CLIENT - runs the deferred 'onMessage' events in the connection as needed // SERVER - send 'onConnect' bounce back message to client onConnectFinishRunnable.run(); } }); } }); if (metaChannel.tcpChannel != null) { cleanupPipeline0(idleTimeout, handler, metaChannel.tcpChannel, channelPromise, true); } if (metaChannel.udpChannel != null) { cleanupPipeline0(idleTimeout, handler, metaChannel.udpChannel, channelPromise, false); } } catch (Exception e) { logger.error("Error during pipeline replace", e); } }
From source file:dorkbox.network.connection.registration.remote.RegistrationRemoteHandler.java
License:Apache License
private void cleanupPipeline0(final int idleTimeout, final ChannelHandler connection, final Channel channel, final ChannelPromise channelPromise, final boolean isTcp) { final ChannelPipeline pipeline = channel.pipeline(); // have to explicitly remove handlers based on the input type. Cannot use this.getClass().... boolean isClient = registrationWrapper.isClient(); if (isClient) { if (isTcp) { pipeline.remove(RegistrationRemoteHandlerClientTCP.class); } else {/*from w ww .j av a 2s . com*/ pipeline.remove(RegistrationRemoteHandlerClientUDP.class); } } else { if (isTcp) { pipeline.remove(RegistrationRemoteHandlerServerTCP.class); } else { pipeline.remove(RegistrationRemoteHandlerServerUDP.class); } } pipeline.remove(ConnectionRegistrationImpl.class); if (idleTimeout > 0) { pipeline.replace(IDLE_HANDLER, IDLE_HANDLER_FULL, new IdleStateHandler(0, 0, idleTimeout, TimeUnit.MILLISECONDS)); } else { pipeline.remove(IDLE_HANDLER); } pipeline.addLast(CONNECTION_HANDLER, connection); // we also DEREGISTER from the HANDSHAKE event-loop and run on the worker event-loop! ChannelFuture future = channel.deregister(); future.addListener(new GenericFutureListener<Future<? super Void>>() { @Override public void operationComplete(final Future<? super Void> f) throws Exception { if (f.isSuccess()) { // TCP and UDP register on DIFFERENT event loops. The channel promise ONLY runs on 1 of them... if (channelPromise.channel() == channel) { workerEventLoop.register(channelPromise); } else { workerEventLoop.register(channel); } } } }); }