A cross-platform C++17 implementation of the Infinispan Hot Rod protocol client.
๐ Smart client - hash-aware routing, automatic failover, full CRUD + metadata ops, typed error handling and user-decided retry (keyed & keyless), and SASL/SCRAM authentication (SCRAM-SHA-1/256/512).
See the complete working example in examples/quickstart/:
cd examples/quickstart ./start-server.sh # Start Infinispan 16.2 mkdir build && cd build cmake .. && make ./quickstart # Run the example
Example output:
=== Hot Rod C++ Client Quickstart ===
Connecting to Infinispan server...
Connected successfully!
--- PUT Operations ---
PUT: greeting = Hello, Infinispan!
PUT: language = C++17
PUT: version = 1.0.0
--- GET Operations ---
GET: greeting = Hello, Infinispan!
GET: language = C++17
GET: version = 1.0.0
--- REMOVE Operations ---
REMOVE: language deleted successfully
=== Quickstart Complete ===
The quickstart demonstrates:
- Connecting to Infinispan
- PUT operations (storing key-value pairs)
- GET operations (reading values)
- REMOVE operations (deleting entries)
- Clean disconnect
A second example, retry.cpp, demonstrates the user-decided retry loop
(cache.excluding(e) on a caught HotRodClientException) for both keyed
operations and keyless ping.
See examples/quickstart/README.md for full documentation.
Build Requirements:
- C++17 compatible compiler (GCC 7+, Clang 6+, MSVC 19.20+)
- CMake 3.15+
- OpenSSL 1.1.1+ or 3.x
- Google Test (for testing)
Runtime Requirements:
- Infinispan Server 16.0+ (all integration suites run against
:latestโ currently 16.3; only the quickstart example pins 16.2) - Docker (for integration tests and quickstart example)
# Install dependencies sudo dnf install cmake gcc-c++ openssl-devel gtest-devel # Build mkdir build && cd build cmake .. make -j$(nproc) # Run tests ctest --output-on-failure
# Install dependencies sudo apt install cmake g++ libssl-dev libgtest-dev # Build mkdir build && cd build cmake .. make -j$(nproc) # Run tests ctest --output-on-failure
# Install dependencies via vcpkg vcpkg install openssl gtest # Build mkdir build cd build cmake .. -DCMAKE_TOOLCHAIN_FILE=[path-to-vcpkg]/scripts/buildsystems/vcpkg.cmake cmake --build . --config Release # Run tests ctest -C Release --output-on-failure
cd build ./unit_tests # Or via CTest ctest -R UnitTests --output-on-failure
Requires Docker to run Infinispan server:
cd build # Run all integration tests (starts server automatically) โ representative subset: ./ping_integration_tests ./get_integration_tests ./put_integration_tests ./remove_integration_tests ./topology_integration_tests # Multi-node cluster tests ./hash_aware_routing_integration_tests # Smart routing tests ./retryview_integration_tests # User-decided retry (keyed) ./pingretry_integration_tests # User-decided retry (keyless ping) # Or run all via CTest ctest --output-on-failure
Note: Integration tests use Docker Compose to manage multi-node Infinispan clusters (up to 4 nodes). Tests verify failover, rebalancing, and hash-aware routing.
๐ Live status lives in docs/STATUS.md โ start there after any break. Design rationale is in docs/DECISIONS.md.
Current Progress: Full CRUD (PING/GET/PUT/REMOVE) + SCRAM auth + topology
awareness + hash-aware routing + async multiplexing + metadata/version-based
operations (Step 10) + typed error handling and user-decided retry, keyed and
keyless (Step 11) + Hot Rod URI support (RemoteCache::fromUri, issue #9) +
multi-server seed list with startup/runtime failover (issue #12) โ all shipped.
Next: bulk operations (Step 12) or multiplexing benchmarks. See
docs/STATUS.md for live status.
Per-step milestone history (frozen at Step 9) is archived at
docs/archive/PROGRESS.md.
(Step numbers follow ../hotrod-foundry/ROADMAP.md;
docs/STATUS.md is authoritative for which steps are done โ not
any headline count.)
Test Results โ unit and integration suites all pass (integration against live
Infinispan via Docker). See docs/STATUS.md for the current
coverage breakdown and counts.
- โ Cross-platform support (Linux + Windows)
- โ Wire format primitives (vInt, vLong, strings, byte arrays)
- โ Protocol 4.0 headers (complete spec with all conditional fields)
- โ Client Intelligence 0x03 (HASH_DISTRIBUTION_AWARE)
- โ Hash-aware routing (keys route directly to primary owner)
- โ Automatic failover (primary โ backup owners โ any server)
- โ Topology awareness (cluster rebalancing, updates)
- โ Consistent hashing (MurmurHash3 x64_32, segment-based routing)
- โ Connection pooling (one connection per server)
- โ Multiplexed connections (concurrent async operations on single connection per server)
- โ
Async operations (all operations return
std::futurefor non-blocking execution) - โ PING operation (server connectivity check)
- โ GET operation (read from cache with failover)
- โ PUT operation (write to cache with lifespan/maxIdle)
- โ REMOVE operation (delete from cache)
- โ
Metadata / version-based operations (
getWithMetadata,putIfAbsent,replace,containsKey,removeWithVersion,replaceWithVersion) (Step 10) - โ
Typed error handling (
HotRodClientExceptionwith phase / server status / tried nodes) +isTransient/outcomeUncertainclassification (Step 11a) - โ
User-decided retry (
cache.excluding(e)bound view) for keyed ops and keylessping, with automatic before-send failover (Step 11b/11c) - โ
SASL/SCRAM authentication (
setAuthentication(...)) โ end-to-end for the SCRAM family (SCRAM-SHA-1/SCRAM-SHA-256/SCRAM-SHA-512), applied to every connection; seedocumentation/topics/security.adoc - โ
Hot Rod URI (
RemoteCache::fromUri("hotrod[s]://...")) โ build a client from a connection string (hosts, credentials,sasl_mechanism/client_intelligence/protocol_versionparams, and the server-auth TLS params below); timeouts and more in issue #10 - โ
Server-authenticated TLS (
setTls(...)/hotrods://, issue #18) โ wraps every connection in a TLS session (OpenSSL). PEM trust (ca_file, empty = system store), SNI, and host-name validation (default on); min TLS 1.2. URI keys:trust_store_file_name(PEM CA),sni_host_name,ssl_hostname_validation. Mutual TLS / keystore formats are deferred (issue #10) - โ Multi-server seed list (issue #12) โ all hosts in the URI become seed servers with startup and runtime failover (ops fall back to the seed list when the connected server dies or no topology is known, e.g. in BASIC mode)
- โ Integration test framework (GoogleTest + Docker + multi-node clusters)
// Connect with hash-aware routing RemoteCache cache("localhost", 11222, "my-cache"); cache.setClientIntelligence(ClientIntelligence::HASH_DISTRIBUTION_AWARE); cache.connect(); // All operations are async (return std::future) and can run concurrently // Multiple operations share a single multiplexed connection per server // CREATE/UPDATE - routes to primary owner auto putFuture = cache.put(key, value, lifespan, maxIdle); // READ - automatic failover to backup if primary fails auto getFuture = cache.get(key); // DELETE - with automatic failover auto removeFuture = cache.remove(key); // PING auto pingFuture = cache.ping(); // Wait for results when needed auto result = getFuture.get(); // blocks until complete if (result.has_value()) { ByteArray value = result.value(); } // Or fire-and-forget for max throughput for (int i = 0; i < 1000; i++) { cache.put(keys[i], values[i]); // returns immediately, executes concurrently }
// hotrod://[user:password@]host1[:port1][,host2[:port2]...][?k=v&...] // Returns a configured, not-yet-connected client (RemoteCache owns a mutex, so // it is non-movable โ unique_ptr). Call connect() yourself. auto cache = RemoteCache::fromUri( "hotrod://user:pass@node1:11222,node2:11222" "?sasl_mechanism=SCRAM-SHA-256&client_intelligence=hash_distribution_aware", "my-cache"); cache->connect(); // Supports hotrod:// and hotrods:// (TLS). All hosts become seed servers (issue // #12): connect() tries each in order, and ops fall back to the seed list when the // connected server dies or no topology is known (e.g. BASIC mode). Credentials // enable SCRAM, and sasl_mechanism/client_intelligence/protocol_version (Java // "4.0"/"4.1" form) are honoured. hotrods:// enables server-auth TLS; the // trust_store_file_name (PEM CA) / sni_host_name / ssl_hostname_validation params // map to setTls(...). Userinfo and query values are percent-decoded (RFC 3986), so // a reserved character in a password is written encoded โ e.g. a password of p@ss // is "...://admin:p%40ss@host". Timeouts, mutual TLS, and other parameters throw // for now (see issue #10). // // // TLS from a URI (private CA): // auto c = RemoteCache::fromUri("hotrods://cache:11222?trust_store_file_name=/etc/pki/ca.pem"); // // or programmatically: // RemoteCache cache("cache", 11222); // cache.setTls("/etc/pki/ca.pem"); // ca_file; empty = system trust store // cache.connect();
๐ The full, authoritative backlog lives in docs/STATUS.md โ ๐ Backlog, and the 1โ3 immediate items in โญ Next steps. This is just a summary.
- โ
Step 10 โ Metadata / version-based operations (shipped):
getWithMetadata,replaceWithVersion,removeWithVersion,putIfAbsent,replace,containsKey - โ Step 11 โ Error handling (shipped): ERROR response parsing, typed exception, user-decided retry (keyed + keyless)
- โ
Server-authenticated TLS (shipped, issue #18):
hotrods://+setTls(...) - Step 12 โ Bulk operations (next):
GET_ALL,PUT_ALL,BULK_GET - Also: multiplexing benchmarks, mutual TLS (client cert/key, issue #10)
cpp17-client/
โโโ CMakeLists.txt # Build configuration
โโโ README.md # This file
โโโ LICENSE # Apache 2.0
โโโ include/hotrod/ # Public API headers
โ โโโ Types.h # Type definitions
โ โโโ Codec.h # Wire format primitives
โ โโโ HeaderCodec.h # Protocol 4.0 headers
โ โโโ Connection.h # TCP connection
โ โโโ RemoteCache.h # High-level API (with hash-aware routing)
โ โโโ TopologyInfo.h # Cluster tracking
โ โโโ ConsistentHash.h # Smart routing
โ โโโ MurmurHash3.h # Hash function
โโโ src/ # Implementation
โ โโโ codec/ # Encoding/decoding
โ โโโ transport/ # Network I/O
โ โโโ topology/ # Cluster tracking
โ โโโ hash/ # MurmurHash3 + consistent hashing
โ โโโ operations/ # Hot Rod operations (with failover)
โโโ tests/ # Test suite
โ โโโ unit/ # unit tests (gtest)
โ โโโ integration/ # integration tests (multi-node clusters, Docker)
โโโ documentation/ # AsciiDoc user guide (index.adoc + topics/)
โโโ examples/ # Usage examples
โ โโโ quickstart/ # Simple GET/PUT/REMOVE + retry + auth examples
โโโ scripts/ # Test infrastructure
โ โโโ start_cluster.sh # Start multi-node cluster
โ โโโ add_cluster_node.sh # Add node dynamically
โ โโโ remove_cluster_node.sh # Remove node for failover tests
โโโ test-configs/ # Server configurations
โโโ docker-compose-cluster.yml # Multi-node setup
โโโ infinispan-cluster.xml # No-auth config
๐ Working on this project? Read docs/WORKFLOW.md โ the per-session workflow (how to re-orient after a break, what to update before you stop, and which protocol sources are authoritative). It's built for intermittent, solo work.
This implementation follows the hotrod-foundry incremental approach:
- Test-driven development - Test vectors โ Unit tests โ Implementation
- Java reference - Study Java implementation for each step (MANDATORY) โ it is the authoritative source for behavior and semantics (what each op does, statuses, edge cases)
- Byte-level validation - Compare with test vectors and the Kaitai wire-format schema (authoritative for byte layout); if the two disagree, stop and investigate
- Cross-platform - Linux + Windows support required
- Infrastructure-first - Steps 0-5 (foundation), then operations
See hotrod-foundry/ROADMAP.md for the complete step-by-step plan.
The authoritative source for protocol behavior and semantics โ study it first for each step (see workflow above).
- Local:
/home/rigazilla/git/infinispan/client/hotrod-client/ - Public: https://github.com/infinispan/infinispan/tree/main/client/hotrod-client
- Infinispan Project: https://infinispan.org/
- Hot Rod Foundry: ../hotrod-foundry/
- Java Client Source (authoritative for behavior/semantics): local
/home/rigazilla/git/infinispan/client/hotrod-client/ยท public https://github.com/infinispan/infinispan/tree/main/client/hotrod-client - Protocol Specification: https://infinispan.org/docs/stable/titles/hotrod_protocol/
- Wire-format schema (Kaitai, protocol 4.0/4.1): https://github.com/rigazilla/hotrod-dissector/tree/main/schemas โ an independent, machine-readable encoding of the protocol; use it to double-check byte layouts against the Java client.
Apache 2.0 (matching Infinispan project)
Start with docs/WORKFLOW.md โ the per-session workflow. In short, following the hotrod-foundry porting guidelines:
- One step at a time (complete step N before step N+1)
- Update docs/STATUS.md before you stop each session (next steps + date)
- Log design decisions in docs/DECISIONS.md as you make them
- Validate against test vectors
- Ensure cross-platform compatibility
- โ v0.1.0 (2026-06-11): Foundation complete (Steps 0-5)
- โ v0.2.0 (2026-06-12): PING operation complete (Step 6)
- โ v0.3.0 (2026-06-12): GET operation complete (Step 7)
- โ v0.4.0 (2026-06-12): PUT operation complete (Step 8)
- โ v0.5.0 (2026-06-12): REMOVE operation complete (Step 9) - Full CRUD!
- โ v0.6.0 (2026-06-17): Topology awareness (Step 4)
- โ v0.7.0 (2026-06-17): Hash-aware routing with failover - Smart Client!
- โ v0.8.0 (2026-09-20): Metadata / version-based operations (Step 10)
- โ v0.9.0 (2026-09-25): Typed error handling + user-decided retry, keyed & keyless (Step 11)
- โ
2026-10 (issue-based): Hot Rod URI
fromUri(#9) + multi-server seed list with startup/runtime failover (#12) - ๐ฏ v0.10.0 (upcoming): Bulk operations (Step 12)
Maintained by: rigazilla
Status: Active development
Current Step: Step 11 (error handling + user-decided retry, keyed & keyless)
complete; since then Hot Rod URI fromUri (#9) and multi-server seed list +
failover (#12) shipped. Next: bulk operations (Step 12). โ