FileDocCategorySizeDatePackage
SocketChannelImpl.javaAPI DocAndroid 1.5 API34223Wed May 06 22:41:04 BST 2009org.apache.harmony.nio.internal

SocketChannelImpl

public class SocketChannelImpl extends SocketChannel implements org.apache.harmony.luni.platform.FileDescriptorHandler

Fields Summary
private static final int
EOF
private static final int
ERRCODE_SOCKET_NONBLOCKING_WOULD_BLOCK
static final org.apache.harmony.luni.platform.INetworkSystem
networkSystem
static final int
SOCKET_STATUS_UNINIT
static final int
SOCKET_STATUS_UNCONNECTED
static final int
SOCKET_STATUS_PENDING
static final int
SOCKET_STATUS_CONNECTED
static final int
SOCKET_STATUS_CLOSED
private static final int
TIMEOUT_NONBLOCK
private static final int
TIMEOUT_BLOCK
private static final int
HY_SOCK_STEP_START
private static final int
HY_PORT_SOCKET_STEP_CHECK
private static final int
CONNECT_SUCCESS
FileDescriptor
fd
private Socket
socket
InetSocketAddress
connectAddress
InetAddress
localAddress
int
localPort
int
status
volatile boolean
isBound
private final Object
readLock
private final Object
writeLock
private byte[]
connectContext
private int
trafficClass
Constructors Summary
public SocketChannelImpl(SelectorProvider selectorProvider)


    // -------------------------------------------------------------------
    // Constructor
    // -------------------------------------------------------------------

    /*
     * Constructor
     */
      
              
        super(selectorProvider);
        fd = new FileDescriptor();
        status = SOCKET_STATUS_UNCONNECTED;
        networkSystem.createSocket(fd, true);
    
private SocketChannelImpl()

        super(SelectorProvider.provider());
        fd = new FileDescriptor();
        connectAddress = new InetSocketAddress(0);
        status = SOCKET_STATUS_CONNECTED;
    
SocketChannelImpl(Socket aSocket, FileDescriptor aFd)

        super(SelectorProvider.provider());
        socket = aSocket;
        fd = aFd;
        status = SOCKET_STATUS_UNCONNECTED;
    
Methods Summary
private intcalculateByteBufferArray(java.nio.ByteBuffer[] sources, int offset, int length)

        int sum = 0;
        for (int val = offset; val < offset + length; val++) {
            sum = sum + sources[val].remaining();
        }
        return sum;
    
private synchronized voidcheckOpenConnected()

        if (!isOpen()) {
            throw new ClosedChannelException();
        }
        if (!isConnected()) {
            throw new NotYetConnectedException();
        }
    
private synchronized voidcheckUnconnected()

        if (!isOpen()) {
            throw new ClosedChannelException();
        }
        if (status == SOCKET_STATUS_CONNECTED) {
            throw new AlreadyConnectedException();
        }
        if (status == SOCKET_STATUS_PENDING) {
            throw new ConnectionPendingException();
        }
    
public booleanconnect(java.net.SocketAddress socketAddress)

        // status must be open and unconnected
        checkUnconnected();

        // check the address
        InetSocketAddress inetSocketAddress = validateAddress(socketAddress);

        int port = inetSocketAddress.getPort();
        String hostName = inetSocketAddress.getAddress().getHostName();
        // security check
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkConnect(hostName, port);
        }

        // connect result
        int result = EOF;
        boolean finished = false;

        try {
            if (!isBound) {
                // bind
                networkSystem.bind2(fd, 0, true, InetAddress
                        .getByAddress(new byte[] { 0, 0, 0, 0 }));
                isBound = true;
            }

            if (isBlocking()) {
                begin();
                result = networkSystem.connect(fd, trafficClass,
                        inetSocketAddress.getAddress(), inetSocketAddress
                                .getPort());

            } else {
                result = networkSystem.connectWithTimeout(fd, 0, trafficClass,
                        inetSocketAddress.getAddress(), inetSocketAddress
                                .getPort(), HY_SOCK_STEP_START, connectContext);
                // set back to nonblocking to work around with a bug in portlib
                if (!this.isBlocking()) {
                    networkSystem.setNonBlocking(fd, true);
                }
            }
            finished = (CONNECT_SUCCESS == result);
            isBound = finished;
        } catch (IOException e) {
            if (e instanceof ConnectException && !isBlocking()) {
                status = SOCKET_STATUS_PENDING;
            } else {
                if (isOpen()) {
                    close();
                    finished = true;
                }
                throw e;
            }
        } finally {
            if (isBlocking()) {
                end(finished);
            }
        }

        // set local port
        localPort = networkSystem.getSocketLocalPort(fd, false);
        localAddress = networkSystem.getSocketLocalAddress(fd, false);

        // set the connected address.
        connectAddress = inetSocketAddress;
        synchronized (this) {
            if (isBlocking()) {
                status = (finished ? SOCKET_STATUS_CONNECTED
                        : SOCKET_STATUS_UNCONNECTED);
            } else {
                status = SOCKET_STATUS_PENDING;
            }
        }
        return finished;
    
