jdk/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java
author alanb
Sun, 31 Aug 2008 18:39:01 +0100
changeset 1152 29d6145d1097
parent 2 90ce3da70b43
child 1247 b4c26443dee5
permissions -rw-r--r--
4640544: New I/O: Complete socket-channel functionality Reviewed-by: iris, sherman, chegar
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
     2
 * Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
90ce3da70b43 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Sun designates this
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
90ce3da70b43 Initial load
duke
parents:
diff changeset
     9
 * by Sun in the LICENSE file that accompanied this code.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    21
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    22
 * CA 95054 USA or visit www.sun.com if you need additional information or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    23
 * have any questions.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package sun.nio.ch;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import java.io.FileDescriptor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import java.io.IOException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import java.lang.reflect.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.net.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
import java.nio.channels.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
import java.nio.channels.spi.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
import java.security.AccessController;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
import java.security.PrivilegedAction;
1152
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
    36
import java.util.*;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
 * An implementation of ServerSocketChannels
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
class ServerSocketChannelImpl
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
    extends ServerSocketChannel
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
    implements SelChImpl
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
    // Used to make native close and configure calls
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
    private static NativeDispatcher nd;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
    // Our file descriptor
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
    private final FileDescriptor fd;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
    // fd value needed for dev/poll. This value will remain valid
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
    // even after the value in the file descriptor object has been set to -1
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
    private int fdVal;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
    // ID of native thread currently blocked in this channel, for signalling
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
    private volatile long thread = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
    // Lock held by thread currently blocked in this channel
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
    private final Object lock = new Object();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
    // Lock held by any thread that modifies the state fields declared below
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
    // DO NOT invoke a blocking I/O operation while holding this lock!
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
    private final Object stateLock = new Object();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
    // -- The following fields are protected by stateLock
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
    // Channel state, increases monotonically
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
    private static final int ST_UNINITIALIZED = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
    private static final int ST_INUSE = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
    private static final int ST_KILLED = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
    private int state = ST_UNINITIALIZED;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
    // Binding
