History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/nio/ch/ServerSocketChannelImpl.java (1 of 18352 files). Show all

Unified · Split

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