Skip to content

Adding bolt v4.2 handshake. #762

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,10 @@
import io.netty.buffer.ByteBuf;

import org.neo4j.driver.internal.messaging.BoltProtocolVersion;
import org.neo4j.driver.internal.messaging.v1.BoltProtocolV1;
import org.neo4j.driver.internal.messaging.v2.BoltProtocolV2;
import org.neo4j.driver.internal.messaging.v3.BoltProtocolV3;
import org.neo4j.driver.internal.messaging.v4.BoltProtocolV4;
import org.neo4j.driver.internal.messaging.v41.BoltProtocolV41;
import org.neo4j.driver.internal.messaging.v42.BoltProtocolV42;

import static io.netty.buffer.Unpooled.copyInt;
import static io.netty.buffer.Unpooled.unreleasableBuffer;
Expand All @@ -42,10 +41,10 @@ public final class BoltProtocolUtil

private static final ByteBuf HANDSHAKE_BUF = unreleasableBuffer( copyInt(
BOLT_MAGIC_PREAMBLE,
BoltProtocolV42.VERSION.toInt(),
BoltProtocolV41.VERSION.toInt(),
BoltProtocolV4.VERSION.toInt(),
BoltProtocolV3.VERSION.toInt(),
0 ) ).asReadOnly();
BoltProtocolV3.VERSION.toInt() ) ).asReadOnly();

private static final String HANDSHAKE_STRING = createHandshakeString();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import io.netty.channel.Channel;
import io.netty.channel.ChannelPromise;

import java.util.Map;
import java.util.concurrent.CompletionStage;

import org.neo4j.driver.AuthToken;
Expand All @@ -30,7 +29,6 @@
import org.neo4j.driver.Session;
import org.neo4j.driver.Transaction;
import org.neo4j.driver.TransactionConfig;
import org.neo4j.driver.Value;
import org.neo4j.driver.exceptions.ClientException;
import org.neo4j.driver.internal.BookmarkHolder;
import org.neo4j.driver.internal.InternalBookmark;
Expand All @@ -42,6 +40,7 @@
import org.neo4j.driver.internal.messaging.v3.BoltProtocolV3;
import org.neo4j.driver.internal.messaging.v4.BoltProtocolV4;
import org.neo4j.driver.internal.messaging.v41.BoltProtocolV41;
import org.neo4j.driver.internal.messaging.v42.BoltProtocolV42;
import org.neo4j.driver.internal.spi.Connection;

import static org.neo4j.driver.internal.async.connection.ChannelAttributes.protocolVersion;
Expand Down Expand Up @@ -173,6 +172,9 @@ else if ( BoltProtocolV4.VERSION.equals( version ) )
} else if ( BoltProtocolV41.VERSION.equals( version ) )
{
return BoltProtocolV41.INSTANCE;
} else if ( BoltProtocolV42.VERSION.equals( version ) )
{
return BoltProtocolV42.INSTANCE;
}
throw new ClientException( "Unknown protocol version: " + version );
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2002-2020 "Neo4j,"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.neo4j.driver.internal.messaging.v42;

import org.neo4j.driver.internal.messaging.BoltProtocol;
import org.neo4j.driver.internal.messaging.BoltProtocolVersion;
import org.neo4j.driver.internal.messaging.v41.BoltProtocolV41;

