datagramsocketimpl-branch: fix issue with receive packet buf size datagramsocketimpl-branch
authorchegar
Fri, 18 Oct 2019 17:08:59 +0100
branchdatagramsocketimpl-branch
changeset 58688 2b1e684c3ce6
parent 58680 7e9e2f10a050
child 58697 e3ff12d14d43
datagramsocketimpl-branch: fix issue with receive packet buf size
src/java.base/share/classes/java/net/DatagramPacket.java
src/java.base/share/classes/jdk/internal/access/JavaNetDatagramPacketAccess.java
src/java.base/share/classes/jdk/internal/access/SharedSecrets.java
src/java.base/share/classes/sun/nio/ch/NioDatagramSocketImpl.java
test/jdk/java/net/DatagramPacket/ReuseBuf.java
--- a/src/java.base/share/classes/java/net/DatagramPacket.java	Thu Oct 17 21:15:33 2019 +0100
+++ b/src/java.base/share/classes/java/net/DatagramPacket.java	Fri Oct 18 17:08:59 2019 +0100
@@ -25,6 +25,9 @@
 
 package java.net;
 
+import jdk.internal.access.JavaNetDatagramPacketAccess;
+import jdk.internal.access.SharedSecrets;
+
 /**
  * This class represents a datagram packet.
  * <p>
@@ -367,12 +370,36 @@
      * @since 1.1
      */
     public synchronized void setLength(int length) {
+        setLengthField(length);
+        this.bufLength = this.length;
+    }
+
+    private synchronized void setLengthField(int length) {
         if ((length + offset) > buf.length || length < 0 ||
-            (length + offset) < 0) {
+                (length + offset) < 0) {
             throw new IllegalArgumentException("illegal length");
         }
         this.length = length;
-        this.bufLength = this.length;
+    }
+
+    private synchronized int getBufLength() {
+        return bufLength;
+    }
+
+    static {
+        SharedSecrets.setJavaNetDatagrtamPacketAccess(
+            new JavaNetDatagramPacketAccess() {
+                @Override
+                public int getBufLengthField(DatagramPacket packet) {
+                    return packet.getBufLength();
+                }
+
+                @Override
+                public void setLengthField(DatagramPacket packet, int length) {
+                    packet.setLengthField(length);
+                }
+            }
+        );
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/access/JavaNetDatagramPacketAccess.java	Fri Oct 18 17:08:59 2019 +0100
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.access;
+
+import java.net.DatagramPacket;
+
+public interface JavaNetDatagramPacketAccess {
+    int getBufLengthField(DatagramPacket packet);
+    void setLengthField(DatagramPacket packet, int length);
+}
--- a/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java	Thu Oct 17 21:15:33 2019 +0100
+++ b/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java	Fri Oct 18 17:08:59 2019 +0100
@@ -64,6 +64,7 @@
     private static JavaIORandomAccessFileAccess javaIORandomAccessFileAccess;
     private static JavaObjectInputStreamAccess javaObjectInputStreamAccess;
     private static JavaObjectInputFilterAccess javaObjectInputFilterAccess;
+    private static JavaNetDatagramPacketAccess javaNetDatagramPacketAccess;
     private static JavaNetInetAddressAccess javaNetInetAddressAccess;
     private static JavaNetHttpCookieAccess javaNetHttpCookieAccess;
     private static JavaNetUriAccess javaNetUriAccess;
@@ -138,6 +139,16 @@
         return javaLangReflectAccess;
     }
 
+    public static void setJavaNetDatagrtamPacketAccess(JavaNetDatagramPacketAccess jndpa) {
+        javaNetDatagramPacketAccess = jndpa;
+    }
+
+    public static JavaNetDatagramPacketAccess getJavaNetDatagramPacketAccess() {
+        if (javaNetDatagramPacketAccess == null)
+            unsafe.ensureClassInitialized(java.net.DatagramPacket.class);
+        return javaNetDatagramPacketAccess;
+    }
+
     public static void setJavaNetUriAccess(JavaNetUriAccess jnua) {
         javaNetUriAccess = jnua;
     }
--- a/src/java.base/share/classes/sun/nio/ch/NioDatagramSocketImpl.java	Thu Oct 17 21:15:33 2019 +0100
+++ b/src/java.base/share/classes/sun/nio/ch/NioDatagramSocketImpl.java	Fri Oct 18 17:08:59 2019 +0100
@@ -48,6 +48,8 @@
 import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.locks.ReentrantLock;
+import jdk.internal.access.JavaNetDatagramPacketAccess;
+import jdk.internal.access.SharedSecrets;
 import jdk.internal.ref.CleanerFactory;
 import sun.net.PlatformDatagramSocketImpl;
 import sun.net.ResourceManager;
@@ -65,6 +67,9 @@
 
     private static final NativeDispatcher nd = new SocketDispatcher();
 
+    private static final JavaNetDatagramPacketAccess DATAGRAM_PACKET_ACCESS =
+            SharedSecrets.getJavaNetDatagramPacketAccess();
+
     private static final int MAX_PACKET_LEN = 65536;
 
     private static final ProtocolFamily family = family();
@@ -410,7 +415,7 @@
         Objects.requireNonNull(p);
         byte[] b = p.getData();
         int off = p.getOffset();
-        int len = b.length - off;
+        int len = DATAGRAM_PACKET_ACCESS.getBufLengthField(p);
         assert len >= 0;
         if (len > MAX_PACKET_LEN)
             len = MAX_PACKET_LEN;
@@ -441,7 +446,7 @@
                     p.setAddress(sender.getAddress());
                 if (p.getPort() != sender.getPort())
                     p.setPort(sender.getPort());
-                p.setLength(n);
+                DATAGRAM_PACKET_ACCESS.setLengthField(p, n);
             } catch (IOException e) {
                 // #### reset packet offset and length! ??
                 throw e;
--- a/test/jdk/java/net/DatagramPacket/ReuseBuf.java	Thu Oct 17 21:15:33 2019 +0100
+++ b/test/jdk/java/net/DatagramPacket/ReuseBuf.java	Fri Oct 18 17:08:59 2019 +0100
@@ -21,14 +21,16 @@
  * questions.
  */
 
-/**
+/*
  * @test
- *
  * @bug 4424096
- *
  * @summary DatagramPacket spec needs clarification (reuse buf)
+ * @run main ReuseBuf
+ * @run main/othervm -Djava.net.preferIPv4Stack=true ReuseBuf
+ * @run main/othervm -Djdk.net.usePlainDatagramSocketImpl=true ReuseBuf
  */
 import java.net.*;
+import static java.lang.System.out;
 
 public class ReuseBuf {
     static String msgs[] = {"Hello World", "Java", "Good Bye"};
@@ -54,8 +56,12 @@
                 try {
                     ds.receive(dp);
                     String reply = new String(dp.getData(), dp.getOffset(), dp.getLength());
-                    ds.send(new DatagramPacket(reply.getBytes(),reply.length(),
-                                               dp.getAddress(),dp.getPort()));
+                    out.println("server: received [" + reply + "]");
+                    for (int i=0; i<2; i++) {
+                        out.println("server: sending [" + reply + "]");
+                        ds.send(new DatagramPacket(reply.getBytes(), reply.length(),
+                                dp.getAddress(), dp.getPort()));
+                    }
                     if (reply.equals(msgs[msgs.length-1])) {
                         break;
                     }
@@ -76,16 +82,32 @@
         byte b[] = new byte[100];
         DatagramPacket dp = new DatagramPacket(b,b.length);
         for (int i = 0; i < msgs.length; i++) {
+            out.println("client: sending [" + msgs[i] + "]");
             ds.send(new DatagramPacket(msgs[i].getBytes(),msgs[i].length(),
                                        InetAddress.getLocalHost(),
                                        port));
             ds.receive(dp);
-            if (!msgs[i].equals(new String(dp.getData(), dp.getOffset(), dp.getLength()))) {
-                throw new RuntimeException("Msg expected: "+msgs[i] +msgs[i].length()+
-                                           "msg received: "+new String(dp.getData(), dp.getOffset(), dp.getLength())+dp.getLength());
+            String recvmsg = new String(dp.getData(), dp.getOffset(), dp.getLength());
+            out.println("client: received [" + recvmsg + "]");
+            if (!msgs[i].equals(recvmsg)) {
+                throw new RuntimeException("Msg expected: " + msgs[i] +
+                                           ", msg received: " + recvmsg);
+            }
+
+            byte ba[] = new byte[1];
+            DatagramPacket dp2 = new DatagramPacket(ba, ba.length);
+            dp2.setData(new byte[99], 5, 3);  // only 3 bytes
+            ds.receive(dp2);
+            String expectedMsg = msgs[i].substring(0, 3);
+            recvmsg = new String(dp2.getData(), dp2.getOffset(), dp2.getLength());
+            out.println("client: received [" + recvmsg + "]");
+            if (!expectedMsg.equals(recvmsg)) {
+                throw new RuntimeException("Msg truncated expected: " + expectedMsg +
+                                            ", msg received: "+ recvmsg);
             }
         }
         ds.close();
-        System.out.println("Test Passed!!!");
+        out.println("Test Passed!!!");
+        st.join();
     }
 }