@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(); }
/** * 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; }
@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; } }
@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); } } } } }
/** * 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); } } } } }
@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)); } }
/** * 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(); } }
@Override public String toString() { return StringUtil.simpleClassName(this) + '(' + buf.toString() + ')'; }
@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)); } } }