Skip to content

Commit c34705d

Browse files
authored
Since Server v4.0 the server agent received in response to the Hello message is unreliable. Instead, since the server and Bolt protocol versions are aligned, we use the protocol version instead for all connections to Server 4.0 and higher (#708)
Since Server v4.0 the server agent received in response to the Hello message is unreliable. Instead, since the server and Bolt protocol versions are aligned, we use the protocol version instead for all connections to Server 4.0 and higher. Note: A future refactoring is required when support for 3.5 is dropped. The name serverVersion filed of the netty channel no longer reflects its true purpose since it essentially becomes protocolVersion. We keep the current naming for now since the split in meaning between 3.5 and 4.X+
1 parent 36154db commit c34705d

File tree

3 files changed

+37
-12
lines changed

3 files changed

+37
-12
lines changed

driver/src/main/java/org/neo4j/driver/internal/handlers/HelloResponseHandler.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,20 +37,30 @@ public class HelloResponseHandler implements ResponseHandler
3737

3838
private final ChannelPromise connectionInitializedPromise;
3939
private final Channel channel;
40+
private final int protocolVersion;
4041

41-
public HelloResponseHandler( ChannelPromise connectionInitializedPromise )
42+
public HelloResponseHandler( ChannelPromise connectionInitializedPromise, int protocolVersion )
4243
{
4344
this.connectionInitializedPromise = connectionInitializedPromise;
4445
this.channel = connectionInitializedPromise.channel();
46+
this.protocolVersion = protocolVersion;
4547
}
4648

4749
@Override
4850
public void onSuccess( Map<String,Value> metadata )
4951
{
5052
try
5153
{
52-
ServerVersion serverVersion = extractNeo4jServerVersion( metadata );
53-
setServerVersion( channel, serverVersion );
54+
// From Server V4 extracting server from metadata in the success message is unreliable
55+
// so we fix the Server version against the Bolt Protocol version for Server V4 and above.
56+
if ( protocolVersion == 4 )
57+
{
58+
setServerVersion( channel, ServerVersion.v4_0_0 );
59+
}
60+
else
61+
{
62+
setServerVersion( channel, extractNeo4jServerVersion( metadata ) );
63+
}
5464

5565
String connectionId = extractConnectionId( metadata );
5666
setConnectionId( channel, connectionId );

driver/src/main/java/org/neo4j/driver/internal/messaging/v3/BoltProtocolV3.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public void initializeChannel( String userAgent, Map<String,Value> authToken, Ch
8080
Channel channel = channelInitializedPromise.channel();
8181

8282
HelloMessage message = new HelloMessage( userAgent, authToken );
83-
HelloResponseHandler handler = new HelloResponseHandler( channelInitializedPromise );
83+
HelloResponseHandler handler = new HelloResponseHandler( channelInitializedPromise, version() );
8484

8585
messageDispatcher( channel ).enqueue( handler );
8686
channel.writeAndFlush( message, channel.voidPromise() );

driver/src/test/java/org/neo4j/driver/internal/handlers/HelloResponseHandlerTest.java

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.neo4j.driver.internal.async.inbound.InboundMessageDispatcher;
3838
import org.neo4j.driver.internal.async.outbound.OutboundMessageHandler;
3939
import org.neo4j.driver.internal.messaging.v1.MessageFormatV1;
40+
import org.neo4j.driver.internal.util.ServerVersion;
4041

4142
import static org.junit.jupiter.api.Assertions.assertEquals;
4243
import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -73,7 +74,7 @@ void tearDown()
7374
void shouldSetServerVersionOnChannel()
7475
{
7576
ChannelPromise channelPromise = channel.newPromise();
76-
HelloResponseHandler handler = new HelloResponseHandler( channelPromise );
77+
HelloResponseHandler handler = new HelloResponseHandler( channelPromise, 3 );
7778

7879
Map<String,Value> metadata = metadata( anyServerVersion(), "bolt-1" );
7980
handler.onSuccess( metadata );
@@ -86,7 +87,7 @@ void shouldSetServerVersionOnChannel()
8687
void shouldThrowWhenServerVersionNotReturned()
8788
{
8889
ChannelPromise channelPromise = channel.newPromise();
89-
HelloResponseHandler handler = new HelloResponseHandler( channelPromise );
90+
HelloResponseHandler handler = new HelloResponseHandler( channelPromise, 3 );
9091

9192
Map<String,Value> metadata = metadata( null, "bolt-1" );
9293
assertThrows( UntrustedServerException.class, () -> handler.onSuccess( metadata ) );
@@ -99,7 +100,7 @@ void shouldThrowWhenServerVersionNotReturned()
99100
void shouldThrowWhenServerVersionIsNull()
100101
{
101102
ChannelPromise channelPromise = channel.newPromise();
102-
HelloResponseHandler handler = new HelloResponseHandler( channelPromise );
103+
HelloResponseHandler handler = new HelloResponseHandler( channelPromise, 3 );
103104

104105
Map<String,Value> metadata = metadata( Values.NULL, "bolt-x" );
105106
assertThrows( UntrustedServerException.class, () -> handler.onSuccess( metadata ) );
@@ -112,7 +113,7 @@ void shouldThrowWhenServerVersionIsNull()
112113
void shouldThrowWhenServerVersionCantBeParsed()
113114
{
114115
ChannelPromise channelPromise = channel.newPromise();
115-
HelloResponseHandler handler = new HelloResponseHandler( channelPromise );
116+
HelloResponseHandler handler = new HelloResponseHandler( channelPromise, 3 );
116117

117118
Map<String,Value> metadata = metadata( "WrongServerVersion", "bolt-x" );
118119
assertThrows( IllegalArgumentException.class, () -> handler.onSuccess( metadata ) );
@@ -121,11 +122,25 @@ void shouldThrowWhenServerVersionCantBeParsed()
121122
assertTrue( channel.closeFuture().isDone() ); // channel was closed
122123
}
123124

125+
@Test
126+
void shouldUseProtocolVersionForServerVersionWhenConnectedWithBoltV4()
127+
{
128+
ChannelPromise channelPromise = channel.newPromise();
129+
HelloResponseHandler handler = new HelloResponseHandler( channelPromise, 4 );
130+
131+
// server used in metadata should be ignored
132+
Map<String,Value> metadata = metadata( ServerVersion.vInDev, "bolt-1" );
133+
handler.onSuccess( metadata );
134+
135+
assertTrue( channelPromise.isSuccess() );
136+
assertEquals( ServerVersion.v4_0_0, serverVersion( channel ) );
137+
}
138+
124139
@Test
125140
void shouldSetConnectionIdOnChannel()
126141
{
127142
ChannelPromise channelPromise = channel.newPromise();
128-
HelloResponseHandler handler = new HelloResponseHandler( channelPromise );
143+
HelloResponseHandler handler = new HelloResponseHandler( channelPromise, 3 );
129144

130145
Map<String,Value> metadata = metadata( anyServerVersion(), "bolt-42" );
131146
handler.onSuccess( metadata );
@@ -138,7 +153,7 @@ void shouldSetConnectionIdOnChannel()
138153
void shouldThrowWhenConnectionIdNotReturned()
139154
{
140155
ChannelPromise channelPromise = channel.newPromise();
141-
HelloResponseHandler handler = new HelloResponseHandler( channelPromise );
156+
HelloResponseHandler handler = new HelloResponseHandler( channelPromise, 3 );
142157

143158
Map<String,Value> metadata = metadata( anyServerVersion(), null );
144159
assertThrows( IllegalStateException.class, () -> handler.onSuccess( metadata ) );
@@ -151,7 +166,7 @@ void shouldThrowWhenConnectionIdNotReturned()
151166
void shouldThrowWhenConnectionIdIsNull()
152167
{
153168
ChannelPromise channelPromise = channel.newPromise();
154-
HelloResponseHandler handler = new HelloResponseHandler( channelPromise );
169+
HelloResponseHandler handler = new HelloResponseHandler( channelPromise, 3 );
155170

156171
Map<String,Value> metadata = metadata( anyServerVersion(), Values.NULL );
157172
assertThrows( IllegalStateException.class, () -> handler.onSuccess( metadata ) );
@@ -164,7 +179,7 @@ void shouldThrowWhenConnectionIdIsNull()
164179
void shouldCloseChannelOnFailure() throws Exception
165180
{
166181
ChannelPromise channelPromise = channel.newPromise();
167-
HelloResponseHandler handler = new HelloResponseHandler( channelPromise );
182+
HelloResponseHandler handler = new HelloResponseHandler( channelPromise, 3 );
168183

169184
RuntimeException error = new RuntimeException( "Hi!" );
170185
handler.onFailure( error );

0 commit comments

Comments
 (0)