├── .gitignore ├── LICENSE ├── README.adoc ├── jmh ├── .gitignore ├── pom.xml └── src │ └── main │ └── java │ └── net │ └── openhft │ └── chronicle │ └── network │ ├── ChanelHubTest.java │ ├── VerySimpleClient.java │ └── WireEchoRequestHandler.java ├── pom.xml ├── src ├── main │ └── java │ │ └── net │ │ └── openhft │ │ └── chronicle │ │ └── network │ │ ├── AcceptStrategies.java │ │ ├── AcceptStrategy.java │ │ ├── AcceptorEventHandler.java │ │ ├── AlwaysStartOnPrimaryConnectionStrategy.java │ │ ├── ChronicleSocketChannelBuilder.java │ │ ├── ClientClosedProvider.java │ │ ├── ClientSessionProvider.java │ │ ├── ConnectionListener.java │ │ ├── ConnectionStrategy.java │ │ ├── HeaderTcpHandler.java │ │ ├── HeartbeatListener.java │ │ ├── HostnamePortLookupTable.java │ │ ├── MarshallableFunction.java │ │ ├── MethodTcpHandler.java │ │ ├── NetworkContext.java │ │ ├── NetworkContextManager.java │ │ ├── NetworkLog.java │ │ ├── NetworkStatsListener.java │ │ ├── NetworkUtil.java │ │ ├── ReadWithFlowControl.java │ │ ├── RemoteConnector.java │ │ ├── ServerThreadingStrategy.java │ │ ├── SessionMode.java │ │ ├── SocketConnectionNotifier.java │ │ ├── TCPRegistry.java │ │ ├── TcpEventHandler.java │ │ ├── TcpEventHandlerManager.java │ │ ├── TcpHandlerBias.java │ │ ├── VanillaClientConnectionMonitor.java │ │ ├── VanillaNetworkContext.java │ │ ├── VanillaSessionDetails.java │ │ ├── WireTcpHandler.java │ │ ├── WireTypeSniffingTcpHandler.java │ │ ├── api │ │ ├── NetworkStats.java │ │ ├── TcpHandler.java │ │ └── session │ │ │ ├── SessionDetails.java │ │ │ ├── SessionDetailsProvider.java │ │ │ ├── SessionProvider.java │ │ │ ├── SubHandler.java │ │ │ └── WritableSubHandler.java │ │ ├── cluster │ │ ├── AbstractSubHandler.java │ │ ├── Cluster.java │ │ ├── ClusterAcceptorEventHandler.java │ │ ├── ClusterContext.java │ │ ├── ClusteredNetworkContext.java │ │ ├── ConnectionManager.java │ │ ├── HeartbeatEventHandler.java │ │ ├── HostConnector.java │ │ ├── HostDetails.java │ │ ├── LoggingNetworkStatsListener.java │ │ ├── VanillaClusteredNetworkContext.java │ │ └── handlers │ │ │ ├── CspTcpHandler.java │ │ │ ├── HeartbeatHandler.java │ │ │ ├── Registerable.java │ │ │ ├── RejectedHandlerException.java │ │ │ └── UberHandler.java │ │ ├── connection │ │ ├── AbstractAsyncSubscription.java │ │ ├── AbstractAsyncTemporarySubscription.java │ │ ├── AbstractConnectionStrategy.java │ │ ├── AbstractStatelessClient.java │ │ ├── AsyncSubscription.java │ │ ├── AsyncTemporarySubscription.java │ │ ├── ClientConnectionMonitor.java │ │ ├── ConnectionListeners.java │ │ ├── CoreFields.java │ │ ├── EventId.java │ │ ├── FatalFailureConnectionStrategy.java │ │ ├── FatalFailureMonitor.java │ │ ├── SocketAddressSupplier.java │ │ ├── TcpChannelHub.java │ │ ├── ThreadPrivateTLongObjHashMap.java │ │ ├── TraceLock.java │ │ ├── TryLock.java │ │ ├── VanillaWireOutPublisher.java │ │ ├── WireOutConsumer.java │ │ └── WireOutPublisher.java │ │ ├── internal │ │ ├── AddressCache.java │ │ ├── SocketExceptionUtil.java │ │ ├── cluster │ │ │ └── handlers │ │ │ │ └── NoOpHandler.java │ │ ├── lookuptable │ │ │ ├── FileBasedHostnamePortLookupTable.java │ │ │ └── ProcessLocalHostnamePortLookupTable.java │ │ └── package-info.java │ │ ├── ssl │ │ ├── BufferHandler.java │ │ ├── BytesBufferHandler.java │ │ ├── SslDelegatingTcpHandler.java │ │ ├── SslEngineStateMachine.java │ │ └── SslNetworkContext.java │ │ └── tcp │ │ ├── ChronicleServerSocket.java │ │ ├── ChronicleServerSocketChannel.java │ │ ├── ChronicleServerSocketFactory.java │ │ ├── ChronicleSocket.java │ │ ├── ChronicleSocketChannel.java │ │ ├── ChronicleSocketChannelFactory.java │ │ ├── ChronicleSocketFactory.java │ │ ├── FastJ8SocketChannel.java │ │ ├── UnsafeFastJ8SocketChannel.java │ │ ├── VanillaChronicleServerSocketChannel.java │ │ └── VanillaSocketChannel.java └── test │ ├── java │ └── net │ │ └── openhft │ │ ├── chronicle │ │ └── network │ │ │ ├── AlwaysStartOnPrimaryConnectionStrategyTest.java │ │ │ ├── ClusterTest.java │ │ │ ├── ConnectionListenerTest.java │ │ │ ├── CrossProcessTCPRegistryTest.java │ │ │ ├── InMemoryTCPRegistryTest.java │ │ │ ├── NetworkStatsAdapter.java │ │ │ ├── NetworkTestCommon.java │ │ │ ├── RemoteConnectorTest.java │ │ │ ├── TCPRegistryTest.java │ │ │ ├── TcpEventHandlerReleaseTest.java │ │ │ ├── UberHandlerTest.java │ │ │ ├── VanillaNetworkContextTest.java │ │ │ ├── cluster │ │ │ ├── ClusterAcceptorEventHandlerTest.java │ │ │ ├── ClusterConnectivityTest.java │ │ │ ├── ClusterContextTest.java │ │ │ ├── ConnectionManagerTest.java │ │ │ └── handlers │ │ │ │ └── HeartbeatHandlerTest.java │ │ │ ├── connection │ │ │ ├── AbstractConnectionStrategyTest.java │ │ │ └── FatalFailureConnectionStrategyTest.java │ │ │ ├── internal │ │ │ ├── AddressCacheTest.java │ │ │ ├── SocketExceptionUtilTest.java │ │ │ └── lookuptable │ │ │ │ └── FileBasedHostnamePortLookupTableTest.java │ │ │ ├── ssl │ │ │ ├── AbstractSocketBufferHandler.java │ │ │ ├── NioSslIntegrationTest.java │ │ │ ├── NonClusteredSslIntegrationTest.java │ │ │ ├── PingSender.java │ │ │ ├── SSLContextLoader.java │ │ │ ├── StateMachineProcessor.java │ │ │ └── TransparentSslPerformanceTest.java │ │ │ ├── tcp │ │ │ └── FastJ8SocketChannelTest.java │ │ │ ├── test │ │ │ ├── TestCluster.java │ │ │ ├── TestClusterContext.java │ │ │ └── TestClusteredNetworkContext.java │ │ │ └── util │ │ │ ├── TestServer.java │ │ │ └── TestUtil.java │ │ └── performance │ │ └── tests │ │ ├── network │ │ ├── BufferSizeTest.java │ │ ├── EchoHandler.java │ │ ├── LegacyHanderFactory.java │ │ ├── PingPongWithMains.java │ │ ├── SelectedSelectionKeySet.java │ │ ├── SimpleServerAndClientTest.java │ │ ├── TestData.java │ │ ├── TimedEchoHandler.java │ │ ├── VerySimpleClientTest.java │ │ ├── WireEchoRequestHandler.java │ │ └── WireTcpHandlerTest.java │ │ ├── third │ │ └── party │ │ │ └── frameworks │ │ │ ├── grizzly │ │ │ ├── GrizzlyClientLatencyTest.java │ │ │ ├── GrizzlyClientThroughPutTest.java │ │ │ └── GrizzlyEchoServer.java │ │ │ ├── mina │ │ │ ├── MinaClientLatencyTest.java │ │ │ ├── MinaClientThroughPutTest.java │ │ │ └── MinaEchoServer.java │ │ │ └── netty │ │ │ ├── NettyClientLatencyTest.java │ │ │ ├── NettyClientThroughPutTest.java │ │ │ └── NettyEchoServer.java │ │ └── vanilla │ │ └── tcp │ │ ├── EchoClientMain.java │ │ ├── EchoMultiServerMain.java │ │ ├── EchoReconnectingClientMain.java │ │ ├── EchoServer2Main.java │ │ └── EchoServerMain.java │ └── resources │ ├── ssl-test-cluster.yaml │ └── test.jks ├── system.properties └── systemProperties.adoc /.gitignore: -------------------------------------------------------------------------------- 1 | ### How to update 2 | # This is copied from OpenHFT/.gitignore 3 | # update the original and run OpenHFT/update_gitignore.sh 4 | 5 | ### Compiled class file 6 | *.class 7 | 8 | ### Package Files 9 | *.jar 10 | *.war 11 | *.ear 12 | 13 | ### Log file 14 | *.log 15 | 16 | ### IntelliJ 17 | *.iml 18 | *.ipr 19 | *.iws 20 | .idea 21 | compat_reports 22 | .attach_pid* 23 | 24 | ### Virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 25 | hs_err_pid* 26 | 27 | ### Maven template 28 | target/ 29 | pom.xml.tag 30 | pom.xml.releaseBackup 31 | pom.xml.versionsBackup 32 | pom.xml.next 33 | release.properties 34 | 35 | ### Eclipse template 36 | *.pydevproject 37 | .metadata 38 | .gradle 39 | bin/ 40 | tmp/ 41 | *.tmp 42 | *.bak 43 | *.swp 44 | *~.nib 45 | local.properties 46 | .classpath 47 | .project 48 | .settings/ 49 | .loadpath 50 | 51 | ### Queue files 52 | *.cq4t 53 | *.cq4 54 | 55 | shared_hostname_mappings 56 | -------------------------------------------------------------------------------- /jmh/.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Package Files # 4 | *.jar 5 | *.war 6 | *.ear 7 | 8 | # IntelliJ 9 | *.iml 10 | *.ipr 11 | *.iws 12 | .idea 13 | compat_reports 14 | 15 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 16 | hs_err_pid* 17 | 18 | # Eclipse 19 | .classpath 20 | .project 21 | .settings/ 22 | 23 | # maven 24 | target 25 | #jmh 26 | -------------------------------------------------------------------------------- /jmh/src/main/java/net/openhft/chronicle/network/WireEchoRequestHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015-2020 chronicle.software 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU Lesser General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU Lesser General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | package net.openhft.chronicle.network; 18 | 19 | import net.openhft.chronicle.bytes.Bytes; 20 | import net.openhft.chronicle.network.api.session.SessionDetailsProvider; 21 | import net.openhft.chronicle.wire.Wire; 22 | import net.openhft.chronicle.wire.WireIn; 23 | import net.openhft.chronicle.wire.WireOut; 24 | import org.jetbrains.annotations.NotNull; 25 | 26 | import java.util.function.Function; 27 | 28 | public class WireEchoRequestHandler extends WireTcpHandler { 29 | 30 | public WireEchoRequestHandler(@NotNull Function, Wire> bytesToWire) { 31 | super(bytesToWire); 32 | } 33 | 34 | /** 35 | * simply reads the csp,tid and payload and sends back the tid and payload 36 | * 37 | * @param inWire the wire from the client 38 | * @param outWire the wire to be sent back to the server 39 | * @param sd details about this session 40 | */ 41 | @Override 42 | protected void process(@NotNull WireIn inWire, 43 | @NotNull WireOut outWire, 44 | @NotNull SessionDetailsProvider sd) { 45 | 46 | inWire.readDocument(m -> { 47 | long tid = inWire.read("tid").int64(); 48 | outWire.writeDocument(true, meta -> meta.write("tid") 49 | .int64(tid)); 50 | 51 | }, d -> { 52 | outWire.writeDocument(false, data -> data.write("payloadResponse") 53 | .text(inWire.read("payload").text())); 54 | }); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/AcceptStrategies.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network; 20 | 21 | import net.openhft.chronicle.network.tcp.ChronicleServerSocketChannel; 22 | import net.openhft.chronicle.network.tcp.ChronicleSocketChannel; 23 | 24 | import java.io.IOException; 25 | 26 | public enum AcceptStrategies implements AcceptStrategy { 27 | ACCEPT_ALL { 28 | @Override 29 | public ChronicleSocketChannel accept(final ChronicleServerSocketChannel ssc) throws IOException { 30 | return ssc.accept(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/AcceptStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network; 19 | 20 | import net.openhft.chronicle.network.tcp.ChronicleServerSocketChannel; 21 | import net.openhft.chronicle.network.tcp.ChronicleSocketChannel; 22 | import net.openhft.chronicle.wire.Marshallable; 23 | 24 | import java.io.IOException; 25 | 26 | /** 27 | * Can be used to reject incoming connections e.g. you could implement an AcceptStrategy that checks remote IPs and rejects if not in whitelist 28 | */ 29 | @FunctionalInterface 30 | public interface AcceptStrategy extends Marshallable { 31 | 32 | AcceptStrategy ACCEPT_ALL = AcceptStrategies.ACCEPT_ALL; 33 | 34 | /** 35 | * Determine whether to accept the incoming connection 36 | * 37 | * @param ssc 38 | * @return null to reject the connection, otherwise return the accepted SocketChannel 39 | * @throws IOException 40 | */ 41 | ChronicleSocketChannel accept(ChronicleServerSocketChannel ssc) throws IOException; 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/ClientClosedProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network; 19 | 20 | public interface ClientClosedProvider { 21 | /** 22 | * @return {@code true} if the client has intentionally closed 23 | */ 24 | default boolean hasClientClosed() { 25 | return false; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/ClientSessionProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network; 19 | 20 | import net.openhft.chronicle.network.api.session.SessionDetails; 21 | import net.openhft.chronicle.network.api.session.SessionProvider; 22 | import org.jetbrains.annotations.NotNull; 23 | 24 | /** 25 | * An immutable implementation of a SessionProvider 26 | */ 27 | public final class ClientSessionProvider implements SessionProvider { 28 | @NotNull 29 | private final SessionDetails sessionDetails; 30 | 31 | public ClientSessionProvider(@NotNull final SessionDetails sessionDetails) { 32 | this.sessionDetails = sessionDetails; 33 | } 34 | 35 | @Override 36 | public SessionDetails get() { 37 | return sessionDetails; 38 | } 39 | 40 | @Override 41 | public void set(@NotNull final SessionDetails sessionDetails) { 42 | throw new UnsupportedOperationException(); 43 | } 44 | 45 | @NotNull 46 | @Override 47 | public String toString() { 48 | return "sessionDetails=" + sessionDetails; 49 | } 50 | } -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/ConnectionListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network; 19 | 20 | public interface ConnectionListener { 21 | 22 | void onConnected(int localIdentifier, int remoteIdentifier, boolean isAcceptor); 23 | 24 | void onDisconnected(int localIdentifier, int remoteIdentifier, boolean isAcceptor); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/HeaderTcpHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network; 19 | 20 | import net.openhft.chronicle.bytes.Bytes; 21 | import net.openhft.chronicle.core.Jvm; 22 | import net.openhft.chronicle.core.io.SimpleCloseable; 23 | import net.openhft.chronicle.network.api.TcpHandler; 24 | import net.openhft.chronicle.network.api.session.SessionDetailsProvider; 25 | import net.openhft.chronicle.network.api.session.SubHandler; 26 | import net.openhft.chronicle.wire.*; 27 | import org.jetbrains.annotations.NotNull; 28 | 29 | import java.util.function.Function; 30 | 31 | import static net.openhft.chronicle.network.NetworkUtil.TCP_USE_PADDING; 32 | 33 | public class HeaderTcpHandler> extends SimpleCloseable implements TcpHandler { 34 | 35 | public static final String HANDLER = "handler"; 36 | @NotNull 37 | private final TcpEventHandler handlerManager; 38 | @NotNull 39 | private final Function> handlerFunction; 40 | 41 | public HeaderTcpHandler(@NotNull final TcpEventHandler handlerManager, 42 | @NotNull final Function> handlerFunction) { 43 | this.handlerManager = handlerManager; 44 | this.handlerFunction = handlerFunction; 45 | } 46 | 47 | @Override 48 | public void process(@NotNull final Bytes in, 49 | @NotNull final Bytes out, 50 | @NotNull final T nc) { 51 | throwExceptionIfClosed(); 52 | 53 | WireType wireType = nc.wireType() == null ? WireType.BINARY : nc.wireType(); 54 | 55 | // the type of the header 56 | final Wire inWire = wireType.apply(in); 57 | inWire.usePadding(TCP_USE_PADDING); 58 | final long start = in.readPosition(); 59 | 60 | Object o = null; 61 | try (final DocumentContext dc = inWire.readingDocument()) { 62 | 63 | if (!dc.isPresent()) 64 | return; 65 | 66 | if (YamlLogging.showServerReads()) 67 | Jvm.startup().on(getClass(), "nc.isAcceptor=" + nc.isAcceptor() + 68 | ", read:\n" + Wires.fromSizePrefixedBlobs(in, start, in.readLimit() - start)); 69 | 70 | final long readPosition = inWire.bytes().readPosition(); 71 | @NotNull final ValueIn read = inWire.read(() -> HANDLER); 72 | 73 | if (dc.isMetaData() && read.isTyped()) 74 | o = read.typedMarshallable(); 75 | else { 76 | inWire.bytes().readPosition(readPosition); 77 | o = toSessionDetails(inWire); 78 | } 79 | 80 | final TcpHandler handler = handlerFunction.apply(o); 81 | 82 | if (handler instanceof NetworkContextManager) 83 | ((NetworkContextManager) handler).nc(nc); 84 | 85 | handlerManager.tcpHandler(handler); 86 | } catch (Throwable e) { 87 | if (isClosed()) 88 | return; 89 | Jvm.pause(50); 90 | if (isClosed()) 91 | return; 92 | if (o instanceof SubHandler) { 93 | Jvm.warn().on(getClass(), "SubHandler " + o + " sent before UberHandler, closing."); 94 | close(); 95 | } else { 96 | Jvm.warn().on(getClass(), "wirein=" + Wires.fromSizePrefixedBlobs(inWire), e); 97 | } 98 | } 99 | } 100 | 101 | @NotNull 102 | private SessionDetailsProvider toSessionDetails(@NotNull final Wire inWire) { 103 | @NotNull final VanillaSessionDetails sd = new VanillaSessionDetails(); 104 | sd.readMarshallable(inWire); 105 | return sd; 106 | } 107 | } -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/HeartbeatListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network; 19 | 20 | @FunctionalInterface 21 | public interface HeartbeatListener { 22 | 23 | /** 24 | * called when we don't receive a heartbeat ( or in some cases any message ) 25 | * 26 | * @return false if TcpHandler is allowed to drop the connection, true if the implementer tries to recover 27 | */ 28 | boolean onMissedHeartbeat(); 29 | 30 | /** 31 | * If the above returned true, this method should provide the amount of time TcpHandler should wait before condsidering connection dead. 32 | */ 33 | default long lingerTimeBeforeDisconnect() { 34 | return 0; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/HostnamePortLookupTable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network; 20 | 21 | import java.net.InetSocketAddress; 22 | import java.util.Set; 23 | import java.util.function.BiConsumer; 24 | 25 | public interface HostnamePortLookupTable { 26 | 27 | InetSocketAddress lookup(String description); 28 | 29 | void clear(); 30 | 31 | Set aliases(); 32 | 33 | void put(String description, InetSocketAddress address); 34 | 35 | void forEach(BiConsumer consumer); 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/MarshallableFunction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network; 19 | 20 | import net.openhft.chronicle.wire.Demarshallable; 21 | import net.openhft.chronicle.wire.WireOut; 22 | import net.openhft.chronicle.wire.WriteMarshallable; 23 | import org.jetbrains.annotations.NotNull; 24 | 25 | import java.util.function.Function; 26 | 27 | @FunctionalInterface 28 | public interface MarshallableFunction extends Demarshallable, WriteMarshallable, 29 | Function { 30 | 31 | @Override 32 | default void writeMarshallable(@NotNull WireOut wire) { 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/MethodTcpHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network; 19 | 20 | import net.openhft.chronicle.bytes.Bytes; 21 | import net.openhft.chronicle.bytes.MethodReader; 22 | import net.openhft.chronicle.core.Jvm; 23 | import net.openhft.chronicle.wire.DocumentContext; 24 | import net.openhft.chronicle.wire.Wire; 25 | import net.openhft.chronicle.wire.WireOut; 26 | import net.openhft.chronicle.wire.WireType; 27 | import org.jetbrains.annotations.NotNull; 28 | 29 | import java.util.function.Consumer; 30 | import java.util.function.Supplier; 31 | 32 | public class MethodTcpHandler> extends WireTcpHandler { 33 | 34 | private final Supplier implSupplier; 35 | private final Class outClass; 36 | // Todo: investigate why outSetter is never used. 37 | private final Consumer outSetter; 38 | private MethodReader reader; 39 | // Todo: investigate why output is never used. 40 | private O output; 41 | 42 | /** 43 | * This TcpHandler turns messages into method calls. 44 | * 45 | * @param implSupplier supplier for the object implementing the inbound messages 46 | * @param outClass proxy to call for outbound messages 47 | * @param outSetter setter to call when the output is initialised/changed 48 | */ 49 | public MethodTcpHandler(Supplier implSupplier, Class outClass, Consumer outSetter) { 50 | this.implSupplier = implSupplier; 51 | this.outClass = outClass; 52 | this.outSetter = outSetter; 53 | } 54 | 55 | @Override 56 | protected Wire initialiseOutWire(Bytes out, @NotNull WireType wireType) { 57 | Wire wire = super.initialiseOutWire(out, wireType); 58 | output = wire.methodWriter(outClass); 59 | return wire; 60 | 61 | } 62 | 63 | @Override 64 | protected Wire initialiseInWire(@NotNull WireType wireType, Bytes in) { 65 | Wire wire = super.initialiseInWire(wireType, in); 66 | reader = wire.methodReader(implSupplier.get()); 67 | return wire; 68 | } 69 | 70 | @Override 71 | protected void onRead(@NotNull DocumentContext in, @NotNull WireOut out) { 72 | for (; ; ) { 73 | long pos = in.wire().bytes().readPosition(); 74 | if (!reader.readOne()) 75 | return; 76 | if (pos <= in.wire().bytes().readPosition()) { 77 | Jvm.warn().on(getClass(), "unable to parse data at the end of message " + in.wire().bytes().toDebugString()); 78 | return; 79 | } 80 | } 81 | } 82 | 83 | @Override 84 | protected void onInitialize() { 85 | // Do nothing 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/NetworkContextManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network; 19 | 20 | public interface NetworkContextManager> { 21 | 22 | T nc(); 23 | 24 | void nc(T nc); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/NetworkLog.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network; 19 | 20 | import net.openhft.chronicle.bytes.RandomDataInput; 21 | import net.openhft.chronicle.core.Jvm; 22 | import net.openhft.chronicle.network.tcp.ChronicleSocketChannel; 23 | import org.jetbrains.annotations.NotNull; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | 27 | import java.io.IOException; 28 | import java.nio.ByteBuffer; 29 | 30 | class NetworkLog { 31 | private static final Logger LOG = LoggerFactory.getLogger(NetworkLog.class.getName()); 32 | @NotNull 33 | private final String desc; 34 | private long lastOut = System.currentTimeMillis(); 35 | 36 | public NetworkLog(@NotNull ChronicleSocketChannel channel, String op) { 37 | if (channel.isOpen()) { 38 | String desc0 = "unknown"; 39 | try { 40 | desc0 = op 41 | + " " + channel.getLocalAddress().getPort() 42 | + " " + channel.getRemoteAddress().getPort(); 43 | } catch (IOException e) { 44 | desc0 = "unknown"; 45 | } finally { 46 | desc = desc0; 47 | } 48 | 49 | } else 50 | this.desc = ""; 51 | } 52 | 53 | public void idle() { 54 | if (!Jvm.isDebug() || !LOG.isDebugEnabled()) return; 55 | long now = System.currentTimeMillis(); 56 | if (now - lastOut > 2000) { 57 | lastOut = now; 58 | Jvm.debug().on(getClass(), desc + " idle"); 59 | } 60 | } 61 | 62 | public void log(@NotNull ByteBuffer bytes, int start, int end) { 63 | if (!Jvm.isDebug() || !LOG.isDebugEnabled()) return; 64 | 65 | // avoid inlining this. 66 | log0(bytes, start, end); 67 | } 68 | 69 | private void log0(@NotNull ByteBuffer bytes, int start, int end) { 70 | @NotNull final StringBuilder sb = new StringBuilder(desc); 71 | sb.append(" len: ").append(end - start).append(" - "); 72 | if (end - start > 128) { 73 | for (int i = start; i < start + 64; i++) 74 | appendByte(bytes, sb, i); 75 | sb.append(" ... "); 76 | for (int i = end - 64; i < end; i++) 77 | appendByte(bytes, sb, i); 78 | } else { 79 | for (int i = start; i < end; i++) 80 | appendByte(bytes, sb, i); 81 | } 82 | 83 | Jvm.debug().on(getClass(), sb.toString()); 84 | } 85 | 86 | private void appendByte(@NotNull ByteBuffer bytes, @NotNull StringBuilder sb, int i) { 87 | sb.append(RandomDataInput.charToString[bytes.get(i) & 0xFF]); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/NetworkStatsListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network; 19 | 20 | import net.openhft.chronicle.core.io.Closeable; 21 | import net.openhft.chronicle.network.tcp.ChronicleSocketChannel; 22 | import org.jetbrains.annotations.NotNull; 23 | import org.jetbrains.annotations.Nullable; 24 | 25 | import java.net.InetSocketAddress; 26 | 27 | public interface NetworkStatsListener> extends Closeable { 28 | 29 | /** 30 | * notifies the NetworkStatsListener of the host and port based on the SocketChannel 31 | * 32 | * @param sc SocketChannel 33 | * @param nl NetworkStatsListener 34 | */ 35 | static > void notifyHostPort(@Nullable final ChronicleSocketChannel sc, @Nullable final NetworkStatsListener nl) { 36 | if (nl != null && sc != null && sc.socket() != null 37 | && sc.socket().getRemoteSocketAddress() instanceof InetSocketAddress) { 38 | @NotNull final InetSocketAddress remoteSocketAddress = (InetSocketAddress) sc.socket() 39 | .getRemoteSocketAddress(); 40 | nl.onHostPort(remoteSocketAddress.getHostName(), remoteSocketAddress.getPort()); 41 | } 42 | } 43 | 44 | void networkContext(N networkContext); 45 | 46 | /** 47 | * Called periodically (see tcp.event.monitor.secs system property) with summary network stats 48 | * 49 | * @param writeBps write Bytes/sec 50 | * @param readBps read Bytes/sec 51 | * @param socketPollCountPerSecond socket poll count/sec 52 | */ 53 | void onNetworkStats(long writeBps, long readBps, long socketPollCountPerSecond); 54 | 55 | void onHostPort(String hostName, int port); 56 | 57 | /** 58 | * Notification of individual round trip latency, called only if acknowledge enabled 59 | * 60 | * @param nanosecondLatency latency 61 | */ 62 | void onRoundTripLatency(long nanosecondLatency); 63 | 64 | default void procPrefix(String procPrefix) { 65 | } 66 | 67 | /** 68 | * Notification of individual message one way trip latency (requires sender's clock to be synchronised with receiver's) 69 | * 70 | * @param nanosecondLatency latency 71 | */ 72 | default void onReceiveLatency(long nanosecondLatency) { 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/NetworkUtil.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.network; 2 | 3 | import net.openhft.chronicle.core.Jvm; 4 | import net.openhft.chronicle.core.io.IORuntimeException; 5 | 6 | import java.net.ServerSocket; 7 | import java.net.Socket; 8 | import java.net.SocketException; 9 | 10 | import static net.openhft.chronicle.core.Jvm.getInteger; 11 | 12 | public enum NetworkUtil { 13 | ; 14 | public static final int TCP_BUFFER_SIZE = getTcpBufferSize(); 15 | public static final int TCP_SAFE_SIZE = getInteger("tcp.safe.size", 128 << 10); 16 | public static final boolean TCP_USE_PADDING = Jvm.getBoolean("tcp.use.padding", false); 17 | 18 | private static int getTcpBufferSize() { 19 | final String sizeStr = Jvm.getProperty("TcpEventHandler.tcpBufferSize"); 20 | if (sizeStr != null && !sizeStr.isEmpty()) 21 | try { 22 | final int size = Integer.parseInt(sizeStr); 23 | if (size >= 64 << 10) 24 | return size; 25 | } catch (Exception e) { 26 | Jvm.warn().on(NetworkUtil.class, "Unable to parse tcpBufferSize=" + sizeStr, e); 27 | } 28 | try { 29 | try (ServerSocket ss = new ServerSocket(0)) { 30 | try (Socket s = new Socket("localhost", ss.getLocalPort())) { 31 | s.setReceiveBufferSize(4 << 20); 32 | s.setSendBufferSize(4 << 20); 33 | final int size = Math.min(s.getReceiveBufferSize(), s.getSendBufferSize()); 34 | (size >= 128 << 10 ? Jvm.debug() : Jvm.warn()) 35 | .on(NetworkUtil.class, "tcpBufferSize = " + size / 1024.0 + " KiB"); 36 | return size; 37 | } 38 | } 39 | } catch (Exception e) { 40 | throw new IORuntimeException(e); // problem with networking subsystem. 41 | } 42 | } 43 | 44 | public static void setTcpNoDelay(Socket socket, boolean tcpNoDelay) throws SocketException { 45 | for (int i = 10; i >= 0; i--) { 46 | try { 47 | 48 | socket.setTcpNoDelay(tcpNoDelay); 49 | } catch (SocketException se) { 50 | if (i == 0) 51 | throw se; 52 | Jvm.pause(1); 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/ReadWithFlowControl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network; 20 | 21 | import net.openhft.chronicle.bytes.Bytes; 22 | import net.openhft.chronicle.network.tcp.ChronicleSocketChannel; 23 | import org.jetbrains.annotations.NotNull; 24 | 25 | import java.io.IOException; 26 | import java.nio.ByteBuffer; 27 | 28 | import static java.util.Objects.requireNonNull; 29 | import static net.openhft.chronicle.wire.Wires.lengthOf; 30 | 31 | /** 32 | * provides flow control and back pressure to the socket writer, so that only just one message is read at a time from the TCP/IP socket This class 33 | * is only used in data grid 34 | */ 35 | public final class ReadWithFlowControl implements TcpEventHandler.SocketReader { 36 | 37 | private int len = 0; 38 | private boolean hasReadLen = false; 39 | private int position = 0; 40 | private int limit = 4; 41 | private int rawLen; 42 | 43 | /** 44 | * reads just a single message from the socket 45 | */ 46 | public int read(@NotNull final ChronicleSocketChannel socketChannel, @NotNull final Bytes bytes) throws IOException { 47 | ByteBuffer bb = requireNonNull(bytes.underlyingObject()); 48 | bb.limit(limit); 49 | bb.position(position); 50 | if (hasReadLen) { 51 | // write the len 52 | bytes.writeInt(0, rawLen); 53 | } else { 54 | // read the len 55 | socketChannel.read(bb); 56 | 57 | if (bb.position() < bb.limit()) 58 | return 0; 59 | rawLen = bytes.readInt(this.len); 60 | len = lengthOf(rawLen); 61 | bytes.ensureCapacity(this.len + 4L); 62 | bb = requireNonNull(bytes.underlyingObject()); 63 | limit(this.len + 8); 64 | position(4); 65 | limit(len + 4); 66 | bb.limit(limit); 67 | hasReadLen = true; 68 | } 69 | 70 | socketChannel.read(bb); 71 | 72 | // we can read the message, now read the len of the next message 73 | if (bb.position() == len + 4) { 74 | position(0); 75 | limit(4); 76 | final int result = len; 77 | bytes.readPositionRemaining(0, len); 78 | hasReadLen = false; 79 | len = 0; 80 | // read all the data from the buffer 81 | return result; 82 | } 83 | 84 | // we can read the message and the len 85 | if (bb.position() == len + 8) { 86 | position(4); 87 | final int result = len; 88 | rawLen = bytes.readInt(this.len); 89 | this.len = lengthOf(rawLen); 90 | limit(this.len + 4); 91 | bytes.ensureCapacity(this.len + 4L); 92 | bb = requireNonNull(bytes.underlyingObject()); 93 | bb.position(len + 4); 94 | bytes.readPositionRemaining(0, result); 95 | hasReadLen = true; 96 | 97 | return result; 98 | } 99 | 100 | if (bb.position() > len + 4) 101 | throw new IllegalStateException("an error has occurred, position=" + bb.position()); 102 | 103 | return 0; 104 | } 105 | 106 | private void limit(final int limit) { 107 | this.limit = limit; 108 | } 109 | 110 | private void position(final int position) { 111 | this.position = position; 112 | } 113 | } -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/ServerThreadingStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network; 19 | 20 | @Deprecated(/* To be considered for removal in x.24 */) 21 | public enum ServerThreadingStrategy { 22 | 23 | SINGLE_THREADED("uses a single threaded prioritised event loop," + 24 | " where the reads take priority over the asynchronous writes"), 25 | @Deprecated(/* To be considered for removal in x.24 */) 26 | CONCURRENT("each client connection is partitioned to a limit number of threads, " + 27 | "This is ideal when you have a small number of client connections on a server with a large number of free cores"); 28 | 29 | private final String description; 30 | 31 | ServerThreadingStrategy(String description) { 32 | this.description = description; 33 | } 34 | 35 | public String getDescription() { 36 | return description; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/SessionMode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network; 19 | 20 | public enum SessionMode { 21 | ACTIVE, 22 | PASSIVE 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/SocketConnectionNotifier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network; 19 | 20 | import net.openhft.chronicle.core.Jvm; 21 | import net.openhft.chronicle.wire.Marshallable; 22 | 23 | import static net.openhft.chronicle.core.Mocker.intercepting; 24 | 25 | @FunctionalInterface 26 | public interface SocketConnectionNotifier extends Marshallable { 27 | 28 | static SocketConnectionNotifier newDefaultConnectionNotifier() { 29 | return intercepting(SocketConnectionNotifier.class, 30 | "connection ", 31 | msg -> Jvm.debug().on(SocketConnectionNotifier.class, msg)); 32 | } 33 | 34 | void onConnected(String host, long port, T nc); 35 | 36 | default void onDisconnected(String host, long port) { 37 | // Do nothing 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/TcpEventHandlerManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network; 19 | 20 | import net.openhft.chronicle.network.api.TcpHandler; 21 | 22 | @FunctionalInterface 23 | interface TcpEventHandlerManager> { 24 | void tcpHandler(TcpHandler tcpHandler); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/TcpHandlerBias.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network; 20 | 21 | import java.util.function.Supplier; 22 | 23 | public enum TcpHandlerBias implements Supplier { 24 | /** 25 | * Defines a read-bias for TcpEventHandler. This will prioritise reads, and will only do 1 write per 8 reads 26 | */ 27 | READ { 28 | @Override 29 | public BiasController get() { 30 | return new ReadBiasController(); 31 | } 32 | }, 33 | /** 34 | * Defines a fair TcpEventHandler biasing, with 1 write per each read 35 | */ 36 | FAIR { 37 | @Override 38 | public BiasController get() { 39 | return new FairBiasController(); 40 | } 41 | }, 42 | /** 43 | * Defines a write-bias for TcpEventHandler. This will prioritise writes, and will only do 1 read per 8 writes 44 | */ 45 | WRITE { 46 | @Override 47 | public BiasController get() { 48 | return new WriteBiasController(); 49 | } 50 | }; 51 | 52 | interface BiasController { 53 | 54 | /** 55 | * Returns if a read operation is permitted according 56 | * to this BiasController. 57 | * 58 | * @return if a read operation is permitted according 59 | * to this BiasController 60 | */ 61 | boolean canRead(); 62 | 63 | /** 64 | * Returns if a write operation is permitted according 65 | * to this BiasController. 66 | * 67 | * @return if a write operation is permitted according 68 | * to this BiasController 69 | */ 70 | boolean canWrite(); 71 | } 72 | 73 | private static final int RATIO = 8; 74 | 75 | private static final class ReadBiasController implements BiasController { 76 | private int reads = 0; 77 | 78 | @Override 79 | public boolean canRead() { 80 | reads++; 81 | return true; 82 | } 83 | 84 | @Override 85 | public boolean canWrite() { 86 | if (reads >= RATIO) { 87 | reads = 0; 88 | return true; 89 | } 90 | return false; 91 | } 92 | } 93 | 94 | private static final class WriteBiasController implements BiasController { 95 | private int writes = 0; 96 | 97 | @Override 98 | public boolean canWrite() { 99 | writes++; 100 | return true; 101 | } 102 | 103 | @Override 104 | public boolean canRead() { 105 | if (writes >= RATIO) { 106 | writes = 0; 107 | return true; 108 | } 109 | return false; 110 | } 111 | } 112 | 113 | private static final class FairBiasController implements BiasController { 114 | @Override 115 | public boolean canRead() { 116 | return true; 117 | } 118 | 119 | @Override 120 | public boolean canWrite() { 121 | return true; 122 | } 123 | } 124 | } -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/VanillaClientConnectionMonitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network; 20 | 21 | import net.openhft.chronicle.network.connection.ClientConnectionMonitor; 22 | import net.openhft.chronicle.wire.AbstractMarshallableCfg; 23 | import org.jetbrains.annotations.Nullable; 24 | 25 | import java.net.SocketAddress; 26 | 27 | import static net.openhft.chronicle.core.Jvm.debug; 28 | 29 | public class VanillaClientConnectionMonitor extends AbstractMarshallableCfg implements ClientConnectionMonitor { 30 | 31 | @Override 32 | public void onConnected(String name, @Nullable SocketAddress socketAddress) { 33 | debug().on(this.getClass(), "onConnected name=" + name + ",socketAddress=" + socketAddress); 34 | } 35 | 36 | @Override 37 | public void onDisconnected(String name, @Nullable SocketAddress socketAddress) { 38 | debug().on(this.getClass(), "onDisconnected name=" + name + ",socketAddress=" + socketAddress); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/WireTypeSniffingTcpHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network; 19 | 20 | import net.openhft.chronicle.bytes.Bytes; 21 | import net.openhft.chronicle.core.io.SimpleCloseable; 22 | import net.openhft.chronicle.network.api.TcpHandler; 23 | import net.openhft.chronicle.network.connection.WireOutPublisher; 24 | import net.openhft.chronicle.wire.WireType; 25 | import net.openhft.chronicle.wire.Wires; 26 | import org.jetbrains.annotations.NotNull; 27 | 28 | import java.util.function.Function; 29 | 30 | import static net.openhft.chronicle.wire.WireType.*; 31 | 32 | /** 33 | * sets the wire-type in the network context by inspecting the byte message 34 | */ 35 | public class WireTypeSniffingTcpHandler> extends SimpleCloseable implements TcpHandler { 36 | 37 | @NotNull 38 | private final TcpEventHandler handlerManager; 39 | 40 | @NotNull 41 | private final Function> delegateHandlerFactory; 42 | 43 | public WireTypeSniffingTcpHandler(@NotNull final TcpEventHandler handlerManager, 44 | @NotNull final Function> delegateHandlerFactory) { 45 | this.handlerManager = handlerManager; 46 | this.delegateHandlerFactory = delegateHandlerFactory; 47 | } 48 | 49 | @Override 50 | public void process(final @NotNull Bytes in, 51 | final @NotNull Bytes out, 52 | T nc) { 53 | throwExceptionIfClosed(); 54 | 55 | final WireOutPublisher publisher = nc.wireOutPublisher(); 56 | 57 | if (publisher != null) 58 | publisher.applyAction(out); 59 | 60 | // read the wire type of the messages from the header - the header its self must be 61 | // of type TEXT or BINARY 62 | if (in.readRemaining() < 5) 63 | return; 64 | 65 | final int required = Wires.lengthOf(in.readInt(in.readPosition())); 66 | 67 | assert required < 10 << 20; 68 | 69 | if (in.readRemaining() < required + 4) 70 | return; 71 | 72 | final byte b = in.readByte(4); 73 | 74 | @NotNull final WireType wireType; 75 | if (b < 0) 76 | wireType = DELTA_BINARY.isAvailable() ? DELTA_BINARY : BINARY; 77 | else if (b > ' ') 78 | wireType = TEXT; 79 | else 80 | throw new IllegalStateException("Unable to identify the wire type from " + Integer.toHexString(b & 0xFF)); 81 | 82 | // the type of the header 83 | nc.wireType(wireType); 84 | 85 | final TcpHandler handler = delegateHandlerFactory.apply(nc); 86 | 87 | if (handler instanceof NetworkContextManager) 88 | ((NetworkContextManager) handler).nc(nc); 89 | 90 | handlerManager.tcpHandler(handler); 91 | } 92 | 93 | @Override 94 | public String toString() { 95 | return "WireTypeSniffingTcpHandler@" + Integer.toHexString(hashCode()); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/api/TcpHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.api; 19 | 20 | import net.openhft.chronicle.bytes.Bytes; 21 | import net.openhft.chronicle.core.io.Closeable; 22 | import net.openhft.chronicle.network.ClientClosedProvider; 23 | import net.openhft.chronicle.network.NetworkContext; 24 | import net.openhft.chronicle.network.api.session.SessionDetailsProvider; 25 | import org.jetbrains.annotations.NotNull; 26 | 27 | import java.nio.ByteBuffer; 28 | 29 | public interface TcpHandler> extends ClientClosedProvider, Closeable { 30 | 31 | /** 32 | * The server reads the bytes {@code in} from the client and sends a response {@code out} back 33 | * to the client. 34 | * 35 | * @param in the bytes send from the client 36 | * @param out the response send back to the client 37 | */ 38 | void process(@NotNull Bytes in, @NotNull Bytes out, N nc); 39 | 40 | default void sendHeartBeat(Bytes out, SessionDetailsProvider sessionDetails) { 41 | } 42 | 43 | default void onEndOfConnection(boolean heartbeatTimeOut) { 44 | } 45 | 46 | default void onReadTime(long readTimeNS, final ByteBuffer inBB, final int position, final int limit) { 47 | } 48 | 49 | default void onWriteTime(long writeTimeNS, 50 | final ByteBuffer byteBuffer, 51 | final int start, 52 | final int position) { 53 | } 54 | 55 | /** 56 | * Perform any low priority work, called when the handler is not busy, or after it has been 57 | * busy for a long time. 58 | */ 59 | default void performIdleWork() { 60 | } 61 | 62 | /** 63 | * Check if an application-layer timeout has occurred, if this returns true, 64 | * the current connection will be dropped and a reconnection attempt will be made 65 | */ 66 | default boolean hasTimedOut() { 67 | return false; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/api/session/SessionDetails.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.api.session; 19 | 20 | import net.openhft.chronicle.network.SessionMode; 21 | import net.openhft.chronicle.network.connection.EventId; 22 | import net.openhft.chronicle.wire.WireOut; 23 | import net.openhft.chronicle.wire.WireType; 24 | import net.openhft.chronicle.wire.WriteMarshallable; 25 | import org.jetbrains.annotations.NotNull; 26 | import org.jetbrains.annotations.Nullable; 27 | 28 | import java.net.InetSocketAddress; 29 | import java.util.UUID; 30 | 31 | /** 32 | * Session local details stored here.