1152
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
    77
    private SocketAddress localAddress; // null => unbound
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
    // Our socket adaptor, if any
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
    ServerSocket socket;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
    // -- End of fields protected by stateLock
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
    public ServerSocketChannelImpl(SelectorProvider sp) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
        super(sp);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
        this.fd =  Net.serverSocket(true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
        this.fdVal = IOUtil.fdVal(fd);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
        this.state = ST_INUSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
    public ServerSocketChannelImpl(SelectorProvider sp, FileDescriptor fd)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
        throws IOException
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
        super(sp);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
        this.fd =  fd;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
        this.fdVal = IOUtil.fdVal(fd);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
        this.state = ST_INUSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
        localAddress = Net.localAddress(fd);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
    public ServerSocket socket() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
        synchronized (stateLock) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
            if (socket == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
                socket = ServerSocketAdaptor.create(this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
            return socket;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
1152
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   110
    @Override
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   111
    public SocketAddress getLocalAddress() throws IOException {
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   112
        synchronized (stateLock) {
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   113
            if (!isOpen())
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   114
                return null;
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   115
            return localAddress;
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   116
        }
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   117
    }
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   118
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   119
    @Override
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   120
    public ServerSocketChannel setOption(SocketOption name, Object value)
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   121
        throws IOException
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   122
    {
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   123
        if (name == null)
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   124
            throw new NullPointerException();
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   125
        if (!options().contains(name))
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   126
            throw new IllegalArgumentException("invalid option name");
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   127
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   128
        synchronized (stateLock) {
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   129
            if (!isOpen())
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   130
                throw new ClosedChannelException();
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   131
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   132
            // no options that require special handling
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   133
            Net.setSocketOption(fd, Net.UNSPEC, name, value);
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   134
            return this;
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   135
        }
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   136
    }
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   137
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   138
    @Override
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   139
    @SuppressWarnings("unchecked")
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   140
    public <T> T getOption(SocketOption<T> name)
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   141
        throws IOException
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   142
    {
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   143
        if (name == null)
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   144
            throw new NullPointerException();
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   145
        if (!options().contains(name))
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   146
            throw new IllegalArgumentException("invalid option name");
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   147
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   148
        synchronized (stateLock) {
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   149
            if (!isOpen())
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   150
                throw new ClosedChannelException();
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   151
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   152
            // no options that require special handling
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   153
            return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   154
        }
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   155
    }
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   156
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   157
    private static class LazyInitialization {
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   158
        static final Set<SocketOption<?>> defaultOptions = defaultOptions();
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   159
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   160
        private static Set<SocketOption<?>> defaultOptions() {
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   161
            HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(2);
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   162
            set.add(StandardSocketOption.SO_RCVBUF);
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   163
            set.add(StandardSocketOption.SO_REUSEADDR);
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   164
            return Collections.unmodifiableSet(set);
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   165
        }
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   166
    }
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   167
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   168
    @Override
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   169
    public final Set<SocketOption<?>> options() {
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   170
        return LazyInitialization.defaultOptions;
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   171
    }
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   172
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
    public boolean isBound() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
        synchronized (stateLock) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
            return localAddress != null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
    public SocketAddress localAddress() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
        synchronized (stateLock) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
            return localAddress;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
1152
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   185
    @Override
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   186
    public ServerSocketChannel bind(SocketAddress local, int backlog) throws IOException {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
        synchronized (lock) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
            if (!isOpen())
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
                throw new ClosedChannelException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
            if (isBound())
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
                throw new AlreadyBoundException();
1152
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   192
            InetSocketAddress isa = (local == null) ? new InetSocketAddress(0) :
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   193
                Net.checkAddress(local);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
            SecurityManager sm = System.getSecurityManager();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
            if (sm != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
                sm.checkListen(isa.getPort());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
            Net.bind(fd, isa.getAddress(), isa.getPort());
1152
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   198
            Net.listen(fd, backlog < 1 ? 50 : backlog);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
            synchronized (stateLock) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
                localAddress = Net.localAddress(fd);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
        }
1152
29d6145d1097 4640544: New I/O: Complete socket-channel functionality
alanb
parents: 2
diff changeset
   203
        return this;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
    public SocketChannel accept() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
        synchronized (lock) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
            if (!isOpen())
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
                throw new ClosedChannelException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
            if (!isBound())
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
                throw new NotYetBoundException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
            SocketChannel sc = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
            int n = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
            FileDescriptor newfd = new FileDescriptor();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
            InetSocketAddress[] isaa = new InetSocketAddress[1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
                begin();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
                if (!isOpen())
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
                    return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
                thread = NativeThread.current();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
                for (;;) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
                    n = accept0(this.fd, newfd, isaa);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
                    if ((n == IOStatus.INTERRUPTED) && isOpen())
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
                        continue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
            } finally {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
                thread = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
                end(n > 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
                assert IOStatus.check(n);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
            if (n < 1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
                return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
            IOUtil.configureBlocking(newfd, true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
            InetSocketAddress isa = isaa[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
            sc = new SocketChannelImpl(provider(), newfd, isa);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
            SecurityManager sm = System.getSecurityManager();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
            if (sm != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
                try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
                    sm.checkAccept(isa.getAddress().getHostAddress(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
                                   isa.getPort());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
                } catch (SecurityException x) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
                    sc.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
                    throw x;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
            return sc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
    protected void implConfigureBlocking(boolean block) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
        IOUtil.configureBlocking(fd, block);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
    protected void implCloseSelectableChannel() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
        synchronized (stateLock) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
            nd.preClose(fd);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
            long th = thread;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
            if (th != 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
                NativeThread.signal(th);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
            if (!isRegistered())
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
                kill();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
    public void kill() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
        synchronized (stateLock) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
            if (state == ST_KILLED)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
            if (state == ST_UNINITIALIZED) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
                state = ST_KILLED;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
            assert !isOpen() && !isRegistered();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
            nd.close(fd);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
            state = ST_KILLED;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
     * Translates native poll revent set into a ready operation set
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
    public boolean translateReadyOps(int ops, int initialOps,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
                                     SelectionKeyImpl sk) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
        int intOps = sk.nioInterestOps(); // Do this just once, it synchronizes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
        int oldOps = sk.nioReadyOps();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
        int newOps = initialOps;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
        if ((ops & PollArrayWrapper.POLLNVAL) != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
            // This should only happen if this channel is pre-closed while a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
            // selection operation is in progress
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
            // ## Throw an error if this channel has not been pre-closed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
        if ((ops & (PollArrayWrapper.POLLERR
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
                    | PollArrayWrapper.POLLHUP)) != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
            newOps = intOps;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
            sk.nioReadyOps(newOps);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
            return (newOps & ~oldOps) != 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
        if (((ops & PollArrayWrapper.POLLIN) != 0) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
            ((intOps & SelectionKey.OP_ACCEPT) != 0))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
                newOps |= SelectionKey.OP_ACCEPT;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
        sk.nioReadyOps(newOps);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
        return (newOps & ~oldOps) != 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
    public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
        return translateReadyOps(ops, sk.nioReadyOps(), sk);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
    public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
        return translateReadyOps(ops, 0, sk);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
     * Translates an interest operation set into a native poll event set
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
    public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
        int newOps = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
        // Translate ops
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
        if ((ops & SelectionKey.OP_ACCEPT) != 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
            newOps |= PollArrayWrapper.POLLIN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
        // Place ops into pollfd array
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
        sk.selector.putEventOps(sk, newOps);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
    public FileDescriptor getFD() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
        return fd;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
    public int getFDVal() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
        return fdVal;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
    public String toString() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
        StringBuffer sb = new StringBuffer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
        sb.append(this.getClass().getName());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
        sb.append('[');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
        if (!isOpen())
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
            sb.append("closed");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
        else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
            synchronized (stateLock) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
                if (localAddress() == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
                    sb.append("unbound");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
                    sb.append(localAddress().toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
        sb.append(']');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
        return sb.toString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
    // -- Native methods --
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
    // Accepts a new connection, setting the given file descriptor to refer to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
    // the new socket and setting isaa[0] to the socket's remote address.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
    // Returns 1 on success, or IOStatus.UNAVAILABLE (if non-blocking and no
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
    // connections are pending) or IOStatus.INTERRUPTED.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
    //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
    private native int accept0(FileDescriptor ssfd, FileDescriptor newfd,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
                               InetSocketAddress[] isaa)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
        throws IOException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
    private static native void initIDs();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
    static {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
        Util.load();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
        initIDs();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
        nd = new SocketDispatcher();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
}