Repository navigation
Parse unbracketed IPv6 ip:port from the server (#1422) - #3307
Conversation
CLUSTER NODES, MOVED/ASK and CLIENT LIST write IPv6 addresses without brackets, i.e. "2a06:4e80:3:a::a:7000". The RFC 3986 parser used for configuration strings reads that as a (valid!) eight-group address with no port, so cluster nodes ended up as "[2a06:4e80:3:a::a:7000]:0" and redirections and client addresses were equally wrong. Add Format.TryParseServerEndPoint for the server's "ip:port" form: when there is no ']' and more than one ':', split at the last colon and require both halves to parse; anything else goes to the existing parser unchanged, so configuration parsing is not touched. Use it at the three sites that receive server-emitted text. The sentinel +switch-master handler gets host and port as separate tokens and was gluing them back together with ':' before parsing; pass them to the (host, port) overload instead.
|
Thanks, this is more thorough than what I had in mind. One more spot that looks like it has the same problem: |
|
Agreed, same defect and with a worse failure mode: the port-0 result looks like the placeholder form, so the endpoint vanished rather than coming out wrong. |
ParseMigrationEndPoint used the configuration-string parser, so an unbracketed IPv6 address parsed as an address with port 0, which the placeholder check then discarded. Use TryParseServerEndPoint, as the other server-emitted sites do; tests for the MOVING successor and SMIGRATED source/target.
Fixes #1422
CLUSTER NODES,MOVED/ASKandCLIENT LISTwrite IPv6 addresses without brackets, e.g.2a06:4e80:3:a::a:7000@17000. That text went through the RFC 3986 parser used for configuration strings, which treats it as a valid eight-group IPv6 address with no port. The node therefore surfaced as[2a06:4e80:3:a::a:7000]:0, which is what the issue reports and what the latest comment still reproduces on 3.4.20.Per the discussion on the issue, the normal endpoint parser is left alone. A new internal
Format.TryParseServerEndPointhandles the server'sip:portform: when the text has no]and more than one:, it splits at the last colon and requires both halves to parse (address and in-range port); anything else is handed to the existing parser unchanged. It is used at the four sites that receive server-emitted text:ClusterNode(CLUSTER NODES)MOVED/ASKredirect handling inResultProcessorClientInfo(CLIENT LISTaddr=, the case raised mid-thread)ParseMigrationEndPointinPhysicalConnection.Maintenance(theMOVINGsuccessor andSMIGRATEDsource/target, raised in review). Here the old behaviour was worse than a wrong port: port 0 looks like the "no address" placeholder, so the endpoint was silently dropped.The sentinel
+switch-masterhandler receives host and port as separate tokens and was concatenating them with:before parsing, which has the same problem for an IPv6 primary; it now uses the(host, port)overload.Tests:
FormatTests.ParseServerEndPoint(unbracketed IPv6, plus the bracketed, IPv4, hostname and?cases to show they are unchanged),ClusterNodeParseUnitTests.UnbracketedIPv6AddressIsParsed(with and without the@cporttrailer), a newClientInfoParseUnitTestsfor the rawCLIENT LISTline, andMaintenanceNotificationTests.MovingToAnUnbracketedIPv6AddressIsParsed/SlotMigrationBetweenUnbracketedIPv6AddressesIsParsed(both fail without the fix). Built on all TFMs; the classes pass on net10.0.