/**
* Bolt V4.2 is identical to V4.1
*/
public class BoltProtocolV42 extends BoltProtocolV41
{
public static final BoltProtocolVersion VERSION = new BoltProtocolVersion( 4, 2 );
public static final BoltProtocol INSTANCE = new BoltProtocolV42();

@Override
public BoltProtocolVersion version()
{
return VERSION;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@
import org.neo4j.driver.internal.messaging.BoltProtocolVersion;
import org.neo4j.driver.internal.messaging.v4.BoltProtocolV4;
import org.neo4j.driver.internal.messaging.v41.BoltProtocolV41;
import org.neo4j.driver.internal.messaging.v42.BoltProtocolV42;

import static java.lang.Integer.compare;

public class ServerVersion
{
public static final String NEO4J_PRODUCT = "Neo4j";

public static final ServerVersion v4_2_0 = new ServerVersion( NEO4J_PRODUCT, 4, 2, 0 );
public static final ServerVersion v4_1_0 = new ServerVersion( NEO4J_PRODUCT, 4, 1, 0 );
public static final ServerVersion v4_0_0 = new ServerVersion( NEO4J_PRODUCT, 4, 0, 0 );
public static final ServerVersion v3_5_0 = new ServerVersion( NEO4J_PRODUCT, 3, 5, 0 );
Expand Down Expand Up @@ -188,6 +190,9 @@ public static ServerVersion fromBoltProtocolVersion( BoltProtocolVersion protoco
else if ( BoltProtocolV41.VERSION.equals( protocolVersion ) )
{
return ServerVersion.v4_1_0;
} else if ( BoltProtocolV42.VERSION.equals( protocolVersion ) )
{
return ServerVersion.v4_2_0;
}

return ServerVersion.vInDev;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,10 @@
import io.netty.buffer.Unpooled;
import org.junit.jupiter.api.Test;

import org.neo4j.driver.internal.messaging.v1.BoltProtocolV1;
import org.neo4j.driver.internal.messaging.v2.BoltProtocolV2;
import org.neo4j.driver.internal.messaging.v3.BoltProtocolV3;
import org.neo4j.driver.internal.messaging.v4.BoltProtocolV4;
import org.neo4j.driver.internal.messaging.v41.BoltProtocolV41;
import org.neo4j.driver.internal.messaging.v42.BoltProtocolV42;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.neo4j.driver.internal.async.connection.BoltProtocolUtil.BOLT_MAGIC_PREAMBLE;
Expand All @@ -44,15 +43,15 @@ void shouldReturnHandshakeBuf()
{
assertByteBufContains(
handshakeBuf(),
BOLT_MAGIC_PREAMBLE, BoltProtocolV41.VERSION.toInt(), BoltProtocolV4.VERSION.toInt(),
BoltProtocolV3.VERSION.toInt(), 0
BOLT_MAGIC_PREAMBLE, BoltProtocolV42.VERSION.toInt(), BoltProtocolV41.VERSION.toInt(),
BoltProtocolV4.VERSION.toInt(), BoltProtocolV3.VERSION.toInt()
);
}

@Test
void shouldReturnHandshakeString()
{
assertEquals( "[0x6060b017, 260, 4, 3, 0]", handshakeString() );
assertEquals( "[0x6060b017, 516, 260, 4, 3]", handshakeString() );
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.io.IOException;
import java.util.stream.Stream;
import javax.net.ssl.SSLHandshakeException;

import org.neo4j.driver.Logging;
Expand All @@ -40,10 +44,12 @@
import org.neo4j.driver.internal.async.outbound.OutboundMessageHandler;
import org.neo4j.driver.internal.messaging.BoltProtocolVersion;
import org.neo4j.driver.internal.messaging.MessageFormat;
import org.neo4j.driver.internal.messaging.v1.BoltProtocolV1;
import org.neo4j.driver.internal.messaging.v1.MessageFormatV1;
import org.neo4j.driver.internal.messaging.v2.BoltProtocolV2;
import org.neo4j.driver.internal.messaging.v2.MessageFormatV2;
import org.neo4j.driver.internal.messaging.v3.BoltProtocolV3;
import org.neo4j.driver.internal.messaging.v3.MessageFormatV3;
import org.neo4j.driver.internal.messaging.v4.BoltProtocolV4;
import org.neo4j.driver.internal.messaging.v4.MessageFormatV4;
import org.neo4j.driver.internal.messaging.v41.BoltProtocolV41;
import org.neo4j.driver.internal.messaging.v42.BoltProtocolV42;
import org.neo4j.driver.internal.util.ErrorUtil;

import static io.netty.buffer.Unpooled.copyInt;
Expand All @@ -54,6 +60,7 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.params.provider.Arguments.arguments;
import static org.neo4j.driver.internal.async.connection.BoltProtocolUtil.NO_PROTOCOL_VERSION;
import static org.neo4j.driver.internal.async.connection.ChannelAttributes.setMessageDispatcher;
import static org.neo4j.driver.internal.logging.DevNullLogging.DEV_NULL_LOGGING;
Expand Down Expand Up @@ -187,16 +194,33 @@ void shouldTranslateSSLHandshakeException()
assertNull( await( channel.closeFuture() ) );
}

@Test
void shouldSelectProtocolV1WhenServerSuggests()
@ParameterizedTest
@MethodSource( "protocolVersions" )
public void testProtocolSelection( BoltProtocolVersion protocolVersion, Class<? extends MessageFormat> expectedMessageFormatClass )
{
testProtocolSelection( BoltProtocolV1.VERSION, MessageFormatV1.class );
}
ChannelPromise handshakeCompletedPromise = channel.newPromise();
MemorizingChannelPipelineBuilder pipelineBuilder = new MemorizingChannelPipelineBuilder();
HandshakeHandler handler = newHandler( pipelineBuilder, handshakeCompletedPromise );
channel.pipeline().addLast( handler );

@Test
void shouldSelectProtocolV2WhenServerSuggests()
{
testProtocolSelection( BoltProtocolV2.VERSION, MessageFormatV2.class );
channel.pipeline().fireChannelRead( copyInt( protocolVersion.toInt() ) );

// expected message format should've been used
assertThat( pipelineBuilder.usedMessageFormat, instanceOf( expectedMessageFormatClass ) );

// handshake handler itself should be removed
assertNull( channel.pipeline().get( HandshakeHandler.class ) );

// all inbound handlers should be set
assertNotNull( channel.pipeline().get( ChunkDecoder.class ) );
assertNotNull( channel.pipeline().get( MessageDecoder.class ) );
assertNotNull( channel.pipeline().get( InboundMessageHandler.class ) );

// all outbound handlers should be set
assertNotNull( channel.pipeline().get( OutboundMessageHandler.class ) );

// promise should be successful
assertNull( await( handshakeCompletedPromise ) );
}

@Test
Expand Down Expand Up @@ -254,31 +278,12 @@ private void testFailure( BoltProtocolVersion serverSuggestedVersion, String exp
assertNull( await( channel.closeFuture() ) );
}

private void testProtocolSelection( BoltProtocolVersion protocolVersion, Class<? extends MessageFormat> expectedMessageFormatClass )
private static Stream<Arguments> protocolVersions()
{
ChannelPromise handshakeCompletedPromise = channel.newPromise();
MemorizingChannelPipelineBuilder pipelineBuilder = new MemorizingChannelPipelineBuilder();
HandshakeHandler handler = newHandler( pipelineBuilder, handshakeCompletedPromise );
channel.pipeline().addLast( handler );

channel.pipeline().fireChannelRead( copyInt( protocolVersion.toInt() ) );

// expected message format should've been used
assertThat( pipelineBuilder.usedMessageFormat, instanceOf( expectedMessageFormatClass ) );

// handshake handler itself should be removed
assertNull( channel.pipeline().get( HandshakeHandler.class ) );

// all inbound handlers should be set
assertNotNull( channel.pipeline().get( ChunkDecoder.class ) );
assertNotNull( channel.pipeline().get( MessageDecoder.class ) );
assertNotNull( channel.pipeline().get( InboundMessageHandler.class ) );

// all outbound handlers should be set
assertNotNull( channel.pipeline().get( OutboundMessageHandler.class ) );

// promise should be successful
assertNull( await( handshakeCompletedPromise ) );
return Stream.of( arguments( BoltProtocolV3.VERSION, MessageFormatV3.class ),
arguments( BoltProtocolV4.VERSION, MessageFormatV4.class ),
arguments( BoltProtocolV41.VERSION, MessageFormatV4.class ),
arguments( BoltProtocolV42.VERSION, MessageFormatV4.class ) );
}

private static HandshakeHandler newHandler( ChannelPromise handshakeCompletedPromise )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@
import org.neo4j.driver.internal.cluster.RoutingTableHandler;
import org.neo4j.driver.internal.cluster.RoutingTableRegistry;
import org.neo4j.driver.internal.messaging.BoltProtocol;
import org.neo4j.driver.internal.messaging.v4.BoltProtocolV4;
import org.neo4j.driver.internal.messaging.v41.BoltProtocolV41;
import org.neo4j.driver.internal.messaging.v42.BoltProtocolV42;
import org.neo4j.driver.internal.spi.Connection;
import org.neo4j.driver.internal.spi.ConnectionPool;
import org.neo4j.driver.internal.util.FakeClock;
Expand Down Expand Up @@ -395,7 +394,7 @@ private static Connection newBoltV4Connection( BoltServerAddress address )
{
Connection connection = mock( Connection.class );
when( connection.serverAddress() ).thenReturn( address );
when( connection.protocol() ).thenReturn( BoltProtocol.forVersion( BoltProtocolV41.VERSION ) );
when( connection.protocol() ).thenReturn( BoltProtocol.forVersion( BoltProtocolV42.VERSION ) );
when( connection.serverVersion() ).thenReturn( ServerVersion.v4_1_0 );
when( connection.release() ).thenReturn( completedWithNull() );
return connection;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class BoltProtocolVersionTest
{

@ParameterizedTest( name = "V{0}.{1}" )
@CsvSource( {"3, 0", "4, 0", "4, 1", "100, 100", "255, 255", "0, 0"} )
@CsvSource( {"3, 0", "4, 0", "4, 1", "4, 2", "100, 100", "255, 255", "0, 0"} )
void shouldParseVersion( int major, int minor )
{
BoltProtocolVersion protocolVersion = new BoltProtocolVersion( major, minor );
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2002-2020 "Neo4j,"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.neo4j.driver.internal.messaging.v42;

import org.neo4j.driver.internal.messaging.BoltProtocol;
import org.neo4j.driver.internal.messaging.v41.BoltProtocolV41Test;

public class BoltProtocolV42Test extends BoltProtocolV41Test
{
@Override
protected BoltProtocol createProtocol()
{
return BoltProtocolV42.INSTANCE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.neo4j.driver.internal.messaging.BoltProtocolVersion;
import org.neo4j.driver.internal.messaging.v4.BoltProtocolV4;
import org.neo4j.driver.internal.messaging.v41.BoltProtocolV41;
import org.neo4j.driver.internal.messaging.v42.BoltProtocolV42;

import static java.lang.Integer.MAX_VALUE;
import static org.hamcrest.MatcherAssert.assertThat;
Expand Down Expand Up @@ -71,6 +72,7 @@ void shouldReturnCorrectServerVersionFromBoltProtocolVersion()
{
assertEquals( ServerVersion.v4_0_0, ServerVersion.fromBoltProtocolVersion( BoltProtocolV4.VERSION ) );
assertEquals( ServerVersion.v4_1_0, ServerVersion.fromBoltProtocolVersion( BoltProtocolV41.VERSION ) );
assertEquals( ServerVersion.v4_2_0, ServerVersion.fromBoltProtocolVersion( BoltProtocolV42.VERSION ) );
assertEquals( ServerVersion.vInDev, ServerVersion.fromBoltProtocolVersion( new BoltProtocolVersion( MAX_VALUE, MAX_VALUE ) ) );
}
}
3 changes: 2 additions & 1 deletion driver/src/test/java/org/neo4j/driver/util/TestUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
import org.neo4j.driver.internal.messaging.v3.BoltProtocolV3;
import org.neo4j.driver.internal.messaging.v4.BoltProtocolV4;
import org.neo4j.driver.internal.messaging.v41.BoltProtocolV41;
import org.neo4j.driver.internal.messaging.v42.BoltProtocolV42;
import org.neo4j.driver.internal.retry.RetryLogic;
import org.neo4j.driver.internal.spi.Connection;
import org.neo4j.driver.internal.spi.ConnectionProvider;
Expand Down Expand Up @@ -532,7 +533,7 @@ public static Connection connectionMock( String databaseName, AccessMode mode, B
setupSuccessfulPullAll( connection, "BEGIN" );
}
else if ( version.equals( BoltProtocolV3.VERSION ) || version.equals( BoltProtocolV4.VERSION ) ||
version.equals( BoltProtocolV41.VERSION ))
version.equals( BoltProtocolV41.VERSION ) || version.equals( BoltProtocolV42.VERSION ))
{
setupSuccessResponse( connection, CommitMessage.class );
setupSuccessResponse( connection, RollbackMessage.class );
Expand Down