コード例 #1
0
  @Override
  public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
    long size = calculateSize(msg);
    long curtime = System.currentTimeMillis();

    if (trafficCounter != null) {
      trafficCounter.bytesRecvFlowControl(size);
      if (readLimit == 0) {
        // no action
        ctx.fireChannelRead(msg);

        return;
      }

      // compute the number of ms to wait before reopening the channel
      long wait =
          getTimeToWait(
              readLimit, trafficCounter.currentReadBytes(), trafficCounter.lastTime(), curtime);
      if (wait >= MINIMAL_WAIT) { // At least 10ms seems a minimal
        // time in order to
        // try to limit the traffic
        if (!isSuspended(ctx)) {
          ctx.attr(READ_SUSPENDED).set(true);

          // Create a Runnable to reactive the read if needed. If one was create before it will just
          // be
          // reused to limit object creation
          Attribute<Runnable> attr = ctx.attr(REOPEN_TASK);
          Runnable reopenTask = attr.get();
          if (reopenTask == null) {
            reopenTask = new ReopenReadTimerTask(ctx);
            attr.set(reopenTask);
          }
          ctx.executor().schedule(reopenTask, wait, TimeUnit.MILLISECONDS);
        } else {
          // Create a Runnable to update the next handler in the chain. If one was create before it
          // will
          // just be reused to limit object creation
          Runnable bufferUpdateTask =
              new Runnable() {
                @Override
                public void run() {
                  ctx.fireChannelRead(msg);
                }
              };
          ctx.executor().schedule(bufferUpdateTask, wait, TimeUnit.MILLISECONDS);
          return;
        }
      }
    }
    ctx.fireChannelRead(msg);
  }
コード例 #2
0
ファイル: SslHandler.java プロジェクト: zoopnin/netty
  /**
   * Starts an SSL / TLS handshake for the specified channel.
   *
   * @return a {@link ChannelFuture} which is notified when the handshake succeeds or fails.
   */
  public ChannelFuture handshake(final ChannelFuture future) {
    final ChannelHandlerContext ctx = this.ctx;

    final ScheduledFuture<?> timeoutFuture;
    if (handshakeTimeoutMillis > 0) {
      timeoutFuture =
          ctx.executor()
              .schedule(
                  new Runnable() {
                    @Override
                    public void run() {
                      if (future.isDone()) {
                        return;
                      }

                      SSLException e = new SSLException("handshake timed out");
                      if (future.setFailure(e)) {
                        ctx.fireExceptionCaught(e);
                        ctx.close();
                      }
                    }
                  },
                  handshakeTimeoutMillis,
                  TimeUnit.MILLISECONDS);
    } else {
      timeoutFuture = null;
    }

    ctx.executor()
        .execute(
            new Runnable() {
              @Override
              public void run() {
                try {
                  if (timeoutFuture != null) {
                    timeoutFuture.cancel(false);
                  }
                  engine.beginHandshake();
                  handshakeFutures.add(future);
                  flush(ctx, ctx.newFuture());
                } catch (Exception e) {
                  if (future.setFailure(e)) {
                    ctx.fireExceptionCaught(e);
                    ctx.close();
                  }
                }
              }
            });

    return future;
  }
コード例 #3
0
  @Override
  public void write(final ChannelHandlerContext ctx, final Object msg, final ChannelPromise promise)
      throws Exception {
    long curtime = System.currentTimeMillis();
    long size = calculateSize(msg);

    if (size > -1 && trafficCounter != null) {
      trafficCounter.bytesWriteFlowControl(size);
      if (writeLimit == 0) {
        ctx.write(msg, promise);
        return;
      }
      // compute the number of ms to wait before continue with the
      // channel
      long wait =
          getTimeToWait(
              writeLimit, trafficCounter.currentWrittenBytes(), trafficCounter.lastTime(), curtime);
      if (wait >= MINIMAL_WAIT) {
        ctx.executor()
            .schedule(
                new Runnable() {
                  @Override
                  public void run() {
                    ctx.write(msg, promise);
                  }
                },
                wait,
                TimeUnit.MILLISECONDS);
        return;
      }
    }
    ctx.write(msg, promise);
  }
