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/java/net/AbstractPlainSocketImpl.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/net/AbstractPlainSocketImpl.java+716−0
@@ -0,0 +1,716 @@
1+/*
2+ * Copyright (c) 1995, 2011, 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 java.net;
27+
28+import java.io.IOException;
29+import java.io.InputStream;
30+import java.io.OutputStream;
31+import java.io.FileDescriptor;
32+
33+import sun.net.ConnectionResetException;
34+import sun.net.NetHooks;
35+import sun.net.ResourceManager;
36+
37+/**
38+ * Default Socket Implementation. This implementation does
39+ * not implement any security checks.
40+ * Note this class should <b>NOT</b> be public.
41+ *
42+ * @author Steven B. Byrne
43+ */
44+abstract class AbstractPlainSocketImpl extends SocketImpl
45+{
46+ /* instance variable for SO_TIMEOUT */
47+ int timeout; // timeout in millisec
48+ // traffic class
49+ private int trafficClass;
50+
51+ private boolean shut_rd = false;
52+ private boolean shut_wr = false;
53+
54+ private SocketInputStream socketInputStream = null;
55+
56+ /* number of threads using the FileDescriptor */
57+ protected int fdUseCount = 0;
58+
59+ /* lock when increment/decrementing fdUseCount */
60+ protected final Object fdLock = new Object();
61+
62+ /* indicates a close is pending on the file descriptor */
63+ protected boolean closePending = false;
64+
65+ /* indicates connection reset state */
66+ private int CONNECTION_NOT_RESET = 0;
67+ private int CONNECTION_RESET_PENDING = 1;
68+ private int CONNECTION_RESET = 2;
69+ private int resetState;
70+ private final Object resetLock = new Object();
71+
72+ /* whether this Socket is a stream (TCP) socket or not (UDP)
73+ */
74+ private boolean stream;
75+
76+ /**
77+ * Load net library into runtime.
78+ */
79+ static {
80+ java.security.AccessController.doPrivileged(
81+ new sun.security.action.LoadLibraryAction("net"));
82+ }
83+
84+ /**
85+ * Creates a socket with a boolean that specifies whether this
86+ * is a stream socket (true) or an unconnected UDP socket (false).
87+ */
88+ protected synchronized void create(boolean stream) throws IOException {
89+ fd = new FileDescriptor();
90+ this.stream = stream;
91+ if (!stream) {
92+ ResourceManager.beforeUdpCreate();
93+ try {
94+ socketCreate(false);
95+ } catch (IOException ioe) {
96+ ResourceManager.afterUdpClose();
97+ fd = null;
98+ throw ioe;
99+ }
100+ } else {
101+ socketCreate(true);
102+ }
103+ if (socket != null)
104+ socket.setCreated();
105+ if (serverSocket != null)
106+ serverSocket.setCreated();
107+ }
108+
109+ /**
110+ * Creates a socket and connects it to the specified port on
111+ * the specified host.
112+ * @param host the specified host
113+ * @param port the specified port
114+ */
115+ protected void connect(String host, int port)
116+ throws UnknownHostException, IOException
117+ {
118+ boolean connected = false;
119+ try {
120+ InetAddress address = InetAddress.getByName(host);
121+ this.port = port;
122+ this.address = address;
123+
124+ connectToAddress(address, port, timeout);
125+ connected = true;
126+ } finally {
127+ if (!connected) {
128+ try {
129+ close();
130+ } catch (IOException ioe) {
131+ /* Do nothing. If connect threw an exception then
132+ it will be passed up the call stack */
133+ }
134+ }
135+ }
136+ }
137+
138+ /**
139+ * Creates a socket and connects it to the specified address on
140+ * the specified port.
141+ * @param address the address
142+ * @param port the specified port
143+ */
144+ protected void connect(InetAddress address, int port) throws IOException {
145+ this.port = port;
146+ this.address = address;
147+
148+ try {
149+ connectToAddress(address, port, timeout);
150+ return;
151+ } catch (IOException e) {
152+ // everything failed
153+ close();
154+ throw e;
155+ }
156+ }
157+
158+ /**
159+ * Creates a socket and connects it to the specified address on
160+ * the specified port.
161+ * @param address the address
162+ * @param timeout the timeout value in milliseconds, or zero for no timeout.
163+ * @throws IOException if connection fails
164+ * @throws IllegalArgumentException if address is null or is a
165+ * SocketAddress subclass not supported by this socket
166+ * @since 1.4
167+ */
168+ protected void connect(SocketAddress address, int timeout)
169+ throws IOException {
170+ boolean connected = false;
171+ try {
172+ if (address == null || !(address instanceof InetSocketAddress))
173+ throw new IllegalArgumentException("unsupported address type");
174+ InetSocketAddress addr = (InetSocketAddress) address;
175+ if (addr.isUnresolved())
176+ throw new UnknownHostException(addr.getHostName());
177+ this.port = addr.getPort();
178+ this.address = addr.getAddress();
179+
180+ connectToAddress(this.address, port, timeout);
181+ connected = true;
182+ } finally {
183+ if (!connected) {
184+ try {
185+ close();
186+ } catch (IOException ioe) {
187+ /* Do nothing. If connect threw an exception then
188+ it will be passed up the call stack */
189+ }
190+ }
191+ }
192+ }
193+
194+ private void connectToAddress(InetAddress address, int port, int timeout) throws IOException {
195+ if (address.isAnyLocalAddress()) {
196+ doConnect(InetAddress.getLocalHost(), port, timeout);
197+ } else {
198+ doConnect(address, port, timeout);
199+ }
200+ }
201+
202+ public void setOption(int opt, Object val) throws SocketException {
203+ if (isClosedOrPending()) {
204+ throw new SocketException("Socket Closed");
205+ }
206+ boolean on = true;
207+ switch (opt) {
208+ /* check type safety b4 going native. These should never
209+ * fail, since only java.Socket* has access to
210+ * PlainSocketImpl.setOption().
211+ */
212+ case SO_LINGER:
213+ if (val == null || (!(val instanceof Integer) && !(val instanceof Boolean)))
214+ throw new SocketException("Bad parameter for option");
215+ if (val instanceof Boolean) {
216+ /* true only if disabling - enabling should be Integer */
217+ on = false;
218+ }
219+ break;
220+ case SO_TIMEOUT:
221+ if (val == null || (!(val instanceof Integer)))
222+ throw new SocketException("Bad parameter for SO_TIMEOUT");
223+ int tmp = ((Integer) val).intValue();
224+ if (tmp < 0)
225+ throw new IllegalArgumentException("timeout < 0");
226+ timeout = tmp;
227+ break;
228+ case IP_TOS:
229+ if (val == null || !(val instanceof Integer)) {
230+ throw new SocketException("bad argument for IP_TOS");
231+ }
232+ trafficClass = ((Integer)val).intValue();
233+ break;
234+ case SO_BINDADDR:
235+ throw new SocketException("Cannot re-bind socket");
236+ case TCP_NODELAY:
237+ if (val == null || !(val instanceof Boolean))
238+ throw new SocketException("bad parameter for TCP_NODELAY");
239+ on = ((Boolean)val).booleanValue();
240+ break;
241+ case SO_SNDBUF:
242+ case SO_RCVBUF:
243+ if (val == null || !(val instanceof Integer) ||
244+ !(((Integer)val).intValue() > 0)) {
245+ throw new SocketException("bad parameter for SO_SNDBUF " +
246+ "or SO_RCVBUF");
247+ }
248+ break;
249+ case SO_KEEPALIVE:
250+ if (val == null || !(val instanceof Boolean))
251+ throw new SocketException("bad parameter for SO_KEEPALIVE");
252+ on = ((Boolean)val).booleanValue();
253+ break;
254+ case SO_OOBINLINE:
255+ if (val == null || !(val instanceof Boolean))
256+ throw new SocketException("bad parameter for SO_OOBINLINE");
257+ on = ((Boolean)val).booleanValue();
258+ break;
259+ case SO_REUSEADDR:
260+ if (val == null || !(val instanceof Boolean))
261+ throw new SocketException("bad parameter for SO_REUSEADDR");
262+ on = ((Boolean)val).booleanValue();
263+ break;
264+ default:
265+ throw new SocketException("unrecognized TCP option: " + opt);
266+ }
267+ socketSetOption(opt, on, val);
268+ }
269+ public Object getOption(int opt) throws SocketException {
270+ if (isClosedOrPending()) {
271+ throw new SocketException("Socket Closed");
272+ }
273+ if (opt == SO_TIMEOUT) {
274+ return new Integer(timeout);
275+ }
276+ int ret = 0;
277+ /*
278+ * The native socketGetOption() knows about 3 options.
279+ * The 32 bit value it returns will be interpreted according
280+ * to what we're asking. A return of -1 means it understands
281+ * the option but its turned off. It will raise a SocketException
282+ * if "opt" isn't one it understands.
283+ */
284+
285+ switch (opt) {
286+ case TCP_NODELAY:
287+ ret = socketGetOption(opt, null);
288+ return Boolean.valueOf(ret != -1);
289+ case SO_OOBINLINE:
290+ ret = socketGetOption(opt, null);
291+ return Boolean.valueOf(ret != -1);
292+ case SO_LINGER:
293+ ret = socketGetOption(opt, null);
294+ return (ret == -1) ? Boolean.FALSE: (Object)(new Integer(ret));
295+ case SO_REUSEADDR:
296+ ret = socketGetOption(opt, null);
297+ return Boolean.valueOf(ret != -1);
298+ case SO_BINDADDR:
299+ InetAddressContainer in = new InetAddressContainer();
300+ ret = socketGetOption(opt, in);
301+ return in.addr;
302+ case SO_SNDBUF:
303+ case SO_RCVBUF:
304+ ret = socketGetOption(opt, null);
305+ return new Integer(ret);
306+ case IP_TOS:
307+ ret = socketGetOption(opt, null);
308+ if (ret == -1) { // ipv6 tos
309+ return new Integer(trafficClass);
310+ } else {
311+ return new Integer(ret);
312+ }
313+ case SO_KEEPALIVE:
314+ ret = socketGetOption(opt, null);
315+ return Boolean.valueOf(ret != -1);
316+ // should never get here
317+ default:
318+ return null;
319+ }
320+ }
321+
322+ /**
323+ * The workhorse of the connection operation. Tries several times to
324+ * establish a connection to the given <host, port>. If unsuccessful,
325+ * throws an IOException indicating what went wrong.
326+ */
327+
328+ synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException {
329+ synchronized (fdLock) {
330+ if (!closePending && (socket == null || !socket.isBound())) {
331+ NetHooks.beforeTcpConnect(fd, address, port);
332+ }
333+ }
334+ try {
335+ acquireFD();
336+ try {
337+ socketConnect(address, port, timeout);
338+ /* socket may have been closed during poll/select */
339+ synchronized (fdLock) {
340+ if (closePending) {
341+ throw new SocketException ("Socket closed");
342+ }
343+ }
344+ // If we have a ref. to the Socket, then sets the flags
345+ // created, bound & connected to true.
346+ // This is normally done in Socket.connect() but some
347+ // subclasses of Socket may call impl.connect() directly!
348+ if (socket != null) {
349+ socket.setBound();
350+ socket.setConnected();
351+ }
352+ } finally {
353+ releaseFD();
354+ }
355+ } catch (IOException e) {
356+ close();
357+ throw e;
358+ }
359+ }
360+
361+ /**
362+ * Binds the socket to the specified address of the specified local port.
363+ * @param address the address
364+ * @param port the port
365+ */
366+ protected synchronized void bind(InetAddress address, int lport)
367+ throws IOException
368+ {
369+ synchronized (fdLock) {
370+ if (!closePending && (socket == null || !socket.isBound())) {
371+ NetHooks.beforeTcpBind(fd, address, lport);
372+ }
373+ }
374+ socketBind(address, lport);
375+ if (socket != null)
376+ socket.setBound();
377+ if (serverSocket != null)
378+ serverSocket.setBound();
379+ }
380+
381+ /**
382+ * Listens, for a specified amount of time, for connections.
383+ * @param count the amount of time to listen for connections
384+ */
385+ protected synchronized void listen(int count) throws IOException {
386+ socketListen(count);
387+ }
388+
389+ /**
390+ * Accepts connections.
391+ * @param s the connection
392+ */
393+ protected void accept(SocketImpl s) throws IOException {
394+ acquireFD();
395+ try {
396+ socketAccept(s);
397+ } finally {
398+ releaseFD();
399+ }
400+ }
401+
402+ /**
403+ * Gets an InputStream for this socket.
404+ */
405+ protected synchronized InputStream getInputStream() throws IOException {
406+ if (isClosedOrPending()) {
407+ throw new IOException("Socket Closed");
408+ }
409+ if (shut_rd) {
410+ throw new IOException("Socket input is shutdown");
411+ }
412+ if (socketInputStream == null) {
413+ socketInputStream = new SocketInputStream(this);
414+ }
415+ return socketInputStream;
416+ }
417+
418+ void setInputStream(SocketInputStream in) {
419+ socketInputStream = in;
420+ }
421+
422+ /**
423+ * Gets an OutputStream for this socket.
424+ */
425+ protected synchronized OutputStream getOutputStream() throws IOException {
426+ if (isClosedOrPending()) {
427+ throw new IOException("Socket Closed");
428+ }
429+ if (shut_wr) {
430+ throw new IOException("Socket output is shutdown");
431+ }
432+ return new SocketOutputStream(this);
433+ }
434+
435+ void setFileDescriptor(FileDescriptor fd) {
436+ this.fd = fd;
437+ }
438+
439+ void setAddress(InetAddress address) {
440+ this.address = address;
441+ }
442+
443+ void setPort(int port) {
444+ this.port = port;
445+ }
446+
447+ void setLocalPort(int localport) {
448+ this.localport = localport;
449+ }
450+
451+ /**
452+ * Returns the number of bytes that can be read without blocking.
453+ */
454+ protected synchronized int available() throws IOException {
455+ if (isClosedOrPending()) {
456+ throw new IOException("Stream closed.");
457+ }
458+
459+ /*
460+ * If connection has been reset then return 0 to indicate
461+ * there are no buffered bytes.
462+ */
463+ if (isConnectionReset()) {
464+ return 0;
465+ }
466+
467+ /*
468+ * If no bytes available and we were previously notified
469+ * of a connection reset then we move to the reset state.
470+ *
471+ * If are notified of a connection reset then check
472+ * again if there are bytes buffered on the socket.
473+ */
474+ int n = 0;
475+ try {
476+ n = socketAvailable();
477+ if (n == 0 && isConnectionResetPending()) {
478+ setConnectionReset();
479+ }
480+ } catch (ConnectionResetException exc1) {
481+ setConnectionResetPending();
482+ try {
483+ n = socketAvailable();
484+ if (n == 0) {
485+ setConnectionReset();
486+ }
487+ } catch (ConnectionResetException exc2) {
488+ }
489+ }
490+ return n;
491+ }
492+
493+ /**
494+ * Closes the socket.
495+ */
496+ protected void close() throws IOException {
497+ synchronized(fdLock) {
498+ if (fd != null) {
499+ if (!stream) {
500+ ResourceManager.afterUdpClose();
501+ }
502+ if (fdUseCount == 0) {
503+ if (closePending) {
504+ return;
505+ }
506+ closePending = true;
507+ /*
508+ * We close the FileDescriptor in two-steps - first the
509+ * "pre-close" which closes the socket but doesn't
510+ * release the underlying file descriptor. This operation
511+ * may be lengthy due to untransmitted data and a long
512+ * linger interval. Once the pre-close is done we do the
513+ * actual socket to release the fd.
514+ */
515+ try {
516+ socketPreClose();
517+ } finally {
518+ socketClose();
519+ }
520+ fd = null;
521+ return;
522+ } else {
523+ /*
524+ * If a thread has acquired the fd and a close
525+ * isn't pending then use a deferred close.
526+ * Also decrement fdUseCount to signal the last
527+ * thread that releases the fd to close it.
528+ */
529+ if (!closePending) {
530+ closePending = true;
531+ fdUseCount--;
532+ socketPreClose();
533+ }
534+ }
535+ }
536+ }
537+ }
538+
539+ void reset() throws IOException {
540+ if (fd != null) {
541+ socketClose();
542+ }
543+ fd = null;
544+ super.reset();
545+ }
546+
547+
548+ /**
549+ * Shutdown read-half of the socket connection;
550+ */
551+ protected void shutdownInput() throws IOException {
552+ if (fd != null) {
553+ socketShutdown(SHUT_RD);
554+ if (socketInputStream != null) {
555+ socketInputStream.setEOF(true);
556+ }
557+ shut_rd = true;
558+ }
559+ }
560+
561+ /**
562+ * Shutdown write-half of the socket connection;
563+ */
564+ protected void shutdownOutput() throws IOException {
565+ if (fd != null) {
566+ socketShutdown(SHUT_WR);
567+ shut_wr = true;
568+ }
569+ }
570+
571+ protected boolean supportsUrgentData () {
572+ return true;
573+ }
574+
575+ protected void sendUrgentData (int data) throws IOException {
576+ if (fd == null) {
577+ throw new IOException("Socket Closed");
578+ }
579+ socketSendUrgentData (data);
580+ }
581+
582+ /**
583+ * Cleans up if the user forgets to close it.
584+ */
585+ protected void finalize() throws IOException {
586+ close();
587+ }
588+
589+ /*
590+ * "Acquires" and returns the FileDescriptor for this impl
591+ *
592+ * A corresponding releaseFD is required to "release" the
593+ * FileDescriptor.
594+ */
595+ FileDescriptor acquireFD() {
596+ synchronized (fdLock) {
597+ fdUseCount++;
598+ return fd;
599+ }
600+ }
601+
602+ /*
603+ * "Release" the FileDescriptor for this impl.
604+ *
605+ * If the use count goes to -1 then the socket is closed.
606+ */
607+ void releaseFD() {
608+ synchronized (fdLock) {
609+ fdUseCount--;
610+ if (fdUseCount == -1) {
611+ if (fd != null) {
612+ try {
613+ socketClose();
614+ } catch (IOException e) {
615+ } finally {
616+ fd = null;
617+ }
618+ }
619+ }
620+ }
621+ }
622+
623+ public boolean isConnectionReset() {
624+ synchronized (resetLock) {
625+ return (resetState == CONNECTION_RESET);
626+ }
627+ }
628+
629+ public boolean isConnectionResetPending() {
630+ synchronized (resetLock) {
631+ return (resetState == CONNECTION_RESET_PENDING);
632+ }
633+ }
634+
635+ public void setConnectionReset() {
636+ synchronized (resetLock) {
637+ resetState = CONNECTION_RESET;
638+ }
639+ }
640+
641+ public void setConnectionResetPending() {
642+ synchronized (resetLock) {
643+ if (resetState == CONNECTION_NOT_RESET) {
644+ resetState = CONNECTION_RESET_PENDING;
645+ }
646+ }
647+
648+ }
649+
650+ /*
651+ * Return true if already closed or close is pending
652+ */
653+ public boolean isClosedOrPending() {
654+ /*
655+ * Lock on fdLock to ensure that we wait if a
656+ * close is in progress.
657+ */
658+ synchronized (fdLock) {
659+ if (closePending || (fd == null)) {
660+ return true;
661+ } else {
662+ return false;
663+ }
664+ }
665+ }
666+
667+ /*
668+ * Return the current value of SO_TIMEOUT
669+ */
670+ public int getTimeout() {
671+ return timeout;
672+ }
673+
674+ /*
675+ * "Pre-close" a socket by dup'ing the file descriptor - this enables
676+ * the socket to be closed without releasing the file descriptor.
677+ */
678+ private void socketPreClose() throws IOException {
679+ socketClose0(true);
680+ }
681+
682+ /*
683+ * Close the socket (and release the file descriptor).
684+ */
685+ protected void socketClose() throws IOException {
686+ socketClose0(false);
687+ }
688+
689+ abstract void socketCreate(boolean isServer) throws IOException;
690+ abstract void socketConnect(InetAddress address, int port, int timeout)
691+ throws IOException;
692+ abstract void socketBind(InetAddress address, int port)
693+ throws IOException;
694+ abstract void socketListen(int count)
695+ throws IOException;
696+ abstract void socketAccept(SocketImpl s)
697+ throws IOException;
698+ abstract int socketAvailable()
699+ throws IOException;
700+ abstract void socketClose0(boolean useDeferredClose)
701+ throws IOException;
702+ abstract void socketShutdown(int howto)
703+ throws IOException;
704+ abstract void socketSetOption(int cmd, boolean on, Object value)
705+ throws SocketException;
706+ abstract int socketGetOption(int opt, Object iaContainerObj) throws SocketException;
707+ abstract void socketSendUrgentData(int data)
708+ throws IOException;
709+
710+ public final static int SHUT_RD = 0;
711+ public final static int SHUT_WR = 1;
712+}
713+
714+class InetAddressContainer {
715+ InetAddress addr;
716+}