List of usage examples for io.netty.util.concurrent GenericFutureListener GenericFutureListener
GenericFutureListener
From source file:com.kixeye.kixmpp.server.module.muc.MucRoom.java
License:Apache License
private void sendExistingOccupantsPresenceToNewOccupant(final User newUser, final Channel channel) { final KixmppJid jid = channel.attr(BindKixmppServerModule.JID).get(); final MucRole role = jidRoles.get(jid.withoutResource()); Promise<Set<String>> promise = service.getServer().createPromise(); promise.addListener(new GenericFutureListener<Future<Set<String>>>() { @Override/*from ww w. j av a 2 s.com*/ public void operationComplete(Future<Set<String>> future) throws Exception { if (future.isSuccess()) { Set<String> nicknames = future.get(); for (String nickname : nicknames) { if (newUser.getNickname().equals(nickname)) { continue; } Element presence = createPresence(roomJid.withResource(nickname), jid, role, null); channel.write(presence); } if (!nicknames.isEmpty()) { channel.flush(); } } } }); service.getServer() .sendMapReduceRequest(new GetMucRoomNicknamesRequest(service.getSubDomain(), roomId, jid, promise)); }
From source file:com.lambdaworks.redis.resource.Futures.java
License:Apache License
/** * Create a promise that emits a {@code Boolean} value on completion of the {@code future} * /*from w ww . ja v a 2 s. c o m*/ * @param future the future. * @return Promise emitting a {@code Boolean} value. {@literal true} if the {@code future} completed successfully, otherwise * the cause wil be transported. */ static Promise<Boolean> toBooleanPromise(Future<?> future) { final DefaultPromise<Boolean> result = new DefaultPromise<>(GlobalEventExecutor.INSTANCE); future.addListener(new GenericFutureListener<Future<Object>>() { @Override public void operationComplete(Future<Object> future) throws Exception { if (future.isSuccess()) { result.setSuccess(true); } else { result.setFailure(future.cause()); } } }); return result; }
From source file:com.lampard.netty4.ssl.SecureChatServerHandler.java
License:Apache License
@Override public void channelActive(final ChannelHandlerContext ctx) throws Exception { // Once session is secured, send a greeting and register the channel to // the global channel // list so the channel received the messages from others. ctx.pipeline().get(SslHandler.class).handshakeFuture() .addListener(new GenericFutureListener<Future<Channel>>() { @Override// ww w . j a v a2s. c o m public void operationComplete(Future<Channel> future) throws Exception { ctx.writeAndFlush("Welcome to " + InetAddress.getLocalHost().getHostName() + " secure chat service!\n"); ctx.writeAndFlush("Your session is protected by " + ctx.pipeline().get(SslHandler.class).engine().getSession().getCipherSuite() + " cipher suite.\n"); channels.add(ctx.channel()); } }); }
From source file:com.mobicage.rogerthat.plugins.news.NewsChannel.java
License:Apache License
public void connect() { if (TestUtils.isRunningTest()) { return;/*from w w w . ja v a 2 s.c om*/ } T.NEWS(); if (mIsConnected) { L.d("Already connected to news channel"); return; } else if (!mService.getNetworkConnectivityManager().isConnected()) { L.d("Cannot connect to news channel: no internet connection."); return; } else if (mHost == null) { L.d("Not connecting to news channel because no host was found"); return; } else if (mPort == -1) { L.d("Not connecting to news channel because no port was found"); return; } mIsRetryingToConnect = true; L.d("Attemping to connect to news channel..."); final SslContext sslCtx; if (CloudConstants.NEWS_CHANNEL_SSL) { try { if (CloudConstants.NEWS_CHANNEL_MUST_VALIDATE_SSL_CERTIFICATE) { TrustManagerFactory factory = TrustManagerFactory .getInstance(TrustManagerFactory.getDefaultAlgorithm()); KeyStore keyStore = KeyStore.getInstance("AndroidCAStore"); // Gets the default system keystore keyStore.load(null, null); factory.init(keyStore); sslCtx = SslContextBuilder.forClient().trustManager(factory).build(); } else { sslCtx = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE) .build(); } } catch (NoSuchAlgorithmException | KeyStoreException | CertificateException | IOException e) { L.bug(e); return; } } else { sslCtx = null; } if (mEventLoopGroup == null) { mEventLoopGroup = new NioEventLoopGroup(); } Bootstrap b = new Bootstrap(); b.group(mEventLoopGroup).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true) .handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); if (sslCtx != null) { SslHandler sslHandler = sslCtx.newHandler(ch.alloc(), mHost, mPort); Future<Channel> handshakeDone = sslHandler.handshakeFuture(); handshakeDone.addListener(new GenericFutureListener<Future<? super Channel>>() { @Override public void operationComplete(Future<? super Channel> future) throws Exception { authenticate(); } }); p.addLast(sslHandler); } // decoder p.addLast(new DelimiterBasedFrameDecoder(102400, Delimiters.lineDelimiter())); p.addLast(new StringDecoder(Charset.forName("UTF-8"))); //encoder p.addLast(new StringEncoder(Charset.forName("UTF-8"))); p.addLast(NewsChannel.this); } }); // Bind and start to accept incoming connections. mChannel = b.connect(mHost, mPort).channel(); }
From source file:com.ociweb.pronghorn.adapter.netty.impl.WebSocketServerHandler.java
License:Apache License
private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) { // Handle a bad request. if (!req.decoderResult().isSuccess()) { sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, BAD_REQUEST)); return;//from w w w . jav a2 s.c o m } // Allow only GET methods. if (req.method() != GET) { sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, FORBIDDEN)); return; } String path = HttpStaticFileServerHandler.sanitizeUri(req.uri(), SystemPropertyUtil.get("user.dir")); System.out.println("path:" + path); if (null != path) { File file = new File(path); if (file.exists() && !file.isHidden()) { try { HttpStaticFileServerHandler.sendFile(ctx, req, file); } catch (ParseException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } return; } } // Handshake WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(getWebSocketLocation(req), null, true); handshaker = wsFactory.newHandshaker(req); if (handshaker == null) { WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel()); } else { GenericFutureListener<ChannelFuture> webSocketIsOpen = new GenericFutureListener<ChannelFuture>() { @Override public void operationComplete(ChannelFuture future) throws Exception { System.out.println("UpgradedWebSocket for id " + future.channel().id().asShortText() + " ||| " + future.channel().id().asLongText() + " thread " + Thread.currentThread().getId()); } }; handshaker.handshake(ctx.channel(), req).addListener(webSocketIsOpen); } }
From source file:com.relayrides.pushy.apns.ApnsClient.java
License:Open Source License
/** * <p>Connects to the given APNs gateway on the given port.</p> * * <p>Once an initial connection has been established and until the client has been explicitly disconnected via the * {@link ApnsClient#disconnect()} method, the client will attempt to reconnect automatically if the connection * closes unexpectedly. If the connection closes unexpectedly, callers may monitor the status of the reconnection * attempt with the {@code Future} returned by the {@link ApnsClient#getReconnectionFuture()} method.</p> * * @param host the APNs gateway to which to connect * @param port the port on which to connect to the APNs gateway * * @return a {@code Future} that will succeed when the client has connected to the gateway and is ready to send * push notifications/*from ww w .j a va2 s.com*/ * * @see ApnsClient#PRODUCTION_APNS_HOST * @see ApnsClient#DEVELOPMENT_APNS_HOST * @see ApnsClient#DEFAULT_APNS_PORT * @see ApnsClient#ALTERNATE_APNS_PORT * * @since 0.5 */ public Future<Void> connect(final String host, final int port) { final Future<Void> connectionReadyFuture; if (this.bootstrap.config().group().isShuttingDown() || this.bootstrap.config().group().isShutdown()) { connectionReadyFuture = new FailedFuture<>(GlobalEventExecutor.INSTANCE, new IllegalStateException( "Client's event loop group has been shut down and cannot be restarted.")); } else { synchronized (this.bootstrap) { // We only want to begin a connection attempt if one is not already in progress or complete; if we already // have a connection future, just return the existing promise. if (this.connectionReadyPromise == null) { this.metricsListener.handleConnectionAttemptStarted(this); final ChannelFuture connectFuture = this.bootstrap.connect(host, port); this.connectionReadyPromise = connectFuture.channel().newPromise(); connectFuture.addListener(new GenericFutureListener<ChannelFuture>() { @Override public void operationComplete(final ChannelFuture future) throws Exception { if (!future.isSuccess()) { final ChannelPromise connectionReadyPromise = ApnsClient.this.connectionReadyPromise; if (connectionReadyPromise != null) { // This may seem spurious, but our goal here is to accurately report the cause of // connection failure; if we just wait for connection closure, we won't be able to // tell callers anything more specific about what went wrong. connectionReadyPromise.tryFailure(future.cause()); } } } }); connectFuture.channel().closeFuture().addListener(new GenericFutureListener<ChannelFuture>() { @Override public void operationComplete(final ChannelFuture future) throws Exception { synchronized (ApnsClient.this.bootstrap) { if (ApnsClient.this.connectionReadyPromise != null) { // We always want to try to fail the "connection ready" promise if the connection // closes; if it has already succeeded, this will have no effect. ApnsClient.this.connectionReadyPromise.tryFailure(new IllegalStateException( "Channel closed before HTTP/2 preface completed.")); ApnsClient.this.connectionReadyPromise = null; } if (ApnsClient.this.reconnectionPromise != null) { log.debug("Disconnected. Next automatic reconnection attempt in {} seconds.", ApnsClient.this.reconnectDelaySeconds); ApnsClient.this.scheduledReconnectFuture = future.channel().eventLoop() .schedule(new Runnable() { @Override public void run() { log.debug("Attempting to reconnect."); ApnsClient.this.connect(host, port); } }, ApnsClient.this.reconnectDelaySeconds, TimeUnit.SECONDS); ApnsClient.this.reconnectDelaySeconds = Math.min( ApnsClient.this.reconnectDelaySeconds, MAX_RECONNECT_DELAY_SECONDS); } } } }); this.connectionReadyPromise.addListener(new GenericFutureListener<ChannelFuture>() { @Override public void operationComplete(final ChannelFuture future) throws Exception { if (future.isSuccess()) { synchronized (ApnsClient.this.bootstrap) { if (ApnsClient.this.reconnectionPromise != null) { log.info("Connection to {} restored.", future.channel().remoteAddress()); ApnsClient.this.reconnectionPromise.trySuccess(); } else { log.info("Connected to {}.", future.channel().remoteAddress()); } ApnsClient.this.reconnectDelaySeconds = INITIAL_RECONNECT_DELAY_SECONDS; ApnsClient.this.reconnectionPromise = future.channel().newPromise(); } ApnsClient.this.metricsListener.handleConnectionAttemptSucceeded(ApnsClient.this); } else { log.info("Failed to connect.", future.cause()); ApnsClient.this.metricsListener.handleConnectionAttemptFailed(ApnsClient.this); } } }); } connectionReadyFuture = this.connectionReadyPromise; } } return connectionReadyFuture; }
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>//ww w. j a v a2 s. c om * * <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:com.relayrides.pushy.apns.ApnsClient.java
License:Open Source License
/** * <p>Gracefully disconnects from the APNs gateway. The disconnection process will wait until notifications that * have been sent to the APNs server have been either accepted or rejected. Note that some notifications passed to * {@link com.relayrides.pushy.apns.ApnsClient#sendNotification(ApnsPushNotification)} may still be enqueued and * not yet sent by the time the shutdown process begins; the {@code Futures} associated with those notifications * will fail.</p>//from w w w . j ava2s. c o m * * <p>The returned {@code Future} will be marked as complete when the connection has closed completely. If the * connection is already closed when this method is called, the returned {@code Future} will be marked as complete * immediately.</p> * * <p>If a non-null {@code EventLoopGroup} was provided at construction time, clients may be reconnected and reused * after they have been disconnected. If no event loop group was provided at construction time, clients may not be * restarted after they have been disconnected via this method.</p> * * @return a {@code Future} that will be marked as complete when the connection has been closed * * @since 0.5 */ @SuppressWarnings({ "rawtypes", "unchecked" }) public Future<Void> disconnect() { log.info("Disconnecting."); final Future<Void> disconnectFuture; synchronized (this.bootstrap) { this.reconnectionPromise = null; if (this.scheduledReconnectFuture != null) { this.scheduledReconnectFuture.cancel(true); } final Future<Void> channelCloseFuture; if (this.connectionReadyPromise != null) { channelCloseFuture = this.connectionReadyPromise.channel().close(); } else { channelCloseFuture = new SucceededFuture<>(GlobalEventExecutor.INSTANCE, null); } if (this.shouldShutDownEventLoopGroup) { // Wait for the channel to close before we try to shut down the event loop group channelCloseFuture.addListener(new GenericFutureListener<Future<Void>>() { @Override public void operationComplete(final Future<Void> future) throws Exception { ApnsClient.this.bootstrap.config().group().shutdownGracefully(); } }); // Since the termination future for the event loop group is a Future<?> instead of a Future<Void>, // we'll need to create our own promise and then notify it when the termination future completes. disconnectFuture = new DefaultPromise<>(GlobalEventExecutor.INSTANCE); this.bootstrap.config().group().terminationFuture().addListener(new GenericFutureListener() { @Override public void operationComplete(final Future future) throws Exception { assert disconnectFuture instanceof DefaultPromise; ((DefaultPromise<Void>) disconnectFuture).trySuccess(null); } }); } else { // We're done once we've closed the channel, so we can return the closure future directly. disconnectFuture = channelCloseFuture; } } return disconnectFuture; }
From source file:com.relayrides.pushy.apns.ApnsClientHandler.java
License:Open Source License
@Override public void write(final ChannelHandlerContext context, final Object message, final ChannelPromise writePromise) throws Http2Exception { if (message instanceof PushNotificationAndResponsePromise) { final PushNotificationAndResponsePromise pushNotificationAndResponsePromise = (PushNotificationAndResponsePromise) message; final ApnsPushNotification pushNotification = pushNotificationAndResponsePromise.getPushNotification(); if (this.responsePromises.containsKey(pushNotification)) { writePromise.tryFailure(new PushNotificationStillPendingException()); } else {/*from w w w . j av a2 s .c om*/ this.responsePromises.put(pushNotification, pushNotificationAndResponsePromise.getResponsePromise()); pushNotificationAndResponsePromise.getResponsePromise().addListener( new GenericFutureListener<Future<PushNotificationResponse<ApnsPushNotification>>>() { @Override public void operationComplete( final Future<PushNotificationResponse<ApnsPushNotification>> future) { // Regardless of the outcome, when the response promise is finished, we want to remove it from // the map of pending promises. ApnsClientHandler.this.responsePromises.remove(pushNotification); } }); this.write(context, pushNotification, writePromise); } } else if (message instanceof ApnsPushNotification) { final ApnsPushNotification pushNotification = (ApnsPushNotification) message; try { final int streamId = (int) this.nextStreamId; final Http2Headers headers = new DefaultHttp2Headers().method(HttpMethod.POST.asciiName()) .authority(this.authority).path(APNS_PATH_PREFIX + pushNotification.getToken()) .addInt(APNS_EXPIRATION_HEADER, pushNotification.getExpiration() == null ? 0 : (int) (pushNotification.getExpiration().getTime() / 1000)); final String authenticationToken = this.apnsClient .getAuthenticationTokenSupplierForTopic(pushNotification.getTopic()).getToken(); headers.add(APNS_AUTHORIZATION_HEADER, "bearer " + authenticationToken); if (pushNotification.getCollapseId() != null) { headers.add(APNS_COLLAPSE_ID_HEADER, pushNotification.getCollapseId()); } if (pushNotification.getPriority() != null) { headers.addInt(APNS_PRIORITY_HEADER, pushNotification.getPriority().getCode()); } if (pushNotification.getTopic() != null) { headers.add(APNS_TOPIC_HEADER, pushNotification.getTopic()); } final ChannelPromise headersPromise = context.newPromise(); this.encoder().writeHeaders(context, streamId, headers, 0, false, headersPromise); log.trace("Wrote headers on stream {}: {}", streamId, headers); final ByteBuf payloadBuffer = context.alloc().ioBuffer(INITIAL_PAYLOAD_BUFFER_CAPACITY); payloadBuffer.writeBytes(pushNotification.getPayload().getBytes(StandardCharsets.UTF_8)); final ChannelPromise dataPromise = context.newPromise(); this.encoder().writeData(context, streamId, payloadBuffer, 0, true, dataPromise); log.trace("Wrote payload on stream {}: {}", streamId, pushNotification.getPayload()); final PromiseCombiner promiseCombiner = new PromiseCombiner(); promiseCombiner.addAll(headersPromise, dataPromise); promiseCombiner.finish(writePromise); writePromise.addListener(new GenericFutureListener<ChannelPromise>() { @Override public void operationComplete(final ChannelPromise future) throws Exception { if (future.isSuccess()) { ApnsClientHandler.this.pushNotificationsByStreamId.put(streamId, pushNotification); ApnsClientHandler.this.authenticationTokensByStreamId.put(streamId, authenticationToken); } else { log.trace("Failed to write push notification on stream {}.", streamId, future.cause()); final Promise<PushNotificationResponse<ApnsPushNotification>> responsePromise = ApnsClientHandler.this.responsePromises .get(pushNotification); if (responsePromise != null) { responsePromise.tryFailure(future.cause()); } else { log.error("Notification write failed, but no response promise found."); } } } }); this.nextStreamId += 2; if (this.nextStreamId >= STREAM_ID_RESET_THRESHOLD) { // This is very unlikely, but in the event that we run out of stream IDs (the maximum allowed is // 2^31, per https://httpwg.github.io/specs/rfc7540.html#StreamIdentifiers), we need to open a new // connection. Just closing the context should be enough; automatic reconnection should take things // from there. context.close(); } } catch (NoKeyForTopicException | SignatureException e) { writePromise.tryFailure(e); } } else { // This should never happen, but in case some foreign debris winds up in the pipeline, just pass it through. log.error("Unexpected object in pipeline: {}", message); context.write(message, writePromise); } }
From source file:com.relayrides.pushy.apns.ApnsClientHandler.java
License:Open Source License
@Override public void userEventTriggered(final ChannelHandlerContext context, final Object event) throws Exception { if (event instanceof IdleStateEvent) { assert PING_TIMEOUT < ApnsClient.PING_IDLE_TIME_MILLIS; log.trace("Sending ping due to inactivity."); final ByteBuf pingDataBuffer = context.alloc().ioBuffer(8, 8); pingDataBuffer.writeLong(this.nextPingId++); this.encoder().writePing(context, false, pingDataBuffer, context.newPromise()) .addListener(new GenericFutureListener<ChannelFuture>() { @Override//from w w w .j ava 2 s .c o m public void operationComplete(final ChannelFuture future) throws Exception { if (future.isSuccess()) { ApnsClientHandler.this.pingTimeoutFuture = future.channel().eventLoop() .schedule(new Runnable() { @Override public void run() { log.debug("Closing channel due to ping timeout."); future.channel().close(); } }, PING_TIMEOUT, TimeUnit.SECONDS); } else { log.debug("Failed to write PING frame.", future.cause()); future.channel().close(); } } }); this.flush(context); } super.userEventTriggered(context, event); }