1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  the License.  You may obtain a copy of the License at
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18ae704b984c10a63883cc366e823d53902d6ac7a9Elliott Hughespackage java.nio;
19f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.FileDescriptor;
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException;
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.InterruptedIOException;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.ConnectException;
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.DatagramPacket;
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.DatagramSocket;
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.DatagramSocketImpl;
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.InetAddress;
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.InetSocketAddress;
298de7cf6bff36093dda9e25a1ab3718720cb54906Elliott Hughesimport java.net.PlainDatagramSocketImpl;
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.SocketAddress;
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.SocketException;
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.AlreadyConnectedException;
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.ClosedChannelException;
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.DatagramChannel;
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.IllegalBlockingModeException;
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.NotYetConnectedException;
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.spi.SelectorProvider;
38a1603838fe9e865575c87982e32c6343740e464cElliott Hughesimport java.util.Arrays;
3932b0fa4d1a31ef07bc4297c615f0fe50e9aa7c21Elliott Hughesimport libcore.io.ErrnoException;
400b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport libcore.io.IoBridge;
41454a95f6a28855aa3c88d168b15a45bf315efc99Elliott Hughesimport libcore.io.IoUtils;
4232b0fa4d1a31ef07bc4297c615f0fe50e9aa7c21Elliott Hughesimport libcore.io.Libcore;
436186821cb13f4ac7ff50950c813394367e021eaeJesse Wilsonimport libcore.util.EmptyArray;
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The default implementation class of java.nio.channels.DatagramChannel.
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
48d320e321d5567a4ac94b6e5874eda4b1f1189e13Elliott Hughesclass DatagramChannelImpl extends DatagramChannel implements FileDescriptorChannel {
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // The fd to interact with native code
50c6e0981e5a2d23a0758ed71a8086c4278a7832efJesse Wilson    private final FileDescriptor fd;
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Our internal DatagramSocket.
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private DatagramSocket socket = null;
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // The address to be connected.
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    InetSocketAddress connectAddress = null;
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // local port
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int localPort;
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // At first, uninitialized.
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    boolean connected = false;
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // whether the socket is bound
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    boolean isBound = false;
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
675e23b687ef8b3c696d54d1880b454942875665b7Elliott Hughes    private final Object readLock = new Object();
685e23b687ef8b3c696d54d1880b454942875665b7Elliott Hughes    private final Object writeLock = new Object();
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /*
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructor
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
734e4000ed98f9056639fba0713a3fd3caacf9746cElliott Hughes    protected DatagramChannelImpl(SelectorProvider selectorProvider) throws IOException {
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(selectorProvider);
750b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes        fd = IoBridge.socket(false);
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /*
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * for native call
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
81f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    @SuppressWarnings("unused")
82f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    private DatagramChannelImpl() {
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(SelectorProvider.provider());
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fd = new FileDescriptor();
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        connectAddress = new InetSocketAddress(0);
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /*
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Getting the internal DatagramSocket If we have not the socket, we create
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * a new one.
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    synchronized public DatagramSocket socket() {
94b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes        if (socket == null) {
954e4000ed98f9056639fba0713a3fd3caacf9746cElliott Hughes            socket = new DatagramSocketAdapter(new PlainDatagramSocketImpl(fd, localPort), this);
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return socket;
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1010a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes     * Returns the local address to which the socket is bound.
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    InetAddress getLocalAddress() {
1040b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes        return IoBridge.getSocketLocalAddress(fd);
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
107f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    /**
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see java.nio.channels.DatagramChannel#isConnected()
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    synchronized public boolean isConnected() {
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return connected;
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
115f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    /**
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see java.nio.channels.DatagramChannel#connect(java.net.SocketAddress)
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1194e4000ed98f9056639fba0713a3fd3caacf9746cElliott Hughes    synchronized public DatagramChannel connect(SocketAddress address) throws IOException {
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // must open
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        checkOpen();
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // status must be un-connected.
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (connected) {
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalStateException();
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // check the address
1284e4000ed98f9056639fba0713a3fd3caacf9746cElliott Hughes        InetSocketAddress inetSocketAddress = SocketChannelImpl.validateAddress(address);
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            begin();
1310b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes            IoBridge.connect(fd, inetSocketAddress.getAddress(), inetSocketAddress.getPort());
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (ConnectException e) {
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // ConnectException means connect fail, not exception
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } finally {
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            end(true);
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // set the connected address.
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        connectAddress = inetSocketAddress;
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        connected = true;
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isBound = true;
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return this;
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
145f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    /**
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see java.nio.channels.DatagramChannel#disconnect()
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    synchronized public DatagramChannel disconnect() throws IOException {
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isConnected() || !isOpen()) {
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return this;
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        connected = false;
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        connectAddress = null;
15532b0fa4d1a31ef07bc4297c615f0fe50e9aa7c21Elliott Hughes        try {
15632b0fa4d1a31ef07bc4297c615f0fe50e9aa7c21Elliott Hughes            Libcore.os.connect(fd, InetAddress.UNSPECIFIED, 0);
15732b0fa4d1a31ef07bc4297c615f0fe50e9aa7c21Elliott Hughes        } catch (ErrnoException errnoException) {
15832b0fa4d1a31ef07bc4297c615f0fe50e9aa7c21Elliott Hughes            throw errnoException.rethrowAsIOException();
15932b0fa4d1a31ef07bc4297c615f0fe50e9aa7c21Elliott Hughes        }
160b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes        if (socket != null) {
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            socket.disconnect();
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return this;
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public SocketAddress receive(ByteBuffer target) throws IOException {
168e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes        target.checkWritable();
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        checkOpen();
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isBound) {
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null;
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SocketAddress retAddr = null;
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            begin();
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // receive real data packet, (not peek)
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            synchronized (readLock) {
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                boolean loop = isBlocking();
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (!target.isDirect()) {
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    retAddr = receiveImpl(target, loop);
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    retAddr = receiveDirectImpl(target, loop);
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (InterruptedIOException e) {
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // this line used in Linux
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null;
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } finally {
192b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes            end(retAddr != null);
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return retAddr;
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
196eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson
19779ff4e73fd689dae6667a8137ee57137962ff13aElliott Hughes    private SocketAddress receiveImpl(ByteBuffer target, boolean loop) throws IOException {
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SocketAddress retAddr = null;
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        DatagramPacket receivePacket;
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int oldposition = target.position();
201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int received = 0;
20223ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes        // TODO: disallow mapped buffers and lose this conditional?
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (target.hasArray()) {
20423ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes            receivePacket = new DatagramPacket(target.array(), target.position() + target.arrayOffset(), target.remaining());
205eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson        } else {
20623ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes            receivePacket = new DatagramPacket(new byte[target.remaining()], target.remaining());
207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        do {
2090b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes            received = IoBridge.recvfrom(false, fd, receivePacket.getData(), receivePacket.getOffset(), receivePacket.getLength(), 0, receivePacket, isConnected());
210b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes            if (receivePacket != null && receivePacket.getAddress() != null) {
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (received > 0) {
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (target.hasArray()) {
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        target.position(oldposition + received);
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    } else {
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        // copy the data of received packet
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        target.put(receivePacket.getData(), 0, received);
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                retAddr = receivePacket.getSocketAddress();
220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } while (loop);
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return retAddr;
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
225eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson
22679ff4e73fd689dae6667a8137ee57137962ff13aElliott Hughes    private SocketAddress receiveDirectImpl(ByteBuffer target, boolean loop) throws IOException {
227f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        SocketAddress retAddr = null;
228693eacca9fa67ad79d1b35dbaad61c5ac1ac457cElliott Hughes        DatagramPacket receivePacket = new DatagramPacket(EmptyArray.BYTE, 0);
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int oldposition = target.position();
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int received = 0;
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        do {
2320b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes            received = IoBridge.recvfrom(false, fd, target, 0, receivePacket, isConnected());
233b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes            if (receivePacket != null && receivePacket.getAddress() != null) {
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // copy the data of received packet
235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (received > 0) {
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    target.position(oldposition + received);
237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                retAddr = receivePacket.getSocketAddress();
239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } while (loop);
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return retAddr;
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
2464e4000ed98f9056639fba0713a3fd3caacf9746cElliott Hughes    public int send(ByteBuffer source, SocketAddress socketAddress) throws IOException {
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        checkNotNull(source);
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        checkOpen();
249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        InetSocketAddress isa = (InetSocketAddress) socketAddress;
251b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes        if (isa.getAddress() == null) {
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IOException();
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
255ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes        if (isConnected() && !connectAddress.equals(isa)) {
256ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes            throw new IllegalArgumentException();
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
25990d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes        synchronized (writeLock) {
26090d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes            int sendCount = 0;
26190d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes            try {
26290d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes                begin();
26390d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes                int oldPosition = source.position();
2640b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes                sendCount = IoBridge.sendto(fd, source, 0, isa.getAddress(), isa.getPort());
265a28bc96d63595a77fa918da8ccdda50e9eaae95eElliott Hughes                if (sendCount > 0) {
266a28bc96d63595a77fa918da8ccdda50e9eaae95eElliott Hughes                    source.position(oldPosition + sendCount);
267a28bc96d63595a77fa918da8ccdda50e9eaae95eElliott Hughes                }
26890d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes            } finally {
26990d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes                end(sendCount >= 0);
270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return sendCount;
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int read(ByteBuffer target) throws IOException {
277e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes        target.checkWritable();
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        checkOpenConnected();
279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!target.hasRemaining()) {
281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return 0;
282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
284f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        int readCount = 0;
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (target.isDirect() || target.hasArray()) {
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            readCount = readImpl(target);
287f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            if (readCount > 0) {
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                target.position(target.position() + readCount);
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            byte[] readArray = new byte[target.remaining()];
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            ByteBuffer readBuffer = ByteBuffer.wrap(readArray);
294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            readCount = readImpl(readBuffer);
295f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            if (readCount > 0) {
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                target.put(readArray, 0, readCount);
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return readCount;
300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
3032620ff9a08ce7fc6d66b60784b1eecd78eb001baElliott Hughes    public long read(ByteBuffer[] targets, int offset, int length) throws IOException {
304a1603838fe9e865575c87982e32c6343740e464cElliott Hughes        Arrays.checkOffsetAndCount(targets.length, offset, length);
305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // status must be open and connected
307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        checkOpenConnected();
3082620ff9a08ce7fc6d66b60784b1eecd78eb001baElliott Hughes        int totalCount = FileChannelImpl.calculateTotalRemaining(targets, offset, length, true);
3092620ff9a08ce7fc6d66b60784b1eecd78eb001baElliott Hughes        if (totalCount == 0) {
3102620ff9a08ce7fc6d66b60784b1eecd78eb001baElliott Hughes            return 0;
311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // read data to readBuffer, and then transfer data from readBuffer to
314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // targets.
315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        ByteBuffer readBuffer = ByteBuffer.allocate(totalCount);
316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int readCount;
317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        readCount = readImpl(readBuffer);
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int left = readCount;
319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int index = offset;
320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // transfer data from readBuffer to targets
321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        byte[] readArray = readBuffer.array();
322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while (left > 0) {
323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int putLength = Math.min(targets[index].remaining(), left);
324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            targets[index].put(readArray, readCount - left, putLength);
325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            index++;
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            left -= putLength;
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return readCount;
329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /*
332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * read from channel, and store the result in the target.
333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
33423ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes    private int readImpl(ByteBuffer dst) throws IOException {
335f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        synchronized (readLock) {
336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int readCount = 0;
337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            try {
338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                begin();
3390b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes                readCount = IoBridge.recvfrom(false, fd, dst, 0, null, isConnected());
340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } catch (InterruptedIOException e) {
341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // InterruptedIOException will be thrown when timeout.
342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return 0;
343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } finally {
344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                end(readCount > 0);
345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
34623ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes            return readCount;
347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
35023ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes    @Override public int write(ByteBuffer src) throws IOException {
35123ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes        checkNotNull(src);
352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        checkOpenConnected();
35323ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes        if (!src.hasRemaining()) {
354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return 0;
355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
35723ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes        int writeCount = writeImpl(src);
358a28bc96d63595a77fa918da8ccdda50e9eaae95eElliott Hughes        if (writeCount > 0) {
359a28bc96d63595a77fa918da8ccdda50e9eaae95eElliott Hughes            src.position(src.position() + writeCount);
360a28bc96d63595a77fa918da8ccdda50e9eaae95eElliott Hughes        }
36123ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes        return writeCount;
362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
364f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    /**
365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see java.nio.channels.DatagramChannel#write(java.nio.ByteBuffer[], int,
366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *      int)
367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
3692620ff9a08ce7fc6d66b60784b1eecd78eb001baElliott Hughes    public long write(ByteBuffer[] sources, int offset, int length) throws IOException {
370a1603838fe9e865575c87982e32c6343740e464cElliott Hughes        Arrays.checkOffsetAndCount(sources.length, offset, length);
371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // status must be open and connected
373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        checkOpenConnected();
3742620ff9a08ce7fc6d66b60784b1eecd78eb001baElliott Hughes        int count = FileChannelImpl.calculateTotalRemaining(sources, offset, length, false);
3752620ff9a08ce7fc6d66b60784b1eecd78eb001baElliott Hughes        if (count == 0) {
376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return 0;
377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        ByteBuffer writeBuf = ByteBuffer.allocate(count);
379f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        for (int val = offset; val < length + offset; val++) {
380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            ByteBuffer source = sources[val];
381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int oldPosition = source.position();
382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            writeBuf.put(source);
383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            source.position(oldPosition);
384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writeBuf.flip();
386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int result = writeImpl(writeBuf);
387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int val = offset;
388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int written = result;
389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while (result > 0) {
390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            ByteBuffer source = sources[val];
391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int gap = Math.min(result, source.remaining());
392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            source.position(source.position() + gap);
393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            val++;
394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            result -= gap;
395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return written;
397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int writeImpl(ByteBuffer buf) throws IOException {
400f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        synchronized (writeLock) {
401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int result = 0;
402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            try {
403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                begin();
4040b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes                result = IoBridge.sendto(fd, buf, 0, null, 0);
405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } finally {
406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                end(result > 0);
407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
40890d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes            return result;
409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
41290d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes    @Override protected synchronized void implCloseSelectableChannel() throws IOException {
413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        connected = false;
414c6e0981e5a2d23a0758ed71a8086c4278a7832efJesse Wilson        if (socket != null && !socket.isClosed()) {
415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            socket.close();
416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
4170b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes            IoBridge.closeSocket(fd);
418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
421a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes    @Override protected void implConfigureBlocking(boolean blocking) throws IOException {
422a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes        synchronized (blockingLock()) {
423a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes            IoUtils.setBlocking(fd, blocking);
424a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes        }
425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /*
428f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * Status check, must be open.
429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void checkOpen() throws IOException {
431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isOpen()) {
432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new ClosedChannelException();
433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /*
437f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * Status check, must be open and connected, for read and write.
438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void checkOpenConnected() throws IOException {
440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        checkOpen();
441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isConnected()) {
442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new NotYetConnectedException();
443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /*
447f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * Buffer check, must not null
448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void checkNotNull(ByteBuffer source) {
450b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes        if (source == null) {
45186acc043d3334651ee26c65467d78d6cefedd397Kenny Root            throw new NullPointerException("source == null");
452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /*
456f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * Get the fd for internal use.
457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public FileDescriptor getFD() {
459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return fd;
460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /*
463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The adapter class of DatagramSocket
464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static class DatagramSocketAdapter extends DatagramSocket {
466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /*
468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * The internal datagramChannelImpl.
469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private DatagramChannelImpl channelImpl;
471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /*
473f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson         * Constructor initialize the datagramSocketImpl and datagramChannelImpl
474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        DatagramSocketAdapter(DatagramSocketImpl socketimpl,
476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                DatagramChannelImpl channelImpl) {
477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            super(socketimpl);
478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            this.channelImpl = channelImpl;
479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /*
482f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson         * Get the internal datagramChannelImpl
483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        @Override
485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public DatagramChannel getChannel() {
486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return channelImpl;
487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
489f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        /**
490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @see java.net.DatagramSocket#isBound()
491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        @Override
493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public boolean isBound() {
494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return channelImpl.isBound;
495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
497f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        /**
498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @see java.net.DatagramSocket#isConnected()
499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        @Override
501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public boolean isConnected() {
502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return channelImpl.isConnected();
503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
505f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        /**
506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @see java.net.DatagramSocket#getInetAddress()
507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        @Override
509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public InetAddress getInetAddress() {
510b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes            if (channelImpl.connectAddress == null) {
511adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return null;
512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return channelImpl.connectAddress.getAddress();
514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
516f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        /**
517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @see java.net.DatagramSocket#getLocalAddress()
518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        @Override
520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public InetAddress getLocalAddress() {
521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return channelImpl.getLocalAddress();
522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
524f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        /**
525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @see java.net.DatagramSocket#getPort()
526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        @Override
528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public int getPort() {
529b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes            if (channelImpl.connectAddress == null) {
530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return -1;
531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return channelImpl.connectAddress.getPort();
533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
535f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        /**
536adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @see java.net.DatagramSocket#bind(java.net.SocketAddress)
537adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        @Override
539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public void bind(SocketAddress localAddr) throws SocketException {
540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (channelImpl.isConnected()) {
541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new AlreadyConnectedException();
542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            super.bind(localAddr);
544adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            channelImpl.isBound = true;
545adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
546adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
547f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        /**
548adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @see java.net.DatagramSocket#receive(java.net.DatagramPacket)
549adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        @Override
551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public void receive(DatagramPacket packet) throws IOException {
552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!channelImpl.isBlocking()) {
553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalBlockingModeException();
554adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            super.receive(packet);
556adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
558f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        /**
559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @see java.net.DatagramSocket#send(java.net.DatagramPacket)
560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        @Override
562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public void send(DatagramPacket packet) throws IOException {
563adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!channelImpl.isBlocking()) {
564adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalBlockingModeException();
565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            super.send(packet);
567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
569f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        /**
570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @see java.net.DatagramSocket#close()
571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        @Override
573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public void close() {
574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            synchronized (channelImpl) {
575adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (channelImpl.isOpen()) {
576adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    try {
577adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        channelImpl.close();
578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    } catch (IOException e) {
579adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        // Ignore
580adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
581adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
582adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                super.close();
583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
586f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        /**
587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @see java.net.DatagramSocket#disconnect()
588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
589adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        @Override
590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public void disconnect() {
591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            try {
592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                channelImpl.disconnect();
593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } catch (IOException e) {
594adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // Ignore
595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
596adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            super.disconnect();
597adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
598adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
600