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+
26+package sun.nio.ch;
27+
28+import java.io.FileDescriptor;
29+import java.io.IOException;
30+import java.net.*;
31+import java.nio.channels.*;
32+import java.nio.channels.spi.*;
33+import java.util.*;
34+import sun.net.NetHooks;
35+
36+
37+/**
38+ * An implementation of ServerSocketChannels
39+ */
40+
41+class 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+}