@Override
 public String toString() {
   StringBuilder buf = new StringBuilder().append(StringUtil.simpleClassName(this)).append('(');
   if (group != null) {
     buf.append("group: ").append(StringUtil.simpleClassName(group)).append(", ");
   }
   if (channelFactory != null) {
     buf.append("channelFactory: ").append(channelFactory).append(", ");
   }
   if (localAddress != null) {
     buf.append("localAddress: ").append(localAddress).append(", ");
   }
   synchronized (options) {
     if (!options.isEmpty()) {
       buf.append("options: ").append(options).append(", ");
     }
   }
   synchronized (attrs) {
     if (!attrs.isEmpty()) {
       buf.append("attrs: ").append(attrs).append(", ");
     }
   }
   if (handler != null) {
     buf.append("handler: ").append(handler).append(", ");
   }
   if (buf.charAt(buf.length() - 1) == '(') {
     buf.append(')');
   } else {
     buf.setCharAt(buf.length() - 2, ')');
     buf.setLength(buf.length() - 1);
   }
   return buf.toString();
 }
Beispiel #2
0
  /**
   * If there's no match, returns the result with {@link #notFound(Object) notFound} as the target
   * if it is set, otherwise returns {@code null}.
   */
  public RouteResult<T> route(final HttpMethod method, final String uri) {
    final QueryStringDecoder decoder = new QueryStringDecoder(uri);
    final String[] tokens = StringUtil.split(Path.removeSlashesAtBothEnds(decoder.path()), '/');

    MethodlessRouter<T> router = routers.get(method);
    if (router == null) {
      router = anyMethodRouter;
    }

    RouteResult<T> ret = router.route(tokens);
    if (ret != null) {
      return new RouteResult<T>(ret.target(), ret.pathParams(), decoder.parameters());
    }

    if (router != anyMethodRouter) {
      ret = anyMethodRouter.route(tokens);
      if (ret != null) {
        return new RouteResult<T>(ret.target(), ret.pathParams(), decoder.parameters());
      }
    }

    if (notFound != null) {
      // Return mutable map to be consistent, instead of
      // Collections.<String, String>emptyMap()
      return new RouteResult<T>(notFound, new HashMap<String, String>(), decoder.parameters());
    }

    return null;
  }
Beispiel #3
0
  @Override
  protected Object filterOutboundMessage(Object msg) {
    if (msg instanceof DatagramPacket) {
      DatagramPacket p = (DatagramPacket) msg;
      ByteBuf content = p.content();
      if (isSingleDirectBuffer(content)) {
        return p;
      }
      return new DatagramPacket(newDirectBuffer(p, content), p.recipient());
    }

    if (msg instanceof ByteBuf) {
      ByteBuf buf = (ByteBuf) msg;
      if (isSingleDirectBuffer(buf)) {
        return buf;
      }
      return newDirectBuffer(buf);
    }

    if (msg instanceof AddressedEnvelope) {
      @SuppressWarnings("unchecked")
      AddressedEnvelope<Object, SocketAddress> e = (AddressedEnvelope<Object, SocketAddress>) msg;
      if (e.content() instanceof ByteBuf) {
        ByteBuf content = (ByteBuf) e.content();
        if (isSingleDirectBuffer(content)) {
          return e;
        }
        return new DefaultAddressedEnvelope<ByteBuf, SocketAddress>(
            newDirectBuffer(e, content), e.recipient());
      }
    }

    throw new UnsupportedOperationException(
        "unsupported message type: " + StringUtil.simpleClassName(msg) + EXPECTED_TYPES);
  }
 @Override
 protected int doWrite(MessageList<Object> msgs, int index) throws Exception {
   int size = msgs.size();
   int writeIndex = index;
   for (; ; ) {
     if (writeIndex >= size) {
       break;
     }
     Object msg = msgs.get(writeIndex);
     if (msg instanceof ByteBuf) {
       ByteBuf buf = (ByteBuf) msg;
       while (buf.isReadable()) {
         doWriteBytes(buf);
       }
       buf.release();
       writeIndex++;
     } else if (msg instanceof FileRegion) {
       FileRegion region = (FileRegion) msg;
       doWriteFileRegion(region);
       region.release();
       writeIndex++;
     } else {
       throw new UnsupportedOperationException(
           "unsupported message type: " + StringUtil.simpleClassName(msg));
     }
   }
   return writeIndex - index;
 }
  @Override
  public String toString() {
    StringBuilder buf = new StringBuilder();
    buf.append(StringUtil.simpleClassName(this));
    buf.append("(last: ");
    buf.append(isLast());
    buf.append("; unidirectional: ");
    buf.append(isUnidirectional());
    buf.append(')');
    buf.append(StringUtil.NEWLINE);
    buf.append("--> Stream-ID = ");
    buf.append(streamId());
    buf.append(StringUtil.NEWLINE);
    if (associatedStreamId != 0) {
      buf.append("--> Associated-To-Stream-ID = ");
      buf.append(associatedStreamId());
      buf.append(StringUtil.NEWLINE);
    }
    buf.append("--> Priority = ");
    buf.append(priority());
    buf.append(StringUtil.NEWLINE);
    buf.append("--> Headers:");
    buf.append(StringUtil.NEWLINE);
    appendHeaders(buf);

    // Remove the last newline.
    buf.setLength(buf.length() - StringUtil.NEWLINE.length());
    return buf.toString();
  }
  private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {
    if (logger.isLoggable(Level.FINE)) {
      logger.fine(
          String.format(
              "Channel %s received %s",
              ctx.channel().hashCode(), StringUtil.simpleClassName(frame)));
    }

    if (frame instanceof CloseWebSocketFrame) {
      handshaker.close(ctx.channel(), (CloseWebSocketFrame) frame);
    } else if (frame instanceof PingWebSocketFrame) {
      ctx.write(new PongWebSocketFrame(frame.isFinalFragment(), frame.rsv(), frame.content()));
    } else if (frame instanceof TextWebSocketFrame) {
      ctx.write(frame);
    } else if (frame instanceof BinaryWebSocketFrame) {
      ctx.write(frame);
    } else if (frame instanceof ContinuationWebSocketFrame) {
      ctx.write(frame);
    } else if (frame instanceof PongWebSocketFrame) {
      frame.release();
      // Ignore
    } else {
      throw new UnsupportedOperationException(
          String.format("%s frame types not supported", frame.getClass().getName()));
    }
  }
 @Override
 public String toString() {
   return StringUtil.simpleClassName(ChannelHandlerContext.class)
       + '('
       + name
       + ", "
       + channel
       + ')';
 }
 protected SpdyOrHttpChooser.SelectedProtocol getProtocol(SSLEngine var1) {
   String[] var2 = StringUtil.split(var1.getSession().getProtocol(), ':');
   if (var2.length < 2) {
     return SpdyOrHttpChooser.SelectedProtocol.HTTP_1_1;
   } else {
     SpdyOrHttpChooser.SelectedProtocol var3 =
         SpdyOrHttpChooser.SelectedProtocol.protocol(var2[1]);
     return var3;
   }
 }