public booleanfinishConnect()

        // status check
        synchronized (this) {
            if (!isOpen()) {
                throw new ClosedChannelException();
            }
            if (status == SOCKET_STATUS_CONNECTED) {
                return true;
            }
            if (status != SOCKET_STATUS_PENDING) {
                throw new NoConnectionPendingException();
            }
        }

        // finish result
        int result = EOF;
        boolean finished = false;

        try {
            begin();
            result = networkSystem.connectWithTimeout(fd,
                    isBlocking() ? -1 : 0, trafficClass, connectAddress
                            .getAddress(), connectAddress.getPort(),
                    HY_PORT_SOCKET_STEP_CHECK, connectContext);
            finished = (result == CONNECT_SUCCESS);
            isBound = finished;
            localAddress = networkSystem.getSocketLocalAddress(fd, false);
        } catch (ConnectException e) {
            if (isOpen()) {
                close();
                finished = true;
            }
            throw e;
        } finally {
            end(finished);
        }

        synchronized (this) {
            status = (finished ? SOCKET_STATUS_CONNECTED : status);
            isBound = finished;
        }
        return finished;
    
public java.io.FileDescriptorgetFD()

        return fd;
    
public java.net.InetAddressgetLocalAddress()

        byte[] any_bytes = { 0, 0, 0, 0 };
        if (!isBound) {
            return InetAddress.getByAddress(any_bytes);
        }
        return localAddress;
    
protected synchronized voidimplCloseSelectableChannel()

        if (SOCKET_STATUS_CLOSED != status) {
            status = SOCKET_STATUS_CLOSED;
            if (null != socket && !socket.isClosed()) {
                socket.close();
            } else {
                networkSystem.socketClose(fd);
            }
        }
    
protected voidimplConfigureBlocking(boolean blockMode)

        synchronized (blockingLock()) {
            networkSystem.setNonBlocking(fd, !blockMode);
        }
    
public synchronized booleanisConnected()

        return status == SOCKET_STATUS_CONNECTED;
    
public synchronized booleanisConnectionPending()

        return status == SOCKET_STATUS_PENDING;
    
private booleanisIndexValid(java.nio.ByteBuffer[] targets, int offset, int length)

        return (length >= 0) && (offset >= 0)
                && ((long)length + (long)offset <= targets.length);
    
public intread(java.nio.ByteBuffer target)

        if (null == target) {
            throw new NullPointerException();
        }
        checkOpenConnected();
        if (!target.hasRemaining()) {
            return 0;
        }
        
        int readCount;
        if (target.isDirect() || target.hasArray()) {
            readCount = readImpl(target);
            if (readCount > 0) {
                target.position(target.position() + readCount);
            }
        } else {
            ByteBuffer readBuffer = null;
            byte[] readArray = null;
            readArray = new byte[target.remaining()];
            readBuffer = ByteBuffer.wrap(readArray);
            readCount = readImpl(readBuffer);
            if (readCount > 0) {
                target.put(readArray, 0, readCount);
            }
        }
        return readCount;
    
public longread(java.nio.ByteBuffer[] targets, int offset, int length)

        if (!isIndexValid(targets, offset, length)) {
            throw new IndexOutOfBoundsException();
        }

        checkOpenConnected();
        int totalCount = calculateByteBufferArray(targets, offset, length);
        if (0 == totalCount) {
            return 0;
        }
        byte[] readArray = new byte[totalCount];
        ByteBuffer readBuffer = ByteBuffer.wrap(readArray);
        int readCount;
        // read data to readBuffer, and then transfer data from readBuffer to
        // targets.
        readCount = readImpl(readBuffer);
        if (readCount > 0) {
            int left = readCount;
            int index = offset;
            // transfer data from readArray to targets
            while (left > 0) {
                int putLength = Math.min(targets[index].remaining(), left);
                targets[index].put(readArray, readCount - left, putLength);
                index++;
                left -= putLength;
            }
        }
        return readCount;
    
