From b3e0903dae594473719aab03c935fcc368e1c4c2 Mon Sep 17 00:00:00 2001 From: Will Dey Date: Wed, 4 Sep 2024 21:41:08 -0400 Subject: [PATCH 1/3] Avoid reflection where possible --- .../cassandra/utils/HostnameSocket.java | 259 ++++++++++++++++++ .../cassandra/utils/InetAddressUtils.java | 42 --- .../cassandra/net/MessagingService.java | 4 +- .../cassandra/utils/InetAddressUtilsTest.java | 38 --- 4 files changed, 261 insertions(+), 82 deletions(-) create mode 100644 src/java/com/palantir/cassandra/utils/HostnameSocket.java delete mode 100644 src/java/com/palantir/cassandra/utils/InetAddressUtils.java delete mode 100644 test/unit/com/palantir/cassandra/utils/InetAddressUtilsTest.java diff --git a/src/java/com/palantir/cassandra/utils/HostnameSocket.java b/src/java/com/palantir/cassandra/utils/HostnameSocket.java new file mode 100644 index 0000000000..b97b2d96cf --- /dev/null +++ b/src/java/com/palantir/cassandra/utils/HostnameSocket.java @@ -0,0 +1,259 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 com.palantir.cassandra.utils; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.SocketException; +import java.net.SocketImplFactory; +import java.net.UnknownHostException; +import java.nio.channels.SocketChannel; + +public class HostnameSocket extends Socket +{ + private final Socket delegate; + private final InetAddress inetAddress; + + public HostnameSocket(Socket delegate, String hostname) + { + this.delegate = delegate; + try + { + inetAddress = InetAddress.getByAddress(hostname, delegate.getInetAddress().getAddress()); + } + catch (UnknownHostException e) + { + throw new RuntimeException(e); + } + } + + public void connect(SocketAddress endpoint) throws IOException + { + delegate.connect(endpoint); + } + + public void connect(SocketAddress endpoint, int timeout) throws IOException + { + delegate.connect(endpoint, timeout); + } + + public void bind(SocketAddress bindpoint) throws IOException + { + delegate.bind(bindpoint); + } + + public InetAddress getInetAddress() + { + return inetAddress; + } + + public InetAddress getLocalAddress() + { + return delegate.getLocalAddress(); + } + + public int getPort() + { + return delegate.getPort(); + } + + public int getLocalPort() + { + return delegate.getLocalPort(); + } + + public SocketAddress getRemoteSocketAddress() + { + return delegate.getRemoteSocketAddress(); + } + + public SocketAddress getLocalSocketAddress() + { + return delegate.getLocalSocketAddress(); + } + + public SocketChannel getChannel() + { + return delegate.getChannel(); + } + + public InputStream getInputStream() throws IOException + { + return delegate.getInputStream(); + } + + public OutputStream getOutputStream() throws IOException + { + return delegate.getOutputStream(); + } + + public void setTcpNoDelay(boolean on) throws SocketException + { + delegate.setTcpNoDelay(on); + } + + public boolean getTcpNoDelay() throws SocketException + { + return delegate.getTcpNoDelay(); + } + + public void setSoLinger(boolean on, int linger) throws SocketException + { + delegate.setSoLinger(on, linger); + } + + public int getSoLinger() throws SocketException + { + return delegate.getSoLinger(); + } + + public void sendUrgentData(int data) throws IOException + { + delegate.sendUrgentData(data); + } + + public void setOOBInline(boolean on) throws SocketException + { + delegate.setOOBInline(on); + } + + public boolean getOOBInline() throws SocketException + { + return delegate.getOOBInline(); + } + + public void setSoTimeout(int timeout) throws SocketException + { + delegate.setSoTimeout(timeout); + } + + public int getSoTimeout() throws SocketException + { + return delegate.getSoTimeout(); + } + + public void setSendBufferSize(int size) throws SocketException + { + delegate.setSendBufferSize(size); + } + + public int getSendBufferSize() throws SocketException + { + return delegate.getSendBufferSize(); + } + + public void setReceiveBufferSize(int size) throws SocketException + { + delegate.setReceiveBufferSize(size); + } + + public int getReceiveBufferSize() throws SocketException + { + return delegate.getReceiveBufferSize(); + } + + public void setKeepAlive(boolean on) throws SocketException + { + delegate.setKeepAlive(on); + } + + public boolean getKeepAlive() throws SocketException + { + return delegate.getKeepAlive(); + } + + public void setTrafficClass(int tc) throws SocketException + { + delegate.setTrafficClass(tc); + } + + public int getTrafficClass() throws SocketException + { + return delegate.getTrafficClass(); + } + + public void setReuseAddress(boolean on) throws SocketException + { + delegate.setReuseAddress(on); + } + + public boolean getReuseAddress() throws SocketException + { + return delegate.getReuseAddress(); + } + + public void close() throws IOException + { + delegate.close(); + } + + public void shutdownInput() throws IOException + { + delegate.shutdownInput(); + } + + public void shutdownOutput() throws IOException + { + delegate.shutdownOutput(); + } + + public String toString() + { + return delegate.toString(); + } + + public boolean isConnected() + { + return delegate.isConnected(); + } + + public boolean isBound() + { + return delegate.isBound(); + } + + public boolean isClosed() + { + return delegate.isClosed(); + } + + public boolean isInputShutdown() + { + return delegate.isInputShutdown(); + } + + public boolean isOutputShutdown() + { + return delegate.isOutputShutdown(); + } + + public static void setSocketImplFactory(SocketImplFactory fac) throws IOException + { + Socket.setSocketImplFactory(fac); + } + + public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) + { + delegate.setPerformancePreferences(connectionTime, latency, bandwidth); + } +} diff --git a/src/java/com/palantir/cassandra/utils/InetAddressUtils.java b/src/java/com/palantir/cassandra/utils/InetAddressUtils.java deleted file mode 100644 index 63da807c7b..0000000000 --- a/src/java/com/palantir/cassandra/utils/InetAddressUtils.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.palantir.cassandra.utils; - -import java.net.InetAddress; - -import org.apache.commons.lang3.reflect.FieldUtils; -import org.apache.commons.lang3.reflect.MethodUtils; - -public final class InetAddressUtils -{ - private InetAddressUtils() {} - - public static void setHostname(InetAddress address, String hostname) { - try - { - Object inetAddressHolder = MethodUtils.invokeMethod(address, true, "holder"); - FieldUtils.writeField(inetAddressHolder, "hostName", hostname, true); - FieldUtils.writeField(inetAddressHolder, "originalHostName", hostname, true); - } - catch (Exception e) - { - throw new RuntimeException("Failed to set hostname for InetAddress", e); - } - } -} diff --git a/src/java/org/apache/cassandra/net/MessagingService.java b/src/java/org/apache/cassandra/net/MessagingService.java index 193758a8a7..bcbde75aca 100644 --- a/src/java/org/apache/cassandra/net/MessagingService.java +++ b/src/java/org/apache/cassandra/net/MessagingService.java @@ -44,7 +44,7 @@ import com.palantir.cassandra.cvim.CrossVpcIpMappingSyn; import com.palantir.cassandra.net.HostnameResolver; import com.palantir.cassandra.net.KubernetesHostnameResolver; -import com.palantir.cassandra.utils.InetAddressUtils; +import com.palantir.cassandra.utils.HostnameSocket; import org.apache.cassandra.concurrent.ExecutorLocals; import org.apache.cassandra.concurrent.ScheduledExecutors; import org.apache.cassandra.concurrent.Stage; @@ -1004,7 +1004,7 @@ public void run() InetAddress remote = socket.getInetAddress(); if (Boolean.getBoolean("palantir_cassandra.use_custom_reverse_dns")) { - InetAddressUtils.setHostname(remote, hostnameResolver.getHostname(remote)); + socket = new HostnameSocket(socket, hostnameResolver.getHostname(remote)); } logger.trace("Attempting to accept incoming connection from {}", remote); diff --git a/test/unit/com/palantir/cassandra/utils/InetAddressUtilsTest.java b/test/unit/com/palantir/cassandra/utils/InetAddressUtilsTest.java deleted file mode 100644 index bfd8a0ebd6..0000000000 --- a/test/unit/com/palantir/cassandra/utils/InetAddressUtilsTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 com.palantir.cassandra.utils; - -import java.net.InetAddress; - -import com.google.common.net.InetAddresses; -import org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -public class InetAddressUtilsTest -{ - @Test - public void testSetInetAddress() - { - InetAddress inetAddress = InetAddresses.forString("10.0.0.1"); - InetAddressUtils.setHostname(inetAddress, "manually.specified.hostname"); - - assertThat(inetAddress.toString()).isEqualTo("manually.specified.hostname/10.0.0.1"); - } -} From 651bbe2ec61042675394c647001c480b441709d9 Mon Sep 17 00:00:00 2001 From: Will Dey Date: Thu, 5 Sep 2024 00:31:25 -0400 Subject: [PATCH 2/3] unittest --- .../cassandra/utils/HostnameSocketTest.java | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 test/unit/com/palantir/cassandra/utils/HostnameSocketTest.java diff --git a/test/unit/com/palantir/cassandra/utils/HostnameSocketTest.java b/test/unit/com/palantir/cassandra/utils/HostnameSocketTest.java new file mode 100644 index 0000000000..a35ee238cd --- /dev/null +++ b/test/unit/com/palantir/cassandra/utils/HostnameSocketTest.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 com.palantir.cassandra.utils; + +import java.net.InetAddress; +import java.net.Socket; + +import com.google.common.net.InetAddresses; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +public class HostnameSocketTest +{ + @Test + public void testInetAddress() + { + InetAddress inetAddress = InetAddresses.forString("10.0.0.1"); + Socket socket = mock(Socket.class); + doReturn(inetAddress).when(socket).getInetAddress(); + + HostnameSocket hostnameSocket = new HostnameSocket(socket, "manually.specified.hostname"); + assertThat(hostnameSocket.getInetAddress().toString()).isEqualTo("manually.specified.hostname/10.0.0.1"); + } +} From e798952d36167df01487a3380a72ce7ebc54af38 Mon Sep 17 00:00:00 2001 From: Will Dey Date: Thu, 5 Sep 2024 00:39:14 -0400 Subject: [PATCH 3/3] cruft --- src/java/com/palantir/cassandra/utils/HostnameSocket.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/java/com/palantir/cassandra/utils/HostnameSocket.java b/src/java/com/palantir/cassandra/utils/HostnameSocket.java index b97b2d96cf..b0037daeb4 100644 --- a/src/java/com/palantir/cassandra/utils/HostnameSocket.java +++ b/src/java/com/palantir/cassandra/utils/HostnameSocket.java @@ -247,11 +247,6 @@ public boolean isOutputShutdown() return delegate.isOutputShutdown(); } - public static void setSocketImplFactory(SocketImplFactory fac) throws IOException - { - Socket.setSocketImplFactory(fac); - } - public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) { delegate.setPerformancePreferences(connectionTime, latency, bandwidth);