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

DatagramChannelImpl

public class DatagramChannelImpl extends DatagramChannel implements org.apache.harmony.luni.platform.FileDescriptorHandler

Fields Summary
private static final org.apache.harmony.luni.platform.INetworkSystem
networkSystem
private static final int
DEFAULT_TIMEOUT
private static final int
ERRCODE_SOCKET_NONBLOCKING_WOULD_BLOCK
private static final byte[]
stubArray
private FileDescriptor
fd
private DatagramSocket
socket
InetSocketAddress
connectAddress
private int
localPort
boolean
connected
boolean
isBound
private final Object
readLock
private final Object
writeLock
private int
trafficClass
Constructors Summary
protected DatagramChannelImpl(SelectorProvider selectorProvider)


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

    /*
     * Constructor
     */
      
              
        super(selectorProvider);
        fd = new FileDescriptor();
        networkSystem.createDatagramSocket(fd, true);
    
private DatagramChannelImpl()

        super(SelectorProvider.provider());
        fd = new FileDescriptor();
        connectAddress = new InetSocketAddress(0);
    
Methods Summary
private intcalculateByteBufferArray(java.nio.ByteBuffer[] sources, int offset, int length)

        int sum = 0;
        for (int val = offset; val < offset + length; val++) {
            sum += sources[val].remaining();
        }
        return sum;
    
private voidcheckNotNull(java.nio.ByteBuffer source)

        if (null == source) {
            throw new NullPointerException();
        }
    
private voidcheckOpen()

        if (!isOpen()) {
            throw new ClosedChannelException();
        }
    
private voidcheckOpenConnected()

        checkOpen();
        if (!isConnected()) {
            throw new NotYetConnectedException();
        }
    
private voidcheckWritable(java.nio.ByteBuffer target)

        // including checking of NPE.
        if (target.isReadOnly()) {
            throw new IllegalArgumentException();
        }
    
public synchronized java.nio.channels.DatagramChannelconnect(java.net.SocketAddress address)

        // must open
        checkOpen();
        // status must be un-connected.
        if (connected) {
            throw new IllegalStateException();
        }

        // check the address
        InetSocketAddress inetSocketAddress = SocketChannelImpl
                .validateAddress(address);

        // security check
        SecurityManager sm = System.getSecurityManager();
        if (null != sm) {
            if (inetSocketAddress.getAddress().isMulticastAddress()) {
                sm.checkMulticast(inetSocketAddress.getAddress());
            } else {
                sm.checkConnect(inetSocketAddress.getAddress().getHostName(),
                        inetSocketAddress.getPort());
            }
        }

        try {
            begin();
            networkSystem.connectDatagram(fd, inetSocketAddress.getPort(),
                    trafficClass, inetSocketAddress.getAddress());
        } catch (ConnectException e) {
            // ConnectException means connect fail, not exception
        } finally {
            end(true);
        }

        // set the connected address.
        connectAddress = inetSocketAddress;
        connected = true;
        isBound = true;
        return this;
    
public synchronized java.nio.channels.DatagramChanneldisconnect()

        if (!isConnected() || !isOpen()) {
            return this;
        }
        connected = false;
        connectAddress = null;
        networkSystem.disconnectDatagram(fd);
        if (null != socket) {
            socket.disconnect();
        }
        return this;
    
public java.io.FileDescriptorgetFD()

        return fd;
    
java.net.InetAddressgetLocalAddress()
Answer the local address from the IP stack. This method should not be called directly as it does not check the security policy.

return
InetAddress the local address to which the socket is bound.
see
DatagramSocket

        return networkSystem.getSocketLocalAddress(fd, NetUtil
                .preferIPv6Addresses());
    
protected synchronized voidimplCloseSelectableChannel()

        connected = false;
        if (null != socket && !socket.isClosed()) {
            socket.close();
        } else {
            networkSystem.socketClose(fd);
        }
    
protected voidimplConfigureBlocking(boolean blockingMode)

        // Do nothing here. For real read/write operation in nonblocking mode,
        // it uses select system call. Whether a channel is blocking can be
        // decided by isBlocking() method.
    
public synchronized booleanisConnected()

        return connected;
    
