1818import org .elasticsearch .cluster .node .DiscoveryNodeUtils ;
1919import org .elasticsearch .common .io .stream .BytesStreamOutput ;
2020import org .elasticsearch .common .io .stream .StreamInput ;
21+ import org .elasticsearch .core .Strings ;
2122import org .elasticsearch .core .TimeValue ;
2223import org .elasticsearch .core .UpdateForV10 ;
2324import org .elasticsearch .tasks .TaskId ;
@@ -101,7 +102,7 @@ public void testHandshakeRequestAndResponse() throws IOException {
101102 }
102103
103104 @ TestLogging (reason = "testing WARN logging" , value = "org.elasticsearch.transport.TransportHandshaker:WARN" )
104- public void testIncompatibleHandshakeRequest () throws IOException {
105+ public void testIncompatibleHandshakeRequest () throws Exception {
105106 TransportHandshaker .HandshakeRequest handshakeRequest = new TransportHandshaker .HandshakeRequest (
106107 getRandomIncompatibleTransportVersion (),
107108 randomIdentifier ()
@@ -111,27 +112,69 @@ public void testIncompatibleHandshakeRequest() throws IOException {
111112 handshakeRequest .writeTo (bytesStreamOutput );
112113 StreamInput input = bytesStreamOutput .bytes ().streamInput ();
113114 input .setTransportVersion (HANDSHAKE_REQUEST_VERSION );
114- final TestTransportChannel channel = new TestTransportChannel (ActionListener .running (() -> fail ("should not complete" )));
115115
116- MockLog .assertThatLogger (
117- () -> assertThat (
118- expectThrows (IllegalStateException .class , () -> handshaker .handleHandshake (channel , randomNonNegativeLong (), input ))
119- .getMessage (),
120- allOf (
121- containsString ("Rejecting unreadable transport handshake" ),
122- containsString ("[" + handshakeRequest .releaseVersion + "/" + handshakeRequest .transportVersion + "]" ),
123- containsString ("[" + Build .current ().version () + "/" + TransportVersion .current () + "]" ),
124- containsString ("which has an incompatible wire format" )
116+ if (handshakeRequest .transportVersion .onOrAfter (TransportVersions .MINIMUM_COMPATIBLE )) {
117+
118+ final PlainActionFuture <TransportResponse > responseFuture = new PlainActionFuture <>();
119+ final TestTransportChannel channel = new TestTransportChannel (responseFuture );
120+
121+ // we fall back to the best known version
122+ MockLog .assertThatLogger (() -> {
123+ try {
124+ handshaker .handleHandshake (channel , randomNonNegativeLong (), input );
125+ } catch (IOException e ) {
126+ throw new AssertionError (e );
127+ }
128+ },
129+ TransportHandshaker .class ,
130+ new MockLog .SeenEventExpectation (
131+ "warning" ,
132+ TransportHandshaker .class .getCanonicalName (),
133+ Level .WARN ,
134+ Strings .format (
135+ """
136+ Negotiating transport handshake with remote node with version [%s/%s] received on [*] which appears to be from \
137+ a chronologically-older release with a numerically-newer version compared to this node's version [%s/%s]. \
138+ Upgrading to a chronologically-older release may not work reliably and is not recommended. Falling back to \
139+ transport protocol version [%s].""" ,
140+ handshakeRequest .releaseVersion ,
141+ handshakeRequest .transportVersion ,
142+ Build .current ().version (),
143+ TransportVersion .current (),
144+ handshakeRequest .transportVersion .bestKnownVersion ()
145+ )
125146 )
126- ),
127- TransportHandshaker .class ,
128- new MockLog .SeenEventExpectation (
129- "warning" ,
130- TransportHandshaker .class .getCanonicalName (),
131- Level .WARN ,
132- "Rejecting unreadable transport handshake * incompatible wire format."
133- )
134- );
147+ );
148+
149+ assertTrue (responseFuture .isDone ());
150+ assertEquals (
151+ handshakeRequest .transportVersion .bestKnownVersion (),
152+ asInstanceOf (TransportHandshaker .HandshakeResponse .class , responseFuture .result ()).getTransportVersion ()
153+ );
154+
155+ } else {
156+ final TestTransportChannel channel = new TestTransportChannel (ActionListener .running (() -> fail ("should not complete" )));
157+
158+ MockLog .assertThatLogger (
159+ () -> assertThat (
160+ expectThrows (IllegalStateException .class , () -> handshaker .handleHandshake (channel , randomNonNegativeLong (), input ))
161+ .getMessage (),
162+ allOf (
163+ containsString ("Rejecting unreadable transport handshake" ),
164+ containsString ("[" + handshakeRequest .releaseVersion + "/" + handshakeRequest .transportVersion + "]" ),
165+ containsString ("[" + Build .current ().version () + "/" + TransportVersion .current () + "]" ),
166+ containsString ("which has an incompatible wire format" )
167+ )
168+ ),
169+ TransportHandshaker .class ,
170+ new MockLog .SeenEventExpectation (
171+ "warning" ,
172+ TransportHandshaker .class .getCanonicalName (),
173+ Level .WARN ,
174+ "Rejecting unreadable transport handshake * incompatible wire format."
175+ )
176+ );
177+ }
135178 }
136179
137180 public void testHandshakeResponseFromOlderNode () throws Exception {
@@ -150,40 +193,66 @@ public void testHandshakeResponseFromOlderNode() throws Exception {
150193 }
151194
152195 @ TestLogging (reason = "testing WARN logging" , value = "org.elasticsearch.transport.TransportHandshaker:WARN" )
153- public void testHandshakeResponseFromOlderNodeWithPatchedProtocol () {
196+ public void testHandshakeResponseFromOlderNodeWithPatchedProtocol () throws Exception {
154197 final PlainActionFuture <TransportVersion > versionFuture = new PlainActionFuture <>();
155198 final long reqId = randomNonNegativeLong ();
156199 handshaker .sendHandshake (reqId , node , channel , SAFE_AWAIT_TIMEOUT , versionFuture );
157200 TransportResponseHandler <TransportHandshaker .HandshakeResponse > handler = handshaker .removeHandlerForHandshake (reqId );
158201
159202 assertFalse (versionFuture .isDone ());
160203
161- final var handshakeResponse = new TransportHandshaker .HandshakeResponse (
162- getRandomIncompatibleTransportVersion (),
163- randomIdentifier ()
164- );
204+ final var randomIncompatibleTransportVersion = getRandomIncompatibleTransportVersion ();
205+ final var handshakeResponse = new TransportHandshaker .HandshakeResponse (randomIncompatibleTransportVersion , randomIdentifier ());
206+
207+ if (randomIncompatibleTransportVersion .onOrAfter (TransportVersions .MINIMUM_COMPATIBLE )) {
208+ // we fall back to the best known version
209+ MockLog .assertThatLogger (
210+ () -> handler .handleResponse (handshakeResponse ),
211+ TransportHandshaker .class ,
212+ new MockLog .SeenEventExpectation (
213+ "warning" ,
214+ TransportHandshaker .class .getCanonicalName (),
215+ Level .WARN ,
216+ Strings .format (
217+ """
218+ Negotiating transport handshake with remote node with version [%s/%s] received on [*] which appears to be from \
219+ a chronologically-older release with a numerically-newer version compared to this node's version [%s/%s]. \
220+ Upgrading to a chronologically-older release may not work reliably and is not recommended. Falling back to \
221+ transport protocol version [%s].""" ,
222+ handshakeResponse .getReleaseVersion (),
223+ handshakeResponse .getTransportVersion (),
224+ Build .current ().version (),
225+ TransportVersion .current (),
226+ randomIncompatibleTransportVersion .bestKnownVersion ()
227+ )
228+ )
229+ );
165230
166- MockLog .assertThatLogger (
167- () -> handler .handleResponse (handshakeResponse ),
168- TransportHandshaker .class ,
169- new MockLog .SeenEventExpectation (
170- "warning" ,
171- TransportHandshaker .class .getCanonicalName (),
172- Level .WARN ,
173- "Rejecting unreadable transport handshake * incompatible wire format."
174- )
175- );
231+ assertTrue (versionFuture .isDone ());
232+ assertEquals (randomIncompatibleTransportVersion .bestKnownVersion (), versionFuture .result ());
233+ } else {
234+ MockLog .assertThatLogger (
235+ () -> handler .handleResponse (handshakeResponse ),
236+ TransportHandshaker .class ,
237+ new MockLog .SeenEventExpectation (
238+ "warning" ,
239+ TransportHandshaker .class .getCanonicalName (),
240+ Level .WARN ,
241+ "Rejecting unreadable transport handshake * incompatible wire format."
242+ )
243+ );
176244
177- assertTrue (versionFuture .isDone ());
178- assertThat (
179- expectThrows (ExecutionException .class , IllegalStateException .class , versionFuture ::result ).getMessage (),
180- allOf (
181- containsString ("Rejecting unreadable transport handshake" ),
182- containsString ("[" + handshakeResponse .getReleaseVersion () + "/" + handshakeResponse .getTransportVersion () + "]" ),
183- containsString ("[" + Build .current ().version () + "/" + TransportVersion .current () + "]" ),
184- containsString ("which has an incompatible wire format" )
185- )
186- );
245+ assertTrue (versionFuture .isDone ());
246+ assertThat (
247+ expectThrows (ExecutionException .class , IllegalStateException .class , versionFuture ::result ).getMessage (),
248+ allOf (
249+ containsString ("Rejecting unreadable transport handshake" ),
250+ containsString ("[" + handshakeResponse .getReleaseVersion () + "/" + handshakeResponse .getTransportVersion () + "]" ),
251+ containsString ("[" + Build .current ().version () + "/" + TransportVersion .current () + "]" ),
252+ containsString ("which has an incompatible wire format" )
253+ )
254+ );
255+ }
187256 }
188257
189258 private static TransportVersion getRandomIncompatibleTransportVersion () {
0 commit comments