@Override public DatagramChannel bind(SocketAddress local) throws IOException { synchronized (readLock) { synchronized (writeLock) { synchronized (stateLock) { ensureOpen(); if (localAddress != null) throw new AlreadyBoundException(); InetSocketAddress isa; if (local == null) { // only Inet4Address allowed with IPv4 socket if (family == StandardProtocolFamily.INET) { isa = new InetSocketAddress(InetAddress.getByName("0.0.0.0"), 0); } else { isa = new InetSocketAddress(0); } } else { isa = Net.checkAddress(local); // only Inet4Address allowed with IPv4 socket if (family == StandardProtocolFamily.INET) { InetAddress addr = isa.getAddress(); if (!(addr instanceof Inet4Address)) throw new UnsupportedAddressTypeException(); } } SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkListen(isa.getPort()); } Net.bind(family, fd, isa.getAddress(), isa.getPort()); localAddress = Net.localAddress(fd); } } } return this; }
public DatagramChannel connect(SocketAddress sa) throws IOException { int localPort = 0; synchronized (readLock) { synchronized (writeLock) { synchronized (stateLock) { ensureOpenAndUnconnected(); InetSocketAddress isa = Net.checkAddress(sa); SecurityManager sm = System.getSecurityManager(); if (sm != null) sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort()); int n = Net.connect(family, fd, isa.getAddress(), isa.getPort()); if (n <= 0) throw new Error(); // Can't happen // Connection succeeded; disallow further invocation state = ST_CONNECTED; remoteAddress = sa; sender = isa; cachedSenderInetAddress = isa.getAddress(); cachedSenderPort = isa.getPort(); // set or refresh local address localAddress = Net.localAddress(fd); } } } return this; }
/** Block datagrams from given source if a memory to receive all datagrams. */ void block(MembershipKeyImpl key, InetAddress source) throws IOException { assert key.channel() == this; assert key.sourceAddress() == null; synchronized (stateLock) { if (!key.isValid()) throw new IllegalStateException("key is no longer valid"); if (source.isAnyLocalAddress()) throw new IllegalArgumentException("Source address is a wildcard address"); if (source.isMulticastAddress()) throw new IllegalArgumentException("Source address is multicast address"); if (source.getClass() != key.group().getClass()) throw new IllegalArgumentException("Source address is different type to group"); int n; if (key instanceof MembershipKeyImpl.Type6) { MembershipKeyImpl.Type6 key6 = (MembershipKeyImpl.Type6) key; n = Net.block6(fd, key6.groupAddress(), key6.index(), Net.inet6AsByteArray(source)); } else { MembershipKeyImpl.Type4 key4 = (MembershipKeyImpl.Type4) key; n = Net.block4(fd, key4.groupAddress(), key4.interfaceAddress(), Net.inet4AsInt(source)); } if (n == IOStatus.UNAVAILABLE) { // ancient kernel throw new UnsupportedOperationException(); } } }
public DatagramChannelImpl(SelectorProvider sp, FileDescriptor fd) throws IOException { super(sp); this.family = Net.isIPv6Available() ? StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; this.fd = fd; this.fdVal = IOUtil.fdVal(fd); this.state = ST_UNCONNECTED; this.localAddress = Net.localAddress(fd); }
public void bind(SocketAddress local) throws IOException { synchronized (readLock) { synchronized (writeLock) { synchronized (stateLock) { ensureOpenAndUnconnected(); if (localAddress != null) throw new AlreadyBoundException(); InetSocketAddress isa = Net.checkAddress(local); Net.bind(fd, isa.getAddress(), isa.getPort()); localAddress = Net.localAddress(fd); } } } }
public DatagramChannelImpl(SelectorProvider sp) throws IOException { super(sp); ResourceManager.beforeUdpCreate(); try { this.family = Net.isIPv6Available() ? StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; this.fd = Net.socket(family, false); this.fdVal = IOUtil.fdVal(fd); this.state = ST_UNCONNECTED; } catch (IOException ioe) { ResourceManager.afterUdpClose(); throw ioe; } }
public int send(ByteBuffer src, SocketAddress target) throws IOException { if (src == null) throw new NullPointerException(); synchronized (writeLock) { ensureOpen(); InetSocketAddress isa = Net.checkAddress(target); InetAddress ia = isa.getAddress(); if (ia == null) throw new IOException("Target address not resolved"); synchronized (stateLock) { if (!isConnected()) { if (target == null) throw new NullPointerException(); SecurityManager sm = System.getSecurityManager(); if (sm != null) { if (ia.isMulticastAddress()) { sm.checkMulticast(ia); } else { sm.checkConnect(ia.getHostAddress(), isa.getPort()); } } } else { // Connected case; Check address then write if (!target.equals(remoteAddress)) { throw new IllegalArgumentException("Connected address not equal to target address"); } return write(src); } } int n = 0; try { begin(); if (!isOpen()) return 0; writerThread = NativeThread.current(); do { n = send(fd, src, isa); } while ((n == IOStatus.INTERRUPTED) && isOpen()); synchronized (stateLock) { if (isOpen() && (localAddress == null)) { localAddress = Net.localAddress(fd); } } return IOStatus.normalize(n); } finally { writerThread = 0; end((n > 0) || (n == IOStatus.UNAVAILABLE)); assert IOStatus.check(n); } } }
@Override public DatagramChannel connect(SocketAddress sa) throws IOException { int localPort = 0; synchronized (readLock) { synchronized (writeLock) { synchronized (stateLock) { ensureOpenAndUnconnected(); InetSocketAddress isa = Net.checkAddress(sa); SecurityManager sm = System.getSecurityManager(); if (sm != null) sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort()); int n = Net.connect(family, fd, isa.getAddress(), isa.getPort()); if (n <= 0) throw new Error(); // Can't happen // Connection succeeded; disallow further invocation state = ST_CONNECTED; remoteAddress = isa; sender = isa; cachedSenderInetAddress = isa.getAddress(); cachedSenderPort = isa.getPort(); // set or refresh local address localAddress = Net.localAddress(fd); // flush any packets already received. boolean blocking = false; synchronized (blockingLock()) { try { blocking = isBlocking(); // remainder of each packet thrown away ByteBuffer tmpBuf = ByteBuffer.allocate(1); if (blocking) { configureBlocking(false); } do { tmpBuf.clear(); } while (receive(tmpBuf) != null); } finally { if (blocking) { configureBlocking(true); } } } } } } return this; }
private long read0(ByteBuffer[] bufs) throws IOException { if (bufs == null) throw new NullPointerException(); synchronized (readLock) { if (!ensureReadOpen()) return -1; long n = 0; try { begin(); synchronized (stateLock) { if (!isOpen()) return 0; readerThread = NativeThread.current(); } for (; ; ) { n = Net.read(fd, bufs); if ((n == IOStatus.INTERRUPTED) && isOpen()) continue; return IOStatus.normalize(n); } } finally { readerCleanup(); end(n > 0 || (n == IOStatus.UNAVAILABLE)); synchronized (stateLock) { if ((n <= 0) && (!isInputOpen)) return IOStatus.EOF; } assert IOStatus.check(n); } } }
public long write0(ByteBuffer[] bufs) throws IOException { if (bufs == null) throw new NullPointerException(); synchronized (writeLock) { ensureWriteOpen(); long n = 0; try { begin(); synchronized (stateLock) { if (!isOpen()) return 0; writerThread = NativeThread.current(); } for (; ; ) { n = Net.write(fd, bufs); if ((n == IOStatus.INTERRUPTED) && isOpen()) continue; return IOStatus.normalize(n); } } finally { writerCleanup(); end((n > 0) || (n == IOStatus.UNAVAILABLE)); synchronized (stateLock) { if ((n <= 0) && (!isOutputOpen)) throw new AsynchronousCloseException(); } assert IOStatus.check(n); } } }
public DatagramChannelImpl(SelectorProvider sp, ProtocolFamily family) throws IOException { super(sp); if ((family != StandardProtocolFamily.INET) && (family != StandardProtocolFamily.INET6)) { if (family == null) throw new NullPointerException("'family' is null"); else throw new UnsupportedOperationException("Protocol family not supported"); } if (family == StandardProtocolFamily.INET6) { if (!Net.isIPv6Available()) { throw new UnsupportedOperationException("IPv6 not available"); } } this.family = family; this.fd = Net.socket(family, false); this.fdVal = IOUtil.fdVal(fd); this.state = ST_UNCONNECTED; }
public boolean connect(SocketAddress sa) throws IOException { int trafficClass = 0; // ## Pick up from options int localPort = 0; synchronized (readLock) { synchronized (writeLock) { ensureOpenAndUnconnected(); InetSocketAddress isa = Net.checkAddress(sa); SecurityManager sm = System.getSecurityManager(); if (sm != null) sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort()); synchronized (blockingLock()) { int n = 0; try { try { begin(); synchronized (stateLock) { if (!isOpen()) { return false; } readerThread = NativeThread.current(); } for (; ; ) { InetAddress ia = isa.getAddress(); if (ia.isAnyLocalAddress()) ia = InetAddress.getLocalHost(); n = connectImpl(ia, isa.getPort(), trafficClass); if ((n == IOStatus.INTERRUPTED) && isOpen()) continue; break; } } finally { readerCleanup(); end((n > 0) || (n == IOStatus.UNAVAILABLE)); assert IOStatus.check(n); } } catch (IOException x) { // If an exception was thrown, close the channel after // invoking end() so as to avoid bogus // AsynchronousCloseExceptions close(); throw x; } synchronized (stateLock) { remoteAddress = isa; if (n > 0) { // Connection succeeded; disallow further // invocation state = ST_CONNECTED; return true; } // If nonblocking and no exception then connection // pending; disallow another invocation if (!isBlocking()) state = ST_PENDING; else assert false; } } return false; } } }
@Override public SocketAddress getLocalAddress() throws IOException { synchronized (stateLock) { if (!isOpen()) throw new ClosedChannelException(); // Perform security check before returning address return Net.getRevealedLocalAddress(localAddress); } }
@Override <A> Future<Void> implConnect( SocketAddress remote, A attachment, CompletionHandler<Void, ? super A> handler) { if (!isOpen()) { Throwable exc = new ClosedChannelException(); if (handler == null) return CompletedFuture.withFailure(exc); Invoker.invoke(this, handler, attachment, null, exc); return null; } InetSocketAddress isa = Net.checkAddress(remote); // permission check SecurityManager sm = System.getSecurityManager(); if (sm != null) sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort()); // check and update state // ConnectEx requires the socket to be bound to a local address IOException bindException = null; synchronized (stateLock) { if (state == ST_CONNECTED) throw new AlreadyConnectedException(); if (state == ST_PENDING) throw new ConnectionPendingException(); if (localAddress == null) { try { bind(new InetSocketAddress(0)); } catch (IOException x) { bindException = x; } } if (bindException == null) state = ST_PENDING; } // handle bind failure if (bindException != null) { try { close(); } catch (IOException ignore) { } if (handler == null) return CompletedFuture.withFailure(bindException); Invoker.invoke(this, handler, attachment, null, bindException); return null; } // setup task PendingFuture<Void, A> result = new PendingFuture<Void, A>(this, handler, attachment); ConnectTask task = new ConnectTask<A>(isa, result); result.setContext(task); // initiate I/O if (Iocp.supportsThreadAgnosticIo()) { task.run(); } else { Invoker.invokeOnThreadInThreadPool(this, task); } return result; }
@Override @SuppressWarnings("unchecked") public <T> T getOption(SocketOption<T> name) throws IOException { if (name == null) throw new NullPointerException(); if (!supportedOptions().contains(name)) throw new UnsupportedOperationException("'" + name + "' not supported"); synchronized (stateLock) { ensureOpen(); if (name == StandardSocketOptions.IP_TOS || name == StandardSocketOptions.IP_MULTICAST_TTL || name == StandardSocketOptions.IP_MULTICAST_LOOP) { return (T) Net.getSocketOption(fd, family, name); } if (name == StandardSocketOptions.IP_MULTICAST_IF) { if (family == StandardProtocolFamily.INET) { int address = Net.getInterface4(fd); if (address == 0) return null; // default interface InetAddress ia = Net.inet4FromInt(address); NetworkInterface ni = NetworkInterface.getByInetAddress(ia); if (ni == null) throw new IOException("Unable to map address to interface"); return (T) ni; } else { int index = Net.getInterface6(fd); if (index == 0) return null; // default interface NetworkInterface ni = NetworkInterface.getByIndex(index); if (ni == null) throw new IOException("Unable to map index to interface"); return (T) ni; } } if (name == StandardSocketOptions.SO_REUSEADDR && reuseAddressEmulated) { return (T) Boolean.valueOf(isReuseAddress); } // no special handling return (T) Net.getSocketOption(fd, Net.UNSPEC, name); } }
public SocketAddress localAddress() { synchronized (stateLock) { if (state == ST_CONNECTED && (localAddress == null || ((InetSocketAddress) localAddress).getAddress().isAnyLocalAddress())) { // Socket was not bound before connecting or // Socket was bound with an "anyLocalAddress" localAddress = Net.localAddress(fd); } return localAddress; } }
/** Unblock given source. */ void unblock(MembershipKeyImpl key, InetAddress source) { assert key.channel() == this; assert key.sourceAddress() == null; synchronized (stateLock) { if (!key.isValid()) throw new IllegalStateException("key is no longer valid"); try { if (key instanceof MembershipKeyImpl.Type6) { MembershipKeyImpl.Type6 key6 = (MembershipKeyImpl.Type6) key; Net.unblock6(fd, key6.groupAddress(), key6.index(), Net.inet6AsByteArray(source)); } else { MembershipKeyImpl.Type4 key4 = (MembershipKeyImpl.Type4) key; Net.unblock4(fd, key4.groupAddress(), key4.interfaceAddress(), Net.inet4AsInt(source)); } } catch (IOException ioe) { // should not happen throw new AssertionError(ioe); } } }
// package-private void drop(MembershipKeyImpl key) { assert key.channel() == this; synchronized (stateLock) { if (!key.isValid()) return; try { if (key instanceof MembershipKeyImpl.Type6) { MembershipKeyImpl.Type6 key6 = (MembershipKeyImpl.Type6) key; Net.drop6(fd, key6.groupAddress(), key6.index(), key6.source()); } else { MembershipKeyImpl.Type4 key4 = (MembershipKeyImpl.Type4) key; Net.drop4(fd, key4.groupAddress(), key4.interfaceAddress(), key4.source()); } } catch (IOException ioe) { // should not happen throw new AssertionError(ioe); } key.invalidate(); registry.remove(key); } }
@Override public <T> DatagramChannel setOption(SocketOption<T> name, T value) throws IOException { if (name == null) throw new NullPointerException(); if (!supportedOptions().contains(name)) throw new UnsupportedOperationException("'" + name + "' not supported"); synchronized (stateLock) { ensureOpen(); if (name == StandardSocketOptions.IP_TOS) { // IPv4 only; no-op for IPv6 if (family == StandardProtocolFamily.INET) { Net.setSocketOption(fd, family, name, value); } return this; } if (name == StandardSocketOptions.IP_MULTICAST_TTL || name == StandardSocketOptions.IP_MULTICAST_LOOP) { // options are protocol dependent Net.setSocketOption(fd, family, name, value); return this; } if (name == StandardSocketOptions.IP_MULTICAST_IF) { if (value == null) throw new IllegalArgumentException("Cannot set IP_MULTICAST_IF to 'null'"); NetworkInterface interf = (NetworkInterface) value; if (family == StandardProtocolFamily.INET6) { int index = interf.getIndex(); if (index == -1) throw new IOException("Network interface cannot be identified"); Net.setInterface6(fd, index); } else { // need IPv4 address to identify interface Inet4Address target = Net.anyInet4Address(interf); if (target == null) throw new IOException("Network interface not configured for IPv4"); int targetAddress = Net.inet4AsInt(target); Net.setInterface4(fd, targetAddress); } return this; } // remaining options don't need any special handling Net.setSocketOption(fd, Net.UNSPEC, name, value); return this; } }
public DatagramChannel disconnect() throws IOException { synchronized (readLock) { synchronized (writeLock) { synchronized (stateLock) { if (!isConnected() || !isOpen()) return this; InetSocketAddress isa = (InetSocketAddress) remoteAddress; SecurityManager sm = System.getSecurityManager(); if (sm != null) sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort()); disconnect0(fd); remoteAddress = null; state = ST_UNCONNECTED; // refresh local address localAddress = Net.localAddress(fd); } } } return this; }
// package-private int poll(int events, long timeout) throws IOException { assert Thread.holdsLock(blockingLock()) && !isBlocking(); synchronized (readLock) { int n = 0; try { begin(); synchronized (stateLock) { if (!isOpen()) return 0; readerThread = NativeThread.current(); } n = Net.poll(fd, events, timeout); } finally { readerThread = 0; end(n > 0); } return n; } }
/** Task to initiate a connection. */ @Override public void run() { long overlapped = 0L; Throwable exc = null; try { begin(); // synchronize on result to allow this thread handle the case // where the connection is established immediately. synchronized (result) { overlapped = ioCache.add(result); // initiate the connection int n = connect0( handle, Net.isIPv6Available(), remote.getAddress(), remote.getPort(), overlapped); if (n == IOStatus.UNAVAILABLE) { // connection is pending return; } // connection established immediately afterConnect(); result.setResult(null); } } catch (Throwable x) { if (overlapped != 0L) ioCache.remove(overlapped); exc = x; } finally { end(); } if (exc != null) { closeChannel(); result.setFailure(toIOException(exc)); } Invoker.invoke(result); }
public int read(ByteBuffer buf) throws IOException { if (buf == null) throw new NullPointerException(); synchronized (readLock) { if (!ensureReadOpen()) return -1; int n = 0; try { // Set up the interruption machinery; see // AbstractInterruptibleChannel for details // begin(); synchronized (stateLock) { if (!isOpen()) { // Either the current thread is already interrupted, so // begin() closed the channel, or another thread closed the // channel since we checked it a few bytecodes ago. In // either case the value returned here is irrelevant since // the invocation of end() in the finally block will throw // an appropriate exception. // return 0; } // Save this thread so that it can be signalled on those // platforms that require it // readerThread = NativeThread.current(); } // Between the previous test of isOpen() and the return of the // IOUtil.read invocation below, this channel might be closed // or this thread might be interrupted. We rely upon the // implicit synchronization point in the kernel read() call to // make sure that the right thing happens. In either case the // implCloseSelectableChannel method is ultimately invoked in // some other thread, so there are three possibilities: // // - implCloseSelectableChannel() invokes nd.preClose() // before this thread invokes read(), in which case the // read returns immediately with either EOF or an error, // the latter of which will cause an IOException to be // thrown. // // - implCloseSelectableChannel() invokes nd.preClose() after // this thread is blocked in read(). On some operating // systems (e.g., Solaris and Windows) this causes the read // to return immediately with either EOF or an error // indication. // // - implCloseSelectableChannel() invokes nd.preClose() after // this thread is blocked in read() but the operating // system (e.g., Linux) doesn't support preemptive close, // so implCloseSelectableChannel() proceeds to signal this // thread, thereby causing the read to return immediately // with IOStatus.INTERRUPTED. // // In all three cases the invocation of end() in the finally // clause will notice that the channel has been closed and // throw an appropriate exception (AsynchronousCloseException // or ClosedByInterruptException) if necessary. // // *There is A fourth possibility. implCloseSelectableChannel() // invokes nd.preClose(), signals reader/writer thred and quickly // moves on to nd.close() in kill(), which does a real close. // Then a third thread accepts a new connection, opens file or // whatever that causes the released "fd" to be recycled. All // above happens just between our last isOpen() check and the // next kernel read reached, with the recycled "fd". The solution // is to postpone the real kill() if there is a reader or/and // writer thread(s) over there "waiting", leave the cleanup/kill // to the reader or writer thread. (the preClose() still happens // so the connection gets cut off as usual). // // For socket channels there is the additional wrinkle that // asynchronous shutdown works much like asynchronous close, // except that the channel is shutdown rather than completely // closed. This is analogous to the first two cases above, // except that the shutdown operation plays the role of // nd.preClose(). for (; ; ) { n = Net.read(fd, buf); if ((n == IOStatus.INTERRUPTED) && isOpen()) { // The system call was interrupted but the channel // is still open, so retry continue; } return IOStatus.normalize(n); } } finally { readerCleanup(); // Clear reader thread // The end method, which is defined in our superclass // AbstractInterruptibleChannel, resets the interruption // machinery. If its argument is true then it returns // normally; otherwise it checks the interrupt and open state // of this channel and throws an appropriate exception if // necessary. // // So, if we actually managed to do any I/O in the above try // block then we pass true to the end method. We also pass // true if the channel was in non-blocking mode when the I/O // operation was initiated but no data could be transferred; // this prevents spurious exceptions from being thrown in the // rare event that a channel is closed or a thread is // interrupted at the exact moment that a non-blocking I/O // request is made. // end(n > 0 || (n == IOStatus.UNAVAILABLE)); // Extra case for socket channels: Asynchronous shutdown // synchronized (stateLock) { if ((n <= 0) && (!isInputOpen)) return IOStatus.EOF; } assert IOStatus.check(n); } } }
// Constructor for normal connecting sockets // SocketChannelImpl(SelectorProvider sp) throws IOException { super(sp); this.fd = Net.socket(true); this.state = ST_UNCONNECTED; }
/** Joins channel's socket to the given group/interface and optional source address. */ private MembershipKey innerJoin(InetAddress group, NetworkInterface interf, InetAddress source) throws IOException { if (!group.isMulticastAddress()) throw new IllegalArgumentException("Group not a multicast address"); // check multicast address is compatible with this socket if (group instanceof Inet4Address) { if (family == StandardProtocolFamily.INET6 && !Net.canIPv6SocketJoinIPv4Group()) throw new IllegalArgumentException("IPv6 socket cannot join IPv4 multicast group"); } else if (group instanceof Inet6Address) { if (family != StandardProtocolFamily.INET6) throw new IllegalArgumentException("Only IPv6 sockets can join IPv6 multicast group"); } else { throw new IllegalArgumentException("Address type not supported"); } // check source address if (source != null) { if (source.isAnyLocalAddress()) throw new IllegalArgumentException("Source address is a wildcard address"); if (source.isMulticastAddress()) throw new IllegalArgumentException("Source address is multicast address"); if (source.getClass() != group.getClass()) throw new IllegalArgumentException("Source address is different type to group"); } SecurityManager sm = System.getSecurityManager(); if (sm != null) sm.checkMulticast(group); synchronized (stateLock) { if (!isOpen()) throw new ClosedChannelException(); // check the registry to see if we are already a member of the group if (registry == null) { registry = new MembershipRegistry(); } else { // return existing membership key MembershipKey key = registry.checkMembership(group, interf, source); if (key != null) return key; } MembershipKeyImpl key; if ((family == StandardProtocolFamily.INET6) && ((group instanceof Inet6Address) || Net.canJoin6WithIPv4Group())) { int index = interf.getIndex(); if (index == -1) throw new IOException("Network interface cannot be identified"); // need multicast and source address as byte arrays byte[] groupAddress = Net.inet6AsByteArray(group); byte[] sourceAddress = (source == null) ? null : Net.inet6AsByteArray(source); // join the group int n = Net.join6(fd, groupAddress, index, sourceAddress); if (n == IOStatus.UNAVAILABLE) throw new UnsupportedOperationException(); key = new MembershipKeyImpl.Type6( this, group, interf, source, groupAddress, index, sourceAddress); } else { // need IPv4 address to identify interface Inet4Address target = Net.anyInet4Address(interf); if (target == null) throw new IOException("Network interface not configured for IPv4"); int groupAddress = Net.inet4AsInt(group); int targetAddress = Net.inet4AsInt(target); int sourceAddress = (source == null) ? 0 : Net.inet4AsInt(source); // join the group int n = Net.join4(fd, groupAddress, targetAddress, sourceAddress); if (n == IOStatus.UNAVAILABLE) throw new UnsupportedOperationException(); key = new MembershipKeyImpl.Type4( this, group, interf, source, groupAddress, targetAddress, sourceAddress); } registry.add(key); return key; } }