コード例 #4
0
ファイル: SslHandler.java プロジェクト: njutony1991/netty
  /** Performs TLS renegotiation. */
  public Future<Channel> renegotiate(final Promise<Channel> promise) {
    if (promise == null) {
      throw new NullPointerException("promise");
    }

    ChannelHandlerContext ctx = this.ctx;
    if (ctx == null) {
      throw new IllegalStateException();
    }

    EventExecutor executor = ctx.executor();
    if (!executor.inEventLoop()) {
      executor.execute(
          new OneTimeTask() {
            @Override
            public void run() {
              handshake(promise);
            }
          });
      return promise;
    }

    handshake(promise);
    return promise;
  }
コード例 #5
0
ファイル: SslHandler.java プロジェクト: njutony1991/netty
  /** Performs TLS renegotiation. */
  public Future<Channel> renegotiate() {
    ChannelHandlerContext ctx = this.ctx;
    if (ctx == null) {
      throw new IllegalStateException();
    }

    return renegotiate(ctx.executor().<Channel>newPromise());
  }
コード例 #6
0
 @Override
 public void channelRead0(final ChannelHandlerContext ctx, HttpRequest req) throws Exception {
   if (req.getUri().equals("/hello")) {
     ctx.executor().schedule(new HelloWorldRunnable(ctx), 10, TimeUnit.SECONDS);
   } else {
     ctx.fireChannelRead(req);
   }
 }
コード例 #7
0
ファイル: SslHandler.java プロジェクト: njutony1991/netty
  private void safeClose(
      final ChannelHandlerContext ctx, ChannelFuture flushFuture, final ChannelPromise promise) {
    if (!ctx.channel().isActive()) {
      ctx.close(promise);
      return;
    }

    final ScheduledFuture<?> timeoutFuture;
    if (closeNotifyTimeoutMillis > 0) {
      // Force-close the connection if close_notify is not fully sent in time.
      timeoutFuture =
          ctx.executor()
              .schedule(
                  new Runnable() {
                    @Override
                    public void run() {
                      logger.warn(
                          "{} Last write attempt timed out; force-closing the connection.",
                          ctx.channel());

                      // We notify the promise in the TryNotifyListener as there is a "race" where
                      // the close(...) call
                      // by the timeoutFuture and the close call in the flushFuture listener will be
                      // called. Because of
                      // this we need to use trySuccess() and tryFailure(...) as otherwise we can
                      // cause an
                      // IllegalStateException.
                      ctx.close(ctx.newPromise()).addListener(new ChannelPromiseNotifier(promise));
                    }
                  },
                  closeNotifyTimeoutMillis,
                  TimeUnit.MILLISECONDS);
    } else {
      timeoutFuture = null;
    }

    // Close the connection if close_notify is sent in time.
    flushFuture.addListener(
        new ChannelFutureListener() {
          @Override
          public void operationComplete(ChannelFuture f) throws Exception {
            if (timeoutFuture != null) {
              timeoutFuture.cancel(false);
            }
            // Trigger the close in all cases to make sure the promise is notified
            // See https://github.com/netty/netty/issues/2358
            //
            // We notify the promise in the ChannelPromiseNotifier as there is a "race" where the
            // close(...) call
            // by the timeoutFuture and the close call in the flushFuture listener will be called.
            // Because of
            // this we need to use trySuccess() and tryFailure(...) as otherwise we can cause an
            // IllegalStateException.
            ctx.close(ctx.newPromise()).addListener(new ChannelPromiseNotifier(promise));
          }
        });
  }
コード例 #8
0
  private void scheduleTimeout(final ChannelHandlerContext ctx, final ChannelPromise promise) {
    // Schedule a timeout.
    final WriteTimeoutTask task = new WriteTimeoutTask(ctx, promise);
    task.scheduledFuture = ctx.executor().schedule(task, timeoutNanos, TimeUnit.NANOSECONDS);

    if (!task.scheduledFuture.isDone()) {
      addWriteTimeoutTask(task);

      // Cancel the scheduled timeout if the flush promise is complete.
      promise.addListener(task);
    }
  }
コード例 #9
0
ファイル: SslHandler.java プロジェクト: zoopnin/netty
  /** See {@link #close()} */
  public ChannelFuture close(final ChannelFuture future) {
    final ChannelHandlerContext ctx = this.ctx;
    ctx.executor()
        .execute(
            new Runnable() {
              @Override
              public void run() {
                engine.closeOutbound();
                ctx.flush(future);
              }
            });

    return future;
  }