Beispiel #9
0
  @Override
  protected final Object filterOutboundMessage(Object msg) throws Exception {
    if (msg instanceof SctpMessage) {
      SctpMessage m = (SctpMessage) msg;
      ByteBuf buf = m.content();
      if (buf.isDirect() && buf.nioBufferCount() == 1) {
        return m;
      }

      return new SctpMessage(
          m.protocolIdentifier(), m.streamIdentifier(), m.isUnordered(), newDirectBuffer(m, buf));
    }

    throw new UnsupportedOperationException(
        "unsupported message type: "
            + StringUtil.simpleClassName(msg)
            + " (expected: "
            + StringUtil.simpleClassName(SctpMessage.class));
  }
 private static int contentLength(Object msg) {
   if (msg instanceof HttpContent) {
     return ((HttpContent) msg).content().readableBytes();
   }
   if (msg instanceof ByteBuf) {
     return ((ByteBuf) msg).readableBytes();
   }
   if (msg instanceof FileRegion) {
     return (int) ((FileRegion) msg).count();
   }
   throw new IllegalStateException("unexpected message type: " + StringUtil.simpleClassName(msg));
 }
 private static Object encodeAndRetain(Object msg) {
   if (msg instanceof ByteBuf) {
     return ((ByteBuf) msg).retain();
   }
   if (msg instanceof HttpContent) {
     return ((HttpContent) msg).content().retain();
   }
   if (msg instanceof FileRegion) {
     return ((FileRegion) msg).retain();
   }
   throw new IllegalStateException("unexpected message type: " + StringUtil.simpleClassName(msg));
 }
 private void reportLeak(Level level) {
   if (!logger.isErrorEnabled()) {
     for (; ; ) {
       ResourceLeakDetector<T>.DefaultResourceLeak ref =
           (DefaultResourceLeak) this.refQueue.poll();
       if (ref == null) {
         break;
       }
       ref.close();
     }
     return;
   }
   int samplingInterval = level == Level.PARANOID ? 1 : this.samplingInterval;
   if ((this.active * samplingInterval > this.maxActive)
       && (this.loggedTooManyActive.compareAndSet(false, true))) {
     logger.error(
         "LEAK: You are creating too many "
             + this.resourceType
             + " instances.  "
             + this.resourceType
             + " is a shared resource that must be reused across the JVM,"
             + "so that only a few instances are created.");
   }
   for (; ; ) {
     ResourceLeakDetector<T>.DefaultResourceLeak ref = (DefaultResourceLeak) this.refQueue.poll();
     if (ref == null) {
       break;
     }
     ref.clear();
     if (ref.close()) {
       String records = ref.toString();
       if (this.reportedLeaks.putIfAbsent(records, Boolean.TRUE) == null) {
         if (records.isEmpty()) {
           logger.error(
               "LEAK: {}.release() was not called before it's garbage-collected. Enable advanced leak reporting to find out where the leak occurred. To enable advanced leak reporting, specify the JVM option '-D{}={}' or call {}.setLevel()",
               new Object[] {
                 this.resourceType,
                 "io.netty.leakDetectionLevel",
                 Level.ADVANCED.name().toLowerCase(),
                 StringUtil.simpleClassName(this)
               });
         } else {
           logger.error(
               "LEAK: {}.release() was not called before it's garbage-collected.{}",
               this.resourceType,
               records);
         }
       }
     }
   }
 }