Created by Peter Lawrey on 01/06/15. 33 | */ 34 | public interface SessionDetails extends WriteMarshallable { 35 | 36 | // a unique id used to identify this session, this field is by contract immutable 37 | UUID sessionId(); 38 | 39 | // a unique id used to identify the client 40 | UUID clientId(); 41 | 42 | @Nullable 43 | String userId(); 44 | 45 | @Nullable 46 | String securityToken(); 47 | 48 | @Nullable 49 | String domain(); 50 | 51 | SessionMode sessionMode(); 52 | 53 | @Nullable 54 | InetSocketAddress clientAddress(); 55 | 56 | long connectTimeMS(); 57 | 58 | void set(Class infoClass, I info); 59 | 60 | @NotNull 61 | I get(Class infoClass); 62 | 63 | @Nullable 64 | WireType wireType(); 65 | 66 | byte hostId(); 67 | 68 | @Override 69 | default void writeMarshallable(@NotNull WireOut w) { 70 | w.writeEventName(EventId.userId).text(userId()) 71 | .writeEventName(EventId.domain).text(domain()); 72 | if (sessionMode() != null) 73 | w.writeEventName(EventId.sessionMode).text(sessionMode().toString()); 74 | w.writeEventName(EventId.securityToken).text(securityToken()) 75 | .writeEventName(EventId.clientId).text(clientId().toString()) 76 | .writeEventName(EventId.hostId).int8(hostId()) 77 | .writeEventName(EventId.wireType).asEnum(wireType()); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/api/session/SessionDetailsProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.api.session; 19 | 20 | import net.openhft.chronicle.core.io.IORuntimeException; 21 | import net.openhft.chronicle.network.SessionMode; 22 | import net.openhft.chronicle.network.VanillaSessionDetails; 23 | import net.openhft.chronicle.network.connection.EventId; 24 | import net.openhft.chronicle.wire.Marshallable; 25 | import net.openhft.chronicle.wire.WireIn; 26 | import net.openhft.chronicle.wire.WireOut; 27 | import net.openhft.chronicle.wire.WireType; 28 | import org.jetbrains.annotations.NotNull; 29 | import org.jetbrains.annotations.Nullable; 30 | 31 | import java.net.InetSocketAddress; 32 | import java.util.UUID; 33 | public interface SessionDetailsProvider extends SessionDetails, Marshallable { 34 | 35 | void connectTimeMS(long connectTimeMS); 36 | 37 | void clientAddress(InetSocketAddress connectionAddress); 38 | 39 | void securityToken(String securityToken); 40 | 41 | void userId(String userId); 42 | 43 | void domain(String domain); 44 | 45 | void sessionMode(SessionMode sessionMode); 46 | 47 | void clientId(UUID clientId); 48 | 49 | void wireType(@Nullable WireType wireType); 50 | 51 | void hostId(byte id); 52 | 53 | @Override 54 | default void readMarshallable(@NotNull WireIn wire) throws IORuntimeException { 55 | userId(wire.read(EventId.userId).text()); 56 | domain(wire.read(EventId.domain).text()); 57 | sessionMode(wire.read(EventId.sessionMode).object(SessionMode.class)); 58 | securityToken(wire.read(EventId.securityToken).text()); 59 | @Nullable final String uid = wire.read(EventId.clientId).text(); 60 | if (uid != null) 61 | clientId(UUID.fromString(uid)); 62 | wireType(wire.read(EventId.wireType).object(WireType.class)); 63 | hostId(wire.read(EventId.hostId).int8()); 64 | } 65 | 66 | @Override 67 | default void writeMarshallable(@NotNull WireOut w) { 68 | SessionDetails.super.writeMarshallable(w); 69 | } 70 | 71 | @NotNull 72 | static SessionDetailsProvider create() { 73 | return new VanillaSessionDetails(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/api/session/SessionProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.api.session; 19 | 20 | import org.jetbrains.annotations.NotNull; 21 | import org.jetbrains.annotations.Nullable; 22 | 23 | /** 24 | * A holder for the Session specific details i.e. for a remote client. 25 | */ 26 | public interface SessionProvider { 27 | /** 28 | * @return the current session details 29 | */ 30 | @Nullable 31 | SessionDetails get(); 32 | 33 | /** 34 | * Replace the session details 35 | * 36 | * @param sessionDetails to set to 37 | */ 38 | void set(@NotNull SessionDetails sessionDetails); 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/api/session/SubHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.api.session; 19 | 20 | import net.openhft.chronicle.core.io.Closeable; 21 | import net.openhft.chronicle.core.io.ManagedCloseable; 22 | import net.openhft.chronicle.network.NetworkContext; 23 | import net.openhft.chronicle.network.NetworkContextManager; 24 | import net.openhft.chronicle.wire.WireIn; 25 | import net.openhft.chronicle.wire.WireOut; 26 | import org.jetbrains.annotations.NotNull; 27 | 28 | import java.util.concurrent.RejectedExecutionException; 29 | 30 | public interface SubHandler> extends NetworkContextManager, ManagedCloseable { 31 | 32 | void cid(long cid); 33 | 34 | long cid(); 35 | 36 | void csp(@NotNull String cspText); 37 | 38 | String csp(); 39 | 40 | void onRead(@NotNull WireIn inWire, @NotNull WireOut outWire); 41 | 42 | Closeable closable(); 43 | 44 | void remoteIdentifier(int remoteIdentifier); 45 | 46 | void localIdentifier(int localIdentifier); 47 | 48 | /** 49 | * called after all the construction and configuration has completed 50 | * 51 | * @param outWire allow data to be written 52 | */ 53 | void onInitialize(WireOut outWire) throws RejectedExecutionException; 54 | 55 | /** 56 | * Some events may result in long-lived actions, which must yield periodically to allow (eg) buffers to clear (out messages to be sent) 57 | * A busy handler can indicate a long-lived action by returning true from inProgress 58 | * The caller should then use this to invoke onTouch to give the handler another slice 59 | * 60 | * @param outWire 61 | * @return - true if the long-lived action is complete; false if there's more to do 62 | */ 63 | default boolean onTouch(WireOut outWire) { return true; } 64 | 65 | /** 66 | * Is a long-lived action (see above) in progress? 67 | * @return - true if long-lived action in progress; else false 68 | */ 69 | default boolean inProgress() { return false; } 70 | 71 | void closeable(Closeable closeable); 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/api/session/WritableSubHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.api.session; 19 | 20 | import net.openhft.chronicle.network.NetworkContext; 21 | import net.openhft.chronicle.wire.WireOut; 22 | 23 | public interface WritableSubHandler> extends SubHandler { 24 | void onWrite(WireOut outWire); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/cluster/AbstractSubHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.cluster; 19 | 20 | import net.openhft.chronicle.core.io.Closeable; 21 | import net.openhft.chronicle.network.NetworkContext; 22 | import net.openhft.chronicle.network.api.session.SubHandler; 23 | import net.openhft.chronicle.wire.WireIn; 24 | import net.openhft.chronicle.wire.WireOut; 25 | import net.openhft.chronicle.wire.WriteMarshallable; 26 | import org.jetbrains.annotations.NotNull; 27 | 28 | public abstract class AbstractSubHandler> implements SubHandler { 29 | private Closeable closeable; 30 | private T nc; 31 | private long cid; 32 | private String csp; 33 | private int remoteIdentifier; 34 | private int localIdentifier; 35 | private volatile boolean isClosed; 36 | 37 | @Override 38 | public void cid(long cid) { 39 | this.cid = cid; 40 | } 41 | 42 | @Override 43 | public long cid() { 44 | return cid; 45 | } 46 | 47 | @Override 48 | public void csp(@NotNull String csp) { 49 | this.csp = csp; 50 | } 51 | 52 | @Override 53 | public String csp() { 54 | return this.csp; 55 | } 56 | 57 | @Override 58 | public T nc() { 59 | return nc; 60 | } 61 | 62 | @Override 63 | public void closeable(Closeable closeable) { 64 | this.closeable = closeable; 65 | } 66 | 67 | @Override 68 | public Closeable closable() { 69 | return closeable; 70 | } 71 | 72 | @Override 73 | public void nc(T nc) { 74 | this.nc = nc; 75 | } 76 | 77 | public int remoteIdentifier() { 78 | return remoteIdentifier; 79 | } 80 | 81 | @Override 82 | public void remoteIdentifier(int remoteIdentifier) { 83 | this.remoteIdentifier = remoteIdentifier; 84 | } 85 | 86 | public void publish(WriteMarshallable event) { 87 | nc().wireOutPublisher().publish(event); 88 | } 89 | 90 | @Override 91 | public void localIdentifier(int localIdentifier) { 92 | this.localIdentifier = localIdentifier; 93 | } 94 | 95 | public int localIdentifier() { 96 | return localIdentifier; 97 | } 98 | 99 | @Override 100 | public void close() { 101 | isClosed = true; 102 | } 103 | 104 | @Override 105 | public boolean isClosed() { 106 | return isClosed; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/cluster/ClusteredNetworkContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.cluster; 19 | 20 | import net.openhft.chronicle.core.threads.EventLoop; 21 | import net.openhft.chronicle.network.NetworkContext; 22 | 23 | public interface ClusteredNetworkContext> extends NetworkContext { 24 | default EventLoop eventLoop() { 25 | throw new UnsupportedOperationException(); 26 | } 27 | 28 | byte getLocalHostIdentifier(); 29 | 30 | > C clusterContext(); 31 | } -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/cluster/HeartbeatEventHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.cluster; 19 | 20 | @FunctionalInterface 21 | public interface HeartbeatEventHandler { 22 | void onMessageReceived(); 23 | 24 | /** 25 | * Has a timeout been detected? 26 | * 27 | * @return true if a timeout has been detected, false otherwise 28 | */ 29 | default boolean hasTimedOut() { 30 | return false; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/cluster/HostDetails.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.cluster; 19 | 20 | import net.openhft.chronicle.wire.SelfDescribingMarshallable; 21 | import org.jetbrains.annotations.NotNull; 22 | 23 | public class HostDetails extends SelfDescribingMarshallable { 24 | 25 | private int hostId; 26 | private int tcpBufferSize; 27 | private String connectUri; 28 | 29 | public int tcpBufferSize() { 30 | return tcpBufferSize; 31 | } 32 | 33 | @NotNull 34 | public HostDetails hostId(int hostId) { 35 | this.hostId = hostId; 36 | return this; 37 | } 38 | 39 | public String connectUri() { 40 | return connectUri; 41 | } 42 | 43 | public int hostId() { 44 | return hostId; 45 | } 46 | 47 | @NotNull 48 | public HostDetails tcpBufferSize(int tcpBufferSize) { 49 | this.tcpBufferSize = tcpBufferSize; 50 | return this; 51 | } 52 | 53 | @NotNull 54 | public HostDetails connectUri(@NotNull String connectUri) { 55 | this.connectUri = connectUri; 56 | return this; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/cluster/LoggingNetworkStatsListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2020 chronicle.software 3 | */ 4 | package net.openhft.chronicle.network.cluster; 5 | 6 | import net.openhft.chronicle.core.Jvm; 7 | import net.openhft.chronicle.network.NetworkContext; 8 | import net.openhft.chronicle.network.NetworkStatsListener; 9 | 10 | @SuppressWarnings("rawtypes") 11 | public enum LoggingNetworkStatsListener implements NetworkStatsListener { 12 | INSTANCE; 13 | 14 | @Override 15 | public void networkContext(final NetworkContext networkContext) { 16 | // Ignore 17 | } 18 | 19 | @Override 20 | public void onNetworkStats(final long writeBps, final long readBps, final long socketPollCountPerSecond) { 21 | if (Jvm.isDebugEnabled(LoggingNetworkStatsListener.class)) 22 | Jvm.debug().on(LoggingNetworkStatsListener.class, String.format( 23 | "networkStats: writeBps %d, readBps %d, pollCount/sec %d", 24 | writeBps, readBps, socketPollCountPerSecond)); 25 | 26 | } 27 | 28 | @Override 29 | public void onHostPort(final String hostName, final int port) { 30 | if (Jvm.isDebugEnabled(LoggingNetworkStatsListener.class)) 31 | Jvm.debug().on(LoggingNetworkStatsListener.class, String.format("onHostPort %s, %d", 32 | hostName, port)); 33 | } 34 | 35 | @Override 36 | public void onRoundTripLatency(final long latencyNanos) { 37 | if (Jvm.isDebugEnabled(LoggingNetworkStatsListener.class)) 38 | Jvm.debug().on(LoggingNetworkStatsListener.class, String.format("onRoundTripLatency %d", latencyNanos)); 39 | } 40 | 41 | @Override 42 | public void close() { 43 | // Do nothing 44 | } 45 | 46 | @Override 47 | public boolean isClosed() { 48 | return false; 49 | } 50 | } -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/cluster/VanillaClusteredNetworkContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network.cluster; 20 | 21 | import net.openhft.chronicle.core.Jvm; 22 | import net.openhft.chronicle.core.threads.EventLoop; 23 | import net.openhft.chronicle.network.VanillaNetworkContext; 24 | import org.jetbrains.annotations.NotNull; 25 | 26 | public class VanillaClusteredNetworkContext, C extends ClusterContext> 27 | extends VanillaNetworkContext implements ClusteredNetworkContext { 28 | 29 | @NotNull 30 | private final EventLoop eventLoop; 31 | 32 | @NotNull 33 | protected final C clusterContext; 34 | 35 | public VanillaClusteredNetworkContext(@NotNull C clusterContext) { 36 | this.clusterContext = clusterContext; 37 | this.eventLoop = clusterContext.eventLoop(); 38 | heartbeatListener(this::logMissedHeartbeat); 39 | serverThreadingStrategy(clusterContext.serverThreadingStrategy()); 40 | } 41 | 42 | @Override 43 | public EventLoop eventLoop() { 44 | return eventLoop; 45 | } 46 | 47 | @Override 48 | public byte getLocalHostIdentifier() { 49 | return clusterContext.localIdentifier(); 50 | } 51 | 52 | @Override 53 | public C clusterContext() { 54 | return clusterContext; 55 | } 56 | 57 | private boolean logMissedHeartbeat() { 58 | Jvm.warn().on(VanillaClusteredNetworkContext.class, "Missed heartbeat on network context " + socketChannel()); 59 | return false; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/cluster/handlers/Registerable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.cluster.handlers; 19 | 20 | import net.openhft.chronicle.network.api.session.SubHandler; 21 | 22 | import java.util.Map; 23 | 24 | public interface Registerable { 25 | Object registryKey(); 26 | 27 | void registry(Map registry); 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/cluster/handlers/RejectedHandlerException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.cluster.handlers; 19 | 20 | public class RejectedHandlerException extends RuntimeException { 21 | public RejectedHandlerException(String message) { 22 | super(message); 23 | } 24 | 25 | public RejectedHandlerException() { 26 | super(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/connection/AbstractAsyncSubscription.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.connection; 19 | 20 | import net.openhft.chronicle.wire.WireOut; 21 | import org.jetbrains.annotations.NotNull; 22 | 23 | /** 24 | * @deprecated This has been moved to DataGrid without a replacement 25 | */ 26 | @Deprecated(/* For removal in x.25 */) 27 | public abstract class AbstractAsyncSubscription implements AsyncSubscription { 28 | 29 | private final long tid; 30 | @NotNull 31 | private final TcpChannelHub hub; 32 | private final String csp; 33 | private final String name; 34 | 35 | protected AbstractAsyncSubscription(@NotNull final TcpChannelHub hub, String csp, String name) { 36 | tid = hub.nextUniqueTransaction(System.currentTimeMillis()); 37 | this.hub = hub; 38 | this.csp = csp; 39 | this.name = name; 40 | } 41 | 42 | protected AbstractAsyncSubscription(@NotNull final TcpChannelHub hub, String csp, byte identifier, String name) { 43 | this.tid = hub.nextUniqueTransaction(System.currentTimeMillis()) * identifier; 44 | this.hub = hub; 45 | this.csp = csp; 46 | this.name = name; 47 | } 48 | 49 | @Override 50 | public long tid() { 51 | return tid; 52 | } 53 | 54 | @Override 55 | public void applySubscribe() { 56 | assert hub.outBytesLock().isHeldByCurrentThread(); 57 | hub.writeMetaDataForKnownTID(tid(), hub.outWire(), csp, 0, false); 58 | hub.outWire().writeDocument(false, this::onSubscribe); 59 | hub.writeSocket(hub.outWire(), false, false); // will retry after reconnect. 60 | } 61 | 62 | /** 63 | * called when ever the TcpChannelHub is ready to make a subscription 64 | * 65 | * @param wireOut the wire to write the subscription to 66 | */ 67 | public abstract void onSubscribe(WireOut wireOut); 68 | 69 | /** 70 | * called whenever the connection to the server has been dropped 71 | */ 72 | @Override 73 | public void onClose() { 74 | 75 | } 76 | 77 | @NotNull 78 | @Override 79 | public String toString() { 80 | return "AbstractAsyncSubscription{" + 81 | "name='" + name + '\'' + 82 | ", csp='" + csp + '\'' + 83 | ", tid=" + tid + 84 | '}'; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/connection/AbstractAsyncTemporarySubscription.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.connection; 19 | 20 | import org.jetbrains.annotations.NotNull; 21 | import org.jetbrains.annotations.Nullable; 22 | 23 | /** 24 | * @deprecated This has been moved to DataGrid without a replacement 25 | */ 26 | @Deprecated(/* For removal in x.25 */) 27 | public abstract class AbstractAsyncTemporarySubscription extends AbstractAsyncSubscription 28 | implements AsyncTemporarySubscription { 29 | 30 | /** 31 | * @param hub handles the tcp connectivity. 32 | * @param csp the url of the subscription. 33 | * @param name the name of the subscription 34 | */ 35 | protected AbstractAsyncTemporarySubscription(@NotNull TcpChannelHub hub, @Nullable String csp, String name) { 36 | super(hub, csp, name); 37 | } 38 | 39 | /** 40 | * @param hub handles the tcp connectivity. 41 | * @param csp the url of the subscription. 42 | * @param id use as a seed to the tid, makes unique tid's makes reading the logs easier. 43 | * @param name the name of the subscription 44 | */ 45 | protected AbstractAsyncTemporarySubscription(@NotNull TcpChannelHub hub, @Nullable String csp, byte id, String name) { 46 | super(hub, csp, id, name); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/connection/AsyncSubscription.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.connection; 19 | 20 | import net.openhft.chronicle.wire.WireIn; 21 | import org.jetbrains.annotations.NotNull; 22 | 23 | /** 24 | * @deprecated This has been moved to DataGrid without a replacement 25 | */ 26 | @Deprecated(/* For removal in x.25 */) 27 | interface AsyncSubscription { 28 | 29 | /** 30 | * returns the unique tid that will be used in the subscription, this tid must be unique per 31 | * socket connection 32 | * 33 | * @return the unique tid 34 | */ 35 | long tid(); 36 | 37 | /** 38 | * Implement this to establish a subscription with the server 39 | */ 40 | void applySubscribe(); 41 | 42 | /** 43 | * Implement this to consume the subscription 44 | * 45 | * @param inWire the wire to write the subscription to 46 | */ 47 | void onConsumer(@NotNull final WireIn inWire); 48 | 49 | /** 50 | * called when the socket connection is closed 51 | */ 52 | void onClose(); 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/connection/AsyncTemporarySubscription.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.connection; 19 | 20 | /** 21 | * TemporarySubscriptions are not re-established after a socket disconnection 22 | * 23 | * @author Rob Austin. 24 | * @deprecated This has been moved to DataGrid without a replacement 25 | */ 26 | @Deprecated(/* For removal in x.25 */) 27 | interface AsyncTemporarySubscription extends AsyncSubscription { 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/connection/ClientConnectionMonitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.connection; 19 | 20 | import net.openhft.chronicle.wire.Marshallable; 21 | import org.jetbrains.annotations.Nullable; 22 | 23 | import java.net.SocketAddress; 24 | 25 | public interface ClientConnectionMonitor extends FatalFailureMonitor, Marshallable { 26 | 27 | /** 28 | * Call just after the client as successfully established a connection to the server 29 | * 30 | * @param name the name of the connection 31 | * @param socketAddress the address that we have just connected to or @null if not known 32 | */ 33 | void onConnected(@Nullable String name, @Nullable SocketAddress socketAddress); 34 | 35 | /** 36 | * call just after the client has disconnect to the server, this maybe called as part of a 37 | * failover 38 | * 39 | * @param name the name of the connection 40 | * @param socketAddress the address of the socket that we have been disconnected from or @null if not known 41 | */ 42 | void onDisconnected(@Nullable String name, @Nullable SocketAddress socketAddress); 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/connection/ConnectionListeners.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.connection; 19 | 20 | import net.openhft.chronicle.core.Jvm; 21 | import net.openhft.chronicle.network.ConnectionListener; 22 | 23 | public enum ConnectionListeners implements ConnectionListener { 24 | NONE { 25 | @Override 26 | public void onConnected(int localIdentifier, int remoteIdentifier, boolean isAcceptor) { 27 | // Do Nothing 28 | } 29 | 30 | @Override 31 | public void onDisconnected(int localIdentifier, int remoteIdentifier, boolean isAcceptor) { 32 | // Do Nothing 33 | } 34 | }, 35 | LOGGING { 36 | @Override 37 | public void onConnected(int localIdentifier, int remoteIdentifier, boolean isAcceptor) { 38 | Jvm.startup().on(getClass(), "onConnected lid:" + localIdentifier + ", rid:" + remoteIdentifier + ", acceptor:" + isAcceptor); 39 | } 40 | 41 | @Override 42 | public void onDisconnected(int localIdentifier, int remoteIdentifier, boolean isAcceptor) { 43 | Jvm.startup().on(getClass(), "onDisconnected lid:" + localIdentifier + ", rid:" + remoteIdentifier + ", acceptor:" + isAcceptor); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/connection/CoreFields.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.connection; 19 | 20 | import net.openhft.chronicle.wire.ValueIn; 21 | import net.openhft.chronicle.wire.WireIn; 22 | import net.openhft.chronicle.wire.WireKey; 23 | import net.openhft.chronicle.wire.Wires; 24 | import org.jetbrains.annotations.NotNull; 25 | public enum CoreFields implements WireKey { 26 | tid, 27 | csp, 28 | cid, 29 | reply, 30 | exception, 31 | lastUpdateTime, 32 | handler; 33 | 34 | @NotNull 35 | static final ThreadLocal cpsBuilder = ThreadLocal.withInitial(StringBuilder::new); 36 | 37 | private static long longEvent(@NotNull final WireKey expecting, @NotNull final WireIn wire) { 38 | final StringBuilder eventName = Wires.acquireStringBuilder(); 39 | long position = wire.bytes().readPosition(); 40 | @NotNull final ValueIn valueIn = wire.readEventName(eventName); 41 | if (expecting.contentEquals(eventName)) 42 | return valueIn.int64(); 43 | 44 | throw new IllegalArgumentException("expecting a " + expecting 45 | + " was\n" + wire.bytes().toHexString(position, wire.bytes().readLimit() - position)); 46 | } 47 | 48 | @NotNull 49 | public static StringBuilder stringEvent(@NotNull final WireKey expecting, @NotNull StringBuilder using, 50 | @NotNull final WireIn wire) { 51 | final StringBuilder eventName = Wires.acquireStringBuilder(); 52 | @NotNull final ValueIn valueIn = wire.readEventName(eventName); 53 | if (expecting.contentEquals(eventName)) { 54 | valueIn.textTo(using); 55 | return using; 56 | } 57 | 58 | throw new IllegalArgumentException("expecting a " + expecting); 59 | } 60 | 61 | public static long tid(@NotNull final WireIn wire) { 62 | return longEvent(CoreFields.tid, wire); 63 | } 64 | 65 | public static long cid(@NotNull final WireIn wire) { 66 | return longEvent(CoreFields.cid, wire); 67 | } 68 | 69 | @NotNull 70 | public static StringBuilder csp(@NotNull final WireIn wire) { 71 | return stringEvent(CoreFields.csp, cpsBuilder.get(), wire); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/connection/EventId.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.connection; 19 | 20 | import net.openhft.chronicle.wire.WireKey; 21 | 22 | public enum EventId implements WireKey { 23 | heartbeat, 24 | heartbeatReply, 25 | onClientClosing, 26 | onClosingReply, 27 | userId, 28 | sessionMode, 29 | domain, 30 | securityToken, 31 | clientId, 32 | wireType, 33 | hostId 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/connection/FatalFailureMonitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.connection; 19 | 20 | import org.jetbrains.annotations.Nullable; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | public interface FatalFailureMonitor { 25 | Logger LOG = LoggerFactory.getLogger(FatalFailureMonitor.class); 26 | 27 | /** 28 | * A no-op implementation 29 | */ 30 | FatalFailureMonitor NO_OP = new FatalFailureMonitor() { 31 | @Override 32 | public void onFatalFailure(@Nullable String name, String message) { 33 | // Do nothing 34 | } 35 | }; 36 | 37 | /** 38 | * called if all the connection attempts/(and/or timeouts) determined by the connection strategy has been exhausted 39 | * 40 | * @param name the name of the connection 41 | * @param message reason 42 | */ 43 | default void onFatalFailure(@Nullable String name, String message) { 44 | LOG.error("name=" + name + ",message=" + message); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/connection/TraceLock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.connection; 19 | 20 | import net.openhft.chronicle.core.Jvm; 21 | import net.openhft.chronicle.core.StackTrace; 22 | import org.jetbrains.annotations.NotNull; 23 | import org.jetbrains.annotations.Nullable; 24 | 25 | import java.util.concurrent.TimeUnit; 26 | import java.util.concurrent.locks.ReentrantLock; 27 | 28 | /** 29 | * @deprecated This has been moved to DataGrid without a replacement 30 | */ 31 | @Deprecated(/* For removal in x.25 */) 32 | class TraceLock extends ReentrantLock { 33 | 34 | private static final long serialVersionUID = 1997992705529515418L; 35 | @Nullable 36 | private volatile Throwable here; 37 | 38 | @NotNull 39 | public static ReentrantLock create() { 40 | return Jvm.isDebug() ? new TraceLock() : new ReentrantLock(); 41 | } 42 | 43 | @Override 44 | public void lockInterruptibly() throws InterruptedException { 45 | super.lockInterruptibly(); 46 | here = new StackTrace(); 47 | } 48 | 49 | @Override 50 | public void lock() { 51 | 52 | super.lock(); 53 | here = new StackTrace(); 54 | } 55 | 56 | @Override 57 | public String toString() { 58 | 59 | @Nullable Throwable here = this.here; 60 | if (here == null) 61 | return super.toString(); 62 | 63 | @NotNull final StringBuilder sb = new StringBuilder(super.toString()); 64 | 65 | for (StackTraceElement s : here.getStackTrace()) { 66 | sb.append("\n\tat ").append(s); 67 | } 68 | 69 | return sb.toString(); 70 | 71 | } 72 | 73 | @Override 74 | public void unlock() { 75 | if (getHoldCount() == 1) 76 | here = null; 77 | super.unlock(); 78 | } 79 | 80 | @Override 81 | public boolean tryLock() { 82 | final boolean b = super.tryLock(); 83 | if (b) 84 | here = new StackTrace(); 85 | return b; 86 | } 87 | 88 | @Override 89 | public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { 90 | 91 | final boolean b = super.tryLock(timeout, unit); 92 | if (b) 93 | here = new StackTrace(); 94 | return b; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/connection/TryLock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.connection; 19 | 20 | 21 | /** 22 | * @deprecated This has been moved to DataGrid without a replacement 23 | */ 24 | @Deprecated(/* For removal in x.25 */) 25 | public enum TryLock { 26 | 27 | LOCK, TRY_LOCK_IGNORE, TRY_LOCK_WARN 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/connection/WireOutConsumer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.connection; 19 | 20 | import net.openhft.chronicle.core.threads.InvalidEventHandlerException; 21 | import net.openhft.chronicle.wire.WireOut; 22 | 23 | @FunctionalInterface 24 | public interface WireOutConsumer { 25 | void accept(WireOut wireOut) throws InvalidEventHandlerException, InterruptedException; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/connection/WireOutPublisher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.connection; 19 | 20 | import net.openhft.chronicle.bytes.Bytes; 21 | import net.openhft.chronicle.core.io.Closeable; 22 | import net.openhft.chronicle.wire.WireOut; 23 | import net.openhft.chronicle.wire.WireType; 24 | import net.openhft.chronicle.wire.WriteMarshallable; 25 | import org.jetbrains.annotations.NotNull; 26 | import org.jetbrains.annotations.Nullable; 27 | import org.slf4j.Logger; 28 | import org.slf4j.LoggerFactory; 29 | 30 | @FunctionalInterface 31 | public interface WireOutPublisher extends Closeable { 32 | Logger LOG = LoggerFactory.getLogger(WireOutPublisher.class); 33 | 34 | default void applyAction(@NotNull Bytes out) { 35 | throw new UnsupportedOperationException(); 36 | } 37 | 38 | default void applyAction(@NotNull WireOut out) { 39 | applyAction(out.bytes()); 40 | } 41 | 42 | default void addWireConsumer(WireOutConsumer wireOutConsumer) { 43 | throw new UnsupportedOperationException(); 44 | } 45 | 46 | default boolean removeBytesConsumer(WireOutConsumer wireOutConsumer) { 47 | throw new UnsupportedOperationException(); 48 | } 49 | 50 | default boolean canTakeMoreData() { 51 | return false; 52 | } 53 | 54 | /** 55 | * @param key the key to the event, only used when throttling, otherwise NULL if the 56 | * throttling is not required 57 | * @param event the marshallable event 58 | */ 59 | void put(@Nullable final Object key, WriteMarshallable event); 60 | 61 | @Override 62 | default boolean isClosed() { 63 | throw new UnsupportedOperationException(); 64 | } 65 | 66 | default boolean isEmpty() { 67 | throw new UnsupportedOperationException(); 68 | } 69 | 70 | @Override 71 | default void close() { 72 | throw new UnsupportedOperationException(); 73 | } 74 | 75 | default void wireType(WireType wireType) { 76 | throw new UnsupportedOperationException(); 77 | } 78 | 79 | default void clear() { 80 | throw new UnsupportedOperationException(); 81 | } 82 | 83 | /** 84 | * publishes an event without a throttle key 85 | * 86 | * @param event the event to publish 87 | */ 88 | default void publish(WriteMarshallable event) { 89 | put("", event); 90 | } 91 | 92 | default WireOutPublisher connectionDescription(String connectionDescription) { 93 | return this; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/internal/SocketExceptionUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network.internal; 20 | 21 | import net.openhft.chronicle.core.Jvm; 22 | 23 | import java.io.IOException; 24 | import java.net.SocketException; 25 | import java.util.Locale; 26 | 27 | @Deprecated(/* to be removed in x.25 */) 28 | public final class SocketExceptionUtil { 29 | 30 | private SocketExceptionUtil() { 31 | } 32 | 33 | /** 34 | * Is the passed exception one that results from reading from or writing to a reset 35 | * connection? 36 | *

37 | * NOTE: This is not reliable and shouldn't be used for anything critical. We use it 38 | * to make logging less noisy, false negatives are acceptable and expected. It should 39 | * not produce false positives, but there's no guarantees it doesn't. 40 | * 41 | * @deprecated To be removed in x.25 42 | * @see net.openhft.chronicle.core.io.IOTools#isClosedException(java.lang.Exception) 43 | * 44 | * @param e The exception 45 | * @return true if the exception is one that signifies the connection was reset 46 | */ 47 | @Deprecated(/* to be removed in x.25 */) 48 | public static boolean isAConnectionResetException(IOException e) { 49 | Language.warnOnce(); 50 | 51 | return isALinuxJava12OrLessConnectionResetException(e) 52 | || isAWindowsConnectionResetException(e) 53 | || isALinuxJava13OrGreaterConnectionResetException(e) 54 | || isAWindowsEstablishedConnectionAbortedException(e) 55 | || isAnOSXBrokenPipeException(e); 56 | } 57 | 58 | private static boolean isALinuxJava13OrGreaterConnectionResetException(IOException e) { 59 | return e.getClass().equals(SocketException.class) && "Connection reset".equals(e.getMessage()); 60 | } 61 | 62 | private static boolean isAWindowsConnectionResetException(IOException e) { 63 | return e.getClass().equals(IOException.class) && "An existing connection was forcibly closed by the remote host".equals(e.getMessage()); 64 | } 65 | 66 | private static boolean isALinuxJava12OrLessConnectionResetException(IOException e) { 67 | return e.getClass().equals(IOException.class) && "Connection reset by peer".equals(e.getMessage()); 68 | } 69 | 70 | private static boolean isAWindowsEstablishedConnectionAbortedException(Exception e) { 71 | return e.getClass().equals(IOException.class) && "An established connection was aborted by the software in your host machine".equals(e.getMessage()); 72 | } 73 | 74 | private static boolean isAnOSXBrokenPipeException(Exception e) { 75 | return e.getClass().equals(IOException.class) && "Broken pipe".equals(e.getMessage()); 76 | } 77 | 78 | private static final class Language { 79 | static { 80 | if (!Locale.getDefault().getLanguage().equals(Locale.ENGLISH.getLanguage())) { 81 | Jvm.warn().on(SocketExceptionUtil.class, 82 | "Running under non-English locale '" + Locale.getDefault().getLanguage() + 83 | "', transient exceptions will be reported with higher level than necessary."); 84 | } 85 | } 86 | 87 | static void warnOnce() { 88 | // No-op. 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/internal/cluster/handlers/NoOpHandler.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.network.internal.cluster.handlers; 2 | 3 | import net.openhft.chronicle.core.io.Closeable; 4 | import net.openhft.chronicle.network.NetworkContext; 5 | import net.openhft.chronicle.network.api.session.SubHandler; 6 | import net.openhft.chronicle.wire.WireIn; 7 | import net.openhft.chronicle.wire.WireOut; 8 | import org.jetbrains.annotations.NotNull; 9 | 10 | import java.util.concurrent.RejectedExecutionException; 11 | 12 | /** 13 | * An immutable {@link SubHandler} that does nothing on read or write 14 | * 15 | * @param 16 | */ 17 | public final class NoOpHandler> implements SubHandler { 18 | 19 | private static final NoOpHandler INSTANCE = new NoOpHandler<>(); 20 | 21 | private NoOpHandler() { 22 | // Just to make it private, it's a singleton 23 | } 24 | 25 | public static > SubHandler instance() { 26 | return (NoOpHandler) INSTANCE; 27 | } 28 | 29 | @Override 30 | public void cid(long cid) { 31 | // Do nothing, it's stateless & shared 32 | } 33 | 34 | @Override 35 | public long cid() { 36 | return -1; 37 | } 38 | 39 | @Override 40 | public void csp(@NotNull String cspText) { 41 | // Do nothing, it's stateless & shared 42 | } 43 | 44 | @Override 45 | public String csp() { 46 | return "no-csp"; 47 | } 48 | 49 | @Override 50 | public void onRead(@NotNull WireIn inWire, @NotNull WireOut outWire) { 51 | // Do nothing 52 | } 53 | 54 | @Override 55 | public Closeable closable() { 56 | return null; 57 | } 58 | 59 | @Override 60 | public void remoteIdentifier(int remoteIdentifier) { 61 | // Do nothing, it's stateless & shared 62 | } 63 | 64 | @Override 65 | public void localIdentifier(int localIdentifier) { 66 | // Do nothing, it's stateless & shared 67 | } 68 | 69 | @Override 70 | public void onInitialize(WireOut outWire) throws RejectedExecutionException { 71 | // Do nothing 72 | } 73 | 74 | @Override 75 | public void closeable(Closeable closeable) { 76 | // Do nothing, it's stateless & shared 77 | } 78 | 79 | @Override 80 | public void close() { 81 | // Do nothing 82 | } 83 | 84 | @Override 85 | public boolean isClosed() { 86 | return false; 87 | } 88 | 89 | @Override 90 | public T nc() { 91 | return null; 92 | } 93 | 94 | @Override 95 | public void nc(T nc) { 96 | // Do nothing, it's stateless & shared 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/internal/lookuptable/ProcessLocalHostnamePortLookupTable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network.internal.lookuptable; 20 | 21 | import net.openhft.chronicle.network.HostnamePortLookupTable; 22 | 23 | import java.io.IOException; 24 | import java.net.InetSocketAddress; 25 | import java.util.Map; 26 | import java.util.Set; 27 | import java.util.concurrent.ConcurrentSkipListMap; 28 | import java.util.function.BiConsumer; 29 | 30 | /** 31 | * Just uses a concurrent map to store the mappings, doesn't work across processes 32 | */ 33 | public class ProcessLocalHostnamePortLookupTable implements HostnamePortLookupTable, java.io.Closeable { 34 | 35 | private final Map aliases; 36 | 37 | public ProcessLocalHostnamePortLookupTable() { 38 | this.aliases = new ConcurrentSkipListMap<>(); 39 | } 40 | 41 | @Override 42 | public InetSocketAddress lookup(String description) { 43 | return aliases.get(description); 44 | } 45 | 46 | @Override 47 | public void clear() { 48 | aliases.clear(); 49 | } 50 | 51 | @Override 52 | public Set aliases() { 53 | return aliases.keySet(); 54 | } 55 | 56 | @Override 57 | public void put(String description, InetSocketAddress address) { 58 | aliases.put(description, address); 59 | } 60 | 61 | @Override 62 | public void forEach(BiConsumer consumer) { 63 | aliases.forEach(consumer); 64 | } 65 | 66 | @Override 67 | public void close() throws IOException { 68 | clear(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/internal/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | /** 20 | * This package and any and all sub-packages contains strictly internal classes for this Chronicle library. 21 | * Internal classes shall never be used directly. 22 | *

23 | * Specifically, the following actions (including, but not limited to) are not allowed 24 | * on internal classes and packages: 25 | *

    26 | *
  • Casting to
  • 27 | *
  • Reflection of any kind
  • 28 | *
  • Explicit Serialize/deserialize
  • 29 | *
30 | *

31 | * The classes in this package and any sub-package are subject to 32 | * changes at any time for any reason. 33 | */ 34 | package net.openhft.chronicle.network.internal; 35 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/ssl/BufferHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network.ssl; 20 | 21 | import java.io.IOException; 22 | import java.nio.ByteBuffer; 23 | 24 | /** 25 | * This class handles the bridge between two sets of buffers: 26 | * - socket-side data - encrypted, handled by readData, writeData 27 | * - application-side data - decrypted, handled by handleDecryptedData 28 | * 29 | * @deprecated To be removed in x.25 30 | */ 31 | @Deprecated(/* To be removed in x.25 */) 32 | public interface BufferHandler { 33 | /** 34 | * Read encrypted data from an input into the supplied buffer. 35 | * 36 | * @param target the target buffer for encrypted data 37 | * @return the number of bytes written 38 | * @throws IOException if an exception occurs 39 | */ 40 | int readData(final ByteBuffer target) throws IOException; 41 | 42 | /** 43 | * Accept decrypted input data, previous collected by an invocation of readData. 44 | * Any plain-text output should be written to the output buffer for encryption. 45 | * 46 | * @param input a buffer containing decrypted input data 47 | * @param output a buffer that can be used for writing plain-text output 48 | */ 49 | void handleDecryptedData(final ByteBuffer input, final ByteBuffer output); 50 | 51 | /** 52 | * Write encrypted data to an output from the supplied buffer. 53 | * 54 | * @param encrypted the buffer containing encrypted data 55 | * @return the number of bytes written 56 | * @throws IOException if an exception occurs 57 | */ 58 | int writeData(final ByteBuffer encrypted) throws IOException; 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/ssl/SslNetworkContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network.ssl; 20 | 21 | import net.openhft.chronicle.network.NetworkContext; 22 | 23 | import javax.net.ssl.SSLContext; 24 | 25 | @Deprecated(/* To be removed in x.25 */) 26 | public interface SslNetworkContext> 27 | extends NetworkContext { 28 | SSLContext sslContext(); 29 | } -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/tcp/ChronicleServerSocket.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network.tcp; 20 | 21 | import java.net.SocketAddress; 22 | import java.net.SocketException; 23 | 24 | public interface ChronicleServerSocket { 25 | int getLocalPort(); 26 | 27 | void close(); 28 | 29 | void setReuseAddress(boolean b) throws SocketException; 30 | 31 | SocketAddress getLocalSocketAddress(); 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/tcp/ChronicleServerSocketChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network.tcp; 20 | 21 | import java.io.Closeable; 22 | import java.io.IOException; 23 | import java.net.InetSocketAddress; 24 | import java.net.SocketAddress; 25 | import java.net.SocketOption; 26 | import java.nio.channels.AlreadyBoundException; 27 | import java.nio.channels.ClosedChannelException; 28 | import java.nio.channels.UnsupportedAddressTypeException; 29 | 30 | public interface ChronicleServerSocketChannel extends Closeable { 31 | 32 | ChronicleSocketChannel accept() throws IOException; 33 | 34 | boolean isOpen(); 35 | 36 | ChronicleServerSocket socket(); 37 | 38 | void close(); 39 | 40 | /** 41 | * Binds the channel's socket to a local address and configures the socket 42 | * to listen for connections. 43 | * 44 | *

An invocation of this method is equivalent to the following: 45 | *

46 |      * bind(local, 0);
47 |      * 
48 | * 49 | * @param address The local address to bind the socket, or {@code null} to bind 50 | * to an automatically assigned socket address 51 | * @throws AlreadyBoundException if bound 52 | * @throws UnsupportedAddressTypeException if address unsupported 53 | * @throws ClosedChannelException if channel is closed 54 | * @throws IOException if unable to open 55 | * @throws SecurityException If a security manager has been installed and its {@link SecurityManager#checkListen checkListen} 56 | * method denies the operation 57 | * @since 1.7 58 | */ 59 | void bind(InetSocketAddress address) throws IOException; 60 | 61 | SocketAddress getLocalAddress() throws IOException; 62 | 63 | void setOption(SocketOption soReuseaddr, boolean b) throws IOException; 64 | 65 | void configureBlocking(boolean b) throws IOException; 66 | 67 | String hostPort(); 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/tcp/ChronicleServerSocketFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network.tcp; 20 | 21 | import net.openhft.chronicle.core.util.ObjectUtils; 22 | 23 | public class ChronicleServerSocketFactory { 24 | 25 | public static ChronicleServerSocketChannel open(String hostPort) { 26 | return new VanillaChronicleServerSocketChannel(hostPort); 27 | } 28 | 29 | public static ChronicleServerSocketChannel openNative() { 30 | String className = "software.chronicle.network.impl.NativeChronicleServerSocketChannel"; 31 | return ObjectUtils.newInstance(className); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/tcp/ChronicleSocket.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network.tcp; 20 | 21 | import java.io.IOException; 22 | import java.net.SocketException; 23 | import java.net.SocketOptions; 24 | 25 | public interface ChronicleSocket { 26 | 27 | void setTcpNoDelay(final boolean tcpNoDelay) throws SocketException; 28 | 29 | int getReceiveBufferSize() throws SocketException; 30 | 31 | void setReceiveBufferSize(final int tcpBuffer) throws SocketException; 32 | 33 | int getSendBufferSize() throws SocketException; 34 | 35 | void setSendBufferSize(final int tcpBuffer) throws SocketException; 36 | 37 | void setSoTimeout(int i) throws SocketException; 38 | 39 | /** 40 | * Enable/disable {@link SocketOptions#SO_LINGER SO_LINGER} with the specified linger time in seconds. The maximum timeout value is platform 41 | * specific. 42 | * 43 | * The setting only affects socket close. 44 | * 45 | * @param on whether or not to linger on. 46 | * @param linger how long to linger for, if on is true. 47 | * @throws SocketException if there is an error in the underlying protocol, such as a TCP error. 48 | * @throws IllegalArgumentException if the linger value is negative. 49 | * @since JDK1.1 50 | */ 51 | void setSoLinger(boolean on, int linger) throws SocketException; 52 | 53 | void shutdownInput() throws IOException; 54 | 55 | void shutdownOutput() throws IOException; 56 | 57 | Object getRemoteSocketAddress(); 58 | 59 | Object getLocalSocketAddress(); 60 | 61 | int getLocalPort(); 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/tcp/ChronicleSocketChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network.tcp; 20 | 21 | import net.openhft.chronicle.core.io.Closeable; 22 | import net.openhft.chronicle.network.ChronicleSocketChannelBuilder; 23 | 24 | import java.io.IOException; 25 | import java.net.InetSocketAddress; 26 | import java.net.SocketOption; 27 | import java.nio.ByteBuffer; 28 | import java.nio.channels.ClosedChannelException; 29 | import java.nio.channels.Selector; 30 | import java.nio.channels.SocketChannel; 31 | 32 | public interface ChronicleSocketChannel extends Closeable { 33 | 34 | static ChronicleSocketChannelBuilder builder(InetSocketAddress socketAddress) { 35 | return new ChronicleSocketChannelBuilder(socketAddress); 36 | } 37 | 38 | int read(ByteBuffer byteBuffer) throws IOException; 39 | 40 | int write(ByteBuffer byteBuffer) throws IOException; 41 | 42 | long write(ByteBuffer[] byteBuffers) throws IOException; 43 | 44 | void configureBlocking(boolean blocking) throws IOException; 45 | 46 | InetSocketAddress getLocalAddress() throws IOException; 47 | 48 | void bind(InetSocketAddress localAddress) throws IOException; 49 | 50 | InetSocketAddress getRemoteAddress() throws IOException; 51 | 52 | boolean isOpen(); 53 | 54 | boolean isBlocking(); 55 | 56 | ChronicleSocket socket(); 57 | 58 | void connect(InetSocketAddress socketAddress) throws IOException; 59 | 60 | void register(Selector selector, int opConnect) throws ClosedChannelException; 61 | 62 | boolean finishConnect() throws IOException; 63 | 64 | void setOption(SocketOption soReuseaddr, boolean b) throws IOException; 65 | 66 | SocketChannel socketChannel(); 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/tcp/ChronicleSocketChannelFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network.tcp; 20 | 21 | import net.openhft.chronicle.core.Jvm; 22 | import net.openhft.chronicle.core.OS; 23 | import net.openhft.chronicle.core.util.ObjectUtils; 24 | import org.jetbrains.annotations.NotNull; 25 | 26 | import java.io.IOException; 27 | import java.net.InetSocketAddress; 28 | import java.nio.channels.SocketChannel; 29 | 30 | public enum ChronicleSocketChannelFactory { 31 | ; 32 | public static final boolean FAST_JAVA8_IO = isFastJava8IO(); 33 | 34 | private static boolean isFastJava8IO() { 35 | boolean fastJava8IO = Jvm.getBoolean("fastJava8IO") && !Jvm.isJava9Plus() && OS.isLinux(); 36 | if (fastJava8IO) Jvm.startup().on(ChronicleSocketChannelFactory.class, "FastJava8IO: enabled"); 37 | return fastJava8IO; 38 | } 39 | 40 | public static ChronicleSocketChannel wrap() throws IOException { 41 | return wrap(false, SocketChannel.open()); 42 | } 43 | 44 | public static ChronicleSocketChannel wrap(InetSocketAddress socketAddress) throws IOException { 45 | return wrap(false, SocketChannel.open(socketAddress)); 46 | } 47 | 48 | public static ChronicleSocketChannel wrap(boolean isNative, InetSocketAddress socketAddress) throws IOException { 49 | SocketChannel sc = SocketChannel.open(socketAddress); 50 | return wrap(isNative, sc); 51 | } 52 | 53 | public static ChronicleSocketChannel wrap(@NotNull final SocketChannel sc) { 54 | return wrap(false, sc); 55 | } 56 | 57 | public static ChronicleSocketChannel wrap(boolean isNative, @NotNull final SocketChannel sc) { 58 | return isNative ? newNativeInstance(sc) : FAST_JAVA8_IO ? newFastInstance(sc) : newInstance(sc); 59 | } 60 | 61 | public static ChronicleSocketChannel wrapUnsafe(@NotNull final SocketChannel sc) { 62 | return FAST_JAVA8_IO ? newFastUnsafeInstance(sc) : newInstance(sc); 63 | } 64 | 65 | @NotNull 66 | private static ChronicleSocketChannel newInstance(@NotNull final SocketChannel sc) { 67 | return new VanillaSocketChannel(sc); 68 | } 69 | 70 | @NotNull 71 | private static ChronicleSocketChannel newFastInstance(@NotNull final SocketChannel sc) { 72 | return new FastJ8SocketChannel(sc); 73 | } 74 | 75 | private static ChronicleSocketChannel newNativeInstance(@NotNull final SocketChannel sc) { 76 | String className = "software.chronicle.network.impl.NativeChronicleSocketChannel"; 77 | return ObjectUtils.newInstance(className); 78 | } 79 | 80 | @NotNull 81 | private static ChronicleSocketChannel newFastUnsafeInstance(@NotNull final SocketChannel sc) { 82 | return new UnsafeFastJ8SocketChannel(sc); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/tcp/ChronicleSocketFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network.tcp; 20 | 21 | import net.openhft.chronicle.network.NetworkUtil; 22 | 23 | import java.io.IOException; 24 | import java.net.Socket; 25 | import java.net.SocketException; 26 | 27 | public enum ChronicleSocketFactory { 28 | ; 29 | 30 | public static ChronicleSocket toChronicleSocket(Socket socket) { 31 | return new ChronicleSocket() { 32 | 33 | @Override 34 | public void setTcpNoDelay(final boolean tcpNoDelay) throws SocketException { 35 | NetworkUtil.setTcpNoDelay(socket, tcpNoDelay); 36 | } 37 | 38 | @Override 39 | public int getReceiveBufferSize() throws SocketException { 40 | return socket.getReceiveBufferSize(); 41 | } 42 | 43 | @Override 44 | public void setReceiveBufferSize(final int tcpBuffer) throws SocketException { 45 | socket.setReceiveBufferSize(tcpBuffer); 46 | } 47 | 48 | @Override 49 | public int getSendBufferSize() throws SocketException { 50 | return socket.getSendBufferSize(); 51 | } 52 | 53 | @Override 54 | public void setSendBufferSize(final int tcpBuffer) throws SocketException { 55 | socket.setSendBufferSize(tcpBuffer); 56 | } 57 | 58 | @Override 59 | public void setSoTimeout(final int i) throws SocketException { 60 | socket.setSoTimeout(i); 61 | } 62 | 63 | @Override 64 | public void setSoLinger(final boolean b, final int i) throws SocketException { 65 | socket.setSoLinger(b, i); 66 | } 67 | 68 | @Override 69 | public void shutdownInput() throws IOException { 70 | socket.shutdownInput(); 71 | } 72 | 73 | @Override 74 | public void shutdownOutput() throws IOException { 75 | socket.shutdownOutput(); 76 | } 77 | 78 | @Override 79 | public Object getRemoteSocketAddress() { 80 | return socket.getRemoteSocketAddress(); 81 | } 82 | 83 | @Override 84 | public Object getLocalSocketAddress() { 85 | return socket.getLocalSocketAddress(); 86 | } 87 | 88 | @Override 89 | public int getLocalPort() { 90 | return socket.getLocalPort(); 91 | } 92 | }; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/tcp/FastJ8SocketChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.tcp; 19 | 20 | import net.openhft.chronicle.core.Jvm; 21 | import net.openhft.chronicle.core.OS; 22 | import net.openhft.chronicle.core.io.IOTools; 23 | 24 | import java.io.FileDescriptor; 25 | import java.io.IOException; 26 | import java.nio.ByteBuffer; 27 | import java.nio.channels.SocketChannel; 28 | 29 | public class FastJ8SocketChannel extends VanillaSocketChannel { 30 | final FileDescriptor fd; 31 | private final Object readLock; 32 | volatile boolean open; 33 | private volatile boolean blocking; 34 | 35 | public FastJ8SocketChannel(SocketChannel socketChannel) { 36 | super(socketChannel); 37 | fd = Jvm.getValue(socketChannel, "fd"); 38 | open = socketChannel.isOpen(); 39 | blocking = socketChannel.isBlocking(); 40 | readLock = Jvm.getValue(socketChannel, "readLock"); 41 | } 42 | 43 | @Override 44 | public int read(ByteBuffer buf) throws IOException { 45 | throwExceptionIfClosed(); 46 | 47 | if (buf == null) 48 | throw new NullPointerException(); 49 | 50 | if (isBlocking() || isClosed() || !IOTools.isDirectBuffer(buf) || !super.isOpen()) 51 | return super.read(buf); 52 | return read0(buf); 53 | } 54 | 55 | int read0(ByteBuffer buf) throws IOException { 56 | synchronized (readLock) { 57 | if (Thread.interrupted()) 58 | throw new IOException(new InterruptedException()); 59 | 60 | return readInternal(buf); 61 | } 62 | } 63 | 64 | @Override 65 | public void configureBlocking(boolean blocking) throws IOException { 66 | super.configureBlocking(blocking); 67 | this.blocking = super.isBlocking(); 68 | } 69 | 70 | @Override 71 | public boolean isOpen() { 72 | return open; 73 | } 74 | 75 | @Override 76 | public boolean isBlocking() { 77 | return blocking; 78 | } 79 | 80 | @Override 81 | protected void performClose() { 82 | super.performClose(); 83 | open = false; 84 | } 85 | 86 | @Override 87 | public int write(ByteBuffer byteBuffer) throws IOException { 88 | throwExceptionIfClosed(); 89 | 90 | try { 91 | int write = super.write(byteBuffer); 92 | open &= write >= 0; 93 | return write; 94 | 95 | } catch (Exception e) { 96 | open = super.isOpen(); 97 | throw e; 98 | } 99 | } 100 | 101 | int readInternal(ByteBuffer buf) throws IOException { 102 | int n = OS.read0(fd, IOTools.addressFor(buf) + buf.position(), buf.remaining()); 103 | if ((n == IOTools.IOSTATUS_INTERRUPTED) && socketChannel.isOpen()) { 104 | // The system call was interrupted but the channel 105 | // is still open, so retry 106 | return 0; 107 | } 108 | int ret = IOTools.normaliseIOStatus(n); 109 | if (ret > 0) 110 | buf.position(buf.position() + ret); 111 | else if (ret < 0) 112 | open = false; 113 | return ret; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/network/tcp/UnsafeFastJ8SocketChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.chronicle.network.tcp; 19 | 20 | import net.openhft.chronicle.core.OS; 21 | import net.openhft.chronicle.core.io.IOTools; 22 | 23 | import java.io.IOException; 24 | import java.nio.ByteBuffer; 25 | import java.nio.channels.AsynchronousCloseException; 26 | import java.nio.channels.SocketChannel; 27 | 28 | /** 29 | * Doesn't do any locking so can only be used in a single-threaded manner 30 | */ 31 | public class UnsafeFastJ8SocketChannel extends FastJ8SocketChannel { 32 | public UnsafeFastJ8SocketChannel(SocketChannel socketChannel) { 33 | super(socketChannel); 34 | singleThreadedCheckDisabled(true); 35 | } 36 | 37 | @Override 38 | int read0(ByteBuffer buf) throws IOException { 39 | return readInternal(buf); 40 | } 41 | 42 | @Override 43 | public int write(ByteBuffer buf) throws IOException { 44 | if (buf == null) 45 | throw new NullPointerException(); 46 | 47 | if (isBlocking() || isClosed() || !IOTools.isDirectBuffer(buf)) 48 | return super.write(buf); 49 | 50 | return writeInternal(buf); 51 | } 52 | 53 | private int writeInternal(ByteBuffer buf) throws IOException { 54 | int pos = buf.position(); 55 | int lim = buf.limit(); 56 | int len = lim <= pos ? 0 : lim - pos; 57 | int res = OS.write0(fd, IOTools.addressFor(buf) + pos, len); 58 | if (res > 0) 59 | buf.position(pos + res); 60 | if ((res == IOTools.IOSTATUS_INTERRUPTED) && socketChannel.isOpen()) { 61 | // The system call was interrupted but the channel 62 | // is still open, so retry 63 | return 0; 64 | } 65 | res = IOTools.normaliseIOStatus(res); 66 | if (res < 0) 67 | open = false; 68 | if (res <= 0 && !socketChannel.isOpen()) 69 | throw new AsynchronousCloseException(); 70 | 71 | return res; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/network/ClusterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network; 20 | 21 | import net.openhft.chronicle.core.util.ThrowingFunction; 22 | import net.openhft.chronicle.network.cluster.Cluster; 23 | import net.openhft.chronicle.network.cluster.ClusteredNetworkContext; 24 | import net.openhft.chronicle.wire.Marshallable; 25 | import net.openhft.chronicle.wire.WireType; 26 | import org.jetbrains.annotations.NotNull; 27 | import org.junit.jupiter.api.Test; 28 | 29 | import java.io.IOException; 30 | 31 | import static org.junit.jupiter.api.Assertions.assertEquals; 32 | import static org.junit.jupiter.api.Assertions.assertNotNull; 33 | 34 | class ClusterTest extends NetworkTestCommon { 35 | 36 | @Test 37 | > void testDeepCopy() { 38 | MyClusterContext cc = new MyClusterContext().value(22).wireType(WireType.TEXT); 39 | String s = Marshallable.$toString(cc); 40 | MyClusterContext o = Marshallable.fromString(s); 41 | assertEquals(cc.value, o.value); 42 | MyClusterContext cc2 = cc.deepCopy(); 43 | assertEquals(cc.value, cc2.value); 44 | 45 | try (Cluster> c = new MyCluster()) { 46 | c.clusterContext(cc); 47 | try (Cluster> c2 = c.deepCopy()) { 48 | MyClusterContext mcc = c2.clusterContext(); 49 | assertNotNull(mcc); 50 | assertEquals(22, mcc.value); 51 | } 52 | } 53 | } 54 | 55 | private static class MyCluster> extends Cluster> { 56 | public MyCluster() { 57 | super(); 58 | } 59 | } 60 | 61 | static class MyClusterContext> extends net.openhft.chronicle.network.cluster.ClusterContext, T> { 62 | int value; 63 | 64 | @Override 65 | protected String clusterNamePrefix() { 66 | return ""; 67 | } 68 | 69 | @NotNull 70 | @Override 71 | public ThrowingFunction, IOException> tcpEventHandlerFactory() { 72 | return null; 73 | } 74 | 75 | public MyClusterContext value(int v) { 76 | this.value = v; 77 | return this; 78 | } 79 | 80 | @Override 81 | protected void defaults() { 82 | 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/network/CrossProcessTCPRegistryTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network; 20 | 21 | import net.openhft.chronicle.core.OS; 22 | import net.openhft.chronicle.network.internal.lookuptable.FileBasedHostnamePortLookupTable; 23 | import org.junit.jupiter.api.AfterEach; 24 | import org.junit.jupiter.api.BeforeEach; 25 | import org.junit.jupiter.api.Test; 26 | 27 | import java.io.IOException; 28 | import java.net.InetSocketAddress; 29 | 30 | class CrossProcessTCPRegistryTest extends TCPRegistryTest { 31 | 32 | @BeforeEach 33 | void setUp() { 34 | if (OS.isWindows()) { 35 | ignoreException("Error deleting the shared lookup table"); 36 | } 37 | TCPRegistry.useCrossProcessRegistry(); 38 | } 39 | 40 | @Test 41 | void resetOnFreshRegistryWillClearExistingEntries() throws IOException { 42 | final String hostAlias = "should_be_cleared"; 43 | try (final FileBasedHostnamePortLookupTable lookupTable = new FileBasedHostnamePortLookupTable()) { 44 | // write an alias to the lookup table file 45 | lookupTable.put(hostAlias, new InetSocketAddress(0)); 46 | // reset before static lookup table is lazily created 47 | TCPRegistry.reset(); 48 | // this should not log any warnings, the alias should be clear 49 | TCPRegistry.createServerSocketChannelFor(hostAlias); 50 | } 51 | } 52 | 53 | @AfterEach 54 | void tearDown() { 55 | TCPRegistry.useInMemoryRegistry(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/network/InMemoryTCPRegistryTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network; 20 | 21 | class InMemoryTCPRegistryTest extends TCPRegistryTest { 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/network/NetworkStatsAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network; 20 | 21 | /** 22 | * Adapter to make it easier to make inline NetworkStatsListeners 23 | * 24 | * @param the NetworkContext type 25 | */ 26 | public class NetworkStatsAdapter> implements NetworkStatsListener { 27 | 28 | @Override 29 | public void networkContext(N networkContext) { 30 | } 31 | 32 | @Override 33 | public void onNetworkStats(long writeBps, long readBps, long socketPollCountPerSecond) { 34 | } 35 | 36 | @Override 37 | public void onHostPort(String hostName, int port) { 38 | } 39 | 40 | @Override 41 | public void onRoundTripLatency(long nanosecondLatency) { 42 | } 43 | 44 | @Override 45 | public void close() { 46 | } 47 | 48 | @Override 49 | public boolean isClosed() { 50 | return false; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/network/NetworkTestCommon.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network; 20 | 21 | import net.openhft.chronicle.core.internal.JvmExceptionTracker; 22 | import net.openhft.chronicle.core.io.AbstractCloseable; 23 | import net.openhft.chronicle.core.io.AbstractReferenceCounted; 24 | import net.openhft.chronicle.core.onoes.ExceptionKey; 25 | import net.openhft.chronicle.core.threads.CleaningThread; 26 | import net.openhft.chronicle.core.threads.ThreadDump; 27 | import net.openhft.chronicle.core.time.SystemTimeProvider; 28 | import net.openhft.chronicle.testframework.internal.ExceptionTracker; 29 | import org.junit.jupiter.api.AfterEach; 30 | import org.junit.jupiter.api.BeforeEach; 31 | 32 | import java.util.function.Predicate; 33 | 34 | public class NetworkTestCommon { 35 | 36 | protected ThreadDump threadDump; 37 | private ExceptionTracker exceptionTracker; 38 | 39 | @BeforeEach 40 | void enableReferenceTracing() { 41 | AbstractReferenceCounted.enableReferenceTracing(); 42 | } 43 | 44 | public void assertReferencesReleased() { 45 | AbstractReferenceCounted.assertReferencesReleased(); 46 | } 47 | 48 | // @BeforeEach add to tests that need it 49 | protected void threadDump() { 50 | threadDump = new ThreadDump(); 51 | } 52 | 53 | public void checkThreadDump() { 54 | if (threadDump != null) 55 | threadDump.assertNoNewThreads(); 56 | } 57 | 58 | @BeforeEach 59 | void recordExceptions() { 60 | exceptionTracker = JvmExceptionTracker.create(false); 61 | exceptionTracker.ignoreException("unable to connect to any of the hosts"); 62 | exceptionTracker.ignoreException("Warming up"); 63 | exceptionTracker.ignoreException("warmed up"); 64 | exceptionTracker.ignoreException("Wrapping elastic bytes with unchecked()"); 65 | } 66 | 67 | public void expectException(String message) { 68 | exceptionTracker.expectException(message); 69 | } 70 | 71 | public void ignoreException(String message) { 72 | exceptionTracker.ignoreException(message); 73 | } 74 | 75 | public void ignoreException(Predicate predicate, String description) { 76 | exceptionTracker.ignoreException(predicate, description); 77 | } 78 | 79 | public void checkExceptions() { 80 | exceptionTracker.checkExceptions(); 81 | } 82 | 83 | @AfterEach 84 | void afterChecks() { 85 | SystemTimeProvider.CLOCK = SystemTimeProvider.INSTANCE; 86 | 87 | CleaningThread.performCleanup(Thread.currentThread()); 88 | 89 | // find any discarded resources. 90 | TCPRegistry.reset(); 91 | 92 | AbstractCloseable.waitForCloseablesToClose(100); 93 | 94 | assertReferencesReleased(); 95 | checkThreadDump(); 96 | checkExceptions(); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/network/RemoteConnectorTest.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.network; 2 | 3 | import net.openhft.chronicle.core.Jvm; 4 | import net.openhft.chronicle.core.threads.EventLoop; 5 | import net.openhft.chronicle.network.tcp.ChronicleServerSocketChannel; 6 | import net.openhft.chronicle.network.tcp.ChronicleSocketChannel; 7 | import net.openhft.chronicle.network.test.TestClusterContext; 8 | import net.openhft.chronicle.network.test.TestClusteredNetworkContext; 9 | import net.openhft.chronicle.testframework.Waiters; 10 | import net.openhft.chronicle.threads.EventGroup; 11 | import org.jetbrains.annotations.NotNull; 12 | import org.junit.jupiter.api.BeforeEach; 13 | import org.junit.jupiter.api.Test; 14 | import org.junit.jupiter.api.Timeout; 15 | 16 | import java.io.IOException; 17 | import java.util.concurrent.atomic.AtomicBoolean; 18 | 19 | import static org.junit.jupiter.api.Assertions.*; 20 | import static org.mockito.internal.util.io.IOUtil.closeQuietly; 21 | 22 | class RemoteConnectorTest extends NetworkTestCommon { 23 | 24 | private RemoteConnector remoteConnector; 25 | private volatile Object connectedToSocketAddress; 26 | private AtomicBoolean tcpHandlerAddedToEventLoop = new AtomicBoolean(false); 27 | 28 | @BeforeEach 29 | void setUp() { 30 | remoteConnector = new RemoteConnector<>(this::createTcpEventHandler); 31 | } 32 | 33 | @Override 34 | @BeforeEach 35 | protected void threadDump() { 36 | super.threadDump(); 37 | } 38 | 39 | @Test 40 | @Timeout(3) 41 | void remoteConnectorLooksUpAddressOnEachIteration() throws IOException { 42 | final ChronicleServerSocketChannel initialSocketChannel = TCPRegistry.createServerSocketChannelFor("test-server"); 43 | Jvm.startup().on(RemoteConnectorTest.class, "Initial socket address is " + initialSocketChannel.socket().getLocalSocketAddress()); 44 | try (final EventGroup eventGroup = EventGroup.builder().build(); 45 | final TestClusterContext clusterContext = new TestClusterContext(); 46 | final TestClusteredNetworkContext nc = new TestClusteredNetworkContext(clusterContext)) { 47 | eventGroup.start(); 48 | closeQuietly(initialSocketChannel); 49 | // Will resolve initial channel, which is closed 50 | remoteConnector.connect("test-server", eventGroup, nc, 10); 51 | Jvm.pause(100); 52 | assertNull(connectedToSocketAddress); // it never connected 53 | // Reassign name to a fail-over channel 54 | final ChronicleServerSocketChannel failOverChannel = TCPRegistry.createServerSocketChannelFor("test-server"); 55 | assertNotEquals(failOverChannel.socket().getLocalPort(), initialSocketChannel.socket().getLocalPort()); 56 | Jvm.startup().on(RemoteConnectorTest.class, "Failover socket address is " + failOverChannel.socket().getLocalSocketAddress()); 57 | // Accept the connection 58 | try (final ChronicleSocketChannel accept = failOverChannel.accept()) { 59 | // Assert we connected to the fail-over socket 60 | assertNotNull(accept); 61 | Waiters.waitForCondition("Client connected address not populated", () -> tcpHandlerAddedToEventLoop.get(), 3_000); 62 | assertEquals(failOverChannel.socket().getLocalSocketAddress(), connectedToSocketAddress); 63 | } 64 | } 65 | } 66 | 67 | private TcpEventHandler createTcpEventHandler(TestClusteredNetworkContext nc) { 68 | connectedToSocketAddress = nc.socketChannel().socket().getRemoteSocketAddress(); 69 | return new InstrumentedTcpHandler(nc); 70 | } 71 | 72 | private class InstrumentedTcpHandler extends TcpEventHandler { 73 | 74 | public InstrumentedTcpHandler(@NotNull TestClusteredNetworkContext nc) { 75 | super(nc); 76 | } 77 | 78 | @Override 79 | public void eventLoop(EventLoop eventLoop) { 80 | super.eventLoop(eventLoop); 81 | tcpHandlerAddedToEventLoop.set(true); 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/network/VanillaNetworkContextTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network; 20 | 21 | import net.openhft.chronicle.core.io.BackgroundResourceReleaser; 22 | import net.openhft.chronicle.threads.Pauser; 23 | import net.openhft.chronicle.threads.TimingPauser; 24 | import org.junit.jupiter.api.Test; 25 | 26 | import java.util.concurrent.TimeUnit; 27 | import java.util.concurrent.TimeoutException; 28 | import java.util.concurrent.atomic.AtomicReference; 29 | 30 | import static org.junit.jupiter.api.Assertions.assertFalse; 31 | 32 | class VanillaNetworkContextTest extends NetworkTestCommon { 33 | 34 | @Test 35 | void networkStatsListenerShouldNotBeClosedOnBackgroundResourceReleaserThread() throws TimeoutException { 36 | final VanillaNetworkContext vanillaNetworkContext = new VanillaNetworkContext<>(); 37 | AtomicReference wasClosedInBackgroundReleaserThread = new AtomicReference<>(); 38 | vanillaNetworkContext.networkStatsListener(new NetworkStatsAdapter() { 39 | @Override 40 | public void close() { 41 | wasClosedInBackgroundReleaserThread.set(BackgroundResourceReleaser.isOnBackgroundResourceReleaserThread()); 42 | } 43 | }); 44 | vanillaNetworkContext.close(); 45 | TimingPauser pauser = Pauser.balanced(); 46 | while (wasClosedInBackgroundReleaserThread.get() == null) { 47 | pauser.pause(5, TimeUnit.SECONDS); 48 | } 49 | assertFalse(wasClosedInBackgroundReleaserThread.get()); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/network/cluster/handlers/HeartbeatHandlerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network.cluster.handlers; 20 | 21 | import net.openhft.chronicle.bytes.Bytes; 22 | import net.openhft.chronicle.network.NetworkTestCommon; 23 | import net.openhft.chronicle.wire.BinaryWire; 24 | import net.openhft.chronicle.wire.Wire; 25 | import org.junit.jupiter.api.Test; 26 | 27 | import static org.junit.jupiter.api.Assertions.assertThrows; 28 | 29 | class HeartbeatHandlerTest extends NetworkTestCommon { 30 | 31 | public static final long CID = 1234L; 32 | public static final int VALID_HEARTBEAT_TIMEOUT_MS = 1000; 33 | public static final int VALID_HEARTBEAT_INTERVAL_MS = 500; 34 | public static final int TOO_SMALL_HEARTBEAT_TIMEOUT_MS = 999; 35 | public static final int TOO_SMALL_HEARTBEAT_INTERVAL_MS = 499; 36 | 37 | @Test 38 | void tooSmallHeartbeatIntervalMsThrowsIllegalArgumentException() { 39 | assertThrows(IllegalArgumentException.class, () -> 40 | HeartbeatHandler.heartbeatHandler(VALID_HEARTBEAT_TIMEOUT_MS, TOO_SMALL_HEARTBEAT_INTERVAL_MS, CID)); 41 | } 42 | 43 | @Test 44 | void tooSmallHeartbeatIntervalMsThrowsIllegalArgumentExceptionConstructor() { 45 | assertThrows(IllegalArgumentException.class, () -> 46 | createByDeserialization(VALID_HEARTBEAT_TIMEOUT_MS, TOO_SMALL_HEARTBEAT_INTERVAL_MS)); 47 | } 48 | 49 | @Test 50 | void tooSmallHeartbeatTimeoutMsThrowsIllegalArgumentException() { 51 | assertThrows(IllegalArgumentException.class, () -> 52 | HeartbeatHandler.heartbeatHandler(TOO_SMALL_HEARTBEAT_TIMEOUT_MS, VALID_HEARTBEAT_INTERVAL_MS, CID)); 53 | } 54 | 55 | @Test 56 | void tooSmallHeartbeatTimeoutMsThrowsIllegalArgumentExceptionConstructor() { 57 | assertThrows(IllegalArgumentException.class, () -> 58 | createByDeserialization(TOO_SMALL_HEARTBEAT_TIMEOUT_MS, VALID_HEARTBEAT_INTERVAL_MS)); 59 | } 60 | 61 | @Test 62 | void intervalEqualToTimeoutThrowsIllegalStateException() { 63 | assertThrows(IllegalArgumentException.class, () -> 64 | HeartbeatHandler.heartbeatHandler(VALID_HEARTBEAT_TIMEOUT_MS, VALID_HEARTBEAT_TIMEOUT_MS, CID)); 65 | } 66 | 67 | @Test 68 | void intervalEqualToTimeoutThrowsIllegalStateExceptionConstructor() { 69 | assertThrows(IllegalArgumentException.class, () -> 70 | createByDeserialization(VALID_HEARTBEAT_TIMEOUT_MS, VALID_HEARTBEAT_TIMEOUT_MS)); 71 | } 72 | 73 | @Test 74 | void intervalGreaterThanTimeoutThrowsIllegalStateException() { 75 | assertThrows(IllegalArgumentException.class, () -> 76 | HeartbeatHandler.heartbeatHandler(VALID_HEARTBEAT_TIMEOUT_MS, VALID_HEARTBEAT_TIMEOUT_MS + 100, CID)); 77 | } 78 | 79 | @Test 80 | void intervalGreaterThanTimeoutThrowsIllegalStateExceptionConstructor() { 81 | assertThrows(IllegalArgumentException.class, () -> 82 | createByDeserialization(VALID_HEARTBEAT_TIMEOUT_MS, VALID_HEARTBEAT_TIMEOUT_MS + 100)); 83 | } 84 | 85 | private void createByDeserialization(long heartbeatTimeoutMs, long heartbeatIntervalMs) { 86 | Wire wire = new BinaryWire(Bytes.allocateElasticOnHeap()); 87 | wire.write("heartbeatTimeoutMs").int64(heartbeatTimeoutMs); 88 | wire.write("heartbeatIntervalMs").int64(heartbeatIntervalMs); 89 | new HeartbeatHandler<>(wire); 90 | } 91 | } -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/network/internal/AddressCacheTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network.internal; 20 | 21 | import net.openhft.chronicle.core.util.ThrowingRunnable; 22 | import net.openhft.chronicle.network.NetworkTestCommon; 23 | import org.junit.jupiter.api.BeforeEach; 24 | import org.junit.jupiter.api.Test; 25 | 26 | import java.net.InetSocketAddress; 27 | import java.security.Security; 28 | 29 | import static org.junit.jupiter.api.Assertions.*; 30 | 31 | class AddressCacheTest extends NetworkTestCommon { 32 | 33 | private static final String NETWORK_ADDRESS_CACHE_TTL = "networkaddress.cache.ttl"; 34 | private static final String DEFAULT_NETWORK_ADDRESS_CACHE_TTL = "-1"; 35 | private AddressCache addressCache; 36 | 37 | @BeforeEach 38 | void setUp() { 39 | addressCache = new AddressCache(); 40 | } 41 | 42 | @Test 43 | void addingEntryWillMakeItAvailableForLookup() { 44 | addressCache.add("test-123", "google.com", 123); 45 | assertEquals(addressCache.lookup("test-123"), new InetSocketAddress("google.com", 123)); 46 | } 47 | 48 | @Test 49 | void entriesAreUnavailableUntilAdded() { 50 | assertNull(addressCache.lookup("test-123")); 51 | } 52 | 53 | @Test 54 | void clearingWillMakeItUnavailableForLookup() { 55 | addressCache.add("test-123", "google.com", 123); 56 | assertEquals(addressCache.lookup("test-123"), new InetSocketAddress("google.com", 123)); 57 | addressCache.clear(); 58 | assertNull(addressCache.lookup("test-123")); 59 | } 60 | 61 | @Test 62 | void resolvedAddressesAreCachedWhenCachingIsEnabled() throws Throwable { 63 | withNetworkAddressCacheTtl("100", () -> { 64 | addressCache.add("test-123", "google.com", 123); 65 | InetSocketAddress original = addressCache.lookup("test-123"); 66 | assertSame(original, addressCache.lookup("test-123")); 67 | }); 68 | } 69 | 70 | @Test 71 | void resolvedAddressesAreCachedWhenCachingForeverIsEnabled() throws Throwable { 72 | withNetworkAddressCacheTtl("-1", () -> { 73 | addressCache.add("test-123", "google.com", 123); 74 | InetSocketAddress original = addressCache.lookup("test-123"); 75 | assertSame(original, addressCache.lookup("test-123")); 76 | }); 77 | } 78 | 79 | @Test 80 | void resolvedAddressesAreNotCachedWhenCachingIsDisabled() throws Throwable { 81 | withNetworkAddressCacheTtl("0", () -> { 82 | addressCache.add("test-123", "google.com", 123); 83 | InetSocketAddress original = addressCache.lookup("test-123"); 84 | assertNotSame(original, addressCache.lookup("test-123")); 85 | }); 86 | } 87 | 88 | private void withNetworkAddressCacheTtl(String ttlValue, ThrowingRunnable testCode) throws Throwable { 89 | Security.setProperty(NETWORK_ADDRESS_CACHE_TTL, ttlValue); 90 | try { 91 | testCode.run(); 92 | } finally { 93 | Security.setProperty(NETWORK_ADDRESS_CACHE_TTL, DEFAULT_NETWORK_ADDRESS_CACHE_TTL); 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/network/ssl/AbstractSocketBufferHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network.ssl; 20 | 21 | import net.openhft.chronicle.network.tcp.ChronicleSocketChannel; 22 | 23 | import java.io.IOException; 24 | import java.nio.ByteBuffer; 25 | 26 | abstract class AbstractSocketBufferHandler implements BufferHandler { 27 | private final ChronicleSocketChannel channel; 28 | 29 | AbstractSocketBufferHandler(final ChronicleSocketChannel socketChannel) { 30 | this.channel = socketChannel; 31 | } 32 | 33 | @Override 34 | public int readData(final ByteBuffer target) throws IOException { 35 | return channel.read(target); 36 | } 37 | 38 | @Override 39 | public int writeData(final ByteBuffer encrypted) throws IOException { 40 | return channel.write(encrypted); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/network/ssl/PingSender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network.ssl; 20 | 21 | import net.openhft.chronicle.core.threads.EventHandler; 22 | import net.openhft.chronicle.core.threads.InvalidEventHandlerException; 23 | import net.openhft.chronicle.network.NetworkContext; 24 | import net.openhft.chronicle.network.connection.CoreFields; 25 | 26 | import java.util.function.IntSupplier; 27 | import java.util.function.Supplier; 28 | 29 | final class PingSender implements EventHandler { 30 | 31 | private final Supplier nc; 32 | private final IntSupplier local; 33 | private final IntSupplier remote; 34 | private final long cid; 35 | private long lastPublish = 0; 36 | private int counter; 37 | 38 | PingSender(final Supplier nc, final IntSupplier local, final IntSupplier remote, final long cid) { 39 | this.nc = nc; 40 | this.local = local; 41 | this.remote = remote; 42 | this.cid = cid; 43 | } 44 | 45 | @Override 46 | public boolean action() throws InvalidEventHandlerException { 47 | if (lastPublish < System.currentTimeMillis() - 5000L) { 48 | 49 | nc.get().wireOutPublisher().put(null, wireOut -> { 50 | wireOut.writeDocument(true, d -> d.write(CoreFields.cid).int64(cid)); 51 | wireOut.writeDocument(false, 52 | d -> d.writeEventName("ping").int32(counter++)); 53 | 54 | }); 55 | lastPublish = System.currentTimeMillis(); 56 | } 57 | return false; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/network/ssl/SSLContextLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network.ssl; 20 | 21 | import org.jetbrains.annotations.NotNull; 22 | 23 | import javax.net.ssl.KeyManagerFactory; 24 | import javax.net.ssl.SSLContext; 25 | import javax.net.ssl.TrustManagerFactory; 26 | import java.io.File; 27 | import java.io.FileInputStream; 28 | import java.io.IOException; 29 | import java.security.*; 30 | import java.security.cert.CertificateException; 31 | 32 | final class SSLContextLoader { 33 | static final File KEYSTORE_FILE = new File("src/test/resources", "test.jks"); 34 | 35 | @NotNull 36 | static SSLContext getInitialisedContext() throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException, UnrecoverableKeyException, KeyManagementException { 37 | final SSLContext context = SSLContext.getInstance("TLS"); 38 | KeyManagerFactory kmf = 39 | KeyManagerFactory.getInstance("SunX509"); 40 | final KeyStore keyStore = KeyStore.getInstance("JKS"); 41 | final char[] password = "password".toCharArray(); 42 | keyStore.load(new FileInputStream(KEYSTORE_FILE), password); 43 | kmf.init(keyStore, password); 44 | 45 | final KeyStore trustStore = KeyStore.getInstance("JKS"); 46 | trustStore.load(new FileInputStream(KEYSTORE_FILE), password); 47 | 48 | TrustManagerFactory tmf = 49 | TrustManagerFactory.getInstance("SunX509"); 50 | tmf.init(trustStore); 51 | context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom()); 52 | return context; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/network/ssl/StateMachineProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.chronicle.network.ssl; 20 | 21 | import net.openhft.chronicle.threads.Pauser; 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | 25 | import javax.net.ssl.SSLContext; 26 | 27 | final class StateMachineProcessor implements Runnable { 28 | private static final Logger LOGGER = LoggerFactory.getLogger(StateMachineProcessor.class); 29 | 30 | private final SSLContext context; 31 | private final SslEngineStateMachine stateMachine; 32 | private final Pauser pauser = Pauser.balanced(); 33 | private volatile boolean running = true; 34 | 35 | StateMachineProcessor(final boolean isAcceptor, 36 | final SSLContext context, 37 | final BufferHandler bufferHandler) { 38 | this.context = context; 39 | stateMachine = new SslEngineStateMachine(bufferHandler, isAcceptor); 40 | } 41 | 42 | @Override 43 | public void run() { 44 | try { 45 | stateMachine.initialise(context); 46 | 47 | while (!Thread.currentThread().isInterrupted() && running) { 48 | while (running && stateMachine.action()) { 49 | pauser.reset(); 50 | } 51 | pauser.pause(); 52 | } 53 | } catch (Throwable e) { 54 | if (running) 55 | LOGGER.error("Exception caught while processing SSL state machine. Exiting.", e); 56 | } 57 | } 58 | 59 | public void stop() { 60 | this.running = false; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/network/tcp/FastJ8SocketChannelTest.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.network.tcp; 2 | 3 | import net.openhft.chronicle.network.NetworkTestCommon; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import java.io.IOException; 7 | import java.net.InetSocketAddress; 8 | import java.nio.ByteBuffer; 9 | import java.nio.channels.ClosedChannelException; 10 | import java.nio.channels.ServerSocketChannel; 11 | import java.nio.channels.SocketChannel; 12 | 13 | import static org.junit.jupiter.api.Assertions.assertThrows; 14 | 15 | class FastJ8SocketChannelTest extends NetworkTestCommon { 16 | 17 | @Test 18 | void closedChannelExceptionIsThrownWhenAttemptIsMadeToReadFromClosedChannel() throws IOException { 19 | try (final ServerSocketChannel local = ServerSocketChannel.open().bind(new InetSocketAddress("localhost", 0))) { 20 | local.configureBlocking(false); 21 | try (final SocketChannel remote = SocketChannel.open(local.socket().getLocalSocketAddress())) { 22 | remote.configureBlocking(false); 23 | final FastJ8SocketChannel fastJ8SocketChannel = new FastJ8SocketChannel(remote); 24 | remote.close(); 25 | assertThrows(ClosedChannelException.class, () -> fastJ8SocketChannel.read(ByteBuffer.allocateDirect(100))); 26 | fastJ8SocketChannel.close(); 27 | } 28 | } 29 | } 30 | 31 | @Test 32 | void closedChannelExceptionIsThrownWhenAttemptIsMadeToWriteToClosedChannel() throws IOException { 33 | try (final ServerSocketChannel local = ServerSocketChannel.open().bind(new InetSocketAddress("localhost", 0))) { 34 | local.configureBlocking(false); 35 | try (final SocketChannel remote = SocketChannel.open(local.socket().getLocalSocketAddress())) { 36 | remote.configureBlocking(false); 37 | final FastJ8SocketChannel fastJ8SocketChannel = new FastJ8SocketChannel(remote); 38 | remote.close(); 39 | assertThrows(ClosedChannelException.class, () -> fastJ8SocketChannel.write(ByteBuffer.allocateDirect(100))); 40 | fastJ8SocketChannel.close(); 41 | } 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/network/test/TestCluster.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.network.test; 2 | 3 | import net.openhft.chronicle.network.cluster.Cluster; 4 | 5 | /** 6 | * A very minimal {@link Cluster} implementation for use in tests 7 | */ 8 | public class TestCluster extends Cluster { 9 | public TestCluster(TestClusterContext clusterContext) { 10 | super(); 11 | clusterContext(clusterContext); 12 | clusterContext.cluster(this); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/network/test/TestClusteredNetworkContext.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.network.test; 2 | 3 | import net.openhft.chronicle.network.ConnectionListener; 4 | import net.openhft.chronicle.network.cluster.VanillaClusteredNetworkContext; 5 | import org.apache.mina.util.IdentityHashSet; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.util.Collection; 10 | import java.util.Set; 11 | 12 | /** 13 | * A very minimal {@link net.openhft.chronicle.network.cluster.ClusteredNetworkContext} implementation for use in tests 14 | */ 15 | public class TestClusteredNetworkContext extends VanillaClusteredNetworkContext { 16 | 17 | public final Set connectionListeners = new IdentityHashSet<>(); 18 | private final ConnectionListener compositeConnectionListener = new CompositeConnectionListener(connectionListeners); 19 | private Long heartbeatTimeoutMsOverride; 20 | private boolean disableReconnect = false; 21 | private boolean returnNullConnectionListener = false; 22 | 23 | public TestClusteredNetworkContext(@NotNull TestClusterContext clusterContext) { 24 | super(clusterContext); 25 | } 26 | 27 | /** 28 | * Disable the reconnection, calls to {@link #socketReconnector()} will return a no-op {@link Runnable} 29 | */ 30 | public void disableReconnect() { 31 | disableReconnect = true; 32 | } 33 | 34 | /** 35 | * This will override the NetworkContext#heartbeatTimeoutMs that's set on this context 36 | * 37 | * @param heartbeatTimeoutMsOverride The desired return value for heartbeatTimeoutMs 38 | */ 39 | public void heartbeatTimeoutMsOverride(Long heartbeatTimeoutMsOverride) { 40 | this.heartbeatTimeoutMsOverride = heartbeatTimeoutMsOverride; 41 | } 42 | 43 | /** 44 | * This will cause the context to return a null ConnectionListener 45 | */ 46 | public void returnNullConnectionListener() { 47 | this.returnNullConnectionListener = true; 48 | } 49 | 50 | @Override 51 | public Runnable socketReconnector() { 52 | if (disableReconnect) { 53 | return () -> { 54 | }; 55 | } 56 | return super.socketReconnector(); 57 | } 58 | 59 | @Override 60 | public long heartbeatTimeoutMs() { 61 | if (heartbeatTimeoutMsOverride != null) { 62 | return heartbeatTimeoutMsOverride; 63 | } 64 | return super.heartbeatTimeoutMs(); 65 | } 66 | 67 | @Override 68 | public void addConnectionListener(ConnectionListener connectionListener) { 69 | connectionListeners.add(connectionListener); 70 | } 71 | 72 | @Override 73 | public void removeConnectionListener(ConnectionListener connectionListener) { 74 | connectionListeners.remove(connectionListener); 75 | } 76 | 77 | @Override 78 | public @Nullable ConnectionListener acquireConnectionListener() { 79 | return returnNullConnectionListener ? null : compositeConnectionListener; 80 | } 81 | 82 | static class CompositeConnectionListener implements ConnectionListener { 83 | private final Collection listenerCollection; 84 | 85 | public CompositeConnectionListener(Collection listenerCollection) { 86 | this.listenerCollection = listenerCollection; 87 | } 88 | 89 | @Override 90 | public void onConnected(int localIdentifier, int remoteIdentifier, boolean isAcceptor) { 91 | listenerCollection.forEach(cl -> cl.onConnected(localIdentifier, remoteIdentifier, isAcceptor)); 92 | } 93 | 94 | @Override 95 | public void onDisconnected(int localIdentifier, int remoteIdentifier, boolean isAcceptor) { 96 | listenerCollection.forEach(cl -> cl.onDisconnected(localIdentifier, remoteIdentifier, isAcceptor)); 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/network/util/TestServer.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.network.util; 2 | 3 | import net.openhft.chronicle.core.Jvm; 4 | import net.openhft.chronicle.core.io.AbstractCloseable; 5 | import net.openhft.chronicle.core.io.Closeable; 6 | import net.openhft.chronicle.network.TCPRegistry; 7 | import net.openhft.chronicle.network.tcp.ChronicleServerSocketChannel; 8 | import net.openhft.chronicle.network.tcp.ChronicleSocketChannel; 9 | 10 | import java.io.IOException; 11 | import java.net.InetSocketAddress; 12 | import java.util.concurrent.CountDownLatch; 13 | 14 | public class TestServer extends AbstractCloseable { 15 | 16 | private final ChronicleServerSocketChannel serverSocketChannel; 17 | private final String uri; 18 | private Thread serverThread; 19 | 20 | public TestServer(String registryHostName) throws IOException { 21 | serverSocketChannel = TCPRegistry.createServerSocketChannelFor(registryHostName); 22 | final InetSocketAddress localSocketAddress = (InetSocketAddress) serverSocketChannel.socket().getLocalSocketAddress(); 23 | uri = localSocketAddress.getHostName() + ":" + localSocketAddress.getPort(); 24 | Jvm.startup().on(TestServer.class, "Test server URI is " + uri); 25 | } 26 | 27 | public void prepareToAcceptAConnection() { 28 | CountDownLatch latch = new CountDownLatch(2); 29 | serverThread = new Thread(() -> { 30 | waitAtLatch(latch); 31 | try (final ChronicleSocketChannel accept = serverSocketChannel.accept()) { 32 | Jvm.startup().on(TestServer.class, "Connected to " + accept.getRemoteAddress()); 33 | } catch (IOException e) { 34 | throw new RuntimeException(e); 35 | } 36 | }); 37 | serverThread.start(); 38 | waitAtLatch(latch); 39 | } 40 | 41 | private void waitAtLatch(CountDownLatch latch) { 42 | try { 43 | latch.countDown(); 44 | latch.await(); 45 | } catch (InterruptedException e) { 46 | Thread.currentThread().interrupt(); 47 | throw new RuntimeException(e); 48 | } 49 | } 50 | 51 | @Override 52 | protected void performClose() { 53 | Closeable.closeQuietly(serverSocketChannel); 54 | try { 55 | if (serverThread != null) 56 | serverThread.join(); 57 | } catch (InterruptedException e) { 58 | Thread.currentThread().interrupt(); 59 | throw new RuntimeException(e); 60 | } 61 | } 62 | 63 | public String uri() { 64 | return uri; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/network/util/TestUtil.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.network.util; 2 | 3 | import java.io.IOException; 4 | import java.net.ServerSocket; 5 | 6 | public enum TestUtil { 7 | ; 8 | 9 | /** 10 | * Get a port number that's most likely available 11 | * 12 | * @return a port number that's available 13 | */ 14 | public static int getAvailablePortNumber() { 15 | try (final ServerSocket serverSocket = new ServerSocket(0)) { 16 | return serverSocket.getLocalPort(); 17 | } catch (IOException e) { 18 | throw new RuntimeException(e); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/performance/tests/network/EchoHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.performance.tests.network; 19 | 20 | import net.openhft.chronicle.bytes.Bytes; 21 | import net.openhft.chronicle.core.io.AbstractCloseable; 22 | import net.openhft.chronicle.network.VanillaNetworkContext; 23 | import net.openhft.chronicle.network.api.TcpHandler; 24 | import org.jetbrains.annotations.NotNull; 25 | 26 | public class EchoHandler> extends AbstractCloseable implements TcpHandler { 27 | 28 | public EchoHandler() { 29 | } 30 | 31 | @Override 32 | protected void performClose() { 33 | } 34 | 35 | @Override 36 | public void process(@NotNull final Bytes in, @NotNull final Bytes out, T nc) { 37 | // // System.out.println(in.readRemaining()); 38 | if (in.readRemaining() == 0) 39 | return; 40 | // // System.out.println("P start " + in.toDebugString()); 41 | long toWrite = Math.min(in.readRemaining(), out.writeRemaining()); 42 | out.write(in, in.readPosition(), toWrite); 43 | in.readSkip(toWrite); 44 | // // System.out.println("... P End " + in.toDebugString()); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/performance/tests/network/LegacyHanderFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.performance.tests.network; 19 | 20 | import net.openhft.chronicle.network.HeaderTcpHandler; 21 | import net.openhft.chronicle.network.NetworkContext; 22 | import net.openhft.chronicle.network.TcpEventHandler; 23 | import net.openhft.chronicle.network.WireTypeSniffingTcpHandler; 24 | import net.openhft.chronicle.network.api.TcpHandler; 25 | import net.openhft.chronicle.network.api.session.SessionDetailsProvider; 26 | import net.openhft.chronicle.network.connection.VanillaWireOutPublisher; 27 | import net.openhft.chronicle.wire.WireType; 28 | import org.jetbrains.annotations.NotNull; 29 | 30 | import java.util.function.Function; 31 | 32 | import static net.openhft.chronicle.wire.WireType.TEXT; 33 | 34 | public enum LegacyHanderFactory { 35 | INSTANCE; 36 | 37 | public static > Function> 38 | legacyTcpEventHandlerFactory(@NotNull final Function> defaultHandedFactory, 39 | final long heartbeatIntervalTicks, 40 | final long heartbeatIntervalTimeout) { 41 | return (networkContext) -> { 42 | @NotNull final TcpEventHandler handler = new TcpEventHandler<>(networkContext); 43 | 44 | @NotNull final Function> consumer = o -> { 45 | if (o instanceof SessionDetailsProvider) { 46 | networkContext.sessionDetails((SessionDetailsProvider) o); 47 | return defaultHandedFactory.apply(networkContext); 48 | } else if (o instanceof TcpHandler) 49 | return (TcpHandler) o; 50 | 51 | throw new UnsupportedOperationException(""); 52 | }; 53 | 54 | @NotNull final HeaderTcpHandler headerTcpHandler = new HeaderTcpHandler<>(handler, 55 | consumer 56 | ); 57 | 58 | @NotNull final WireTypeSniffingTcpHandler wireTypeSniffingTcpHandler = 59 | new WireTypeSniffingTcpHandler<>(handler, (nc) -> headerTcpHandler); 60 | 61 | handler.tcpHandler(wireTypeSniffingTcpHandler); 62 | return handler; 63 | }; 64 | } 65 | 66 | public static > Function> legacyTcpEventHandlerFactory( 67 | @NotNull final Function> defaultHandedFactory) { 68 | return legacyTcpEventHandlerFactory(defaultHandedFactory, 20_000, 40_000); 69 | } 70 | 71 | public static > Function> simpleTcpEventHandlerFactory(@NotNull final Function> defaultHandedFactory, final WireType text) { 72 | return (networkContext) -> { 73 | 74 | networkContext.wireOutPublisher(new VanillaWireOutPublisher(TEXT)); 75 | @NotNull final TcpEventHandler handler = new TcpEventHandler<>(networkContext); 76 | handler.tcpHandler(new WireTypeSniffingTcpHandler<>(handler, 77 | defaultHandedFactory)); 78 | return handler; 79 | 80 | }; 81 | } 82 | 83 | public static > Function> defaultTcpEventHandlerFactory(@NotNull final Function> defaultHandedFactory) { 84 | return (networkContext) -> { 85 | networkContext.wireOutPublisher(new VanillaWireOutPublisher(TEXT)); 86 | @NotNull final TcpEventHandler handler = new TcpEventHandler<>(networkContext); 87 | handler.tcpHandler(defaultHandedFactory.apply(networkContext)); 88 | return handler; 89 | 90 | }; 91 | } 92 | } -------------------------------------------------------------------------------- /src/test/java/net/openhft/performance/tests/network/SelectedSelectionKeySet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The Netty Project 3 | * 4 | * The Netty Project licenses this file to you under the Apache License, 5 | * version 2.0 (the "License"); you may not use this file except in compliance 6 | * with the License. You may obtain a copy of the License at: 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations 14 | * under the License. 15 | */ 16 | 17 | package net.openhft.performance.tests.network; 18 | 19 | import org.jetbrains.annotations.NotNull; 20 | 21 | import java.nio.channels.SelectionKey; 22 | import java.util.AbstractSet; 23 | import java.util.Iterator; 24 | 25 | final class SelectedSelectionKeySet extends AbstractSet { 26 | 27 | private SelectionKey[] keysA; 28 | private int keysASize; 29 | private SelectionKey[] keysB; 30 | private int keysBSize; 31 | private boolean isA = true; 32 | 33 | SelectedSelectionKeySet() { 34 | keysA = new SelectionKey[1024]; 35 | keysB = keysA.clone(); 36 | } 37 | 38 | @Override 39 | public boolean add(SelectionKey o) { 40 | if (o == null) { 41 | return false; 42 | } 43 | 44 | if (isA) { 45 | int size = keysASize; 46 | keysA[size ++] = o; 47 | keysASize = size; 48 | if (size == keysA.length) { 49 | doubleCapacityA(); 50 | } 51 | } else { 52 | int size = keysBSize; 53 | keysB[size ++] = o; 54 | keysBSize = size; 55 | if (size == keysB.length) { 56 | doubleCapacityB(); 57 | } 58 | } 59 | 60 | return true; 61 | } 62 | 63 | private void doubleCapacityA() { 64 | SelectionKey[] newKeysA = new SelectionKey[keysA.length << 1]; 65 | System.arraycopy(keysA, 0, newKeysA, 0, keysASize); 66 | keysA = newKeysA; 67 | } 68 | 69 | private void doubleCapacityB() { 70 | SelectionKey[] newKeysB = new SelectionKey[keysB.length << 1]; 71 | System.arraycopy(keysB, 0, newKeysB, 0, keysBSize); 72 | keysB = newKeysB; 73 | } 74 | 75 | SelectionKey[] flip() { 76 | if (isA) { 77 | isA = false; 78 | keysA[keysASize] = null; 79 | keysBSize = 0; 80 | return keysA; 81 | } else { 82 | isA = true; 83 | keysB[keysBSize] = null; 84 | keysASize = 0; 85 | return keysB; 86 | } 87 | } 88 | 89 | @Override 90 | public int size() { 91 | if (isA) { 92 | return keysASize; 93 | } else { 94 | return keysBSize; 95 | } 96 | } 97 | 98 | @Override 99 | public boolean remove(Object o) { 100 | return false; 101 | } 102 | 103 | @Override 104 | public boolean contains(Object o) { 105 | return false; 106 | } 107 | 108 | @Override 109 | public @NotNull Iterator iterator() { 110 | throw new UnsupportedOperationException(); 111 | } 112 | } -------------------------------------------------------------------------------- /src/test/java/net/openhft/performance/tests/network/TestData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.performance.tests.network; 19 | 20 | import net.openhft.chronicle.wire.WireIn; 21 | import net.openhft.chronicle.wire.WireKey; 22 | import net.openhft.chronicle.wire.WireOut; 23 | import org.jetbrains.annotations.NotNull; 24 | 25 | import java.util.function.DoubleConsumer; 26 | import java.util.function.IntConsumer; 27 | import java.util.function.LongConsumer; 28 | 29 | class TestData implements DoubleConsumer, LongConsumer, IntConsumer { 30 | int value1; 31 | long value2; 32 | double value3; 33 | 34 | public TestData() { 35 | } 36 | 37 | public void write(@NotNull WireOut wire) { 38 | wire.write(Field.key1).int32(value1) 39 | .write(Field.key2).int64(value2) 40 | .write(Field.key3).float64(value3); 41 | } 42 | 43 | public void read(@NotNull WireIn wire) { 44 | wire.read(Field.key1).int32(this, (o, i) -> value1 = i) 45 | .read(Field.key2).int64(this, (o, i) -> value2 = i) 46 | .read(Field.key3).float64(this, (o, i) -> value3 = i); 47 | } 48 | 49 | @Override 50 | public void accept(double value) { 51 | value3 = value; 52 | } 53 | 54 | @Override 55 | public void accept(int value) { 56 | } 57 | 58 | @Override 59 | public void accept(long value) { 60 | } 61 | 62 | enum Field implements WireKey { 63 | key1, key2, key3 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/performance/tests/network/TimedEchoHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.performance.tests.network; 19 | 20 | import net.openhft.chronicle.bytes.Bytes; 21 | import net.openhft.chronicle.core.io.SimpleCloseable; 22 | import net.openhft.chronicle.core.threads.EventLoop; 23 | import net.openhft.chronicle.network.AcceptorEventHandler; 24 | import net.openhft.chronicle.network.NetworkContext; 25 | import net.openhft.chronicle.network.VanillaNetworkContext; 26 | import net.openhft.chronicle.network.api.TcpHandler; 27 | import net.openhft.chronicle.threads.EventGroup; 28 | import net.openhft.performance.tests.vanilla.tcp.EchoClientMain; 29 | import org.jetbrains.annotations.NotNull; 30 | 31 | import java.io.IOException; 32 | 33 | class TimedEchoHandler> 34 | extends SimpleCloseable 35 | implements TcpHandler { 36 | 37 | public TimedEchoHandler(T t) { 38 | 39 | } 40 | 41 | public static > void main(String[] args) throws IOException { 42 | @NotNull EventLoop eg = EventGroup.builder().withDaemon(false).build(); 43 | eg.start(); 44 | @NotNull AcceptorEventHandler eah = new AcceptorEventHandler<>("*:" + EchoClientMain.PORT, 45 | LegacyHanderFactory.legacyTcpEventHandlerFactory(TimedEchoHandler::new), 46 | () -> (T) new VanillaNetworkContext<>()); 47 | 48 | eg.addHandler(eah); 49 | } 50 | 51 | @Override 52 | public void process(@NotNull final Bytes in, @NotNull final Bytes out, T nc) { 53 | if (in.readRemaining() == 0) 54 | return; 55 | long toWrite = Math.min(in.readRemaining(), out.writeRemaining()); 56 | out.write(in, in.readPosition(), toWrite); 57 | out.writeLong(System.nanoTime()); 58 | in.readSkip(toWrite); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/performance/tests/network/WireEchoRequestHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.performance.tests.network; 19 | 20 | import net.openhft.chronicle.network.NetworkContext; 21 | import net.openhft.chronicle.network.WireTcpHandler; 22 | import net.openhft.chronicle.wire.DocumentContext; 23 | import net.openhft.chronicle.wire.Wire; 24 | import net.openhft.chronicle.wire.WireOut; 25 | import org.jetbrains.annotations.NotNull; 26 | 27 | /** 28 | * This code is used to read the tid and payload from a wire message, and send the same tid and 29 | * message back to the client 30 | */ 31 | public class WireEchoRequestHandler extends WireTcpHandler { 32 | 33 | public WireEchoRequestHandler(NetworkContext networkContext) { 34 | 35 | } 36 | 37 | /** 38 | * simply reads the csp,tid and payload and sends back the tid and payload 39 | * 40 | * @param in the DocumentContext from the client 41 | * @param outWire the wire to be sent back to the server 42 | */ 43 | @Override 44 | protected void onRead(@NotNull DocumentContext in, 45 | @NotNull WireOut outWire) { 46 | 47 | Wire wire = in.wire(); 48 | assert wire != null; 49 | if (in.isMetaData()) { 50 | long tid = wire.read("tid").int64(); 51 | outWire.writeDocument(true, 52 | meta -> meta.write("tid").int64(tid)); 53 | } else { 54 | String payload = wire.read("payload").text(); 55 | outWire.writeDocument(false, 56 | data -> data.write("payloadResponse").text(payload)); 57 | } 58 | 59 | } 60 | 61 | @Override 62 | protected void onInitialize() { 63 | 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/performance/tests/third/party/frameworks/grizzly/GrizzlyEchoServer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.performance.tests.third.party.frameworks.grizzly; 19 | 20 | import org.glassfish.grizzly.filterchain.*; 21 | import org.glassfish.grizzly.nio.transport.TCPNIOTransport; 22 | import org.jetbrains.annotations.NotNull; 23 | 24 | import java.io.IOException; 25 | import java.util.concurrent.CountDownLatch; 26 | import java.util.concurrent.TimeUnit; 27 | import java.util.logging.Logger; 28 | 29 | import static org.glassfish.grizzly.nio.transport.TCPNIOTransportBuilder.newInstance; 30 | 31 | /** 32 | * Class initializes and starts the echo server, based on Grizzly 2.3 33 | */ 34 | public class GrizzlyEchoServer { 35 | 36 | static final int PORT = Integer.parseInt(System.getProperty("port", "9124")); 37 | private static final Logger LOG = Logger.getLogger(GrizzlyEchoServer.class.getName()); 38 | @NotNull 39 | private static CountDownLatch countDownLatch = new CountDownLatch(1); 40 | 41 | public static void main(String[] args) throws IOException, InterruptedException { 42 | // Create a FilterChain using FilterChainBuilder 43 | @NotNull FilterChainBuilder filterChainBuilder = FilterChainBuilder.stateless(); 44 | 45 | // Add TransportFilter, which is responsible 46 | // for reading and writing data to the connection 47 | filterChainBuilder.add(new TransportFilter()); 48 | 49 | // EchoFilter is responsible for echoing received messages 50 | filterChainBuilder.add(new BaseFilter() { 51 | @Override 52 | public NextAction handleRead(@NotNull FilterChainContext ctx) { 53 | // Peer address is used for non-connected UDP Connection :) 54 | final Object peerAddress = ctx.getAddress(); 55 | final Object message = ctx.getMessage(); 56 | 57 | ctx.write(peerAddress, message, null); 58 | 59 | return ctx.getStopAction(); 60 | } 61 | }); 62 | 63 | // Create TCP transport 64 | final TCPNIOTransport transport = newInstance().build(); 65 | 66 | transport.setProcessor(filterChainBuilder.build()); 67 | try { 68 | // binding transport to start listen on certain host and port 69 | transport.bind(PORT); 70 | 71 | // start the transport 72 | transport.start(); 73 | 74 | countDownLatch.await(50, TimeUnit.SECONDS); 75 | } finally { 76 | LOG.info("Stopping transport..."); 77 | // stop the transport 78 | transport.shutdownNow(); 79 | 80 | LOG.info("Stopped transport..."); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/performance/tests/third/party/frameworks/mina/MinaEchoServer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.performance.tests.third.party.frameworks.mina; 19 | 20 | import org.apache.mina.core.service.IoAcceptor; 21 | import org.apache.mina.core.service.IoHandlerAdapter; 22 | import org.apache.mina.core.session.IdleStatus; 23 | import org.apache.mina.core.session.IoSession; 24 | import org.apache.mina.transport.socket.nio.NioSocketAcceptor; 25 | import org.jetbrains.annotations.NotNull; 26 | 27 | import java.io.IOException; 28 | import java.net.InetSocketAddress; 29 | 30 | public class MinaEchoServer { 31 | 32 | static final int PORT = Integer.getInteger("port", 9120); 33 | 34 | public static void main(String[] args) throws IOException { 35 | 36 | @NotNull final IoAcceptor acceptor = new NioSocketAcceptor(); 37 | 38 | acceptor.setHandler(new IoHandlerAdapter() { 39 | @Override 40 | public void exceptionCaught(IoSession session, @NotNull Throwable cause) { 41 | cause.printStackTrace(); 42 | } 43 | 44 | @Override 45 | public void messageReceived(@NotNull IoSession session, Object message) { 46 | session.write(message); 47 | } 48 | 49 | @Override 50 | public void sessionIdle(IoSession session, IdleStatus status) { 51 | 52 | } 53 | }); 54 | 55 | acceptor.getSessionConfig().setReadBufferSize(2048); 56 | acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10); 57 | acceptor.bind(new InetSocketAddress(PORT)); 58 | } 59 | } -------------------------------------------------------------------------------- /src/test/java/net/openhft/performance/tests/third/party/frameworks/netty/NettyEchoServer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.performance.tests.third.party.frameworks.netty; 19 | 20 | import io.netty.bootstrap.ServerBootstrap; 21 | import io.netty.channel.*; 22 | import io.netty.channel.nio.NioEventLoopGroup; 23 | import io.netty.channel.socket.SocketChannel; 24 | import io.netty.channel.socket.nio.NioServerSocketChannel; 25 | import net.openhft.performance.tests.vanilla.tcp.EchoClientMain; 26 | import org.jetbrains.annotations.NotNull; 27 | 28 | /** 29 | * Discards any incoming data. 30 | */ 31 | public class NettyEchoServer { 32 | 33 | private int port; 34 | 35 | public NettyEchoServer(int port) { 36 | this.port = port; 37 | } 38 | 39 | public static void main(@NotNull String[] args) throws InterruptedException { 40 | int port; 41 | if (args.length > 0) { 42 | port = Integer.parseInt(args[0]); 43 | 44 | } else { 45 | port = EchoClientMain.PORT; 46 | } 47 | new NettyEchoServer(port).run(); 48 | } 49 | 50 | public void run() throws InterruptedException { 51 | @NotNull EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1) 52 | @NotNull EventLoopGroup workerGroup = new NioEventLoopGroup(); 53 | try { 54 | @NotNull ServerBootstrap b = new ServerBootstrap(); // (2) 55 | b.group(bossGroup, workerGroup) 56 | .channel(NioServerSocketChannel.class) // (3) 57 | .childHandler(new ChannelInitializer() { // (4) 58 | @Override 59 | public void initChannel(@NotNull SocketChannel ch) { 60 | ch.pipeline().addLast(new ChannelInboundHandlerAdapter() { 61 | // echo server 62 | @Override 63 | public void channelRead(@NotNull ChannelHandlerContext ctx, Object msg) { // (2) 64 | ctx.write(msg); // (1) 65 | ctx.flush(); // (2) 66 | } 67 | 68 | @Override 69 | public void exceptionCaught(@NotNull ChannelHandlerContext ctx, @NotNull Throwable cause) { // (4) 70 | // Close the connection when an exception is raised. 71 | cause.printStackTrace(); 72 | ctx.close(); 73 | } 74 | }); 75 | } 76 | }) 77 | .option(ChannelOption.SO_BACKLOG, 128) // (5) 78 | .childOption(ChannelOption.SO_KEEPALIVE, true); // (6) 79 | 80 | // Bind and start to accept incoming connections. 81 | ChannelFuture f = b.bind(port).sync(); // (7) 82 | 83 | // Wait until the server socket is closed. 84 | // In this example, this does not happen, but you can do that to gracefully 85 | // shut down your server. 86 | f.channel().closeFuture().sync(); 87 | } finally { 88 | workerGroup.shutdownGracefully(); 89 | bossGroup.shutdownGracefully(); 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /src/test/java/net/openhft/performance/tests/vanilla/tcp/EchoMultiServerMain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package net.openhft.performance.tests.vanilla.tcp; 19 | 20 | import net.openhft.chronicle.threads.NamedThreadFactory; 21 | import org.jetbrains.annotations.NotNull; 22 | 23 | import java.io.IOException; 24 | import java.net.InetSocketAddress; 25 | import java.nio.ByteBuffer; 26 | import java.nio.channels.ServerSocketChannel; 27 | import java.nio.channels.SocketChannel; 28 | import java.util.concurrent.ExecutorService; 29 | import java.util.concurrent.SynchronousQueue; 30 | import java.util.concurrent.ThreadPoolExecutor; 31 | import java.util.concurrent.TimeUnit; 32 | 33 | /** 34 | * @author peter.lawrey 35 | */ 36 | public class EchoMultiServerMain { 37 | 38 | public static final int CAPACITY = 64 << 10; 39 | 40 | public static void main(@NotNull String... args) throws IOException { 41 | int port = args.length < 1 ? EchoClientMain.PORT : Integer.parseInt(args[0]); 42 | ServerSocketChannel ssc = ServerSocketChannel.open(); 43 | ssc.bind(new InetSocketAddress(port)); 44 | System.out.println("listening on " + ssc); 45 | ExecutorService service = new ThreadPoolExecutor(0, 1000, 46 | 60L, TimeUnit.SECONDS, 47 | new SynchronousQueue(), 48 | new NamedThreadFactory("connections", true)); 49 | ((ThreadPoolExecutor) service).setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); 50 | 51 | while (true) { 52 | final SocketChannel socket = ssc.accept(); 53 | socket.socket().setTcpNoDelay(true); 54 | socket.configureBlocking(true); 55 | service.submit(() -> process(socket)); 56 | } 57 | } 58 | 59 | private static void process(SocketChannel socket) { 60 | ByteBuffer bb = ByteBuffer.allocateDirect(CAPACITY); 61 | ByteBuffer bb2 = ByteBuffer.allocateDirect(CAPACITY); 62 | for (; ; ) { 63 | try { 64 | // simulate copying the data. 65 | // obviously faster if you don't touch the data but no real service would do that. 66 | bb.clear(); 67 | int len = socket.read(bb); 68 | if (len < 0) { 69 | System.out.println("... closed " + socket + " on read"); 70 | socket.close(); 71 | return; 72 | } else if (len == 0) { 73 | continue; 74 | } 75 | bb.flip(); 76 | bb2.clear(); 77 | bb2.put(bb); 78 | bb2.flip(); 79 | // make sure there is enough space to do a full read the next time. 80 | 81 | while ((len = socket.write(bb2)) > 0) { 82 | // busy wait 83 | } 84 | if (len < 0) { 85 | System.out.println("... closed " + socket + " on write"); 86 | socket.close(); 87 | return; 88 | } 89 | } catch (IOException ioe) { 90 | System.out.println("... closed " + socket + " on " + ioe); 91 | try { 92 | socket.close(); 93 | } catch (IOException e) { 94 | // ignored 95 | } 96 | return; 97 | } 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/performance/tests/vanilla/tcp/EchoServer2Main.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 chronicle.software 3 | * 4 | * https://chronicle.software 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package net.openhft.performance.tests.vanilla.tcp; 20 | 21 | import net.openhft.affinity.Affinity; 22 | import net.openhft.chronicle.core.threads.EventLoop; 23 | import net.openhft.chronicle.network.AcceptorEventHandler; 24 | import net.openhft.chronicle.network.TcpEventHandler; 25 | import net.openhft.chronicle.network.VanillaNetworkContext; 26 | import net.openhft.chronicle.threads.EventGroup; 27 | import net.openhft.chronicle.threads.Pauser; 28 | import net.openhft.performance.tests.network.EchoHandler; 29 | import org.jetbrains.annotations.NotNull; 30 | 31 | import java.io.IOException; 32 | 33 | public class EchoServer2Main { 34 | public static > void main(String[] args) throws IOException { 35 | System.setProperty("pauser.minProcessors", "1"); 36 | Affinity.acquireCore(); 37 | @NotNull EventLoop eg = EventGroup.builder().withDaemon(false).withPauser(Pauser.busy()).withBinding("any").build(); 38 | eg.start(); 39 | 40 | @NotNull AcceptorEventHandler eah = new AcceptorEventHandler("*:" + EchoClientMain.PORT, 41 | nc -> { 42 | TcpEventHandler teh = new TcpEventHandler(nc); 43 | teh.tcpHandler(new EchoHandler<>()); 44 | return teh; 45 | }, 46 | () -> (T) new VanillaNetworkContext()); 47 | eg.addHandler(eah); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/resources/ssl-test-cluster.yaml: -------------------------------------------------------------------------------- 1 | { 2 | context: !SslTestClusterContext {}, 3 | hostOne: { 4 | hostId: 1, 5 | connectUri: "host1.port" 6 | }, 7 | hostTwo: { 8 | hostId: 2, 9 | connectUri: "host2.port" 10 | } 11 | } -------------------------------------------------------------------------------- /src/test/resources/test.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHFT/Chronicle-Network/1755b5a65e64f4540a3e7f498823527bc18117ab/src/test/resources/test.jks -------------------------------------------------------------------------------- /system.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2016-2022 chronicle.software 3 | # 4 | # https://chronicle.software 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | # Tracing if resources are closed/released correctly. 20 | jvm.resource.tracing=true 21 | check.thread.safety=true 22 | disable.discard.warning=false 23 | # for profiling 24 | jvm.safepoint.enabled=false 25 | # reduce logging of the announcer 26 | chronicle.announcer.disable=true 27 | 28 | 29 | ping_pong.server=16 30 | ping_pong.client1=15 31 | ping_pong.client2=15 32 | 33 | tcp.cic=false 34 | -------------------------------------------------------------------------------- /systemProperties.adoc: -------------------------------------------------------------------------------- 1 | == System Properties 2 | Below, a number of relevant System Properties are listed. 3 | 4 | 5 | NOTE: All boolean properties below are read using link:https://javadoc.io/static/net.openhft/chronicle-core/2.23ea13/net/openhft/chronicle/core/Jvm.html#getBoolean-java.lang.String-[net.openhft.chronicle.core.Jvm.getBoolean(java.lang.String)], and so are enabled if either `-Dflag` or `-Dflag=true` or `-Dflag=yes` 6 | 7 | .System properties 8 | [cols=4*, options="header"] 9 | |=== 10 | | Property Key | Default | Description | Java Variable Name (Type) 11 | | chronicle.network.callOnMissedHeartbeatOnDisconnect |`false` | If enabled, calls onMissedHeartbeat when the connection is abruptly dropped | _CALL_MISSED_HEARTBEAT_ON_DISCONNECT_ (boolean) 12 | | client.timeout | 500 | The overall timeout; number of milliseconds after which a client is timed out if they cannot connect to a server | _pausePeriodMs_ (int) 13 | | connectionStrategy.pauseMillisBeforeReconnect | 500 | Allows control of a backoff strategy, and returns how long in milliseconds to pause before attempting reconnect | pauseMillisBeforeReconnect (long) 14 | | connectionStrategy.pause.max.secs | 5 | Controls the maximum time the ConnectionStrategy.connect method is paused for | _maxPauseSec_ (long) 15 | | connectionStrategy.pause.min.secs | 5 | Controls the minimum time the ConnectionStrategy.connect method is paused for | _minPauseSec_ (long) 16 | | connectionStrategy.socketConnectionTimeoutMs | 1 | Amount of time waiting for a socket to open i.e. if the strategy is to retry every x seconds, each individual attempt will timeout after `connectionStrategy.socketConnectionTimeoutMS` and it will stop retrying after `client.timeout` | socketConnectionTimeoutMs (int) 17 | | disable.tcp.nodelay | `false` | This disables link:https://en.wikipedia.org/wiki/Nagle%27s_algorithm[Nagle's algorithm] for connections. When true, the connection will optimise for low packet latency at the cost of overall traffic | _DISABLE_TCP_NODELAY_ (boolean) 18 | | tcp.client.buffer.size | 4 MiB | Sets the value for `SO_RCVBUF` | _tcpBufferSize_ (int) 19 | | TcpEventHandler.targetWriteSize | 1024 | Determines the size of what is trying to be written to the ByteBuffer to check if ByteBuffer has capacity | _TARGET_WRITE_SIZE_ (int) 20 | | tcp.event.monitor.secs | 10 | Sets how often the network stats listener will be notified of the network statistics, and the window over which they are measured. | _MONITOR_POLL_EVERY_SEC_ (int) 21 | | tcp.failover.time | 2_000 MS | Amount of time before the TCP session timeout is triggered | _failoverTimeout_ (long) 22 | | tcp.nbr.warning.nanos | 20_000_000L | Threshold before warning is triggered that non-blocking socket is being read to | _NBR_WARNING_NANOS_ (long) 23 | | tcp.nbw.warning.nanos | 20_000_000L | Threshold before warning is triggered that non-blocking socket is being written to | _NBW_WARNING_NANOS_ (long) --------------------------------------------------------------------------------