コード例 #10
0
ファイル: SslHandler.java プロジェクト: zoopnin/netty
  private void safeClose(
      final ChannelHandlerContext ctx, ChannelFuture flushFuture, final ChannelFuture closeFuture) {
    if (!ctx.channel().isActive()) {
      ctx.close(closeFuture);
      return;
    }

    final ScheduledFuture<?> timeoutFuture;
    if (closeNotifyTimeoutMillis > 0) {
      // Force-close the connection if close_notify is not fully sent in time.
      timeoutFuture =
          ctx.executor()
              .schedule(
                  new Runnable() {
                    @Override
                    public void run() {
                      logger.warn(
                          ctx.channel()
                              + " last write attempt timed out."
                              + " Force-closing the connection.");
                      ctx.close(closeFuture);
                    }
                  },
                  closeNotifyTimeoutMillis,
                  TimeUnit.MILLISECONDS);
    } else {
      timeoutFuture = null;
    }

    // Close the connection if close_notify is sent in time.
    flushFuture.addListener(
        new ChannelFutureListener() {
          @Override
          public void operationComplete(ChannelFuture f) throws Exception {
            if (timeoutFuture != null) {
              timeoutFuture.cancel(false);
            }
            if (ctx.channel().isActive()) {
              ctx.close(closeFuture);
            }
          }
        });
  }
コード例 #11
0
  @Override
  public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    Message message = (Message) msg;
    // 握手成功主动发送心跳
    if (message.getHeader() != null
        && message.getHeader().getType() == MessageType.LOGIN_RESP.value()) {

      heartBeat =
          ctx.executor()
              .scheduleAtFixedRate(new HeartBeatTask(ctx), 0, 5000, TimeUnit.MILLISECONDS);

    } else if (message.getHeader() != null
        && message.getHeader().getType() == MessageType.HEARTBEAT_RESP.value()) {

      System.out.println("Client receive server heart beat message:---->" + message);

    } else {
      ctx.fireChannelRead(message);
    }
  }
コード例 #12
0
ファイル: SslHandler.java プロジェクト: njutony1991/netty
  /** See {@link #close()} */
  public ChannelFuture close(final ChannelPromise future) {
    final ChannelHandlerContext ctx = this.ctx;
    ctx.executor()
        .execute(
            new Runnable() {
              @Override
              public void run() {
                engine.closeOutbound();
                try {
                  write(ctx, Unpooled.EMPTY_BUFFER, future);
                  flush(ctx);
                } catch (Exception e) {
                  if (!future.tryFailure(e)) {
                    logger.warn("{} flush() raised a masked exception.", ctx.channel(), e);
                  }
                }
              }
            });

    return future;
  }
コード例 #13
0
ファイル: SslHandler.java プロジェクト: hsoumare/netty
  private Future<Channel> handshake() {
    final ScheduledFuture<?> timeoutFuture;
    if (handshakeTimeoutMillis > 0) {
      timeoutFuture =
          ctx.executor()
              .schedule(
                  new Runnable() {
                    @Override
                    public void run() {
                      if (handshakePromise.isDone()) {
                        return;
                      }
                      notifyHandshakeFailure(HANDSHAKE_TIMED_OUT);
                    }
                  },
                  handshakeTimeoutMillis,
                  TimeUnit.MILLISECONDS);
    } else {
      timeoutFuture = null;
    }

    handshakePromise.addListener(
        new GenericFutureListener<Future<Channel>>() {
          @Override
          public void operationComplete(Future<Channel> f) throws Exception {
            if (timeoutFuture != null) {
              timeoutFuture.cancel(false);
            }
          }
        });
    try {
      engine.beginHandshake();
      wrapNonAppData(ctx, false);
      ctx.flush();
    } catch (Exception e) {
      notifyHandshakeFailure(e);
    }
    return handshakePromise;
  }
コード例 #14
0
 protected void scheduleTask(ChannelHandlerContext ctx, Runnable task, long delay, TimeUnit tu) {
   cancelTask();
   responseTask = ctx.executor().schedule(task, delay, tu);
 }