public intread(java.nio.ByteBuffer target)

        if (null == target) {
            throw new NullPointerException();
        }
        // status must be open and connected
        checkOpenConnected();
        // target buffer must be not null and not readonly
        checkWritable(target);

        if (!target.hasRemaining()) {
            return 0;
        }

        int readCount  = 0;
        if (target.isDirect() || target.hasArray()) {
            readCount = readImpl(target);
            if(readCount > 0){
                target.position(target.position() + readCount);
            }

        } else {
            byte[] readArray = new byte[target.remaining()];
            ByteBuffer 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 (length < 0 || offset < 0
                || (long) length + (long) offset > targets.length) {
            throw new IndexOutOfBoundsException();
        }

        // status must be open and connected
        checkOpenConnected();

        int totalCount = 0;
        for (int val = offset; val < length; val++) {
            // target buffer must be not null and not readonly
            checkWritable(targets[val]);
            totalCount += targets[val].remaining();
        }

        // read data to readBuffer, and then transfer data from readBuffer to
        // targets.
        ByteBuffer readBuffer = ByteBuffer.allocate(totalCount);
        int readCount;
        readCount = readImpl(readBuffer);
        int left = readCount;
        int index = offset;
        // transfer data from readBuffer to targets
        byte[] readArray = readBuffer.array();
        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 readBuffer)

        synchronized(readLock){
            int readCount = 0;
            try {
                begin();
                // timeout == 0 means block read.
                // DEFAULT_TIMEOUT is used in non-block mode.
                int timeout = isBlocking() ? 0 : DEFAULT_TIMEOUT;
                int start = readBuffer.position();
                int length = readBuffer.remaining();
                if (readBuffer.isDirect()) {
                    int address = AddressUtil.getDirectBufferAddress(readBuffer);
                    if (isConnected()) {
                        readCount = networkSystem.recvConnectedDatagramDirect(fd,
                                null, address, start, length, timeout, false);
                    } else {
                        readCount = networkSystem.receiveDatagramDirect(fd,
                                null, address, start, length, timeout, false);
                    }
                } else {
                    // the target is assured to have array.
                    byte[] target = readBuffer.array();
                    start += readBuffer.arrayOffset();
                    if (isConnected()) {
                        readCount = networkSystem.recvConnectedDatagram(fd, null,
                                target, start, length, timeout, false);
                    } else {
                        readCount = networkSystem.receiveDatagram(fd, null, target,
                                start, length, timeout, false);
                    }
                }
                return readCount;
            } catch (InterruptedIOException e) {
                // InterruptedIOException will be thrown when timeout.
                return 0;
            } finally {
                end(readCount > 0);
            }
        }
    
public java.net.SocketAddressreceive(java.nio.ByteBuffer target)

        // must not null and not readonly
        checkWritable(target);
        // must open
        checkOpen();

        if (!isBound) {
            return null;
        }

        SocketAddress retAddr = null;
        try {
            begin();

            // receive real data packet, (not peek)
            synchronized (readLock) {
                boolean loop = isBlocking();
                if (!target.isDirect()) {
                    retAddr = receiveImpl(target, loop);
                } else {
                    retAddr = receiveDirectImpl(target, loop);
                }
            }
        } catch (InterruptedIOException e) {
            // this line used in Linux
            return null;
        } finally {
            end(null != retAddr);
        }
        return retAddr;
    
private java.net.SocketAddressreceiveDirectImpl(java.nio.ByteBuffer target, boolean loop)

        SocketAddress retAddr = null;  
        DatagramPacket receivePacket = new DatagramPacket(
                stubArray, 0);
        int oldposition = target.position();
        int received = 0;
        do {
            int address = AddressUtil.getDirectBufferAddress(target);
            if (isConnected()) {
                received = networkSystem.recvConnectedDatagramDirect(fd, receivePacket,
                        address, target.position(),
                        target.remaining(), isBlocking() ? 0
                                : DEFAULT_TIMEOUT, false);
            } else {
                received = networkSystem.receiveDatagramDirect(fd, receivePacket,
                        address, target.position(),
                        target.remaining(), isBlocking() ? 0
                                : DEFAULT_TIMEOUT, false);
            }

            // security check
            SecurityManager sm = System.getSecurityManager();
            if (!isConnected() && null != sm) {
                try {
                    sm.checkAccept(receivePacket.getAddress()
                            .getHostAddress(), receivePacket.getPort());
                } catch (SecurityException e) {
                    // do discard the datagram packet
                    receivePacket = null;
                }
            }
            if (null != receivePacket
                    && null != receivePacket.getAddress()) {
                // copy the data of received packet
                if (received > 0) {
                    target.position(oldposition + received);
                }
                retAddr = receivePacket.getSocketAddress();
                break;
            }
        } while (loop);
        return retAddr;
    