Beispiel #13
0
  /**
   * Returns allowed methods for a specific URI.
   *
   * <p>For {@code OPTIONS *}, use {@link #allAllowedMethods()} instead of this method.
   */
  public Set<HttpMethod> allowedMethods(final String uri) {
    final QueryStringDecoder decoder = new QueryStringDecoder(uri);
    final String[] tokens = StringUtil.split(Path.removeSlashesAtBothEnds(decoder.path()), '/');

    if (anyMethodRouter.anyMatched(tokens)) {
      return allAllowedMethods();
    }

    final Set<HttpMethod> ret = new HashSet<HttpMethod>(routers.size());
    for (Map.Entry<HttpMethod, MethodlessRouter<T>> entry : routers.entrySet()) {
      final MethodlessRouter<T> router = entry.getValue();
      if (router.anyMatched(tokens)) {
        final HttpMethod method = entry.getKey();
        ret.add(method);
      }
    }

    return ret;
  }
  /**
   * 处理网络事件
   *
   * @param key
   * @throws IOException
   */
  private static void handle(SelectionKey key, Selector selector) throws IOException {
    if (key.isValid()) {
      if (key.isAcceptable()) {
        // 1、客户端请求连接事件(对应:serverChannel.register(selector, SelectionKey.OP_ACCEPT))
        ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
        // 2、接受并得到客户端连接
        SocketChannel channel = serverChannel.accept();
        // 3、设置为非阻塞模式
        channel.configureBlocking(false);
        // 4、得到客户端连接后,并不立即读取io,而是把客户端连接注册到多路复用器上,并监听读io事件
        channel.register(selector, SelectionKey.OP_READ);
      }

      if (key.isReadable()) {
        // 处理io读事件,(对应:channel.register(selector, SelectionKey.OP_READ);)
        SocketChannel channel = (SocketChannel) key.channel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        // 把客户端请求数据读到buffer中
        int readBytes = channel.read(buffer);
        if (readBytes > 0) {
          buffer.flip();
          byte[] bytes = new byte[buffer.remaining()];
          buffer.get(bytes);
          // 得到输入的字符串
          String inputStr = new String(bytes, CharsetUtil.UTF_8);
          System.out.println("收到的输入:" + inputStr);
          // 把了输入的字符串写回客户端
          if (!StringUtil.isNullOrEmpty(inputStr)) {
            byte[] resp = inputStr.getBytes(CharsetUtil.UTF_8);
            ByteBuffer wBuffer = ByteBuffer.allocate(resp.length);
            wBuffer.put(resp);
            wBuffer.flip();
            // 写回客户端
            channel.write(wBuffer);
          }
        }
      }
    }
  }
Beispiel #15
0
  @Override
  protected void encodeInitialLine(final ByteBuf buf, final HttpMessage message) throws Exception {
    if (message instanceof HttpRequest) {
      HttpRequest request = (HttpRequest) message;
      ByteBufUtil.writeAscii(buf, request.method().asciiName());
      buf.writeByte(SP);
      buf.writeBytes(request.uri().getBytes(CharsetUtil.UTF_8));
      buf.writeByte(SP);
      ByteBufUtil.writeAscii(buf, request.protocolVersion().text());
      buf.writeBytes(CRLF);
    } else if (message instanceof HttpResponse) {
      HttpResponse response = (HttpResponse) message;
      ByteBufUtil.writeAscii(buf, response.protocolVersion().text());
      buf.writeByte(SP);
      buf.writeBytes(String.valueOf(response.status().code()).getBytes(CharsetUtil.US_ASCII));
      buf.writeByte(SP);
      ByteBufUtil.writeAscii(buf, response.status().reasonPhrase());

      buf.writeBytes(CRLF);
    } else {
      throw new UnsupportedMessageTypeException(
          "Unsupported type " + StringUtil.simpleClassName(message));
    }
  }
Beispiel #16
0
/**
 * An NIO datagram {@link Channel} that sends and receives an {@link AddressedEnvelope
 * AddressedEnvelope<ByteBuf, SocketAddress>}.
 *
 * @see AddressedEnvelope
 * @see DatagramPacket
 */
