1e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera/*
2519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
3e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera *
5e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * This code is free software; you can redistribute it and/or modify it
6e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * under the terms of the GNU General Public License version 2 only, as
7e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * published by the Free Software Foundation.  Oracle designates this
8e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * particular file as subject to the "Classpath" exception as provided
9e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * by Oracle in the LICENSE file that accompanied this code.
10e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera *
11e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * This code is distributed in the hope that it will be useful, but WITHOUT
12e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * version 2 for more details (a copy is included in the LICENSE file that
15e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * accompanied this code).
16e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera *
17e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * You should have received a copy of the GNU General Public License version
18e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * 2 along with this work; if not, write to the Free Software Foundation,
19e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera *
21e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * or visit www.oracle.com if you need additional information or have any
23e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * questions.
24e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera */
25e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
26e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmerapackage sun.nio.ch;
27e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
28e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmeraimport java.nio.ByteBuffer;
29e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmeraimport java.nio.channels.*;
30e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmeraimport java.net.SocketOption;
31e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmeraimport java.net.StandardSocketOptions;
32e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmeraimport java.net.SocketAddress;
33e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmeraimport java.net.InetSocketAddress;
34e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmeraimport java.io.IOException;
35e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmeraimport java.io.FileDescriptor;
36e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmeraimport java.util.Set;
37e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmeraimport java.util.HashSet;
38e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmeraimport java.util.Collections;
39e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmeraimport java.util.concurrent.*;
40e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmeraimport java.util.concurrent.locks.*;
41e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmeraimport sun.net.NetHooks;
42e573e88e89daf5efb323719c54117c5a423eb245Yi Kongimport sun.net.ExtendedOptionsImpl;
43e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
44e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera/**
45e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * Base implementation of AsynchronousSocketChannel
46e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera */
47e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
48e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmeraabstract class AsynchronousSocketChannelImpl
49e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    extends AsynchronousSocketChannel
50e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    implements Cancellable, Groupable
51e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera{
52e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    protected final FileDescriptor fd;
53e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
54e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    // protects state, localAddress, and remoteAddress
55e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    protected final Object stateLock = new Object();
56e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
57e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    protected volatile InetSocketAddress localAddress = null;
58e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    protected volatile InetSocketAddress remoteAddress = null;
59e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
60e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    // State, increases monotonically
61e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    static final int ST_UNINITIALIZED = -1;
62e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    static final int ST_UNCONNECTED = 0;
63e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    static final int ST_PENDING = 1;
64e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    static final int ST_CONNECTED = 2;
65e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    protected volatile int state = ST_UNINITIALIZED;
66e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
67e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    // reading state
68e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private final Object readLock = new Object();
69e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private boolean reading;
70e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private boolean readShutdown;
71e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private boolean readKilled;     // further reading disallowed due to timeout
72e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
73e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    // writing state
74e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private final Object writeLock = new Object();
75e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private boolean writing;
76e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private boolean writeShutdown;
77e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private boolean writeKilled;    // further writing disallowed due to timeout
78e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
79e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    // close support
80e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private final ReadWriteLock closeLock = new ReentrantReadWriteLock();
81e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private volatile boolean open = true;
82e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
83e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    // set true when exclusive binding is on and SO_REUSEADDR is emulated
84e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private boolean isReuseAddress;
85e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
86e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    AsynchronousSocketChannelImpl(AsynchronousChannelGroupImpl group)
87e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        throws IOException
88e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    {
89e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        super(group.provider());
90e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        this.fd = Net.socket(true);
91e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        this.state = ST_UNCONNECTED;
92e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
93e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
94e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    // Constructor for sockets obtained from AsynchronousServerSocketChannelImpl
95e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    AsynchronousSocketChannelImpl(AsynchronousChannelGroupImpl group,
96e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                  FileDescriptor fd,
97e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                  InetSocketAddress remote)
98e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        throws IOException
99e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    {
100e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        super(group.provider());
101e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        this.fd = fd;
102e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        this.state = ST_CONNECTED;
103e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        this.localAddress = Net.localAddress(fd);
104e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        this.remoteAddress = remote;
105e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
106e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
107e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
108e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public final boolean isOpen() {
109e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return open;
110e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
111e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
112e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    /**
113e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     * Marks beginning of access to file descriptor/handle
114e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     */
115e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    final void begin() throws IOException {
116e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        closeLock.readLock().lock();
117e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (!isOpen())
118e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            throw new ClosedChannelException();
119e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
120e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
121e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    /**
122e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     * Marks end of access to file descriptor/handle
123e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     */
124e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    final void end() {
125e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        closeLock.readLock().unlock();
126e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
127e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
128e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    /**
129e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     * Invoked to close socket and release other resources.
130e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     */
131e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    abstract void implClose() throws IOException;
132e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
133e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
134e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public final void close() throws IOException {
135e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        // synchronize with any threads initiating asynchronous operations
136e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        closeLock.writeLock().lock();
137e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        try {
138e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (!open)
139e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                return;     // already closed
140e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            open = false;
141e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        } finally {
142e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            closeLock.writeLock().unlock();
143e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
144e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        implClose();
145e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
146e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
147e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    final void enableReading(boolean killed) {
148e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        synchronized (readLock) {
149e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            reading = false;
150e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (killed)
151e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                readKilled = true;
152e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
153e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
154e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
155e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    final void enableReading() {
156e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        enableReading(false);
157e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
158e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
159e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    final void enableWriting(boolean killed) {
160e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        synchronized (writeLock) {
161e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            writing = false;
162e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (killed)
163e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                writeKilled = true;
164e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
165e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
166e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
167e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    final void enableWriting() {
168e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        enableWriting(false);
169e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
170e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
171e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    final void killReading() {
172e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        synchronized (readLock) {
173e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            readKilled = true;
174e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
175e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
176e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
177e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    final void killWriting() {
178e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        synchronized (writeLock) {
179e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            writeKilled = true;
180e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
181e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
182e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
183e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    final void killConnect() {
184e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        // when a connect is cancelled then the connection may have been
185e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        // established so prevent reading or writing.
186e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        killReading();
187e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        killWriting();
188e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
189e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
190e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    /**
191e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     * Invoked by connect to initiate the connect operation.
192e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     */
193e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    abstract <A> Future<Void> implConnect(SocketAddress remote,
194e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                          A attachment,
195e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                          CompletionHandler<Void,? super A> handler);
196e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
197e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
198e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public final Future<Void> connect(SocketAddress remote) {
199e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return implConnect(remote, null, null);
200e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
201e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
202e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
203e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public final <A> void connect(SocketAddress remote,
204e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                  A attachment,
205e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                  CompletionHandler<Void,? super A> handler)
206e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    {
207e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (handler == null)
208e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            throw new NullPointerException("'handler' is null");
209e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        implConnect(remote, attachment, handler);
210e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
211e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
212e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    /**
213e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     * Invoked by read to initiate the I/O operation.
214e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     */
215e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    abstract <V extends Number,A> Future<V> implRead(boolean isScatteringRead,
216e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                     ByteBuffer dst,
217e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                     ByteBuffer[] dsts,
218e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                     long timeout,
219e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                     TimeUnit unit,
220e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                     A attachment,
221e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                     CompletionHandler<V,? super A> handler);
222e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
223e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @SuppressWarnings("unchecked")
224e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private <V extends Number,A> Future<V> read(boolean isScatteringRead,
225e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                ByteBuffer dst,
226e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                ByteBuffer[] dsts,
227e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                long timeout,
228e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                TimeUnit unit,
229e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                A att,
230e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                CompletionHandler<V,? super A> handler)
231e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    {
232e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (!isOpen()) {
233e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            Throwable e = new ClosedChannelException();
234e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (handler == null)
235e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                return CompletedFuture.withFailure(e);
236e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            Invoker.invoke(this, handler, att, null, e);
237e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            return null;
238e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
239e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
240e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (remoteAddress == null)
241e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            throw new NotYetConnectedException();
242e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
243e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        boolean hasSpaceToRead = isScatteringRead || dst.hasRemaining();
244e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        boolean shutdown = false;
245e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
246e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        // check and update state
247e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        synchronized (readLock) {
248e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (readKilled)
249e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                throw new IllegalStateException("Reading not allowed due to timeout or cancellation");
250e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (reading)
251e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                throw new ReadPendingException();
252e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (readShutdown) {
253e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                shutdown = true;
254e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            } else {
255e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                if (hasSpaceToRead) {
256e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    reading = true;
257e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                }
258e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            }
259e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
260e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
261e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        // immediately complete with -1 if shutdown for read
262e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        // immediately complete with 0 if no space remaining
263e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (shutdown || !hasSpaceToRead) {
264e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            Number result;
265e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (isScatteringRead) {
266e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                result = (shutdown) ? Long.valueOf(-1L) : Long.valueOf(0L);
267e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            } else {
268e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                result = (shutdown) ? -1 : 0;
269e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            }
270e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (handler == null)
271e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                return CompletedFuture.withResult((V)result);
272e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            Invoker.invoke(this, handler, att, (V)result, null);
273e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            return null;
274e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
275e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
276e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return implRead(isScatteringRead, dst, dsts, timeout, unit, att, handler);
277e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
278e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
279e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
280e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public final Future<Integer> read(ByteBuffer dst) {
281e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (dst.isReadOnly())
282e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            throw new IllegalArgumentException("Read-only buffer");
283e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return read(false, dst, null, 0L, TimeUnit.MILLISECONDS, null, null);
284e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
285e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
286e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
287e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public final <A> void read(ByteBuffer dst,
288e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                               long timeout,
289e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                               TimeUnit unit,
290e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                               A attachment,
291e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                               CompletionHandler<Integer,? super A> handler)
292e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    {
293e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (handler == null)
294e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            throw new NullPointerException("'handler' is null");
295e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (dst.isReadOnly())
296e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            throw new IllegalArgumentException("Read-only buffer");
297e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        read(false, dst, null, timeout, unit, attachment, handler);
298e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
299e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
300e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
301e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public final <A> void read(ByteBuffer[] dsts,
302e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                               int offset,
303e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                               int length,
304e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                               long timeout,
305e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                               TimeUnit unit,
306e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                               A attachment,
307e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                               CompletionHandler<Long,? super A> handler)
308e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    {
309e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (handler == null)
310e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            throw new NullPointerException("'handler' is null");
311e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
312e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            throw new IndexOutOfBoundsException();
313e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        ByteBuffer[] bufs = Util.subsequence(dsts, offset, length);
314e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        for (int i=0; i<bufs.length; i++) {
315e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (bufs[i].isReadOnly())
316e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                throw new IllegalArgumentException("Read-only buffer");
317e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
318e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        read(true, null, bufs, timeout, unit, attachment, handler);
319e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
320e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
321e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    /**
322e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     * Invoked by write to initiate the I/O operation.
323e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     */
324e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    abstract <V extends Number,A> Future<V> implWrite(boolean isGatheringWrite,
325e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                      ByteBuffer src,
326e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                      ByteBuffer[] srcs,
327e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                      long timeout,
328e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                      TimeUnit unit,
329e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                      A attachment,
330e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                      CompletionHandler<V,? super A> handler);
331e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
332e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @SuppressWarnings("unchecked")
333e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private <V extends Number,A> Future<V> write(boolean isGatheringWrite,
334e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                 ByteBuffer src,
335e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                 ByteBuffer[] srcs,
336e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                 long timeout,
337e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                 TimeUnit unit,
338e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                 A att,
339e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                                 CompletionHandler<V,? super A> handler)
340e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    {
341e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        boolean hasDataToWrite = isGatheringWrite || src.hasRemaining();
342e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
343e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        boolean closed = false;
344e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (isOpen()) {
345e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (remoteAddress == null)
346e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                throw new NotYetConnectedException();
347e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            // check and update state
348e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            synchronized (writeLock) {
349e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                if (writeKilled)
350e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    throw new IllegalStateException("Writing not allowed due to timeout or cancellation");
351e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                if (writing)
352e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    throw new WritePendingException();
353e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                if (writeShutdown) {
354e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    closed = true;
355e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                } else {
356e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    if (hasDataToWrite)
357e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                        writing = true;
358e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                }
359e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            }
360e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        } else {
361e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            closed = true;
362e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
363e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
364e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        // channel is closed or shutdown for write
365e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (closed) {
366e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            Throwable e = new ClosedChannelException();
367e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (handler == null)
368e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                return CompletedFuture.withFailure(e);
369e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            Invoker.invoke(this, handler, att, null, e);
370e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            return null;
371e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
372e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
373e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        // nothing to write so complete immediately
374e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (!hasDataToWrite) {
375e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            Number result = (isGatheringWrite) ? (Number)0L : (Number)0;
376e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (handler == null)
377e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                return CompletedFuture.withResult((V)result);
378e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            Invoker.invoke(this, handler, att, (V)result, null);
379e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            return null;
380e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
381e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
382e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return implWrite(isGatheringWrite, src, srcs, timeout, unit, att, handler);
383e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
384e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
385e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
386e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public final Future<Integer> write(ByteBuffer src) {
387e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return write(false, src, null, 0L, TimeUnit.MILLISECONDS, null, null);
388e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
389e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
390e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
391e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public final <A> void write(ByteBuffer src,
392e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                long timeout,
393e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                TimeUnit unit,
394e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                A attachment,
395e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                CompletionHandler<Integer,? super A> handler)
396e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    {
397e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (handler == null)
398e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            throw new NullPointerException("'handler' is null");
399e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        write(false, src, null, timeout, unit, attachment, handler);
400e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
401e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
402e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
403e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public final <A> void  write(ByteBuffer[] srcs,
404e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                 int offset,
405e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                 int length,
406e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                 long timeout,
407e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                 TimeUnit unit,
408e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                 A attachment,
409e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                                 CompletionHandler<Long,? super A> handler)
410e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    {
411e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (handler == null)
412e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            throw new NullPointerException("'handler' is null");
413e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
414e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            throw new IndexOutOfBoundsException();
415e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        srcs = Util.subsequence(srcs, offset, length);
416e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        write(true, null, srcs, timeout, unit, attachment, handler);
417e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
418e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
419e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
420e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public final AsynchronousSocketChannel bind(SocketAddress local)
421e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        throws IOException
422e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    {
423e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        try {
424e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            begin();
425e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            synchronized (stateLock) {
426e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                if (state == ST_PENDING)
427e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    throw new ConnectionPendingException();
428e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                if (localAddress != null)
429e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    throw new AlreadyBoundException();
430e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                InetSocketAddress isa = (local == null) ?
431e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    new InetSocketAddress(0) : Net.checkAddress(local);
432519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera                SecurityManager sm = System.getSecurityManager();
433519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera                if (sm != null) {
434519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera                    sm.checkListen(isa.getPort());
435519adb2f61bb2bfa6cc993b1ca15cf7022b96697Shubham Ajmera                }
436e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
437e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                Net.bind(fd, isa.getAddress(), isa.getPort());
438e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                localAddress = Net.localAddress(fd);
439e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            }
440e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        } finally {
441e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            end();
442e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
443e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return this;
444e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
445e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
446e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
447e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public final SocketAddress getLocalAddress() throws IOException {
448e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (!isOpen())
449e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            throw new ClosedChannelException();
450e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera         return Net.getRevealedLocalAddress(localAddress);
451e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
452e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
453e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
454e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public final <T> AsynchronousSocketChannel setOption(SocketOption<T> name, T value)
455e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        throws IOException
456e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    {
457e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (name == null)
458e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            throw new NullPointerException();
459e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (!supportedOptions().contains(name))
460e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            throw new UnsupportedOperationException("'" + name + "' not supported");
461e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
462e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        try {
463e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            begin();
464e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (writeShutdown)
465e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                throw new IOException("Connection has been shutdown for writing");
466e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (name == StandardSocketOptions.SO_REUSEADDR &&
467e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    Net.useExclusiveBind())
468e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            {
469e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                // SO_REUSEADDR emulated when using exclusive bind
470e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                isReuseAddress = (Boolean)value;
471e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            } else {
472e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                Net.setSocketOption(fd, Net.UNSPEC, name, value);
473e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            }
474e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            return this;
475e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        } finally {
476e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            end();
477e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
478e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
479e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
480e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
481e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @SuppressWarnings("unchecked")
482e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public final <T> T getOption(SocketOption<T> name) throws IOException {
483e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (name == null)
484e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            throw new NullPointerException();
485e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (!supportedOptions().contains(name))
486e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            throw new UnsupportedOperationException("'" + name + "' not supported");
487e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
488e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        try {
489e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            begin();
490e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (name == StandardSocketOptions.SO_REUSEADDR &&
491e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    Net.useExclusiveBind())
492e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            {
493e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                // SO_REUSEADDR emulated when using exclusive bind
494e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                return (T)Boolean.valueOf(isReuseAddress);
495e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            }
496e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
497e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        } finally {
498e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            end();
499e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
500e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
501e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
502e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private static class DefaultOptionsHolder {
503e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        static final Set<SocketOption<?>> defaultOptions = defaultOptions();
504e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
505e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        private static Set<SocketOption<?>> defaultOptions() {
506e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(5);
507e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            set.add(StandardSocketOptions.SO_SNDBUF);
508e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            set.add(StandardSocketOptions.SO_RCVBUF);
509e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            set.add(StandardSocketOptions.SO_KEEPALIVE);
510e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            set.add(StandardSocketOptions.SO_REUSEADDR);
511e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            set.add(StandardSocketOptions.TCP_NODELAY);
512e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            if (ExtendedOptionsImpl.flowSupported()) {
513e573e88e89daf5efb323719c54117c5a423eb245Yi Kong                set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA);
514e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            }
515e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            return Collections.unmodifiableSet(set);
516e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
517e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
518e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
519e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
520e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public final Set<SocketOption<?>> supportedOptions() {
521e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return DefaultOptionsHolder.defaultOptions;
522e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
523e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
524e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
525e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public final SocketAddress getRemoteAddress() throws IOException {
526e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (!isOpen())
527e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            throw new ClosedChannelException();
528e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return remoteAddress;
529e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
530e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
531e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
532e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public final AsynchronousSocketChannel shutdownInput() throws IOException {
533e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        try {
534e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            begin();
535e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (remoteAddress == null)
536e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                throw new NotYetConnectedException();
537e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            synchronized (readLock) {
538e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                if (!readShutdown) {
539e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    Net.shutdown(fd, Net.SHUT_RD);
540e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    readShutdown = true;
541e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                }
542e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            }
543e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        } finally {
544e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            end();
545e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
546e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return this;
547e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
548e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
549e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
550e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public final AsynchronousSocketChannel shutdownOutput() throws IOException {
551e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        try {
552e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            begin();
553e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (remoteAddress == null)
554e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                throw new NotYetConnectedException();
555e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            synchronized (writeLock) {
556e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                if (!writeShutdown) {
557e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    Net.shutdown(fd, Net.SHUT_WR);
558e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    writeShutdown = true;
559e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                }
560e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            }
561e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        } finally {
562e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            end();
563e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
564e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return this;
565e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
566e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
567e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
568e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public final String toString() {
569e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        StringBuilder sb = new StringBuilder();
570e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        sb.append(this.getClass().getName());
571e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        sb.append('[');
572e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        synchronized (stateLock) {
573e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (!isOpen()) {
574e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                sb.append("closed");
575e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            } else {
576e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                switch (state) {
577e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                case ST_UNCONNECTED:
578e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    sb.append("unconnected");
579e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    break;
580e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                case ST_PENDING:
581e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    sb.append("connection-pending");
582e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    break;
583e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                case ST_CONNECTED:
584e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    sb.append("connected");
585e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    if (readShutdown)
586e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                        sb.append(" ishut");
587e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    if (writeShutdown)
588e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                        sb.append(" oshut");
589e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    break;
590e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                }
591e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                if (localAddress != null) {
592e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    sb.append(" local=");
593e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    sb.append(
594e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                            Net.getRevealedLocalAddressAsString(localAddress));
595e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                }
596e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                if (remoteAddress != null) {
597e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    sb.append(" remote=");
598e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    sb.append(remoteAddress.toString());
599e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                }
600e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            }
601e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
602e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        sb.append(']');
603e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return sb.toString();
604e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
605e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera}
606