Skip to content

Networking: hash RPCs by compiler-independent type name#204

Closed
Kheartz wants to merge 1 commit into
MafiaHub:developfrom
Kheartz:rpc_type_name
Closed

Networking: hash RPCs by compiler-independent type name#204
Kheartz wants to merge 1 commit into
MafiaHub:developfrom
Kheartz:rpc_type_name

Conversation

@Kheartz

@Kheartz Kheartz commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Came across this issue when attempting to chat from a client running hogwarts-mp on Windows against a Ubuntu 24.04 Linux VM.

typeid(T).name() is not portable across compilers (MSVC emits a readable decorated name, the Itanium ABI a mangled one), so an MSVC client and a GCC server computed different CRC32 hashes for the same RPC type and silently dropped each other's RPCs (chat, weather, SetTransform game RPC).

Add Utils::TypeName(), which normalizes FUNCSIG/PRETTY_FUNCTION to an identical string across MSVC/GCC/Clang, plus a per-type RPC identity cache (RPCHash/RPCName) shared by IRPC and IGameRPC. Covered by unit tests in tests/modules/type_name_ut.h.

Question: Does this require a version change?

Also verified to work with Windows client against Linux server.

GHA checks will still fail until #203 is merged.

Summary by CodeRabbit

  • Refactor

    • Refactored RPC identity resolution mechanisms to provide consistent and reliable behavior across different compiler platforms, improving system portability and stability.
  • Tests

    • Added comprehensive unit tests to verify type name resolution and RPC identity verification across multiple scenarios.

typeid(T).name() is not portable across compilers (MSVC emits a readable decorated name, the Itanium ABI a mangled one), so an MSVC client and a GCC server computed different CRC32 hashes for the same RPC type and silently dropped each other's RPCs (chat, weather, SetTransform game RPC).

Add Utils::TypeName<T>(), which normalizes __FUNCSIG__/__PRETTY_FUNCTION__ to an identical string across MSVC/GCC/Clang, plus a per-type RPC identity cache (RPCHash/RPCName) shared by IRPC and IGameRPC. Covered by unit tests in tests/modules/type_name_ut.h.
@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Introduces Framework::Utils::TypeName<T>(), a constexpr helper that extracts stable, compiler-independent fully-qualified type names from __FUNCSIG__/__PRETTY_FUNCTION__. A new rpc_identity.h wraps this into cached RPCHash<T>() and RPCName<T>() helpers. IRPC<T> and IGameRPC<T> are updated to use these helpers, removing per-instance _rpcName members and typeid(T).name() dependencies. Unit tests validate TypeName<T>() behavior.

Changes

Compiler-independent RPC Identity

Layer / File(s) Summary
TypeName<T>() utility and unit tests
code/framework/src/utils/type_name.h, code/tests/modules/type_name_ut.h, code/tests/framework_ut.cpp
Adds constexpr TypeName<T>() extracting stable type names from compiler signature macros with MSVC keyword trimming. Unit tests verify fully-qualified names, nested namespaces, prefix stripping, primitive types, repeat-call stability, and CRC32 hash distinctness.
RPCHash<T>() and RPCName<T>() identity helpers
code/framework/src/networking/rpc/rpc_identity.h
New header exposing two cached per-type inline template functions: RPCHash<T>() memoizes CRC32 of TypeName<T>(), and RPCName<T>() caches and returns the type name string.
IRPC<T> and IGameRPC<T> migration
code/framework/src/networking/rpc/rpc.h, code/framework/src/networking/rpc/game_rpc.h
Both RPC base classes include rpc_identity.h, switch _hashName init to RPCHash<T>(), remove the per-instance _rpcName member, and return RPCName<T>() from GetName(). Removes now-unused <typeinfo> and <utils/hashing.h> includes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

A rabbit hopped past typeid one day,
"Your names are unstable!" it had to say.
With __FUNCSIG__ and some careful trim,
the type names are steady on every whim.
CRC32 now hashes a trustworthy string —
cross-platform RPC, a joyful thing! 🐇✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: moving RPC identification from compiler-dependent typeid() hashing to a compiler-independent approach using normalized type names.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
code/tests/modules/type_name_ut.h (2)

25-27: ⚡ Quick win

Add a closing comment for the nested namespace.

Please close namespace Inner with an explicit comment to match the repository namespace-closing rule.

Suggested patch
     namespace Inner {
         struct Delta {};
-    }
+    } // namespace Inner

As per coding guidelines, "Use namespaces with closing comment pattern: namespace Framework::SubModule { ... } // namespace Framework::SubModule".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@code/tests/modules/type_name_ut.h` around lines 25 - 27, The nested namespace
Inner is missing a closing comment on its closing brace. Add an explicit closing
comment after the closing brace of namespace Inner to match the repository's
namespace-closing rule. The comment should follow the pattern // namespace Inner
to clearly indicate which namespace is being closed.

Source: Coding guidelines


14-15: ⚡ Quick win

Include <string> directly where std::string is used.

This test uses std::string (Lines 62-63) but relies on transitive includes. Add a direct include to keep compile dependencies explicit.

Suggested patch
 `#include` <string_view>
+#include <string>

Also applies to: 62-63

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@code/tests/modules/type_name_ut.h` around lines 14 - 15, The file uses
std::string in the test code but relies on transitive includes to provide it
rather than directly including the header. Add a direct include for <string> in
the include section near where <string_view> is included to make the compile
dependency explicit and avoid relying on transitive includes from other headers.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@code/tests/modules/type_name_ut.h`:
- Around line 25-27: The nested namespace Inner is missing a closing comment on
its closing brace. Add an explicit closing comment after the closing brace of
namespace Inner to match the repository's namespace-closing rule. The comment
should follow the pattern // namespace Inner to clearly indicate which namespace
is being closed.
- Around line 14-15: The file uses std::string in the test code but relies on
transitive includes to provide it rather than directly including the header. Add
a direct include for <string> in the include section near where <string_view> is
included to make the compile dependency explicit and avoid relying on transitive
includes from other headers.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b33b1407-1d94-413d-81c0-f503a11a9108

📥 Commits

Reviewing files that changed from the base of the PR and between 314b8bd and 6918456.

📒 Files selected for processing (6)
  • code/framework/src/networking/rpc/game_rpc.h
  • code/framework/src/networking/rpc/rpc.h
  • code/framework/src/networking/rpc/rpc_identity.h
  • code/framework/src/utils/type_name.h
  • code/tests/framework_ut.cpp
  • code/tests/modules/type_name_ut.h

@Kheartz

Kheartz commented Jun 14, 2026

Copy link
Copy Markdown
Contributor Author

This seems to be addressed by #201 . I'll hold on to the Kheartz:rpc_type_name patch for our remote server until that's merged.

@Kheartz Kheartz closed this Jun 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant