Skip to content

Commit

Permalink
Support ipv6 in network receiver uri creation
Browse files Browse the repository at this point in the history
  • Loading branch information
martinfurmanski committed Jun 30, 2017
1 parent c0913b9 commit cf2f46a
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 7 deletions.
Expand Up @@ -38,6 +38,9 @@
import org.jboss.netty.util.ThreadRenamingRunnable; import org.jboss.netty.util.ThreadRenamingRunnable;


import java.net.ConnectException; import java.net.ConnectException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
Expand Down Expand Up @@ -240,23 +243,30 @@ public void receive( Message message )
} }
} }


URI getURI( InetSocketAddress address ) URI getURI( InetSocketAddress socketAddress )
{ {
String uri; String uri;


// Socket.toString() already prepends a / InetAddress address = socketAddress.getAddress();
if ( address.getAddress().getHostAddress().startsWith( "0" ) )
if ( address instanceof Inet6Address )
{
uri = CLUSTER_SCHEME + "://" + wrapAddressForIPv6Uri( address.getHostAddress() ) + ":" + socketAddress.getPort();
}
else if ( address instanceof Inet4Address )
{ {
uri = CLUSTER_SCHEME + "://0.0.0.0:" + address.getPort(); uri = CLUSTER_SCHEME + "://" + address.getHostAddress() + ":" + socketAddress.getPort();
} }
else else
{ {
uri = CLUSTER_SCHEME + "://" + address.getAddress().getHostAddress() + ":" + address.getPort(); throw new IllegalArgumentException( "Address type unknown" );
} }


// Add name if given // Add name if given
if (config.name() != null) if ( config.name() != null )
uri += "/?name="+config.name(); {
uri += "/?name=" + config.name();
}


return URI.create( uri ); return URI.create( uri );
} }
Expand Down Expand Up @@ -329,6 +339,10 @@ public void messageReceived( ChannelHandlerContext ctx, MessageEvent event ) thr
InetSocketAddress remote = (InetSocketAddress) ctx.getChannel().getRemoteAddress(); InetSocketAddress remote = (InetSocketAddress) ctx.getChannel().getRemoteAddress();
String remoteAddress = remote.getAddress().getHostAddress(); String remoteAddress = remote.getAddress().getHostAddress();
URI fromHeader = URI.create( message.getHeader( Message.FROM ) ); URI fromHeader = URI.create( message.getHeader( Message.FROM ) );
if ( remote.getAddress() instanceof Inet6Address )
{
remoteAddress = wrapAddressForIPv6Uri( remoteAddress );
}
fromHeader = URI.create(fromHeader.getScheme()+"://"+remoteAddress + ":" + fromHeader.getPort()); fromHeader = URI.create(fromHeader.getScheme()+"://"+remoteAddress + ":" + fromHeader.getPort());
message.setHeader( Message.FROM, fromHeader.toASCIIString() ); message.setHeader( Message.FROM, fromHeader.toASCIIString() );


Expand Down Expand Up @@ -359,4 +373,9 @@ public void exceptionCaught( ChannelHandlerContext ctx, ExceptionEvent e ) throw
} }
} }
} }

private static String wrapAddressForIPv6Uri( String address )
{
return "[" + address + "]";
}
} }
@@ -0,0 +1,115 @@
/*
* Copyright (c) 2002-2017 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.kernel.ha;

import org.junit.Rule;
import org.junit.Test;

import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;

import org.neo4j.cluster.ClusterSettings;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.factory.HighlyAvailableGraphDatabaseFactory;
import org.neo4j.test.rule.TestDirectory;

import static org.junit.Assume.assumeTrue;

public class HaIPv6ConfigurationTest
{
@Rule
public TestDirectory dir = TestDirectory.testDirectory();

@Test
public void testClusterWithLocalhostAddresses() throws Throwable
{
GraphDatabaseService db = new HighlyAvailableGraphDatabaseFactory()
.newEmbeddedDatabaseBuilder( dir.makeGraphDbDir() )
.setConfig( ClusterSettings.cluster_server, ipv6HostPortSetting( "::1", 5000 ) )
.setConfig( ClusterSettings.initial_hosts, ipv6HostPortSetting( "::1", 5000 ) )
.setConfig( HaSettings.ha_server, ipv6HostPortSetting( "::", 6000 ) )
.setConfig( ClusterSettings.server_id, "1" )
.newGraphDatabase();

try ( Transaction tx = db.beginTx() )
{
db.createNode();
tx.success();
}

db.shutdown();
}

@Test
public void testClusterWithLinkLocalAddress() throws Throwable
{
boolean foundAnIpv6LinkLocalAddress = false;
InetAddress inetAddress = null;

Enumeration<NetworkInterface> nics = NetworkInterface.getNetworkInterfaces();
while ( nics.hasMoreElements() )
{
NetworkInterface nic = nics.nextElement();
Enumeration<InetAddress> inetAddresses = nic.getInetAddresses();
while ( inetAddresses.hasMoreElements() )
{
inetAddress = inetAddresses.nextElement();
if ( inetAddress instanceof Inet6Address && inetAddress.isLinkLocalAddress() )
{
foundAnIpv6LinkLocalAddress = true;
break;
}
}
}

assumeTrue( foundAnIpv6LinkLocalAddress );

GraphDatabaseService db = new HighlyAvailableGraphDatabaseFactory()
.newEmbeddedDatabaseBuilder( dir.makeGraphDbDir() )
.setConfig( ClusterSettings.cluster_server, ipv6HostPortSetting( inetAddress.getHostAddress(), 5000 ) )
.setConfig( ClusterSettings.initial_hosts, ipv6HostPortSetting( inetAddress.getHostAddress(), 5000 ) )
.setConfig( HaSettings.ha_server, ipv6HostPortSetting( "::", 6000 ) )
.setConfig( ClusterSettings.server_id, "1" )
.newGraphDatabase();

db.shutdown();
}

@Test
public void testClusterWithWildcardAddresses() throws Throwable
{
GraphDatabaseService db = new HighlyAvailableGraphDatabaseFactory()
.newEmbeddedDatabaseBuilder( dir.makeGraphDbDir() )
.setConfig( ClusterSettings.cluster_server, ipv6HostPortSetting( "::", 5000 ) )
.setConfig( ClusterSettings.initial_hosts, ipv6HostPortSetting( "::1", 5000 ) )
.setConfig( HaSettings.ha_server, ipv6HostPortSetting( "::", 6000 ) )
.setConfig( ClusterSettings.server_id, "1" )
.newGraphDatabase();

db.shutdown();
}

private String ipv6HostPortSetting( String address, int port )
{
return "[" + address + "]:" + port;
}
}

0 comments on commit cf2f46a

Please sign in to comment.