FileDocCategorySizeDatePackage
PlainSocketImpl.javaAPI DocJava SE 6 API18846Tue Jun 10 00:25:40 BST 2008java.net

PlainSocketImpl

public class PlainSocketImpl extends SocketImpl
Default Socket Implementation. This implementation does not implement any security checks. Note this class should NOT be public.
author
Steven B. Byrne
version
1.67, 03/08/07

Fields Summary
int
timeout
private int
trafficClass
private boolean
shut_rd
private boolean
shut_wr
private SocketInputStream
socketInputStream
private int
fdUseCount
private Object
fdLock
private boolean
closePending
private int
CONNECTION_NOT_RESET
private int
CONNECTION_RESET_PENDING
private int
CONNECTION_RESET
private int
resetState
private Object
resetLock
private FileDescriptor
fd1
private InetAddress
anyLocalBoundAddr
private int
lastfd
public static final int
SHUT_RD
public static final int
SHUT_WR
Constructors Summary
PlainSocketImpl()
Constructs an empty instance.


              
     
	java.security.AccessController.doPrivileged(
		  new sun.security.action.LoadLibraryAction("net"));
	initProto();
     
PlainSocketImpl(FileDescriptor fd)
Constructs an instance with the given file descriptor. Note, this will not work with IPv6, since two fds are used.

	this.fd = fd;
    
Methods Summary
protected synchronized voidaccept(java.net.SocketImpl s)
Accepts connections.

param
s the connection

	FileDescriptor fd = acquireFD();
	try {
	    socketAccept(s);
	} finally {
	    releaseFD();
	}
    
public final java.io.FileDescriptoracquireFD()

	synchronized (fdLock) {
	    fdUseCount++;
	    return fd;
	}
    
protected synchronized intavailable()
Returns the number of bytes that can be read without blocking.

	if (isClosedOrPending()) {
            throw new IOException("Stream closed.");
	}

	/*
	 * If connection has been reset then return 0 to indicate
	 * there are no buffered bytes.
	 */
	if (isConnectionReset()) {
	    return 0;
	}

	/*
	 * If no bytes available and we were previously notified
	 * of a connection reset then we move to the reset state.
	 *
	 * If are notified of a connection reset then check
	 * again if there are bytes buffered on the socket. 
	 */
	int n = 0;
	try { 
	    n = socketAvailable();
	    if (n == 0 && isConnectionResetPending()) {
	        setConnectionReset();
	    }
	} catch (ConnectionResetException exc1) {
	    setConnectionResetPending();
	    try {
	        n = socketAvailable();
		if (n == 0) {
		    setConnectionReset();
		}
	    } catch (ConnectionResetException exc2) {
	    }
	}
	return n;
    
protected synchronized voidbind(java.net.InetAddress address, int lport)
Binds the socket to the specified address of the specified local port.

param
address the address
param
port the port

	socketBind(address, lport);
	if (socket != null)
	    socket.setBound();
	if (serverSocket != null)
	    serverSocket.setBound();
	if (address.isAnyLocalAddress()) {
	    anyLocalBoundAddr = address;
	}
    
protected voidclose()
Closes the socket.

	synchronized(fdLock) {
	    if (fd != null || fd1 != null) {
		if (fdUseCount == 0) {
		    if (closePending) {
			return;
		    }
		    closePending = true;
		    /*
		     * We close the FileDescriptor in two-steps - first the
 		     * "pre-close" which closes the socket but doesn't
		     * release the underlying file descriptor. This operation
		     * may be lengthy due to untransmitted data and a long
		     * linger interval. Once the pre-close is done we do the
		     * actual socket to release the fd.
		     */
		    try {
		        socketPreClose();
		    } finally {
		        socketClose();
		    }
		    fd = null;
		    fd1 = null;
		    return;
		} else {
		    /*
		     * If a thread has acquired the fd and a close
		     * isn't pending then use a deferred close.
		     * Also decrement fdUseCount to signal the last
		     * thread that releases the fd to close it.
		     */
		    if (!closePending) {
			closePending = true;
		        fdUseCount--;
			socketPreClose();
		    }
		}
	    }
	}
    
protected voidconnect(java.lang.String host, int port)
Creates a socket and connects it to the specified port on the specified host.