private java.net.SocketAddressreceiveImpl(java.nio.ByteBuffer target, boolean loop)

        SocketAddress retAddr = null;
        DatagramPacket receivePacket;
        int oldposition = target.position();
        int received = 0;
        if (target.hasArray()) {
            receivePacket = new DatagramPacket(target.array(), target
                    .position()
                    + target.arrayOffset(), target.remaining());
        } else {        
            receivePacket = new DatagramPacket(new byte[target.remaining()], target.remaining());
        }
        do {
            if (isConnected()) {
                received = networkSystem.recvConnectedDatagram(fd, receivePacket,
                        receivePacket.getData(), receivePacket.getOffset(),
                        receivePacket.getLength(), isBlocking() ? 0
                                : DEFAULT_TIMEOUT, false);
            } else {
                received = networkSystem.receiveDatagram(fd, receivePacket,
                        receivePacket.getData(), receivePacket.getOffset(),
                        receivePacket.getLength(), isBlocking() ? 0
                                : DEFAULT_TIMEOUT, false);
            }

            // security check
            SecurityManager sm = System.getSecurityManager();
            if (!isConnected() && null != sm) {
                try {
                    sm.checkAccept(receivePacket.getAddress().getHostAddress(),
                            receivePacket.getPort());
                } catch (SecurityException e) {
                    // do discard the datagram packet
                    receivePacket = null;
                }
            }
            if (null != receivePacket && null != receivePacket.getAddress()) {
                               
                if (received > 0) {
                    if (target.hasArray()) {
                        target.position(oldposition + received);
                    } else {
                        // copy the data of received packet
                        target.put(receivePacket.getData(), 0, received);
                    }
                }
                retAddr = receivePacket.getSocketAddress();
                break;
            }
        } while (loop);
        return retAddr;
    
public intsend(java.nio.ByteBuffer source, java.net.SocketAddress socketAddress)

        // must not null
        checkNotNull(source);
        // must open
        checkOpen();

        // transfer socketAddress
        InetSocketAddress isa = (InetSocketAddress) socketAddress;
        if (null == isa.getAddress()) {
            throw new IOException();
        }

        if (isConnected()) {
            if (!connectAddress.equals(isa)) {
                throw new IllegalArgumentException();
            }
        } else {
            // not connected, check security
            SecurityManager sm = System.getSecurityManager();
            if (sm != null) {
                if (isa.getAddress().isMulticastAddress()) {
                    sm.checkMulticast(isa.getAddress());
                } else {
                    sm.checkConnect(isa.getAddress().getHostAddress(), isa
                            .getPort());
                }
            }
        }

        // the return value.
        int sendCount = 0;
        try {
            begin();
            byte[] array = null;
            int length = source.remaining();
            int oldposition = source.position();
            int start = oldposition;
            if (source.isDirect()) {
                synchronized (writeLock) {
                    int data_address = AddressUtil
                            .getDirectBufferAddress(source);
                    sendCount = networkSystem.sendDatagramDirect(fd,
                            data_address, start, length, isa.getPort(), false,
                            trafficClass, isa.getAddress());
                }
            } else {
                if (source.hasArray()) {
                    array = source.array();
                    start += source.arrayOffset();
                } else {
                    array = new byte[length];
                    source.get(array);
                    start = 0;
                }
                synchronized (writeLock) {
                    sendCount = networkSystem.sendDatagram(fd, array, start,
                            length, isa.getPort(), false, trafficClass, isa
                                    .getAddress());
                }
            }
            source.position(oldposition + sendCount);
            return sendCount;
        } finally {
            end(sendCount >= 0);
        }
    
public synchronized java.net.DatagramSocketsocket()

        if (null == socket) {
            socket = new DatagramSocketAdapter(SocketImplProvider
                    .getDatagramSocketImpl(fd, localPort), this);
        }
        return socket;
    
public intwrite(java.nio.ByteBuffer source)

        // source buffer must be not null
        checkNotNull(source);
        // status must be open and connected
        checkOpenConnected();
        // return immediately if source is full
        if (!source.hasRemaining()) {
            return 0;
        }

        ByteBuffer writeBuffer = null;
        byte[] writeArray = null;
        int oldposition = source.position();
        int result;
        if (source.isDirect() || source.hasArray()) {
            writeBuffer = source;
        } else {
            writeArray = new byte[source.remaining()];
            source.get(writeArray);
            writeBuffer = ByteBuffer.wrap(writeArray);
        }
        result = writeImpl(writeBuffer);
        if (result > 0) {
            source.position(oldposition + result);
        }
        return result;
    
public longwrite(java.nio.ByteBuffer[] sources, int offset, int length)

        if (length < 0 || offset < 0
                || (long) length + (long) offset > sources.length) {
            throw new IndexOutOfBoundsException();
        }

        // status must be open and connected
        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 buf)

        synchronized(writeLock){
            int result = 0;
            try {
                begin();
                int length = buf.remaining();
                int start = buf.position();
    
                if (buf.isDirect()) {
                    int address = AddressUtil.getDirectBufferAddress(buf);
                    result = networkSystem.sendConnectedDatagramDirect(fd, address,
                            start, length, isBound);
                } else {
                    // buf is assured to have array.
                    start += buf.arrayOffset();
                    result = networkSystem.sendConnectedDatagram(fd, buf.array(),
                            start, length, isBound);
                }
                return result;
            } catch (SocketException e) {
                if (e.getCause() instanceof ErrorCodeException) {
                    if (ERRCODE_SOCKET_NONBLOCKING_WOULD_BLOCK == ((ErrorCodeException) e
                            .getCause()).getErrorCode()) {
                        return result;
                    }
                }
                throw e;
            } finally {
                end(result > 0);
            }
        }