コード例 #15
0
ファイル: SslHandler.java プロジェクト: njutony1991/netty
  /**
   * Performs TLS (re)negotiation.
   *
   * @param newHandshakePromise if {@code null}, use the existing {@link #handshakePromise},
   *     assuming that the current negotiation has not been finished. Currently, {@code null} is
   *     expected only for the initial handshake.
   */
  private void handshake(final Promise<Channel> newHandshakePromise) {
    final Promise<Channel> p;
    if (newHandshakePromise != null) {
      final Promise<Channel> oldHandshakePromise = handshakePromise;
      if (!oldHandshakePromise.isDone()) {
        // There's no need to handshake because handshake is in progress already.
        // Merge the new promise into the old one.
        oldHandshakePromise.addListener(
            new FutureListener<Channel>() {
              @Override
              public void operationComplete(Future<Channel> future) throws Exception {
                if (future.isSuccess()) {
                  newHandshakePromise.setSuccess(future.getNow());
                } else {
                  newHandshakePromise.setFailure(future.cause());
                }
              }
            });
        return;
      }

      handshakePromise = p = newHandshakePromise;
    } else {
      // Forced to reuse the old handshake.
      p = handshakePromise;
      assert !p.isDone();
    }

    // Begin handshake.
    final ChannelHandlerContext ctx = this.ctx;
    try {
      engine.beginHandshake();
      wrapNonAppData(ctx, false);
      ctx.flush();
    } catch (Exception e) {
      notifyHandshakeFailure(e);
    }

    // Set timeout if necessary.
    final long handshakeTimeoutMillis = this.handshakeTimeoutMillis;
    if (handshakeTimeoutMillis <= 0 || p.isDone()) {
      return;
    }

    final ScheduledFuture<?> timeoutFuture =
        ctx.executor()
            .schedule(
                new Runnable() {
                  @Override
                  public void run() {
                    if (p.isDone()) {
                      return;
                    }
                    notifyHandshakeFailure(HANDSHAKE_TIMED_OUT);
                  }
                },
                handshakeTimeoutMillis,
                TimeUnit.MILLISECONDS);

    // Cancel the handshake timeout when handshake is finished.
    p.addListener(
        new FutureListener<Channel>() {
          @Override
          public void operationComplete(Future<Channel> f) throws Exception {
            timeoutFuture.cancel(false);
          }
        });
  }
コード例 #16
0
ファイル: SslHandler.java プロジェクト: zoopnin/netty
  @Override
  public void flush(final ChannelHandlerContext ctx, ChannelFuture future) throws Exception {
    final ByteBuf in = ctx.outboundByteBuffer();
    final ByteBuf out = ctx.nextOutboundByteBuffer();

    out.unsafe().discardSomeReadBytes();

    // Do not encrypt the first write request if this handler is
    // created with startTLS flag turned on.
    if (startTls && !sentFirstMessage) {
      sentFirstMessage = true;
      out.writeBytes(in);
      ctx.flush(future);
      return;
    }

    if (ctx.executor() == ctx.channel().eventLoop()) {
      flushFutureNotifier.addFlushFuture(future, in.readableBytes());
    } else {
      synchronized (flushFutureNotifier) {
        flushFutureNotifier.addFlushFuture(future, in.readableBytes());
      }
    }

    boolean unwrapLater = false;
    int bytesConsumed = 0;
    try {
      for (; ; ) {
        SSLEngineResult result = wrap(engine, in, out);
        bytesConsumed += result.bytesConsumed();
        if (result.getStatus() == Status.CLOSED) {
          // SSLEngine has been closed already.
          // Any further write attempts should be denied.
          if (in.readable()) {
            in.clear();
            SSLException e = new SSLException("SSLEngine already closed");
            future.setFailure(e);
            ctx.fireExceptionCaught(e);
            flush0(ctx, bytesConsumed, e);
            bytesConsumed = 0;
          }
          break;
        } else {
          switch (result.getHandshakeStatus()) {
            case NEED_WRAP:
              ctx.flush();
              continue;
            case NEED_UNWRAP:
              if (ctx.inboundByteBuffer().readable()) {
                unwrapLater = true;
              }
              break;
            case NEED_TASK:
              runDelegatedTasks();
              continue;
            case FINISHED:
              setHandshakeSuccess();
              continue;
            case NOT_HANDSHAKING:
              break;
            default:
              throw new IllegalStateException(
                  "Unknown handshake status: " + result.getHandshakeStatus());
          }

          if (result.bytesConsumed() == 0 && result.bytesProduced() == 0) {
            break;
          }
        }
      }

      if (unwrapLater) {
        inboundBufferUpdated(ctx);
      }
    } catch (SSLException e) {
      setHandshakeFailure(e);
      throw e;
    } finally {
      in.unsafe().discardSomeReadBytes();
      flush0(ctx, bytesConsumed);
    }
  }