1 /* 2 * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* @test 25 * @bug 8053479 26 * @run main Truncate 27 * @summary Test DatagramChannel receive/read where there are fewer bytes remaining 28 * in the buffer than are required to hold the datagram. The remainder of the 29 * datagram should be silently discarded. 30 */ 31 32 import java.io.IOException; 33 import java.net.InetAddress; 34 import java.net.InetSocketAddress; 35 import java.net.SocketAddress; 36 import java.nio.ByteBuffer; 37 import java.nio.channels.DatagramChannel; 38 import java.util.Arrays; 39 import java.util.stream.IntStream; 40 41 public class Truncate { 42 static final int LARGE_SIZE = 1000; 43 static final int SMALL_SIZE = 100; 44 45 public static void main(String[] args) throws Exception { 46 try (DatagramChannel dc = DatagramChannel.open()) { 47 dc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); 48 49 // not connected 50 testReceiveDiscards(dc); 51 52 // connected 53 dc.connect(dc.getLocalAddress()); 54 testReceiveDiscards(dc); 55 testReadDiscards(dc); 56 testScatteringReadDiscards(dc); 57 } 58 } 59 60 /** 61 * Receive a datagram with a buffer that has fewer bytes remaining than are 62 * required to hold the datagram. 63 */ 64 static void testReceiveDiscards(DatagramChannel dc) throws IOException { 65 ByteBuffer largeBuffer = send(dc, LARGE_SIZE, dc.getLocalAddress()); 66 67 ByteBuffer smallBuffer = ByteBuffer.allocate(SMALL_SIZE); 68 SocketAddress sender = dc.receive(smallBuffer); 69 assertTrue(sender.equals(dc.getLocalAddress())); 70 71 // check buffer/contents 72 smallBuffer.flip(); 73 assertTrue(smallBuffer.remaining() == SMALL_SIZE); 74 assertTrue(Arrays.equals(smallBuffer.array(), 0, SMALL_SIZE, 75 largeBuffer.array(), 0, SMALL_SIZE)); 76 } 77 78 /** 79 * Read a datagram with a buffer that has fewer bytes remaining than are 80 * required to hold the datagram. 81 */ 82 static void testReadDiscards(DatagramChannel dc) throws IOException { 83 ByteBuffer largeBuffer = send(dc, LARGE_SIZE, dc.getRemoteAddress()); 84 85 ByteBuffer smallBuffer = ByteBuffer.allocate(SMALL_SIZE); 86 int n = dc.read(smallBuffer); 87 assertTrue(n == SMALL_SIZE); 88 89 // check buffer/contents 90 smallBuffer.flip(); 91 assertTrue(smallBuffer.remaining() == SMALL_SIZE); 92 assertTrue(Arrays.equals(smallBuffer.array(), 0, SMALL_SIZE, 93 largeBuffer.array(), 0, SMALL_SIZE)); 94 } 95 96 /** 97 * Read a datagram with an array of buffers that have fewer bytes remaining 98 * than are required to hold the datagram. 99 */ 100 static void testScatteringReadDiscards(DatagramChannel dc) throws IOException { 101 ByteBuffer largeBuffer = send(dc, LARGE_SIZE, dc.getRemoteAddress()); 102 103 ByteBuffer smallBuffer1 = ByteBuffer.allocate(SMALL_SIZE); 104 ByteBuffer smallBuffer2 = ByteBuffer.allocate(SMALL_SIZE); 105 ByteBuffer[] bufs = new ByteBuffer[] { smallBuffer1, smallBuffer2 }; 106 long n = dc.read(bufs); 107 assertTrue(n == (SMALL_SIZE * bufs.length)); 108 109 // check buffer/contents 110 smallBuffer1.flip(); 111 assertTrue(smallBuffer1.remaining() == SMALL_SIZE); 112 assertTrue(Arrays.equals(smallBuffer1.array(), 0, SMALL_SIZE, 113 largeBuffer.array(), 0, SMALL_SIZE)); 114 smallBuffer2.flip(); 115 assertTrue(smallBuffer2.remaining() == SMALL_SIZE); 116 assertTrue(Arrays.equals(smallBuffer2.array(), 0, SMALL_SIZE, 117 largeBuffer.array(), SMALL_SIZE, SMALL_SIZE << 1)); 118 } 119 120 /** 121 * Send a datagram of the given size to the given target address. 122 * @return the buffer with the datagram sent to the target address 123 */ 124 static ByteBuffer send(DatagramChannel dc, int size, SocketAddress target) 125 throws IOException 126 { 127 ByteBuffer buffer = ByteBuffer.allocate(size); 128 IntStream.range(0, size).forEach(i -> buffer.put((byte)i)); 129 buffer.flip(); 130 131 int n = dc.send(buffer, target); 132 assertTrue(n == size); 133 buffer.flip(); 134 return buffer; 135 } 136 137 static void assertTrue(boolean e) { 138 if (!e) throw new RuntimeException(); 139 } 140 }