151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
22c87ad3a45cecf9e344487cad1abfdebe79f2c7cNarayan Kamath * Copyright (C) 2014 The Android Open Source Project
3519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage sun.nio.ch;
2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.FileDescriptor;
3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.IOException;
315ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport java.net.DatagramSocket;
325ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport java.net.Inet4Address;
335ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport java.net.Inet6Address;
345ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport java.net.InetAddress;
355ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport java.net.InetSocketAddress;
365ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport java.net.NetworkInterface;
375ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport java.net.PortUnreachableException;
385ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport java.net.ProtocolFamily;
395ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport java.net.SocketAddress;
405ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport java.net.SocketOption;
415ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport java.net.StandardProtocolFamily;
425ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport java.net.StandardSocketOptions;
4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.nio.ByteBuffer;
445ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport java.nio.channels.AlreadyBoundException;
455ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport java.nio.channels.ClosedChannelException;
465ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport java.nio.channels.DatagramChannel;
475ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport java.nio.channels.MembershipKey;
485ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport java.nio.channels.NotYetConnectedException;
495ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport java.nio.channels.SelectionKey;
505ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport java.nio.channels.UnsupportedAddressTypeException;
515ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport java.nio.channels.spi.SelectorProvider;
525ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport java.util.Collections;
535ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport java.util.HashSet;
545ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport java.util.Set;
551d568d5e72820f7e487a49e3c57dee4f1e7f14bcNarayan Kamath
561d568d5e72820f7e487a49e3c57dee4f1e7f14bcNarayan Kamathimport dalvik.system.BlockGuard;
575ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport dalvik.system.CloseGuard;
58519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmeraimport sun.net.ExtendedOptionsImpl;
595ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmeraimport sun.net.ResourceManager;
6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**
6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * An implementation of DatagramChannels.
6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiclass DatagramChannelImpl
6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    extends DatagramChannel
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    implements SelChImpl
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski{
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Used to make native read and write calls
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static NativeDispatcher nd = new DatagramDispatcher();
7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Our file descriptor
74e409de23a3281073142ff137b609778d6c70a31cYi Kong    // Android-changed: Make the fd package visible so that we can expose it through DatagramSocketAdaptor.
75e409de23a3281073142ff137b609778d6c70a31cYi Kong    final FileDescriptor fd;
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // fd value needed for dev/poll. This value will remain valid
7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // even after the value in the file descriptor object has been set to -1
7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final int fdVal;
8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // The protocol family of the socket
8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final ProtocolFamily family;
8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // IDs of native threads doing reads and writes, for signalling
8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private volatile long readerThread = 0;
8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private volatile long writerThread = 0;
8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Cached InetAddress and port for unconnected DatagramChannels
8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // used by receive0
9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private InetAddress cachedSenderInetAddress;
9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private int cachedSenderPort;
9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Lock held by current reading or connecting thread
9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final Object readLock = new Object();
9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Lock held by current writing or connecting thread
9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final Object writeLock = new Object();
9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Lock held by any thread that modifies the state fields declared below
10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // DO NOT invoke a blocking I/O operation while holding this lock!
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final Object stateLock = new Object();
10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // -- The following fields are protected by stateLock
10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // State (does not necessarily increase monotonically)
10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final int ST_UNINITIALIZED = -1;
10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final int ST_UNCONNECTED = 0;
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final int ST_CONNECTED = 1;
10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final int ST_KILLED = 2;
11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private int state = ST_UNINITIALIZED;
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Binding
11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private InetSocketAddress localAddress;
11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private InetSocketAddress remoteAddress;
11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Our socket adaptor, if any
11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private DatagramSocket socket;
11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
119e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    // Multicast support
120e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private MembershipRegistry registry;
121e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // set true when socket is bound and SO_REUSEADDRESS is emulated
12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean reuseAddressEmulated;
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // set true/false when socket is already bound and SO_REUSEADDR is emulated
12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean isReuseAddress;
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // -- End of fields protected by stateLock
12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
1305ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera    // Android-changed: Add CloseGuard support.
1315ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera    private final CloseGuard guard = CloseGuard.get();
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public DatagramChannelImpl(SelectorProvider sp)
13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        super(sp);
13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ResourceManager.beforeUdpCreate();
13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.family = Net.isIPv6Available() ?
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.fd = Net.socket(family, false);
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.fdVal = IOUtil.fdVal(fd);
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.state = ST_UNCONNECTED;
1445ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera            // Android-changed: Add CloseGuard support.
1455ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera            // Net#socket will set |fd| if it succeeds.
1465ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera            if (fd != null && fd.valid()) {
1475ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera                guard.open("close");
1485ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera            }
14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (IOException ioe) {
15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ResourceManager.afterUdpClose();
15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw ioe;
15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public DatagramChannelImpl(SelectorProvider sp, ProtocolFamily family)
15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        super(sp);
15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if ((family != StandardProtocolFamily.INET) &&
16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            (family != StandardProtocolFamily.INET6))
16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        {
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (family == null)
16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new NullPointerException("'family' is null");
16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            else
16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new UnsupportedOperationException("Protocol family not supported");
16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (family == StandardProtocolFamily.INET6) {
16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!Net.isIPv6Available()) {
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new UnsupportedOperationException("IPv6 not available");
17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.family = family;
17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.fd = Net.socket(family, false);
17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.fdVal = IOUtil.fdVal(fd);
17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.state = ST_UNCONNECTED;
1765ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera        // Android-changed: Add CloseGuard support.
1775ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera        // Net#socket will set |fd| if it succeeds.
1785ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera        if (fd != null && fd.valid()) {
1795ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera            guard.open("close");
1805ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera        }
18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public DatagramChannelImpl(SelectorProvider sp, FileDescriptor fd)
18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        super(sp);
18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.family = Net.isIPv6Available() ?
18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.fd = fd;
19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.fdVal = IOUtil.fdVal(fd);
19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.state = ST_UNCONNECTED;
19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.localAddress = Net.localAddress(fd);
1935ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera        // Android-changed: Add CloseGuard support.
1945ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera        if (fd != null && fd.valid()) {
1955ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera            guard.open("close");
1965ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera        }
19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public DatagramSocket socket() {
20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized (stateLock) {
20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (socket == null)
20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                socket = DatagramSocketAdaptor.create(this);
20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return socket;
20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
207e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public SocketAddress getLocalAddress() throws IOException {
20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized (stateLock) {
21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!isOpen())
21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new ClosedChannelException();
212519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera            // Perform security check before returning address
21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return Net.getRevealedLocalAddress(localAddress);
21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    @Override
21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public SocketAddress getRemoteAddress() throws IOException {
21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized (stateLock) {
22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!isOpen())
22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new ClosedChannelException();
22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return remoteAddress;
22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    @Override
22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public <T> DatagramChannel setOption(SocketOption<T> name, T value)
22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (name == null)
23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NullPointerException();
23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!supportedOptions().contains(name))
23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new UnsupportedOperationException("'" + name + "' not supported");
23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized (stateLock) {
23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ensureOpen();
23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
238519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera            if (name == StandardSocketOptions.IP_TOS ||
239519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera                name == StandardSocketOptions.IP_MULTICAST_TTL ||
24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                name == StandardSocketOptions.IP_MULTICAST_LOOP)
24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            {
24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // options are protocol dependent
24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                Net.setSocketOption(fd, family, name, value);
24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return this;
24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (name == StandardSocketOptions.IP_MULTICAST_IF) {
24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (value == null)
24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new IllegalArgumentException("Cannot set IP_MULTICAST_IF to 'null'");
25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                NetworkInterface interf = (NetworkInterface)value;
25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (family == StandardProtocolFamily.INET6) {
25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int index = interf.getIndex();
25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (index == -1)
25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        throw new IOException("Network interface cannot be identified");
25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    Net.setInterface6(fd, index);
25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // need IPv4 address to identify interface
25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    Inet4Address target = Net.anyInet4Address(interf);
25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (target == null)
26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        throw new IOException("Network interface not configured for IPv4");
26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int targetAddress = Net.inet4AsInt(target);
26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    Net.setInterface4(fd, targetAddress);
26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return this;
26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (name == StandardSocketOptions.SO_REUSEADDR &&
26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    Net.useExclusiveBind() && localAddress != null)
26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            {
26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                reuseAddressEmulated = true;
27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                this.isReuseAddress = (Boolean)value;
27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // remaining options don't need any special handling
27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Net.setSocketOption(fd, Net.UNSPEC, name, value);
27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return this;
27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
279e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    @SuppressWarnings("unchecked")
28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public <T> T getOption(SocketOption<T> name)
28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (name == null)
28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NullPointerException();
28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!supportedOptions().contains(name))
28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new UnsupportedOperationException("'" + name + "' not supported");
28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized (stateLock) {
29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ensureOpen();
29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
292519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera            if (name == StandardSocketOptions.IP_TOS ||
293519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera                name == StandardSocketOptions.IP_MULTICAST_TTL ||
29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                name == StandardSocketOptions.IP_MULTICAST_LOOP)
29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            {
29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return (T) Net.getSocketOption(fd, family, name);
29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (name == StandardSocketOptions.IP_MULTICAST_IF) {
30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (family == StandardProtocolFamily.INET) {
30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int address = Net.getInterface4(fd);
30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (address == 0)
30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return null;    // default interface
30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    InetAddress ia = Net.inet4FromInt(address);
30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    NetworkInterface ni = NetworkInterface.getByInetAddress(ia);
30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (ni == null)
30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        throw new IOException("Unable to map address to interface");
30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return (T) ni;
31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int index = Net.getInterface6(fd);
31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (index == 0)
31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return null;    // default interface
31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    NetworkInterface ni = NetworkInterface.getByIndex(index);
31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (ni == null)
31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        throw new IOException("Unable to map index to interface");
31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return (T) ni;
31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (name == StandardSocketOptions.SO_REUSEADDR &&
32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    reuseAddressEmulated)
32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            {
32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return (T)Boolean.valueOf(isReuseAddress);
32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // no special handling
32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static class DefaultOptionsHolder {
33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        static final Set<SocketOption<?>> defaultOptions = defaultOptions();
33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private static Set<SocketOption<?>> defaultOptions() {
33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(8);
33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            set.add(StandardSocketOptions.SO_SNDBUF);
33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            set.add(StandardSocketOptions.SO_RCVBUF);
34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            set.add(StandardSocketOptions.SO_REUSEADDR);
34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            set.add(StandardSocketOptions.SO_BROADCAST);
34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            set.add(StandardSocketOptions.IP_TOS);
34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            set.add(StandardSocketOptions.IP_MULTICAST_IF);
34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            set.add(StandardSocketOptions.IP_MULTICAST_TTL);
34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            set.add(StandardSocketOptions.IP_MULTICAST_LOOP);
346e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            if (ExtendedOptionsImpl.flowSupported()) {
347e573e88e89daf5efb323719c54117c5a423eb245Yi Kong                set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA);
348e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            }
34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return Collections.unmodifiableSet(set);
35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
353e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public final Set<SocketOption<?>> supportedOptions() {
35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return DefaultOptionsHolder.defaultOptions;
35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void ensureOpen() throws ClosedChannelException {
35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!isOpen())
36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new ClosedChannelException();
36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private SocketAddress sender;       // Set by receive0 (## ugh)
36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public SocketAddress receive(ByteBuffer dst) throws IOException {
36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (dst.isReadOnly())
36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IllegalArgumentException("Read-only buffer");
36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (dst == null)
36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NullPointerException();
3706975f84c2ed72e1e26d20190b6f318718c849008Tobias Thierer        // Android-changed: Do not attempt to bind to 0 (or 0.0.0.0) if there hasn't been
371396f2361ba82cce530a4ff8aa9ac0780af8d4d56Narayan Kamath        // an explicit call to bind() yet. Fail fast and return null.
372396f2361ba82cce530a4ff8aa9ac0780af8d4d56Narayan Kamath        if (localAddress == null)
373396f2361ba82cce530a4ff8aa9ac0780af8d4d56Narayan Kamath            return null;
37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized (readLock) {
37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ensureOpen();
37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Socket was not bound before attempting receive
377396f2361ba82cce530a4ff8aa9ac0780af8d4d56Narayan Kamath            // if (localAddress() == null)
378396f2361ba82cce530a4ff8aa9ac0780af8d4d56Narayan Kamath            //     bind(null);
37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int n = 0;
38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ByteBuffer bb = null;
38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                begin();
38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!isOpen())
38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return null;
38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                SecurityManager security = System.getSecurityManager();
38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                readerThread = NativeThread.current();
38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (isConnected() || (security == null)) {
38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    do {
38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        n = receive(fd, dst);
39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    } while ((n == IOStatus.INTERRUPTED) && isOpen());
39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (n == IOStatus.UNAVAILABLE)
39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return null;
39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    bb = Util.getTemporaryDirectBuffer(dst.remaining());
39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    for (;;) {
39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        do {
39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            n = receive(fd, bb);
39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        } while ((n == IOStatus.INTERRUPTED) && isOpen());
39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (n == IOStatus.UNAVAILABLE)
40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            return null;
40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        InetSocketAddress isa = (InetSocketAddress)sender;
40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        try {
40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            security.checkAccept(
40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                isa.getAddress().getHostAddress(),
40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                isa.getPort());
40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        } catch (SecurityException se) {
40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            // Ignore packet
40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            bb.clear();
40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            n = 0;
41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            continue;
41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        bb.flip();
41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        dst.put(bb);
41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        break;
41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return sender;
41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } finally {
41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (bb != null)
42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    Util.releaseTemporaryDirectBuffer(bb);
42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                readerThread = 0;
42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                end((n > 0) || (n == IOStatus.UNAVAILABLE));
42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                assert IOStatus.check(n);
42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private int receive(FileDescriptor fd, ByteBuffer dst)
42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int pos = dst.position();
43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int lim = dst.limit();
43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        assert (pos <= lim);
43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int rem = (pos <= lim ? lim - pos : 0);
43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (dst instanceof DirectBuffer && rem > 0)
43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return receiveIntoNativeBuffer(fd, dst, rem, pos);
43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Substitute a native buffer. If the supplied buffer is empty
43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // we must instead use a nonempty buffer, otherwise the call
44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // will not block waiting for a datagram on some platforms.
44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int newSize = Math.max(rem, 1);
44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ByteBuffer bb = Util.getTemporaryDirectBuffer(newSize);
44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
4441d568d5e72820f7e487a49e3c57dee4f1e7f14bcNarayan Kamath            BlockGuard.getThreadPolicy().onNetwork();
4451d568d5e72820f7e487a49e3c57dee4f1e7f14bcNarayan Kamath
44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int n = receiveIntoNativeBuffer(fd, bb, newSize, 0);
44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            bb.flip();
44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (n > 0 && rem > 0)
44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                dst.put(bb);
45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return n;
45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } finally {
45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Util.releaseTemporaryDirectBuffer(bb);
45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private int receiveIntoNativeBuffer(FileDescriptor fd, ByteBuffer bb,
45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                        int rem, int pos)
45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int n = receive0(fd, ((DirectBuffer)bb).address() + pos, rem,
46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         isConnected());
46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (n > 0)
46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            bb.position(pos + n);
46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return n;
46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int send(ByteBuffer src, SocketAddress target)
46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
46951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (src == null)
47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NullPointerException();
47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
47351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized (writeLock) {
47451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ensureOpen();
47551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            InetSocketAddress isa = Net.checkAddress(target);
47651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            InetAddress ia = isa.getAddress();
47751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (ia == null)
47851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new IOException("Target address not resolved");
47951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            synchronized (stateLock) {
48051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!isConnected()) {
48151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (target == null)
48251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        throw new NullPointerException();
48351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    SecurityManager sm = System.getSecurityManager();
48451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (sm != null) {
48551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (ia.isMulticastAddress()) {
48651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            sm.checkMulticast(ia);
48751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        } else {
48851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            sm.checkConnect(ia.getHostAddress(),
48951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                            isa.getPort());
49051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
49151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
49251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else { // Connected case; Check address then write
49351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (!target.equals(remoteAddress)) {
49451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        throw new IllegalArgumentException(
49551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            "Connected address not equal to target address");
49651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
49751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return write(src);
49851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
49951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
50051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
50151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int n = 0;
50251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
50351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                begin();
50451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!isOpen())
50551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return 0;
50651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                writerThread = NativeThread.current();
5071d568d5e72820f7e487a49e3c57dee4f1e7f14bcNarayan Kamath                BlockGuard.getThreadPolicy().onNetwork();
5081d568d5e72820f7e487a49e3c57dee4f1e7f14bcNarayan Kamath
50951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                do {
51051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    n = send(fd, src, isa);
51151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } while ((n == IOStatus.INTERRUPTED) && isOpen());
51251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
51351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                synchronized (stateLock) {
51451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (isOpen() && (localAddress == null)) {
51551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        localAddress = Net.localAddress(fd);
51651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
51751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
51851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return IOStatus.normalize(n);
51951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } finally {
52051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                writerThread = 0;
52151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                end((n > 0) || (n == IOStatus.UNAVAILABLE));
52251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                assert IOStatus.check(n);
52351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
52451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
52551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
52651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
52751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private int send(FileDescriptor fd, ByteBuffer src, InetSocketAddress target)
52851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
52951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
53051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (src instanceof DirectBuffer)
53151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return sendFromNativeBuffer(fd, src, target);
53251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
53351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Substitute a native buffer
53451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int pos = src.position();
53551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int lim = src.limit();
53651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        assert (pos <= lim);
53751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int rem = (pos <= lim ? lim - pos : 0);
53851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
53951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);
54051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
54151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            bb.put(src);
54251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            bb.flip();
54351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Do not update src until we see how many bytes were written
54451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            src.position(pos);
54551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
54651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int n = sendFromNativeBuffer(fd, bb, target);
54751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (n > 0) {
54851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // now update src
54951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                src.position(pos + n);
55051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
55151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return n;
55251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } finally {
55351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Util.releaseTemporaryDirectBuffer(bb);
55451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
55551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
55651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
55751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private int sendFromNativeBuffer(FileDescriptor fd, ByteBuffer bb,
55851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                     InetSocketAddress target)
55951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
56051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
56151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int pos = bb.position();
56251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int lim = bb.limit();
56351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        assert (pos <= lim);
56451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int rem = (pos <= lim ? lim - pos : 0);
56551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
56651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean preferIPv6 = (family != StandardProtocolFamily.INET);
56751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int written;
56851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
56951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            written = send0(preferIPv6, fd, ((DirectBuffer)bb).address() + pos,
57051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            rem, target.getAddress(), target.getPort());
57151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (PortUnreachableException pue) {
57251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (isConnected())
57351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw pue;
57451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            written = rem;
57551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
57651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (written > 0)
57751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            bb.position(pos + written);
57851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return written;
57951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
58051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
58151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int read(ByteBuffer buf) throws IOException {
58251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (buf == null)
58351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NullPointerException();
58451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized (readLock) {
58551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            synchronized (stateLock) {
58651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                ensureOpen();
58751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!isConnected())
58851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new NotYetConnectedException();
58951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
59051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int n = 0;
59151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
59251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                begin();
59351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!isOpen())
59451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return 0;
59551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                readerThread = NativeThread.current();
59651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                do {
59751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    n = IOUtil.read(fd, buf, -1, nd);
59851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } while ((n == IOStatus.INTERRUPTED) && isOpen());
59951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return IOStatus.normalize(n);
60051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } finally {
60151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                readerThread = 0;
60251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                end((n > 0) || (n == IOStatus.UNAVAILABLE));
60351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                assert IOStatus.check(n);
60451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
60551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
60651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
60751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
60851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public long read(ByteBuffer[] dsts, int offset, int length)
60951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
61051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
61151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
61251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IndexOutOfBoundsException();
61351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized (readLock) {
61451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            synchronized (stateLock) {
61551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                ensureOpen();
61651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!isConnected())
61751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new NotYetConnectedException();
61851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
61951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            long n = 0;
62051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
62151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                begin();
62251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!isOpen())
62351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return 0;
62451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                readerThread = NativeThread.current();
62551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                do {
62651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    n = IOUtil.read(fd, dsts, offset, length, nd);
62751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } while ((n == IOStatus.INTERRUPTED) && isOpen());
62851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return IOStatus.normalize(n);
62951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } finally {
63051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                readerThread = 0;
63151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                end((n > 0) || (n == IOStatus.UNAVAILABLE));
63251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                assert IOStatus.check(n);
63351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
63451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
63551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
63651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
63751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int write(ByteBuffer buf) throws IOException {
63851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (buf == null)
63951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NullPointerException();
64051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized (writeLock) {
64151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            synchronized (stateLock) {
64251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                ensureOpen();
64351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!isConnected())
64451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new NotYetConnectedException();
64551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
64651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int n = 0;
64751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
64851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                begin();
64951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!isOpen())
65051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return 0;
65151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                writerThread = NativeThread.current();
65251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                do {
65351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    n = IOUtil.write(fd, buf, -1, nd);
65451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } while ((n == IOStatus.INTERRUPTED) && isOpen());
65551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return IOStatus.normalize(n);
65651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } finally {
65751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                writerThread = 0;
65851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                end((n > 0) || (n == IOStatus.UNAVAILABLE));
65951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                assert IOStatus.check(n);
66051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
66151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
66251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
66351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
66451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public long write(ByteBuffer[] srcs, int offset, int length)
66551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
66651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
66751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
66851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IndexOutOfBoundsException();
66951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized (writeLock) {
67051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            synchronized (stateLock) {
67151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                ensureOpen();
67251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!isConnected())
67351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new NotYetConnectedException();
67451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
67551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            long n = 0;
67651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
67751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                begin();
67851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!isOpen())
67951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return 0;
68051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                writerThread = NativeThread.current();
68151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                do {
68251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    n = IOUtil.write(fd, srcs, offset, length, nd);
68351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } while ((n == IOStatus.INTERRUPTED) && isOpen());
68451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return IOStatus.normalize(n);
68551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } finally {
68651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                writerThread = 0;
68751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                end((n > 0) || (n == IOStatus.UNAVAILABLE));
68851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                assert IOStatus.check(n);
68951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
69051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
69151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
69251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
69351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected void implConfigureBlocking(boolean block) throws IOException {
69451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        IOUtil.configureBlocking(fd, block);
69551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
69651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
69751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public SocketAddress localAddress() {
69851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized (stateLock) {
69951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return localAddress;
70051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
70151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
70251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
70351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public SocketAddress remoteAddress() {
70451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized (stateLock) {
70551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return remoteAddress;
70651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
70751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
70851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
70951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    @Override
71051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public DatagramChannel bind(SocketAddress local) throws IOException {
71151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized (readLock) {
71251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            synchronized (writeLock) {
71351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                synchronized (stateLock) {
71451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    ensureOpen();
71551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (localAddress != null)
71651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        throw new AlreadyBoundException();
71751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    InetSocketAddress isa;
71851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (local == null) {
71951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        // only Inet4Address allowed with IPv4 socket
72051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (family == StandardProtocolFamily.INET) {
72151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            isa = new InetSocketAddress(InetAddress.getByName("0.0.0.0"), 0);
72251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        } else {
72351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            isa = new InetSocketAddress(0);
72451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
72551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    } else {
72651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        isa = Net.checkAddress(local);
72751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
72851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        // only Inet4Address allowed with IPv4 socket
72951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (family == StandardProtocolFamily.INET) {
73051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            InetAddress addr = isa.getAddress();
73151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            if (!(addr instanceof Inet4Address))
73251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                throw new UnsupportedAddressTypeException();
73351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
73451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
73551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    SecurityManager sm = System.getSecurityManager();
73651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (sm != null) {
73751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        sm.checkListen(isa.getPort());
73851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
73951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    Net.bind(family, fd, isa.getAddress(), isa.getPort());
74051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    localAddress = Net.localAddress(fd);
74151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
74251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
74351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
74451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return this;
74551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
74651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
74751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean isConnected() {
74851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized (stateLock) {
74951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (state == ST_CONNECTED);
75051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
75151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
75251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
75351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    void ensureOpenAndUnconnected() throws IOException { // package-private
75451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized (stateLock) {
75551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!isOpen())
75651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new ClosedChannelException();
75751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (state != ST_UNCONNECTED)
75851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new IllegalStateException("Connect already invoked");
75951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
76051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
76151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
76251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    @Override
76351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public DatagramChannel connect(SocketAddress sa) throws IOException {
76451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int localPort = 0;
76551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
76651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized(readLock) {
76751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            synchronized(writeLock) {
76851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                synchronized (stateLock) {
76951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    ensureOpenAndUnconnected();
77051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    InetSocketAddress isa = Net.checkAddress(sa);
77151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    SecurityManager sm = System.getSecurityManager();
77251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (sm != null)
77351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        sm.checkConnect(isa.getAddress().getHostAddress(),
77451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                        isa.getPort());
77551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int n = Net.connect(family,
77651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                        fd,
77751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                        isa.getAddress(),
77851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                        isa.getPort());
77951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (n <= 0)
78051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        throw new Error();      // Can't happen
78151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
78251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // Connection succeeded; disallow further invocation
78351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    state = ST_CONNECTED;
78451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    remoteAddress = isa;
78551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    sender = isa;
78651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    cachedSenderInetAddress = isa.getAddress();
78751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    cachedSenderPort = isa.getPort();
78851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
78951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // set or refresh local address
79051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    localAddress = Net.localAddress(fd);
7916031a510d88327487d4a22bdfef0c6ba17a7b2a6Yi Kong
7926031a510d88327487d4a22bdfef0c6ba17a7b2a6Yi Kong                    // flush any packets already received.
7936031a510d88327487d4a22bdfef0c6ba17a7b2a6Yi Kong                    boolean blocking = false;
7946031a510d88327487d4a22bdfef0c6ba17a7b2a6Yi Kong                    synchronized (blockingLock()) {
7956031a510d88327487d4a22bdfef0c6ba17a7b2a6Yi Kong                        try {
7966031a510d88327487d4a22bdfef0c6ba17a7b2a6Yi Kong                            blocking = isBlocking();
7976031a510d88327487d4a22bdfef0c6ba17a7b2a6Yi Kong                            // remainder of each packet thrown away
7986031a510d88327487d4a22bdfef0c6ba17a7b2a6Yi Kong                            ByteBuffer tmpBuf = ByteBuffer.allocate(1);
7996031a510d88327487d4a22bdfef0c6ba17a7b2a6Yi Kong                            if (blocking) {
8006031a510d88327487d4a22bdfef0c6ba17a7b2a6Yi Kong                                configureBlocking(false);
8016031a510d88327487d4a22bdfef0c6ba17a7b2a6Yi Kong                            }
8026031a510d88327487d4a22bdfef0c6ba17a7b2a6Yi Kong                            do {
8036031a510d88327487d4a22bdfef0c6ba17a7b2a6Yi Kong                                tmpBuf.clear();
8048b9413f7171bd5193be546cd3a2bc9672bcf725dYi Kong                            } while (receive(tmpBuf) != null);
8056031a510d88327487d4a22bdfef0c6ba17a7b2a6Yi Kong                        } finally {
8066031a510d88327487d4a22bdfef0c6ba17a7b2a6Yi Kong                            if (blocking) {
8076031a510d88327487d4a22bdfef0c6ba17a7b2a6Yi Kong                                configureBlocking(true);
8086031a510d88327487d4a22bdfef0c6ba17a7b2a6Yi Kong                            }
8096031a510d88327487d4a22bdfef0c6ba17a7b2a6Yi Kong                        }
8106031a510d88327487d4a22bdfef0c6ba17a7b2a6Yi Kong                    }
81151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
81251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
81351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
81451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return this;
81551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
81651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
81751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public DatagramChannel disconnect() throws IOException {
81851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized(readLock) {
81951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            synchronized(writeLock) {
82051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                synchronized (stateLock) {
82151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (!isConnected() || !isOpen())
82251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return this;
82351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    InetSocketAddress isa = remoteAddress;
82451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    SecurityManager sm = System.getSecurityManager();
82551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (sm != null)
82651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        sm.checkConnect(isa.getAddress().getHostAddress(),
82751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                        isa.getPort());
82851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    boolean isIPv6 = (family == StandardProtocolFamily.INET6);
82951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    disconnect0(fd, isIPv6);
83051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    remoteAddress = null;
83151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    state = ST_UNCONNECTED;
83251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
83351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // refresh local address
83451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    localAddress = Net.localAddress(fd);
83551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
83651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
83751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
83851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return this;
83951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
84051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
841e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    /**
842e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     * Joins channel's socket to the given group/interface and
843e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     * optional source address.
844e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     */
845e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private MembershipKey innerJoin(InetAddress group,
846e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                    NetworkInterface interf,
847e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                    InetAddress source)
848e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        throws IOException
849e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    {
850e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (!group.isMulticastAddress())
851e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            throw new IllegalArgumentException("Group not a multicast address");
852e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
853e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        // check multicast address is compatible with this socket
854e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (group instanceof Inet4Address) {
855e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (family == StandardProtocolFamily.INET6 && !Net.canIPv6SocketJoinIPv4Group())
856e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                throw new IllegalArgumentException("IPv6 socket cannot join IPv4 multicast group");
857e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        } else if (group instanceof Inet6Address) {
858e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (family != StandardProtocolFamily.INET6)
859e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                throw new IllegalArgumentException("Only IPv6 sockets can join IPv6 multicast group");
860e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        } else {
861e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            throw new IllegalArgumentException("Address type not supported");
862e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
863e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
864e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        // check source address
865e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (source != null) {
866e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (source.isAnyLocalAddress())
867e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                throw new IllegalArgumentException("Source address is a wildcard address");
868e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (source.isMulticastAddress())
869e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                throw new IllegalArgumentException("Source address is multicast address");
870e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (source.getClass() != group.getClass())
871e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                throw new IllegalArgumentException("Source address is different type to group");
872e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
873e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
874e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        SecurityManager sm = System.getSecurityManager();
875e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (sm != null)
876e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            sm.checkMulticast(group);
877e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
878e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        synchronized (stateLock) {
879e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (!isOpen())
880e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                throw new ClosedChannelException();
881e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
882e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            // check the registry to see if we are already a member of the group
883e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (registry == null) {
884e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                registry = new MembershipRegistry();
885e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            } else {
886e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                // return existing membership key
887e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                MembershipKey key = registry.checkMembership(group, interf, source);
888e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                if (key != null)
889e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    return key;
890e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            }
891e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
892e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            MembershipKeyImpl key;
893e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if ((family == StandardProtocolFamily.INET6) &&
894e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                ((group instanceof Inet6Address) || Net.canJoin6WithIPv4Group()))
895e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            {
896e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                int index = interf.getIndex();
897e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                if (index == -1)
898e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    throw new IOException("Network interface cannot be identified");
899e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
900e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                // need multicast and source address as byte arrays
901e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                byte[] groupAddress = Net.inet6AsByteArray(group);
902e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                byte[] sourceAddress = (source == null) ? null :
903e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    Net.inet6AsByteArray(source);
904e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
905e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                // join the group
906e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                int n = Net.join6(fd, groupAddress, index, sourceAddress);
907e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                if (n == IOStatus.UNAVAILABLE)
908e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    throw new UnsupportedOperationException();
909e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
910e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                key = new MembershipKeyImpl.Type6(this, group, interf, source,
911e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                  groupAddress, index, sourceAddress);
912e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
913e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            } else {
914e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                // need IPv4 address to identify interface
915e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                Inet4Address target = Net.anyInet4Address(interf);
916e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                if (target == null)
917e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    throw new IOException("Network interface not configured for IPv4");
918e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
919e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                int groupAddress = Net.inet4AsInt(group);
920e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                int targetAddress = Net.inet4AsInt(target);
921e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                int sourceAddress = (source == null) ? 0 : Net.inet4AsInt(source);
922e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
923e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                // join the group
924e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                int n = Net.join4(fd, groupAddress, targetAddress, sourceAddress);
925e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                if (n == IOStatus.UNAVAILABLE)
926e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    throw new UnsupportedOperationException();
927e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
928e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                key = new MembershipKeyImpl.Type4(this, group, interf, source,
929e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                  groupAddress, targetAddress, sourceAddress);
930e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            }
931e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
932e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            registry.add(key);
933e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            return key;
934e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
935e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
936e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
937e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
938e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public MembershipKey join(InetAddress group,
939e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                              NetworkInterface interf)
940e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        throws IOException
941e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    {
942e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return innerJoin(group, interf, null);
943e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
944e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
945e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
946e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public MembershipKey join(InetAddress group,
947e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                              NetworkInterface interf,
948e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                              InetAddress source)
949e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        throws IOException
950e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    {
951e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (source == null)
952e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            throw new NullPointerException("source address is null");
953e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return innerJoin(group, interf, source);
954e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
955e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
956e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    // package-private
957e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    void drop(MembershipKeyImpl key) {
958e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        assert key.channel() == this;
959e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
960e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        synchronized (stateLock) {
961e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (!key.isValid())
962e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                return;
963e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
964e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            try {
965e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                if (key instanceof MembershipKeyImpl.Type6) {
966e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    MembershipKeyImpl.Type6 key6 =
967e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                        (MembershipKeyImpl.Type6)key;
968e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    Net.drop6(fd, key6.groupAddress(), key6.index(), key6.source());
969e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                } else {
970e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    MembershipKeyImpl.Type4 key4 = (MembershipKeyImpl.Type4)key;
971e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    Net.drop4(fd, key4.groupAddress(), key4.interfaceAddress(),
972e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                        key4.source());
973e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                }
974e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            } catch (IOException ioe) {
975e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                // should not happen
976e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                throw new AssertionError(ioe);
977e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            }
978e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
979e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            key.invalidate();
980e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            registry.remove(key);
981e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
982e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
983e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
984e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    /**
985e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     * Block datagrams from given source if a memory to receive all
986e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     * datagrams.
987e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     */
988e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    void block(MembershipKeyImpl key, InetAddress source)
989e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        throws IOException
990e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    {
991e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        assert key.channel() == this;
992e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        assert key.sourceAddress() == null;
993e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
994e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        synchronized (stateLock) {
995e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (!key.isValid())
996e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                throw new IllegalStateException("key is no longer valid");
997e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (source.isAnyLocalAddress())
998e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                throw new IllegalArgumentException("Source address is a wildcard address");
999e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (source.isMulticastAddress())
1000e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                throw new IllegalArgumentException("Source address is multicast address");
1001e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (source.getClass() != key.group().getClass())
1002e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                throw new IllegalArgumentException("Source address is different type to group");
1003e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
1004e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            int n;
1005e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (key instanceof MembershipKeyImpl.Type6) {
1006e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                 MembershipKeyImpl.Type6 key6 =
1007e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    (MembershipKeyImpl.Type6)key;
1008e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                n = Net.block6(fd, key6.groupAddress(), key6.index(),
1009e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                               Net.inet6AsByteArray(source));
1010e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            } else {
1011e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                MembershipKeyImpl.Type4 key4 =
1012e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    (MembershipKeyImpl.Type4)key;
1013e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                n = Net.block4(fd, key4.groupAddress(), key4.interfaceAddress(),
1014e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                               Net.inet4AsInt(source));
1015e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            }
1016e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (n == IOStatus.UNAVAILABLE) {
1017e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                // ancient kernel
1018e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                throw new UnsupportedOperationException();
1019e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            }
1020e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
1021e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
1022e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
1023e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    /**
1024e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     * Unblock given source.
1025e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     */
1026e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    void unblock(MembershipKeyImpl key, InetAddress source) {
1027e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        assert key.channel() == this;
1028e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        assert key.sourceAddress() == null;
1029e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
1030e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        synchronized (stateLock) {
1031e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (!key.isValid())
1032e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                throw new IllegalStateException("key is no longer valid");
1033e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
1034e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            try {
1035e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                if (key instanceof MembershipKeyImpl.Type6) {
1036e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    MembershipKeyImpl.Type6 key6 =
1037e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                        (MembershipKeyImpl.Type6)key;
1038e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    Net.unblock6(fd, key6.groupAddress(), key6.index(),
1039e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                 Net.inet6AsByteArray(source));
1040e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                } else {
1041e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    MembershipKeyImpl.Type4 key4 =
1042e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                        (MembershipKeyImpl.Type4)key;
1043e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    Net.unblock4(fd, key4.groupAddress(), key4.interfaceAddress(),
1044e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                 Net.inet4AsInt(source));
1045e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                }
1046e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            } catch (IOException ioe) {
1047e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                // should not happen
1048e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                throw new AssertionError(ioe);
1049e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            }
1050e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
1051e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
1052e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
105351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected void implCloseSelectableChannel() throws IOException {
105451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized (stateLock) {
10555ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera            // Android-changed: Add CloseGuard support.
10565ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera            guard.close();
105751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (state != ST_KILLED)
105851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                nd.preClose(fd);
105951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ResourceManager.afterUdpClose();
106051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
1061e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            // if member of mulitcast group then invalidate all keys
1062e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (registry != null)
1063e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                registry.invalidateAll();
1064e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
106551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            long th;
106651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if ((th = readerThread) != 0)
106751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                NativeThread.signal(th);
106851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if ((th = writerThread) != 0)
106951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                NativeThread.signal(th);
107051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!isRegistered())
107151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                kill();
107251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
107351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
107451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
107551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void kill() throws IOException {
107651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized (stateLock) {
107751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (state == ST_KILLED)
107851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return;
107951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (state == ST_UNINITIALIZED) {
108051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                state = ST_KILLED;
108151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return;
108251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
108351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            assert !isOpen() && !isRegistered();
108451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            nd.close(fd);
108551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            state = ST_KILLED;
108651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
108751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
108851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
10895ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera    protected void finalize() throws Throwable {
10905ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera        try {
1091ce821390b935d8005f1124002d839b2e0d88368aNarayan Kamath            // Android-changed: Add CloseGuard support.
1092ce821390b935d8005f1124002d839b2e0d88368aNarayan Kamath            if (guard != null) {
1093ce821390b935d8005f1124002d839b2e0d88368aNarayan Kamath                guard.warnIfOpen();
1094ce821390b935d8005f1124002d839b2e0d88368aNarayan Kamath            }
10955ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera            // fd is null if constructor threw exception
10965ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera            if (fd != null)
10975ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera                close();
10985ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera        } finally {
10995ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera            super.finalize();
11005ba24bd205f9c8ed2179a0a32859a529a795a4c3Shubham Ajmera        }
110151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
110251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
110351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
110451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Translates native poll revent set into a ready operation set
110551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
110651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean translateReadyOps(int ops, int initialOps,
110751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                     SelectionKeyImpl sk) {
110851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int intOps = sk.nioInterestOps(); // Do this just once, it synchronizes
110951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int oldOps = sk.nioReadyOps();
111051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int newOps = initialOps;
111151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
1112519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera        if ((ops & Net.POLLNVAL) != 0) {
111351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // This should only happen if this channel is pre-closed while a
111451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // selection operation is in progress
111551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // ## Throw an error if this channel has not been pre-closed
111651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
111751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
111851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
1119519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera        if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
112051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            newOps = intOps;
112151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            sk.nioReadyOps(newOps);
112251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (newOps & ~oldOps) != 0;
112351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
112451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
1125519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera        if (((ops & Net.POLLIN) != 0) &&
112651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ((intOps & SelectionKey.OP_READ) != 0))
112751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            newOps |= SelectionKey.OP_READ;
112851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
1129519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera        if (((ops & Net.POLLOUT) != 0) &&
113051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ((intOps & SelectionKey.OP_WRITE) != 0))
113151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            newOps |= SelectionKey.OP_WRITE;
113251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
113351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        sk.nioReadyOps(newOps);
113451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (newOps & ~oldOps) != 0;
113551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
113651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
113751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) {
113851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return translateReadyOps(ops, sk.nioReadyOps(), sk);
113951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
114051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
114151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) {
114251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return translateReadyOps(ops, 0, sk);
114351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
114451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
1145519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera    // package-private
1146519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera    int poll(int events, long timeout) throws IOException {
1147519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera        assert Thread.holdsLock(blockingLock()) && !isBlocking();
1148519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera
1149519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera        synchronized (readLock) {
1150519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera            int n = 0;
1151519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera            try {
1152519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera                begin();
1153519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera                synchronized (stateLock) {
1154519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera                    if (!isOpen())
1155519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera                        return 0;
1156519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera                    readerThread = NativeThread.current();
1157519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera                }
1158519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera                n = Net.poll(fd, events, timeout);
1159519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera            } finally {
1160519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera                readerThread = 0;
1161519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera                end(n > 0);
1162519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera            }
1163519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera            return n;
1164519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera        }
1165519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera    }
1166519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera
116751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
116851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Translates an interest operation set into a native poll event set
116951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
117051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
117151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int newOps = 0;
117251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
117351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if ((ops & SelectionKey.OP_READ) != 0)
1174519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera            newOps |= Net.POLLIN;
117551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if ((ops & SelectionKey.OP_WRITE) != 0)
1176519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera            newOps |= Net.POLLOUT;
117751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if ((ops & SelectionKey.OP_CONNECT) != 0)
1178519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera            newOps |= Net.POLLIN;
117951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        sk.selector.putEventOps(sk, newOps);
118051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
118151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
118251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public FileDescriptor getFD() {
118351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return fd;
118451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
118551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
118651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int getFDVal() {
118751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return fdVal;
118851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
118951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
119051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
119151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // -- Native methods --
119251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
119351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static native void initIDs();
119451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
119551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static native void disconnect0(FileDescriptor fd, boolean isIPv6)
119651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException;
119751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
119851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private native int receive0(FileDescriptor fd, long address, int len,
119951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                boolean connected)
120051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException;
120151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
120251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private native int send0(boolean preferIPv6, FileDescriptor fd, long address,
120351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                             int len, InetAddress addr, int port)
120451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException;
120551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
120651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static {
120751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        initIDs();
120851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
120951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
121051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
1211