param
host the specified host
param
port the specified port

	IOException pending = null;
	try {
	    InetAddress 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;
    
protected voidconnect(java.net.InetAddress address, int port)
Creates a socket and connects it to the specified address on the specified port.

param
address the address
param
port the specified port

	this.port = port;
	this.address = address;

	try {
	    connectToAddress(address, port, timeout);
	    return;
	} catch (IOException e) {
	    // everything failed
	    close();
	    throw e;
	}
    
protected voidconnect(java.net.SocketAddress address, int timeout)
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

	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 voidconnectToAddress(java.net.InetAddress address, int port, int timeout)

	if (address.isAnyLocalAddress()) {
	    doConnect(InetAddress.getLocalHost(), port, timeout);
	} else {
	    doConnect(address, port, timeout);
	}
    
protected synchronized voidcreate(boolean stream)
Creates a socket with a boolean that specifies whether this is a stream socket (true) or an unconnected UDP socket (false).

	fd = new FileDescriptor();
	fd1 = new FileDescriptor();
	socketCreate(stream);
	if (socket != null)
	    socket.setCreated();
	if (serverSocket != null)
	    serverSocket.setCreated();
    
private synchronized voiddoConnect(java.net.InetAddress address, int port, int timeout)
The workhorse of the connection operation. Tries several times to establish a connection to the given . If unsuccessful, throws an IOException indicating what went wrong.

        try {
	    FileDescriptor fd = acquireFD();
	    try {
	        socketConnect(address, port, timeout);
		// If we have a ref. to the Socket, then sets the flags
		// created, bound & connected to true.
		// This is normally done in Socket.connect() but some
		// subclasses of Socket may call impl.connect() directly!
		if (socket != null) {
		    socket.setBound();
		    socket.setConnected();
		}
	    } finally {
		releaseFD();
	    }
	} catch (IOException e) {	
	    close();
	    throw e;
	}
    
protected voidfinalize()
Cleans up if the user forgets to close it.

	close();
    
protected synchronized java.io.InputStreamgetInputStream()
Gets an InputStream for this socket.

	if (isClosedOrPending()) {
	    throw new IOException("Socket Closed");
	}
	if (shut_rd) {
	    throw new IOException("Socket input is shutdown");
	}
	if (socketInputStream == null) {
	    socketInputStream = new SocketInputStream(this);
	}
	return socketInputStream;
    
public java.lang.ObjectgetOption(int opt)

	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 Boolean.valueOf(ret != -1);
	case SO_OOBINLINE:
	    ret = socketGetOption(opt, null);
	    return Boolean.valueOf(ret != -1);
	case SO_LINGER:
	    ret = socketGetOption(opt, null);
	    return (ret == -1) ? Boolean.FALSE: (Object)(new Integer(ret));
	case SO_REUSEADDR:
	    ret = socketGetOption(opt, null);
	    return Boolean.valueOf(ret != -1);
	case SO_BINDADDR:
	    if (fd != null && fd1 != null ) {
		/* must be unbound or else bound to anyLocal */
		return anyLocalBoundAddr;
	    }
	    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 Boolean.valueOf(ret != -1);
	// should never get here
	default:
	    return null;
	}
    
protected synchronized java.io.OutputStreamgetOutputStream()
Gets an OutputStream for this socket.

	if (isClosedOrPending()) {
	    throw new IOException("Socket Closed");
	}
        if (shut_wr) {
	    throw new IOException("Socket output is shutdown");
	}
	return new SocketOutputStream(this);
    
public intgetTimeout()

	return timeout;
    
private static native voidinitProto()

public booleanisClosedOrPending()

	/*
	 * Lock on fdLock to ensure that we wait if a
	 * close is in progress.
	 */
	synchronized (fdLock) {
	    if (closePending || (fd == null && fd1 == null)) {
		return true;
	    } else {
		return false;
	    }
	}
    
public booleanisConnectionReset()

	synchronized (resetLock) {
	    return (resetState == CONNECTION_RESET);
	}
    
public booleanisConnectionResetPending()

	synchronized (resetLock) {
            return (resetState == CONNECTION_RESET_PENDING);
        }
    
protected synchronized voidlisten(int count)
Listens, for a specified amount of time, for connections.

param
count the amount of time to listen for connections

	socketListen(count);
    
public final voidreleaseFD()

	synchronized (fdLock) {
	    fdUseCount--;
	    if (fdUseCount == -1) {
		if (fd != null) {
	            try {
			socketClose();
	            } catch (IOException e) { 
		    } finally {
		        fd = null;
		    }
		}
	    }
	}
    
voidreset()

        if (fd != null || fd1 != null) {
            socketClose();
        }
        fd = null;
        fd1 = null;
        super.reset();
    
protected voidsendUrgentData(int data)

        if (fd == null) {
            throw new IOException("Socket Closed");
        }
        socketSendUrgentData (data);
    
public voidsetConnectionReset()

	synchronized (resetLock) {
            resetState = CONNECTION_RESET;
        }
    
public voidsetConnectionResetPending()

	synchronized (resetLock) {
            if (resetState == CONNECTION_NOT_RESET) {
                resetState = CONNECTION_RESET_PENDING;
            }
        }

    
voidsetInputStream(SocketInputStream in)

	socketInputStream = in;
    
public voidsetOption(int opt, java.lang.Object val)

	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);
    
protected voidshutdownInput()
Shutdown read-half of the socket connection;

      if (fd != null) {
	  socketShutdown(SHUT_RD);
	  if (socketInputStream != null) {
	      socketInputStream.setEOF(true);
	  }
	  shut_rd = true;
      }
    
protected voidshutdownOutput()
Shutdown write-half of the socket connection;

      if (fd != null) {
	  socketShutdown(SHUT_WR);
	  shut_wr = true;
      }
    
private native voidsocketAccept(java.net.SocketImpl s)

private native intsocketAvailable()

private native voidsocketBind(java.net.InetAddress address, int port)

private voidsocketClose()

	socketClose0(false);
    
private native voidsocketClose0(boolean useDeferredClose)

private native voidsocketConnect(java.net.InetAddress address, int port, int timeout)

private native voidsocketCreate(boolean isServer)

private native intsocketGetOption(int opt, java.lang.Object iaContainerObj)

private native intsocketGetOption1(int opt, java.lang.Object iaContainerObj, java.io.FileDescriptor fd)

private native voidsocketListen(int count)

private voidsocketPreClose()

	socketClose0(true);
    
private native voidsocketSendUrgentData(int data)

private native voidsocketSetOption(int cmd, boolean on, java.lang.Object value)

private native voidsocketShutdown(int howto)

protected booleansupportsUrgentData()

        return true;