diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml index 948008af5..89e63fc76 100644 --- a/.github/workflows/actions.yml +++ b/.github/workflows/actions.yml @@ -362,7 +362,7 @@ jobs: echo '${{ toJSON(runner) }}' sw_vers - name: Get Dependencies - run: brew install --formulae cmake gettext libdeflate libevent libpsl miniupnpc ninja node pkgconf + run: brew install --formulae cmake gettext libdeflate libevent libpsl miniupnpc ninja node pkgconf crc32c - name: Get Dependencies (GTK) if: ${{ needs.what-to-make.outputs.make-gtk == 'true' }} run: brew install --formula gtkmm3 @@ -393,7 +393,8 @@ jobs: -DENABLE_UTILS=${{ (needs.what-to-make.outputs.make-utils == 'true') && 'ON' || 'OFF' }} \ -DREBUILD_WEB=${{ (needs.what-to-make.outputs.make-web == 'true') && 'ON' || 'OFF' }} \ -DENABLE_WERROR=ON \ - -DRUN_CLANG_TIDY=OFF + -DRUN_CLANG_TIDY=OFF \ + -DUSE_SYSTEM_Crc32c=ON - name: Make run: cmake --build obj --config RelWithDebInfo - name: Test @@ -420,7 +421,7 @@ jobs: echo '${{ toJSON(runner) }}' sw_vers - name: Get Dependencies - run: brew install --formulae cmake gettext libdeflate libevent libpsl miniupnpc ninja node pkgconf + run: brew install --formulae cmake gettext libdeflate libevent libpsl miniupnpc ninja node pkgconf crc32c - name: Get Source uses: actions/checkout@v4 with: @@ -445,7 +446,8 @@ jobs: -DENABLE_QT=OFF \ -DENABLE_TESTS=OFF \ -DENABLE_WERROR=ON \ - -DRUN_CLANG_TIDY=OFF + -DRUN_CLANG_TIDY=OFF \ + -DUSE_SYSTEM_CRC32C=ON - name: Make run: cmake --build obj --config RelWithDebInfo @@ -468,6 +470,7 @@ jobs: apk add \ ca-certificates \ cmake \ + crc32c-dev \ curl-dev \ fmt-dev \ g++ \ @@ -509,7 +512,8 @@ jobs: -DENABLE_UTILS=${{ (needs.what-to-make.outputs.make-utils == 'true') && 'ON' || 'OFF' }} \ -DREBUILD_WEB=${{ (needs.what-to-make.outputs.make-web == 'true') && 'ON' || 'OFF' }} \ -DENABLE_WERROR=ON \ - -DRUN_CLANG_TIDY=OFF + -DRUN_CLANG_TIDY=OFF \ + -DUSE_SYSTEM_CRC32C=ON - name: Make run: cmake --build obj --config RelWithDebInfo - name: Test @@ -864,6 +868,7 @@ jobs: fmt-devel \ gcc-c++ \ gettext \ + google-crc32c-devel \ libcurl-devel \ libdeflate-devel \ libevent-devel \ @@ -905,7 +910,8 @@ jobs: -DREBUILD_WEB=${{ (needs.what-to-make.outputs.make-web == 'true') && 'ON' || 'OFF' }} \ -DENABLE_DEPRECATED=ON \ -DENABLE_WERROR=OFF \ - -DRUN_CLANG_TIDY=OFF + -DRUN_CLANG_TIDY=OFF \ + -DUSE_SYSTEM_Crc32c=ON - name: Build run: cmake --build obj --config RelWithDebInfo - name: Test diff --git a/.gitmodules b/.gitmodules index b94e07e68..86f89e64e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -61,3 +61,6 @@ path = third-party/rpavlik-cmake-modules # synced with https://github.com/rpavlik/cmake-modules.git url = https://github.com/transmission/rpavlik-cmake-modules.git +[submodule "third-party/crc32c"] + path = third-party/crc32c + url = https://github.com/google/crc32c.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 6fb5d1d0e..177824cd1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,6 +79,7 @@ tr_auto_option(USE_SYSTEM_NATPMP "Use system natpmp library" AUTO) tr_auto_option(USE_SYSTEM_UTP "Use system utp library" AUTO) tr_auto_option(USE_SYSTEM_B64 "Use system b64 library" AUTO) tr_auto_option(USE_SYSTEM_PSL "Use system psl library" AUTO) +tr_auto_option(USE_SYSTEM_CRC32C "Use system crc32c library" AUTO) tr_list_option(USE_GTK_VERSION "Use specific GTK version" AUTO 3 4) tr_list_option(USE_QT_VERSION "Use specific Qt version" AUTO 5 6) tr_list_option(WITH_CRYPTO "Use specified crypto library" AUTO ccrypto mbedtls openssl wolfssl) @@ -558,6 +559,14 @@ tr_add_external_auto_library(B64 libb64 b64 CMAKE_ARGS -DLIBB64_SHARED:BOOL=OFF) +tr_add_external_auto_library(CRC32C crc32c crc32c + TARGET Crc32c::crc32c + CMAKE_ARGS + -DCRC32C_BUILD_TESTS=OFF + -DCRC32C_BUILD_BENCHMARKS=OFF + -DCRC32C_USE_GLOG=OFF + -DCRC32C_INSTALL=ON) + set(TR_WEB_ASSETS ${PROJECT_SOURCE_DIR}/web/public_html) if(REBUILD_WEB) tr_get_required_flag(REBUILD_WEB NPM_IS_REQUIRED) diff --git a/Transmission.xcodeproj/project.pbxproj b/Transmission.xcodeproj/project.pbxproj index 5fdf6397d..acae3fac9 100644 --- a/Transmission.xcodeproj/project.pbxproj +++ b/Transmission.xcodeproj/project.pbxproj @@ -453,6 +453,20 @@ ED86936F2ADAE34D00342B1A /* DefaultAppHelper.mm in Sources */ = {isa = PBXBuildFile; fileRef = ED86936E2ADAE34D00342B1A /* DefaultAppHelper.mm */; }; ED8A16412735A8AA000D61F9 /* peer-mgr-wishlist.h in Headers */ = {isa = PBXBuildFile; fileRef = ED8A163D2735A8AA000D61F9 /* peer-mgr-wishlist.h */; }; ED8A16422735A8AA000D61F9 /* peer-mgr-wishlist.cc in Sources */ = {isa = PBXBuildFile; fileRef = ED8A163E2735A8AA000D61F9 /* peer-mgr-wishlist.cc */; }; + ED91F28B2CBDA72C008388AA /* crc32c.cc in Sources */ = {isa = PBXBuildFile; fileRef = ED91F01E2CBDA72C008388AA /* crc32c.cc */; }; + ED91F2B52CBDA72C008388AA /* crc32c_sse42.cc in Sources */ = {isa = PBXBuildFile; fileRef = ED91F0312CBDA72C008388AA /* crc32c_sse42.cc */; settings = {COMPILER_FLAGS = "-msse4.2"; }; }; + ED91F2F52CBDA72C008388AA /* crc32c_arm64.cc in Sources */ = {isa = PBXBuildFile; fileRef = ED91F0202CBDA72C008388AA /* crc32c_arm64.cc */; }; + ED91F3152CBDA72C008388AA /* crc32c_portable.cc in Sources */ = {isa = PBXBuildFile; fileRef = ED91F0282CBDA72C008388AA /* crc32c_portable.cc */; }; + ED91F33A2CBDA72C008388AA /* crc32c_arm64.h in Headers */ = {isa = PBXBuildFile; fileRef = ED91F01F2CBDA72C008388AA /* crc32c_arm64.h */; }; + ED91F3432CBDA72C008388AA /* crc32c_prefetch.h in Headers */ = {isa = PBXBuildFile; fileRef = ED91F02A2CBDA72C008388AA /* crc32c_prefetch.h */; }; + ED91F34B2CBDA72C008388AA /* crc32c_sse42_check.h in Headers */ = {isa = PBXBuildFile; fileRef = ED91F0322CBDA72C008388AA /* crc32c_sse42_check.h */; }; + ED91F3502CBDA72C008388AA /* crc32c_round_up.h in Headers */ = {isa = PBXBuildFile; fileRef = ED91F02E2CBDA72C008388AA /* crc32c_round_up.h */; }; + ED91F3542CBDA72C008388AA /* crc32c_sse42.h in Headers */ = {isa = PBXBuildFile; fileRef = ED91F0302CBDA72C008388AA /* crc32c_sse42.h */; }; + ED91F35A2CBDA72C008388AA /* crc32c.h in Headers */ = {isa = PBXBuildFile; fileRef = ED91F01B2CBDA72C008388AA /* crc32c.h */; settings = {ATTRIBUTES = (Public, ); }; }; + ED91F35D2CBDA72C008388AA /* crc32c_read_le.h in Headers */ = {isa = PBXBuildFile; fileRef = ED91F02C2CBDA72C008388AA /* crc32c_read_le.h */; }; + ED91F3602CBDA72C008388AA /* crc32c_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = ED91F0272CBDA72C008388AA /* crc32c_internal.h */; }; + ED91F3612CBDA72C008388AA /* crc32c_arm64_check.h in Headers */ = {isa = PBXBuildFile; fileRef = ED91F0212CBDA72C008388AA /* crc32c_arm64_check.h */; }; + ED91F3962CBDAAED008388AA /* libcrc32c.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ED91F00C2CBDA5D3008388AA /* libcrc32c.a */; }; ED9862972B979AA2002F3035 /* Utils.mm in Sources */ = {isa = PBXBuildFile; fileRef = ED9862962B979AA2002F3035 /* Utils.mm */; }; EDBA61FF2D4180D5001470F8 /* torrent-queue.h in Headers */ = {isa = PBXBuildFile; fileRef = EDBA61FD2D4180D5001470F8 /* torrent-queue.h */; }; EDBA62002D4180D5001470F8 /* torrent-queue.cc in Sources */ = {isa = PBXBuildFile; fileRef = EDBA61FE2D4180D5001470F8 /* torrent-queue.cc */; }; @@ -590,6 +604,13 @@ remoteGlobalIDString = 4D18389609DEC0030047D688; remoteInfo = libtransmission; }; + ED91F3942CBDA9BD008388AA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; + proxyType = 1; + remoteGlobalIDString = ED91F00B2CBDA5D3008388AA; + remoteInfo = crc32c; + }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -1372,6 +1393,20 @@ ED86936E2ADAE34D00342B1A /* DefaultAppHelper.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DefaultAppHelper.mm; sourceTree = ""; }; ED8A163D2735A8AA000D61F9 /* peer-mgr-wishlist.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = "peer-mgr-wishlist.h"; sourceTree = ""; }; ED8A163E2735A8AA000D61F9 /* peer-mgr-wishlist.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "peer-mgr-wishlist.cc"; sourceTree = ""; }; + ED91F00C2CBDA5D3008388AA /* libcrc32c.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libcrc32c.a; sourceTree = BUILT_PRODUCTS_DIR; }; + ED91F01B2CBDA72C008388AA /* crc32c.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = crc32c.h; sourceTree = ""; }; + ED91F01E2CBDA72C008388AA /* crc32c.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = crc32c.cc; sourceTree = ""; }; + ED91F01F2CBDA72C008388AA /* crc32c_arm64.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = crc32c_arm64.h; sourceTree = ""; }; + ED91F0202CBDA72C008388AA /* crc32c_arm64.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = crc32c_arm64.cc; sourceTree = ""; }; + ED91F0212CBDA72C008388AA /* crc32c_arm64_check.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = crc32c_arm64_check.h; sourceTree = ""; }; + ED91F0272CBDA72C008388AA /* crc32c_internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = crc32c_internal.h; sourceTree = ""; }; + ED91F0282CBDA72C008388AA /* crc32c_portable.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = crc32c_portable.cc; sourceTree = ""; }; + ED91F02A2CBDA72C008388AA /* crc32c_prefetch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = crc32c_prefetch.h; sourceTree = ""; }; + ED91F02C2CBDA72C008388AA /* crc32c_read_le.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = crc32c_read_le.h; sourceTree = ""; }; + ED91F02E2CBDA72C008388AA /* crc32c_round_up.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = crc32c_round_up.h; sourceTree = ""; }; + ED91F0302CBDA72C008388AA /* crc32c_sse42.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = crc32c_sse42.h; sourceTree = ""; }; + ED91F0312CBDA72C008388AA /* crc32c_sse42.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = crc32c_sse42.cc; sourceTree = ""; }; + ED91F0322CBDA72C008388AA /* crc32c_sse42_check.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = crc32c_sse42_check.h; sourceTree = ""; }; ED9862952B979AA2002F3035 /* Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Utils.h; sourceTree = ""; }; ED9862962B979AA2002F3035 /* Utils.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Utils.mm; sourceTree = ""; }; EDBA61FD2D4180D5001470F8 /* torrent-queue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "torrent-queue.h"; sourceTree = ""; }; @@ -1466,6 +1501,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + ED91F3962CBDAAED008388AA /* libcrc32c.a in Frameworks */, C1846BA9294F7B5A00A98F30 /* libwildmat.a in Frameworks */, C3D9062F27B7F7E200EF2386 /* libpsl.a in Frameworks */, C3CEBBFC2794A12200683BE0 /* libdeflate.a in Frameworks */, @@ -1566,6 +1602,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + ED91F00A2CBDA5D3008388AA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -1704,6 +1747,7 @@ C3CEBBA927949CA000683BE0 /* libdeflate.a */, C3D9062127B7E3C900EF2386 /* libpsl.a */, C1846B9E294F7A3400A98F30 /* libwildmat.a */, + ED91F00C2CBDA5D3008388AA /* libcrc32c.a */, ); name = Products; sourceTree = ""; @@ -1727,6 +1771,7 @@ C3D9061627B7E12F00EF2386 /* libpsl */, C1639A751A55F52800E42033 /* b64 */, C1846B82294F777000A98F30 /* wildmat */, + ED91F2682CBDA72C008388AA /* crc32c */, 4DDBB71509E16B3F00284745 /* Libraries */, A2F35BBA15C5A0A100EBF632 /* Frameworks */, 19C28FACFE9D520D11CA2CBB /* Products */, @@ -2368,6 +2413,51 @@ name = "Overlay Window"; sourceTree = ""; }; + ED91F01C2CBDA72C008388AA /* crc32c */ = { + isa = PBXGroup; + children = ( + ED91F01B2CBDA72C008388AA /* crc32c.h */, + ); + path = crc32c; + sourceTree = ""; + }; + ED91F01D2CBDA72C008388AA /* include */ = { + isa = PBXGroup; + children = ( + ED91F01C2CBDA72C008388AA /* crc32c */, + ); + path = include; + sourceTree = ""; + }; + ED91F0362CBDA72C008388AA /* src */ = { + isa = PBXGroup; + children = ( + ED91F01E2CBDA72C008388AA /* crc32c.cc */, + ED91F01F2CBDA72C008388AA /* crc32c_arm64.h */, + ED91F0202CBDA72C008388AA /* crc32c_arm64.cc */, + ED91F0212CBDA72C008388AA /* crc32c_arm64_check.h */, + ED91F0272CBDA72C008388AA /* crc32c_internal.h */, + ED91F0282CBDA72C008388AA /* crc32c_portable.cc */, + ED91F02A2CBDA72C008388AA /* crc32c_prefetch.h */, + ED91F02C2CBDA72C008388AA /* crc32c_read_le.h */, + ED91F02E2CBDA72C008388AA /* crc32c_round_up.h */, + ED91F0302CBDA72C008388AA /* crc32c_sse42.h */, + ED91F0312CBDA72C008388AA /* crc32c_sse42.cc */, + ED91F0322CBDA72C008388AA /* crc32c_sse42_check.h */, + ); + path = src; + sourceTree = ""; + }; + ED91F2682CBDA72C008388AA /* crc32c */ = { + isa = PBXGroup; + children = ( + ED91F01D2CBDA72C008388AA /* include */, + ED91F0362CBDA72C008388AA /* src */, + ); + name = crc32c; + path = "third-party/crc32c"; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -2573,6 +2663,22 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + ED91F0082CBDA5D3008388AA /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ED91F35A2CBDA72C008388AA /* crc32c.h in Headers */, + ED91F33A2CBDA72C008388AA /* crc32c_arm64.h in Headers */, + ED91F3612CBDA72C008388AA /* crc32c_arm64_check.h in Headers */, + ED91F34B2CBDA72C008388AA /* crc32c_sse42_check.h in Headers */, + ED91F3542CBDA72C008388AA /* crc32c_sse42.h in Headers */, + ED91F3432CBDA72C008388AA /* crc32c_prefetch.h in Headers */, + ED91F3502CBDA72C008388AA /* crc32c_round_up.h in Headers */, + ED91F35D2CBDA72C008388AA /* crc32c_read_le.h in Headers */, + ED91F3602CBDA72C008388AA /* crc32c_internal.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ @@ -2605,6 +2711,7 @@ buildRules = ( ); dependencies = ( + ED91F3952CBDA9BD008388AA /* PBXTargetDependency */, C1846BA7294F7B1400A98F30 /* PBXTargetDependency */, C33E46A22794B3CC0090F2AA /* PBXTargetDependency */, A226FDB10D0CDF6E005A7F71 /* PBXTargetDependency */, @@ -2903,6 +3010,26 @@ productReference = C8B27BA128153F3400A22B5D /* transmission-show */; productType = "com.apple.product-type.tool"; }; + ED91F00B2CBDA5D3008388AA /* crc32c */ = { + isa = PBXNativeTarget; + buildConfigurationList = ED91F0172CBDA5D3008388AA /* Build configuration list for PBXNativeTarget "crc32c" */; + buildPhases = ( + ED91F3982CBDAB95008388AA /* Copy libcrc32c headers */, + ED91F0082CBDA5D3008388AA /* Headers */, + ED91F0092CBDA5D3008388AA /* Sources */, + ED91F00A2CBDA5D3008388AA /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = crc32c; + packageProductDependencies = ( + ); + productName = crc32c; + productReference = ED91F00C2CBDA5D3008388AA /* libcrc32c.a */; + productType = "com.apple.product-type.library.static"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -2926,6 +3053,9 @@ C3D9062027B7E3C900EF2386 = { CreatedOnToolsVersion = 13.0; }; + ED91F00B2CBDA5D3008388AA = { + CreatedOnToolsVersion = 16.0; + }; }; }; buildConfigurationList = 4DF0C59A089918A300DD8943 /* Build configuration list for PBXProject "Transmission" */; @@ -2977,6 +3107,7 @@ C3CEBB9F27949CA000683BE0 /* deflate */, C3D9062027B7E3C900EF2386 /* psl */, C1846B96294F7A3400A98F30 /* wildmat */, + ED91F00B2CBDA5D3008388AA /* crc32c */, ); }; /* End PBXProject section */ @@ -3140,6 +3271,25 @@ shellPath = /bin/sh; shellScript = "sed 's|@LIBPSL_[A-Z_]*@|0|' < third-party/libpsl/include/libpsl.h.in > third-party/libpsl/include/libpsl.h\n\n# Generate files to be included\nPYTHON=$( command -v python3 ) || PYTHON=$( command -v python3.7 ) || PYTHON=$( command -v python2 )\n\"${PYTHON}\" \"third-party/libpsl/src/psl-make-dafsa\" --output-format=cxx+ \"third-party/libpsl/list/public_suffix_list.dat\" \"third-party/suffixes_dafsa.h\"\n"; }; + ED91F3982CBDAB95008388AA /* Copy libcrc32c headers */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "$(SRCROOT)/third_party/macosx-crc32c-config.h", + ); + name = "Copy libcrc32c headers"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/bash; + shellScript = "cd third-party/crc32c/include/crc32c\n\nif [ ! -e crc32c_config.h -a ! ../../../macosx-crc32c-config.h -ef crc32c_config.h ]; then\n ln -s ../../../macosx-crc32c-config.h crc32c_config.h;\nfi\n\n"; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -3497,6 +3647,17 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + ED91F0092CBDA5D3008388AA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ED91F28B2CBDA72C008388AA /* crc32c.cc in Sources */, + ED91F2B52CBDA72C008388AA /* crc32c_sse42.cc in Sources */, + ED91F2F52CBDA72C008388AA /* crc32c_arm64.cc in Sources */, + ED91F3152CBDA72C008388AA /* crc32c_portable.cc in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -3590,6 +3751,11 @@ target = 4D18389609DEC0030047D688 /* libtransmission */; targetProxy = C8B27B9428153F3400A22B5D /* PBXContainerItemProxy */; }; + ED91F3952CBDA9BD008388AA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = ED91F00B2CBDA5D3008388AA /* crc32c */; + targetProxy = ED91F3942CBDA9BD008388AA /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ @@ -5133,6 +5299,36 @@ }; name = Release; }; + ED91F0142CBDA5D3008388AA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GENERATE_MASTER_OBJECT_FILE = YES; + HEADER_SEARCH_PATHS = "third-party/crc32c/include"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + ED91F0152CBDA5D3008388AA /* Release - Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GENERATE_MASTER_OBJECT_FILE = YES; + HEADER_SEARCH_PATHS = "third-party/crc32c/include"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = "Release - Debug"; + }; + ED91F0162CBDA5D3008388AA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GENERATE_MASTER_OBJECT_FILE = YES; + HEADER_SEARCH_PATHS = "third-party/crc32c/include"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -5326,6 +5522,16 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; + ED91F0172CBDA5D3008388AA /* Build configuration list for PBXNativeTarget "crc32c" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + ED91F0142CBDA5D3008388AA /* Debug */, + ED91F0152CBDA5D3008388AA /* Release - Debug */, + ED91F0162CBDA5D3008388AA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; /* End XCConfigurationList section */ }; rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; diff --git a/cmake/FindCRC32C.cmake b/cmake/FindCRC32C.cmake new file mode 100644 index 000000000..7dbe24d22 --- /dev/null +++ b/cmake/FindCRC32C.cmake @@ -0,0 +1,30 @@ +if(CRC32C_PREFER_STATIC_LIB) + set(CRC32C_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) + if(WIN32) + set(CMAKE_FIND_LIBRARY_SUFFIXES .a .lib ${CMAKE_FIND_LIBRARY_SUFFIXES}) + else() + set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) + endif() +endif() + +find_path(CRC32C_INCLUDE_DIR + NAMES crc32c/crc32c.h) +find_library(CRC32C_LIBRARY + NAMES crc32c) + +set(CRC32C_INCLUDE_DIRS ${CRC32C_INCLUDE_DIR}) +set(CRC32C_LIBRARIES ${CRC32C_LIBRARY}) + +include(FindPackageHandleStandardArgs) + +find_package_handle_standard_args(CRC32C + REQUIRED_VARS + CRC32C_INCLUDE_DIR + CRC32C_LIBRARY) + +mark_as_advanced(CRC32C_INCLUDE_DIR CRC32C_LIBRARY) + +if(CRC32C_PREFER_STATIC_LIB) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${CRC32C_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) + unset(CRC32C_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES) +endif() diff --git a/libtransmission/CMakeLists.txt b/libtransmission/CMakeLists.txt index bfe849948..500dd3cfd 100644 --- a/libtransmission/CMakeLists.txt +++ b/libtransmission/CMakeLists.txt @@ -285,6 +285,7 @@ target_link_libraries(${TR_NAME} utf8::cpp wildmat WideInteger::WideInteger + Crc32c::crc32c $<$:crypt32> $<$:shlwapi> "$<$:-framework Foundation>" diff --git a/libtransmission/crypto-utils.cc b/libtransmission/crypto-utils.cc index 4503706e6..b2e57aa43 100644 --- a/libtransmission/crypto-utils.cc +++ b/libtransmission/crypto-utils.cc @@ -21,6 +21,8 @@ extern "C" #include } +#include + #include #include "libtransmission/crypto-utils.h" @@ -239,6 +241,11 @@ std::optional tr_sha256_from_string(std::string_view hex) return digest; } +uint32_t tr_crc32c(uint8_t const* data, size_t count) +{ + return crc32c::Crc32c(data, count); +} + // fallback implementation in case the system crypto library's RNG fails void tr_rand_buffer_std(void* buffer, size_t length) { diff --git a/libtransmission/crypto-utils.h b/libtransmission/crypto-utils.h index 713624246..da9898371 100644 --- a/libtransmission/crypto-utils.h +++ b/libtransmission/crypto-utils.h @@ -194,6 +194,11 @@ using tr_sha256_string = tr_strbuf; */ [[nodiscard]] std::optional tr_sha256_from_string(std::string_view hex); +/** + * @brief Calculate CRC32-C checksum for a buffer. + */ +[[nodiscard]] uint32_t tr_crc32c(uint8_t const* data, size_t count); + // Convenience utility to efficiently get many random small values. // Use this instead of making a lot of calls to tr_rand_int(). template diff --git a/libtransmission/peer-mgr.cc b/libtransmission/peer-mgr.cc index cad1c0b6a..7c3f11adf 100644 --- a/libtransmission/peer-mgr.cc +++ b/libtransmission/peer-mgr.cc @@ -256,6 +256,64 @@ void tr_peer_info::merge(tr_peer_info& that) noexcept } } +void tr_peer_info::update_canonical_priority() +{ + auto const type = client_external_address_.type; + + // https://www.bittorrent.org/beps/bep_0040.html + // If the IP addresses are the same, the port numbers (16-bit integers) should be used instead: + // priority = crc32-c(sort(client_port, peer_port)) + // N.B. Although not specified in BEP-40, in libtorrent's implementation, the port numbers are + // in network byte order when calculating the crc32-c result. + if (client_external_address_ == listen_address()) + { + auto buf = std::array{ get_client_advertised_port_().host(), listen_port().host() }; + static_assert(std::is_same_v, uint16_t>); + std::sort(std::begin(buf), std::end(buf)); + std::transform(std::begin(buf), std::end(buf), std::begin(buf), [](uint16_t p) { return htons(p); }); + canonical_priority_ = tr_crc32c(reinterpret_cast(std::data(buf)), std::size(buf) * sizeof(uint16_t)); + return; + } + + // https://www.bittorrent.org/beps/bep_0040.html + // The formula to be used in prioritizing peers is this: + // priority = crc32-c(sort(masked_client_ip, masked_peer_ip)) + // N.B. Although not specified in BEP-40, in libtorrent's implementation, + // smaller IP addresses go first. + auto const address_size = tr_address::CompactAddrBytes[type]; + auto addresses = std::array{ client_external_address_, listen_address() }; + std::sort(std::begin(addresses), std::end(addresses)); + + auto buf = std::array{}; + auto const first = std::begin(buf); + auto const second = addresses[0].to_compact(first); + addresses[1].to_compact(second); + TR_ASSERT(second - first == address_size); + + // https://www.bittorrent.org/beps/bep_0040.html + // For an IPv4 address, the mask to be used should be FF.FF.55.55 + // unless the IP addresses are in the same /16. In that case, the + // mask to be used should be FF.FF.FF.55. If the IP addresses are + // in the same /24, the entire address should be used (mask FF.FF.FF.FF). + // + // For an IPv6 address, the mask should be derived in the same way, + // beginning with FFFF:FFFF:FFFF:5555:5555:5555:5555:5555. If the + // IP addresses are in the same /48, the mask to be used should be + // FFFF:FFFF:FFFF:FF55:5555:5555:5555:5555. If the IP addresses are + // in the same /56, the mask to be used should be + // FFFF:FFFF:FFFF:FFFF:5555:5555:5555:5555, etc... + static auto constexpr MaskStartBaseOffset = std::array{ 2U, 6U }; + auto const base_idx = MaskStartBaseOffset[type]; + auto const mismatch_idx = std::mismatch(first, second, second).first - first; + for (auto i = mismatch_idx >= base_idx ? mismatch_idx + 1 : base_idx; i < address_size; ++i) + { + first[i] &= std::byte{ 0x55 }; + second[i] &= std::byte{ 0x55 }; + } + + canonical_priority_ = tr_crc32c(reinterpret_cast(std::data(buf)), address_size * 2U); +} + #define tr_logAddDebugSwarm(swarm, msg) tr_logAddDebugTor((swarm)->tor, msg) #define tr_logAddTraceSwarm(swarm, msg) tr_logAddTraceTor((swarm)->tor, msg) @@ -272,6 +330,12 @@ constexpr struct return -val; } + // According to libtorrent, larger values has higher priority. Not specified in BEP-40. + if (auto const val = tr_compare_3way(a.get_canonical_priority(), b.get_canonical_priority()); val != 0) + { + return -val; + } + if (auto const val = tr_compare_3way(a.from_best(), b.from_best()); val != 0) { return val; @@ -482,7 +546,14 @@ public: else { peer_info = connectable_pool - .try_emplace(socket_address, std::make_shared(socket_address, flags, from)) + .try_emplace( + socket_address, + std::make_shared( + socket_address, + flags, + from, + tor->session->global_address(socket_address.address().type).value_or(tr_address{}), + get_client_advertised_port)) .first->second; ++stats.known_peer_from_count[from]; } @@ -624,6 +695,11 @@ public: tr_peerMsgs* optimistic = nullptr; /* the optimistic peer, or nullptr if none */ + std::function const get_client_advertised_port = [this] + { + return tor->session->advertisedPeerPort(); + }; + private: void rebuild_webseeds() { @@ -1327,7 +1403,11 @@ void create_bit_torrent_peer( if (result.io->is_incoming()) { - info = std::make_shared(socket_address.address(), 0U, TR_PEER_FROM_INCOMING); + info = std::make_shared( + socket_address.address(), + 0U, + TR_PEER_FROM_INCOMING, + swarm->get_client_advertised_port); } if (!info) diff --git a/libtransmission/peer-mgr.h b/libtransmission/peer-mgr.h index 319d8fa0a..9bf19f5b0 100644 --- a/libtransmission/peer-mgr.h +++ b/libtransmission/peer-mgr.h @@ -61,20 +61,29 @@ enum : uint8_t class tr_peer_info { public: - tr_peer_info(tr_socket_address socket_address, uint8_t pex_flags, tr_peer_from from) + tr_peer_info( + tr_socket_address socket_address, + uint8_t pex_flags, + tr_peer_from from, + tr_address client_external_address, + std::function get_client_advertised_port) : listen_socket_address_{ socket_address } + , client_external_address_{ std::move(client_external_address) } , from_first_{ from } , from_best_{ from } + , get_client_advertised_port_{ std::move(get_client_advertised_port) } { TR_ASSERT(!std::empty(socket_address.port())); ++n_known_connectable; set_pex_flags(pex_flags); + update_canonical_priority(); } - tr_peer_info(tr_address address, uint8_t pex_flags, tr_peer_from from) + tr_peer_info(tr_address address, uint8_t pex_flags, tr_peer_from from, std::function get_client_advertised_port) : listen_socket_address_{ address, tr_port{} } , from_first_{ from } , from_best_{ from } + , get_client_advertised_port_{ std::move(get_client_advertised_port) } { set_pex_flags(pex_flags); } @@ -117,14 +126,15 @@ public: void set_listen_port(tr_port port_in) noexcept { - if (!std::empty(port_in)) + if (auto& port = listen_socket_address_.port_; !std::empty(port_in) && port_in != port) { - auto& port = listen_socket_address_.port_; - if (std::empty(port)) // increment known connectable peers if we did not know the listening port of this peer before + if (std::empty(port)) { + // increment known connectable peers if we did not know the listening port of this peer before ++n_known_connectable; } port = port_in; + update_canonical_priority(); } } @@ -474,6 +484,30 @@ public: // --- + void maybe_update_canonical_priority(tr_address client_external_address) + { + if (!client_external_address.is_valid() || client_external_address.type != listen_address().type) + { + return; + } + + if (client_external_address == client_external_address_) + { + return; + } + + client_external_address_ = client_external_address; + + update_canonical_priority(); + } + + [[nodiscard]] constexpr auto get_canonical_priority() const noexcept + { + return canonical_priority_; + } + + // --- + // merge two peer info objects that supposedly describes the same peer void merge(tr_peer_info& that) noexcept; @@ -517,6 +551,8 @@ private: } } + void update_canonical_priority(); + // the minimum we'll wait before attempting to reconnect to a peer static auto constexpr MinimumReconnectIntervalSecs = time_t{ 5U }; static auto constexpr InactiveThresSecs = time_t{ 60 * 60 }; @@ -525,6 +561,7 @@ private: // if the port is 0, it SHOULD mean we don't know this peer's listen socket address tr_socket_address listen_socket_address_; + tr_address client_external_address_; time_t connection_attempted_at_ = {}; time_t connection_changed_at_ = {}; @@ -542,12 +579,17 @@ private: uint8_t num_consecutive_fruitless_ = {}; uint8_t pex_flags_ = {}; + // https://www.bittorrent.org/beps/bep_0040.html + uint32_t canonical_priority_ = {}; + bool is_banned_ = false; bool is_connected_ = false; bool is_seed_ = false; bool is_upload_only_ = false; std::unique_ptr outgoing_handshake_; + + std::function const get_client_advertised_port_; }; struct tr_pex diff --git a/libtransmission/peer-msgs.cc b/libtransmission/peer-msgs.cc index a29e03d59..7213cbbd4 100644 --- a/libtransmission/peer-msgs.cc +++ b/libtransmission/peer-msgs.cc @@ -1307,6 +1307,27 @@ void tr_peerMsgsImpl::parse_ltep_handshake(MessageReader& payload) set_user_agent(tr_interned_string{ tr_strv_convert_utf8(sv) }); } + // https://www.bittorrent.org/beps/bep_0010.html + // A string containing the compact representation of the ip address + // this peer sees you as. i.e. this is the receiver's external ip + // address (no port is included). This may be either an IPv4 (4 bytes) + // or an IPv6 (16 bytes) address. + if (auto sv = std::string_view{}; tr_variantDictFindStrView(&*var, TR_KEY_yourip, &sv)) + { + auto const* const bytes = reinterpret_cast(std::data(sv)); + switch (std::size(sv)) + { + case tr_address::CompactAddrBytes[TR_AF_INET]: + peer_info->maybe_update_canonical_priority(tr_address::from_compact_ipv4(bytes).first); + break; + case tr_address::CompactAddrBytes[TR_AF_INET6]: + peer_info->maybe_update_canonical_priority(tr_address::from_compact_ipv6(bytes).first); + break; + default: + break; + } + } + /* get peer's listening port */ if (auto p = int64_t{}; tr_variantDictFindInt(&*var, TR_KEY_p, &p) && p > 0) { diff --git a/tests/libtransmission/tr-peer-info-test.cc b/tests/libtransmission/tr-peer-info-test.cc index 8041c9a55..83614a145 100644 --- a/tests/libtransmission/tr-peer-info-test.cc +++ b/tests/libtransmission/tr-peer-info-test.cc @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -16,6 +17,8 @@ #include "gtest/gtest.h" +using namespace std::literals; + using PeerInfoTest = ::testing::Test; TEST_F(PeerInfoTest, mergeConnectable) @@ -54,8 +57,8 @@ TEST_F(PeerInfoTest, mergeConnectable) { auto const& [this_connectable, this_connected, that_connectable, that_connected] = condition; - auto info_this = tr_peer_info{ tr_address{}, 0, TR_PEER_FROM_PEX }; - auto info_that = tr_peer_info{ tr_address{}, 0, TR_PEER_FROM_PEX }; + auto info_this = tr_peer_info{ tr_address{}, 0, TR_PEER_FROM_PEX, {} }; + auto info_that = tr_peer_info{ tr_address{}, 0, TR_PEER_FROM_PEX, {} }; if (this_connectable) { @@ -74,3 +77,86 @@ TEST_F(PeerInfoTest, mergeConnectable) EXPECT_EQ(info_this.is_connectable(), result); } } + +TEST_F(PeerInfoTest, updateCanonicalPriority) +{ + static auto constexpr Tests = std::array{ + // crc32-c(624C14007BD50000), default mask + std::tuple{ "123.213.32.10:51413"sv, "98.76.54.32:6881"sv, uint32_t{ 0xEC2D7224 } }, + // crc32-c(7BD520007BD52140), /16 mask + std::tuple{ "123.213.32.10:51413"sv, "123.213.33.234:6881"sv, uint32_t{ 0xF61850A9 } }, + // crc32-c(7BD5200A7BD520EA), /24 mask + std::tuple{ "123.213.32.10:51413"sv, "123.213.32.234:6881"sv, uint32_t{ 0x99568189 } }, + // crc32-c(1AE1C8D5), peer port + std::tuple{ "123.213.32.10:51413"sv, "123.213.32.10:6881"sv, uint32_t{ 0x9F852E9F } }, + // crc32-c(2A032880F177010550441004000005542A032880F27701455044100400000145), default mask + std::tuple{ "[2a03:2880:f277:1cd:face:b00c:0:167]:51413"sv, + "[2a03:2880:f177:185:face:b00c:0:25de]:6881"sv, + uint32_t{ 0xE4D0F2E2 } }, + // crc32-c(2A032880F177F14550441004000001452A032880F177F2055044100400000554), /48 mask + std::tuple{ "[2a03:2880:f177:f1cd:face:b00c:0:167]:51413"sv, + "[2a03:2880:f177:f285:face:b00c:0:25de]:6881"sv, + uint32_t{ 0xCD993D35 } }, + // crc32-c(2A032880F177018550441004000005542A032880F17701CD5044100400000145), /56 mask + std::tuple{ "[2a03:2880:f177:1cd:face:b00c:0:167]:51413"sv, + "[2a03:2880:f177:185:face:b00c:0:25de]:6881"sv, + uint32_t{ 0xF47E9889 } }, + // crc32-c(2A032880F17701CDFA441004000001452A032880F17701CDFB44100400000554), /64 mask + std::tuple{ "[2a03:2880:f177:1cd:face:b00c:0:167]:51413"sv, + "[2a03:2880:f177:1cd:fbce:b00c:0:25de]:6881"sv, + uint32_t{ 0x2BC35C30 } }, + // crc32-c(2A032880F17701CDFACE1004000001452A032880F17701CDFACF100400000554), /72 mask + std::tuple{ "[2a03:2880:f177:1cd:face:b00c:0:167]:51413"sv, + "[2a03:2880:f177:1cd:facf:b00c:0:25de]:6881"sv, + uint32_t{ 0x04BFAA11 } }, + // crc32-c(2A032880F17701CDFACEB005000005542A032880F17701CDFACEB50400000145), /80 mask + std::tuple{ "[2a03:2880:f177:1cd:face:b50c:0:167]:51413"sv, + "[2a03:2880:f177:1cd:face:b00d:0:25de]:6881"sv, + uint32_t{ 0xA0F96012 } }, + // crc32-c(2A032880F17701CDFACEB00C000001452A032880F17701CDFACEB00D00000554), /88 mask + std::tuple{ "[2a03:2880:f177:1cd:face:b00c:0:167]:51413"sv, + "[2a03:2880:f177:1cd:face:b00d:0:25de]:6881"sv, + uint32_t{ 0x47FC5342 } }, + // crc32-c(2A032880F17701CDFACEB00C005505542A032880F17701CDFACEB00CFF000145), /96 mask + std::tuple{ "[2a03:2880:f177:1cd:face:b00c:ff00:167]:51413"sv, + "[2a03:2880:f177:1cd:face:b00c:ff:25de]:6881"sv, + uint32_t{ 0x51BB5B16 } }, + // crc32-c(2A032880F17701CDFACEB00C000001452A032880F17701CDFACEB00C00010554), /104 mask + std::tuple{ "[2a03:2880:f177:1cd:face:b00c:0:167]:51413"sv, + "[2a03:2880:f177:1cd:face:b00c:1:25de]:6881"sv, + uint32_t{ 0xDAACAE90 } }, + // crc32-c(2A032880F17701CDFACEB00C000001452A032880F17701CDFACEB00C00002554), /112 mask + std::tuple{ "[2a03:2880:f177:1cd:face:b00c:0:167]:51413"sv, + "[2a03:2880:f177:1cd:face:b00c:0:25de]:6881"sv, + uint32_t{ 0x0066DFEC } }, + // crc32-c(2A032880F17701CDFACEB00C000001452A032880F17701CDFACEB00C00001654), /120 mask + std::tuple{ "[2a03:2880:f177:1cd:face:b00c:0:167]:51413"sv, + "[2a03:2880:f177:1cd:face:b00c:0:16de]:6881"sv, + uint32_t{ 0x74CF65F6 } }, + // crc32-c(1AE11AE2), peer port + std::tuple{ "[2a03:2880:f177:1cd:face:b00c:0:167]:6882"sv, + "[2a03:2880:f177:1cd:face:b00c:0:167]:6881"sv, + uint32_t{ 0x67F8FE57 } }, + }; + + for (auto [client_sockaddr_str, peer_sockaddr_str, expected] : Tests) + { + auto client_sockaddr = tr_socket_address::from_string(client_sockaddr_str); + auto peer_sockaddr = tr_socket_address::from_string(peer_sockaddr_str); + EXPECT_TRUE(client_sockaddr && peer_sockaddr) << "Test case is bugged"; + if (!client_sockaddr || !peer_sockaddr) + { + continue; + } + + auto const info = tr_peer_info{ *peer_sockaddr, + 0, + TR_PEER_FROM_PEX, + client_sockaddr->address(), + [&client_sockaddr] + { + return client_sockaddr->port(); + } }; + EXPECT_EQ(info.get_canonical_priority(), expected); + } +} diff --git a/third-party/crc32c b/third-party/crc32c new file mode 160000 index 000000000..2bbb3be42 --- /dev/null +++ b/third-party/crc32c @@ -0,0 +1 @@ +Subproject commit 2bbb3be42e20a0e6c0f7b39dc07dc863d9ffbc07 diff --git a/third-party/macosx-crc32c-config.h b/third-party/macosx-crc32c-config.h new file mode 100644 index 000000000..e607e90f3 --- /dev/null +++ b/third-party/macosx-crc32c-config.h @@ -0,0 +1,48 @@ +// Copyright 2017 The CRC32C Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef CRC32C_CRC32C_CONFIG_H_ +#define CRC32C_CRC32C_CONFIG_H_ + +// Define to 1 if building for a big-endian platform. +#undef BYTE_ORDER_BIG_ENDIAN + +// Define to 1 if the compiler has the __builtin_prefetch intrinsic. +#if __has_builtin(__builtin_prefetch) +#define HAVE_BUILTIN_PREFETCH 1 +#else +#undef HAVE_BUILTIN_PREFETCH +#endif + +// Define to 1 if targeting X86 and the compiler has the _mm_prefetch intrinsic. +#undef HAVE_MM_PREFETCH + +// Define to 1 if targeting X86 and the compiler has the _mm_crc32_u{8,32,64} +// intrinsics. +#if defined(__x86_64__) +#define HAVE_SSE42 1 +#else +#undef HAVE_SSE42 +#endif + +// Define to 1 if targeting ARM and the compiler has the __crc32c{b,h,w,d} and +// the vmull_p64 intrinsics. +#if defined(__aarch64__) +#define HAVE_ARM64_CRC32C 1 +#else +#undef HAVE_ARM64_CRC32C +#endif + +// Define to 1 if the system libraries have the getauxval function in the +// header. Should be true on Linux and Android API level 20+. +#undef HAVE_STRONG_GETAUXVAL + +// Define to 1 if the compiler supports defining getauxval as a weak symbol. +// Should be true for any compiler that supports __attribute__((weak)). +#undef HAVE_WEAK_GETAUXVAL + +// Define to 1 if CRC32C tests have been built with Google Logging. +#undef CRC32C_TESTS_BUILT_WITH_GLOG + +#endif // CRC32C_CRC32C_CONFIG_H_