public final class NioDatagramChannel extends AbstractNioMessageChannel
    implements io.netty.channel.socket.DatagramChannel {

  private static final ChannelMetadata METADATA = new ChannelMetadata(true);
  private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();
  private static final String EXPECTED_TYPES =
      " (expected: "
          + StringUtil.simpleClassName(DatagramPacket.class)
          + ", "
          + StringUtil.simpleClassName(AddressedEnvelope.class)
          + '<'
          + StringUtil.simpleClassName(ByteBuf.class)
          + ", "
          + StringUtil.simpleClassName(SocketAddress.class)
          + ">, "
          + StringUtil.simpleClassName(ByteBuf.class)
          + ')';

  private final DatagramChannelConfig config;

  private Map<InetAddress, List<MembershipKey>> memberships;

  private static DatagramChannel newSocket(SelectorProvider provider) {
    try {
      /**
       * Use the {@link SelectorProvider} to open {@link SocketChannel} and so remove condition in
       * {@link SelectorProvider#provider()} which is called by each DatagramChannel.open()
       * otherwise.
       *
       * <p>See <a href="https://github.com/netty/netty/issues/2308">#2308</a>.
       */
      return provider.openDatagramChannel();
    } catch (IOException e) {
      throw new ChannelException("Failed to open a socket.", e);
    }
  }

  private static DatagramChannel newSocket(
      SelectorProvider provider, InternetProtocolFamily ipFamily) {
    if (ipFamily == null) {
      return newSocket(provider);
    }

    checkJavaVersion();

    try {
      return provider.openDatagramChannel(ProtocolFamilyConverter.convert(ipFamily));
    } catch (IOException e) {
      throw new ChannelException("Failed to open a socket.", e);
    }
  }

  private static void checkJavaVersion() {
    if (PlatformDependent.javaVersion() < 7) {
      throw new UnsupportedOperationException("Only supported on java 7+.");
    }
  }

  /**
   * Create a new instance which will use the Operation Systems default {@link
   * InternetProtocolFamily}.
   */
  public NioDatagramChannel() {
    this(newSocket(DEFAULT_SELECTOR_PROVIDER));
  }

  /**
   * Create a new instance using the given {@link SelectorProvider} which will use the Operation
   * Systems default {@link InternetProtocolFamily}.
   */
  public NioDatagramChannel(SelectorProvider provider) {
    this(newSocket(provider));
  }

  /**
   * Create a new instance using the given {@link InternetProtocolFamily}. If {@code null} is used
   * it will depend on the Operation Systems default which will be chosen.
   */
  public NioDatagramChannel(InternetProtocolFamily ipFamily) {
    this(newSocket(DEFAULT_SELECTOR_PROVIDER, ipFamily));
  }

  /**
   * Create a new instance using the given {@link SelectorProvider} and {@link
   * InternetProtocolFamily}. If {@link InternetProtocolFamily} is {@code null} it will depend on
   * the Operation Systems default which will be chosen.
   */
  public NioDatagramChannel(SelectorProvider provider, InternetProtocolFamily ipFamily) {
    this(newSocket(provider, ipFamily));
  }

  /** Create a new instance from the given {@link DatagramChannel}. */
  public NioDatagramChannel(DatagramChannel socket) {
    super(null, socket, SelectionKey.OP_READ);
    config = new NioDatagramChannelConfig(this, socket);
  }

  @Override
  public ChannelMetadata metadata() {
    return METADATA;
  }

  @Override
  public DatagramChannelConfig config() {
    return config;
  }

  @Override
  @SuppressWarnings("deprecation")
  public boolean isActive() {
    DatagramChannel ch = javaChannel();
    return ch.isOpen()
        && (config.getOption(ChannelOption.DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION)
                && isRegistered()
            || ch.socket().isBound());
  }

  @Override
  public boolean isConnected() {
    return javaChannel().isConnected();
  }

  @Override
  protected DatagramChannel javaChannel() {
    return (DatagramChannel) super.javaChannel();
  }

  @Override
  protected SocketAddress localAddress0() {
    return javaChannel().socket().getLocalSocketAddress();
  }

  @Override
  protected SocketAddress remoteAddress0() {
    return javaChannel().socket().getRemoteSocketAddress();
  }

  @Override
  protected void doBind(SocketAddress localAddress) throws Exception {
    javaChannel().socket().bind(localAddress);
  }

  @Override
  protected boolean doConnect(SocketAddress remoteAddress, SocketAddress localAddress)
      throws Exception {
    if (localAddress != null) {
      javaChannel().socket().bind(localAddress);
    }

    boolean success = false;
    try {
      javaChannel().connect(remoteAddress);
      success = true;
      return true;
    } finally {
      if (!success) {
        doClose();
      }
    }
  }

  @Override
  protected void doFinishConnect() throws Exception {
    throw new Error();
  }

  @Override
  protected void doDisconnect() throws Exception {
    javaChannel().disconnect();
  }

  @Override
  protected void doClose() throws Exception {
    javaChannel().close();
  }

  @Override
  protected int doReadMessages(List<Object> buf) throws Exception {
    DatagramChannel ch = javaChannel();
    DatagramChannelConfig config = config();
    RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();

    ByteBuf data = allocHandle.allocate(config.getAllocator());
    allocHandle.attemptedBytesRead(data.writableBytes());
    boolean free = true;
    try {
      ByteBuffer nioData = data.internalNioBuffer(data.writerIndex(), data.writableBytes());
      int pos = nioData.position();
      InetSocketAddress remoteAddress = (InetSocketAddress) ch.receive(nioData);
      if (remoteAddress == null) {
        return 0;
      }

      allocHandle.lastBytesRead(nioData.position() - pos);
      buf.add(
          new DatagramPacket(
              data.writerIndex(data.writerIndex() + allocHandle.lastBytesRead()),
              localAddress(),
              remoteAddress));
      free = false;
      return 1;
    } catch (Throwable cause) {
      PlatformDependent.throwException(cause);
      return -1;
    } finally {
      if (free) {
        data.release();
      }
    }
  }

  @Override
  protected boolean doWriteMessage(Object msg, ChannelOutboundBuffer in) throws Exception {
    final SocketAddress remoteAddress;
    final ByteBuf data;
    if (msg instanceof AddressedEnvelope) {
      @SuppressWarnings("unchecked")
      AddressedEnvelope<ByteBuf, SocketAddress> envelope =
          (AddressedEnvelope<ByteBuf, SocketAddress>) msg;
      remoteAddress = envelope.recipient();
      data = envelope.content();
    } else {
      data = (ByteBuf) msg;
      remoteAddress = null;
    }

    final int dataLen = data.readableBytes();
    if (dataLen == 0) {
      return true;
    }

    final ByteBuffer nioData = data.internalNioBuffer(data.readerIndex(), dataLen);
    final int writtenBytes;
    if (remoteAddress != null) {
      writtenBytes = javaChannel().send(nioData, remoteAddress);
    } else {
      writtenBytes = javaChannel().write(nioData);
    }
    return writtenBytes > 0;
  }

  @Override
  protected Object filterOutboundMessage(Object msg) {
    if (msg instanceof DatagramPacket) {
      DatagramPacket p = (DatagramPacket) msg;
      ByteBuf content = p.content();
      if (isSingleDirectBuffer(content)) {
        return p;
      }
      return new DatagramPacket(newDirectBuffer(p, content), p.recipient());
    }

    if (msg instanceof ByteBuf) {
      ByteBuf buf = (ByteBuf) msg;
      if (isSingleDirectBuffer(buf)) {
        return buf;
      }
      return newDirectBuffer(buf);
    }

    if (msg instanceof AddressedEnvelope) {
      @SuppressWarnings("unchecked")
      AddressedEnvelope<Object, SocketAddress> e = (AddressedEnvelope<Object, SocketAddress>) msg;
      if (e.content() instanceof ByteBuf) {
        ByteBuf content = (ByteBuf) e.content();
        if (isSingleDirectBuffer(content)) {
          return e;
        }
        return new DefaultAddressedEnvelope<ByteBuf, SocketAddress>(
            newDirectBuffer(e, content), e.recipient());
      }
    }

    throw new UnsupportedOperationException(
        "unsupported message type: " + StringUtil.simpleClassName(msg) + EXPECTED_TYPES);
  }

  /**
   * Checks if the specified buffer is a direct buffer and is composed of a single NIO buffer. (We
   * check this because otherwise we need to make it a non-composite buffer.)
   */
  private static boolean isSingleDirectBuffer(ByteBuf buf) {
    return buf.isDirect() && buf.nioBufferCount() == 1;
  }

  @Override
  protected boolean continueOnWriteError() {
    // Continue on write error as a DatagramChannel can write to multiple remote peers
    //
    // See https://github.com/netty/netty/issues/2665
    return true;
  }

  @Override
  public InetSocketAddress localAddress() {
    return (InetSocketAddress) super.localAddress();
  }

  @Override
  public InetSocketAddress remoteAddress() {
    return (InetSocketAddress) super.remoteAddress();
  }

  @Override
  public ChannelFuture joinGroup(InetAddress multicastAddress) {
    return joinGroup(multicastAddress, newPromise());
  }

  @Override
  public ChannelFuture joinGroup(InetAddress multicastAddress, ChannelPromise promise) {
    try {
      return joinGroup(
          multicastAddress,
          NetworkInterface.getByInetAddress(localAddress().getAddress()),
          null,
          promise);
    } catch (SocketException e) {
      promise.setFailure(e);
    }
    return promise;
  }

  @Override
  public ChannelFuture joinGroup(
      InetSocketAddress multicastAddress, NetworkInterface networkInterface) {
    return joinGroup(multicastAddress, networkInterface, newPromise());
  }

  @Override
  public ChannelFuture joinGroup(
      InetSocketAddress multicastAddress,
      NetworkInterface networkInterface,
      ChannelPromise promise) {
    return joinGroup(multicastAddress.getAddress(), networkInterface, null, promise);
  }

  @Override
  public ChannelFuture joinGroup(
      InetAddress multicastAddress, NetworkInterface networkInterface, InetAddress source) {
    return joinGroup(multicastAddress, networkInterface, source, newPromise());
  }

  @Override
  public ChannelFuture joinGroup(
      InetAddress multicastAddress,
      NetworkInterface networkInterface,
      InetAddress source,
      ChannelPromise promise) {

    checkJavaVersion();

    if (multicastAddress == null) {
      throw new NullPointerException("multicastAddress");
    }

    if (networkInterface == null) {
      throw new NullPointerException("networkInterface");
    }

    try {
      MembershipKey key;
      if (source == null) {
        key = javaChannel().join(multicastAddress, networkInterface);
      } else {
        key = javaChannel().join(multicastAddress, networkInterface, source);
      }

      synchronized (this) {
        List<MembershipKey> keys = null;
        if (memberships == null) {
          memberships = new HashMap<InetAddress, List<MembershipKey>>();
        } else {
          keys = memberships.get(multicastAddress);
        }
        if (keys == null) {
          keys = new ArrayList<MembershipKey>();
          memberships.put(multicastAddress, keys);
        }
        keys.add(key);
      }

      promise.setSuccess();
    } catch (Throwable e) {
      promise.setFailure(e);
    }

    return promise;
  }

  @Override
  public ChannelFuture leaveGroup(InetAddress multicastAddress) {
    return leaveGroup(multicastAddress, newPromise());
  }

  @Override
  public ChannelFuture leaveGroup(InetAddress multicastAddress, ChannelPromise promise) {
    try {
      return leaveGroup(
          multicastAddress,
          NetworkInterface.getByInetAddress(localAddress().getAddress()),
          null,
          promise);
    } catch (SocketException e) {
      promise.setFailure(e);
    }
    return promise;
  }

  @Override
  public ChannelFuture leaveGroup(
      InetSocketAddress multicastAddress, NetworkInterface networkInterface) {
    return leaveGroup(multicastAddress, networkInterface, newPromise());
  }

  @Override
  public ChannelFuture leaveGroup(
      InetSocketAddress multicastAddress,
      NetworkInterface networkInterface,
      ChannelPromise promise) {
    return leaveGroup(multicastAddress.getAddress(), networkInterface, null, promise);
  }

  @Override
  public ChannelFuture leaveGroup(
      InetAddress multicastAddress, NetworkInterface networkInterface, InetAddress source) {
    return leaveGroup(multicastAddress, networkInterface, source, newPromise());
  }

  @Override
  public ChannelFuture leaveGroup(
      InetAddress multicastAddress,
      NetworkInterface networkInterface,
      InetAddress source,
      ChannelPromise promise) {
    checkJavaVersion();

    if (multicastAddress == null) {
      throw new NullPointerException("multicastAddress");
    }
    if (networkInterface == null) {
      throw new NullPointerException("networkInterface");
    }

    synchronized (this) {
      if (memberships != null) {
        List<MembershipKey> keys = memberships.get(multicastAddress);
        if (keys != null) {
          Iterator<MembershipKey> keyIt = keys.iterator();

          while (keyIt.hasNext()) {
            MembershipKey key = keyIt.next();
            if (networkInterface.equals(key.networkInterface())) {
              if (source == null && key.sourceAddress() == null
                  || source != null && source.equals(key.sourceAddress())) {
                key.drop();
                keyIt.remove();
              }
            }
          }
          if (keys.isEmpty()) {
            memberships.remove(multicastAddress);
          }
        }
      }
    }

    promise.setSuccess();
    return promise;
  }

  /**
   * Block the given sourceToBlock address for the given multicastAddress on the given
   * networkInterface
   */
  @Override
  public ChannelFuture block(
      InetAddress multicastAddress, NetworkInterface networkInterface, InetAddress sourceToBlock) {
    return block(multicastAddress, networkInterface, sourceToBlock, newPromise());
  }

  /**
   * Block the given sourceToBlock address for the given multicastAddress on the given
   * networkInterface
   */
  @Override
  public ChannelFuture block(
      InetAddress multicastAddress,
      NetworkInterface networkInterface,
      InetAddress sourceToBlock,
      ChannelPromise promise) {
    checkJavaVersion();

    if (multicastAddress == null) {
      throw new NullPointerException("multicastAddress");
    }
    if (sourceToBlock == null) {
      throw new NullPointerException("sourceToBlock");
    }

    if (networkInterface == null) {
      throw new NullPointerException("networkInterface");
    }
    synchronized (this) {
      if (memberships != null) {
        List<MembershipKey> keys = memberships.get(multicastAddress);
        for (MembershipKey key : keys) {
          if (networkInterface.equals(key.networkInterface())) {
            try {
              key.block(sourceToBlock);
            } catch (IOException e) {
              promise.setFailure(e);
            }
          }
        }
      }
    }
    promise.setSuccess();
    return promise;
  }

  /** Block the given sourceToBlock address for the given multicastAddress */
  @Override
  public ChannelFuture block(InetAddress multicastAddress, InetAddress sourceToBlock) {
    return block(multicastAddress, sourceToBlock, newPromise());
  }

  /** Block the given sourceToBlock address for the given multicastAddress */
  @Override
  public ChannelFuture block(
      InetAddress multicastAddress, InetAddress sourceToBlock, ChannelPromise promise) {
    try {
      return block(
          multicastAddress,
          NetworkInterface.getByInetAddress(localAddress().getAddress()),
          sourceToBlock,
          promise);
    } catch (SocketException e) {
      promise.setFailure(e);
    }
    return promise;
  }

  @Override
  @Deprecated
  protected void setReadPending(boolean readPending) {
    super.setReadPending(readPending);
  }

  void clearReadPending0() {
    clearReadPending();
  }
}
Beispiel #17
0
 @Override
 public String toString() {
   return StringUtil.simpleClassName(this) + '(' + buf.toString() + ')';
 }