private intreadImpl(java.nio.ByteBuffer target)

        synchronized(readLock){
            int readCount = 0;
            try {
                if (isBlocking()) {
                    begin();
                }
                int offset = target.position();
                int length = target.remaining();
                if (target.isDirect()) {
                    int address = AddressUtil.getDirectBufferAddress(target);
                    readCount = networkSystem.readDirect(fd, address, offset,
                            length, (isBlocking() ? TIMEOUT_BLOCK
                                    : TIMEOUT_NONBLOCK));
                } else {
                    // target is assured to have array.
                    byte[] array = target.array();
                    offset += target.arrayOffset();
                    readCount = networkSystem.read(fd, array, offset, length,
                            (isBlocking() ? TIMEOUT_BLOCK : TIMEOUT_NONBLOCK));
                }
                return readCount;
            } finally {
                if (isBlocking()) {
                    end(readCount > 0);
                }
            }
        }
    
voidsetBound(boolean flag)

        isBound = flag;
    
synchronized voidsetConnected()

        status = SOCKET_STATUS_CONNECTED;
    
public synchronized java.net.Socketsocket()

        if (null == socket) {
            try {
                InetAddress addr = null;
                int port = 0;
                if (connectAddress != null) {
                    addr = connectAddress.getAddress();
                    port = connectAddress.getPort();
                }
                socket = new SocketAdapter(SocketImplProvider.getSocketImpl(fd,
                        localPort, addr, port), this);
            } catch (SocketException e) {
                return null;
            }
        }
        return socket;
    
static java.net.InetSocketAddressvalidateAddress(java.net.SocketAddress socketAddress)

        if (null == socketAddress) {
            throw new IllegalArgumentException();
        }
        if (!(socketAddress instanceof InetSocketAddress)) {
            throw new UnsupportedAddressTypeException();
        }
        InetSocketAddress inetSocketAddress = (InetSocketAddress) socketAddress;
        if (inetSocketAddress.isUnresolved()) {
            throw new UnresolvedAddressException();
        }
        return inetSocketAddress;
    
public intwrite(java.nio.ByteBuffer source)

        if (null == source) {
            throw new NullPointerException();
        }
        checkOpenConnected();
        if (!source.hasRemaining()) {
            return 0;
        }
        return writeImpl(source);
    
public longwrite(java.nio.ByteBuffer[] sources, int offset, int length)

        if (!isIndexValid(sources, offset, length)) {
            throw new IndexOutOfBoundsException();
        }

        checkOpenConnected();
        int count = calculateByteBufferArray(sources, offset, length);
        if (0 == count) {
            return 0;
        }
        ByteBuffer writeBuf = ByteBuffer.allocate(count);
        for (int val = offset; val < length+offset; val++) {
            ByteBuffer source = sources[val];
            int oldPosition = source.position();
            writeBuf.put(source);
            source.position(oldPosition);
        }
        writeBuf.flip();
        int result = writeImpl(writeBuf);
        int val = offset;
        int written = result;
        while (result > 0) {
            ByteBuffer source = sources[val];
            int gap = Math.min(result, source.remaining());
            source.position(source.position() + gap);
            val++;
            result -= gap;
        }
        return written;
    
private intwriteImpl(java.nio.ByteBuffer source)

        synchronized(writeLock){
            if (!source.hasRemaining()) {
                return 0;
            }
            int writeCount = 0;
            try {
                int pos = source.position();
                int length = source.remaining();
                if (isBlocking()) {
                    begin();
                }
                if (source.isDirect()) {
                    int address = AddressUtil.getDirectBufferAddress(source);
                    writeCount = networkSystem
                            .writeDirect(fd, address, pos, length);
                } else if (source.hasArray()) {
                    pos += source.arrayOffset();
                    writeCount = networkSystem.write(fd, source.array(), pos,
                            length);
                } else {
                    byte[] array = new byte[length];
                    source.get(array);
                    writeCount = networkSystem.write(fd, array, 0, length);
                }
                source.position(pos + writeCount);
            } catch (SocketException e) {
                if (e.getCause() instanceof ErrorCodeException) {
                    if (ERRCODE_SOCKET_NONBLOCKING_WOULD_BLOCK == ((ErrorCodeException) e
                            .getCause()).getErrorCode()) {
                        return writeCount;
                    }
                }
                throw e;
            } finally {
                if (isBlocking()) {
                    end(writeCount >= 0);
                }
            }
            return writeCount;
        }