private long waitForNextTick() { long deadline = startTime + tickDuration * tick; for (; ; ) { final long currentTime = System.currentTimeMillis(); long sleepTime = tickDuration * tick - (currentTime - startTime); // Check if we run on windows, as if thats the case we will need // to round the sleepTime as workaround for a bug that only affect // the JVM if it runs on windows. // // See https://github.com/netty/netty/issues/356 if (DetectionUtil.isWindows()) { sleepTime = sleepTime / 10 * 10; } if (sleepTime <= 0) { break; } try { Thread.sleep(sleepTime); } catch (InterruptedException e) { if (shutdown.get()) { return -1; } } } // Increase the tick. tick++; return deadline; }
@Override public final void bind(final SocketAddress localAddress, final ChannelFuture future) { if (eventLoop().inEventLoop()) { if (!ensureOpen(future)) { return; } try { boolean wasActive = isActive(); // See: https://github.com/netty/netty/issues/576 if (!DetectionUtil.isWindows() && !DetectionUtil.isRoot() && Boolean.TRUE.equals(config().getOption(ChannelOption.SO_BROADCAST)) && localAddress instanceof InetSocketAddress && !((InetSocketAddress) localAddress).getAddress().isAnyLocalAddress()) { // Warn a user about the fact that a non-root user can't receive a // broadcast packet on *nix if the socket is bound on non-wildcard address. logger.warn( "A non-root user can't receive a broadcast packet if the socket " + "is not bound to a wildcard address; binding to a non-wildcard " + "address (" + localAddress + ") anyway as requested."); } doBind(localAddress); future.setSuccess(); if (!wasActive && isActive()) { pipeline.fireChannelActive(); } } catch (Throwable t) { future.setFailure(t); closeIfClosed(); } } else { eventLoop() .execute( new Runnable() { @Override public void run() { bind(localAddress, future); } }); } }
/** * Checks if the given {@link Throwable} can be ignore and just "swallowed" * * <p>When an ssl connection is closed a close_notify message is sent. After that the peer also * sends close_notify however, it's not mandatory to receive the close_notify. The party who sent * the initial close_notify can close the connection immediately then the peer will get connection * reset error. */ private boolean ignoreException(Throwable t) { if (!(t instanceof SSLException) && t instanceof IOException && engine.isOutboundDone()) { String message = String.valueOf(t.getMessage()).toLowerCase(); // first try to match connection reset / broke peer based on the regex. This is the fastest // way // but may fail on different jdk impls or OS's if (IGNORABLE_ERROR_MESSAGE.matcher(message).matches()) { return true; } // Inspect the StackTraceElements to see if it was a connection reset / broken pipe or not StackTraceElement[] elements = t.getStackTrace(); for (StackTraceElement element : elements) { String classname = element.getClassName(); String methodname = element.getMethodName(); // skip all classes that belong to the io.netty package if (classname.startsWith("io.netty.")) { continue; } // check if the method name is read if not skip it if (!"read".equals(methodname)) { continue; } // This will also match against SocketInputStream which is used by openjdk 7 and maybe // also others if (IGNORABLE_CLASS_IN_STACK.matcher(classname).matches()) { return true; } try { // No match by now.. Try to load the class via classloader and inspect it. // This is mainly done as other JDK implementations may differ in name of // the impl. Class<?> clazz = getClass().getClassLoader().loadClass(classname); if (SocketChannel.class.isAssignableFrom(clazz) || DatagramChannel.class.isAssignableFrom(clazz)) { return true; } // also match against SctpChannel via String matching as it may not present. if (DetectionUtil.javaVersion() >= 7 && "com.sun.nio.sctp.SctpChannel".equals(clazz.getSuperclass().getName())) { return true; } } catch (ClassNotFoundException e) { // This should not happen just ignore } } } return false; }
private void setOption0(Object option, Object value) { if (DetectionUtil.javaVersion() < 7) { throw new UnsupportedOperationException(); } else { try { SET_OPTION.invoke(javaChannel, option, value); } catch (Exception e) { throw new ChannelException(e); } } }
private Object getOption0(Object option) { if (DetectionUtil.javaVersion() < 7) { throw new UnsupportedOperationException(); } else { try { return GET_OPTION.invoke(javaChannel, option); } catch (Exception e) { throw new ChannelException(e); } } }
@Override public void setBroadcast(boolean broadcast) { try { // See: https://github.com/netty/netty/issues/576 if (broadcast && !DetectionUtil.isWindows() && !DetectionUtil.isRoot() && !socket.getLocalAddress().isAnyLocalAddress()) { // Warn a user about the fact that a non-root user can't receive a // broadcast packet on *nix if the socket is bound on non-wildcard address. logger.warn( "A non-root user can't receive a broadcast packet if the socket " + "is not bound to a wildcard address; setting the SO_BROADCAST flag " + "anyway as requested on the socket which is bound to " + socket.getLocalSocketAddress() + '.'); } socket.setBroadcast(broadcast); } catch (SocketException e) { throw new ChannelException(e); } }
private static DatagramChannel newSocket(InternetProtocolFamily ipFamily) { if (ipFamily == null) { return newSocket(); } if (DetectionUtil.javaVersion() < 7) { throw new UnsupportedOperationException(); } try { return DatagramChannel.open(ProtocolFamilyConverter.convert(ipFamily)); } catch (IOException e) { throw new ChannelException("Failed to open a socket.", e); } }
@Override public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { if (DetectionUtil.javaVersion() < 7) { // XXX Gathering write is not supported because of a known issue. // See http://bugs.sun.com/view_bug.do?bug_id=6210541 return out.write(copiedNioBuffer(index, length)); } else { long writtenBytes = out.write(nioBuffers(index, length)); if (writtenBytes > Integer.MAX_VALUE) { return Integer.MAX_VALUE; } else { return (int) writtenBytes; } } }
@Override public ChannelFuture leaveGroup( InetAddress multicastAddress, NetworkInterface networkInterface, InetAddress source, ChannelPromise promise) { if (DetectionUtil.javaVersion() < 7) { throw new UnsupportedOperationException(); } 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; }
@Override public ChannelFuture joinGroup( InetAddress multicastAddress, NetworkInterface networkInterface, InetAddress source, ChannelPromise promise) { if (DetectionUtil.javaVersion() >= 7) { 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 = 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); } } else { throw new UnsupportedOperationException(); } 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, ChannelPromise promise) { if (DetectionUtil.javaVersion() < 7) { throw new UnsupportedOperationException(); } else { 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; } }