1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package libcore.java.nio.channels; 18 19import java.io.IOException; 20import java.net.BindException; 21import java.net.DatagramSocket; 22import java.net.Inet4Address; 23import java.net.Inet6Address; 24import java.net.InetAddress; 25import java.net.InetSocketAddress; 26import java.net.NetworkInterface; 27import java.net.ProtocolFamily; 28import java.net.StandardProtocolFamily; 29import java.net.StandardSocketOptions; 30import java.nio.ByteBuffer; 31import java.nio.channels.AlreadyBoundException; 32import java.nio.channels.ClosedChannelException; 33import java.nio.channels.DatagramChannel; 34import java.nio.channels.UnsupportedAddressTypeException; 35import java.nio.channels.spi.SelectorProvider; 36import java.util.Enumeration; 37 38public class DatagramChannelTest extends junit.framework.TestCase { 39 public void test_read_intoReadOnlyByteArrays() throws Exception { 40 ByteBuffer readOnly = ByteBuffer.allocate(1).asReadOnlyBuffer(); 41 DatagramSocket ds = new DatagramSocket(0); 42 DatagramChannel dc = DatagramChannel.open(); 43 dc.connect(ds.getLocalSocketAddress()); 44 try { 45 dc.read(readOnly); 46 fail(); 47 } catch (IllegalArgumentException expected) { 48 } 49 try { 50 dc.read(new ByteBuffer[] { readOnly }); 51 fail(); 52 } catch (IllegalArgumentException expected) { 53 } 54 try { 55 dc.read(new ByteBuffer[] { readOnly }, 0, 1); 56 fail(); 57 } catch (IllegalArgumentException expected) { 58 } 59 } 60 61 // http://code.google.com/p/android/issues/detail?id=16579 62 public void testNonBlockingRecv() throws Exception { 63 DatagramChannel dc = DatagramChannel.open(); 64 try { 65 dc.configureBlocking(false); 66 dc.socket().bind(null); 67 // Should return immediately, since we're non-blocking. 68 assertNull(dc.receive(ByteBuffer.allocate(2048))); 69 } finally { 70 dc.close(); 71 } 72 } 73 74 public void testInitialState() throws Exception { 75 DatagramChannel dc = DatagramChannel.open(); 76 try { 77 DatagramSocket socket = dc.socket(); 78 assertFalse(socket.isBound()); 79 assertFalse(socket.getBroadcast()); 80 assertFalse(socket.isClosed()); 81 assertFalse(socket.isConnected()); 82 assertEquals(0, socket.getLocalPort()); 83 assertTrue(socket.getLocalAddress().isAnyLocalAddress()); 84 assertNull(socket.getLocalSocketAddress()); 85 assertNull(socket.getInetAddress()); 86 assertEquals(-1, socket.getPort()); 87 assertNull(socket.getRemoteSocketAddress()); 88 assertFalse(socket.getReuseAddress()); 89 90 assertSame(dc, socket.getChannel()); 91 } finally { 92 dc.close(); 93 } 94 } 95 96 public void test_bind_unresolvedAddress() throws IOException { 97 DatagramChannel dc = DatagramChannel.open(); 98 try { 99 dc.socket().bind(new InetSocketAddress("unresolvedname", 31415)); 100 fail(); 101 } catch (IOException expected) { 102 } 103 104 assertTrue(dc.isOpen()); 105 assertFalse(dc.isConnected()); 106 107 dc.close(); 108 } 109 110 public void test_bind_any_IPv4() throws Exception { 111 test_bind_any(InetAddress.getByName("0.0.0.0")); 112 } 113 114 public void test_bind_any_IPv6() throws Exception { 115 test_bind_any(InetAddress.getByName("::")); 116 } 117 118 private void test_bind_any(InetAddress bindAddress) throws Exception { 119 DatagramChannel dc = DatagramChannel.open(); 120 dc.socket().bind(new InetSocketAddress(bindAddress, 0)); 121 122 assertTrue(dc.isOpen()); 123 assertFalse(dc.isConnected()); 124 125 InetSocketAddress actualAddress = (InetSocketAddress) dc.socket().getLocalSocketAddress(); 126 assertTrue(actualAddress.getAddress().isAnyLocalAddress()); 127 assertTrue(actualAddress.getPort() > 0); 128 129 dc.close(); 130 } 131 132 public void test_bind_loopback_IPv4() throws Exception { 133 test_bind(InetAddress.getByName("127.0.0.1")); 134 } 135 136 public void test_bind_loopback_IPv6() throws Exception { 137 test_bind(InetAddress.getByName("::1")); 138 } 139 140 public void test_bind_IPv4() throws Exception { 141 InetAddress bindAddress = getNonLoopbackNetworkInterfaceAddress(true /* ipv4 */); 142 test_bind(bindAddress); 143 } 144 145 public void test_bind_IPv6() throws Exception { 146 InetAddress bindAddress = getNonLoopbackNetworkInterfaceAddress(false /* ipv4 */); 147 test_bind(bindAddress); 148 } 149 150 private void test_bind(InetAddress bindAddress) throws IOException { 151 DatagramChannel dc = DatagramChannel.open(); 152 dc.socket().bind(new InetSocketAddress(bindAddress, 0)); 153 154 InetSocketAddress actualAddress = (InetSocketAddress) dc.socket().getLocalSocketAddress(); 155 assertEquals(bindAddress, actualAddress.getAddress()); 156 assertTrue(actualAddress.getPort() > 0); 157 158 dc.close(); 159 } 160 161 public void test_setOption() throws Exception { 162 DatagramChannel dc = DatagramChannel.open(); 163 // There were problems in the past as the number used here was below the minimum for 164 // some platforms (b/27821554). It was increased from 1024 to 4096. 165 dc.setOption(StandardSocketOptions.SO_SNDBUF, 4096); 166 167 // Assert that we can read back the option from the channel... 168 assertEquals(4096, (int) dc.getOption(StandardSocketOptions.SO_SNDBUF)); 169 // ... and its socket adaptor. 170 assertEquals(4096, dc.socket().getSendBufferSize()); 171 172 dc.close(); 173 try { 174 dc.setOption(StandardSocketOptions.SO_SNDBUF, 4096); 175 fail(); 176 } catch (ClosedChannelException expected) { 177 } 178 } 179 180 // http://b/26292854 181 public void test_getFileDescriptor() throws Exception { 182 DatagramSocket socket = DatagramChannel.open().socket(); 183 socket.getReuseAddress(); 184 assertNotNull(socket.getFileDescriptor$()); 185 } 186 187 public void test_bind() throws IOException { 188 InetSocketAddress socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK, 0); 189 DatagramChannel channel = DatagramChannel.open(); 190 channel.bind(socketAddress); 191 assertEquals(socketAddress.getAddress(), 192 ((InetSocketAddress)(channel.getLocalAddress())).getAddress()); 193 assertTrue(((InetSocketAddress)(channel.getLocalAddress())).getPort() > 0); 194 195 try { 196 channel.bind(socketAddress); 197 fail(); 198 } catch (AlreadyBoundException expected) { 199 } 200 201 socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK, 202 ((InetSocketAddress)(channel.getLocalAddress())).getPort()); 203 try { 204 DatagramChannel.open().bind(socketAddress); 205 fail(); 206 } catch (BindException expected) {} 207 208 channel.close(); 209 socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK, 0); 210 try { 211 channel.bind(socketAddress); 212 } catch (ClosedChannelException expected) {} 213 } 214 215 public void test_getRemoteAddress() throws IOException { 216 InetSocketAddress socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK, 0); 217 DatagramChannel clientChannel = DatagramChannel.open(); 218 DatagramChannel serverChannel = DatagramChannel.open(); 219 serverChannel.bind(socketAddress); 220 221 assertNull(clientChannel.getRemoteAddress()); 222 223 clientChannel.connect(serverChannel.getLocalAddress()); 224 assertEquals(socketAddress.getAddress(), 225 ((InetSocketAddress)(clientChannel.getRemoteAddress())).getAddress()); 226 assertEquals(((InetSocketAddress)(serverChannel.getLocalAddress())).getPort(), 227 ((InetSocketAddress)(clientChannel.getRemoteAddress())).getPort()); 228 } 229 230 public void test_open$java_net_ProtocolFamily() throws IOException { 231 DatagramChannel channel = DatagramChannel.open(StandardProtocolFamily.INET); 232 233 channel.bind(new InetSocketAddress(Inet4Address.LOOPBACK, 0)); 234 assertEquals(SelectorProvider.provider(), channel.provider()); 235 236 try { 237 // Should not support IPv6 Address 238 // InetSocketAddress(int) returns IPv6 ANY address 239 DatagramChannel.open(StandardProtocolFamily.INET).bind(new InetSocketAddress(0)); 240 fail(); 241 } catch (UnsupportedAddressTypeException expected) {} 242 243 DatagramChannel.open(StandardProtocolFamily.INET6).bind(new InetSocketAddress(0)); 244 245 try { 246 DatagramChannel.open(MockProtocolFamily.MOCK); 247 fail(); 248 } catch (UnsupportedOperationException expected) {} 249 250 try { 251 DatagramChannel.open(null); 252 fail(); 253 } catch (NullPointerException expected) {} 254 } 255 256 private static InetAddress getNonLoopbackNetworkInterfaceAddress(boolean ipv4) throws IOException { 257 Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces(); 258 while (networkInterfaces.hasMoreElements()) { 259 NetworkInterface networkInterface = networkInterfaces.nextElement(); 260 if (networkInterface.isLoopback() || !networkInterface.isUp()) { 261 continue; 262 } 263 Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses(); 264 while (inetAddresses.hasMoreElements()) { 265 InetAddress inetAddress = inetAddresses.nextElement(); 266 if ( (ipv4 && inetAddress instanceof Inet4Address) 267 || (!ipv4 && inetAddress instanceof Inet6Address)) { 268 return inetAddress; 269 } 270 } 271 } 272 return null; 273 } 274 275 enum MockProtocolFamily implements ProtocolFamily { 276 MOCK, 277 } 278} 279