Beispiel #18
0
 @Override
 public CombinedHttpHeaders add(CharSequence name, CharSequence value) {
   return addEscapedValue(name, StringUtil.escapeCsv(value));
 }
  @Override
  protected boolean doWriteMessage(Object msg, ChannelOutboundBuffer in) throws Exception {
    final Object m;
    final SocketAddress remoteAddress;
    ByteBuf data;
    if (msg instanceof AddressedEnvelope) {
      @SuppressWarnings("unchecked")
      AddressedEnvelope<Object, SocketAddress> envelope =
          (AddressedEnvelope<Object, SocketAddress>) msg;
      remoteAddress = envelope.recipient();
      m = envelope.content();
    } else {
      m = msg;
      remoteAddress = null;
    }

    if (m instanceof ByteBufHolder) {
      data = ((ByteBufHolder) m).content();
    } else if (m instanceof ByteBuf) {
      data = (ByteBuf) m;
    } else {
      throw new UnsupportedOperationException(
          "unsupported message type: " + StringUtil.simpleClassName(msg));
    }

    int dataLen = data.readableBytes();
    if (dataLen == 0) {
      return true;
    }

    ByteBufAllocator alloc = alloc();
    boolean needsCopy = data.nioBufferCount() != 1;
    if (!needsCopy) {
      if (!data.isDirect() && alloc.isDirectBufferPooled()) {
        needsCopy = true;
      }
    }
    ByteBuffer nioData;
    if (!needsCopy) {
      nioData = data.nioBuffer();
    } else {
      data = alloc.directBuffer(dataLen).writeBytes(data);
      nioData = data.nioBuffer();
    }

    final int writtenBytes;
    if (remoteAddress != null) {
      writtenBytes = javaChannel().send(nioData, remoteAddress);
    } else {
      writtenBytes = javaChannel().write(nioData);
    }

    boolean done = writtenBytes > 0;
    if (needsCopy) {
      // This means we have allocated a new buffer and need to store it back so we not need to
      // allocate it again
      // later
      if (remoteAddress == null) {
        // remoteAddress is null which means we can handle it as ByteBuf directly
        in.current(data);
      } else {
        if (!done) {
          // store it back with all the needed informations
          in.current(new DefaultAddressedEnvelope<ByteBuf, SocketAddress>(data, remoteAddress));
        } else {
          // Just store back the new create buffer so it is cleaned up once in.remove() is called.
          in.current(data);
        }
      }
    }
    return done;
  }
 public ResourceLeakDetector(Class<?> resourceType, int samplingInterval, long maxActive) {
   this(StringUtil.simpleClassName(resourceType), samplingInterval, maxActive);
 }
  @Override
  protected void doWrite(ChannelOutboundBuffer in) throws Exception {
    for (; ; ) {
      final int msgCount = in.size();

      if (msgCount == 0) {
        // Wrote all messages.
        clearEpollOut();
        break;
      }

      // Do gathering write if:
      // * the outbound buffer contains more than one messages and
      // * they are all buffers rather than a file region.
      if (msgCount > 1) {
        if (PlatformDependent.hasUnsafe()) {
          // this means we can cast to EpollChannelOutboundBuffer and write the AdressEntry
          // directly.
          EpollChannelOutboundBuffer epollIn = (EpollChannelOutboundBuffer) in;
          // Ensure the pending writes are made of memoryaddresses only.
          AddressEntry[] addresses = epollIn.memoryAddresses();
          if (addresses != null) {
            writeBytesMultiple(epollIn, msgCount, addresses);

            // We do not break the loop here even if the outbound buffer was flushed completely,
            // because a user might have triggered another write and flush when we notify his or her
            // listeners.
            continue;
          }
        } else {
          NioSocketChannelOutboundBuffer nioIn = (NioSocketChannelOutboundBuffer) in;
          // Ensure the pending writes are made of memoryaddresses only.
          ByteBuffer[] buffers = nioIn.nioBuffers();
          if (buffers != null) {
            writeBytesMultiple(nioIn, msgCount, buffers);

            // We do not break the loop here even if the outbound buffer was flushed completely,
            // because a user might have triggered another write and flush when we notify his or her
            // listeners.
            continue;
          }
        }
      }

      // The outbound buffer contains only one message or it contains a file region.
      Object msg = in.current();
      if (msg instanceof ByteBuf) {
        ByteBuf buf = (ByteBuf) msg;
        int readableBytes = buf.readableBytes();
        if (readableBytes == 0) {
          in.remove();
          continue;
        }

        int expected = buf.readableBytes();
        int localFlushedAmount = doWriteBytes(buf, expected);
        in.progress(localFlushedAmount);
        if (localFlushedAmount < expected) {
          setEpollOut();
          break;
        }
        if (!buf.isReadable()) {
          in.remove();
        }

      } else if (msg instanceof DefaultFileRegion) {
        DefaultFileRegion region = (DefaultFileRegion) msg;

        long expected = region.count() - region.position();
        long localFlushedAmount = doWriteFileRegion(region, expected);
        in.progress(localFlushedAmount);

        if (localFlushedAmount < expected) {
          setEpollOut();
          break;
        }

        if (region.transfered() >= region.count()) {
          in.remove();
        }
      } else {
        throw new UnsupportedOperationException(
            "unsupported message type: " + StringUtil.simpleClassName(msg));
      }
    }
  }
 public ResourceLeakDetector(Class<?> resourceType) {
   this(StringUtil.simpleClassName(resourceType));
 }
  @Override
  protected void encode(ChannelHandlerContext ctx, Object msg, List<Object> out) throws Exception {
    ByteBuf buf = null;
    if (msg instanceof HttpMessage) {
      if (state != ST_INIT) {
        throw new IllegalStateException(
            "unexpected message type: " + StringUtil.simpleClassName(msg));
      }

      @SuppressWarnings({"unchecked", "CastConflictsWithInstanceof"})
      H m = (H) msg;

      buf = ctx.alloc().buffer();
      // Encode the message.
      encodeInitialLine(buf, m);
      HttpHeaders.encode(m.headers(), buf);
      buf.writeBytes(CRLF);
      state = HttpHeaders.isTransferEncodingChunked(m) ? ST_CONTENT_CHUNK : ST_CONTENT_NON_CHUNK;
    }
    if (msg instanceof HttpContent || msg instanceof ByteBuf || msg instanceof FileRegion) {
      if (state == ST_INIT) {
        throw new IllegalStateException(
            "unexpected message type: " + StringUtil.simpleClassName(msg));
      }

      int contentLength = contentLength(msg);
      if (state == ST_CONTENT_NON_CHUNK) {
        if (contentLength > 0) {
          if (buf != null && buf.writableBytes() >= contentLength && msg instanceof HttpContent) {
            // merge into other buffer for performance reasons
            buf.writeBytes(((HttpContent) msg).content());
            out.add(buf);
          } else {
            if (buf != null) {
              out.add(buf);
            }
            out.add(encodeAndRetain(msg));
          }
        } else {
          if (buf != null) {
            out.add(buf);
          } else {
            // Need to produce some output otherwise an
            // IllegalStateException will be thrown
            out.add(EMPTY_BUFFER);
          }
        }

        if (msg instanceof LastHttpContent) {
          state = ST_INIT;
        }
      } else if (state == ST_CONTENT_CHUNK) {
        if (buf != null) {
          out.add(buf);
        }
        encodeChunkedContent(ctx, msg, contentLength, out);
      } else {
        throw new Error();
      }
    } else {
      if (buf != null) {
        out.add(buf);
      }
    }
  }
  @Override
  protected void doWrite(ChannelOutboundBuffer in) throws Exception {
    int writeSpinCount = -1;

    GatheringByteChannel sink = connection().getSinkChannel();
    for (; ; ) {
      // Do gathering write for a non-single buffer case.
      final int msgCount = in.size();
      if (msgCount > 0) {
        // Ensure the pending writes are made of ByteBufs only.
        ByteBuffer[] nioBuffers = in.nioBuffers();
        if (nioBuffers != null) {

          int nioBufferCnt = in.nioBufferCount();
          long expectedWrittenBytes = in.nioBufferSize();

          long writtenBytes = 0;
          boolean done = false;
          boolean setOpWrite = false;
          for (int i = config().getWriteSpinCount() - 1; i >= 0; i--) {
            final long localWrittenBytes = sink.write(nioBuffers, 0, nioBufferCnt);
            if (localWrittenBytes == 0) {
              setOpWrite = true;
              break;
            }
            expectedWrittenBytes -= localWrittenBytes;
            writtenBytes += localWrittenBytes;
            if (expectedWrittenBytes == 0) {
              done = true;
              break;
            }
          }

          if (done) {
            // Release all buffers
            for (int i = msgCount; i > 0; i--) {
              in.remove();
            }

            // Finish the write loop if no new messages were flushed by in.remove().
            if (in.isEmpty()) {
              connection().getSinkChannel().suspendWrites();
              break;
            }
          } else {
            // Did not write all buffers completely.
            // Release the fully written buffers and update the indexes of the partially written
            // buffer.

            for (int i = msgCount; i > 0; i--) {
              final ByteBuf buf = (ByteBuf) in.current();
              final int readerIndex = buf.readerIndex();
              final int readableBytes = buf.writerIndex() - readerIndex;

              if (readableBytes < writtenBytes) {
                in.progress(readableBytes);
                in.remove();
                writtenBytes -= readableBytes;
              } else if (readableBytes > writtenBytes) {
                buf.readerIndex(readerIndex + (int) writtenBytes);
                in.progress(writtenBytes);
                break;
              } else { // readableBytes == writtenBytes
                in.progress(readableBytes);
                in.remove();
                break;
              }
            }

            incompleteWrite(setOpWrite);
            break;
          }
          continue;
        }
      }

      Object msg = in.current();
      if (msg == null) {
        // Wrote all messages.
        connection().getSinkChannel().suspendWrites();
        break;
      }

      if (msg instanceof ByteBuf) {
        ByteBuf buf = (ByteBuf) msg;
        int readableBytes = buf.readableBytes();
        if (readableBytes == 0) {
          in.remove();
          continue;
        }

        if (!buf.isDirect()) {
          ByteBufAllocator alloc = alloc();
          if (alloc.isDirectBufferPooled()) {
            // Non-direct buffers are copied into JDK's own internal direct buffer on every I/O.
            // We can do a better job by using our pooled allocator. If the current allocator does
            // not
            // pool a direct buffer, we rely on JDK's direct buffer pool.
            buf = alloc.directBuffer(readableBytes).writeBytes(buf);
            in.current(buf);
          }
        }

        boolean setOpWrite = false;
        boolean done = false;
        long flushedAmount = 0;
        if (writeSpinCount == -1) {
          writeSpinCount = config().getWriteSpinCount();
        }
        for (int i = writeSpinCount - 1; i >= 0; i--) {
          int localFlushedAmount = buf.readBytes(sink, buf.readableBytes());
          if (localFlushedAmount == 0) {
            setOpWrite = true;
            break;
          }

          flushedAmount += localFlushedAmount;
          if (!buf.isReadable()) {
            done = true;
            break;
          }
        }

        in.progress(flushedAmount);

        if (done) {
          in.remove();
        } else {
          incompleteWrite(setOpWrite);
          break;
        }
      } else if (msg instanceof FileRegion) {
        FileRegion region = (FileRegion) msg;
        boolean setOpWrite = false;
        boolean done = false;
        long flushedAmount = 0;
        if (writeSpinCount == -1) {
          writeSpinCount = config().getWriteSpinCount();
        }
        for (int i = writeSpinCount - 1; i >= 0; i--) {
          long localFlushedAmount = region.transferTo(sink, region.transfered());
          if (localFlushedAmount == 0) {
            setOpWrite = true;
            break;
          }

          flushedAmount += localFlushedAmount;
          if (region.transfered() >= region.count()) {
            done = true;
            break;
          }
        }

        in.progress(flushedAmount);

        if (done) {
          in.remove();
        } else {
          incompleteWrite(setOpWrite);
          break;
        }
      } else {
        throw new UnsupportedOperationException(
            "unsupported message type: " + StringUtil.simpleClassName(msg));
      }
    }
  }