CRM64Pro GDK v0.16.0 SDL3_net migration and NetworkTCP overhaul
CRM64Pro GDK v0.16.0 is now available, and the biggest change in this release is a major update to the NetworkTCP module.
At first glance this might look like a migration from SDL2_net to SDL3_net. That is certainly part of the story, but not the whole one. During the update I also reworked the login flow, the packet format, the transmission model, and the runtime diagnostics. So in practice, this is less of a backend swap and more of a modernization of the whole networking layer.
The legacy implementation served CRM64Pro well for a long time. It already had packet hashing, a sequencer, a simple password login, and a lightweight XOR protection layer. But it was also a much more direct system: socket sets, immediate sends, and a fairly simple handshake. The new version keeps the same overall client/server philosophy, but the internal model is now much more robust.
What’s new in NetworkTCP
The first major change is the move from SDL2_net to SDL3_net. The legacy code was built around socket sets and explicit polling. The new code uses SDL3_net stream sockets, async hostname resolution, async connection establishment, and a wait-based model adapted to the newer API.
The login flow was also redesigned. In the legacy implementation, the client sent its name plus a password value and the server immediately accepted or rejected the connection. In the new system, the server first sends a login challenge, the client replies with a proof derived from the password, nonce, and client name, and only then is the session accepted. If the login succeeds, both sides derive session state from the password, the server nonce, the session seed, and the client name.
The packet layer is richer now too. The legacy DataNet header was compact and straightforward. The new one carries more structured state, including a 64-bit sequence or system field, a 64-bit hash, payload size, message id, and sender index.
Protection has evolved as well. The old system already used hashing, sequencing, and full-packet XOR obfuscation. The new one keeps that legacy XOR layer, but also adds optional AES-CTR encryption for post-login user payloads. So the accurate description is not “now it is encrypted”, but rather “now it supports session-aware payload encryption”.
Transmission has changed in an important way too. The legacy code generally sent packets immediately. The new version introduces explicit outbound queues on both the client and server sides, flushes those queues from the owner thread, and applies a soft-brake when pending writes grow too much. This makes the system much better behaved under sustained throughput.
On the receive side, the old client queue was kept ordered by shifting elements around. The new client queue is ring-buffer based, with explicit head, tail, byte counters, and peak tracking. That is a much better fit for long-running traffic.
Finally, diagnostics were expanded quite a lot. The old info() report was useful but compact. The new one tracks queue sizes, queue peaks, pending writes, throughput, average packet sizes, bad headers, bad payloads, hash mismatches, sequencer mismatches, and more. In practice, that means far less guesswork when tuning or debugging the network layer.
Benchmark setup
To get a realistic picture, I ran the same benchmark on both the legacy SDL2_net implementation and the new SDL3_net implementation using release builds, authoritative mode, 4 KB packets, and a 10 second test window.
I used two scenarios:
- IntraPC – client and server running on the same machine (Ryzen 9800X3D).
- Inter-PC – client and server running on two different computers over Gigabit Ethernet (Ryzen 9800X3D and Ryzen 2400G).
These are not synthetic microbenchmarks of isolated socket calls. They are end-to-end tests of the actual CRM64Pro networking path.
Performance results
Here are the measured results.
IntraPC benchmark
| VERSION | Packet rate | Bandwidth | Latency |
|---|---|---|---|
| Legacy with SDL2_net | 43914 packets/s | 171,54 MB/s | 10 ms |
| New with SDL3_net | 56703 packets/s | 221,50 MB/s | 0 ms |
Inter-PC benchmark
| VERSION | Packet rate | Bandwidth | Latency |
|---|---|---|---|
| Legacy with SDL2_net | 19858 packets/s | 77,57 MB/s | 0 ms |
| New with SDL3_net | 26797 packets/s | 104,68 MB/s | 1 ms |
Improvement summary
| Scenario | Packet rate improvement | Bandwidth improvement |
|---|---|---|
| IntraPC | +29.1% | +29.1% |
| Inter-PC | +34.9% | +34.9% |
- The new system is faster even though it does more work. The new implementation adds a stronger login flow, richer packet metadata, queue management, pending write tracking, and optional session-based payload encryption support, yet it still outperforms the legacy code in both scenarios.
- The intraPC result shows a clear local throughput improvement. Moving from 171,54 MB/s to 221,50 MB/s is a substantial gain for the same 4 KB authoritative-mode workload.
- The inter-PC result is especially interesting. The new system reached 104,68 MB/s, which is effectively the practical limit of one of the 1 Gbit interfaces used in the test. In that scenario, the network hardware becomes the bottleneck before the new NetworkTCP implementation does.
- The buffered transmission model behaves as expected. In the SDL3_net run, pending TX peaks became quite large during the benchmark, but the final pending TX value returned to zero. That is exactly what I wanted from the queue-and-drain design.
What this means for CRM64Pro v0.16.0
For users of CRM64Pro, the main point is simple: v0.16.0 brings a much more modern NetworkTCP implementation without changing the overall philosophy of the API.
The client/server model is still familiar. Authoritative and non-authoritative modes are still there. Internal DataNet messages are still the foundation. But internally, the system is now more robust, more diagnosable, and faster.
That is exactly the kind of change I like making in CRM64Pro: keep the external model clear, but steadily improve the internal quality.