📄 plainsocketimpl.java
字号:
/* * @(#)PlainSocketImpl.java 1.51 06/10/10 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */package java.net;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.io.FileDescriptor;import sun.net.ConnectionResetException;/** * Default Socket Implementation. This implementation does * not implement any security checks. It does support SOCKS version 4. * Note this class should <b>NOT</b> be public. * * @author Steven B. Byrne * @version 1.51 10/10/06 */class PlainSocketImpl extends SocketImpl{ /* instance variable for SO_TIMEOUT */ int timeout; // timeout in millisec // traffic class private int trafficClass; private boolean shut_rd = false; private boolean shut_wr = false; private SocketInputStream socketInputStream = null; /* number of threads using the FileDescriptor */ private int fdUseCount = 0; /* lock when increment/decrementing fdUseCount */ private Object fdLock = new Object(); /* indicates a close is pending on the file descriptor */ private boolean closePending = false; private static final int REQUEST_REJECTED_NO_IDENTD = 92; private static final int REQUEST_REJECTED_DIFF_IDENTS = 93; /* indicates connection reset state */ private int CONNECTION_NOT_RESET = 0; private int CONNECTION_RESET_PENDING = 1; private int CONNECTION_RESET = 2; private int resetState; private Object resetLock = new Object(); public static final String socksDefaultPortStr = "1080"; /** * Load net library into runtime. */ static { java.security.AccessController.doPrivileged( new sun.security.action.LoadLibraryAction("net")); /* * Wrap initProto() in a privileged block so that we * can read system properties. */ java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Object run() { initProto(); return null; } } ); } /** * Constructs an empty instance. */ PlainSocketImpl() { } /** * Constructs an instance with the given file descriptor. */ PlainSocketImpl(FileDescriptor fd) { this.fd = fd; } /** * Creates a socket with a boolean that specifies whether this * is a stream socket (true) or an unconnected UDP socket (false). */ protected synchronized void create(boolean stream) throws IOException { fd = new FileDescriptor(); socketCreate(stream); if (socket != null) socket.setCreated(); if (serverSocket != null) serverSocket.setCreated(); } /** * Creates a socket and connects it to the specified port on * the specified host. * @param host the specified host * @param port the specified port */ protected void connect(String host, int port) throws UnknownHostException, IOException { IOException pending = null; try { address = InetAddress.getByName(host); try { connectToAddress(address, port, timeout); return; } catch (IOException e) { pending = e; } } catch (UnknownHostException e) { pending = e; } // everything failed close(); throw pending; } /** * Creates a socket and connects it to the specified address on * the specified port. * @param address the address * @param port the specified port */ protected void connect(InetAddress address, int port) throws IOException { this.port = port; this.address = address; try { connectToAddress(address, port, timeout); return; } catch (IOException e) { // everything failed close(); throw e; } } /** * Creates a socket and connects it to the specified address on * the specified port. * @param address the address * @param timeout the timeout value in milliseconds, or zero for no timeout. * @throws IOException if connection fails * @throws IllegalArgumentException if address is null or is a * SocketAddress subclass not supported by this socket * @since 1.4 */ protected void connect(SocketAddress address, int timeout) throws IOException { if (address == null || !(address instanceof InetSocketAddress)) throw new IllegalArgumentException("unsupported address type"); InetSocketAddress addr = (InetSocketAddress) address; if (addr.isUnresolved()) throw new UnknownHostException(addr.getHostName()); this.port = addr.getPort(); this.address = addr.getAddress(); try { connectToAddress(this.address, port, timeout); return; } catch (IOException e) { // everything failed close(); throw e; } } private void connectToAddress(InetAddress address, int port, int timeout) throws IOException { if (address.isAnyLocalAddress()) { doConnect(InetAddress.getLocalHost(), port, timeout); } else { doConnect(address, port, timeout); } } public void setOption(int opt, Object val) throws SocketException { if (isClosedOrPending()) { throw new SocketException("Socket Closed"); } boolean on = true; switch (opt) { /* check type safety b4 going native. These should never * fail, since only java.Socket* has access to * PlainSocketImpl.setOption(). */ case SO_LINGER: if (val == null || (!(val instanceof Integer) && !(val instanceof Boolean))) throw new SocketException("Bad parameter for option"); if (val instanceof Boolean) { /* true only if disabling - enabling should be Integer */ on = false; } break; case SO_TIMEOUT: if (val == null || (!(val instanceof Integer))) throw new SocketException("Bad parameter for SO_TIMEOUT"); int tmp = ((Integer) val).intValue(); if (tmp < 0) throw new IllegalArgumentException("timeout < 0"); timeout = tmp; break; case IP_TOS: if (val == null || !(val instanceof Integer)) { throw new SocketException("bad argument for IP_TOS"); } trafficClass = ((Integer)val).intValue(); break; case SO_BINDADDR: throw new SocketException("Cannot re-bind socket"); case TCP_NODELAY: if (val == null || !(val instanceof Boolean)) throw new SocketException("bad parameter for TCP_NODELAY"); on = ((Boolean)val).booleanValue(); break; case SO_SNDBUF: case SO_RCVBUF: if (val == null || !(val instanceof Integer) || !(((Integer)val).intValue() > 0)) { throw new SocketException("bad parameter for SO_SNDBUF " + "or SO_RCVBUF"); } break; case SO_KEEPALIVE: if (val == null || !(val instanceof Boolean)) throw new SocketException("bad parameter for SO_KEEPALIVE"); on = ((Boolean)val).booleanValue(); break; case SO_OOBINLINE: if (val == null || !(val instanceof Boolean)) throw new SocketException("bad parameter for SO_OOBINLINE"); on = ((Boolean)val).booleanValue(); break; case SO_REUSEADDR: if (val == null || !(val instanceof Boolean)) throw new SocketException("bad parameter for SO_REUSEADDR"); on = ((Boolean)val).booleanValue(); break; default: throw new SocketException("unrecognized TCP option: " + opt); } socketSetOption(opt, on, val); } public Object getOption(int opt) throws SocketException { if (isClosedOrPending()) { throw new SocketException("Socket Closed"); } if (opt == SO_TIMEOUT) { return new Integer(timeout); } int ret = 0; /* * The native socketGetOption() knows about 3 options. * The 32 bit value it returns will be interpreted according * to what we're asking. A return of -1 means it understands * the option but its turned off. It will raise a SocketException * if "opt" isn't one it understands. */ switch (opt) { case TCP_NODELAY: ret = socketGetOption(opt, null); return (ret == -1) ? new Boolean(false): new Boolean(true); case SO_OOBINLINE: ret = socketGetOption(opt, null); return (ret == -1) ? new Boolean(false): new Boolean(true); case SO_LINGER: ret = socketGetOption(opt, null); return (ret == -1) ? new Boolean(false): (Object)(new Integer(ret)); case SO_REUSEADDR: ret = socketGetOption(opt, null); return (ret == -1) ? new Boolean(false): new Boolean(true); case SO_BINDADDR: InetAddressContainer in = new InetAddressContainer(); ret = socketGetOption(opt, in); return in.addr; case SO_SNDBUF: case SO_RCVBUF: ret = socketGetOption(opt, null); return new Integer(ret); case IP_TOS: ret = socketGetOption(opt, null); if (ret == -1) { // ipv6 tos return new Integer(trafficClass); } else { return new Integer(ret); } case SO_KEEPALIVE: ret = socketGetOption(opt, null); return (ret == -1) ? new Boolean(false): new Boolean(true); // should never get here default: return null; } } /** * The workhorse of the connection operation. Tries several times to * establish a connection to the given <host, port>. If unsuccessful, * throws an IOException indicating what went wrong. */ private synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException { try { acquireFD(); try { socketConnect(address, port, timeout); // If we have a ref. to the Socket, then sets the flags // created, bound & connected to true.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -