RFR: JDK-8184770: JDWP support for IPv6
Alex Menkov
alexey.menkov at oracle.com
Fri Apr 12 23:58:17 UTC 2019
updated webrev:
http://cr.openjdk.java.net/~amenkov/IPv6/webrev.03/
changes (vs webrev.02) are non-functional (added/edited comments, code
reformatting, renaming convertIpv4ToIpv6 function to convertIPv4ToIPv6,
renaming env variable to jniEnv (env is already used in one of the
functions)).
About pass/preferredAddressFamily conditions - there is no "logical xor"
in C/C++. Also I think that the current condition is clearer.
--alex
On 04/11/2019 17:18, serguei.spitsyn at oracle.com wrote:
> Hi Alex,
>
> Great debugging feature!
> While I'm still reading all the details, could you, please, fix some
> minor format issues?
>
> http://cr.openjdk.java.net/~amenkov/IPv6/webrev.02/src/jdk.jdi/share/classes/com/sun/tools/jdi/SocketTransportService.java.udiff.html
>
> + * If <code>host</code> is a literal IPv6 address, it may be in square
> brackets. Extra space before "square".
>
>
> http://cr.openjdk.java.net/~amenkov/IPv6/webrev.02/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c.frames.html
>
> I'd suggest to unify comments before functions:
> - start comment with a capital latter and ended with a dot
> - use comment format like this:
> /*
> */
>
> Examples of comments that need this change:
>
> 262 /* result must be release with dbgsysFreeAddrInfo */ => /* * Result
> must be release with dbgsysFreeAddrInfo. */
>
> 325 // input is sockaddr just because all clients have it =>
> /* * Input is sockaddr just because all clients have it. */
>
> 1129 /* reads boolean system value,
> 1130 * sets *result to trueValue if the ptoperty is "true",
> 1131 * to falseValue if the property if "false",
> 1132 * doesn't change *result if the property is not set or failed to read.
> 1133 */ => /* * Read boolean system value andset result to: * -
> trueValue if the property is "true"
> * - falseValue if the property is "false" * * Return JNI_OK if result is set, return JNI_ERR otherwise.
> */
>
> . . .
>
> 293 * use IPv6 socket (to accept IPv6 and mapped Ipv4),...
> 342 * (with AF_INET6 Ipv4 addresses are not parsed even with AI_V4MAPPED
> and AI_ALL flags) ...345 hints.ai_family = AF_UNSPEC; // IPv6 or mapped
> Ipv4 ... 360 } else { // Ipv4 address Replace Ipv4 with IPv4 for
> unification with IPv6
> For unification replace: convertIpv4ToIpv6 => convertIPv4ToIPv6
>
> 297 hints.ai_flags |= AI_PASSIVE
> 298 | (allowOnlyIPv4 ? 0 : AI_V4MAPPED | AI_ALL); Better to have just
> one line
>
>
> 1135 JNIEnv* env, . . . 1165 JNIEnv* jniEnv = NULL;
>
> A suggestion is to use the same name for JNIEnv*:
>
> 1135 JNIEnv* jni, . . .
> 1165 JNIEnv* jni = NULL;
>
>
> Reformat:
>
> 608 if ((pass == 0 && ai->ai_family == preferredAddressFamily) 609 ||
> (pass == 1 && ai->ai_family != preferredAddressFamily)) and
>
> 828 if ((pass == 0 && ai->ai_family == preferredAddressFamily) 829 ||
> (pass == 1 && ai->ai_family != preferredAddressFamily)) => if ((pass ==
> 0 && ai->ai_family == preferredAddressFamily) || (pass == 1 &&
> ai->ai_family != preferredAddressFamily))
>
> Even better, replace it with logical XOR:
>
> if ((pass == 0 ^^ ai->ai_family == preferredAddressFamily)
>
>
> http://cr.openjdk.java.net/~amenkov/IPv6/webrev.02/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis001.java.frames.html
>
> 102 /* Check that listening address returned by
> ListeningConnector.startListening()
> 103 * matches the address which was set via connector's arguments.
> 104 * Empty host address causes listening for local connections only
> (loopback interface)
> 105 * */ Dot is missed at the end. Replace "* */" with "*/".
>
>
> http://cr.openjdk.java.net/~amenkov/IPv6/webrev.02/test/jdk/com/sun/jdi/JdwpAllowTest.java.frames.html
>
> 162 // generate allow address by changing random bit in the local address
> 163 // and calculate 2 masks (prefix length) - one is matches original
> local address
> 164 // and another doesn't. Replace with /* style of comment.
>
>
> 249 positiveTest("PositiveMaskTest(" + test.localAddress + ")",
> test.allowAddress + "/" + test.prefixLengthGood);
> 250 positiveTest("NegativeMaskTest(" + test.localAddress + ")",
> test.allowAddress + "/" + test.prefixLengthBad);
>
> A suggestion to move second argument to additional line:
>
> positiveTest("PositiveMaskTest(" + test.localAddress + ")",
> test.allowAddress + "/" + test.prefixLengthGood);
> positiveTest("NegativeMaskTest(" + test.localAddress + ")",
> test.allowAddress + "/" + test.prefixLengthBad);
>
> Thanks,
> Serguei
>
>
> On 4/2/19 4:14 PM, Alex Menkov wrote:
>> Updated webrev:
>> http://cr.openjdk.java.net/~amenkov/IPv6/webrev.02/
>>
>> - added support for addresses enclosed in square brackets;
>> - updated SocketTransportService.java to handle empty hostname the
>> same way as JDWP agent (listen/attach to loopback address);
>> Has to update nsk/jdi/ListeningConnector/startListening/startlis001.java
>> (all other com/sun/jdi, nsk/jdi, nsk/jdwp, nsk/jdb test are passed).
>>
>> --alex
>>
>> On 04/01/2019 11:21, Alex Menkov wrote:
>>> Hi Chris,
>>>
>>> On 04/01/2019 04:50, Chris Hegarty wrote:
>>>> Alex,
>>>>
>>>> On 29/03/2019 22:07, Alex Menkov wrote:
>>>>> (added net-dev as suggested by Alan)
>>>>>
>>>>> Net gurus, please assist in reviewing socket-related code.
>>>>>
>>>>> New webrev:
>>>>> http://cr.openjdk.java.net/~amenkov/IPv6/webrev.01/
>>>>
>>>> Specifically on SocketTransportService.java. What Arthur has
>>>> proposed is better ( changing to lastIndexOf alone is not
>>>> sufficient ). Or is your assumption that the IPv6 literal is
>>>> not enclosed in square brackets?
>>>
>>> I didn't know about enclosing IPv6 in square brackets, but looks like
>>> that's standard way to alleviate conflict between IPv6 address and
>>> colon as port separator.
>>> Will update the fix to handle them in both JDI connectors
>>> (SocketTransportService.java) and debugger agent (socketTransport.c)
>>>
>>>>
>>>> If keeping Arthur's `static class HostPort` please make the
>>>> fields final.
>>>>
>>>> >> Would it make sense to support the preference properties?
>>>> >> java.net.preferIPv4Stack
>>>> >> java.net.preferIPv6Addresses
>>>>
>>>> I'm not sure about this, especially given the property name
>>>> prefixes. I need to think a little more on it.
>>>
>>> In the initial version of the fix I didn't check the properties.
>>> The rationale here is backward compatibility - is address is empty,
>>> old debuggers tries to connect to IPv4 address only.
>>> But handling this properties we will better handle clients with
>>> properties set (as jdb or any other debugger which uses JDI
>>> connectors are affected by the properties).
>>>
>>> BTW fix provided by Arthur implements listening on localhost
>>> differently - it creates several sockets and binds them to both IPv4
>>> and IPv6 addresses. But the problem here (and that's the reason I
>>> decide to not implement it this way) - how to handle the case when we
>>> successfully bind on one address (for example IPv4), but fail to bind
>>> on other (for example the port is busy for IPv6 stack). Arthur's
>>> version just fail in the case (i.e. the whole Java process
>>> terminates) and I don't think this is good behavior.
>>>
>>>
>>>>
>>>> There is quite a bit of new native code, is it possible to
>>>> rewrite any of this in Java, e.g. reading of the system
>>>> properties ( if that is to remain )?
>>>
>>> socketTransport.c is a debugger agent which is completely native.
>>>
>>> --alex
>>>
>>>>
>>>> -Chris.
>
More information about the serviceability-dev
mailing list