diff --git a/.gitignore b/.gitignore index 799d5d1..d13c4e9 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ /ctsTraffic/Release /ctsTraffic/x64 /ctsTraffic/ARM64 +/ctsTraffic/ctsTraffic.log /Debug /Release /x64 @@ -13,7 +14,8 @@ /MSTest/*/Debug/* /MSTest/*/Release /MSTest/*/Release/* -/MSTest/*/x64 +/MSTest/*/x64* +/MSTest/*/ARM* /ctsPerf/Debug /ctsPerf/Release /ctsPerf/x64 @@ -27,8 +29,5 @@ *.sdf *.aps /.vs -/ARM -/ctsTraffic/ctsTraffic.log /_ReSharper.Caches /packages -/MSTest/ctsIOPatternProtocolPolicyUnitTest/ARM/Release diff --git a/MSTest/ctsIOPatternProtocolPolicyUnitTest/ctsIOPatternProtocolPolicyUnitTest.vcxproj b/MSTest/ctsIOPatternProtocolPolicyUnitTest/ctsIOPatternProtocolPolicyUnitTest.vcxproj index 8979860..a546efc 100644 --- a/MSTest/ctsIOPatternProtocolPolicyUnitTest/ctsIOPatternProtocolPolicyUnitTest.vcxproj +++ b/MSTest/ctsIOPatternProtocolPolicyUnitTest/ctsIOPatternProtocolPolicyUnitTest.vcxproj @@ -181,7 +181,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -206,7 +206,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -230,7 +230,7 @@ - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -255,7 +255,7 @@ - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -278,7 +278,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -303,7 +303,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -328,7 +328,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -353,7 +353,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest diff --git a/MSTest/ctsIOPatternRateLimitPolicyUnitTest/ctsIOPatternRateLimitPolicyUnitTest.vcxproj b/MSTest/ctsIOPatternRateLimitPolicyUnitTest/ctsIOPatternRateLimitPolicyUnitTest.vcxproj index 5c85e6f..7579c76 100644 --- a/MSTest/ctsIOPatternRateLimitPolicyUnitTest/ctsIOPatternRateLimitPolicyUnitTest.vcxproj +++ b/MSTest/ctsIOPatternRateLimitPolicyUnitTest/ctsIOPatternRateLimitPolicyUnitTest.vcxproj @@ -181,7 +181,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -206,7 +206,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -230,7 +230,7 @@ - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -255,7 +255,7 @@ - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -278,7 +278,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -303,7 +303,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -328,7 +328,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -353,7 +353,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest diff --git a/MSTest/ctsIOPatternStateUnitTest/ctsIOPatternStateUnitTest.vcxproj b/MSTest/ctsIOPatternStateUnitTest/ctsIOPatternStateUnitTest.vcxproj index 01abd42..b0a23c4 100644 --- a/MSTest/ctsIOPatternStateUnitTest/ctsIOPatternStateUnitTest.vcxproj +++ b/MSTest/ctsIOPatternStateUnitTest/ctsIOPatternStateUnitTest.vcxproj @@ -174,7 +174,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -199,7 +199,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -223,7 +223,7 @@ - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -248,7 +248,7 @@ - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -271,7 +271,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -296,7 +296,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -321,7 +321,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -346,7 +346,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest diff --git a/MSTest/ctsIOPatternUnitTest_Client/ctsIOPatternUnitTest_Client.vcxproj b/MSTest/ctsIOPatternUnitTest_Client/ctsIOPatternUnitTest_Client.vcxproj index f29a039..5488ee6 100644 --- a/MSTest/ctsIOPatternUnitTest_Client/ctsIOPatternUnitTest_Client.vcxproj +++ b/MSTest/ctsIOPatternUnitTest_Client/ctsIOPatternUnitTest_Client.vcxproj @@ -174,7 +174,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -199,7 +199,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -223,7 +223,7 @@ - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -248,7 +248,7 @@ - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -271,7 +271,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -296,7 +296,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -321,7 +321,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -346,7 +346,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest diff --git a/MSTest/ctsIOPatternUnitTest_Server/ctsIOPatternUnitTest_Server.vcxproj b/MSTest/ctsIOPatternUnitTest_Server/ctsIOPatternUnitTest_Server.vcxproj index 5489010..bb9cbe5 100644 --- a/MSTest/ctsIOPatternUnitTest_Server/ctsIOPatternUnitTest_Server.vcxproj +++ b/MSTest/ctsIOPatternUnitTest_Server/ctsIOPatternUnitTest_Server.vcxproj @@ -174,7 +174,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -199,7 +199,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -223,7 +223,7 @@ - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -248,7 +248,7 @@ - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -271,7 +271,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -296,7 +296,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -321,7 +321,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -346,7 +346,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest diff --git a/MSTest/ctsMediaStreamSendBuffer/ctsMediaStreamSendBufferUnitTest.vcxproj b/MSTest/ctsMediaStreamSendBuffer/ctsMediaStreamSendBufferUnitTest.vcxproj index 27eca31..fa48624 100644 --- a/MSTest/ctsMediaStreamSendBuffer/ctsMediaStreamSendBufferUnitTest.vcxproj +++ b/MSTest/ctsMediaStreamSendBuffer/ctsMediaStreamSendBufferUnitTest.vcxproj @@ -174,7 +174,7 @@ - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" Level4 NotUsing MaxSpeed @@ -200,7 +200,7 @@ - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" Level4 NotUsing MaxSpeed @@ -228,7 +228,7 @@ - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" Level4 NotUsing MaxSpeed @@ -256,7 +256,7 @@ - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" Level4 NotUsing MaxSpeed @@ -293,7 +293,7 @@ false - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -318,7 +318,7 @@ false - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -343,7 +343,7 @@ false - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -368,7 +368,7 @@ false - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest diff --git a/MSTest/ctsMediaStreamServerConnectedSocketUnitTest/ctsMediaStreamServerConnectedSocketUnitTest.vcxproj b/MSTest/ctsMediaStreamServerConnectedSocketUnitTest/ctsMediaStreamServerConnectedSocketUnitTest.vcxproj index 686b533..e382418 100644 --- a/MSTest/ctsMediaStreamServerConnectedSocketUnitTest/ctsMediaStreamServerConnectedSocketUnitTest.vcxproj +++ b/MSTest/ctsMediaStreamServerConnectedSocketUnitTest/ctsMediaStreamServerConnectedSocketUnitTest.vcxproj @@ -175,7 +175,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -199,7 +199,7 @@ - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -224,7 +224,7 @@ - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -249,7 +249,7 @@ - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -272,7 +272,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -297,7 +297,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -322,7 +322,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -347,7 +347,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest diff --git a/MSTest/ctsSocketBrokerUnitTest/ctsSocketBrokerUnitTest.vcxproj b/MSTest/ctsSocketBrokerUnitTest/ctsSocketBrokerUnitTest.vcxproj index 56446ff..0b3a762 100644 --- a/MSTest/ctsSocketBrokerUnitTest/ctsSocketBrokerUnitTest.vcxproj +++ b/MSTest/ctsSocketBrokerUnitTest/ctsSocketBrokerUnitTest.vcxproj @@ -182,7 +182,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -207,7 +207,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -230,7 +230,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -255,7 +255,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -276,7 +276,7 @@ true $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true @@ -302,7 +302,7 @@ true $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" @@ -330,7 +330,7 @@ true $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true @@ -356,7 +356,7 @@ true $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" diff --git a/MSTest/ctsSocketStateUnitTest/ctsSocketStateUnitTest.vcxproj b/MSTest/ctsSocketStateUnitTest/ctsSocketStateUnitTest.vcxproj index 131a85f..bb4f10b 100644 --- a/MSTest/ctsSocketStateUnitTest/ctsSocketStateUnitTest.vcxproj +++ b/MSTest/ctsSocketStateUnitTest/ctsSocketStateUnitTest.vcxproj @@ -173,7 +173,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -197,7 +197,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -219,7 +219,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -243,7 +243,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -267,7 +267,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -295,7 +295,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -321,7 +321,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -349,7 +349,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest diff --git a/MSTest/ctsSocketUnitTest/ctsSocketUnitTest.vcxproj b/MSTest/ctsSocketUnitTest/ctsSocketUnitTest.vcxproj index 0149cfd..ce309b6 100644 --- a/MSTest/ctsSocketUnitTest/ctsSocketUnitTest.vcxproj +++ b/MSTest/ctsSocketUnitTest/ctsSocketUnitTest.vcxproj @@ -174,7 +174,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -199,7 +199,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -223,7 +223,7 @@ - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -248,7 +248,7 @@ - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -271,7 +271,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -296,7 +296,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -321,7 +321,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -346,7 +346,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest diff --git a/MSTest/ctsStatisticsUnitTest/ctsStatisticsUnitTest.vcxproj b/MSTest/ctsStatisticsUnitTest/ctsStatisticsUnitTest.vcxproj index 61a6dc3..44dc8e8 100644 --- a/MSTest/ctsStatisticsUnitTest/ctsStatisticsUnitTest.vcxproj +++ b/MSTest/ctsStatisticsUnitTest/ctsStatisticsUnitTest.vcxproj @@ -174,7 +174,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -199,7 +199,7 @@ true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true stdcpplatest @@ -223,7 +223,7 @@ - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -248,7 +248,7 @@ - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -271,7 +271,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -296,7 +296,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -321,7 +321,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest @@ -346,7 +346,7 @@ $(VCInstallDir)UnitTest\include;..\..\wil\include;%(AdditionalIncludeDirectories) WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) true - /D "_WINSOCK_DEPRECATED_NO_WARNINGS" + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" true true stdcpplatest diff --git a/ctl/ctMath.hpp b/ctl/ctMath.hpp index bd1deb0..f0c0e13 100644 --- a/ctl/ctMath.hpp +++ b/ctl/ctMath.hpp @@ -97,14 +97,14 @@ std::tuple ctInterquartileRange(const BidirectionalItera } const auto numericQuotient = numericCount / 2; - const auto numericRemaineder = numericCount % 2; + const auto numericRemainder = numericCount % 2; // choose the (N+1)/2 value // - if it lands on a value, the iterator before and after // - if it lands between 2 values, return those 2 values BidirectionalIterator lhs; BidirectionalIterator rhs; - if (numericRemaineder == 0) + if (numericRemainder == 0) { // before and after the median lhs = splitBegin + numericQuotient - 2; diff --git a/ctl/ctMemoryGuard.hpp b/ctl/ctMemoryGuard.hpp index 207f2bf..a150c40 100644 --- a/ctl/ctMemoryGuard.hpp +++ b/ctl/ctMemoryGuard.hpp @@ -13,18 +13,12 @@ See the Apache Version 2.0 License for specific language governing permissions a #pragma once -// os headers #include namespace ctl { -////////////////////////////////////////////////////////////////////////////////////////// -/// -/// Can concurrent-safely read from both const and non-const -/// long long * -/// long * -/// -////////////////////////////////////////////////////////////////////////////////////////// + +// Can concurrent-safely read from both const and non-const inline long long ctMemoryGuardRead(const long long* value) noexcept { return ::InterlockedCompareExchange64(const_cast(value), 0LL, 0LL); @@ -45,19 +39,15 @@ inline long ctMemoryGuardRead(_In_ long* value) noexcept return ::InterlockedCompareExchange(value, 0LL, 0LL); } -////////////////////////////////////////////////////////////////////////////////////////// -/// -/// Can concurrent-safely update a long long or long value -/// - *Write returns the *prior* value -/// - *WriteConditionally returns the *prior* value -/// - *Add returns the *prior* value -/// - *Subtract returns the *prior* value -/// (Note subtraction is just the adding a negative long value) -/// -/// - *Increment returns the *new* value -/// - *Decrement returns the *new* value -/// -////////////////////////////////////////////////////////////////////////////////////////// +// Can concurrent-safely update a long long or long value +// - *Write returns the *prior* value +// - *WriteConditionally returns the *prior* value +// - *Add returns the *prior* value +// - *Subtract returns the *prior* value +// (Note subtraction is just the adding a negative long value) +// +// - *Increment returns the *new* value +// - *Decrement returns the *new* value inline long long ctMemoryGuardWrite(_Inout_ long long* value, long long newValue) noexcept { return ::InterlockedExchange64(value, newValue); diff --git a/ctl/ctNetAdapterAddresses.hpp b/ctl/ctNetAdapterAddresses.hpp index bf7f0b6..289a1da 100644 --- a/ctl/ctNetAdapterAddresses.hpp +++ b/ctl/ctNetAdapterAddresses.hpp @@ -122,12 +122,8 @@ class ctNetAdapterAddresses return *this; } - //////////////////////////////////////////////////////////////////////////////// - /// - /// iterator_traits - /// - allows functions to be used - /// - //////////////////////////////////////////////////////////////////////////////// + // iterator_traits + // - allows functions to be used using iterator_category = std::forward_iterator_tag; using value_type = IP_ADAPTER_ADDRESSES; using difference_type = int; @@ -139,35 +135,22 @@ class ctNetAdapterAddresses PIP_ADAPTER_ADDRESSES m_current = nullptr; }; - //////////////////////////////////////////////////////////////////////////////// - /// - /// c'tor - /// - /// - default d'tor, copy c'tor, and copy assignment - /// - Takes an optional _gaaFlags argument which is passed through directly to - /// GetAdapterAddresses internally - use standard GAA_FLAG_* constants - /// - //////////////////////////////////////////////////////////////////////////////// explicit ctNetAdapterAddresses(unsigned family = AF_UNSPEC, DWORD gaaFlags = 0) : m_buffer(std::make_shared>(16384)) { this->refresh(family, gaaFlags); } - //////////////////////////////////////////////////////////////////////////////// - /// - /// refresh - /// - /// - retrieves the current set of adapter address information - /// - Takes an optional _gaaFlags argument which is passed through directly to - /// GetAdapterAddresses internally - use standard GAA_FLAG_* constants - /// - /// NOTE: this will invalidate any iterators from this instance - /// NOTE: this only implements the Basic exception guarantee - /// if this fails, an exception is thrown, and any prior - /// information is lost. This is still safe to call after errors. - /// - //////////////////////////////////////////////////////////////////////////////// + // refresh + // + // - retrieves the current set of adapter address information + // - Takes an optional _gaaFlags argument which is passed through directly to + // GetAdapterAddresses internally - use standard GAA_FLAG_* constants + // + // NOTE: this will invalidate any iterators from this instance + // NOTE: this only implements the Basic exception guarantee + // if this fails, an exception is thrown, and any prior + // information is lost. This is still safe to call after errors. void refresh(unsigned family = AF_UNSPEC, DWORD gaaFlags = 0) const { // get both v4 and v6 adapter info @@ -211,10 +194,10 @@ class ctNetAdapterAddresses std::shared_ptr> m_buffer{}; }; -/// functor ctNetAdapterMatchingAddrPredicate -/// -/// Created to leverage STL algorigthms to parse a ctNetAdapterAddresses set of iterators -/// - to find the first interface that has the specified address assigned +// functor ctNetAdapterMatchingAddrPredicate +// +// Created to leverage STL algorithms to parse a ctNetAdapterAddresses set of iterators +// - to find the first interface that has the specified address assigned struct ctNetAdapterMatchingAddrPredicate { explicit ctNetAdapterMatchingAddrPredicate(ctSockaddr addr) noexcept : diff --git a/ctl/ctSockaddr.hpp b/ctl/ctSockaddr.hpp index b58a877..003f675 100644 --- a/ctl/ctSockaddr.hpp +++ b/ctl/ctSockaddr.hpp @@ -35,7 +35,7 @@ See the Apache Version 2.0 License for specific language governing permissions a namespace ctl { -enum class ByteOrder +enum class ByteOrder : std::uint8_t { HostOrder, NetworkOrder @@ -90,7 +90,7 @@ class ctSockaddr final return outV6; } - enum class AddressType + enum class AddressType : std::uint8_t { Loopback, Any @@ -180,8 +180,8 @@ class ctSockaddr final [[nodiscard]] const IN6_ADDR* in6_addr() const noexcept; private: - static constexpr size_t c_saddrSize = sizeof(SOCKADDR_INET); - SOCKADDR_INET m_saddr{}; + static constexpr size_t c_sockaddrSize = sizeof(SOCKADDR_INET); + SOCKADDR_INET m_sockaddr{}; }; // @@ -242,7 +242,7 @@ inline ctSockaddr::ctSockaddr(const IN6_ADDR* inAddr, unsigned short port, ByteO inline ctSockaddr::ctSockaddr(const ctSockaddr& inAddr) noexcept { - CopyMemory(&m_saddr, &inAddr.m_saddr, c_saddrSize); + CopyMemory(&m_sockaddr, &inAddr.m_sockaddr, c_sockaddrSize); } inline ctSockaddr& ctSockaddr::operator=(const ctSockaddr& inAddr) noexcept @@ -254,28 +254,28 @@ inline ctSockaddr& ctSockaddr::operator=(const ctSockaddr& inAddr) noexcept inline ctSockaddr::ctSockaddr(ctSockaddr&& inAddr) noexcept { - CopyMemory(&m_saddr, &inAddr.m_saddr, c_saddrSize); + CopyMemory(&m_sockaddr, &inAddr.m_sockaddr, c_sockaddrSize); } inline ctSockaddr& ctSockaddr::operator=(ctSockaddr&& inAddr) noexcept { - CopyMemory(&m_saddr, &inAddr.m_saddr, c_saddrSize); - ZeroMemory(&inAddr.m_saddr, c_saddrSize); + CopyMemory(&m_sockaddr, &inAddr.m_sockaddr, c_sockaddrSize); + ZeroMemory(&inAddr.m_sockaddr, c_sockaddrSize); return *this; } inline bool ctSockaddr::operator==(const ctSockaddr& inAddr) const noexcept { - switch (m_saddr.si_family) + switch (m_sockaddr.si_family) { case AF_INET: // only require the v4 slice of the union to match - return 0 == memcmp(&m_saddr.Ipv4, &inAddr.m_saddr.Ipv4, sizeof(SOCKADDR_IN)); + return 0 == memcmp(&m_sockaddr.Ipv4, &inAddr.m_sockaddr.Ipv4, sizeof(SOCKADDR_IN)); case AF_INET6: // only require the v6 slice of the union to match - return 0 == memcmp(&m_saddr.Ipv6, &inAddr.m_saddr.Ipv6, sizeof(SOCKADDR_IN6)); + return 0 == memcmp(&m_sockaddr.Ipv6, &inAddr.m_sockaddr.Ipv6, sizeof(SOCKADDR_IN6)); default: - return 0 == memcmp(&m_saddr, &inAddr.m_saddr, c_saddrSize); + return 0 == memcmp(&m_sockaddr, &inAddr.m_sockaddr, c_sockaddrSize); } } @@ -411,24 +411,24 @@ inline bool ctSockaddr::operator>(const ctSockaddr& rhs) const noexcept inline void ctSockaddr::reset(ADDRESS_FAMILY family) noexcept { - ZeroMemory(&m_saddr, c_saddrSize); - m_saddr.si_family = family; + ZeroMemory(&m_sockaddr, c_sockaddrSize); + m_sockaddr.si_family = family; } inline void ctSockaddr::reset(ADDRESS_FAMILY family, AddressType type) noexcept { - ZeroMemory(&m_saddr, c_saddrSize); - m_saddr.si_family = family; + ZeroMemory(&m_sockaddr, c_sockaddrSize); + m_sockaddr.si_family = family; if (type == AddressType::Loopback) { if (AF_INET == family) { - m_saddr.Ipv4.sin_addr = in4addr_loopback; // from ws2ipdef.h + m_sockaddr.Ipv4.sin_addr = in4addr_loopback; // from ws2ipdef.h } else if (AF_INET6 == family) { - m_saddr.Ipv6.sin6_addr = in6addr_loopback; // from ws2ipdef.h + m_sockaddr.Ipv6.sin6_addr = in6addr_loopback; // from ws2ipdef.h } else { @@ -440,9 +440,9 @@ inline void ctSockaddr::reset(ADDRESS_FAMILY family, AddressType type) noexcept inline void ctSockaddr::swap(_Inout_ ctSockaddr& inAddr) noexcept { SOCKADDR_INET tempAddr{}; - CopyMemory(&tempAddr, &inAddr.m_saddr, c_saddrSize); - CopyMemory(&inAddr.m_saddr, &m_saddr, c_saddrSize); - CopyMemory(&m_saddr, &tempAddr, c_saddrSize); + CopyMemory(&tempAddr, &inAddr.m_sockaddr, c_sockaddrSize); + CopyMemory(&inAddr.m_sockaddr, &m_sockaddr, c_sockaddrSize); + CopyMemory(&m_sockaddr, &tempAddr, c_sockaddrSize); } inline bool ctSockaddr::setAddress(SOCKET s) noexcept @@ -453,100 +453,100 @@ inline bool ctSockaddr::setAddress(SOCKET s) noexcept inline void ctSockaddr::setSockaddr(_In_reads_bytes_(inLength) const SOCKADDR* inAddr, int inLength) noexcept { - const auto length = static_cast(inLength) < c_saddrSize ? inLength : c_saddrSize; - ZeroMemory(&m_saddr, c_saddrSize); - CopyMemory(&m_saddr, inAddr, length); + const auto length = static_cast(inLength) < c_sockaddrSize ? inLength : c_sockaddrSize; + ZeroMemory(&m_sockaddr, c_sockaddrSize); + CopyMemory(&m_sockaddr, inAddr, length); } inline void ctSockaddr::setSockaddr(_In_reads_bytes_(inLength) const SOCKADDR* inAddr, size_t inLength) noexcept { - const auto length = inLength < c_saddrSize ? inLength : c_saddrSize; - ZeroMemory(&m_saddr, c_saddrSize); - CopyMemory(&m_saddr, inAddr, length); + const auto length = inLength < c_sockaddrSize ? inLength : c_sockaddrSize; + ZeroMemory(&m_sockaddr, c_sockaddrSize); + CopyMemory(&m_sockaddr, inAddr, length); } inline void ctSockaddr::setSockaddr(const SOCKADDR_IN* inAddr) noexcept { - ZeroMemory(&m_saddr, c_saddrSize); - CopyMemory(&m_saddr, inAddr, sizeof(SOCKADDR_IN)); + ZeroMemory(&m_sockaddr, c_sockaddrSize); + CopyMemory(&m_sockaddr, inAddr, sizeof(SOCKADDR_IN)); } inline void ctSockaddr::setSockaddr(const SOCKADDR_IN6* inAddr) noexcept { - ZeroMemory(&m_saddr, c_saddrSize); - CopyMemory(&m_saddr, inAddr, sizeof(SOCKADDR_IN6)); + ZeroMemory(&m_sockaddr, c_sockaddrSize); + CopyMemory(&m_sockaddr, inAddr, sizeof(SOCKADDR_IN6)); } inline void ctSockaddr::setSockaddr(const SOCKADDR_INET* inAddr) noexcept { - ZeroMemory(&m_saddr, c_saddrSize); - CopyMemory(&m_saddr, inAddr, sizeof(SOCKADDR_INET)); + ZeroMemory(&m_sockaddr, c_sockaddrSize); + CopyMemory(&m_sockaddr, inAddr, sizeof(SOCKADDR_INET)); } inline void ctSockaddr::setSockaddr(const SOCKET_ADDRESS* inAddr) noexcept { - const auto length = static_cast(inAddr->iSockaddrLength) < c_saddrSize - ? static_cast(inAddr->iSockaddrLength) : c_saddrSize; + const auto length = static_cast(inAddr->iSockaddrLength) < c_sockaddrSize + ? static_cast(inAddr->iSockaddrLength) : c_sockaddrSize; - ZeroMemory(&m_saddr, c_saddrSize); - CopyMemory(&m_saddr, inAddr->lpSockaddr, length); + ZeroMemory(&m_sockaddr, c_sockaddrSize); + CopyMemory(&m_sockaddr, inAddr->lpSockaddr, length); } inline bool ctSockaddr::isAddressLinkLocal() const noexcept { - if (m_saddr.si_family == 0) + if (m_sockaddr.si_family == 0) { WI_ASSERT(false); return false; } - if (m_saddr.si_family == AF_INET6) + if (m_sockaddr.si_family == AF_INET6) { - return IN6_IS_ADDR_LINKLOCAL(&m_saddr.Ipv6.sin6_addr); + return IN6_IS_ADDR_LINKLOCAL(&m_sockaddr.Ipv6.sin6_addr); } - return (m_saddr.Ipv4.sin_addr.S_un.S_addr & 0xffff) == 0xfea9; // 169.254/16 + return (m_sockaddr.Ipv4.sin_addr.S_un.S_addr & 0xffff) == 0xfea9; // 169.254/16 } inline void ctSockaddr::setAddressAny() noexcept { - reset(m_saddr.si_family); + reset(m_sockaddr.si_family); } inline bool ctSockaddr::isAddressAny() const noexcept { - if (m_saddr.si_family == 0) + if (m_sockaddr.si_family == 0) { WI_ASSERT(false); return false; } - if (m_saddr.si_family == AF_INET6) + if (m_sockaddr.si_family == AF_INET6) { - return 0 == memcmp(&m_saddr.Ipv6.sin6_addr, &in6addr_any, sizeof IN6_ADDR); + return 0 == memcmp(&m_sockaddr.Ipv6.sin6_addr, &in6addr_any, sizeof IN6_ADDR); } - return 0 == memcmp(&m_saddr.Ipv4.sin_addr, &in4addr_any, sizeof IN_ADDR); + return 0 == memcmp(&m_sockaddr.Ipv4.sin_addr, &in4addr_any, sizeof IN_ADDR); } inline void ctSockaddr::setAddressLoopback() noexcept { - const ctSockaddr loopbackAddr{m_saddr.si_family, AddressType::Loopback}; - CopyMemory(&m_saddr, &loopbackAddr.m_saddr, c_saddrSize); + const ctSockaddr loopbackAddr{m_sockaddr.si_family, AddressType::Loopback}; + CopyMemory(&m_sockaddr, &loopbackAddr.m_sockaddr, c_sockaddrSize); } inline bool ctSockaddr::isAddressLoopback() const noexcept { - if (m_saddr.si_family == 0) + if (m_sockaddr.si_family == 0) { WI_ASSERT(false); return false; } - if (m_saddr.si_family == AF_INET6) + if (m_sockaddr.si_family == AF_INET6) { - return 0 == memcmp(&m_saddr.Ipv6.sin6_addr, &in6addr_loopback, sizeof IN6_ADDR); + return 0 == memcmp(&m_sockaddr.Ipv6.sin6_addr, &in6addr_loopback, sizeof IN6_ADDR); } - return 0 == memcmp(&m_saddr.Ipv4.sin_addr, &in4addr_loopback, sizeof IN_ADDR); + return 0 == memcmp(&m_sockaddr.Ipv4.sin_addr, &in4addr_loopback, sizeof IN_ADDR); } inline bool ctSockaddr::setAddress(_In_ PCWSTR wszAddr) noexcept @@ -586,33 +586,33 @@ inline bool ctSockaddr::setAddress(_In_ PCSTR szAddr) noexcept inline void ctSockaddr::setAddress(const IN_ADDR* inAddr) noexcept { reset(AF_INET); - m_saddr.Ipv4.sin_addr.S_un.S_addr = inAddr->S_un.S_addr; + m_sockaddr.Ipv4.sin_addr.S_un.S_addr = inAddr->S_un.S_addr; } inline void ctSockaddr::setAddress(const IN6_ADDR* inAddr) noexcept { reset(AF_INET6); - m_saddr.Ipv6.sin6_addr = *inAddr; + m_sockaddr.Ipv6.sin6_addr = *inAddr; } inline void ctSockaddr::setPort(uint16_t port, ByteOrder byteOrder) noexcept { - m_saddr.Ipv4.sin_port = byteOrder == ByteOrder::HostOrder ? htons(port) : port; + m_sockaddr.Ipv4.sin_port = byteOrder == ByteOrder::HostOrder ? htons(port) : port; } inline void ctSockaddr::setScopeId(uint32_t scopeid) noexcept { - if (AF_INET6 == m_saddr.si_family) + if (AF_INET6 == m_sockaddr.si_family) { - m_saddr.Ipv6.sin6_scope_id = scopeid; + m_sockaddr.Ipv6.sin6_scope_id = scopeid; } } inline void ctSockaddr::setFlowInfo(uint32_t flowinfo) noexcept { - if (AF_INET6 == m_saddr.si_family) + if (AF_INET6 == m_sockaddr.si_family) { - m_saddr.Ipv6.sin6_flowinfo = flowinfo; + m_sockaddr.Ipv6.sin6_flowinfo = flowinfo; } } @@ -628,18 +628,18 @@ inline bool ctSockaddr::writeAddress(WCHAR (&address)[FixedStringLength]) const { ZeroMemory(address, FixedStringLength * sizeof(WCHAR)); - const void* const pAddr = AF_INET == m_saddr.si_family - ? static_cast(&m_saddr.Ipv4.sin_addr) : static_cast(&m_saddr.Ipv6.sin6_addr); - return nullptr != InetNtopW(m_saddr.si_family, pAddr, address, FixedStringLength); + const void* const pAddr = AF_INET == m_sockaddr.si_family + ? static_cast(&m_sockaddr.Ipv4.sin_addr) : static_cast(&m_sockaddr.Ipv6.sin6_addr); + return nullptr != InetNtopW(m_sockaddr.si_family, pAddr, address, FixedStringLength); } inline bool ctSockaddr::writeAddress(CHAR (&address)[FixedStringLength]) const noexcept { ZeroMemory(address, FixedStringLength * sizeof(CHAR)); - const void* const pAddr = AF_INET == m_saddr.si_family - ? static_cast(&m_saddr.Ipv4.sin_addr) : static_cast(&m_saddr.Ipv6.sin6_addr); - return nullptr != InetNtopA(m_saddr.si_family, pAddr, address, FixedStringLength); + const void* const pAddr = AF_INET == m_sockaddr.si_family + ? static_cast(&m_sockaddr.Ipv4.sin_addr) : static_cast(&m_sockaddr.Ipv6.sin6_addr); + return nullptr != InetNtopA(m_sockaddr.si_family, pAddr, address, FixedStringLength); } inline std::wstring ctSockaddr::writeCompleteAddress(bool trimScope) const @@ -655,9 +655,9 @@ inline bool ctSockaddr::writeCompleteAddress(WCHAR (&address)[FixedStringLength] ZeroMemory(address, FixedStringLength * sizeof(WCHAR)); DWORD addressLength = FixedStringLength; - if (0 == WSAAddressToStringW(const_cast(sockaddr()), c_saddrSize, nullptr, address, &addressLength)) + if (0 == WSAAddressToStringW(const_cast(sockaddr()), c_sockaddrSize, nullptr, address, &addressLength)) { - if (m_saddr.si_family == AF_INET6 && trimScope) + if (m_sockaddr.si_family == AF_INET6 && trimScope) { // ReSharper disable once CppLocalVariableMayBeConst auto* const end = address + addressLength; @@ -694,9 +694,9 @@ inline bool ctSockaddr::writeCompleteAddress(CHAR (&address)[FixedStringLength], ZeroMemory(address, FixedStringLength * sizeof(CHAR)); DWORD addressLength = FixedStringLength; - if (0 == WSAAddressToStringA(const_cast(sockaddr()), c_saddrSize, nullptr, address, &addressLength)) + if (0 == WSAAddressToStringA(const_cast(sockaddr()), c_sockaddrSize, nullptr, address, &addressLength)) { - if (m_saddr.si_family == AF_INET6 && trimScope) + if (m_sockaddr.si_family == AF_INET6 && trimScope) { // ReSharper disable once CppLocalVariableMayBeConst auto* const end = address + addressLength; @@ -731,95 +731,95 @@ inline bool ctSockaddr::writeCompleteAddress(CHAR (&address)[FixedStringLength], // ReSharper disable once CppMemberFunctionMayBeStatic inline int ctSockaddr::length() const noexcept // NOLINT(readability-convert-member-functions-to-static) { - return static_cast(c_saddrSize); + return static_cast(c_sockaddrSize); } inline ADDRESS_FAMILY ctSockaddr::family() const noexcept { - return m_saddr.si_family; + return m_sockaddr.si_family; } inline uint16_t ctSockaddr::port() const noexcept { - return ntohs(m_saddr.Ipv4.sin_port); + return ntohs(m_sockaddr.Ipv4.sin_port); } inline uint32_t ctSockaddr::flowinfo() const noexcept { - if (AF_INET6 == m_saddr.si_family) + if (AF_INET6 == m_sockaddr.si_family) { - return m_saddr.Ipv6.sin6_flowinfo; + return m_sockaddr.Ipv6.sin6_flowinfo; } return 0; } inline uint32_t ctSockaddr::scope_id() const noexcept { - if (AF_INET6 == m_saddr.si_family) + if (AF_INET6 == m_sockaddr.si_family) { - return m_saddr.Ipv6.sin6_scope_id; + return m_sockaddr.Ipv6.sin6_scope_id; } return 0; } inline SOCKADDR* ctSockaddr::sockaddr() noexcept { - return reinterpret_cast(&m_saddr); + return reinterpret_cast(&m_sockaddr); } inline SOCKADDR_IN* ctSockaddr::sockaddr_in() noexcept { - return &m_saddr.Ipv4; + return &m_sockaddr.Ipv4; } inline SOCKADDR_IN6* ctSockaddr::sockaddr_in6() noexcept { - return &m_saddr.Ipv6; + return &m_sockaddr.Ipv6; } inline SOCKADDR_INET* ctSockaddr::sockaddr_inet() noexcept { - return &m_saddr; + return &m_sockaddr; } inline IN_ADDR* ctSockaddr::in_addr() noexcept { - return &m_saddr.Ipv4.sin_addr; + return &m_sockaddr.Ipv4.sin_addr; } inline IN6_ADDR* ctSockaddr::in6_addr() noexcept { - return &m_saddr.Ipv6.sin6_addr; + return &m_sockaddr.Ipv6.sin6_addr; } inline const SOCKADDR* ctSockaddr::sockaddr() const noexcept { - return reinterpret_cast(&m_saddr); + return reinterpret_cast(&m_sockaddr); } inline const SOCKADDR_IN* ctSockaddr::sockaddr_in() const noexcept { - return &m_saddr.Ipv4; + return &m_sockaddr.Ipv4; } inline const SOCKADDR_IN6* ctSockaddr::sockaddr_in6() const noexcept { - return &m_saddr.Ipv6; + return &m_sockaddr.Ipv6; } inline const SOCKADDR_INET* ctSockaddr::sockaddr_inet() const noexcept { - return &m_saddr; + return &m_sockaddr; } inline const IN_ADDR* ctSockaddr::in_addr() const noexcept { - return &m_saddr.Ipv4.sin_addr; + return &m_sockaddr.Ipv4.sin_addr; } inline const IN6_ADDR* ctSockaddr::in6_addr() const noexcept { - return &m_saddr.Ipv6.sin6_addr; + return &m_sockaddr.Ipv6.sin6_addr; } } // namespace ctl diff --git a/ctl/ctString.hpp b/ctl/ctString.hpp index 9d6f4fa..e9d247a 100644 --- a/ctl/ctString.hpp +++ b/ctl/ctString.hpp @@ -24,33 +24,26 @@ See the Apache Version 2.0 License for specific language governing permissions a #include -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// -/// String parsing and manipulation functions to enable faster, more reliable development -/// -/// Notice all functions are in the ctl::ctString namespace -/// -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////// - +// +// +// String parsing and manipulation functions to enable faster, more reliable development +// +// Notice all functions are in the ctl::ctString namespace +// namespace ctl::ctString { -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// convert_to_string -/// convert_to_wstring -/// -/// Converts between std::string and std::wstring using win32 conversion functions -/// -/// These use UTF8 for all conversion operations -/// -/// Can throw wil::ResultException on failures from the underlying conversion calls -/// Can throw std::bad_alloc -/// -//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// convert_to_string +// convert_to_wstring +// +// Converts between std::string and std::wstring using win32 conversion functions +// +// These use UTF8 for all conversion operations +// +// Can throw wil::ResultException on failures from the underlying conversion calls +// Can throw std::bad_alloc +// inline std::string convert_to_string(const std::wstring& str) { if (str.empty()) @@ -102,35 +95,31 @@ inline std::wstring convert_to_wstring(const std::string& str) } -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// ordinal_equals -/// iordinal_equals -/// -/// Performs Ordinal comparisons of 2 strings, returning a bool if they compare equally. -/// *Note the 'i' version is a case-insensitive comparison -/// -/// Ordinal comparisons are desired when you want "binary equality". Examples include: -/// - want to find a system resource (file, directory, registry key) -/// - want to sort consistently regardless of user locale -/// - want to compare against a value *you* control that's not affected by user locale -/// -/// Can throw a wil::ResultException if the Win32 API fails -/// -/// Examples: -/// -/// wchar_t hello[] = L"Hello"; -/// if (ordinal_equals(hello, L"Hello)) { printf(L"Correct!"); } -/// -/// std::wstring wstringHello (L"hello"); -/// if (iordinal_equals(hello, wstringHello)) { printf(L"Correct!"); } -/// -//////////////////////////////////////////////////////////////////////////////////////////////////// - - +// +// ordinal_equals +// iordinal_equals +// +// Performs Ordinal comparisons of 2 strings, returning a bool if they compare equally. +// *Note the 'i' version is a case-insensitive comparison +// +// Ordinal comparisons are desired when you want "binary equality". Examples include: +// - want to find a system resource (file, directory, registry key) +// - want to sort consistently regardless of user locale +// - want to compare against a value *you* control that's not affected by user locale +// +// Can throw a wil::ResultException if the Win32 API fails +// +// Examples: +// +// wchar_t hello[] = L"Hello"; +// if (ordinal_equals(hello, L"Hello)) { printf(L"Correct!"); } +// +// std::wstring wstringHello (L"hello"); +// if (iordinal_equals(hello, wstringHello)) { printf(L"Correct!"); } +// // Note: wcslen(convert_to_ptr(x)) == get_string_length(x) is strictly required for any pair of // convert_to_ptr/get_string_length implementations, but can't be cleanly expressed in SAL annotations - +// namespace Detail { inline bool OrdinalEquals( @@ -279,24 +268,21 @@ bool iordinal_equals(LeftStringT lhs, RightStringT rhs) } -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// starts_with -/// istarts_with -/// ends_with -/// iends_with -/// -/// Searches the relevant portion of the input string for the search string, returning bool -/// -/// Most useful in combination with std::bind as a predicate to find_if and its friends -/// -/// The "i" versions perform case-insensitive (but *NOT* locale-sensitive) searches. -/// The non-i versions perform exact character comparison - case-sensitive, locale-insensitive -/// -/// *NOT* nothrow -/// -//////////////////////////////////////////////////////////////////////////////////////////////////// - +// +// starts_with +// istarts_with +// ends_with +// iends_with +// +// Searches the relevant portion of the input string for the search string, returning bool +// +// Most useful in combination with std::bind as a predicate to find_if and its friends +// +// The "i" versions perform case-insensitive (but *NOT* locale-sensitive) searches. +// The non-i versions perform exact character comparison - case-sensitive, locale-insensitive +// +// *NOT* nothrow +// inline bool starts_with(const std::wstring& haystack, const std::wstring& needle) { return @@ -379,49 +365,47 @@ inline std::wstring format_message(DWORD messageId) return stringBuffer; } -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// replace_all -/// replace_all_copy -/// -/// Performs a find/replace of a specific character sequence. -/// -/// *Note this is an exact character comparison - case-sensitive without respect for locale -/// -/// *Note key differences between the 2 functions: -/// -/// - replace_all takes an original string as an std::wstring reference. -/// Meaning an implicit std::wstring object cannot be created. -/// -/// This is not valid: -/// wchar_t hello[] = L"hello"; -/// replace_all(hello, L"h", L"j"); -/// -/// This is valid: -/// std::wstring hello(L"hello"); -/// replace_all(hello, L"h", L"j"); -/// -/// - replace_all_copy takes an original string by value into std::wstring. -/// Meaning an implicit std::wstring object *can* be created. -/// Additionally, R-value references can be passed through it via std::move semantics. -/// A new std::wstring is returned with the escaped string. -/// -/// This is now valid: -/// wchar_t hello[] = L"hello"; -/// std::wstring jello = replace_all_copy(hello, L"h", L"j"); -/// -/// This is still valid: -/// std::wstring hello(L"hello"); -/// std::wstring jello = replace_all_copy(hello, L"h", L"j"); -/// -/// This is also valid - will pass down as an R-Value to avoid any copies: -/// std::wstring hello(L"ello"); -/// std::wstring jello = replace_all_copy(L"h" + hello, L"h", L"j"); -/// -/// -/// Can throw a std::exception under low-resources -/// -//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// replace_all +// replace_all_copy +// +// Performs a find/replace of a specific character sequence. +// +// *Note this is an exact character comparison - case-sensitive without respect for locale +// +// *Note key differences between the 2 functions: +// +// - replace_all takes an original string as an std::wstring reference. +// Meaning an implicit std::wstring object cannot be created. +// +// This is not valid: +// wchar_t hello[] = L"hello"; +// replace_all(hello, L"h", L"j"); +// +// This is valid: +// std::wstring hello(L"hello"); +// replace_all(hello, L"h", L"j"); +// +// - replace_all_copy takes an original string by value into std::wstring. +// Meaning an implicit std::wstring object *can* be created. +// Additionally, R-value references can be passed through it via std::move semantics. +// A new std::wstring is returned with the escaped string. +// +// This is now valid: +// wchar_t hello[] = L"hello"; +// std::wstring jello = replace_all_copy(hello, L"h", L"j"); +// +// This is still valid: +// std::wstring hello(L"hello"); +// std::wstring jello = replace_all_copy(hello, L"h", L"j"); +// +// This is also valid - will pass down as an R-Value to avoid any copies: +// std::wstring hello(L"ello"); +// std::wstring jello = replace_all_copy(L"h" + hello, L"h", L"j"); +// +// +// Can throw a std::exception under low-resources +// inline void replace_all(std::wstring& originalString, const std::wstring& searchString, const std::wstring& replacementString) // NOLINT(google-runtime-references) { const auto searchSize = searchString.size(); @@ -459,25 +443,23 @@ inline std::string replace_all_copy(std::string originalString, const std::strin return originalString; } -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// escape_wmi_query -/// escape_wmi_query_copy -/// -/// Escapes characters that are 'special' in the context of a WMI WQL query which could -/// inadvertently affect the result of the query. -/// -/// - escape_wmi_query takes an original string as an std::wstring reference. -/// Meaning an implicit std::wstring object cannot be created. -/// -/// - escape_wmi_query_copy takes an original string by value into std::wstring. -/// Meaning an implicit std::wstring object *can* be created. -/// Additionally, R-value references can be passed through it via std::move semantics. -/// A new std::wstring is returned with the escaped string. -/// -/// Can throw a std::exception under low-resources -/// -//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// escape_wmi_query +// escape_wmi_query_copy +// +// Escapes characters that are 'special' in the context of a WMI WQL query which could +// inadvertently affect the result of the query. +// +// - escape_wmi_query takes an original string as an std::wstring reference. +// Meaning an implicit std::wstring object cannot be created. +// +// - escape_wmi_query_copy takes an original string by value into std::wstring. +// Meaning an implicit std::wstring object *can* be created. +// Additionally, R-value references can be passed through it via std::move semantics. +// A new std::wstring is returned with the escaped string. +// +// Can throw a std::exception under low-resources +// inline void escape_wmi_query(std::wstring& unescapedString) { if (unescapedString.size() > 1) @@ -503,28 +485,6 @@ inline std::wstring escape_wmi_query_copy(std::wstring unescapedString) return unescapedString; } -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// format_string -/// format_string_va -/// -/// Creates a formatted string for the caller - growing the buffer for _vsnwprintf_s -/// Returns a std::wstring with the resulting formatted string -/// -/// Will continue to grow the formatted string up to MAXINT32 characters to avoid truncation -/// to ensure the entire formatted string is captured -/// -/// Can throw a std::exception under low-resources -/// -//////////////////////////////////////////////////////////////////////////////////////////////////// -inline -std::wstring __cdecl format_string_va(_In_ _Printf_format_string_ PCWSTR pszFormat, va_list args) -{ - std::wstring formattedString; - THROW_IF_FAILED(wil::details::str_vprintf_nothrow(formattedString, pszFormat, args)); - return formattedString; -} - inline std::wstring __cdecl format_string(_In_ _Printf_format_string_ PCWSTR pszFormat, ...) { diff --git a/ctl/ctThreadIocp.hpp b/ctl/ctThreadIocp.hpp index aed04f0..83958d2 100644 --- a/ctl/ctThreadIocp.hpp +++ b/ctl/ctThreadIocp.hpp @@ -65,41 +65,37 @@ struct ctThreadIocpCallbackInfo static_assert(sizeof(ctThreadIocpCallbackInfo) == sizeof(OVERLAPPED) + sizeof(PVOID) + sizeof(ctThreadIocpCallback_t)); -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// ctThreadIocp -/// -/// class that encapsulates the new-to-Vista ThreadPool APIs around OVERLAPPED IO completion ports -/// -/// it creates a handle to the system-managed thread pool, -/// - and exposes a method to get an OVERLAPPED* for asynchronous Win32 API calls which use OVERLAPPED I/O -/// -/// Basic usage: -/// - construct a ctThreadIocp object by passing in the HANDLE/SOCKET on which overlapped IO calls will be made -/// - call new_request to get an OVERLAPPED* for an asynchronous Win32 API call the associated HANDLE/SOCKET -/// - additionally pass a function to be invoked on IO completion -/// - if the Win32 API succeeds or returns ERROR_IO_PENDING: -/// - the user's callback function will be called on completion [if succeeds or fails] -/// - from the callback function, the user then calls GetOverlappedResult/WSAGetOverlappedResult -/// on the given OVERLAPPED* to get further details of the IO request [status, bytes transferred] -/// - if the Win32 API fails with an error other than ERROR_IO_PENDING -/// - the user *must* call cancel_request, providing the OVERLAPPED* used in the failed API call -/// - that OVERLAPPED* is no longer valid and cannot be reused -/// [new_request must be called again for another OVLERAPPED*] -/// -/// Additional notes regarding OVERLAPPED I/O: -/// - the user must call new_request to get a new OVERLAPPED* before every Win32 API being made -/// - an OVERLAPPED* is valid only for that one API call and is invalid once the corresponding callback completes -/// - if the IO call must be canceled after is completed successfully or returned ERROR_IO_PENDING, -/// the user should take care to call the appropriate API (CancelIo, CancelIoEx, CloseHandle, closesocket) -/// - the user should then expect the callback to be invoked for all IO requests on that HANDLE/SOCKET -/// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// ctThreadIocp +// +// class that encapsulates the new-to-Vista ThreadPool APIs around OVERLAPPED IO completion ports +// +// it creates a handle to the system-managed thread pool, +// - and exposes a method to get an OVERLAPPED* for asynchronous Win32 API calls which use OVERLAPPED I/O +// +// Basic usage: +// - construct a ctThreadIocp object by passing in the HANDLE/SOCKET on which overlapped IO calls will be made +// - call new_request to get an OVERLAPPED* for an asynchronous Win32 API call the associated HANDLE/SOCKET +// - additionally pass a function to be invoked on IO completion +// - if the Win32 API succeeds or returns ERROR_IO_PENDING: +// - the user's callback function will be called on completion [if succeeds or fails] +// - from the callback function, the user then calls GetOverlappedResult/WSAGetOverlappedResult +// on the given OVERLAPPED* to get further details of the IO request [status, bytes transferred] +// - if the Win32 API fails with an error other than ERROR_IO_PENDING +// - the user *must* call cancel_request, providing the OVERLAPPED* used in the failed API call +// - that OVERLAPPED* is no longer valid and cannot be reused +// [new_request must be called again for another OVERLAPPED*] +// +// Additional notes regarding OVERLAPPED I/O: +// - the user must call new_request to get a new OVERLAPPED* before every Win32 API being made +// - an OVERLAPPED* is valid only for that one API call and is invalid once the corresponding callback completes +// - if the IO call must be canceled after is completed successfully or returned ERROR_IO_PENDING, +// the user should take care to call the appropriate API (CancelIo, CancelIoEx, CloseHandle, closesocket) +// - the user should then expect the callback to be invoked for all IO requests on that HANDLE/SOCKET class ctThreadIocp { public: // - // These c'tors can fail under low resources + // These constructors can fail under low resources // - wil::ResultException (from the ThreadPool APIs) // explicit ctThreadIocp(HANDLE _handle, _In_opt_ PTP_CALLBACK_ENVIRON _ptp_env = nullptr) : @@ -128,7 +124,7 @@ class ctThreadIocp } // - // new_request is expected to be called before each call to a Win32 function taking an OVLERAPPED* + // new_request is expected to be called before each call to a Win32 function taking an OVERLAPPED* // - which the caller expects to have their std::function invoked with the following signature: // void callback_function(OVERLAPPED* _overlapped) // @@ -174,10 +170,6 @@ class ctThreadIocp delete old_request; } - // - // No default c'tor - preventing zombie objects - // No copy c'tors - // ctThreadIocp() = delete; ctThreadIocp(const ctThreadIocp&) = delete; ctThreadIocp& operator=(const ctThreadIocp&) = delete; @@ -189,15 +181,15 @@ class ctThreadIocp PTP_CALLBACK_INSTANCE /*_instance*/, PVOID /*_context*/, PVOID _overlapped, - ULONG /*_ioresult*/, - ULONG_PTR /*_numberofbytestransferred*/, + ULONG /*_ioResult*/, + ULONG_PTR /*_numberOfBytesTransferred*/, PTP_IO /*_io*/) noexcept { // this code may look really odd // the Win32 TP APIs eat stack overflow exceptions and reuses the thread for the next TP request - // it is *not* expected that callers can/will harden their callback functions to be resilient to running out of stack at any momemnt + // it is *not* expected that callers can/will harden their callback functions to be resilient to running out of stack at any moment // since we *do* hit this in stress, and we face ugly lock-related breaks since an SEH was swallowed while a callback held a lock, - // we're working really hard to break and never let TP swalling SEH exceptions + // we're working really hard to break and never let TP swallowing SEH exceptions const EXCEPTION_POINTERS* exr = nullptr; __try { diff --git a/ctl/ctThreadpoolQueue.hpp b/ctl/ctThreadpoolQueue.hpp index 7545587..7545d8d 100644 --- a/ctl/ctThreadpoolQueue.hpp +++ b/ctl/ctThreadpoolQueue.hpp @@ -22,7 +22,7 @@ See the Apache Version 2.0 License for specific language governing permissions a namespace ctl { // forward-declare classes that can instantiate a ctThreadpoolQueueWaitableResult object -enum class ctThreadpoolGrowthPolicy +enum class ctThreadpoolGrowthPolicy : std::uint8_t { Growable, Flat @@ -156,7 +156,7 @@ class ctThreadpoolQueueWaitableResult final : public ctThreadpoolQueueWaitableRe TReturn m_result{}; DWORD m_internalError = NO_ERROR; - enum class RunStatus + enum class RunStatus : std::uint8_t { NotYetRun, Running, @@ -253,16 +253,16 @@ class ctThreadpoolQueue { if (m_tpHandle) { - // immediately release anyone waiting for these workitems not yet run + // immediately release anyone waiting for these work-items not yet run { const auto queueLock = m_lock.lock(); for (const auto& work : m_workItems) { // signal that these are canceled before we shut down the TP which they could be scheduled - if (const auto* pWaitableWorkitem = std::get_if(&work)) + if (const auto* pWaitableWorkItem = std::get_if(&work)) { - (*pWaitableWorkitem)->abort(); + (*pWaitableWorkItem)->abort(); } } diff --git a/ctl/ctTimer.hpp b/ctl/ctTimer.hpp index 333cba9..55267ba 100644 --- a/ctl/ctTimer.hpp +++ b/ctl/ctTimer.hpp @@ -22,7 +22,7 @@ namespace ctl {namespace ctTimer { namespace Details { /// /// InitOnce the QPF value as it won't change after the OS has booted - /// - hiding within an unnamed namesapce + /// - hiding within an unnamed namespace /// // ReSharper disable once CppZeroConstantCanBeReplacedWithNullptr static INIT_ONCE g_qpfInitOnce = INIT_ONCE_STATIC_INIT; diff --git a/ctl/ctWmiClassObject.hpp b/ctl/ctWmiClassObject.hpp index adaa09f..a0ea2e0 100644 --- a/ctl/ctWmiClassObject.hpp +++ b/ctl/ctWmiClassObject.hpp @@ -94,14 +94,14 @@ class ctWmiClassObject // // Not yet implemented // - /// method_iterator method_begin(bool _fLocalMethodsOnly = true) - /// { - /// return method_iterator(wbemClass, _fLocalMethodsOnly); - /// } - /// method_iterator method_end() noexcept - /// { - /// return method_iterator(); - /// } + // method_iterator method_begin(bool _fLocalMethodsOnly = true) + // { + // return method_iterator(wbemClass, _fLocalMethodsOnly); + // } + // method_iterator method_end() noexcept + // { + // return method_iterator(); + // } // A forward property_iterator class type to enable forward-traversing instances of the queried WMI provider class property_iterator @@ -140,13 +140,9 @@ class ctWmiClassObject swap(m_propertyType, rhs.m_propertyType); } - //////////////////////////////////////////////////////////////////////////////// - /// - /// accessors: - /// - dereference operators to access the property name - /// - explicit type() method to expose its CIM type - /// - //////////////////////////////////////////////////////////////////////////////// + // accessors: + // - dereference operators to access the property name + // - explicit type() method to expose its CIM type BSTR operator*() { if (m_index == c_endIteratorIndex) diff --git a/ctl/ctWmiEnumerate.hpp b/ctl/ctWmiEnumerate.hpp index e369b4c..51a7e8c 100644 --- a/ctl/ctWmiEnumerate.hpp +++ b/ctl/ctWmiEnumerate.hpp @@ -86,8 +86,8 @@ class ctWmiEnumerate bool operator==(const iterator&) const noexcept; bool operator!=(const iterator&) const noexcept; - iterator& operator++(); // preincrement - iterator operator++(int); // postincrement + iterator& operator++(); // pre-increment + iterator operator++(int); // post-increment iterator& operator+=(uint32_t); // increment by integer // iterator_traits @@ -170,8 +170,8 @@ class ctWmiEnumerate private: ctWmiService m_wbemServices; - // Marking wbemEnumerator mutabale to allow for const correctness of begin() and end() - // specifically, invoking Reset() is an implementation detail and should not affect external contracts + // Marking wbemEnumerator mutable to allow for const correctness of begin() and end() + // specifically, invoking Reset() is an implementation detail and should not affect external contracts mutable wil::com_ptr m_wbemEnumerator; }; @@ -193,14 +193,12 @@ inline bool ctWmiEnumerate::iterator::operator!=(const iterator& iter) const noe return !(*this == iter); } -// preincrement inline ctWmiEnumerate::iterator& ctWmiEnumerate::iterator::operator++() { increment(); return *this; } -// postincrement inline ctWmiEnumerate::iterator ctWmiEnumerate::iterator::operator++(int) { auto temp(*this); @@ -208,7 +206,6 @@ inline ctWmiEnumerate::iterator ctWmiEnumerate::iterator::operator++(int) return temp; } -// increment by integer inline ctWmiEnumerate::iterator& ctWmiEnumerate::iterator::operator+=(uint32_t inc) { for (auto loop = 0ul; loop < inc; ++loop) diff --git a/ctl/ctWmiInstance.hpp b/ctl/ctWmiInstance.hpp index f0c8576..e30fad6 100644 --- a/ctl/ctWmiInstance.hpp +++ b/ctl/ctWmiInstance.hpp @@ -40,10 +40,6 @@ class ctWmiInstance public: // Constructors: // - requires a IWbemServices object already connected to WMI - // - // - one c'tor creates an empty instance (if set later) - // - one c'tor takes the WMI class name to instantiate a new instance - // - one c'tor takes an existing IWbemClassObject instance explicit ctWmiInstance(ctWmiService service) noexcept : m_wbemServices(std::move(service)) { diff --git a/ctl/ctWmiPerformance.hpp b/ctl/ctWmiPerformance.hpp index 55d7d0f..b3017cb 100644 --- a/ctl/ctWmiPerformance.hpp +++ b/ctl/ctWmiPerformance.hpp @@ -34,54 +34,50 @@ See the Apache Version 2.0 License for specific language governing permissions a #include #include -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// Concepts for this class: -/// - WMI Classes expose performance counters through hi-performance WMI interfaces -/// - ctWmiPerformanceCounter exposes one counter within one WMI performance counter class -/// - Every performance counter object contains a 'Name' key field, uniquely identifying a 'set' of data points for that counter -/// - Counters are 'snapped' every one second, with the timeslot tracked with the data -/// -/// ctWmiPerformanceCounter is exposed to the user through factory functions defined per-counter class (ctSharedPerfCounter) -/// - the factory functions takes in the counter name that the user wants to capture data for -/// - the factory function has a template type matching the data type of the counter data for that counter name -/// -/// Internally, the factory function instantiates a ctWmiPerformanceCounterImpl: -/// - has 3 template arguments: -/// 1. The IWbem* interface used to enumerate instances of this performance class (either IWbemHiPerfEnum or IWbemClassObject) -/// 2. The IWbem* interface used to access data in perf instances of this performance class (either IWbemObjectAccess or IWbemClassObject) -/// 3. The data type of the values for the counter name being recorded -/// - has 2 function arguments -/// 1. The string value of the WMI class to be used -/// 2. The string value of the counter name to be recorded -/// -/// Methods exposed publicly off of ctWmiPerformanceCounter: -/// - add_filter(): allows the caller to only capture instances which match the parameter/value combination for that object -/// - reference_range() : takes an Instance Name by which to return values -/// -- returns begin/end iterators to reference the data -/// -/// ctWmiPerformanceCounter populates data by invoking a pure virtual function (update_counter_data) every one second. -/// - update_counter_data takes a boolean parameter: true will invoke the virtual function to update the data, false will clear the data. -/// That pure virtual function (ctWmiPerformanceCounterImpl::update_counter_data) refreshes its counter (through its template accessor interface) -/// - then iterates through each instance recorded for that counter and invokes add_instance() in the base class. -/// -/// add_instance() takes a WMI* of teh Accessor type: if that instance wasn't explicitly filtered out (through an instance_filter object), -/// - it looks to see if this is a new instance or if we have already been tracking that instance -/// - if new, we create a new ctWmiPerformanceCounterData object and add it to our counter_data -/// - if not new, we just add this object to the counter_data object that we already created -/// -/// There are 2 possible sets of WMI interfaces to access and enumerate performance data, these are defined in ctWmiPerformanceDataAccessor -/// - this is instantiated in ctWmiPerformanceCounterImpl as it knows the Access and Enum template types -/// -/// ctWmiPerformanceCounterData encapsulates the data points for one instance of one counter. -/// - exposes match() taking a string to check if it matches the instance it contains -/// - exposes add() taking both types of Access objects + a ULONGLONG time parameter to retrieve the data and add it to the internal map -/// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Concepts for this class: +// - WMI Classes expose performance counters through hi-performance WMI interfaces +// - ctWmiPerformanceCounter exposes one counter within one WMI performance counter class +// - Every performance counter object contains a 'Name' key field, uniquely identifying a 'set' of data points for that counter +// - Counters are 'snapped' every one second, with the timeslot tracked with the data +// +// ctWmiPerformanceCounter is exposed to the user through factory functions defined per-counter class (ctSharedPerfCounter) +// - the factory functions takes in the counter name that the user wants to capture data for +// - the factory function has a template type matching the data type of the counter data for that counter name +// +// Internally, the factory function instantiates a ctWmiPerformanceCounterImpl: +// - has 3 template arguments: +// 1. The IWbem* interface used to enumerate instances of this performance class (either IWbemHiPerfEnum or IWbemClassObject) +// 2. The IWbem* interface used to access data in perf instances of this performance class (either IWbemObjectAccess or IWbemClassObject) +// 3. The data type of the values for the counter name being recorded +// - has 2 function arguments +// 1. The string value of the WMI class to be used +// 2. The string value of the counter name to be recorded +// +// Methods exposed publicly off of ctWmiPerformanceCounter: +// - add_filter(): allows the caller to only capture instances which match the parameter/value combination for that object +// - reference_range() : takes an Instance Name by which to return values +// -- returns begin/end iterators to reference the data +// +// ctWmiPerformanceCounter populates data by invoking a pure virtual function (update_counter_data) every one second. +// - update_counter_data takes a boolean parameter: true will invoke the virtual function to update the data, false will clear the data. +// That pure virtual function (ctWmiPerformanceCounterImpl::update_counter_data) refreshes its counter (through its template accessor interface) +// - then iterates through each instance recorded for that counter and invokes add_instance() in the base class. +// +// add_instance() takes a WMI* of teh Accessor type: if that instance wasn't explicitly filtered out (through an instance_filter object), +// - it looks to see if this is a new instance or if we have already been tracking that instance +// - if new, we create a new ctWmiPerformanceCounterData object and add it to our counter_data +// - if not new, we just add this object to the counter_data object that we already created +// +// There are 2 possible sets of WMI interfaces to access and enumerate performance data, these are defined in ctWmiPerformanceDataAccessor +// - this is instantiated in ctWmiPerformanceCounterImpl as it knows the Access and Enum template types +// +// ctWmiPerformanceCounterData encapsulates the data points for one instance of one counter. +// - exposes match() taking a string to check if it matches the instance it contains +// - exposes add() taking both types of Access objects + a ULONGLONG time parameter to retrieve the data and add it to the internal map namespace ctl { - enum class ctWmiPerformanceCollectionType + enum class ctWmiPerformanceCollectionType : std::uint8_t { Detailed, MeanOnly, @@ -213,7 +209,7 @@ namespace ctl namespace details { inline wil::unique_variant ReadCounterFromWbemObjectAccess(_In_ IWbemObjectAccess* instance, - _In_ PCWSTR counterName) + _In_ PCWSTR counterName) { LONG propertyHandle{}; CIMTYPE propertyType{}; @@ -224,92 +220,88 @@ namespace ctl { case CIM_SINT32: case CIM_UINT32: - { - ULONG value{}; - THROW_IF_FAILED(instance->ReadDWORD(propertyHandle, &value)); - currentValue = ctWmiMakeVariant(value); - break; - } + { + ULONG value{}; + THROW_IF_FAILED(instance->ReadDWORD(propertyHandle, &value)); + currentValue = ctWmiMakeVariant(value); + break; + } case CIM_SINT64: case CIM_UINT64: - { - ULONGLONG value{}; - THROW_IF_FAILED(instance->ReadQWORD(propertyHandle, &value)); - currentValue = ctWmiMakeVariant(value); - break; - } + { + ULONGLONG value{}; + THROW_IF_FAILED(instance->ReadQWORD(propertyHandle, &value)); + currentValue = ctWmiMakeVariant(value); + break; + } case CIM_STRING: + { + constexpr long cimStringDefaultSize = 64; + std::wstring value(cimStringDefaultSize, L'\0'); + long valueSize = cimStringDefaultSize * sizeof(WCHAR); + long returnedSize{}; + auto hr = instance->ReadPropertyValue( + propertyHandle, + valueSize, + &returnedSize, + reinterpret_cast(value.data())); + if (WBEM_E_BUFFER_TOO_SMALL == hr) { - constexpr long cimStringDefaultSize = 64; - std::wstring value(cimStringDefaultSize, L'\0'); - long valueSize = cimStringDefaultSize * sizeof(WCHAR); - long returnedSize{}; - auto hr = instance->ReadPropertyValue( + valueSize = returnedSize; + value.resize(valueSize / sizeof(WCHAR)); + hr = instance->ReadPropertyValue( propertyHandle, valueSize, &returnedSize, reinterpret_cast(value.data())); - if (WBEM_E_BUFFER_TOO_SMALL == hr) - { - valueSize = returnedSize; - value.resize(valueSize / sizeof(WCHAR)); - hr = instance->ReadPropertyValue( - propertyHandle, - valueSize, - &returnedSize, - reinterpret_cast(value.data())); - } - THROW_IF_FAILED(hr); - currentValue = ctWmiMakeVariant(value.c_str()); - break; } + THROW_IF_FAILED(hr); + currentValue = ctWmiMakeVariant(value.c_str()); + break; + } default: THROW_HR_MSG(HRESULT_FROM_WIN32(ERROR_INVALID_DATA), - "ctWmiPerformance only supports data of type INT32, INT64, and BSTR: counter %ws is of type %u", - counterName, static_cast(propertyType)); + "ctWmiPerformance only supports data of type INT32, INT64, and BSTR: counter %ws is of type %u", + counterName, static_cast(propertyType)); } return currentValue; } - //////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// template class ctWmiPerformanceDataAccessor - /// - /// Refreshes performance data for the target specified based off the classname - /// - and the template types specified [the below are the only types supported]: - /// - /// Note: caller *MUST* provide thread safety - /// this class is not providing locking at this level - /// - /// Note: callers *MUST* guarantee connections with the WMI service stay connected - /// for the lifetime of this object [e.g. guaranteed ctWmiService is instantiated] - /// - /// Note: callers *MUST* guarantee that COM is CoInitialized on this thread before calling - /// - /// Note: the ctWmiPerformance class *will* retain WMI service instance - /// it's recommended to guarantee it stays alive - /// - /// Template typename options: - /// - /// typename TEnum == IWbemHiPerfEnum - /// - encapsulates the processing of IWbemHiPerfEnum instances of type _classname - /// - /// typename TEnum == IWbemClassObject - /// - encapsulates the processing of a single refreshable IWbemClassObject of type _classname - /// - /// typename TAccess == IWbemObjectAccess - /// - begin/end return an iterator to a vector of refreshed perf data - /// - Note: could be N number of instances - /// - /// typename TAccess == IWbemClassObject - /// - begin/end return an iterator to a vector of refreshed perf data - /// - Note: will only ever be a single instance - /// - //////////////////////////////////////////////////////////////////////////////////////////////////// + // template class ctWmiPerformanceDataAccessor + // + // Refreshes performance data for the target specified based off the classname + // - and the template types specified [the below are the only types supported]: + // + // Note: caller *MUST* provide thread safety + // this class is not providing locking at this level + // + // Note: callers *MUST* guarantee connections with the WMI service stay connected + // for the lifetime of this object [e.g. guaranteed ctWmiService is instantiated] + // + // Note: callers *MUST* guarantee that COM is CoInitialized on this thread before calling + // + // Note: the ctWmiPerformance class *will* retain WMI service instance + // it's recommended to guarantee it stays alive + // + // Template typename options: + // + // typename TEnum == IWbemHiPerfEnum + // - encapsulates the processing of IWbemHiPerfEnum instances of type _classname + // + // typename TEnum == IWbemClassObject + // - encapsulates the processing of a single refreshable IWbemClassObject of type _classname + // + // typename TAccess == IWbemObjectAccess + // - begin/end return an iterator to a vector of refreshed perf data + // - Note: could be N number of instances + // + // typename TAccess == IWbemClassObject + // - begin/end return an iterator to a vector of refreshed perf data + // - Note: will only ever be a single instance template class ctWmiPerformanceDataAccessor { @@ -317,16 +309,16 @@ namespace ctl using ctAccessIterator = typename std::vector::const_iterator; ctWmiPerformanceDataAccessor(ctWmiService wmi, const wil::com_ptr& config, - _In_ PCWSTR classname); + _In_ PCWSTR classname); ~ctWmiPerformanceDataAccessor() noexcept { clear(); } - /// - /// refreshes internal data with the latest performance data - /// + // + // refreshes internal data with the latest performance data + // void refresh(); [[nodiscard]] ctAccessIterator begin() const noexcept @@ -393,7 +385,7 @@ namespace ctl if (enumInstances.begin() == enumInstances.end()) { THROW_HR_MSG(HRESULT_FROM_WIN32(ERROR_NOT_FOUND), - "Failed to refresh a static instances of the WMI class %ws", classname); + "Failed to refresh a static instances of the WMI class %ws", classname); } const auto instance = *enumInstances.begin(); @@ -467,24 +459,20 @@ namespace ctl m_currentIterator = m_accessorObjects.end(); } - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Structure to track the performance data for each property desired for the instance being tracked - /// - /// typename T : the data type of the counter to be stored - /// - /// Note: callers *MUST* guarantee connections with the WMI service stay connected - /// for the lifetime of this object [e.g. guaranteed ctWmiService is instantiated] - /// Note: callers *MUST* guarantee that COM is CoInitialized on this thread before calling - /// Note: the ctWmiPerformance class *will* retain WMI service instance - /// it's recommended to guarantee it stays alive - /// - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Structure to track the performance data for each property desired for the instance being tracked + // + // typename T : the data type of the counter to be stored + // + // Note: callers *MUST* guarantee connections with the WMI service stay connected + // for the lifetime of this object [e.g. guaranteed ctWmiService is instantiated] + // Note: callers *MUST* guarantee that COM is CoInitialized on this thread before calling + // Note: the ctWmiPerformance class *will* retain WMI service instance + // it's recommended to guarantee it stays alive template class ctWmiPerformanceCounterData { private: - mutable wil::critical_section m_guardData{500}; + mutable wil::critical_section m_guardData{ 500 }; const ctWmiPerformanceCollectionType m_collectionType = ctWmiPerformanceCollectionType::Detailed; const std::wstring m_instanceName; const std::wstring m_counterName; @@ -688,12 +676,8 @@ namespace ctl return value; } - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// type for the callback implemented in all ctWmiPerformanceCounter classes - /// - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - enum class CallbackAction + // type for the callback implemented in all ctWmiPerformanceCounter classes + enum class CallbackAction : std::uint8_t { Start, Stop, @@ -704,26 +688,20 @@ namespace ctl using ctWmiPerformanceCallback = std::function; } // unnamed namespace - - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// class ctWmiPerformanceCounter - /// - The abstract base class contains the WMI-specific code which all templated instances will derive from - /// - Using public inheritance + protected members over composition as we need a common type which we can pass to - /// ctWmiPerformance - /// - Exposes the iterator class for users to traverse the data points gathered - /// - /// Note: callers *MUST* guarantee connections with the WMI service stay connected - /// for the lifetime of this object [e.g. guaranteed ctWmiService is instantiated] - /// Note: callers *MUST* guarantee that COM is CoInitialized on this thread before calling - /// Note: the ctWmiPerformance class *will* retain WMI service instance - /// it's recommended to guarantee it stays alive - /// - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // forward-declaration to reference ctWmiPerformance class ctWmiPerformance; + // class ctWmiPerformanceCounter + // - The abstract base class contains the WMI-specific code which all templated instances will derive from + // - Using public inheritance + protected members over composition as we need a common type which we can pass to + // ctWmiPerformance + // - Exposes the iterator class for users to traverse the data points gathered + // + // Note: callers *MUST* guarantee connections with the WMI service stay connected + // for the lifetime of this object [e.g. guaranteed ctWmiService is instantiated] + // Note: callers *MUST* guarantee that COM is CoInitialized on this thread before calling + // Note: the ctWmiPerformance class *will* retain WMI service instance + // it's recommended to guarantee it stays alive template class ctWmiPerformanceCounter { @@ -751,22 +729,16 @@ namespace ctl iterator() = default; ~iterator() noexcept = default; - //////////////////////////////////////////////////////////////////////////////// - /// - /// copy c'tor and copy assignment - /// move c'tor and move assignment - /// - //////////////////////////////////////////////////////////////////////////////// iterator(iterator&& i) noexcept : m_current(std::move(i.m_current)), - m_isEmpty(std::move(i.m_isEmpty)) + m_isEmpty(i.m_isEmpty) { } iterator& operator =(iterator&& i) noexcept { m_current = std::move(i.m_current); - m_isEmpty = std::move(i.m_isEmpty); + m_isEmpty = i.m_isEmpty; return *this; } @@ -863,9 +835,9 @@ namespace ctl ctWmiPerformanceCounter(ctWmiPerformanceCounter&&) = delete; ctWmiPerformanceCounter& operator=(ctWmiPerformanceCounter&&) = delete; - /// - /// *not* thread-safe: caller must guarantee sequential access to add_filter() - /// + // + // *not* thread-safe: caller must guarantee sequential access to add_filter() + // template void add_filter(_In_ PCWSTR counterName, V propertyValue) { @@ -875,10 +847,10 @@ namespace ctl m_instanceFilter.emplace_back(counterName, std::move(ctWmiMakeVariant(propertyValue))); } - /// - /// returns a begin/end pair of iterators that exposes data for each time-slice - /// - static classes will have a null instance name - /// + // + // returns a begin/end pair of iterators that exposes data for each time-slice + // - static classes will have a null instance name + // std::pair reference_range(_In_opt_ PCWSTR instanceName = nullptr) { FAIL_FAST_IF_MSG( @@ -895,7 +867,7 @@ namespace ctl if (std::end(m_counterData) == foundInstance) { // nothing matching that instance name - // return the end iterator (default c'tor == end) + // return the end iterator (default constructor == end) return std::pair(iterator(), iterator()); } @@ -973,7 +945,7 @@ namespace ctl wil::com_ptr m_configRefresher; std::vector m_instanceFilter; // Must lock access to counter_data - mutable wil::critical_section m_guardCounterData{500}; + mutable wil::critical_section m_guardCounterData{ 500 }; std::vector>> m_counterData; bool m_dataStopped = true; @@ -988,25 +960,25 @@ namespace ctl // the callback function must be no-except - it can't leak an exception to the caller // as it shouldn't break calling all other callbacks if one happens to fail an update return [this](const details::CallbackAction updateData) noexcept - { - try { - switch (updateData) + try { - case details::CallbackAction::Start: - m_dataStopped = false; - break; + switch (updateData) + { + case details::CallbackAction::Start: + m_dataStopped = false; + break; - case details::CallbackAction::Stop: - m_dataStopped = true; - break; + case details::CallbackAction::Stop: + m_dataStopped = true; + break; - case details::CallbackAction::Update: - // only the derived class has appropriate the accessor class to update the data - update_counter_data(); - break; + case details::CallbackAction::Update: + // only the derived class has appropriate the accessor class to update the data + update_counter_data(); + break; - case details::CallbackAction::Clear: + case details::CallbackAction::Clear: { FAIL_FAST_IF_MSG( !m_dataStopped, @@ -1019,12 +991,12 @@ namespace ctl } break; } + } } - } - CATCH_LOG() - // if failed to update the counter data this pass - // will try again the next timer callback - }; + CATCH_LOG() + // if failed to update the counter data this pass + // will try again the next timer callback + }; } // @@ -1046,7 +1018,7 @@ namespace ctl if (!fAddData) { fAddData = std::any_of(std::cbegin(m_instanceFilter), std::cend(m_instanceFilter), - [&](const auto& filter) { return filter == instance; }); + [&](const auto& filter) { return filter == instance; }); } // add the counter data for this instance if: @@ -1088,34 +1060,30 @@ namespace ctl } }; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// ctWmiPerformanceCounterImpl - /// - derived from the pure-virtual ctWmiPerformanceCounter class - /// shares the same data type template typename with the parent class - /// - /// Template typename details: - /// - /// - TEnum: the IWbem* type to refresh the performance data - /// - TAccess: the IWbem* type used to access the performance data once refreshed - /// - TData: the data type of the counter of the class specified in the c'tor - /// - /// Only 2 combinations currently supported: - /// : ctWmiPerformanceCounter - /// - refreshes N of instances of a counter - /// : ctWmiPerformanceCounter - /// - refreshes a single instance of a counter - /// - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // ctWmiPerformanceCounterImpl + // - derived from the pure-virtual ctWmiPerformanceCounter class + // shares the same data type template typename with the parent class + // + // Template typename details: + // + // - TEnum: the IWbem* type to refresh the performance data + // - TAccess: the IWbem* type used to access the performance data once refreshed + // - TData: the data type of the counter of the class specified in the c'tor + // + // Only 2 combinations currently supported: + // : ctWmiPerformanceCounter + // - refreshes N of instances of a counter + // : ctWmiPerformanceCounter + // - refreshes a single instance of a counter template class ctWmiPerformanceCounterImpl final : public ctWmiPerformanceCounter { public: ctWmiPerformanceCounterImpl(const ctWmiService& wmi, _In_ PCWSTR className, _In_ PCWSTR counterName, - const ctWmiPerformanceCollectionType collectionType) : + const ctWmiPerformanceCollectionType collectionType) : ctWmiPerformanceCounter(counterName, collectionType), m_accessor(wmi, this->access_refresher(), className) - // must qualify 'this' name lookup to access access_refresher since it's in the base class + // must qualify 'this' name lookup to access access_refresher since it's in the base class { } @@ -1128,17 +1096,17 @@ namespace ctl ctWmiPerformanceCounterImpl& operator=(ctWmiPerformanceCounterImpl&&) = delete; private: - /// - /// this concrete template class serves to capture the Enum and Access template types - /// - so can instantiate the appropriate accessor object + // + // this concrete template class serves to capture the Enum and Access template types + // - so can instantiate the appropriate accessor object details::ctWmiPerformanceDataAccessor m_accessor; - /// - /// invoked from the parent class to add data matching any/all filters - /// - /// private function required to be implemented from the abstract base class - /// - concrete class must pass back a function callback for adding data points for the specified counter - /// + // + // invoked from the parent class to add data matching any/all filters + // + // private function required to be implemented from the abstract base class + // - concrete class must pass back a function callback for adding data points for the specified counter + // void update_counter_data() override { const auto coInit = wil::CoInitializeEx(); @@ -1157,18 +1125,14 @@ namespace ctl } }; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// ctWmiPerformance - /// - /// class to register for and collect performance counters - /// - captures counter data into the ctWmiPerformanceCounter objects passed through add() - /// - /// CAUTION: - /// - do not access the ctWmiPerformanceCounter instances while between calling start() and stop() - /// - any iterators returned can be invalidated when more data is added on the next cycle - /// - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // ctWmiPerformance + // + // class to register for and collect performance counters + // - captures counter data into the ctWmiPerformanceCounter objects passed through add() + // + // CAUTION: + // - do not access the ctWmiPerformanceCounter instances while between calling start() and stop() + // - any iterators returned can be invalidated when more data is added on the next cycle class ctWmiPerformance final { public: @@ -1197,9 +1161,9 @@ namespace ctl { m_callbacks.push_back(perfCounterObject->register_callback()); auto revertCallback = wil::scope_exit([&]() noexcept - { - m_callbacks.pop_back(); - }); + { + m_callbacks.pop_back(); + }); THROW_IF_FAILED(m_configRefresher->AddRefresher(perfCounterObject->m_refresher.get(), 0, nullptr)); // dismiss scope-guard - successfully added refresher @@ -1286,7 +1250,7 @@ namespace ctl // and the ctWmiPerformance objects must be movable struct LockedData { - wil::critical_section m_lock{500}; + wil::critical_section m_lock{ 500 }; bool m_countersStarted = false; }; @@ -1321,7 +1285,7 @@ namespace ctl }; - enum class ctWmiEnumClassType + enum class ctWmiEnumClassType : std::uint8_t { Uninitialized, // created with ctMakeStaticPerfCounter @@ -1330,7 +1294,7 @@ namespace ctl Instance }; - enum class ctWmiEnumClassName + enum class ctWmiEnumClassName : std::uint8_t { Uninitialized, Process, @@ -1369,7 +1333,7 @@ namespace ctl template <> inline bool ctWmiPerformanceCounterProperties::PropertyNameExists(_In_ PCWSTR name) const noexcept - // NOLINT(bugprone-exception-escape) + // NOLINT(bugprone-exception-escape) { for (auto counter = 0ul; counter < m_ulongFieldNameCount; ++counter) { @@ -1384,7 +1348,7 @@ namespace ctl template <> inline bool ctWmiPerformanceCounterProperties::PropertyNameExists(_In_ PCWSTR name) const noexcept - // NOLINT(bugprone-exception-escape) + // NOLINT(bugprone-exception-escape) { for (auto counter = 0ul; counter < m_ulonglongFieldNameCount; ++counter) { @@ -1399,7 +1363,7 @@ namespace ctl template <> inline bool ctWmiPerformanceCounterProperties::PropertyNameExists(_In_ PCWSTR name) const noexcept - // NOLINT(bugprone-exception-escape) + // NOLINT(bugprone-exception-escape) { for (auto counter = 0ul; counter < m_stringFieldNameCount; ++counter) { @@ -1414,7 +1378,7 @@ namespace ctl template <> inline bool ctWmiPerformanceCounterProperties::PropertyNameExists(_In_ PCWSTR name) const noexcept - // NOLINT(bugprone-exception-escape) + // NOLINT(bugprone-exception-escape) { for (auto counter = 0ul; counter < m_stringFieldNameCount; ++counter) { @@ -1700,159 +1664,159 @@ namespace ctl inline const ctWmiPerformanceCounterProperties c_performanceCounterPropertiesArray[]{ { - ctWmiEnumClassType::Static, - ctWmiEnumClassName::Memory, - g_memoryCounter, - ARRAYSIZE(g_memoryUlongCounterNames), - g_memoryUlongCounterNames, - ARRAYSIZE(g_memoryUlonglongCounterNames), - g_memoryUlonglongCounterNames, - ARRAYSIZE(g_commonStringPropertyNames), - g_commonStringPropertyNames + .m_classType = ctWmiEnumClassType::Static, + .m_className = ctWmiEnumClassName::Memory, + .m_providerName = g_memoryCounter, + .m_ulongFieldNameCount = ARRAYSIZE(g_memoryUlongCounterNames), + .m_ulongFieldNames = g_memoryUlongCounterNames, + .m_ulonglongFieldNameCount = ARRAYSIZE(g_memoryUlonglongCounterNames), + .m_ulonglongFieldNames = g_memoryUlonglongCounterNames, + .m_stringFieldNameCount = ARRAYSIZE(g_commonStringPropertyNames), + .m_stringFieldNames = g_commonStringPropertyNames }, { - ctWmiEnumClassType::Instance, - ctWmiEnumClassName::Processor, - g_processorInformationCounter, - ARRAYSIZE(g_processorInformationUlongCounterNames), - g_processorInformationUlongCounterNames, - ARRAYSIZE(g_processorInformationUlonglongCounterNames), - g_processorInformationUlonglongCounterNames, - ARRAYSIZE(g_commonStringPropertyNames), - g_commonStringPropertyNames + .m_classType = ctWmiEnumClassType::Instance, + .m_className = ctWmiEnumClassName::Processor, + .m_providerName = g_processorInformationCounter, + .m_ulongFieldNameCount = ARRAYSIZE(g_processorInformationUlongCounterNames), + .m_ulongFieldNames = g_processorInformationUlongCounterNames, + .m_ulonglongFieldNameCount = ARRAYSIZE(g_processorInformationUlonglongCounterNames), + .m_ulonglongFieldNames = g_processorInformationUlonglongCounterNames, + .m_stringFieldNameCount = ARRAYSIZE(g_commonStringPropertyNames), + .m_stringFieldNames = g_commonStringPropertyNames }, { - ctWmiEnumClassType::Instance, - ctWmiEnumClassName::Process, - g_perfProcProcessCounter, - ARRAYSIZE(g_perfProcProcessUlongCounterNames), - g_perfProcProcessUlongCounterNames, - ARRAYSIZE(g_perfProcProcessUlonglongCounterNames), - g_perfProcProcessUlonglongCounterNames, - ARRAYSIZE(g_commonStringPropertyNames), - g_commonStringPropertyNames + .m_classType = ctWmiEnumClassType::Instance, + .m_className = ctWmiEnumClassName::Process, + .m_providerName = g_perfProcProcessCounter, + .m_ulongFieldNameCount = ARRAYSIZE(g_perfProcProcessUlongCounterNames), + .m_ulongFieldNames = g_perfProcProcessUlongCounterNames, + .m_ulonglongFieldNameCount = ARRAYSIZE(g_perfProcProcessUlonglongCounterNames), + .m_ulonglongFieldNames = g_perfProcProcessUlonglongCounterNames, + .m_stringFieldNameCount = ARRAYSIZE(g_commonStringPropertyNames), + .m_stringFieldNames = g_commonStringPropertyNames }, { - ctWmiEnumClassType::Instance, - ctWmiEnumClassName::NetworkAdapter, - g_tcpipNetworkAdapterCounter, - 0, - nullptr, - ARRAYSIZE(g_tcpipNetworkAdapterULongLongCounterNames), - g_tcpipNetworkAdapterULongLongCounterNames, - ARRAYSIZE(g_commonStringPropertyNames), - g_commonStringPropertyNames + .m_classType = ctWmiEnumClassType::Instance, + .m_className = ctWmiEnumClassName::NetworkAdapter, + .m_providerName = g_tcpipNetworkAdapterCounter, + .m_ulongFieldNameCount = 0, + .m_ulongFieldNames = nullptr, + .m_ulonglongFieldNameCount = ARRAYSIZE(g_tcpipNetworkAdapterULongLongCounterNames), + .m_ulonglongFieldNames = g_tcpipNetworkAdapterULongLongCounterNames, + .m_stringFieldNameCount = ARRAYSIZE(g_commonStringPropertyNames), + .m_stringFieldNames = g_commonStringPropertyNames }, { - ctWmiEnumClassType::Instance, - ctWmiEnumClassName::NetworkInterface, - g_tcpipNetworkInterfaceCounter, - 0, - nullptr, - ARRAYSIZE(g_tcpipNetworkInterfaceULongLongCounterNames), - g_tcpipNetworkInterfaceULongLongCounterNames, - ARRAYSIZE(g_commonStringPropertyNames), - g_commonStringPropertyNames + .m_classType = ctWmiEnumClassType::Instance, + .m_className = ctWmiEnumClassName::NetworkInterface, + .m_providerName = g_tcpipNetworkInterfaceCounter, + .m_ulongFieldNameCount = 0, + .m_ulongFieldNames = nullptr, + .m_ulonglongFieldNameCount = ARRAYSIZE(g_tcpipNetworkInterfaceULongLongCounterNames), + .m_ulonglongFieldNames = g_tcpipNetworkInterfaceULongLongCounterNames, + .m_stringFieldNameCount = ARRAYSIZE(g_commonStringPropertyNames), + .m_stringFieldNames = g_commonStringPropertyNames }, { - ctWmiEnumClassType::Static, - ctWmiEnumClassName::TcpipIpv4, - g_tcpipIpv4Counter, - ARRAYSIZE(g_tcpipIpULongCounterNames), - g_tcpipIpULongCounterNames, - 0, - nullptr, - ARRAYSIZE(g_commonStringPropertyNames), - g_commonStringPropertyNames + .m_classType = ctWmiEnumClassType::Static, + .m_className = ctWmiEnumClassName::TcpipIpv4, + .m_providerName = g_tcpipIpv4Counter, + .m_ulongFieldNameCount = ARRAYSIZE(g_tcpipIpULongCounterNames), + .m_ulongFieldNames = g_tcpipIpULongCounterNames, + .m_ulonglongFieldNameCount = 0, + .m_ulonglongFieldNames = nullptr, + .m_stringFieldNameCount = ARRAYSIZE(g_commonStringPropertyNames), + .m_stringFieldNames = g_commonStringPropertyNames }, { - ctWmiEnumClassType::Static, - ctWmiEnumClassName::TcpipIpv6, - g_tcpipIpv6Counter, - ARRAYSIZE(g_tcpipIpULongCounterNames), - g_tcpipIpULongCounterNames, - 0, - nullptr, - ARRAYSIZE(g_commonStringPropertyNames), - g_commonStringPropertyNames + .m_classType = ctWmiEnumClassType::Static, + .m_className = ctWmiEnumClassName::TcpipIpv6, + .m_providerName = g_tcpipIpv6Counter, + .m_ulongFieldNameCount = ARRAYSIZE(g_tcpipIpULongCounterNames), + .m_ulongFieldNames = g_tcpipIpULongCounterNames, + .m_ulonglongFieldNameCount = 0, + .m_ulonglongFieldNames = nullptr, + .m_stringFieldNameCount = ARRAYSIZE(g_commonStringPropertyNames), + .m_stringFieldNames = g_commonStringPropertyNames }, { - ctWmiEnumClassType::Static, - ctWmiEnumClassName::TcpipTcpv4, - g_tcpipTcpv4Counter, - ARRAYSIZE(g_tcpipTcpULongCounterNames), - g_tcpipTcpULongCounterNames, - 0, - nullptr, - ARRAYSIZE(g_commonStringPropertyNames), - g_commonStringPropertyNames + .m_classType = ctWmiEnumClassType::Static, + .m_className = ctWmiEnumClassName::TcpipTcpv4, + .m_providerName = g_tcpipTcpv4Counter, + .m_ulongFieldNameCount = ARRAYSIZE(g_tcpipTcpULongCounterNames), + .m_ulongFieldNames = g_tcpipTcpULongCounterNames, + .m_ulonglongFieldNameCount = 0, + .m_ulonglongFieldNames = nullptr, + .m_stringFieldNameCount = ARRAYSIZE(g_commonStringPropertyNames), + .m_stringFieldNames = g_commonStringPropertyNames }, { - ctWmiEnumClassType::Static, - ctWmiEnumClassName::TcpipTcpv6, - g_tcpipTcpv6Counter, - ARRAYSIZE(g_tcpipTcpULongCounterNames), - g_tcpipTcpULongCounterNames, - 0, - nullptr, - ARRAYSIZE(g_commonStringPropertyNames), - g_commonStringPropertyNames + .m_classType = ctWmiEnumClassType::Static, + .m_className = ctWmiEnumClassName::TcpipTcpv6, + .m_providerName = g_tcpipTcpv6Counter, + .m_ulongFieldNameCount = ARRAYSIZE(g_tcpipTcpULongCounterNames), + .m_ulongFieldNames = g_tcpipTcpULongCounterNames, + .m_ulonglongFieldNameCount = 0, + .m_ulonglongFieldNames = nullptr, + .m_stringFieldNameCount = ARRAYSIZE(g_commonStringPropertyNames), + .m_stringFieldNames = g_commonStringPropertyNames }, { - ctWmiEnumClassType::Static, - ctWmiEnumClassName::TcpipUdpv4, - g_tcpipUdpv4Counter, - ARRAYSIZE(g_tcpipUdpULongCounterNames), - g_tcpipUdpULongCounterNames, - 0, - nullptr, - ARRAYSIZE(g_commonStringPropertyNames), - g_commonStringPropertyNames + .m_classType = ctWmiEnumClassType::Static, + .m_className = ctWmiEnumClassName::TcpipUdpv4, + .m_providerName = g_tcpipUdpv4Counter, + .m_ulongFieldNameCount = ARRAYSIZE(g_tcpipUdpULongCounterNames), + .m_ulongFieldNames = g_tcpipUdpULongCounterNames, + .m_ulonglongFieldNameCount = 0, + .m_ulonglongFieldNames = nullptr, + .m_stringFieldNameCount = ARRAYSIZE(g_commonStringPropertyNames), + .m_stringFieldNames = g_commonStringPropertyNames }, { - ctWmiEnumClassType::Static, - ctWmiEnumClassName::TcpipUdpv6, - g_tcpipUdpv6Counter, - ARRAYSIZE(g_tcpipUdpULongCounterNames), - g_tcpipUdpULongCounterNames, - 0, - nullptr, - ARRAYSIZE(g_commonStringPropertyNames), - g_commonStringPropertyNames + .m_classType = ctWmiEnumClassType::Static, + .m_className = ctWmiEnumClassName::TcpipUdpv6, + .m_providerName = g_tcpipUdpv6Counter, + .m_ulongFieldNameCount = ARRAYSIZE(g_tcpipUdpULongCounterNames), + .m_ulongFieldNames = g_tcpipUdpULongCounterNames, + .m_ulonglongFieldNameCount = 0, + .m_ulonglongFieldNames = nullptr, + .m_stringFieldNameCount = ARRAYSIZE(g_commonStringPropertyNames), + .m_stringFieldNames = g_commonStringPropertyNames }, { - ctWmiEnumClassType::Static, - ctWmiEnumClassName::TcpipDiagnostics, - g_tcpipPerformanceDiagnosticsCounter, - ARRAYSIZE(g_tcpipPerformanceDiagnosticsULongCounterNames), - g_tcpipPerformanceDiagnosticsULongCounterNames, - 0, - nullptr, - ARRAYSIZE(g_commonStringPropertyNames), - g_commonStringPropertyNames + .m_classType = ctWmiEnumClassType::Static, + .m_className = ctWmiEnumClassName::TcpipDiagnostics, + .m_providerName = g_tcpipPerformanceDiagnosticsCounter, + .m_ulongFieldNameCount = ARRAYSIZE(g_tcpipPerformanceDiagnosticsULongCounterNames), + .m_ulongFieldNames = g_tcpipPerformanceDiagnosticsULongCounterNames, + .m_ulonglongFieldNameCount = 0, + .m_ulonglongFieldNames = nullptr, + .m_stringFieldNameCount = ARRAYSIZE(g_commonStringPropertyNames), + .m_stringFieldNames = g_commonStringPropertyNames }, { - ctWmiEnumClassType::Static, - ctWmiEnumClassName::WinsockBsp, - g_microsoftWinsockBspCounter, - ARRAYSIZE(g_microsoftWinsockBspuLongCounterNames), - g_microsoftWinsockBspuLongCounterNames, - 0, - nullptr, - ARRAYSIZE(g_commonStringPropertyNames), - g_commonStringPropertyNames + .m_classType = ctWmiEnumClassType::Static, + .m_className = ctWmiEnumClassName::WinsockBsp, + .m_providerName = g_microsoftWinsockBspCounter, + .m_ulongFieldNameCount = ARRAYSIZE(g_microsoftWinsockBspuLongCounterNames), + .m_ulongFieldNames = g_microsoftWinsockBspuLongCounterNames, + .m_ulonglongFieldNameCount = 0, + .m_ulonglongFieldNames = nullptr, + .m_stringFieldNameCount = ARRAYSIZE(g_commonStringPropertyNames), + .m_stringFieldNames = g_commonStringPropertyNames } }; @@ -1860,7 +1824,9 @@ namespace ctl template std::shared_ptr> ctMakeStaticPerfCounter( - ctWmiService wmi, _In_ PCWSTR className, _In_ PCWSTR counterName, + const ctWmiService& wmi, + _In_ PCWSTR className, + _In_ PCWSTR counterName, ctWmiPerformanceCollectionType collectionType = ctWmiPerformanceCollectionType::Detailed) { // 'static' WMI PerfCounters enumerate via IWbemClassObject and accessed/refreshed via IWbemClassObject @@ -1870,7 +1836,8 @@ namespace ctl template std::shared_ptr> ctMakeStaticPerfCounter( - PCWSTR className, PCWSTR counterName, + PCWSTR className, + PCWSTR counterName, const ctWmiPerformanceCollectionType collectionType = ctWmiPerformanceCollectionType::Detailed) { const ctWmiService wmi(L"root\\cimv2"); @@ -1879,7 +1846,9 @@ namespace ctl template std::shared_ptr> ctMakeInstancePerfCounter( - ctWmiService wmi, _In_ PCWSTR className, _In_ PCWSTR counterName, + const ctWmiService& wmi, + _In_ PCWSTR className, + _In_ PCWSTR counterName, ctWmiPerformanceCollectionType collectionType = ctWmiPerformanceCollectionType::Detailed) { // 'instance' WMI perf objects are enumerated through the IWbemHiPerfEnum interface and accessed/refreshed through the IWbemObjectAccess interface @@ -1889,7 +1858,8 @@ namespace ctl template std::shared_ptr> ctMakeInstancePerfCounter( - _In_ PCWSTR className, _In_ PCWSTR counterName, + _In_ PCWSTR className, + _In_ PCWSTR counterName, ctWmiPerformanceCollectionType collectionType = ctWmiPerformanceCollectionType::Detailed) { const ctWmiService wmi(L"root\\cimv2"); @@ -1898,7 +1868,9 @@ namespace ctl template std::shared_ptr> ctCreatePerfCounter( - ctWmiService wmi, ctWmiEnumClassName className, _In_ PCWSTR counterName, + const ctWmiService& wmi, + ctWmiEnumClassName className, + _In_ PCWSTR counterName, ctWmiPerformanceCollectionType collectionType = ctWmiPerformanceCollectionType::Detailed) { const ctWmiPerformanceCounterProperties* foundProperty = nullptr; @@ -1933,7 +1905,8 @@ namespace ctl template std::shared_ptr> ctCreatePerfCounter( - ctWmiEnumClassName className, _In_ PCWSTR counterName, + ctWmiEnumClassName className, + _In_ PCWSTR counterName, ctWmiPerformanceCollectionType collectionType = ctWmiPerformanceCollectionType::Detailed) { const ctWmiService wmi(L"root\\cimv2"); diff --git a/ctl/ctWmiVariant.hpp b/ctl/ctWmiVariant.hpp index 44e2598..0454afb 100644 --- a/ctl/ctWmiVariant.hpp +++ b/ctl/ctWmiVariant.hpp @@ -49,7 +49,7 @@ inline bool ctWmiReadFromVariant(_In_ const VARIANT* variant, _Out_ bool* value) return false; } THROW_HR_IF(E_INVALIDARG, V_VT(variant) != VT_BOOL); - *value = V_BOOL(variant); + *value = V_BOOL(variant) ? true : false; return true; } @@ -305,7 +305,7 @@ inline bool ctWmiReadFromVariant(_In_ const VARIANT* variant, _Inout_ std::wstri return true; } -// Even though VARIANTs support 64-bit integers, WMI passes them around as BSTRs +// Even though VARIANT's support 64-bit integers, WMI passes them around as BSTRs inline wil::unique_variant ctWmiMakeVariant(const unsigned long long value) { wil::unique_variant localVariant; @@ -327,7 +327,7 @@ inline bool ctWmiReadFromVariant(_In_ const VARIANT* variant, _Out_ unsigned lon return true; } -// Even though VARIANTs support 64-bit integers, WMI passes them around as BSTRs +// Even though VARIANT's support 64-bit integers, WMI passes them around as BSTRs inline wil::unique_variant ctWmiMakeVariant(_In_ const long long value) { wil::unique_variant localVariant; @@ -383,7 +383,7 @@ bool ctWmiReadFromVariant(_In_ const VARIANT* variant, _Inout_ std::vectorparray, reinterpret_cast(&iUnknownArray))); - const auto unaccessArray = wil::scope_exit([&]() noexcept { SafeArrayUnaccessData(variant->parray); }); + const auto unAccessArray = wil::scope_exit([&]() noexcept { SafeArrayUnaccessData(variant->parray); }); std::vector> tempData; for (auto loop = 0ul; loop < variant->parray->rgsabound[0].cElements; ++loop) @@ -432,7 +432,7 @@ inline bool ctWmiReadFromVariant(_In_ const VARIANT* variant, _Inout_ std::vecto BSTR* stringArray{}; THROW_IF_FAILED(::SafeArrayAccessData(variant->parray, reinterpret_cast(&stringArray))); - const auto unaccessArray = wil::scope_exit([&]() noexcept { SafeArrayUnaccessData(variant->parray); }); + const auto unAccessArray = wil::scope_exit([&]() noexcept { SafeArrayUnaccessData(variant->parray); }); std::vector tempData; for (auto loop = 0ul; loop < variant->parray->rgsabound[0].cElements; ++loop) @@ -478,7 +478,7 @@ inline bool ctWmiReadFromVariant(_In_ const VARIANT* variant, _Inout_ std::vecto uint32_t* intArray{}; THROW_IF_FAILED(::SafeArrayAccessData(variant->parray, reinterpret_cast(&intArray))); - const auto unaccessArray = wil::scope_exit([&]() noexcept { SafeArrayUnaccessData(variant->parray); }); + const auto unAccessArray = wil::scope_exit([&]() noexcept { SafeArrayUnaccessData(variant->parray); }); std::vector tempData; for (auto loop = 0ul; loop < variant->parray->rgsabound[0].cElements; ++loop) @@ -491,7 +491,7 @@ inline bool ctWmiReadFromVariant(_In_ const VARIANT* variant, _Inout_ std::vecto inline wil::unique_variant ctWmiMakeVariant(const std::vector& data) { - // WMI marshaler complaines type mismatch using VT_UI2 | VT_ARRAY, and VT_I4 | VT_ARRAY works fine. + // WMI marshaller complains type mismatch using VT_UI2 | VT_ARRAY, and VT_I4 | VT_ARRAY works fine. auto* const tempSafeArray = SafeArrayCreateVector(VT_I4, 0, static_cast(data.size())); THROW_IF_NULL_ALLOC(tempSafeArray); auto guardArray = wil::scope_exit([&]() noexcept { SafeArrayDestroy(tempSafeArray); }); @@ -518,7 +518,7 @@ inline wil::unique_variant ctWmiMakeVariant(const std::vector& d inline bool ctWmiReadFromVariant(_In_ const VARIANT* variant, _Inout_ std::vector* value) { - // WMI marshaler complaines type mismatch using VT_UI2 | VT_ARRAY, and VT_I4 | VT_ARRAY works fine. + // WMI marshaller complains type mismatch using VT_UI2 | VT_ARRAY, and VT_I4 | VT_ARRAY works fine. if (IsVariantEmptyOrNull(variant)) { return false; @@ -527,7 +527,7 @@ inline bool ctWmiReadFromVariant(_In_ const VARIANT* variant, _Inout_ std::vecto long* intArray{}; THROW_IF_FAILED(::SafeArrayAccessData(variant->parray, reinterpret_cast(&intArray))); - const auto unaccessArray = wil::scope_exit([&]() noexcept { SafeArrayUnaccessData(variant->parray); }); + const auto unAccessArray = wil::scope_exit([&]() noexcept { SafeArrayUnaccessData(variant->parray); }); std::vector tempData; for (auto loop = 0ul; loop < variant->parray->rgsabound[0].cElements; ++loop) @@ -574,7 +574,7 @@ inline bool ctWmiReadFromVariant(_In_ const VARIANT* variant, _Inout_ std::vecto unsigned char* charArray{}; THROW_IF_FAILED(::SafeArrayAccessData(variant->parray, reinterpret_cast(&charArray))); - const auto unaccessArray = wil::scope_exit([&]() noexcept { SafeArrayUnaccessData(variant->parray); }); + const auto unAccessArray = wil::scope_exit([&]() noexcept { SafeArrayUnaccessData(variant->parray); }); std::vector tempData; for (auto loop = 0ul; loop < variant->parray->rgsabound[0].cElements; ++loop) diff --git a/ctsPerf/ctsPerf.vcxproj b/ctsPerf/ctsPerf.vcxproj index c93f434..30af091 100644 --- a/ctsPerf/ctsPerf.vcxproj +++ b/ctsPerf/ctsPerf.vcxproj @@ -138,7 +138,7 @@ ..\ctl;%(AdditionalIncludeDirectories) false - /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /permissive- + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" /permissive- true StdCall stdcpplatest @@ -180,7 +180,7 @@ ..\ctl;%(AdditionalIncludeDirectories) false - /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /permissive- + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" /permissive- true StdCall false @@ -222,7 +222,7 @@ ..\ctl;%(AdditionalIncludeDirectories) false - /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /permissive- + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" /permissive- true StdCall false @@ -260,7 +260,7 @@ true - /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /Qvec-report:2 /Zc:strictStrings /Gw /permissive- + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" /Qvec-report:2 /Zc:strictStrings /Gw /permissive- true true StdCall @@ -307,7 +307,7 @@ Speed - /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /Zc:strictStrings /Gw /permissive- /Qfast_transcendentals /volatile:iso + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" /Zc:strictStrings /Gw /permissive- /Qfast_transcendentals /volatile:iso true true true @@ -356,7 +356,7 @@ Speed - /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /Zc:strictStrings /Gw /permissive- /Qfast_transcendentals /volatile:iso + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" /Zc:strictStrings /Gw /permissive- /Qfast_transcendentals /volatile:iso true true true diff --git a/ctsTraffic/ctsAcceptEx.cpp b/ctsTraffic/ctsAcceptEx.cpp index 316995d..99a1d4e 100644 --- a/ctsTraffic/ctsAcceptEx.cpp +++ b/ctsTraffic/ctsAcceptEx.cpp @@ -45,7 +45,7 @@ namespace ctsTraffic // --- operator() // --- the IOCP callback function // -// The 'accept handler' manages the interation between returning connections and posting more AcceptEx calls: +// The 'accept handler' manages the interaction between returning connections and posting more AcceptEx calls: // // - if operator() is called and a connection is ready, // --- set_socket() and complete() are invoked @@ -64,7 +64,7 @@ namespace ctsTraffic namespace details { // - // constant defining how many acceptex requests we want maintained per listener + // constant defining how many AcceptEx requests we want maintained per listener // constexpr uint32_t c_pendedAcceptRequests = 100; @@ -76,11 +76,7 @@ namespace details static void ctsAcceptExIoCompletionCallback(OVERLAPPED*, _In_ ctsAcceptSocketInfo* acceptInfo) noexcept; - //////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// struct to capture relevant details of an accepted connection - /// - //////////////////////////////////////////////////////////////////////////////////////////////////// + // struct to capture relevant details of an accepted connection struct ctsAcceptedConnection { wil::unique_socket m_acceptSocket; @@ -89,28 +85,24 @@ namespace details DWORD m_lastError = 0; }; - //////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Struct to track listening sockets - /// - must have a unique IOCP class for each listener - /// - //////////////////////////////////////////////////////////////////////////////////////////////////// + // Struct to track listening sockets + // - must have a unique IOCP class for each listener struct ctsListenSocketInfo { - // c'tor throws a wil::ResultException or bad_alloc on failure + // constructor throws a wil::ResultException or bad_alloc on failure explicit ctsListenSocketInfo(ctl::ctSockaddr addr) : m_sockaddr(std::move(addr)) { - wil::unique_socket tempsocket( + wil::unique_socket tempSocket( ctsConfig::CreateSocket(m_sockaddr.family(), SOCK_STREAM, IPPROTO_TCP, g_configSettings->SocketFlags)); - auto error = ctsConfig::SetPreBindOptions(tempsocket.get(), m_sockaddr); + auto error = ctsConfig::SetPreBindOptions(tempSocket.get(), m_sockaddr); if (error != 0) { THROW_WIN32_MSG(error, "ctsConfig::SetPreBindOptions (ctsAcceptEx)"); } - if (SOCKET_ERROR == bind(tempsocket.get(), m_sockaddr.sockaddr(), m_sockaddr.length())) + if (SOCKET_ERROR == bind(tempSocket.get(), m_sockaddr.sockaddr(), m_sockaddr.length())) { error = WSAGetLastError(); char addrBuffer[ctl::ctSockaddr::FixedStringLength]{}; @@ -118,16 +110,16 @@ namespace details THROW_WIN32_MSG(error, "bind %hs (ctsAcceptEx)", addrBuffer); } - if (SOCKET_ERROR == listen(tempsocket.get(), ctsConfig::GetListenBacklog())) + if (SOCKET_ERROR == listen(tempSocket.get(), ctsConfig::GetListenBacklog())) { error = WSAGetLastError(); THROW_WIN32_MSG(error, "listen (ctsAcceptEx)"); } - m_iocp = std::make_unique(tempsocket.get(), g_configSettings->pTpEnvironment); + m_iocp = std::make_unique(tempSocket.get(), g_configSettings->pTpEnvironment); // now save the socket after everything succeeded - m_listenSocket = std::move(tempsocket); + m_listenSocket = std::move(tempSocket); } ~ctsListenSocketInfo() noexcept @@ -148,17 +140,13 @@ namespace details std::vector> m_acceptSockets; }; - //////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// struct to track accepted sockets - /// - tracks the 'parent' listen socket structure - /// - preallocates the buffer to use for AcceptEx calls - /// - //////////////////////////////////////////////////////////////////////////////////////////////////// + // struct to track accepted sockets + // - tracks the 'parent' listen socket structure + // - pre-allocates the buffer to use for AcceptEx calls class ctsAcceptSocketInfo { public: - // c'tor throws wil::ResultException on failure + // constructor throws wil::ResultException on failure explicit ctsAcceptSocketInfo(const std::shared_ptr& listenSocket) noexcept : m_listeningSocketInfo(listenSocket) { @@ -167,7 +155,7 @@ namespace details ~ctsAcceptSocketInfo() noexcept = default; // attempts to post a new AcceptEx - internally tracks if succeeds or fails - void InitatiateAcceptEx(); + void InitiateAcceptEx(); // returns a ctsAcceptedConnection struct describing the result of an AcceptEx call // - must be called only after the previous AcceptEx call has completed its OVERLAPPED call @@ -229,14 +217,14 @@ namespace details auto listenSocketInfo(std::make_shared(addr)); PRINT_DEBUG_INFO(L"\t\tListening to %ws\n", addr.writeCompleteAddress().c_str()); // - // Add PendedAcceptRequests pended acceptex objects per listener + // Add PendedAcceptRequests pended AcceptEx objects per listener // for (auto acceptCounter = 0ul; acceptCounter < c_pendedAcceptRequests; ++acceptCounter) { auto acceptSocketInfo = std::make_shared(listenSocketInfo); listenSocketInfo->m_acceptSockets.push_back(acceptSocketInfo); // post AcceptEx on this socket - acceptSocketInfo->InitatiateAcceptEx(); + acceptSocketInfo->InitiateAcceptEx(); } // all successful - save this listen socket @@ -294,14 +282,7 @@ namespace details ctsAcceptExImpl& operator=(ctsAcceptExImpl&&) = delete; }; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// - /// Definitions of ctsAcceptSocketInfo members - /// - /// - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void ctsAcceptSocketInfo::InitatiateAcceptEx() + void ctsAcceptSocketInfo::InitiateAcceptEx() { const auto listeningSocketObject = m_listeningSocketInfo.lock(); if (!listeningSocketObject) @@ -323,7 +304,7 @@ namespace details IPPROTO_TCP, g_configSettings->SocketFlags)); - // since not inheriting from the listening socket, must explicity set options on the accept socket + // since not inheriting from the listening socket, must explicitly set options on the accept socket // - passing the listening address since that will be the local address of this accepted socket auto error = ctsConfig::SetPreBindOptions(newAcceptedSocket.get(), listeningSocketObject->m_sockaddr); if (error != 0) @@ -446,18 +427,18 @@ namespace details return returnDetails; } - ctsAcceptExImpl g_acceptExImpl; // NOLINT(clang-diagnostic-exit-time-destructors) + static ctsAcceptExImpl g_acceptExImpl; // NOLINT(clang-diagnostic-exit-time-destructors) // ReSharper disable once CppZeroConstantCanBeReplacedWithNullptr static INIT_ONCE g_acceptExImplInitOnce = INIT_ONCE_STATIC_INIT; - static BOOL CALLBACK ctsAcceptExImplInitFn(PINIT_ONCE, PVOID perror, PVOID*) noexcept try + static BOOL CALLBACK ctsAcceptExImplInitFn(PINIT_ONCE, PVOID pError, PVOID*) noexcept try { g_acceptExImpl.Start(); return TRUE; } catch (...) { - *static_cast(perror) = ctsConfig::PrintThrownException(); + *static_cast(pError) = ctsConfig::PrintThrownException(); return FALSE; } @@ -494,7 +475,7 @@ namespace details sharedSocket->SetLocalSockaddr(localAddr); } - // socket ownership was successfully transfered + // socket ownership was successfully transferred sharedSocket->SetSocket(acceptedSocket.m_acceptSocket.release()); sharedSocket->SetRemoteSockaddr(acceptedSocket.m_remoteAddr); sharedSocket->CompleteState(0); @@ -524,7 +505,7 @@ namespace details // // always attempt another AcceptEx // - acceptInfo->InitatiateAcceptEx(); + acceptInfo->InitiateAcceptEx(); } catch (...) { @@ -606,7 +587,7 @@ void ctsAcceptEx(const std::weak_ptr& weakSocket) noexcept sharedSocket->SetLocalSockaddr(localAddr); } - // transfering ownership to the ctsSocket + // transferring ownership to the ctsSocket sharedSocket->SetSocket(acceptedConnection.m_acceptSocket.release()); sharedSocket->SetRemoteSockaddr(acceptedConnection.m_remoteAddr); sharedSocket->CompleteState(0); diff --git a/ctsTraffic/ctsConfig.cpp b/ctsTraffic/ctsConfig.cpp index 1549b9c..2f84fb3 100644 --- a/ctsTraffic/ctsConfig.cpp +++ b/ctsTraffic/ctsConfig.cpp @@ -51,20 +51,13 @@ using namespace ctl; namespace ctsTraffic::ctsConfig { - //////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Settings is being defined in this cpp - it is extern'd from ctsConfig.h - /// - //////////////////////////////////////////////////////////////////////////////////////////////////// ctsConfigSettings* g_configSettings; - //////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Hiding the details of the raw data in an unnamed namespace to make it completely private - /// Free functions below provide proper access to this information - /// This design avoids having to pass a "config" object all over to share this information - /// - //////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Hiding the details of the raw data in an unnamed namespace to make it completely private + // Free functions below provide proper access to this information + // This design avoids having to pass a "config" object all over to share this information + // static wil::critical_section g_statusUpdateLock{ ctsConfigSettings::c_CriticalSectionSpinlock }; static wil::critical_section g_shutdownLock{ ctsConfigSettings::c_CriticalSectionSpinlock }; @@ -78,7 +71,6 @@ namespace ctsTraffic::ctsConfig constexpr uint32_t c_defaultTcpConnectionLimit = 8; constexpr uint32_t c_defaultUdpConnectionLimit = 1; constexpr uint32_t c_defaultConnectionThrottleLimit = 1000; - constexpr uint32_t c_defaultThreadpoolFactor = 2; static PTP_POOL g_threadPool = nullptr; static TP_CALLBACK_ENVIRON g_threadPoolEnvironment; @@ -149,11 +141,9 @@ namespace ctsTraffic::ctsConfig FAIL_FAST_IF(!InitOnceExecuteOnce(&g_configInitImpl, InitOnceConfigImpl, nullptr, nullptr)); } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// parses the configuration of the local system for options dependent on deployments - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // parses the configuration of the local system for options dependent on deployments + // static void CheckReuseUnicastPort() noexcept try { // Windows 10+ exposes a new socket option: SO_REUSE_UNICASTPORT @@ -214,7 +204,7 @@ namespace ctsTraffic::ctsConfig catch (...) { PRINT_DEBUG_INFO( - L"\t\tQuerying for NetAdapterRsc failed : 0x%x\n", wil::ResultFromCaughtException()); + L"\t\tQuerying for NetAdapterRsc failed : 0x%lx\n", wil::ResultFromCaughtException()); return {}; } @@ -245,7 +235,7 @@ namespace ctsTraffic::ctsConfig catch (...) { PRINT_DEBUG_INFO( - L"\t\tQuerying for NetAdapterLso failed : 0x%x\n", wil::ResultFromCaughtException()); + L"\t\tQuerying for NetAdapterLso failed : 0x%lx\n", wil::ResultFromCaughtException()); return {}; } @@ -273,7 +263,7 @@ namespace ctsTraffic::ctsConfig catch (...) { PRINT_DEBUG_INFO( - L"\t\tQuerying for NetAdapterRss failed : 0x%x\n", wil::ResultFromCaughtException()); + L"\t\tQuerying for NetAdapterRss failed : 0x%lx\n", wil::ResultFromCaughtException()); return {}; } @@ -385,19 +375,17 @@ namespace ctsTraffic::ctsConfig catch (...) { PRINT_DEBUG_INFO( - L"\t\tQuerying for MSFT_NetAdapterHardwareInfo failed : 0x%x\n", wil::ResultFromCaughtException()); + L"\t\tQuerying for MSFT_NetAdapterHardwareInfo failed : 0x%lx\n", wil::ResultFromCaughtException()); return {}; } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// parses the input argument to determine if it matches the expected parameter - /// if so, it returns a ptr to the corresponding parameter value - /// otherwise, returns nullptr - /// - /// throws invalid_parameter if something is obviously wrong - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // parses the input argument to determine if it matches the expected parameter + // if so, it returns a ptr to the corresponding parameter value + // otherwise, returns nullptr + // + // throws invalid_parameter if something is obviously wrong + // static const wchar_t* ParseArgument(_In_z_ const wchar_t* inputArgument, _In_z_ const wchar_t* expectedParam) { const wchar_t* paramEnd = inputArgument + wcslen(inputArgument); @@ -417,30 +405,28 @@ namespace ctsTraffic::ctsConfig return returnValue; } - //////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// ConvertToIntegral(wstring) - /// - /// Directly converts the *entire* contents of the passed in string to a numeric value - /// - the type of that numeric value being the template type specified - /// - /// e.g. - /// auto a = ConvertToIntegral(L"-1"); - /// auto b = ConvertToIntegral(L"0xa"); - /// auto a = ConvertToIntegral(L"0x123456789abcdef"); - /// auto a = ConvertToIntegral(L"999999999999999999"); - /// - /// NOTE: - /// - will *only* assume a string starting with "0x" to be converted as hexadecimal - /// if does not start with "0x", will assume as base-10 - /// - if an unsigned type is specified in the template and a negative number is entered, - /// will convert that to the "unsigned" version of that set of bits - /// e.g. - /// uint64_t test = ConvertToIntegral(L"-1"); - /// // test == 0xffffffffffffffff - /// - //////////////////////////////////////////////////////////////////////////////////////////////////// - int64_t ConvertToIntegralSigned(const wstring& inputString) + // + // ConvertToIntegral(wstring) + // + // Directly converts the *entire* contents of the passed in string to a numeric value + // - the type of that numeric value being the template type specified + // + // e.g. + // auto a = ConvertToIntegral(L"-1"); + // auto b = ConvertToIntegral(L"0xa"); + // auto a = ConvertToIntegral(L"0x123456789abcdef"); + // auto a = ConvertToIntegral(L"999999999999999999"); + // + // NOTE: + // - will *only* assume a string starting with "0x" to be converted as hexadecimal + // if does not start with "0x", will assume as base-10 + // - if an unsigned type is specified in the template and a negative number is entered, + // will convert that to the "unsigned" version of that set of bits + // e.g. + // uint64_t test = ConvertToIntegral(L"-1"); + // // test == 0xffffffffffffffff + // + static int64_t ConvertToIntegralSigned(const wstring& inputString) { auto returnValue = 0ll; size_t firstUnconvertedOffset = 0; @@ -460,7 +446,7 @@ namespace ctsTraffic::ctsConfig return returnValue; } - uint64_t ConvertToIntegralUnsigned(const wstring& inputString) + static uint64_t ConvertToIntegralUnsigned(const wstring& inputString) { auto returnValue = 0ull; size_t firstUnconvertedOffset = 0; @@ -539,11 +525,9 @@ namespace ctsTraffic::ctsConfig return ConvertToIntegralUnsigned(inputString); } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for the connect function to use - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for the connect function to use + // static void ParseForCreate(const vector&) { if (nullptr == g_configSettings->CreateFunction) @@ -553,16 +537,13 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for the connect function to use - /// - /// -conn:connect - /// -conn:wsaconnect - /// -conn:wsaconnectbyname - /// -conn:connectex (*default) - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for the connect function to use + // + // -conn:connect + // -conn:ConnectByName + // -conn:ConnectEx (*default) + // static void ParseForConnect(vector& args) { auto connectSpecified = false; @@ -622,15 +603,12 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for the accept function to use - /// - /// -acc:accept - /// -acc:wsaaccept - /// -acc:acceptex (*default) - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for the accept function to use + // + // -acc:accept + // -acc:acceptex (*default) + // static void ParseForAccept(vector& args) { g_configSettings->AcceptLimit = c_defaultAcceptExLimit; @@ -681,19 +659,17 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for the IO (read/write) function to use - /// -- only applicable to TCP - /// - /// -io:blocking - /// -io:nonblocking - /// -io:event - /// -io:iocp (*default) - /// -io:wsapoll - /// -io:rioiocp - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for the IO (read/write) function to use + // -- only applicable to TCP + // + // -io:blocking + // -io:nonblocking + // -io:event + // -io:iocp (*default) + // -io:wsapoll + // -io:rioiocp + // static void ParseForIoFunction(vector& args) { const auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -765,14 +741,12 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for the InlineCompletions setting to use - /// - /// -InlineCompletions:on - /// -InlineCompletions:off - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for the InlineCompletions setting to use + // + // -InlineCompletions:on + // -InlineCompletions:off + // static void ParseForInlineCompletions(vector& args) { const auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -800,14 +774,12 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for the MsgWaitAll setting to use - /// - /// -MsgWaitAll:on - /// -MsgWaitAll:off - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for the MsgWaitAll setting to use + // + // -MsgWaitAll:on + // -MsgWaitAll:off + // static void ParseForMsgWaitAll(vector& args) { const auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -839,14 +811,12 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for the L4 Protocol to limit to usage - /// - /// -Protocol:tcp - /// -Protocol:udp - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for the L4 Protocol to limit to usage + // + // -Protocol:tcp + // -Protocol:udp + // static void ParseForProtocol(vector& args) { const auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -879,13 +849,11 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for socket Options - /// - allows for more than one option to be set - /// -Options:] [-Options:<...>] - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for socket Options + // - allows for more than one option to be set + // -Options:] [-Options:<...>] + // static void ParseForOptions(vector& args) { for (;;) @@ -938,11 +906,9 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses the optional -KeepAliveValue:#### - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses the optional -KeepAliveValue:#### + // static void ParseForKeepAlive(vector& args) { const auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -970,17 +936,15 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for the wire-Protocol to use - /// --- these only apply to TCP - /// - /// -pattern:push - /// -pattern:pull - /// -pattern:pushpull - /// -pattern:duplex - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for the wire-Protocol to use + // --- these only apply to TCP + // + // -pattern:push + // -pattern:pull + // -pattern:pushpull + // -pattern:duplex + // static void ParseForIoPattern(vector& args) { auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -1128,7 +1092,6 @@ namespace ctsTraffic::ctsConfig // // Options for the UDP protocol // - foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool { const auto* const value = ParseArgument(parameter, L"-BitsPerSecond"); @@ -1228,22 +1191,20 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for IP address or machine name target to use - /// Can be comma-delimited if more than one - /// - /// 3 different parameters read address/name settings: - /// Supports specifying the parameter multiple times: - /// e.g. -target:machine-a -target:machine-b - /// - /// -listen: (address to listen on) - /// - specifying * == listen to all addresses - /// -target: (address to connect to) - /// -bind: (address to bind before connecting) - /// - specifying * == bind to all addresses (default) - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for IP address or machine name target to use + // Can be comma-delimited if more than one + // + // 3 different parameters read address/name settings: + // Supports specifying the parameter multiple times: + // e.g. -target:machine-a -target:machine-b + // + // -listen: (address to listen on) + // - specifying * == listen to all addresses + // -target: (address to connect to) + // -bind: (address to bind before connecting) + // - specifying * == bind to all addresses (default) + // static void ParseForAddress(vector& args) { // -listen: @@ -1453,13 +1414,11 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for the Port # to listen to/connect to - /// - /// -Port:## - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for the Port # to listen to/connect to + // + // -Port:## + // static void ParseForPort(vector& args) { const auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -1479,13 +1438,11 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for the Port # to listen to/connect to - /// - /// -PortScalability: - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for the Port # to listen to/connect to + // + // -PortScalability: + // static void ParseForPortScalability(vector& args) { const auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -1521,13 +1478,11 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for the connection limit [max number of connections to maintain] - /// - /// -connections:#### - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for the connection limit [max number of connections to maintain] + // + // -connections:#### + // static void ParseForConnections(vector& args) { const auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -1552,13 +1507,11 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for the server limit [max number of connections before the server exits] - /// - /// -ServerExitLimit:#### - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for the server limit [max number of connections before the server exits] + // + // -ServerExitLimit:#### + // static void ParseForServerExitLimit(vector& args) { const auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -1584,13 +1537,11 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for the connection limit [max number of connections to maintain] - /// - /// -ThrottleConnections:#### - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for the connection limit [max number of connections to maintain] + // + // -ThrottleConnections:#### + // static void ParseForThrottleConnections(vector& args) { const auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -1617,7 +1568,7 @@ namespace ctsTraffic::ctsConfig } template - void ReadRangeValues(_In_z_ const wchar_t* value, T& outLow, T& outHigh) + static void ReadRangeValues(_In_z_ const wchar_t* value, T& outLow, T& outHigh) { // a range was specified // - find the ',' the '[', and the ']' @@ -1650,14 +1601,12 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for the buffer size to push down per IO - /// - /// -buffer:#### - /// :[low,high] - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for the buffer size to push down per IO + // + // -buffer:#### + // :[low,high] + // static void ParseForBuffer(vector& args) { const auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -1697,14 +1646,12 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for the total transfer size in bytes per connection - /// - /// -transfer:#### - /// :[low,high] - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for the total transfer size in bytes per connection + // + // -transfer:#### + // :[low,high] + // static void ParseForTransfer(vector& args) { const auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -1738,13 +1685,11 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for the LocalPort # to bind for local connect - /// - /// -LocalPort:## - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for the LocalPort # to bind for local connect + // + // -LocalPort:## + // static void ParseForLocalPort(vector& args) { const auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -1775,13 +1720,11 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for an explicitly specified interface index for outgoing connections - /// - /// -IfIndex:## - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for an explicitly specified interface index for outgoing connections + // + // -IfIndex:## + // static void ParseForIfIndex(vector& args) { const auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -1804,15 +1747,13 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for Tcp throttling parameters - /// - /// -RateLimit:#### - /// :[low,high] - /// -RateLimitPeriod:#### - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for Tcp throttling parameters + // + // -RateLimit:#### + // :[low,high] + // -RateLimitPeriod:#### + // static void ParseForRateLimit(vector& args) { const auto foundRateLimit = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -1867,13 +1808,11 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for the total # of iterations - /// - /// -Iterations:#### - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for the total # of iterations + // + // -Iterations:#### + // static void ParseForIterations(vector& args) { const auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -1897,14 +1836,12 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for the verbosity level - /// - /// -ConsoleVerbosity:## <0-6> - /// -StatusUpdate:#### - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for the verbosity level + // + // -ConsoleVerbosity:## <0-6> + // -StatusUpdate:#### + // static void ParseForLogging(vector& args) { const auto foundVerbosity = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -2111,13 +2048,11 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Sets error policy - /// - /// -OnError: - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Sets error policy + // + // -OnError: + // static void ParseForError(vector& args) { const auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -2145,13 +2080,11 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Sets optional PrePostRecvs value - /// - /// -PrePostRecvs:##### - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Sets optional PrePostRecvs value + // + // -PrePostRecvs:##### + // static void ParseForPrePostRecvs(vector& args) { const auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -2176,13 +2109,11 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Sets optional PrePostSends value - /// - /// -PrePostSends:##### - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Sets optional PrePostSends value + // + // -PrePostSends:##### + // static void ParseForPrePostSends(vector& args) { const auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -2208,13 +2139,11 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Sets optional SO_RCVBUF value - /// - /// -RecvBufValue:##### - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Sets optional SO_RCVBUF value + // + // -RecvBufValue:##### + // static void ParseForRecvBufValue(vector& args) { const auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -2232,13 +2161,11 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Sets optional SO_SNDBUF value - /// - /// -SendBufValue:##### - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Sets optional SO_SNDBUF value + // + // -SendBufValue:##### + // static void ParseForSendBufValue(vector& args) { const auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -2256,13 +2183,11 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Sets an IP Compartment (routing domain) - /// - /// -Compartment: - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Sets an IP Compartment (routing domain) + // + // -Compartment: + // static void ParseForCompartment(vector& args) { const auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -2294,15 +2219,13 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Sets a threadpool environment for TP APIs to consume - /// - /// Configuring for max threads == number of processors * 2 - /// - /// currently not exposing this as a command-line parameter - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Sets a threadpool environment for TP APIs to consume + // + // Configuring for max threads == number of processors * 2 + // + // currently not exposing this as a command-line parameter + // static void ParseForThreadpool(vector& args) { auto setRunsLong = false; @@ -2357,18 +2280,16 @@ namespace ctsTraffic::ctsConfig g_configSettings->pTpEnvironment = &g_threadPoolEnvironment; } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for whether to verify buffer contents on receiver - /// - /// -verify: - /// (the old options were ) - /// - /// Note this controls if using a SharedBuffer across all IO or unique buffers - /// - if not validating data, won't waste memory creating buffers for every connection - /// - if validating data, must create buffers for every connection - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for whether to verify buffer contents on receiver + // + // -verify: + // (the old options were ) + // + // Note this controls if using a SharedBuffer across all IO or unique buffers + // - if not validating data, won't waste memory creating buffers for every connection + // - if validating data, must create buffers for every connection + // static void ParseForShouldVerifyBuffers(vector& args) { const auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -2398,13 +2319,11 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for how the client should close the connection with the server - /// - /// -shutdown: - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for how the client should close the connection with the server + // + // -shutdown: + // static void ParseForShutdown(vector& args) { const auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -2441,14 +2360,12 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for the optional maximum time to run - /// - /// -TimeLimit:## - /// -PauseAtEnd:## - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for the optional maximum time to run + // + // -TimeLimit:## + // -PauseAtEnd:## + // static void ParseForTimeLimit(vector& args) { const auto foundTimeLimitArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -2486,13 +2403,11 @@ namespace ctsTraffic::ctsConfig } } - ////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Parses for the optional CPU Group ID to set affinity - /// - /// -CpuSetGroupId:## - /// - ////////////////////////////////////////////////////////////////////////////////////////// + // + // Parses for the optional CPU Group ID to set affinity + // + // -CpuSetGroupId:## + // static void ParseForCpuSets(vector& args) { const auto foundCpuGroupIdArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool @@ -2514,11 +2429,9 @@ namespace ctsTraffic::ctsConfig } } - //////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Members within the ctsConfig namespace that can be accessed anywhere within ctsTraffic - /// - //////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Members within the ctsConfig namespace that can be accessed anywhere within ctsTraffic + // void PrintUsage(PrintUsageOption option) { ctsConfigInitOnce(); @@ -2945,7 +2858,7 @@ namespace ctsTraffic::ctsConfig } // forward declare this function called by Startup, but implemented later in this function - bool SetProcessDefaultCpuSets(); + static bool SetProcessDefaultCpuSets(); bool Startup(int argc, _In_reads_(argc) const wchar_t** argv) { ctsConfigInitOnce(); @@ -3330,7 +3243,7 @@ namespace ctsTraffic::ctsConfig if (!SetEvent(g_configSettings->CtrlCHandle)) { FAIL_FAST_MSG( - "SetEvent(%p) failed [%u] when trying to shutdown", + "SetEvent(%p) failed [%lu] when trying to shutdown", g_configSettings->CtrlCHandle, GetLastError()); } } @@ -3340,7 +3253,7 @@ namespace ctsTraffic::ctsConfig while (g_timePeriodRefCount > 0) { - timeEndPeriod(1); + (void)timeEndPeriod(1); --g_timePeriodRefCount; } } @@ -3448,14 +3361,12 @@ namespace ctsTraffic::ctsConfig } } - //////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Print* functions - /// - tracks what level of -verbose was specified - /// and prints to console accordingly - /// - //////////////////////////////////////////////////////////////////////////////////////////////////// - void PrintException(const wil::ResultException& e) noexcept + // + // Print* functions + // - tracks what level of -verbose was specified + // and prints to console accordingly + // + static void PrintException(const wil::ResultException& e) noexcept { ctsConfigInitOnce(); @@ -3475,7 +3386,7 @@ namespace ctsTraffic::ctsConfig PrintErrorInfo(errorString); } - void PrintException(const std::exception& e) noexcept + static void PrintException(const std::exception& e) noexcept { ctsConfigInitOnce(); @@ -3493,7 +3404,7 @@ namespace ctsTraffic::ctsConfig const auto hr = wil::ResultFromCaughtException(); if (g_breakOnError) { - FAIL_FAST_MSG("Fatal exception: 0x%x", hr); + FAIL_FAST_MSG("Fatal exception: 0x%lx", hr); } // ReSharper disable once CppDefaultCaseNotHandledInSwitchStatement @@ -3537,7 +3448,7 @@ namespace ctsTraffic::ctsConfig { const auto translation = ctString::format_message(why); const auto formattedString = wil::str_printf( - L"[exception] %ws%ws%ws%ws [%u / 0x%x - %ws]", + L"[exception] %ws%ws%ws%ws [%u / 0x%lx - %ws]", what ? L" " : L"", what ? what : L"", where ? L" at " : L"", @@ -3805,11 +3716,13 @@ namespace ctsTraffic::ctsConfig remoteAddr.writeCompleteAddress(wsaRemoteAddress); if (writeToConsole) { + constexpr auto * const tcpConnectionString = L"[%.3f] TCP connection established [%ws - %ws]\n"; + constexpr auto* const udpConnectionString = L"[%.3f] UDP connection established [%ws - %ws]\n"; + const auto* const connectionString = ProtocolType::TCP == g_configSettings->Protocol ? tcpConnectionString : udpConnectionString; + (void)fwprintf_s( stdout, - ProtocolType::TCP == g_configSettings->Protocol - ? L"[%.3f] TCP connection established [%ws - %ws]\n" - : L"[%.3f] UDP connection established [%ws - %ws]\n", + connectionString, GetStatusTimeStamp(), wsaLocalAddress, wsaRemoteAddress); @@ -3863,7 +3776,7 @@ namespace ctsTraffic::ctsConfig return; } - enum class ErrorType + enum class ErrorType : std::uint8_t { Success, NetworkError, @@ -3999,7 +3912,7 @@ namespace ctsTraffic::ctsConfig return; } - enum class ErrorType + enum class ErrorType : std::uint8_t { Success, NetworkError, @@ -4176,7 +4089,7 @@ namespace ctsTraffic::ctsConfig return; } - enum class ErrorType + enum class ErrorType : std::uint8_t { Success, NetworkError, @@ -4489,8 +4402,10 @@ namespace ctsTraffic::ctsConfig wstring formattedString; if (writeToConsole) { - wil::details::str_vprintf_nothrow(formattedString, text, argptr); - (void)fwprintf_s(stdout, L"%ws\n", formattedString.c_str()); + if (SUCCEEDED(wil::details::str_vprintf_nothrow(formattedString, text, argptr))) + { + (void)fwprintf_s(stdout, L"%ws\n", formattedString.c_str()); + } } if (g_errorLogger && !g_errorLogger->IsCsvFormat()) @@ -4499,11 +4414,15 @@ namespace ctsTraffic::ctsConfig { wil::details::str_vprintf_nothrow(formattedString, text, argptr); } - g_errorLogger->LogError( - wil::str_printf( - L"[%.3f] %ws\r\n", - GetStatusTimeStamp(), - formattedString.c_str()).c_str()); + + if (!formattedString.empty()) + { + g_errorLogger->LogError( + wil::str_printf( + L"[%.3f] %ws\r\n", + GetStatusTimeStamp(), + formattedString.c_str()).c_str()); + } } } catch (...) @@ -4512,12 +4431,10 @@ namespace ctsTraffic::ctsConfig va_end(argptr); } - //////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Get* - /// - accessor functions made public to retrieve configuration details - /// - //////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Get* + // - accessor functions made public to retrieve configuration details + // uint32_t GetBufferSize() noexcept { ctsConfigInitOnce(); @@ -4603,13 +4520,11 @@ namespace ctsTraffic::ctsConfig return static_cast(ctTimer::snap_qpc_as_msec() - g_configSettings->StartTimeMilliseconds) / 1000.0f; } - //////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Set*Options - /// - functions capturing any options that need to be set on a socket across different states - /// - currently only implementing pre-bind options - /// - //////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Set*Options + // - functions capturing any options that need to be set on a socket across different states + // - currently only implementing pre-bind options + // bool SetProcessDefaultCpuSets() { // default to CPU set zero @@ -4618,7 +4533,7 @@ namespace ctsTraffic::ctsConfig { settingsGroupId = g_configSettings->CpuGroupId.value(); } - PRINT_DEBUG_INFO(L"\t\tSetProcessDefaultCpuSets: trying to find CPUs on Group %lu\n", settingsGroupId); + PRINT_DEBUG_INFO(L"\t\tSetProcessDefaultCpuSets: trying to find CPUs on Group %u\n", settingsGroupId); typedef BOOL(__stdcall* pfn_SetProcessDefaultCpuSets)( HANDLE Process, @@ -4704,7 +4619,7 @@ namespace ctsTraffic::ctsConfig if (cpuSetIdsOnCpuGroupZero.empty()) { - PRINT_DEBUG_INFO(L"\t\tSetProcessDefaultCpuSets: No CPU IDs found on Group %lu\n", settingsGroupId); + PRINT_DEBUG_INFO(L"\t\tSetProcessDefaultCpuSets: No CPU IDs found on Group %u\n", settingsGroupId); return false; } @@ -4718,17 +4633,15 @@ namespace ctsTraffic::ctsConfig return false; } - PRINT_DEBUG_INFO(L"\t\tSetProcessDefaultCpuSets: SetProcessDefaultCpuSets set process affinity to all CPU IDs in Group %lu\n", settingsGroupId); + PRINT_DEBUG_INFO(L"\t\tSetProcessDefaultCpuSets: SetProcessDefaultCpuSets set process affinity to all CPU IDs in Group %u\n", settingsGroupId); return true; } - //////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Set*Options - /// - functions capturing any options that need to be set on a socket across different states - /// - currently only implementing pre-bind options - /// - //////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Set*Options + // - functions capturing any options that need to be set on a socket across different states + // - currently only implementing pre-bind options + // int SetPreBindOptions(SOCKET socket, const ctSockaddr& localAddress) noexcept { ctsConfigInitOnce(); @@ -4965,12 +4878,10 @@ namespace ctsTraffic::ctsConfig return 0; } - //////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// PrintSettings - /// - public function to write out to the console applied settings - /// - //////////////////////////////////////////////////////////////////////////////////////////////////// + // + // PrintSettings + // - public function to write out to the console applied settings + // void PrintSettings() { ctsConfigInitOnce(); @@ -5100,7 +5011,7 @@ namespace ctsTraffic::ctsConfig { settingString.append( wil::str_printf( - L"\tBuffer used for each IO request: %u [0x%x] bytes\n", + L"\tBuffer used for each IO request: %u [0x%lx] bytes\n", g_bufferSizeLow, g_bufferSizeLow)); } else @@ -5247,12 +5158,12 @@ namespace ctsTraffic::ctsConfig settingString.append( wil::str_printf( - L"\tConnection limit (maximum established connections): %u [0x%x]\n", + L"\tConnection limit (maximum established connections): %u [0x%lx]\n", g_configSettings->ConnectionLimit, g_configSettings->ConnectionLimit)); settingString.append( wil::str_printf( - L"\tConnection throttling rate (maximum pended connection attempts): %u [0x%x]\n", + L"\tConnection throttling rate (maximum pended connection attempts): %u [0x%lx]\n", g_configSettings->ConnectionThrottleLimit, g_configSettings->ConnectionThrottleLimit)); } diff --git a/ctsTraffic/ctsConfig.h b/ctsTraffic/ctsConfig.h index e03943b..cd6c0d7 100644 --- a/ctsTraffic/ctsConfig.h +++ b/ctsTraffic/ctsConfig.h @@ -28,7 +28,7 @@ See the Apache Version 2.0 License for specific language governing permissions a #include // // ** NOTE ** cannot include local project cts headers to avoid circular references -// - with the exception of ctsStatistics.hpp +// - except for ctsStatistics.hpp // - this header *can* be included here because it does not include any cts* headers // #include "ctsStatistics.hpp" @@ -50,21 +50,21 @@ namespace ctsTraffic // Declaring enum types in the ctsConfig namespace // - to be referenced by ctsConfig functions // - enum class ExitProcessType : LONG + enum class ExitProcessType : std::uint8_t { Running, Normal, Rude }; - enum class ProtocolType + enum class ProtocolType : std::uint8_t { NoProtocolSet, TCP, UDP }; - enum class TcpShutdownType + enum class TcpShutdownType : std::uint8_t { NoShutdownOptionSet, GracefulShutdown, @@ -72,7 +72,7 @@ namespace ctsTraffic Random }; - enum class IoPatternType + enum class IoPatternType : std::uint8_t { NoIoSet, Push, @@ -82,7 +82,7 @@ namespace ctsTraffic MediaStream }; - enum class StatusFormatting + enum class StatusFormatting : std::uint8_t { NoFormattingSet, ClearText, @@ -91,7 +91,7 @@ namespace ctsTraffic }; // cannot be an enum class and have the below operator overloads work correctly - enum OptionType + enum OptionType : std::uint16_t { NoOptionSet = 0x0000, LoopbackFastPath = 0x0001, @@ -107,11 +107,9 @@ namespace ctsTraffic // next enum = 0x0400 }; - //////////////////////////////////////////////////////////////////////////////////////////////////// // // custom operators for the OptionType enum (since it's to be used as a bitmask) // - //////////////////////////////////////////////////////////////////////////////////////////////////// // OR inline OptionType operator|(const OptionType& lhs, const OptionType& rhs) noexcept @@ -155,15 +153,13 @@ namespace ctsTraffic return static_cast(~static_cast(lhs)); } - //////////////////////////////////////////////////////////////////////////////////////////////////// // // Members within the ctsConfig namespace that can be accessed anywhere within ctsTraffic // - //////////////////////////////////////////////////////////////////////////////////////////////////// bool Startup(int argc, _In_reads_(argc) const wchar_t** argv); void Shutdown(ExitProcessType type) noexcept; - enum class PrintUsageOption + enum class PrintUsageOption : std::uint8_t { Default, Tcp, @@ -192,7 +188,7 @@ namespace ctsTraffic void __cdecl PrintSummary(_In_ _Printf_format_string_ PCWSTR text, ...) noexcept; void PrintStatusUpdate() noexcept; - void PrintErrorInfo(_In_ _Printf_format_string_ PCWSTR text, ...) noexcept; + void __cdecl PrintErrorInfo(_In_ _Printf_format_string_ PCWSTR text, ...) noexcept; void PrintErrorIfFailed(_In_ PCSTR what, uint32_t why) noexcept; // Override will always print to console regardless of settings (important if can't even start) void PrintErrorInfoOverride(_In_ PCWSTR text) noexcept; @@ -434,12 +430,10 @@ namespace ctsTraffic static constexpr DWORD c_CriticalSectionSpinlock = 200ul; }; - //////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Settings is defined in ctsConfig.cpp - /// - it's made available to all consumers of ctsConfig.h through extern - /// - //////////////////////////////////////////////////////////////////////////////////////////////////// + // + // ctsConfigSettings is defined in ctsConfig.cpp + // - it's made available to all consumers of ctsConfig.h through extern + // extern ctsConfigSettings* g_configSettings; SOCKET CreateSocket(int af, int type, int protocol, DWORD dwFlags); diff --git a/ctsTraffic/ctsConnectByName.cpp b/ctsTraffic/ctsConnectByName.cpp index ae7e3d3..d30545b 100644 --- a/ctsTraffic/ctsConnectByName.cpp +++ b/ctsTraffic/ctsConnectByName.cpp @@ -66,7 +66,7 @@ namespace ctsTraffic DWORD localAddrLength = localAddr.length(); DWORD remoteAddrLength = remoteAddr.length(); - PRINT_DEBUG_INFO(L"\t\tWSAConnectByName to %ws : %lu\n", targetAddr.c_str(), ctsConfig::g_configSettings->Port); + PRINT_DEBUG_INFO(L"\t\tWSAConnectByName to %ws : %u\n", targetAddr.c_str(), ctsConfig::g_configSettings->Port); if (!WSAConnectByNameW( socket, const_cast(targetAddr.c_str()), diff --git a/ctsTraffic/ctsIOPattern.cpp b/ctsTraffic/ctsIOPattern.cpp index ce98994..200bd6e 100644 --- a/ctsTraffic/ctsIOPattern.cpp +++ b/ctsTraffic/ctsIOPattern.cpp @@ -34,11 +34,11 @@ namespace ctsTraffic constexpr uint32_t c_bufferPatternSize = 0xffff + 0x1; // fill from 0x0000 to 0xffff static unsigned char g_bufferPattern[c_bufferPatternSize * 2]; // * 2 as unsigned short values are twice as large as unsigned char - /// SharedBuffer is a larger buffer with many copies of BufferPattern in it. This is what the various IO patterns - /// will be memcmp'ing against for validity checks. - /// - /// The buffers' sizes will be the constant "BufferPatternSize + ctsConfig::GetMaxBufferSize()", but we - /// need to wait for input parsing before we can set that. + // SharedBuffer is a larger buffer with many copies of BufferPattern in it. This is what the various IO patterns + // will be memcmp'ing against for validity checks. + // + // The buffers' sizes will be the constant "BufferPatternSize + ctsConfig::GetMaxBufferSize()", but we + // need to wait for input parsing before we can set that. static INIT_ONCE g_ctsIoPatternInitializer = INIT_ONCE_STATIC_INIT; static char* g_receiverSharedBuffer = nullptr; @@ -48,7 +48,7 @@ namespace ctsTraffic constexpr auto c_maxSupportedBytesInFlight = 0x1000000ul; static uint32_t g_maxNumberOfRioSendBuffers = 0; - BOOL CALLBACK InitOnceIoPatternCallback(PINIT_ONCE, PVOID, PVOID*) noexcept // NOLINT(bugprone-exception-escape) + static BOOL CALLBACK InitOnceIoPatternCallback(PINIT_ONCE, PVOID, PVOID*) noexcept // NOLINT(bugprone-exception-escape) { // first create the buffer pattern for (size_t fillSlot = 0; fillSlot < c_bufferPatternSize; ++fillSlot) @@ -60,10 +60,10 @@ namespace ctsTraffic g_maxNumberOfRioSendBuffers = c_maxSupportedBytesInFlight / ctsConfig::GetMinBufferSize() + 1; g_receiverSharedBuffer = static_cast(VirtualAlloc(nullptr, g_maximumBufferSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)); - FAIL_FAST_IF_MSG(!g_receiverSharedBuffer, "VirtualAlloc alloc failed: %u", GetLastError()); + FAIL_FAST_IF_MSG(!g_receiverSharedBuffer, "VirtualAlloc alloc failed: %lu", GetLastError()); g_senderSharedBuffer = static_cast(VirtualAlloc(nullptr, g_maximumBufferSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)); - FAIL_FAST_IF_MSG(!g_senderSharedBuffer, "VirtualAlloc alloc failed: %u", GetLastError()); + FAIL_FAST_IF_MSG(!g_senderSharedBuffer, "VirtualAlloc alloc failed: %lu", GetLastError()); // fill in this allocated buffer while we can write to it auto* protectedDestination = g_senderSharedBuffer; @@ -82,15 +82,17 @@ namespace ctsTraffic if (WI_IsFlagClear(ctsConfig::g_configSettings->SocketFlags, WSA_FLAG_REGISTERED_IO)) { DWORD oldSetting; - FAIL_FAST_IF_MSG(!VirtualProtect(g_senderSharedBuffer, g_maximumBufferSize, PAGE_READONLY, &oldSetting), "VirtualProtect failed: %u", GetLastError()); + FAIL_FAST_IF_MSG(!VirtualProtect(g_senderSharedBuffer, g_maximumBufferSize, PAGE_READONLY, &oldSetting), "VirtualProtect failed: %lu", GetLastError()); } return TRUE; } + // // Factory function to build known patterns // - can throw wil::ResultException on a Win32 error // - can throw exception on allocation failure + // shared_ptr ctsIoPattern::MakeIoPattern() { switch (ctsConfig::g_configSettings->IoPattern) @@ -242,9 +244,9 @@ namespace ctsTraffic } } - /// - /// requires that the caller has locked the socket - /// + // + // requires that the caller has locked the socket + // ctsTask ctsIoPattern::InitiateIo() noexcept { // make sure stats starts tracking IO at the first IO request @@ -346,22 +348,18 @@ namespace ctsTraffic return returnTask; } - //////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// CompleteIo - /// - /// requires that the caller has locked the socket - /// - /// updates its internal counters to prepare for the next IO request - /// - the fact that complete_io was called assumes that the IO was successful - /// - /// original_task : the task provided to the caller from initiate_io (or a copy of) - /// current_transfer : the number of bytes successfully transferred from the task - /// status_code: the return code from the prior IO operation [assumes a Win32 error code] - /// - /// Returns the current status of the IO operation on this socket - /// - //////////////////////////////////////////////////////////////////////////////////////////////////// + // + // updates the internal counters to prepare for the next IO request + // - the fact that complete_io was called assumes that the IO was successful + // + // - original_task: the task provided to the caller from initiate_io (or a copy of) + // - current_transfer: the number of bytes successfully transferred from the task + // - status_code: the return code from the prior IO operation [assumes a Win32 error code] + // + // - returns the current status of the IO operation on this socket + // + // requires that the caller has locked the socket + // ctsIoStatus ctsIoPattern::CompleteIo(const ctsTask& originalTask, uint32_t currentTransfer, uint32_t statusCode) noexcept // NOLINT(bugprone-exception-escape) { // preserve the initial state for the prior task @@ -396,24 +394,24 @@ namespace ctsTraffic break; case ctsTaskAction::FatalAbort: - PRINT_DEBUG_INFO(L"\t\tctsIOPattern : completing a FatalAbort (statusCode %lu)\n", statusCode); + PRINT_DEBUG_INFO(L"\t\tctsIOPattern : completing a FatalAbort (statusCode %u)\n", statusCode); UpdateLastError(c_statusErrorNotAllDataTransferred); break; case ctsTaskAction::Abort: - PRINT_DEBUG_INFO(L"\t\tctsIOPattern : completing an Abort (statusCode %lu)\n", statusCode); + PRINT_DEBUG_INFO(L"\t\tctsIOPattern : completing an Abort (statusCode %u)\n", statusCode); break; case ctsTaskAction::GracefulShutdown: // Fall-through to be processed like send or recv IO - PRINT_DEBUG_INFO(L"\t\tctsIOPattern : completing a GracefulShutdown (statusCode %lu)\n", statusCode); + PRINT_DEBUG_INFO(L"\t\tctsIOPattern : completing a GracefulShutdown (statusCode %u)\n", statusCode); [[fallthrough]]; case ctsTaskAction::HardShutdown: // GracefulShutdown falls through to this case - don't print HardShutdown for that case if (originalTask.m_ioAction == ctsTaskAction::HardShutdown) { // Fall-through to be processed like send or recv IO - PRINT_DEBUG_INFO(L"\t\tctsIOPattern : completing a HardShutdown (statusCode %lu)\n", statusCode); + PRINT_DEBUG_INFO(L"\t\tctsIOPattern : completing a HardShutdown (statusCode %u)\n", statusCode); } [[fallthrough]]; case ctsTaskAction::Recv: @@ -425,7 +423,7 @@ namespace ctsTraffic if (ctsTask::BufferType::TcpConnectionId == originalTask.m_bufferType || ctsTask::BufferType::CompletionMessage == originalTask.m_bufferType) { - // not verifying the buffer since it's the connection Id - but must complete the task to update the protocol + // not verifying the buffer since it's the connectionId - but must complete the task to update the protocol verifyIo = false; if (statusCode != NO_ERROR) @@ -481,7 +479,7 @@ namespace ctsTraffic { FAIL_FAST_IF_MSG( originalTask.m_expectedPatternOffset != m_recvPatternOffset, - "ctsIOPattern::complete_io() : ctsIOTask (%p) expected_pattern_offset (%lu) does not match the current pattern_offset (%lu)", + "ctsIOPattern::complete_io() : ctsIOTask (%p) expected_pattern_offset (%u) does not match the current pattern_offset (%u)", &originalTask, originalTask.m_expectedPatternOffset, m_recvPatternOffset); if (!VerifyBuffer(originalTask, currentTransfer)) @@ -698,11 +696,11 @@ namespace ctsTraffic FAIL_FAST_IF_MSG( m_sendPatternOffset >= c_bufferPatternSize, - "pattern_offset being too large (larger than BufferPatternSize %lu) means we might walk off the end of our shared buffer (dt ctsTraffic!ctsTraffic::ctsIOPattern %p)", + "pattern_offset being too large (larger than BufferPatternSize %u) means we might walk off the end of our shared buffer (dt ctsTraffic!ctsTraffic::ctsIOPattern %p)", c_bufferPatternSize, this); FAIL_FAST_IF_MSG( returnTask.m_bufferLength + returnTask.m_bufferOffset > g_maximumBufferSize, - "return_task (%p) for a Send request is specifying a buffer that is larger than the static SharedBufferSize (%lu) (dt ctsTraffic!ctsTraffic::ctsIOPattern %p)", + "return_task (%p) for a Send request is specifying a buffer that is larger than the static SharedBufferSize (%u) (dt ctsTraffic!ctsTraffic::ctsIOPattern %p)", &returnTask, g_maximumBufferSize, this); } else @@ -735,14 +733,13 @@ namespace ctsTraffic "pattern_offset being too large means we might walk off the end of our shared buffer (dt ctsTraffic!ctsTraffic::ctsIOPattern %p)", this); FAIL_FAST_IF_MSG( returnTask.m_bufferLength + returnTask.m_bufferOffset > verifiedNewBufferSize, - "return_task (%p) for a Recv request is specifying a buffer that is larger than buffer_size (%lu) (dt ctsTraffic!ctsTraffic::ctsIOPattern %p)", + "return_task (%p) for a Recv request is specifying a buffer that is larger than buffer_size (%u) (dt ctsTraffic!ctsTraffic::ctsIOPattern %p)", &returnTask, verifiedNewBufferSize, this); } return returnTask; } - // static bool ctsIoPattern::VerifyBuffer(const ctsTask& originalTask, uint32_t transferredBytes) noexcept { // only doing deep verification if the user asked us to @@ -780,23 +777,20 @@ namespace ctsTraffic const auto sharedSocket = m_parentSocket.lock(); if (!sharedSocket) { - // possible if we are in the d'tor of the pattern while the socket is being closed + // possible if we are in the destructor of the pattern while the socket is being closed // and one of the pattern's timer or callback threads is completing return {}; } return sharedSocket->AcquireLock(); } - /////////////////////////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// - Pull Pattern - /// -- TCP-only - /// -- The server pushes data (sends) - /// -- The client pulls data (receives) - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////////////////////////// + // + // ctsIoPatternPull + // - Pull Pattern + // - TCP-only + // - The server pushes data (sends) + // - The client pulls data (receives) + // ctsIoPatternPull::ctsIoPatternPull() : ctsIoPatternStatistics(ctsConfig::IsListening() ? 0 : ctsConfig::g_configSettings->PrePostRecvs), m_ioAction(ctsConfig::IsListening() ? ctsTaskAction::Send : ctsTaskAction::Recv), @@ -804,16 +798,12 @@ namespace ctsTraffic { } - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// virtual methods from the base class: - /// - assumes will be called under a CS from the base class - /// - /// tracking # of outstanding IO requests (configurable through the c'tor) - /// - /// Return an empty task when no more IO is needed - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// + // + // virtual methods from the base class: + // - assumes will be called under a CS from the base class + // - tracking # of outstanding IO requests (configurable through the constructor) + // - returns an empty task when no more IO is needed + // ctsTask ctsIoPatternPull::GetNextTaskFromPattern() noexcept { if (m_ioAction == ctsTaskAction::Recv && m_recvNeeded > 0) @@ -822,10 +812,10 @@ namespace ctsTraffic return CreateTrackedTask(m_ioAction); } - if (m_ioAction == ctsTaskAction::Send && GetIdealSendBacklog() > m_sendBytesInflight) + if (m_ioAction == ctsTaskAction::Send && GetIdealSendBacklog() > m_sendBytesInFlight) { const auto returnTask(CreateTrackedTask(m_ioAction)); - m_sendBytesInflight += returnTask.m_bufferLength; + m_sendBytesInFlight += returnTask.m_bufferLength; return returnTask; } @@ -839,7 +829,7 @@ namespace ctsTraffic if (ctsTaskAction::Send == task.m_ioAction) { m_statistics.m_bytesSent.AddNoLock(completedBytes); - m_sendBytesInflight -= completedBytes; + m_sendBytesInFlight -= completedBytes; } else if (ctsTaskAction::Recv == task.m_ioAction) { @@ -850,17 +840,13 @@ namespace ctsTraffic return ctsIoPatternError::NoError; } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// - Push Pattern - /// -- TCP-only - /// -- The client pushes data (send) - /// -- The server pulls data (recv) - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////////////////////////// + // + // ctsIoPatternPush + // - Push Pattern + // - TCP-only + // - The client pushes data (send) + // - The server pulls data (recv) + // ctsIoPatternPush::ctsIoPatternPush() : ctsIoPatternStatistics(ctsConfig::IsListening() ? ctsConfig::g_configSettings->PrePostRecvs : 0), m_ioAction(ctsConfig::IsListening() ? ctsTaskAction::Recv : ctsTaskAction::Send), @@ -868,16 +854,12 @@ namespace ctsTraffic { } - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// virtual methods from the base class: - /// - assumes will be called under a CS from the base class - /// - /// tracking # of outstanding IO requests (configurable through the c'tor) - /// - /// Return an empty task when no more IO is needed - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// + // + // virtual methods from the base class: + // - assumes will be called under a CS from the base class + // - tracking # of outstanding IO requests (configurable through the constructor) + // - returns an empty task when no more IO is needed + // ctsTask ctsIoPatternPush::GetNextTaskFromPattern() noexcept { if (m_ioAction == ctsTaskAction::Recv && m_recvNeeded > 0) @@ -886,10 +868,10 @@ namespace ctsTraffic return CreateTrackedTask(m_ioAction); } - if (m_ioAction == ctsTaskAction::Send && GetIdealSendBacklog() > m_sendBytesInflight) + if (m_ioAction == ctsTaskAction::Send && GetIdealSendBacklog() > m_sendBytesInFlight) { const auto returnTask(CreateTrackedTask(m_ioAction)); - m_sendBytesInflight += returnTask.m_bufferLength; + m_sendBytesInFlight += returnTask.m_bufferLength; return returnTask; } @@ -903,7 +885,7 @@ namespace ctsTraffic if (ctsTaskAction::Send == task.m_ioAction) { m_statistics.m_bytesSent.AddNoLock(completedBytes); - m_sendBytesInflight -= completedBytes; + m_sendBytesInFlight -= completedBytes; } else if (ctsTaskAction::Recv == task.m_ioAction) { @@ -914,21 +896,17 @@ namespace ctsTraffic return ctsIoPatternError::NoError; } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// - PushPull Pattern - /// -- TCP-only - /// -- The client pushes data in 'segments' - /// -- The server pulls data in 'segments' - /// -- At each segment, roles swap (pusher/puller) - /// - /// -- Currently not supporting concurrent IO via ctsConfig::GetConcurrentIoCount() - /// as we need precise controls when to flip from send -> recv -> send - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////////////////////////// + // + // ctsIoPatternPushPull + // - PushPull Pattern + // - TCP-only + // - The client pushes data in 'segments' + // - The server pulls data in 'segments' + // - At each segment, roles swap (pusher/puller) + // + // - Currently not supporting concurrent IO via ctsConfig::GetConcurrentIoCount() + // as we need precise controls when to flip from send -> recv -> send + // ctsIoPatternPushPull::ctsIoPatternPushPull() : ctsIoPatternStatistics(1), // currently not supporting >1 concurrent IO requests m_pushSegmentSize(ctsConfig::g_configSettings->PushBytes), @@ -938,16 +916,12 @@ namespace ctsTraffic { } - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// virtual methods from the base class: - /// - assumes will be called under a CS from the base class - /// - /// tracks if sending or receiving in the IO flow - /// - /// Return an empty task when no more IO is needed - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// + // + // virtual methods from the base class: + // - assumes will be called under a CS from the base class + // - tracks if sending or receiving in the IO flow + // - returns an empty task when no more IO is needed + // ctsTask ctsIoPatternPushPull::GetNextTaskFromPattern() noexcept { uint32_t segmentSize{}; @@ -963,7 +937,7 @@ namespace ctsTraffic FAIL_FAST_IF_MSG( m_intraSegmentTransfer >= segmentSize, - "Invalid ctsIOPatternPushPull state: intra_segment_transfer (%lu), segment_size (%lu)", + "Invalid ctsIOPatternPushPull state: intra_segment_transfer (%u), segment_size (%u)", m_intraSegmentTransfer, segmentSize); if (m_ioNeeded) @@ -1012,7 +986,7 @@ namespace ctsTraffic FAIL_FAST_IF_MSG( m_intraSegmentTransfer > segmentSize, - "Invalid ctsIOPatternPushPull state: intra_segment_transfer (%lu), segment_size (%lu)", + "Invalid ctsIOPatternPushPull state: intra_segment_transfer (%u), segment_size (%u)", m_intraSegmentTransfer, segmentSize); if (segmentSize == m_intraSegmentTransfer) @@ -1024,16 +998,12 @@ namespace ctsTraffic return ctsIoPatternError::NoError; } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// - Concurrent Pattern - /// -- TCP-only - /// -- The client and server both send and receive data concurrently - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////////////////////////// + // + // ctsIoPatternDuplex + // - Concurrent Pattern + // - TCP-only + // - The client and server both send and receive data concurrently + // ctsIoPatternDuplex::ctsIoPatternDuplex() noexcept : ctsIoPatternStatistics(ctsConfig::g_configSettings->PrePostRecvs), m_recvNeeded(ctsConfig::g_configSettings->PrePostRecvs) @@ -1056,16 +1026,12 @@ namespace ctsTraffic GetTotalTransfer()); } - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// virtual methods from the base class: - /// - assumes will be called under a CS from the base class - /// - /// tracks if sending or receiving in the IO flow - /// - /// Return an empty task when no more IO is needed - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// + // + // virtual methods from the base class: + // - assumes will be called under a CS from the base class + // - tracks if sending or receiving in the IO flow + // - returns an empty task when no more IO is needed + // ctsTask ctsIoPatternDuplex::GetNextTaskFromPattern() noexcept { ctsTask returnTask; @@ -1084,7 +1050,7 @@ namespace ctsTraffic m_remainingRecvBytes -= returnTask.m_bufferLength; --m_recvNeeded; } - else if (m_remainingSendBytes > 0 && GetIdealSendBacklog() > m_sendBytesInflight) + else if (m_remainingSendBytes > 0 && GetIdealSendBacklog() > m_sendBytesInFlight) { // for very large transfers, we need to ensure our SafeInt doesn't overflow when it's cast // to uint32_t when passed to tracked_task() @@ -1093,7 +1059,7 @@ namespace ctsTraffic static_cast(m_remainingSendBytes); returnTask = CreateTrackedTask(ctsTaskAction::Send, maxRemainingBytes); m_remainingSendBytes -= returnTask.m_bufferLength; - m_sendBytesInflight += returnTask.m_bufferLength; + m_sendBytesInFlight += returnTask.m_bufferLength; } else { @@ -1112,7 +1078,7 @@ namespace ctsTraffic case ctsTaskAction::Send: { m_statistics.m_bytesSent.AddNoLock(completedBytes); - m_sendBytesInflight -= completedBytes; + m_sendBytesInFlight -= completedBytes; // first, we need to adjust the total back from our over-subscription guard when this task was created m_remainingSendBytes += task.m_bufferLength; @@ -1139,19 +1105,15 @@ namespace ctsTraffic return ctsIoPatternError::NoError; } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// - ctsIOPatternMediaStream (Server) Pattern - /// -- UDP-only - /// -- The server sends data at a specified rate - /// -- The client receives data continuously - /// After a 'buffer period' of data has been received, - /// The client starts as timer to 'process' a time-slice of data - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////////////////////////// + // + // ctsIoPatternMediaStreamServer + // - ctsIOPatternMediaStream (Server) Pattern + // - UDP-only + // - The server sends data at a specified rate + // - The client receives data continuously + // After a 'buffer period' of data has been received, + // The client starts as timer to 'process' a time-slice of data + // ctsIoPatternMediaStreamServer::ctsIoPatternMediaStreamServer() noexcept : ctsIoPatternStatistics(1), // the pattern will use the recv writeable-buffer for sending a connection ID m_frameSizeBytes(ctsConfig::GetMediaStream().FrameSizeBytes), diff --git a/ctsTraffic/ctsIOPattern.h b/ctsTraffic/ctsIOPattern.h index e7671ee..48d70ec 100644 --- a/ctsTraffic/ctsIOPattern.h +++ b/ctsTraffic/ctsIOPattern.h @@ -32,13 +32,9 @@ namespace ctsTraffic // cannot include its header in this header as there will be a circular reference class ctsSocket; -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// Possible status values returned to the caller upon completing IO -/// - on failure, these codes can be reported as errors back to the caller -/// -//////////////////////////////////////////////////////////////////////////////////////////////////// -enum class ctsIoStatus +// Possible status values returned to the caller upon completing IO +// - on failure, these codes can be reported as errors back to the caller +enum class ctsIoStatus : std::uint8_t { ContinueIo, CompletedIo, @@ -78,22 +74,14 @@ class ctsIoPattern } } - /// - /// Helper factory to build known patterns - /// + // Helper factory to build known patterns static std::shared_ptr MakeIoPattern(); - /// - /// Making available the shared buffer used for sends and recvs - /// + // Making available the shared buffer used for sends and recvs static char* AccessSharedBuffer() noexcept; - /// - /// d'tor must be virtual as this is a base pure virtual class - /// + // destructor must be virtual as this is a base pure virtual class virtual ~ctsIoPattern() noexcept = default; - /// - /// Exposing statistics members publicly to ctsSocket - /// + // Exposing statistics members publicly to ctsSocket virtual void PrintStatistics(const ctl::ctSockaddr& localAddr, const ctl::ctSockaddr& remoteAddr) noexcept = 0; virtual void PrintTcpInfo(const ctl::ctSockaddr& localAddr, const ctl::ctSockaddr& remoteAddr, SOCKET socket) noexcept = 0; @@ -132,30 +120,28 @@ class ctsIoPattern return m_receivingRioBufferIds.size() + m_sendingRioBufferIds.size() + 2; } - /// - /// none of these *_io functions can throw - /// failures are critical and will RaiseException to be debugged - /// - the task given by initiate_io should be returned through complete_io - /// (or a copy of that task) - /// - /// Callers access initiate_io() to retrieve a ctsIOTask object for the next IO operation - /// - they are expected to retain that ctsIOTask object until the IO operation completes - /// - at which time they pass it back to complete_io() - /// - /// initiate_io() can be called repeatedly by the caller if they want overlapping IO calls - /// - without forced to wait for complete_io() for the next IO request - /// - /// complete_io() should be called for every returned initiate_io with the following: - /// _task : the ctsIOTask that was provided to perform - /// _current_transfer : the number of bytes successfully transferred from the task - /// _status_code: the return code from the prior IO operation [assumes a Win32 error code] - /// + // + // none of these *_io functions can throw + // failures are critical and will RaiseException to be debugged + // - the task given by initiate_io should be returned through complete_io + // (or a copy of that task) + // + // Callers access initiate_io() to retrieve a ctsIOTask object for the next IO operation + // - they are expected to retain that ctsIOTask object until the IO operation completes + // - at which time they pass it back to complete_io() + // + // initiate_io() can be called repeatedly by the caller if they want overlapping IO calls + // - without forced to wait for complete_io() for the next IO request + // + // complete_io() should be called for every returned initiate_io with the following: + // _task : the ctsIOTask that was provided to perform + // _current_transfer : the number of bytes successfully transferred from the task + // _status_code: the return code from the prior IO operation [assumes a Win32 error code] + // [[nodiscard]] ctsTask InitiateIo() noexcept; ctsIoStatus CompleteIo(const ctsTask& originalTask, uint32_t currentTransfer, uint32_t statusCode) noexcept; // NOLINT(bugprone-exception-escape) - /// no default c'tor ctsIoPattern() = delete; - /// no copy c'tor or copy assignment ctsIoPattern(const ctsIoPattern&) = delete; ctsIoPattern& operator=(const ctsIoPattern&) = delete; ctsIoPattern(ctsIoPattern&&) = delete; @@ -182,21 +168,19 @@ class ctsIoPattern // - *not* setting the private ctsIOTask::tracked_io property ctsTask CreateNewTask(ctsTaskAction action, uint32_t maxTransfer) noexcept; - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Private method which must be implemented by the derived interface (the IO pattern) - /// - /// ctsIOTask GetNextTaskFromPattern() - /// - must return a ctsIOTask returned from CreateTrackedTask or CreateUntrackedTask - /// - /// ctsIoPatternError CompleteTaskBackToPattern(const ctsIOTask&, uint32_t currentTransfer) noexcept - /// - a notification to the derived class over what task completed - /// - ctsIOTask argument: the ctsIOTask which it previously returned from GetNextTask() - /// - uint32_t argument: the # of bytes actually transferred - /// - cannot throw [if it fails, it must RaiseException to debug] - /// - returns a uint32_t back to the base class to indicate errors - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Private method which must be implemented by the derived interface (the IO pattern) + // + // ctsIOTask GetNextTaskFromPattern() + // - must return a ctsIOTask returned from CreateTrackedTask or CreateUntrackedTask + // + // ctsIoPatternError CompleteTaskBackToPattern(const ctsIOTask&, uint32_t currentTransfer) noexcept + // - a notification to the derived class over what task completed + // - ctsIOTask argument: the ctsIOTask which it previously returned from GetNextTask() + // - uint32_t argument: the # of bytes actually transferred + // - cannot throw [if it fails, it must RaiseException to debug] + // - returns a uint32_t back to the base class to indicate errors + // virtual ctsTask GetNextTaskFromPattern() = 0; virtual ctsIoPatternError CompleteTaskBackToPattern(const ctsTask&, uint32_t currentTransfer) noexcept = 0; @@ -218,12 +202,14 @@ class ctsIoPattern std::optional m_burstCount; std::optional m_burstDelay; + // // recv buffers to return to the caller // - tracking sending buffers separate from receiving buffers // since sending buffers will have a test pattern written to it (thus send buffers can be static) // For supporting multiple recv calls, allocating a larger buffer to contain all recv requests - // - as well as a vector to contain the multiple ptrs to each buffer + // - as well as a vector to contain the multiple pointers to each buffer // When needing to dynamically allocate, containing a vector to hold the bytes + // std::vector m_recvBufferFreeList; std::vector m_recvBufferContainer; std::array m_completionMessageBuffer{}; @@ -289,43 +275,29 @@ class ctsIoPattern uint32_t m_lastError = c_statusIoRunning; protected: - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// protected constructor - /// - /// - only applicable for the derived types to indicate if will need send or recv buffers - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// + // protected constructor + // - only applicable for the derived types to indicate if it will need send or recv buffers explicit ctsIoPattern(uint32_t recvCount); - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// The derived template class for tracking statistics must implement these pure virtual functions - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// + // The derived template class for tracking statistics must implement these pure virtual functions virtual void StartStatistics() noexcept = 0; virtual void EndStatistics() noexcept = 0; virtual char* GetConnectionIdentifier() noexcept = 0; - /// - /// the templated derived class tracking statistics must call Create* when it's generated - /// a connection Id for this instance - /// + // + // the templated derived class tracking statistics must call Create* when it's generated + // a connectionId for this instance + // void CreateRecvBuffers(); void CreateSendBuffers(); - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// CreateTrackedTask(IOTaskAction, uint32_t _max_transfer) - /// CreateUntrackedTask(IOTaskAction, uint32_t _max_transfer) - /// - /// - returns a ctsIOTask for the next transfer based on the IOAction - /// - the returned buffer can be contained to maximum size with _max_transfer - /// - /// tracked tasks will count that IO towards the max_transfer - /// untracked tasks will *not* count the IO towards the max_transfer - /// untracked tasks will *not* have their buffers validated on complete_io - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Returns a ctsIOTask for the next transfer based on the IOAction + // - the returned buffer can be contained to maximum size with _max_transfer + // + // tracked tasks will count that IO towards the max_transfer + // untracked tasks will *not* count the IO towards the max_transfer + // untracked tasks will *not* have their buffers validated on complete_io + // ctsTask CreateTrackedTask(ctsTaskAction, uint32_t maxTransfer = 0) noexcept; ctsTask CreateUntrackedTask(ctsTaskAction, uint32_t maxTransfer = 0) noexcept; @@ -364,9 +336,8 @@ class ctsIoPattern } } - /// Enabling derived types to update the internally tracked last-error - // - // update_last_error will attempt to keep the first error reported + // Enabling derived types to update the internally tracked last-error + // - update_last_error will attempt to keep the first error reported // - this will only update the value if an error has not yet been report for this state uint32_t UpdateLastError(const DWORD error) noexcept { @@ -419,31 +390,27 @@ class ctsIoPattern } } - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Complex derived patterns that need to obtain a lock can encounter complexities if they have - /// their own locks, given that the interface between the base and derived classes allow for - /// each to call the other. Base-calling-Drived && Drived-calling-Base patterns have the - /// inherant risk of deadlocks. - /// - /// Exposing the base class lock for these complex derived types. Most derived types will never - /// need this since the lock is always held before a derived interface is invoked by the base - /// class. - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Complex derived patterns that need to obtain a lock can encounter complexities if they have + // their own locks, given that the interface between the base and derived classes allow for + // each to call the other. Base-calling-Derived && Derived-calling-Base patterns have the + // inherent risk of deadlocks. + // + // Exposing the base class lock for these complex derived types. Most derived types will never + // need this since the lock is always held before a derived interface is invoked by the base + // class. + // [[nodiscard]] wil::cs_leave_scope_exit AcquireIoPatternLock() const noexcept; }; -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// The ctsIOPattern tracks what IO should be conducted on the socket -/// * All public methods protect against concurrent calls by taking an object lock -/// * Templated based off of the type of statistics being tracked by the object -/// Currently supporting -/// - ctsTcpStatistics -/// - ctsUdpStatistics -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// +// +// The ctsIOPattern tracks what IO should be conducted on the socket +// * All public methods protect against concurrent calls by taking an object lock +// * Templated based off of the type of statistics being tracked by the object +// Currently supporting +// - ctsTcpStatistics +// - ctsUdpStatistics +// template class ctsIoPatternStatistics : public ctsIoPattern { @@ -481,7 +448,7 @@ class ctsIoPatternStatistics : public ctsIoPattern // -- we don't need to use Interlocked* to read m_statistics (no m_statistics requires Interlocked*) if (0 == GetLastPatternError() && 0 == m_statistics.GetBytesTransferredNoLock()) { - PRINT_DEBUG_INFO(L"\t\tctsIOPattern::PrintStatistics : reporting a successful IO completion but transfered zero bytes\n"); + PRINT_DEBUG_INFO(L"\t\tctsIOPattern::PrintStatistics : reporting a successful IO completion but transferred zero bytes\n"); UpdateLastPatternError(ctsIoPatternError::TooFewBytes); } @@ -526,15 +493,12 @@ class ctsIoPatternStatistics : public ctsIoPattern bool m_started = false; }; - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// - Pull Pattern -/// -- TCP-only -/// -- The server pushes data in 'segments' (the size of which is defined in the class) -/// -- The client pulls data in 'segments' -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Pull Pattern +// - TCP-only +// - The server pushes data in 'segments' (the size of which is defined in the class) +// - The client pulls data in 'segments' +// class ctsIoPatternPull final : public ctsIoPatternStatistics { public: @@ -553,17 +517,15 @@ class ctsIoPatternPull final : public ctsIoPatternStatistics private: const ctsTaskAction m_ioAction; uint32_t m_recvNeeded{0}; - uint32_t m_sendBytesInflight{0}; + uint32_t m_sendBytesInFlight{0}; }; -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// - Push Pattern -/// -- TCP-only -/// -- The client pushes data in 'segments' (the size of which is defined in the class) -/// -- The server pulls data in 'segments' -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Push Pattern +// - TCP-only +// - The client pushes data in 'segments' (the size of which is defined in the class) +// - The server pulls data in 'segments' +// class ctsIoPatternPush final : public ctsIoPatternStatistics { public: @@ -582,18 +544,16 @@ class ctsIoPatternPush final : public ctsIoPatternStatistics private: const ctsTaskAction m_ioAction; uint32_t m_recvNeeded{0}; - uint32_t m_sendBytesInflight{0}; + uint32_t m_sendBytesInFlight{0}; }; -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// - PushPull Pattern -/// -- TCP-only -/// -- The client pushes data in 'segments' -/// -- The server pulls data in 'segments' -/// -- At each segment, roles swap (pusher/puller) -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// +// +// PushPull Pattern +// - TCP-only +// - The client pushes data in 'segments' +// - The server pulls data in 'segments' +// - At each segment, roles swap (pusher/puller) +// class ctsIoPatternPushPull final : public ctsIoPatternStatistics { public: @@ -619,14 +579,12 @@ class ctsIoPatternPushPull final : public ctsIoPatternStatistics { public: @@ -647,19 +605,16 @@ class ctsIoPatternDuplex final : public ctsIoPatternStatistics uint64_t m_remainingSendBytes{0}; uint64_t m_remainingRecvBytes{0}; uint32_t m_recvNeeded{0}; - uint32_t m_sendBytesInflight{0}; + uint32_t m_sendBytesInFlight{0}; }; - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// - UDP Media server -/// -- Receives a START message from a client to establish a 'connection' -/// -- Streams datagrams at the specified BitRate and FrameRate -/// -- Responds to RESEND requests out-of-band from the normal stream -/// -- Remains alive until the DONE message is sent from the client -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// +// +// UDP Media server +// - Receives a START message from a client to establish a 'connection' +// - Streams datagrams at the specified BitRate and FrameRate +// - Responds to RESEND requests out-of-band from the normal stream +// - Remains alive until the DONE message is sent from the client +// class ctsIoPatternMediaStreamServer final : public ctsIoPatternStatistics { public: @@ -683,7 +638,7 @@ class ctsIoPatternMediaStreamServer final : public ctsIoPatternStatistics { public: @@ -756,9 +708,9 @@ class ctsIoPatternMediaStreamClient final : public ctsIoPatternStatistics #include // os headers #include @@ -54,11 +55,8 @@ ctsIoPatternMediaStreamClient::ctsIoPatternMediaStreamClient() : ctsIoPatternStatistics(ctsConfig::g_configSettings->PrePostRecvs), m_frameRateMsPerFrame(1000.0 / static_cast(ctsConfig::GetMediaStream().FramesPerSecond)) { - // if the entire session fits in the inital buffer, update accordingly - if (m_finalFrame < m_initialBufferFrames) - { - m_initialBufferFrames = m_finalFrame; - } + // if the entire session fits in the initial buffer, update accordingly + m_initialBufferFrames = std::min(m_finalFrame, m_initialBufferFrames); m_timerWheelOffsetFrames = m_initialBufferFrames; constexpr long extraBufferDepthFactor = 2; @@ -71,7 +69,7 @@ ctsIoPatternMediaStreamClient::ctsIoPatternMediaStreamClient() : "BufferDepth & FrameSize don't allow for enough buffered stream"); } - PRINT_DEBUG_INFO(L"\t\tctsIOPatternMediaStreamClient - queue size for this new connection is %u\n", queueSize); + PRINT_DEBUG_INFO(L"\t\tctsIOPatternMediaStreamClient - queue size for this new connection is %ld\n", queueSize); PRINT_DEBUG_INFO(L"\t\tctsIOPatternMediaStreamClient - frame rate in milliseconds per frame : %f\n", m_frameRateMsPerFrame); m_frameEntries.resize(queueSize); @@ -79,7 +77,6 @@ ctsIoPatternMediaStreamClient::ctsIoPatternMediaStreamClient() : // pre-populate the queue of frames with the initial seq numbers int64_t lastUsedSequenceNumber = 1; - // ReSharper disable once CppUseStructuredBinding for (auto& entry : m_frameEntries) { entry.m_sequenceNumber = lastUsedSequenceNumber; @@ -216,7 +213,7 @@ ctsIoPatternError ctsIoPatternMediaStreamClient::CompleteTaskBackToPattern(const m_statistics.m_errorFrames.IncrementNoLock(); PRINT_DEBUG_INFO( - L"\t\tctsIOPatternMediaStreamClient recevieved **an unknown** seq number (%lld) (outside the final frame %lu)\n", + L"\t\tctsIOPatternMediaStreamClient received **an unknown** seq number (%lld) (outside the final frame %u)\n", receivedSequenceNumber, m_finalFrame); } @@ -240,7 +237,7 @@ ctsIoPatternError ctsIoPatternMediaStreamClient::CompleteTaskBackToPattern(const foundSlot->m_bytesReceived += completedBytes; PRINT_DEBUG_INFO( - L"\t\tctsIOPatternMediaStreamClient received seq number %lld (%lu received-bytes, %lu frame-bytes)\n", + L"\t\tctsIOPatternMediaStreamClient received seq number %lld (%u received-bytes, %u frame-bytes)\n", foundSlot->m_sequenceNumber, completedBytes, foundSlot->m_bytesReceived); @@ -270,7 +267,7 @@ ctsIoPatternError ctsIoPatternMediaStreamClient::CompleteTaskBackToPattern(const else { PRINT_DEBUG_INFO( - L"\t\tctsIOPatternMediaStreamClient recevieved **a future** seq number (%lld) - head of queue (%lld) tail of queue (%llu)\n", + L"\t\tctsIOPatternMediaStreamClient received **a future** seq number (%lld) - head of queue (%lld) tail of queue (%llu)\n", receivedSequenceNumber, m_headEntry->m_sequenceNumber, m_headEntry->m_sequenceNumber + m_frameEntries.size() - 1); @@ -336,7 +333,7 @@ bool ctsIoPatternMediaStreamClient::ReceivedBufferedFrames() noexcept bool ctsIoPatternMediaStreamClient::SetNextTimer(bool initialTimer) const noexcept { auto timerScheduled = false; - // only schedule the next timer instance if the d'tor hasn't indicated it's wanting to exit + // only schedule the next timer instance if the destructor hasn't indicated it's wanting to exit if (m_rendererTimer != nullptr) { // calculate when that time should be relative to base_time_milliseconds @@ -381,7 +378,7 @@ void ctsIoPatternMediaStreamClient::SetNextStartTimer() const noexcept void ctsIoPatternMediaStreamClient::RenderFrame() noexcept { // estimating time in flight for this frame by determining how much time since the first send was just 'waiting' to send this frame - // and subtracing that from how much time since the first receive - since time between receives should at least be time between sends + // and subtracting that from how much time since the first receive - since time between receives should at least be time between sends if (m_headEntry->m_receiverQpf != 0 && m_firstFrame.m_receiverQpf != 0) { // ReSharper disable CppRedundantParentheses diff --git a/ctsTraffic/ctsIOPatternProtocolPolicy.hpp b/ctsTraffic/ctsIOPatternProtocolPolicy.hpp index 718b06e..eddf13c 100644 --- a/ctsTraffic/ctsIOPatternProtocolPolicy.hpp +++ b/ctsTraffic/ctsIOPatternProtocolPolicy.hpp @@ -19,7 +19,7 @@ See the Apache Version 2.0 License for specific language governing permissions a namespace ctsTraffic { -enum class ctsIoPatternType +enum class ctsIoPatternType : std::uint8_t { NoIo, SendConnectionGuid, @@ -32,7 +32,7 @@ enum class ctsIoPatternType RequestFin }; -enum class ctsIoPatternError +enum class ctsIoPatternError : std::uint8_t { NotProtocolError, NoConnectionGuid, @@ -108,7 +108,7 @@ template class ctsIoPatternProtocolPolicy { private: - enum class InternalPatternState + enum class InternalPatternState : std::uint8_t { Initialized, MoreIo, @@ -128,7 +128,7 @@ class ctsIoPatternProtocolPolicy // need to know when to stop uint64_t m_maxTransfer = 0; // need to know in-flight bytes - uint64_t m_inflightBytes = 0; + uint64_t m_inFlightBytes = 0; // tracking the pattern state mutable InternalPatternState m_internalState = InternalPatternState::Initialized; // tracking the specific error for this connection @@ -147,17 +147,17 @@ class ctsIoPatternProtocolPolicy // // Guard our internal tracking - all protocol logic assumes these rules // - const auto alreadyTransferred = m_confirmedBytes + m_inflightBytes; + const auto alreadyTransferred = m_confirmedBytes + m_inFlightBytes; FAIL_FAST_IF_MSG( - alreadyTransferred < m_confirmedBytes || alreadyTransferred < m_inflightBytes, - "ctsIOPatternState internal overflow (already_transferred = m_confirmedBytes + m_inflightBytes)\n" + alreadyTransferred < m_confirmedBytes || alreadyTransferred < m_inFlightBytes, + "ctsIOPatternState internal overflow (already_transferred = m_confirmedBytes + m_inFlightBytes)\n" "already_transferred: %llu\n" "m_confirmedBytes: %llu\n" - "m_inflightBytes: %llu\n", + "m_inFlightBytes: %llu\n", alreadyTransferred, m_confirmedBytes, - m_inflightBytes); + m_inFlightBytes); FAIL_FAST_IF_MSG( alreadyTransferred > m_maxTransfer, "ctsIOPatternState internal error: bytes already transferred (%llu) is >= the total we're expected to transfer (%llu)\n", @@ -261,20 +261,13 @@ class ctsIoPatternProtocolPolicy private: // - // these private methods are specialized by the Potocol specified in the class template + // these private methods are specialized by the Protocol specified in the class template // ctsIoPatternType GetNextPatternTypePerProtocol() const noexcept; void CompletedTaskPerProtocol(const ctsTask& completedTask, uint32_t completedTransferredBytes) noexcept; void UpdateErrorPerProtocol(DWORD errorCode) const noexcept; }; -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// Definitions for the class methods -/// - including the specialized methods per-protocol -/// -//////////////////////////////////////////////////////////////////////////////////////////////////// - template ctsIoPatternType ctsIoPatternProtocolPolicy::GetNextPatternType() const noexcept { @@ -290,7 +283,7 @@ ctsIoPatternType ctsIoPatternProtocolPolicy::GetNextPatternType() cons // if (InternalPatternState::MoreIo == m_internalState) { - if (m_confirmedBytes + m_inflightBytes < m_maxTransfer) + if (m_confirmedBytes + m_inFlightBytes < m_maxTransfer) { return ctsIoPatternType::MoreIo; } @@ -343,7 +336,7 @@ void ctsIoPatternProtocolPolicy::NotifyNextTask(const ctsTask& nextTas { if (nextTask.m_trackIo) { - m_inflightBytes += nextTask.m_bufferLength; + m_inFlightBytes += nextTask.m_bufferLength; } } @@ -367,7 +360,7 @@ void ctsIoPatternProtocolPolicy::CompletedTask(const ctsTask& complete if (completedTransferredBytes != ctsStatistics::ConnectionIdLength) { PRINT_DEBUG_INFO( - L"\t\tctsIOPatternState::completedTask : ErrorIoFailed (TooFewBytes) [transfered %u, Expected ConnectionID (%u)]\n", + L"\t\tctsIOPatternState::completedTask : ErrorIoFailed (TooFewBytes) [transferred %u, Expected ConnectionID (%u)]\n", completedTransferredBytes, ctsStatistics::ConnectionIdLength); UpdateProtocolError(ctsIoPatternError::NoConnectionGuid); return; @@ -382,13 +375,13 @@ void ctsIoPatternProtocolPolicy::CompletedTask(const ctsTask& complete // Checking for an inconsistent internal state // FAIL_FAST_IF_MSG( - completedTransferredBytes > m_inflightBytes, + completedTransferredBytes > m_inFlightBytes, "ctsIOPatternState::completedTask : ctsIOTask (%p) returned more bytes (%u) than were in flight (%llu)", - &completedTask, completedTransferredBytes, m_inflightBytes); + &completedTask, completedTransferredBytes, m_inFlightBytes); FAIL_FAST_IF_MSG( - completedTask.m_bufferLength > m_inflightBytes, + completedTask.m_bufferLength > m_inFlightBytes, "ctsIOPatternState::completedTask : the ctsIOTask (%p) had requested more bytes (%u) than were in-flight (%llu)\n", - &completedTask, completedTask.m_bufferLength, m_inflightBytes); + &completedTask, completedTask.m_bufferLength, m_inFlightBytes); FAIL_FAST_IF_MSG( completedTransferredBytes > completedTask.m_bufferLength, "ctsIOPatternState::completedTask : ctsIOTask (%p) returned more bytes (%u) than were posted (%u)\n", @@ -396,7 +389,7 @@ void ctsIoPatternProtocolPolicy::CompletedTask(const ctsTask& complete // // now update our internal tracking of bytes in-flight / completed // - m_inflightBytes -= completedTask.m_bufferLength; + m_inFlightBytes -= completedTask.m_bufferLength; m_confirmedBytes += completedTransferredBytes; } // @@ -547,7 +540,7 @@ inline void ctsIoPatternProtocolPolicy::CompletedTaskPe template <> inline void ctsIoPatternProtocolPolicy::CompletedTaskPerProtocol(const ctsTask& completedTask, uint32_t completedTransferredBytes) noexcept { - const auto alreadyTransferred = m_confirmedBytes + m_inflightBytes; + const auto alreadyTransferred = m_confirmedBytes + m_inFlightBytes; // // TCP has a full state machine // @@ -571,9 +564,9 @@ inline void ctsIoPatternProtocolPolicy::Completed } else if (alreadyTransferred == m_maxTransfer) { - // With TCP, if inflight_bytes > 0, we are not yet done + // With TCP, if inFlightBytes > 0, we are not yet done // - we need to wait for that pended IO to complete - if (0 == m_inflightBytes) + if (0 == m_inFlightBytes) { // clients will recv the server status, then process their shutdown sequence switch (m_internalState) @@ -632,7 +625,7 @@ inline void ctsIoPatternProtocolPolicy::Completed default: FAIL_FAST_MSG( - "ctsIOPatternState::completedTask - invalid internal state (%d): dt %p ctsTraffic!ctsTraffic::ctsIOPatternState, dt %p ctsTraffic!ctstraffic::ctsIOTask", + "ctsIOPatternState::completedTask - invalid internal state (%d): dt %p ctsTraffic!ctsTraffic::ctsIOPatternState, dt %p ctsTraffic!ctsTraffic::ctsIOTask", m_internalState, this, &completedTask); } } @@ -650,7 +643,7 @@ inline void ctsIoPatternProtocolPolicy::Completed template <> inline void ctsIoPatternProtocolPolicy::CompletedTaskPerProtocol(const ctsTask&, uint32_t completedTransferredBytes) noexcept { - const auto alreadyTransferred = m_confirmedBytes + m_inflightBytes; + const auto alreadyTransferred = m_confirmedBytes + m_inFlightBytes; // // TCP has a full state machine // @@ -674,9 +667,9 @@ inline void ctsIoPatternProtocolPolicy::Completed } else if (alreadyTransferred == m_maxTransfer) { - // With TCP, if inflight_bytes > 0, we are not yet done + // With TCP, if inFlightBytes > 0, we are not yet done // - we need to wait for that pended IO to complete - if (0 == m_inflightBytes) + if (0 == m_inFlightBytes) { // servers will first send their final status before starting their shutdown sequence switch (m_internalState) diff --git a/ctsTraffic/ctsIOPatternState.hpp b/ctsTraffic/ctsIOPatternState.hpp index 909ff94..7b23ebd 100644 --- a/ctsTraffic/ctsIOPatternState.hpp +++ b/ctsTraffic/ctsIOPatternState.hpp @@ -24,7 +24,7 @@ namespace ctsTraffic constexpr auto* const c_completionMessage = "DONE"; constexpr uint32_t c_completionMessageSize = 4; -enum class ctsIoPatternType +enum class ctsIoPatternType : std::int8_t { NoIo, SendConnectionId, @@ -37,7 +37,7 @@ enum class ctsIoPatternType RequestFin }; -enum class ctsIoPatternError +enum class ctsIoPatternError : std::int8_t { NoError, TooManyBytes, @@ -49,7 +49,7 @@ enum class ctsIoPatternError class ctsIoPatternState { - enum class InternalPatternState + enum class InternalPatternState : std::int8_t { Initialized, MoreIo, @@ -73,9 +73,9 @@ class ctsIoPatternState // need to know when to stop uint64_t m_maxTransfer = ctsConfig::GetTransferSize(); // need to know in-flight bytes - uint64_t m_inflightBytes = 0UL; + uint64_t m_inFlightBytes = 0UL; // ideal send backlog value - uint32_t m_idealSendbacklog = ctsConfig::g_configSettings->PrePostSends == 0 ? + uint32_t m_idealSendBacklog = ctsConfig::g_configSettings->PrePostSends == 0 ? ctsConfig::GetMaxBufferSize() : ctsConfig::GetMaxBufferSize() * ctsConfig::g_configSettings->PrePostSends; @@ -118,16 +118,16 @@ inline uint64_t ctsIoPatternState::GetRemainingTransfer() const noexcept // // Guard our internal tracking - all protocol logic assumes these rules // - const auto alreadyTransferred = m_confirmedBytes + m_inflightBytes; + const auto alreadyTransferred = m_confirmedBytes + m_inFlightBytes; FAIL_FAST_IF_MSG( - alreadyTransferred < m_confirmedBytes || alreadyTransferred < m_inflightBytes, - "ctsIOPatternState internal overflow (already_transferred = m_confirmedBytes + m_inflightBytes)\n" + alreadyTransferred < m_confirmedBytes || alreadyTransferred < m_inFlightBytes, + "ctsIOPatternState internal overflow (already_transferred = m_confirmedBytes + m_inFlightBytes)\n" "already_transferred: %llu\n" "m_confirmedBytes: %llu\n" - "m_inflightBytes: %llu\n", + "m_inFlightBytes: %llu\n", static_cast(alreadyTransferred), static_cast(m_confirmedBytes), - static_cast(m_inflightBytes)); + static_cast(m_inFlightBytes)); FAIL_FAST_IF_MSG( alreadyTransferred > m_maxTransfer, @@ -149,12 +149,12 @@ inline void ctsIoPatternState::SetMaxTransfer(uint64_t maxTransfer) noexcept inline uint32_t ctsIoPatternState::GetIdealSendBacklog() const noexcept { - return m_idealSendbacklog; + return m_idealSendBacklog; } inline void ctsIoPatternState::SetIdealSendBacklog(uint32_t newIsb) noexcept { - m_idealSendbacklog = newIsb; + m_idealSendBacklog = newIsb; } inline bool ctsIoPatternState::IsCompleted() const noexcept @@ -202,7 +202,7 @@ inline ctsIoPatternType ctsIoPatternState::GetNextPatternType() noexcept case InternalPatternState::MoreIo: // ReSharper disable once CppRedundantParentheses - return (m_confirmedBytes + m_inflightBytes) < m_maxTransfer ? + return (m_confirmedBytes + m_inFlightBytes) < m_maxTransfer ? ctsIoPatternType::MoreIo : ctsIoPatternType::NoIo; @@ -248,7 +248,7 @@ inline void ctsIoPatternState::NotifyNextTask(const ctsTask& nextTask) noexcept { if (nextTask.m_trackIo) { - m_inflightBytes += nextTask.m_bufferLength; + m_inFlightBytes += nextTask.m_bufferLength; } } @@ -264,7 +264,7 @@ inline ctsIoPatternError ctsIoPatternState::UpdateError(DWORD error) noexcept { if (error != 0) { - PRINT_DEBUG_INFO(L"\t\tctsIOPatternState::UpdateError : ErrorIOFailed (%u)\n", error); + PRINT_DEBUG_INFO(L"\t\tctsIOPatternState::UpdateError : ErrorIOFailed (%lu)\n", error); m_internalState = InternalPatternState::ErrorIoFailed; return ctsIoPatternError::ErrorIoFailed; } @@ -283,7 +283,7 @@ inline ctsIoPatternError ctsIoPatternState::UpdateError(DWORD error) noexcept return ctsIoPatternError::NoError; } - PRINT_DEBUG_INFO(L"\t\tctsIOPatternState::UpdateError : ErrorIOFailed (%u)\n", error); + PRINT_DEBUG_INFO(L"\t\tctsIOPatternState::UpdateError : ErrorIOFailed (%lu)\n", error); m_internalState = InternalPatternState::ErrorIoFailed; return ctsIoPatternError::ErrorIoFailed; } @@ -308,7 +308,7 @@ inline ctsIoPatternError ctsIoPatternState::CompletedTask(const ctsTask& complet if (completedTransferBytes != ctsStatistics::ConnectionIdLength) { PRINT_DEBUG_INFO( - L"\t\tctsIOPatternState::CompletedTask : ErrorIOFailed (TooFewBytes) [transfered %u, Expected ConnectionID (%u)]\n", + L"\t\tctsIOPatternState::CompletedTask : ErrorIOFailed (TooFewBytes) [transferred %u, Expected ConnectionID (%u)]\n", completedTransferBytes, ctsStatistics::ConnectionIdLength); @@ -323,25 +323,25 @@ inline ctsIoPatternError ctsIoPatternState::CompletedTask(const ctsTask& complet { // Checking for an inconsistent internal state FAIL_FAST_IF_MSG( - completedTransferBytes > m_inflightBytes, + completedTransferBytes > m_inFlightBytes, "ctsIOPatternState::CompletedTask : ctsIOTask (%p) returned more bytes (%u) than were in flight (%llu)", - &completedTask, completedTransferBytes, m_inflightBytes); + &completedTask, completedTransferBytes, m_inFlightBytes); FAIL_FAST_IF_MSG( - completedTask.m_bufferLength > m_inflightBytes, + completedTask.m_bufferLength > m_inFlightBytes, "ctsIOPatternState::CompletedTask : the ctsIOTask (%p) had requested more bytes (%u) than were in-flight (%llu)\n", - &completedTask, completedTask.m_bufferLength, m_inflightBytes); + &completedTask, completedTask.m_bufferLength, m_inFlightBytes); FAIL_FAST_IF_MSG( completedTransferBytes > completedTask.m_bufferLength, "ctsIOPatternState::CompletedTask : ctsIOTask (%p) returned more bytes (%u) than were posted (%u)\n", &completedTask, completedTransferBytes, completedTask.m_bufferLength); // now update our internal tracking of bytes in-flight / completed - m_inflightBytes -= completedTask.m_bufferLength; + m_inFlightBytes -= completedTask.m_bufferLength; m_confirmedBytes += completedTransferBytes; } // Verify IO Post-condition protocol contracts haven't been violated - const auto alreadyTransferred = m_confirmedBytes + m_inflightBytes; + const auto alreadyTransferred = m_confirmedBytes + m_inFlightBytes; // Udp just tracks bytes if (ctsConfig::ProtocolType::UDP == ctsConfig::g_configSettings->Protocol) @@ -370,9 +370,9 @@ inline ctsIoPatternError ctsIoPatternState::CompletedTask(const ctsTask& complet } else if (alreadyTransferred == m_maxTransfer) { - // With TCP, if inflight_bytes > 0, we are not yet done + // With TCP, if inFlight_bytes > 0, we are not yet done // - we need to wait for that pended IO to complete - if (0 == m_inflightBytes) + if (0 == m_inFlightBytes) { // // All TCP data has been sent/received @@ -483,7 +483,7 @@ inline ctsIoPatternError ctsIoPatternState::CompletedTask(const ctsTask& complet default: FAIL_FAST_MSG( - "ctsIOPatternState::CompletedTask - invalid m_internalState (%d): dt %p ctsTraffic!ctsTraffic::ctsIOPatternState, dt %p ctsTraffic!ctstraffic::ctsIOTask", + "ctsIOPatternState::CompletedTask - invalid m_internalState (%d): dt %p ctsTraffic!ctsTraffic::ctsIOPatternState, dt %p ctsTraffic!ctsTraffic::ctsIOTask", m_internalState, this, &completedTask); } } diff --git a/ctsTraffic/ctsIOPatternT.h b/ctsTraffic/ctsIOPatternT.h index 48ea34a..8ea08c9 100644 --- a/ctsTraffic/ctsIOPatternT.h +++ b/ctsTraffic/ctsIOPatternT.h @@ -24,7 +24,7 @@ See the Apache Version 2.0 License for specific language governing permissions a namespace ctsTraffic { -enum class ctsIoStatus +enum class ctsIoStatus : std::uint8_t { ContinueIo, CompletedIo, @@ -116,7 +116,6 @@ class ctsIoPatternT : public ctsIoPattern return m_protocolPolicy.get_last_error(); } - /// no copy c'tor or copy assignment ctsIoPatternT(const ctsIoPatternT&) = delete; ctsIoPatternT& operator=(const ctsIoPatternT&) = delete; ctsIoPatternT(ctsIoPatternT&&) = delete; diff --git a/ctsTraffic/ctsIOTask.hpp b/ctsTraffic/ctsIOTask.hpp index 3379245..001ef76 100644 --- a/ctsTraffic/ctsIOTask.hpp +++ b/ctsTraffic/ctsIOTask.hpp @@ -25,7 +25,7 @@ namespace ctsTraffic { // The ctsIOTask struct instructs the caller on what action to perform // - and provides it the buffer it should use to send/recv data -enum class ctsTaskAction +enum class ctsTaskAction : std::uint8_t { None, Send, @@ -48,7 +48,7 @@ struct ctsTask ctsTaskAction m_ioAction = ctsTaskAction::None; // (internal) flag identifying the type of buffer - enum class BufferType + enum class BufferType : std::uint8_t { Null, TcpConnectionId, diff --git a/ctsTraffic/ctsLogger.hpp b/ctsTraffic/ctsLogger.hpp index c901db7..ae869c9 100644 --- a/ctsTraffic/ctsLogger.hpp +++ b/ctsTraffic/ctsLogger.hpp @@ -25,20 +25,17 @@ See the Apache Version 2.0 License for specific language governing permissions a namespace ctsTraffic { -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// Base class for all ctsTraffic Loggers -/// -/// -/// - all concrete types must implement: -/// message_impl(_In_ PCWSTR) -/// error_impl(_In_ PCWSTR) -/// -/// Note: all logging functions are no-throw -/// only the c'tor can throw -/// -//////////////////////////////////////////////////////////////////////////////////////////////////// - +// +// Base class for all ctsTraffic Loggers +// +// +// - all concrete types must implement: +// message_impl(_In_ PCWSTR) +// error_impl(_In_ PCWSTR) +// +// Note: all logging functions are no-throw +// only the constructor can throw +// class ctsLogger { public: @@ -97,7 +94,7 @@ class ctsLogger private: ctsConfig::StatusFormatting m_format; - /// pure virtual methods concrete classes must implement + // pure virtual methods concrete classes must implement virtual void LogMessageImpl(_In_ PCWSTR message) noexcept = 0; virtual void LogErrorImpl(_In_ PCWSTR message) noexcept = 0; }; diff --git a/ctsTraffic/ctsMediaStreamClient.cpp b/ctsTraffic/ctsMediaStreamClient.cpp index b365d69..29b49d0 100644 --- a/ctsTraffic/ctsMediaStreamClient.cpp +++ b/ctsTraffic/ctsMediaStreamClient.cpp @@ -38,35 +38,27 @@ namespace ctsTraffic bool m_continueIo = false; }; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Internal implementation functions - /// - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - IoImplStatus ctsMediaStreamClientIoImpl( + // Internal implementation functions + static IoImplStatus ctsMediaStreamClientIoImpl( const std::shared_ptr& sharedSocket, SOCKET socket, const std::shared_ptr& lockedPattern, const ctsTask& task) noexcept; - void ctsMediaStreamClientIoCompletionCallback( + static void ctsMediaStreamClientIoCompletionCallback( _In_ OVERLAPPED* pOverlapped, const std::weak_ptr& weakSocket, const ctsTask& task ) noexcept; - void ctsMediaStreamClientConnectionCompletionCallback( + static void ctsMediaStreamClientConnectionCompletionCallback( _In_ OVERLAPPED* pOverlapped, const std::weak_ptr& weakSocket, const ctl::ctSockaddr& targetAddress ) noexcept; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// The function that is registered with ctsTraffic to run Winsock IO using IO Completion Ports - /// - with the specified ctsSocket - /// - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // The function that is registered with ctsTraffic to run Winsock IO using IO Completion Ports + // - with the specified ctsSocket void ctsMediaStreamClient(const std::weak_ptr& weakSocket) noexcept { // attempt to get a reference to the socket @@ -120,7 +112,6 @@ namespace ctsTraffic if (lambdaSharedSocket->IncrementIo() > 1) { // only running this one task in the OOB callback - // ReSharper disable once CppUseStructuredBinding const IoImplStatus status = ctsMediaStreamClientIoImpl( lambdaSharedSocket, lambdaLockedSocket.GetSocket(), lambdaLockedPattern, task); // decrement the IO count that we added before calling the Impl @@ -160,12 +151,8 @@ namespace ctsTraffic } } - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// The function that is registered with ctsTraffic to 'connect' to the target server by sending a START command - /// using IO Completion Ports - /// - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // The function that is registered with ctsTraffic to 'connect' to the target server by sending a START command + // using IO Completion Ports void ctsMediaStreamClientConnect(const std::weak_ptr& weakSocket) noexcept { // attempt to get a reference to the socket @@ -367,11 +354,7 @@ namespace ctsTraffic } - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// IO Threadpool completion callback - /// - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // IO Threadpool completion callback void ctsMediaStreamClientIoCompletionCallback( _In_ OVERLAPPED* pOverlapped, const std::weak_ptr& weakSocket, @@ -487,11 +470,7 @@ namespace ctsTraffic } } - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// IO Threadpool completion callback for the 'connect' request - /// - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // IO Threadpool completion callback for the 'connect' request void ctsMediaStreamClientConnectionCompletionCallback( _In_ OVERLAPPED* pOverlapped, const std::weak_ptr& weakSocket, diff --git a/ctsTraffic/ctsMediaStreamProtocol.hpp b/ctsTraffic/ctsMediaStreamProtocol.hpp index f918587..acad982 100644 --- a/ctsTraffic/ctsMediaStreamProtocol.hpp +++ b/ctsTraffic/ctsMediaStreamProtocol.hpp @@ -72,18 +72,14 @@ class ctsMediaStreamSendRequests static constexpr uint32_t c_bufferArraySize = 5; - /// - /// compose iteration across buffers to be sent per instantiated request - /// + // + // compose iteration across buffers to be sent per instantiated request + // class iterator { public: - //////////////////////////////////////////////////////////////////////////////// - /// - /// iterator_traits - /// - allows functions to be used - /// - //////////////////////////////////////////////////////////////////////////////// + // iterator_traits + // - allows functions to be used using iterator_category = std::forward_iterator_tag; using value_type = std::array; using difference_type = size_t; @@ -96,10 +92,8 @@ class ctsMediaStreamSendRequests iterator(iterator&&) = default; iterator& operator=(iterator&&) = default; - /// - /// Dereferencing operators - /// - returning non-const array references as Winsock APIs don't take const WSABUF* - /// + // Dereferencing operators + // - returning non-const array references as Winsock APIs don't take const WSABUF* std::array* operator->() noexcept { FAIL_FAST_IF_MSG( @@ -124,9 +118,6 @@ class ctsMediaStreamSendRequests return m_wsaBufArray; } - /// - /// Equality operators - /// bool operator ==(const iterator& comparand) const noexcept { return m_qpcAddress == comparand.m_qpcAddress && @@ -138,7 +129,6 @@ class ctsMediaStreamSendRequests return !(*this == comparand); } - /// preincrement iterator& operator++() noexcept { FAIL_FAST_IF_MSG( @@ -158,7 +148,6 @@ class ctsMediaStreamSendRequests return *this; } - // postincrement iterator operator++(int) noexcept { const iterator temp(*this); @@ -167,7 +156,7 @@ class ctsMediaStreamSendRequests } private: - // c'tor is only available to the begin() and end() methods of ctsMediaStreamSendRequests + // constructor is only available to the begin() and end() methods of ctsMediaStreamSendRequests friend class ctsMediaStreamSendRequests; iterator(_In_opt_ LARGE_INTEGER* qpcAddress, int64_t bytesToSend, const std::array& wsaBufferArray) noexcept : @@ -221,11 +210,11 @@ class ctsMediaStreamSendRequests }; - /// - /// Constructor of the ctsMediaStreamSendRequests captures the properties of the next Send() request - /// - the total # of bytes to send (across X number of send requests) - /// - the sequence number to tag in every send request - /// + // + // Constructor of the ctsMediaStreamSendRequests captures the properties of the next Send() request + // - the total # of bytes to send (across X number of send requests) + // - the sequence number to tag in every send request + // ctsMediaStreamSendRequests(int64_t bytesToSend, int64_t sequenceNumber, const char* sendBuffer) noexcept : m_qpf(ctl::ctTimer::snap_qpf()), m_bytesToSend(bytesToSend), @@ -236,36 +225,36 @@ class ctsMediaStreamSendRequests "ctsMediaStreamSendRequests requires a buffer size to send larger than the ctsTraffic UDP header"); // buffer layout: header#, seq. number, qpc, qpf, then the buffered data - m_wsabuffer[0].buf = reinterpret_cast(const_cast(&c_udpDatagramProtocolHeaderFlagData)); - m_wsabuffer[0].len = c_udpDatagramProtocolHeaderFlagLength; + m_wsaBuffer[0].buf = reinterpret_cast(const_cast(&c_udpDatagramProtocolHeaderFlagData)); + m_wsaBuffer[0].len = c_udpDatagramProtocolHeaderFlagLength; - m_wsabuffer[1].buf = reinterpret_cast(&m_sequenceNumber); - m_wsabuffer[1].len = c_udpDatagramSequenceNumberLength; + m_wsaBuffer[1].buf = reinterpret_cast(&m_sequenceNumber); + m_wsaBuffer[1].len = c_udpDatagramSequenceNumberLength; - m_wsabuffer[2].buf = reinterpret_cast(&m_qpcValue.QuadPart); - m_wsabuffer[2].len = c_udpDatagramQpcLength; + m_wsaBuffer[2].buf = reinterpret_cast(&m_qpcValue.QuadPart); + m_wsaBuffer[2].len = c_udpDatagramQpcLength; - m_wsabuffer[3].buf = reinterpret_cast(&m_qpf); - m_wsabuffer[3].len = c_udpDatagramQpfLength; + m_wsaBuffer[3].buf = reinterpret_cast(&m_qpf); + m_wsaBuffer[3].len = c_udpDatagramQpfLength; - m_wsabuffer[4].buf = const_cast(sendBuffer); + m_wsaBuffer[4].buf = const_cast(sendBuffer); // the "this->wsabuf[4].len" field is dependent on bytes_to_send and can change by iterator() } [[nodiscard]] iterator begin() noexcept { - return {&m_qpcValue, m_bytesToSend, m_wsabuffer}; + return {&m_qpcValue, m_bytesToSend, m_wsaBuffer}; } [[nodiscard]] iterator end() const noexcept { // end == null qpc + 0 byte length - return {nullptr, 0, m_wsabuffer}; + return {nullptr, 0, m_wsaBuffer}; } private: - std::array m_wsabuffer{}; + std::array m_wsaBuffer{}; LARGE_INTEGER m_qpcValue{}; int64_t m_qpf; int64_t m_bytesToSend; diff --git a/ctsTraffic/ctsMediaStreamServer.cpp b/ctsTraffic/ctsMediaStreamServer.cpp index 563411f..7834916 100644 --- a/ctsTraffic/ctsMediaStreamServer.cpp +++ b/ctsTraffic/ctsMediaStreamServer.cpp @@ -35,465 +35,466 @@ See the Apache Version 2.0 License for specific language governing permissions a namespace ctsTraffic { -// Called to 'accept' incoming connections -void ctsMediaStreamServerListener(const std::weak_ptr& weakSocket) noexcept try -{ - ctsMediaStreamServerImpl::InitOnce(); - // ctsMediaStreamServerImpl will complete the ctsSocket object - // when a client request comes in to be 'accepted' - ctsMediaStreamServerImpl::AcceptSocket(weakSocket); -} -catch (...) -{ - const auto error = ctsConfig::PrintThrownException(); - if (const auto sharedSocket = weakSocket.lock()) + // Called to 'accept' incoming connections + void ctsMediaStreamServerListener(const std::weak_ptr& weakSocket) noexcept try { - sharedSocket->CompleteState(error); + ctsMediaStreamServerImpl::InitOnce(); + // ctsMediaStreamServerImpl will complete the ctsSocket object + // when a client request comes in to be 'accepted' + ctsMediaStreamServerImpl::AcceptSocket(weakSocket); } -} - -// Called initiate IO on a datagram socket -void ctsMediaStreamServerIo(const std::weak_ptr& weakSocket) noexcept -{ - const auto sharedSocket(weakSocket.lock()); - if (!sharedSocket) + catch (...) { - return; + const auto error = ctsConfig::PrintThrownException(); + if (const auto sharedSocket = weakSocket.lock()) + { + sharedSocket->CompleteState(error); + } } - // hold a reference on the socket - const auto lockedSocket = sharedSocket->AcquireSocketLock(); - const auto lockedPattern = lockedSocket.GetPattern(); - if (!lockedPattern) + // Called initiate IO on a datagram socket + void ctsMediaStreamServerIo(const std::weak_ptr& weakSocket) noexcept { - return; - } + const auto sharedSocket(weakSocket.lock()); + if (!sharedSocket) + { + return; + } - ctsTask nextTask; - try - { - ctsMediaStreamServerImpl::InitOnce(); + // hold a reference on the socket + const auto lockedSocket = sharedSocket->AcquireSocketLock(); + const auto lockedPattern = lockedSocket.GetPattern(); + if (!lockedPattern) + { + return; + } - do + ctsTask nextTask; + try { - nextTask = lockedPattern->InitiateIo(); + ctsMediaStreamServerImpl::InitOnce(); + + do + { + nextTask = lockedPattern->InitiateIo(); + if (nextTask.m_ioAction != ctsTaskAction::None) + { + ctsMediaStreamServerImpl::ScheduleIo(weakSocket, nextTask); + } + } while (nextTask.m_ioAction != ctsTaskAction::None); + } + catch (...) + { + const auto error = ctsConfig::PrintThrownException(); if (nextTask.m_ioAction != ctsTaskAction::None) { - ctsMediaStreamServerImpl::ScheduleIo(weakSocket, nextTask); + // must complete any IO that was requested but not scheduled + lockedPattern->CompleteIo(nextTask, 0, error); + if (0 == sharedSocket->GetPendedIoCount()) + { + sharedSocket->CompleteState(error); + } } } - while (nextTask.m_ioAction != ctsTaskAction::None); } - catch (...) + + // Called to remove that socket from the tracked vector of connected sockets + void ctsMediaStreamServerClose(const std::weak_ptr& weakSocket) noexcept try { - const auto error = ctsConfig::PrintThrownException(); - if (nextTask.m_ioAction != ctsTaskAction::None) + ctsMediaStreamServerImpl::InitOnce(); + + if (const auto sharedSocket = weakSocket.lock()) { - // must complete any IO that was requested but not scheduled - lockedPattern->CompleteIo(nextTask, 0, error); - if (0 == sharedSocket->GetPendedIoCount()) - { - sharedSocket->CompleteState(error); - } + ctsMediaStreamServerImpl::RemoveSocket(sharedSocket->GetRemoteSockaddr()); } } -} + catch (...) + { + } -// Called to remove that socket from the tracked vector of connected sockets -void ctsMediaStreamServerClose(const std::weak_ptr& weakSocket) noexcept try -{ - ctsMediaStreamServerImpl::InitOnce(); - if (const auto sharedSocket = weakSocket.lock()) + namespace ctsMediaStreamServerImpl { - ctsMediaStreamServerImpl::RemoveSocket(sharedSocket->GetRemoteSockaddr()); - } -} -catch (...) -{ -} + // function for doing the actual IO for a UDP media stream datagram connection + static wsIOResult ConnectedSocketIo(_In_ ctsMediaStreamServerConnectedSocket* connectedSocket) noexcept; + static std::vector> g_listeningSockets; // NOLINT(clang-diagnostic-exit-time-destructors) -namespace ctsMediaStreamServerImpl -{ - // function for doing the actual IO for a UDP media stream datagram connection - wsIOResult ConnectedSocketIo(_In_ ctsMediaStreamServerConnectedSocket* connectedSocket) noexcept; + static wil::critical_section g_socketVectorGuard{ ctsConfig::ctsConfigSettings::c_CriticalSectionSpinlock }; // NOLINT(cppcoreguidelines-interfaces-global-init, clang-diagnostic-exit-time-destructors) - std::vector> g_listeningSockets; // NOLINT(clang-diagnostic-exit-time-destructors) + _Guarded_by_(g_socketVectorGuard) static std::vector> g_connectedSockets; // NOLINT(clang-diagnostic-exit-time-destructors) - wil::critical_section g_socketVectorGuard{ctsConfig::ctsConfigSettings::c_CriticalSectionSpinlock}; // NOLINT(cppcoreguidelines-interfaces-global-init, clang-diagnostic-exit-time-destructors) - _Guarded_by_(g_socketVectorGuard) std::vector> g_connectedSockets; // NOLINT(clang-diagnostic-exit-time-destructors) - // weak_ptr<> to ctsSocket objects ready to accept a connection - _Guarded_by_(g_socketVectorGuard) std::vector> g_acceptingSockets; // NOLINT(clang-diagnostic-exit-time-destructors) - // endpoints that have been received from clients not yet matched to ctsSockets - _Guarded_by_(g_socketVectorGuard) std::vector> g_awaitingEndpoints; // NOLINT(clang-diagnostic-exit-time-destructors) + // weak_ptr<> to ctsSocket objects ready to accept a connection + _Guarded_by_(g_socketVectorGuard) static std::vector> g_acceptingSockets; // NOLINT(clang-diagnostic-exit-time-destructors) + // endpoints that have been received from clients not yet matched to ctsSockets + _Guarded_by_(g_socketVectorGuard) static std::vector> g_awaitingEndpoints; // NOLINT(clang-diagnostic-exit-time-destructors) - // Singleton values used as the actual implementation for every 'connection' - // ReSharper disable once CppZeroConstantCanBeReplacedWithNullptr - static INIT_ONCE g_initImpl = INIT_ONCE_STATIC_INIT; + // Singleton values used as the actual implementation for every 'connection' - static BOOL CALLBACK InitOnceImpl(PINIT_ONCE, PVOID, PVOID*) noexcept try - { - // 'listen' to each address - for (const auto& addr : ctsConfig::g_configSettings->ListenAddresses) + // ReSharper disable once CppZeroConstantCanBeReplacedWithNullptr + static INIT_ONCE g_initImpl = INIT_ONCE_STATIC_INIT; + + static BOOL CALLBACK InitOnceImpl(PINIT_ONCE, PVOID, PVOID*) noexcept try { - wil::unique_socket listening(ctsConfig::CreateSocket(addr.family(), SOCK_DGRAM, IPPROTO_UDP, ctsConfig::g_configSettings->SocketFlags)); + // 'listen' to each address + for (const auto& addr : ctsConfig::g_configSettings->ListenAddresses) + { + wil::unique_socket listening(ctsConfig::CreateSocket(addr.family(), SOCK_DGRAM, IPPROTO_UDP, ctsConfig::g_configSettings->SocketFlags)); + + auto error = ctsConfig::SetPreBindOptions(listening.get(), addr); + if (error != NO_ERROR) + { + THROW_WIN32_MSG(error, "SetPreBindOptions (ctsMediaStreamServer)"); + } - auto error = ctsConfig::SetPreBindOptions(listening.get(), addr); - if (error != NO_ERROR) + if (SOCKET_ERROR == bind(listening.get(), addr.sockaddr(), addr.length())) + { + error = WSAGetLastError(); + char addrBuffer[ctl::ctSockaddr::FixedStringLength]{}; + addr.writeAddress(addrBuffer); + THROW_WIN32_MSG(error, "bind %hs (ctsMediaStreamServer)", addrBuffer); + } + + // capture the socket value before moved into the vector + const SOCKET listeningSocketToPrint(listening.get()); + g_listeningSockets.emplace_back( + std::make_unique(std::move(listening), addr)); + PRINT_DEBUG_INFO( + L"\t\tctsMediaStreamServer - Receiving datagrams on %ws (%Iu)\n", + addr.writeCompleteAddress().c_str(), + listeningSocketToPrint); + } + + if (g_listeningSockets.empty()) { - THROW_WIN32_MSG(error, "SetPreBindOptions (ctsMediaStreamServer)"); + throw std::exception("ctsMediaStreamServer invoked with no listening addresses specified"); } - if (SOCKET_ERROR == bind(listening.get(), addr.sockaddr(), addr.length())) + // initiate the recv's in the 'listening' sockets + for (const auto& listener : g_listeningSockets) { - error = WSAGetLastError(); - char addrBuffer[ctl::ctSockaddr::FixedStringLength]{}; - addr.writeAddress(addrBuffer); - THROW_WIN32_MSG(error, "bind %hs (ctsMediaStreamServer)", addrBuffer); + listener->InitiateRecv(); } - // capture the socket value before moved into the vector - const SOCKET listeningSocketToPrint(listening.get()); - g_listeningSockets.emplace_back( - std::make_unique(std::move(listening), addr)); - PRINT_DEBUG_INFO( - L"\t\tctsMediaStreamServer - Receiving datagrams on %ws (%Iu)\n", - addr.writeCompleteAddress().c_str(), - listeningSocketToPrint); + return TRUE; } - - if (g_listeningSockets.empty()) + catch (...) { - throw std::exception("ctsMediaStreamServer invoked with no listening addresses specified"); + ctsConfig::PrintThrownException(); + return FALSE; } - // initiate the recv's in the 'listening' sockets - for (const auto& listener : g_listeningSockets) + void InitOnce() { - listener->InitiateRecv(); + if (!InitOnceExecuteOnce(&g_initImpl, InitOnceImpl, nullptr, nullptr)) + { + throw std::runtime_error("ctsMediaStreamServerListener could not be instantiated"); + } } - return TRUE; - } - catch (...) - { - ctsConfig::PrintThrownException(); - return FALSE; - } - - void InitOnce() - { - if (!InitOnceExecuteOnce(&g_initImpl, InitOnceImpl, nullptr, nullptr)) + // Schedule the first IO on the specified ctsSocket + void ScheduleIo(const std::weak_ptr& weakSocket, const ctsTask& task) { - throw std::runtime_error("ctsMediaStreamServerListener could not be instantiated"); - } - } + auto sharedSocket = weakSocket.lock(); + if (!sharedSocket) + { + THROW_WIN32_MSG(WSAECONNABORTED, "ctsSocket already freed"); + } - // Schedule the first IO on the specified ctsSocket - void ScheduleIo(const std::weak_ptr& weakSocket, const ctsTask& task) - { - auto sharedSocket = weakSocket.lock(); - if (!sharedSocket) - { - THROW_WIN32_MSG(WSAECONNABORTED, "ctsSocket already freed"); - } + std::shared_ptr sharedConnectedSocket; + { + // must guard connected_sockets since we need to add it + const auto lockConnectedObject = g_socketVectorGuard.lock(); - std::shared_ptr sharedConnectedSocket; - { - // must guard connected_sockets since we need to add it - const auto lockConnectedObject = g_socketVectorGuard.lock(); + // find the matching connected_socket + const auto foundSocket = std::ranges::find_if( + g_connectedSockets, + [&sharedSocket](const std::shared_ptr& connectedSocket) noexcept { + return sharedSocket->GetRemoteSockaddr() == connectedSocket->GetRemoteAddress(); + } + ); - // find the matching connected_socket - const auto foundSocket = std::ranges::find_if( - g_connectedSockets, - [&sharedSocket](const std::shared_ptr& connectedSocket) noexcept { - return sharedSocket->GetRemoteSockaddr() == connectedSocket->GetRemoteAddress(); + if (foundSocket == std::end(g_connectedSockets)) + { + ctsConfig::PrintErrorInfo( + L"ctsMediaStreamServer - failed to find the socket with remote address %ws in our connected socket list to continue sending datagrams", + sharedSocket->GetRemoteSockaddr().writeCompleteAddress().c_str()); + THROW_WIN32_MSG(ERROR_INVALID_DATA, "ctsSocket was not found in the connected sockets to continue sending datagrams"); } - ); - if (foundSocket == std::end(g_connectedSockets)) - { - ctsConfig::PrintErrorInfo( - L"ctsMediaStreamServer - failed to find the socket with remote address %ws in our connected socket list to continue sending datagrams", - sharedSocket->GetRemoteSockaddr().writeCompleteAddress().c_str()); - THROW_WIN32_MSG(ERROR_INVALID_DATA, "ctsSocket was not found in the connected sockets to continue sending datagrams"); + sharedConnectedSocket = *foundSocket; } - - sharedConnectedSocket = *foundSocket; + // must call into connected socket without holding a lock + // and without maintaining an iterator into the list + // since the call to schedule_io could end up asking to remove this object from the list + sharedConnectedSocket->ScheduleTask(task); } - // must call into connected socket without holding a lock - // and without maintaining an iterator into the list - // since the call to schedule_io could end up asking to remove this object from the list - sharedConnectedSocket->ScheduleTask(task); - } - // Process a new ctsSocket from the ctsSocketBroker - // - accept_socket takes the ctsSocket to create a new entry - // which will create a corresponding ctsMediaStreamServerConnectedSocket in the process - void AcceptSocket(const std::weak_ptr& weakSocket) - { - if (const auto sharedSocket = weakSocket.lock()) + // Process a new ctsSocket from the ctsSocketBroker + // - accept_socket takes the ctsSocket to create a new entry + // which will create a corresponding ctsMediaStreamServerConnectedSocket in the process + void AcceptSocket(const std::weak_ptr& weakSocket) { - const auto lockAwaitingObject = g_socketVectorGuard.lock(); - - if (g_awaitingEndpoints.empty()) + if (const auto sharedSocket = weakSocket.lock()) { - // just add it to our accepting sockets vector under the writer lock - g_acceptingSockets.push_back(weakSocket); - } - else - { - auto waitingEndpoint = g_awaitingEndpoints.rbegin(); + const auto lockAwaitingObject = g_socketVectorGuard.lock(); - const auto existingSocket = std::ranges::find_if( - g_connectedSockets, - [&](const std::shared_ptr& connectedSocket) noexcept { - return waitingEndpoint->second == connectedSocket->GetRemoteAddress(); - }); - - if (existingSocket != std::end(g_connectedSockets)) + if (g_awaitingEndpoints.empty()) { - ctsConfig::g_configSettings->UdpStatusDetails.m_duplicateFrames.Increment(); - PRINT_DEBUG_INFO(L"\t\tctsMediaStreamServer::accept_socket - socket with remote address %ws asked to be Started but was already established", - waitingEndpoint->second.writeCompleteAddress().c_str()); - // return early if this was a duplicate request: this can happen if there is latency or drops - // between the client and server as they attempt to negotiating starting a new stream - return; + // just add it to our accepting sockets vector under the writer lock + g_acceptingSockets.push_back(weakSocket); } + else + { + auto waitingEndpoint = g_awaitingEndpoints.rbegin(); - g_connectedSockets.emplace_back( - std::make_shared( - weakSocket, - waitingEndpoint->first, - waitingEndpoint->second, - ConnectedSocketIo)); - - PRINT_DEBUG_INFO(L"\t\tctsMediaStreamServer::accept_socket - socket with remote address %ws added to connected_sockets", - waitingEndpoint->second.writeCompleteAddress().c_str()); + const auto existingSocket = std::ranges::find_if( + g_connectedSockets, + [&](const std::shared_ptr& connectedSocket) noexcept { + return waitingEndpoint->second == connectedSocket->GetRemoteAddress(); + }); - // now complete the ctsSocket 'Create' request - const auto foundSocket = std::ranges::find_if( - g_listeningSockets, - [&waitingEndpoint](const std::unique_ptr& listener) noexcept { - return listener->GetSocket() == waitingEndpoint->first; - }); - FAIL_FAST_IF_MSG( - foundSocket == g_listeningSockets.end(), - "Could not find the socket (%Iu) in the waiting_endpoint from our listening sockets (%p)\n", - waitingEndpoint->first, &g_listeningSockets); - - sharedSocket->SetLocalSockaddr((*foundSocket)->GetListeningAddress()); - sharedSocket->SetRemoteSockaddr(waitingEndpoint->second); - sharedSocket->CompleteState(NO_ERROR); - - ctsConfig::PrintNewConnection(sharedSocket->GetLocalSockaddr(), sharedSocket->GetRemoteSockaddr()); - // if added to connected_sockets, can then safely remove it from the waiting endpoint - g_awaitingEndpoints.pop_back(); - } - } - } + if (existingSocket != std::end(g_connectedSockets)) + { + ctsConfig::g_configSettings->UdpStatusDetails.m_duplicateFrames.Increment(); + PRINT_DEBUG_INFO(L"\t\tctsMediaStreamServer::accept_socket - socket with remote address %ws asked to be Started but was already established", + waitingEndpoint->second.writeCompleteAddress().c_str()); + // return early if this was a duplicate request: this can happen if there is latency or drops + // between the client and server as they attempt to negotiating starting a new stream + return; + } - // Process the removal of a connected socket once it is completed - // - remove_socket takes the remote address to find the socket - void RemoveSocket(const ctl::ctSockaddr& targetAddr) - { - const auto lockConnectedObject = g_socketVectorGuard.lock(); + g_connectedSockets.emplace_back( + std::make_shared( + weakSocket, + waitingEndpoint->first, + waitingEndpoint->second, + ConnectedSocketIo)); - const auto foundSocket = std::ranges::find_if( - g_connectedSockets, - [&targetAddr](const std::shared_ptr& connectedSocket) noexcept { - return targetAddr == connectedSocket->GetRemoteAddress(); - }); + PRINT_DEBUG_INFO(L"\t\tctsMediaStreamServer::accept_socket - socket with remote address %ws added to connected_sockets", + waitingEndpoint->second.writeCompleteAddress().c_str()); - if (foundSocket != std::end(g_connectedSockets)) - { - g_connectedSockets.erase(foundSocket); + // now complete the ctsSocket 'Create' request + const auto foundSocket = std::ranges::find_if( + g_listeningSockets, + [&waitingEndpoint](const std::unique_ptr& listener) noexcept { + return listener->GetSocket() == waitingEndpoint->first; + }); + FAIL_FAST_IF_MSG( + foundSocket == g_listeningSockets.end(), + "Could not find the socket (%Iu) in the waiting_endpoint from our listening sockets (%p)\n", + waitingEndpoint->first, &g_listeningSockets); + + sharedSocket->SetLocalSockaddr((*foundSocket)->GetListeningAddress()); + sharedSocket->SetRemoteSockaddr(waitingEndpoint->second); + sharedSocket->CompleteState(NO_ERROR); + + ctsConfig::PrintNewConnection(sharedSocket->GetLocalSockaddr(), sharedSocket->GetRemoteSockaddr()); + // if added to connected_sockets, can then safely remove it from the waiting endpoint + g_awaitingEndpoints.pop_back(); + } + } } - } - // Processes the incoming START request from the client - // - if we have a waiting ctsSocket to accept it, will add it to connected_sockets - // - else we'll queue it to awaiting_endpoints - void Start(SOCKET socket, const ctl::ctSockaddr& localAddr, const ctl::ctSockaddr& targetAddr) - { - const auto lockAwaitingObject = g_socketVectorGuard.lock(); - - const auto existingSocket = std::ranges::find_if( - g_connectedSockets, - [&targetAddr](const std::shared_ptr& connectedSocket) noexcept { - return targetAddr == connectedSocket->GetRemoteAddress(); - }); - if (existingSocket != std::end(g_connectedSockets)) + // Process the removal of a connected socket once it is completed + // - remove_socket takes the remote address to find the socket + void RemoveSocket(const ctl::ctSockaddr& targetAddr) { - ctsConfig::g_configSettings->UdpStatusDetails.m_duplicateFrames.Increment(); - PRINT_DEBUG_INFO(L"\t\tctsMediaStreamServer::start - socket with remote address %ws asked to be Started but was already in connected_sockets", - targetAddr.writeCompleteAddress().c_str()); - // return early if this was a duplicate request: this can happen if there is latency or drops - // between the client and server as they attempt to negotiating starting a new stream - return; - } + const auto lockConnectedObject = g_socketVectorGuard.lock(); - const auto awaitingEndpoint = std::ranges::find_if( - g_awaitingEndpoints, - [&targetAddr](const std::pair& endpoint) noexcept { - return targetAddr == endpoint.second; - }); - if (awaitingEndpoint != std::end(g_awaitingEndpoints)) - { - ctsConfig::g_configSettings->UdpStatusDetails.m_duplicateFrames.Increment(); - PRINT_DEBUG_INFO(L"\t\tctsMediaStreamServer::start - socket with remote address %ws asked to be Started but was already in awaiting endpoints", - targetAddr.writeCompleteAddress().c_str()); - // return early if this was a duplicate request: this can happen if there is latency or drops - // between the client and server as they attempt to negotiating starting a new stream - return; + const auto foundSocket = std::ranges::find_if( + g_connectedSockets, + [&targetAddr](const std::shared_ptr& connectedSocket) noexcept { + return targetAddr == connectedSocket->GetRemoteAddress(); + }); + + if (foundSocket != std::end(g_connectedSockets)) + { + g_connectedSockets.erase(foundSocket); + } } - // find a ctsSocket waiting to 'accept' a connection and complete it - auto addToAwaiting = true; - while (!g_acceptingSockets.empty()) + // Processes the incoming START request from the client + // - if we have a waiting ctsSocket to accept it, will add it to connected_sockets + // - else we'll queue it to awaiting_endpoints + void Start(SOCKET socket, const ctl::ctSockaddr& localAddr, const ctl::ctSockaddr& targetAddr) { - auto weakInstance = *g_acceptingSockets.rbegin(); - if (const auto sharedInstance = weakInstance.lock()) + const auto lockAwaitingObject = g_socketVectorGuard.lock(); + + const auto existingSocket = std::ranges::find_if( + g_connectedSockets, + [&targetAddr](const std::shared_ptr& connectedSocket) noexcept { + return targetAddr == connectedSocket->GetRemoteAddress(); + }); + if (existingSocket != std::end(g_connectedSockets)) { - // 'move' the accepting socket to connected - g_connectedSockets.emplace_back( - std::make_shared(weakInstance, socket, targetAddr, ConnectedSocketIo)); + ctsConfig::g_configSettings->UdpStatusDetails.m_duplicateFrames.Increment(); + PRINT_DEBUG_INFO(L"\t\tctsMediaStreamServer::start - socket with remote address %ws asked to be Started but was already in connected_sockets", + targetAddr.writeCompleteAddress().c_str()); + // return early if this was a duplicate request: this can happen if there is latency or drops + // between the client and server as they attempt to negotiating starting a new stream + return; + } - PRINT_DEBUG_INFO(L"\t\tctsMediaStreamServer::start - socket with remote address %ws added to connected_sockets", + const auto awaitingEndpoint = std::ranges::find_if( + g_awaitingEndpoints, + [&targetAddr](const std::pair& endpoint) noexcept { + return targetAddr == endpoint.second; + }); + if (awaitingEndpoint != std::end(g_awaitingEndpoints)) + { + ctsConfig::g_configSettings->UdpStatusDetails.m_duplicateFrames.Increment(); + PRINT_DEBUG_INFO(L"\t\tctsMediaStreamServer::start - socket with remote address %ws asked to be Started but was already in awaiting endpoints", targetAddr.writeCompleteAddress().c_str()); + // return early if this was a duplicate request: this can happen if there is latency or drops + // between the client and server as they attempt to negotiating starting a new stream + return; + } - // verify is successfully added to connected_sockets before popping off accepting_sockets - addToAwaiting = false; - g_acceptingSockets.pop_back(); + // find a ctsSocket waiting to 'accept' a connection and complete it + auto addToAwaiting = true; + while (!g_acceptingSockets.empty()) + { + auto weakInstance = *g_acceptingSockets.rbegin(); + if (const auto sharedInstance = weakInstance.lock()) + { + // 'move' the accepting socket to connected + g_connectedSockets.emplace_back( + std::make_shared(weakInstance, socket, targetAddr, ConnectedSocketIo)); - // now complete the accepted ctsSocket back to the ctsSocketState - sharedInstance->SetLocalSockaddr(localAddr); - sharedInstance->SetRemoteSockaddr(targetAddr); - sharedInstance->CompleteState(NO_ERROR); + PRINT_DEBUG_INFO(L"\t\tctsMediaStreamServer::start - socket with remote address %ws added to connected_sockets", + targetAddr.writeCompleteAddress().c_str()); - ctsConfig::PrintNewConnection(localAddr, targetAddr); - break; - } - } + // verify is successfully added to connected_sockets before popping off accepting_sockets + addToAwaiting = false; + g_acceptingSockets.pop_back(); - // if we didn't find a waiting connection to accept it, queue it for when one arrives later - if (addToAwaiting) - { - PRINT_DEBUG_INFO(L"\t\tctsMediaStreamServer::start - socket with remote address %ws added to awaiting_endpoints", - targetAddr.writeCompleteAddress().c_str()); + // now complete the accepted ctsSocket back to the ctsSocketState + sharedInstance->SetLocalSockaddr(localAddr); + sharedInstance->SetRemoteSockaddr(targetAddr); + sharedInstance->CompleteState(NO_ERROR); - // only queue it if we aren't already waiting on this address - g_awaitingEndpoints.emplace_back(socket, targetAddr); - } - } + ctsConfig::PrintNewConnection(localAddr, targetAddr); + break; + } + } - wsIOResult ConnectedSocketIo(_In_ ctsMediaStreamServerConnectedSocket* connectedSocket) noexcept - { - const SOCKET socket = connectedSocket->GetSendingSocket(); - if (INVALID_SOCKET == socket) - { - return wsIOResult(WSA_OPERATION_ABORTED); - } + // if we didn't find a waiting connection to accept it, queue it for when one arrives later + if (addToAwaiting) + { + PRINT_DEBUG_INFO(L"\t\tctsMediaStreamServer::start - socket with remote address %ws added to awaiting_endpoints", + targetAddr.writeCompleteAddress().c_str()); - const ctl::ctSockaddr& remoteAddr(connectedSocket->GetRemoteAddress()); - // ReSharper disable once CppUseStructuredBinding - const ctsTask nextTask = connectedSocket->GetNextTask(); + // only queue it if we aren't already waiting on this address + g_awaitingEndpoints.emplace_back(socket, targetAddr); + } + } - wsIOResult returnResults; - if (ctsTask::BufferType::UdpConnectionId == nextTask.m_bufferType) + wsIOResult ConnectedSocketIo(_In_ ctsMediaStreamServerConnectedSocket* connectedSocket) noexcept { - // making a synchronous call - WSABUF wsabuffer{}; - wsabuffer.buf = nextTask.m_buffer; - wsabuffer.len = nextTask.m_bufferLength; - - const auto sendResult = WSASendTo( - socket, - &wsabuffer, - 1, - &returnResults.m_bytesTransferred, - 0, - remoteAddr.sockaddr(), - remoteAddr.length(), - nullptr, - nullptr); - - if (SOCKET_ERROR == sendResult) + const SOCKET socket = connectedSocket->GetSendingSocket(); + if (INVALID_SOCKET == socket) { - const auto error = WSAGetLastError(); - ctsConfig::PrintErrorInfo( - L"WSASendTo(%Iu, %ws) for the Connection-ID failed [%d]", - socket, - remoteAddr.writeCompleteAddress().c_str(), - error); - return wsIOResult(error); + return wsIOResult(WSA_OPERATION_ABORTED); } - } - else - { - const auto sequenceNumber = connectedSocket->IncrementSequence(); - PRINT_DEBUG_INFO( - L"\t\tctsMediaStreamServer sending seq number %lld (%lu bytes)\n", - sequenceNumber, - nextTask.m_bufferLength); - - ctsMediaStreamSendRequests sendingRequests( - nextTask.m_bufferLength, // total bytes to send - sequenceNumber, - nextTask.m_buffer); - for (auto& sendRequest : sendingRequests) + + const ctl::ctSockaddr& remoteAddr(connectedSocket->GetRemoteAddress()); + const ctsTask nextTask = connectedSocket->GetNextTask(); + + wsIOResult returnResults; + if (ctsTask::BufferType::UdpConnectionId == nextTask.m_bufferType) { // making a synchronous call - DWORD bytesSent{}; + WSABUF wsaBuffer; + wsaBuffer.buf = nextTask.m_buffer; + wsaBuffer.len = nextTask.m_bufferLength; + const auto sendResult = WSASendTo( socket, - sendRequest.data(), - static_cast(sendRequest.size()), - &bytesSent, + &wsaBuffer, + 1, + &returnResults.m_bytesTransferred, 0, remoteAddr.sockaddr(), remoteAddr.length(), nullptr, nullptr); + if (SOCKET_ERROR == sendResult) { const auto error = WSAGetLastError(); - if (WSAEMSGSIZE == error) + ctsConfig::PrintErrorInfo( + L"WSASendTo(%Iu, %ws) for the Connection-ID failed [%d]", + socket, + remoteAddr.writeCompleteAddress().c_str(), + error); + return wsIOResult(error); + } + } + else + { + const auto sequenceNumber = connectedSocket->IncrementSequence(); + PRINT_DEBUG_INFO( + L"\t\tctsMediaStreamServer sending seq number %lld (%u bytes)\n", + sequenceNumber, + nextTask.m_bufferLength); + + ctsMediaStreamSendRequests sendingRequests( + nextTask.m_bufferLength, // total bytes to send + sequenceNumber, + nextTask.m_buffer); + for (auto& sendRequest : sendingRequests) + { + // making a synchronous call + DWORD bytesSent{}; + const auto sendResult = WSASendTo( + socket, + sendRequest.data(), + static_cast(sendRequest.size()), + &bytesSent, + 0, + remoteAddr.sockaddr(), + remoteAddr.length(), + nullptr, + nullptr); + if (SOCKET_ERROR == sendResult) { - uint32_t bytesRequested = 0; - // iterate across each WSABUF* in the array - // ReSharper disable once CppUseStructuredBinding - for (const auto& wasbuffer : sendRequest) + const auto error = WSAGetLastError(); + if (WSAEMSGSIZE == error) { - bytesRequested += wasbuffer.len; + uint32_t bytesRequested = 0; + // iterate across each WSABUF* in the array + for (const auto& wsaBuffer : sendRequest) + { + bytesRequested += wsaBuffer.len; + } + ctsConfig::PrintErrorInfo( + L"WSASendTo(%Iu, seq %lld, %ws) failed with WSAEMSGSIZE : attempted to send datagram of size %u bytes", + socket, + sequenceNumber, + remoteAddr.writeCompleteAddress().c_str(), + bytesRequested); } - ctsConfig::PrintErrorInfo( - L"WSASendTo(%Iu, seq %lld, %ws) failed with WSAEMSGSIZE : attempted to send datagram of size %u bytes", - socket, - sequenceNumber, - remoteAddr.writeCompleteAddress().c_str(), - bytesRequested); - } - else - { - ctsConfig::PrintErrorInfo( - L"WSASendTo(%Iu, seq %lld, %ws) failed [%d]", - socket, - sequenceNumber, - remoteAddr.writeCompleteAddress().c_str(), - error); + else + { + ctsConfig::PrintErrorInfo( + L"WSASendTo(%Iu, seq %lld, %ws) failed [%d]", + socket, + sequenceNumber, + remoteAddr.writeCompleteAddress().c_str(), + error); + } + return wsIOResult(error); } - return wsIOResult(error); - } - // successfully completed synchronously - returnResults.m_bytesTransferred += bytesSent; + // successfully completed synchronously + returnResults.m_bytesTransferred += bytesSent; + } } - } - return returnResults; + return returnResults; + } } -}} +} diff --git a/ctsTraffic/ctsMediaStreamServer.h b/ctsTraffic/ctsMediaStreamServer.h index 242b9d7..bf9e11d 100644 --- a/ctsTraffic/ctsMediaStreamServer.h +++ b/ctsTraffic/ctsMediaStreamServer.h @@ -46,7 +46,7 @@ namespace ctsTraffic { namespace ctsMediaStreamServerImpl // - remove_socket takes the remote address to find the socket // - cannot be called from a TP callback from ctsMediaStreamServerConnectedSocket // as remove_socket will deadlock as it tries to delete the ctsMediaStreamServerConnectedSocket instance - // (which will wait for all TP threads to complete in the d'tor) + // (which will wait for all TP threads to complete in the destructor) void RemoveSocket(const ctl::ctSockaddr& targetAddr); // Processes the incoming START request from the client diff --git a/ctsTraffic/ctsMediaStreamServerConnectedSocket.cpp b/ctsTraffic/ctsMediaStreamServerConnectedSocket.cpp index 3e75bf7..9670dc0 100644 --- a/ctsTraffic/ctsMediaStreamServerConnectedSocket.cpp +++ b/ctsTraffic/ctsMediaStreamServerConnectedSocket.cpp @@ -48,7 +48,7 @@ ctsMediaStreamServerConnectedSocket::ctsMediaStreamServerConnectedSocket( ctsMediaStreamServerConnectedSocket::~ctsMediaStreamServerConnectedSocket() noexcept { - // stop the TP before letting the d'tor delete any member objects + // stop the TP before letting the destructor delete any member objects m_taskTimer.reset(); } diff --git a/ctsTraffic/ctsPrintStatus.hpp b/ctsTraffic/ctsPrintStatus.hpp index 2062ad1..f13343b 100644 --- a/ctsTraffic/ctsPrintStatus.hpp +++ b/ctsTraffic/ctsPrintStatus.hpp @@ -26,7 +26,7 @@ namespace ctsTraffic class ctsStatusInformation { protected: - enum class PrintingStatus + enum class PrintingStatus : std::uint8_t { PrintComplete, NoPrint @@ -119,8 +119,8 @@ class ctsStatusInformation void RightJustifyOutput(uint32_t rightJustifiedOffset, uint32_t maxLength, float value) noexcept { - constexpr uint32_t coversionBufferLength = 16; - wchar_t conversionBuffer[coversionBufferLength]{}; + constexpr uint32_t conversionBufferLength = 16; + wchar_t conversionBuffer[conversionBufferLength]{}; FAIL_FAST_IF_MSG( rightJustifiedOffset > c_outputBufferSize, @@ -129,14 +129,14 @@ class ctsStatusInformation _Analysis_assume_(rightJustifiedOffset <= c_outputBufferSize); FAIL_FAST_IF_MSG( - maxLength > coversionBufferLength - 1, // minus one for the null terminator + maxLength > conversionBufferLength - 1, // minus one for the null terminator "ctsStatusInformation will only print converted strings up to %u characters long - the number '%u' was given", - coversionBufferLength - 1, maxLength); - _Analysis_assume_(maxLength <= coversionBufferLength - 1); + conversionBufferLength - 1, maxLength); + _Analysis_assume_(maxLength <= conversionBufferLength - 1); const auto converted = _snwprintf_s( conversionBuffer, - coversionBufferLength, + conversionBufferLength, L"%.3f", value); FAIL_FAST_IF(-1 == converted); @@ -151,8 +151,8 @@ class ctsStatusInformation void RightJustifyOutput(uint32_t rightJustifiedOffset, uint32_t maxLength, uint32_t value) noexcept { - constexpr uint32_t coversionBufferLength = 12; - wchar_t conversionBuffer[coversionBufferLength]{}; + constexpr uint32_t conversionBufferLength = 12; + wchar_t conversionBuffer[conversionBufferLength]{}; FAIL_FAST_IF_MSG( rightJustifiedOffset > c_outputBufferSize, @@ -161,14 +161,14 @@ class ctsStatusInformation _Analysis_assume_(rightJustifiedOffset <= c_outputBufferSize); FAIL_FAST_IF_MSG( - maxLength > coversionBufferLength - 1, // minus one for the null terminator + maxLength > conversionBufferLength - 1, // minus one for the null terminator "ctsStatusInformation will only print converted strings up to %u characters long - the number '%u' was given", - coversionBufferLength - 1, maxLength); - _Analysis_assume_(maxLength > coversionBufferLength - 1); + conversionBufferLength - 1, maxLength); + _Analysis_assume_(maxLength > conversionBufferLength - 1); const auto converted = _snwprintf_s( conversionBuffer, - coversionBufferLength, + conversionBufferLength, L"%u", value); FAIL_FAST_IF(-1 == converted); @@ -183,8 +183,8 @@ class ctsStatusInformation void RightJustifyOutput(uint32_t rightJustifiedOffset, uint32_t maxLength, int64_t value) noexcept { - constexpr uint32_t coversionBufferLength = 20; - wchar_t conversionBuffer[coversionBufferLength]{}; + constexpr uint32_t conversionBufferLength = 20; + wchar_t conversionBuffer[conversionBufferLength]{}; FAIL_FAST_IF_MSG( value < 0LL, @@ -199,14 +199,14 @@ class ctsStatusInformation _Analysis_assume_(rightJustifiedOffset <= c_outputBufferSize); FAIL_FAST_IF_MSG( - maxLength > coversionBufferLength - 1, // minus one for the null terminator + maxLength > conversionBufferLength - 1, // minus one for the null terminator "ctsStatusInformation will only print converted strings up to %u characters long - the number '%u' was given", - coversionBufferLength - 1, maxLength); - _Analysis_assume_(maxLength <= coversionBufferLength - 1); + conversionBufferLength - 1, maxLength); + _Analysis_assume_(maxLength <= conversionBufferLength - 1); const auto converted = _snwprintf_s( conversionBuffer, - coversionBufferLength, + conversionBufferLength, L"%lld", value); FAIL_FAST_IF(-1 == converted); @@ -232,11 +232,9 @@ class ctsStatusInformation m_outputBuffer[offset + 2] = L'\0'; } - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Functions to write to the output buffer in CSV formatting - /// - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Functions to write to the output buffer in CSV formatting + // uint32_t AppendCsvOutput(uint32_t offset, uint32_t valueLength, float value, bool addComma = true) noexcept { const auto converted = _snwprintf_s( @@ -332,18 +330,14 @@ class ctsStatusInformation } }; -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// All variables are updated with Interlocked* operations -/// as it's more important to remain responsive than to guarantee -/// all information is reflected in the precise printed line -/// - note that *no* information will be lost -/// all data will be accounted for in either the current printed line -/// or in the next printed line -/// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// All variables are updated with Interlocked* operations +// as it's more important to remain responsive than to guarantee +// all information is reflected in the precise printed line +// - note that *no* information will be lost +// all data will be accounted for in either the current printed line +// or in the next printed line +// class ctsUdpStatusInformation final : public ctsStatusInformation { public: @@ -484,14 +478,10 @@ class ctsUdpStatusInformation final : public ctsStatusInformation static constexpr uint32_t c_errorFramesLength = 7; }; -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// Print function for TCP connections -/// - allows an option for 'detailed' status -/// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Print function for TCP connections +// - allows an option for 'detailed' status +// class ctsTcpStatusInformation final : public ctsStatusInformation { public: diff --git a/ctsTraffic/ctsRioIocp.cpp b/ctsTraffic/ctsRioIocp.cpp index d50cfa8..88a9b43 100644 --- a/ctsTraffic/ctsRioIocp.cpp +++ b/ctsTraffic/ctsRioIocp.cpp @@ -55,14 +55,14 @@ namespace ctsTraffic { namespace Rioiocp // static BOOL CALLBACK InitOnceRioiocp(PINIT_ONCE, PVOID, PVOID*) noexcept; // ReSharper disable once CppZeroConstantCanBeReplacedWithNullptr - static INIT_ONCE g_sharedbufferInitializer = INIT_ONCE_STATIC_INIT; + static INIT_ONCE g_sharedBufferInitializer = INIT_ONCE_STATIC_INIT; // global CRITICAL_SECTION no deleting on exit - not racing during process exit static CRITICAL_SECTION g_queueLock{}; // NOLINT(cppcoreguidelines-interfaces-global-init, clang-diagnostic-exit-time-destructors) static RIO_NOTIFICATION_COMPLETION g_rioNotifySettings; // ReSharper disable once CppZeroConstantCanBeReplacedWithNullptr static RIO_CQ g_rioCompletionQueue = RIO_INVALID_CQ; - static uint32_t g_rioComplectionQueueSize = 0; + static uint32_t g_rioCompletionQueueSize = 0; static uint32_t g_rioCompletionQueueUsed = 0; static HANDLE* g_pRioWorkerThreads = nullptr; static uint32_t g_rioWorkerThreadCount = 0; @@ -72,14 +72,14 @@ namespace ctsTraffic { namespace Rioiocp const auto lock = wil::EnterCriticalSection(&g_queueLock); const ULONG newCqUsed = g_rioCompletionQueueUsed + newSlots; - if (g_rioComplectionQueueSize < newCqUsed) + if (g_rioCompletionQueueSize < newCqUsed) { // fail hard if we are already at the max CQ size and can't grow it for more IO FAIL_FAST_IF_MSG( - (RIO_MAX_CQ_SIZE == g_rioComplectionQueueSize) || (newCqUsed > RIO_MAX_CQ_SIZE), + (RIO_MAX_CQ_SIZE == g_rioCompletionQueueSize) || (newCqUsed > RIO_MAX_CQ_SIZE), "ctsRioIocp: attempting to grow the CQ beyond RIO_MAX_CQ_SIZE"); - // multiply new_cq_used by 1.25 for bettery growth patterns + // multiply new_cq_used by 1.25 for better growth patterns auto newCqSize = static_cast(newCqUsed * 1.25); if (newCqSize > RIO_MAX_CQ_SIZE) { @@ -88,8 +88,8 @@ namespace ctsTraffic { namespace Rioiocp } PRINT_DEBUG_INFO( - L"\t\tctsRioIocp: Resizing the CQ from %u to %u (used slots = %u increasing used slots to %u)\n", - g_rioComplectionQueueSize, + L"\t\tctsRioIocp: Resizing the CQ from %u to %lu (used slots = %u increasing used slots to %lu)\n", + g_rioCompletionQueueSize, newCqSize, g_rioCompletionQueueUsed, newCqUsed); @@ -101,18 +101,16 @@ namespace ctsTraffic { namespace Rioiocp return gle; } - g_rioComplectionQueueSize = newCqSize; + g_rioCompletionQueueSize = newCqSize; } g_rioCompletionQueueUsed = newCqUsed; return ERROR_SUCCESS; } - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Release slots in the CQ - /// - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Release slots in the CQ + // static void ReleaseRoomInCompletionQueue(uint32_t slots) noexcept { const auto lock = wil::EnterCriticalSection(&g_queueLock); @@ -130,12 +128,10 @@ namespace ctsTraffic { namespace Rioiocp g_rioCompletionQueueUsed -= slots; } - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Safely dequeus from the CQ into the supplied RIORESULT vector - /// - will always post a Notify with proper synchronization - /// - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Safely dequeues from the CQ into the supplied RIORESULT vector + // - will always post a Notify with proper synchronization + // static uint32_t DequeFromCompletionQueue(_Out_writes_(c_rioResultArrayLength) RIORESULT* rioResults) noexcept { const auto lock = wil::EnterCriticalSection(&g_queueLock); @@ -148,7 +144,7 @@ namespace ctsTraffic { namespace Rioiocp FAIL_FAST_IF_MSG( // ReSharper disable once CppRedundantParentheses (0 == dequeResultCount) || (RIO_CORRUPT_CQ == dequeResultCount), - "ctRIODequeueCompletion on(%p) returned [%u] : expected to have dequeued IO after being signaled", + "ctRIODequeueCompletion on(%p) returned [%lu] : expected to have dequeued IO after being signaled", g_rioCompletionQueue, dequeResultCount); // Immediately after invoking Dequeue, post another Notify @@ -164,11 +160,9 @@ namespace ctsTraffic { namespace Rioiocp return dequeResultCount; } - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Shutdown all IOCP threads and close the CQ - /// - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Shutdown all IOCP threads and close the CQ + // static void DeleteAllCompletionQueues() noexcept { uint32_t threadsAlive = 0; @@ -188,7 +182,7 @@ namespace ctsTraffic { namespace Rioiocp { // if we can't indicate to exit, kill the process to see why FAIL_FAST_MSG( - "PostQueuedCompletionStatus(%p) failed [%u] to tear down the threadpool", + "PostQueuedCompletionStatus(%p) failed [%lu] to tear down the threadpool", g_rioNotifySettings.Iocp.IocpHandle, GetLastError()); } } @@ -205,7 +199,7 @@ namespace ctsTraffic { namespace Rioiocp { // if we can't wait for the worker threads, kill the process to see why FAIL_FAST_MSG( - "WaitForMultipleObjects(%p) failed [%u] to wait on the threadpool", + "WaitForMultipleObjects(%p) failed [%lu] to wait on the threadpool", &g_pRioWorkerThreads[0], GetLastError()); } } @@ -240,16 +234,14 @@ namespace ctsTraffic { namespace Rioiocp free(g_rioNotifySettings.Iocp.Overlapped); g_rioNotifySettings.Iocp.Overlapped = nullptr; - g_rioComplectionQueueSize = 0; + g_rioCompletionQueueSize = 0; g_rioCompletionQueueUsed = 0; } - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Singleton initialization routine for the global CQ and its corresponding IOCP thread pool - /// - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Singleton initialization routine for the global CQ and its corresponding IOCP thread pool + // static BOOL CALLBACK InitOnceRioiocp(PINIT_ONCE, PVOID, PVOID*) noexcept { FAIL_FAST_IF(!InitializeCriticalSectionEx(&g_queueLock, ctsConfig::ctsConfigSettings::c_CriticalSectionSpinlock, 0)); @@ -304,7 +296,7 @@ namespace ctsTraffic { namespace Rioiocp auto closeCompletionQueueOnError = wil::scope_exit([&]() noexcept { ctl::ctRIOCloseCompletionQueue(g_rioCompletionQueue); }); // now that the CQ is created, update info - g_rioComplectionQueueSize = rioDefaultCqSize; + g_rioCompletionQueueSize = rioDefaultCqSize; g_rioCompletionQueueUsed = 0; // reserve space for handles @@ -358,16 +350,14 @@ namespace ctsTraffic { namespace Rioiocp } } - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// RioSocketContext - /// - /// This ptr is passed through RIO APIs as the SOCKET context for that IO operation - /// - /// This stores all relevant information regarding the RIO SOCKET - /// Including encapsulating the RIO_RQ associated with the socket - /// - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // RioSocketContext + // + // This ptr is passed through RIO APIs as the SOCKET context for that IO operation + // + // This stores all relevant information regarding the RIO SOCKET + // Including encapsulating the RIO_RQ associated with the socket + // class RioSocketContext { wil::critical_section m_lock{ctsConfig::ctsConfigSettings::c_CriticalSectionSpinlock}; @@ -384,7 +374,7 @@ namespace ctsTraffic { namespace Rioiocp // pre-allocate all ctsTasks needed, so we don't alloc/free with each IO request std::vector m_tasks; - // Guarantees that there is roon in the RQ for the next IO request + // Guarantees that there is room in the RQ for the next IO request // Returns NO_ERROR for success, or a Win32 error on failure // Requires m_lock to be held std::tuple MakeRoomInRequestQueue(const ctsTask& nextTask) noexcept @@ -471,7 +461,7 @@ namespace ctsTraffic { namespace Rioiocp return std::make_tuple(NO_ERROR, pReturnTask); } - // Guarantees that there is roon in the RQ for the next IO request + // Guarantees that there is room in the RQ for the next IO request // Requires m_lock to be held void ReleaseRoomInRequestQueue(ctsTask* const pCompletedTask) noexcept { @@ -514,7 +504,7 @@ namespace ctsTraffic { namespace Rioiocp THROW_WIN32_MSG(WSAECONNABORTED, "ctsRioIocp: invalid socket given to RioSocketContext"); } - // hold a reference on the iopattern to ask for the RIO IO count + // hold a reference on the ioPattern to ask for the RIO IO count auto lockedPattern(lockedSocket.GetPattern()); if (!lockedPattern) { @@ -618,7 +608,7 @@ namespace ctsTraffic { namespace Rioiocp if (status != NO_ERROR) { PRINT_DEBUG_INFO( - L"\t\tctsRioIocp Failed: %hs (%d) [ctsRioIocp]\n", functionName, status); + L"\t\tctsRioIocp Failed: %hs (%ld) [ctsRioIocp]\n", functionName, status); } // CompleteIo() to see if the protocol needs to issue more IO @@ -672,7 +662,7 @@ namespace ctsTraffic { namespace Rioiocp const auto sharedSocket(m_weakSocket.lock()); FAIL_FAST_IF_MSG( !sharedSocket, - "RioSocketContext::execute_io (this == %p): the ctsSocket should always be valid - it's now nullshared_socket, get() should always return a valid ptr", this); + "RioSocketContext::execute_io (this == %p): the ctsSocket should always be valid - it's now null, get() should always return a valid ptr", this); // hold onto the RIO socket lock while posting IO on it const auto lockedSocket(sharedSocket->AcquireSocketLock()); @@ -688,7 +678,7 @@ namespace ctsTraffic { namespace Rioiocp } // can't initialize to zero - zero indicates to complete_state() - int32_t ioRefcount = -1; + int32_t ioRefCount = -1; // loop until complete_io() doesn't offer IO auto continueIo = true; // take a lock on our RioSocketContext before evaluating changes @@ -708,11 +698,11 @@ namespace ctsTraffic { namespace Rioiocp if (0 != shutdown(rioSocket, SD_SEND)) { error = WSAGetLastError(); - PRINT_DEBUG_INFO(L"\t\tctsRioIocp Failed: shutdown(SD_SEND) (%u)\n", error); + PRINT_DEBUG_INFO(L"\t\tctsRioIocp Failed: shutdown(SD_SEND) (%lu)\n", error); } else { - PRINT_DEBUG_INFO(L"\t\tctsRioIocp initiated shutdown(SD_SEND) (%u)\n", error); + PRINT_DEBUG_INFO(L"\t\tctsRioIocp initiated shutdown(SD_SEND) (%lu)\n", error); } continueIo = lockedPattern->CompleteIo(nextTask, 0, error) == ctsIoStatus::ContinueIo; continue; @@ -729,8 +719,8 @@ namespace ctsTraffic { namespace Rioiocp } // if we're here, we're attempting IO - // pre-incremenet IO tracking on the socket before issuing the IO - ioRefcount = sharedSocket->IncrementIo(); + // pre-increment IO tracking on the socket before issuing the IO + ioRefCount = sharedSocket->IncrementIo(); // must ensure we have room in the RQ & CQ before initiating the IO // as well as getting a ctsTask* that we'll be using for this IO @@ -785,24 +775,22 @@ namespace ctsTraffic { namespace Rioiocp ctsConfig::PrintErrorIfFailed(pRioFunction, error); continueIo = lockedPattern->CompleteIo(nextTask, 0, error) == ctsIoStatus::ContinueIo; - ioRefcount = sharedSocket->DecrementIo(); + ioRefCount = sharedSocket->DecrementIo(); } } // while (...) - return ioRefcount; + return ioRefCount; } }; - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Logic for the thread pool function - /// - /// - Wait for Notify to wake up the IOCP - /// - once notified, take a reader lock over the cq (hold off the writers) - /// - subsequently taking the CS - /// - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Logic for the thread pool function + // + // - Wait for Notify to wake up the IOCP + // - once notified, take a reader lock over the cq (hold off the writers) + // - subsequently taking the CS + // static DWORD WINAPI Rioiocp::RioIocpThreadProc(LPVOID) noexcept // NOLINT(bugprone-exception-escape) { std::array rioResultArray{}; @@ -832,7 +820,7 @@ namespace ctsTraffic { namespace Rioiocp // and making a new CQ FAIL_FAST_IF_MSG( nullptr != pOverlapped, - "GetQueuedCompletionStatus(%p) dequeued a failed IO [%u] - OVERLAPPED [%p]", + "GetQueuedCompletionStatus(%p) dequeued a failed IO [%lu] - OVERLAPPED [%p]", Rioiocp::g_rioNotifySettings.Iocp.IocpHandle, gle, pOverlapped); } @@ -887,7 +875,7 @@ namespace ctsTraffic { namespace Rioiocp // // guarantee fully initialized // - if (!InitOnceExecuteOnce(&Rioiocp::g_sharedbufferInitializer, Rioiocp::InitOnceRioiocp, nullptr, nullptr)) + if (!InitOnceExecuteOnce(&Rioiocp::g_sharedBufferInitializer, Rioiocp::InitOnceRioiocp, nullptr, nullptr)) { auto gle = GetLastError(); if (0 == gle) @@ -900,9 +888,9 @@ namespace ctsTraffic { namespace Rioiocp } // - // context ptrs are declared outside the try block + // context pointers are declared outside the try block // - in the case something fails - // - we must pass these as raw ptrs to RIO, so can't use std containers + // - we must pass these as raw pointers to RIO, so can't use std containers // auto ioCount = 0ul; DWORD error = 0; diff --git a/ctsTraffic/ctsSendRecvIocp.cpp b/ctsTraffic/ctsSendRecvIocp.cpp index 34a0abe..5c23382 100644 --- a/ctsTraffic/ctsSendRecvIocp.cpp +++ b/ctsTraffic/ctsSendRecvIocp.cpp @@ -26,13 +26,13 @@ See the Apache Version 2.0 License for specific language governing permissions a namespace ctsTraffic { - /// forward delcaration + // forward declaration void ctsSendRecvIocp(const std::weak_ptr& weakSocket) noexcept; struct ctsSendRecvStatus { // Winsock error code - uint32_t m_ioErrorcode = NO_ERROR; + uint32_t m_ioErrorCode = NO_ERROR; // flag if to request another ctsIOTask bool m_ioDone = false; // returns if IO was started (since can return !io_done, but I/O wasn't started yet) @@ -123,13 +123,11 @@ namespace ctsTraffic } } - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// Attempts the IO specified in the ctsIOTask on the ctsSocket - /// - /// ** ctsSocket::increment_io must have been called before this function was invoked - /// - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Attempts the IO specified in the ctsIOTask on the ctsSocket + // + // ** ctsSocket::increment_io must have been called before this function was invoked + // static ctsSendRecvStatus ctsSendRecvProcessTask(SOCKET socket, const std::shared_ptr& sharedSocket, const std::shared_ptr& sharedPattern, const ctsTask& nextIo) noexcept { ctsSendRecvStatus returnStatus; @@ -137,11 +135,11 @@ namespace ctsTraffic // if we no longer have a valid socket return early if (INVALID_SOCKET == socket) { - returnStatus.m_ioErrorcode = WSAECONNABORTED; + returnStatus.m_ioErrorCode = WSAECONNABORTED; returnStatus.m_ioStarted = false; returnStatus.m_ioDone = true; // even if the socket was closed we still must complete the IO request - sharedPattern->CompleteIo(nextIo, 0, returnStatus.m_ioErrorcode); + sharedPattern->CompleteIo(nextIo, 0, returnStatus.m_ioErrorCode); return returnStatus; } @@ -149,21 +147,21 @@ namespace ctsTraffic { if (shutdown(socket, SD_SEND) != 0) { - returnStatus.m_ioErrorcode = WSAGetLastError(); - PRINT_DEBUG_INFO(L"\t\tIO Failed: shutdown(SD_SEND) (%d) [ctsSendRecvIocp]\n", returnStatus.m_ioErrorcode); + returnStatus.m_ioErrorCode = WSAGetLastError(); + PRINT_DEBUG_INFO(L"\t\tIO Failed: shutdown(SD_SEND) (%d) [ctsSendRecvIocp]\n", returnStatus.m_ioErrorCode); } else { - PRINT_DEBUG_INFO(L"\t\tIO successfully called shutdown(SD_SEND) (%d) [ctsSendRecvIocp]\n", returnStatus.m_ioErrorcode); + PRINT_DEBUG_INFO(L"\t\tIO successfully called shutdown(SD_SEND) (%d) [ctsSendRecvIocp]\n", returnStatus.m_ioErrorCode); } - returnStatus.m_ioDone = sharedPattern->CompleteIo(nextIo, 0, returnStatus.m_ioErrorcode) != ctsIoStatus::ContinueIo; + returnStatus.m_ioDone = sharedPattern->CompleteIo(nextIo, 0, returnStatus.m_ioErrorCode) != ctsIoStatus::ContinueIo; returnStatus.m_ioStarted = false; } else if (ctsTaskAction::HardShutdown == nextIo.m_ioAction) { // pass through -1 to force an RST with the closesocket - returnStatus.m_ioErrorcode = sharedSocket->CloseSocket(static_cast(SOCKET_ERROR)); - returnStatus.m_ioDone = sharedPattern->CompleteIo(nextIo, 0, returnStatus.m_ioErrorcode) != ctsIoStatus::ContinueIo; + returnStatus.m_ioErrorCode = sharedSocket->CloseSocket(static_cast(SOCKET_ERROR)); + returnStatus.m_ioDone = sharedPattern->CompleteIo(nextIo, 0, returnStatus.m_ioErrorCode) != ctsIoStatus::ContinueIo; returnStatus.m_ioStarted = false; } else @@ -177,9 +175,9 @@ namespace ctsTraffic ctsSendRecvCompletionCallback(pCallbackOverlapped, weak_reference, nextIo); }); - WSABUF wsabuffer{}; - wsabuffer.buf = nextIo.m_buffer + nextIo.m_bufferOffset; - wsabuffer.len = nextIo.m_bufferLength; + WSABUF wsaBuffer{}; + wsaBuffer.buf = nextIo.m_buffer + nextIo.m_bufferOffset; + wsaBuffer.len = nextIo.m_bufferLength; PCSTR functionName{}; if (ctsTaskAction::Send == nextIo.m_ioAction) @@ -190,29 +188,29 @@ namespace ctsTraffic } functionName = "WSASend"; - if (WSASend(socket, &wsabuffer, 1, nullptr, 0, pOverlapped, nullptr) != 0) + if (WSASend(socket, &wsaBuffer, 1, nullptr, 0, pOverlapped, nullptr) != 0) { - returnStatus.m_ioErrorcode = WSAGetLastError(); + returnStatus.m_ioErrorCode = WSAGetLastError(); } } else { functionName = "WSARecv"; DWORD flags = ctsConfig::g_configSettings->Options & ctsConfig::OptionType::MsgWaitAll ? MSG_WAITALL : 0; - if (WSARecv(socket, &wsabuffer, 1, nullptr, &flags, pOverlapped, nullptr) != 0) + if (WSARecv(socket, &wsaBuffer, 1, nullptr, &flags, pOverlapped, nullptr) != 0) { - returnStatus.m_ioErrorcode = WSAGetLastError(); + returnStatus.m_ioErrorCode = WSAGetLastError(); } } // // not calling complete_io if returned IO pended // not calling complete_io if returned success but not handling inline completions // - if (WSA_IO_PENDING == returnStatus.m_ioErrorcode || + if (WSA_IO_PENDING == returnStatus.m_ioErrorCode || // ReSharper disable once CppRedundantParentheses - (NO_ERROR == returnStatus.m_ioErrorcode && !(ctsConfig::g_configSettings->Options & ctsConfig::OptionType::HandleInlineIocp))) + (NO_ERROR == returnStatus.m_ioErrorCode && !(ctsConfig::g_configSettings->Options & ctsConfig::OptionType::HandleInlineIocp))) { - returnStatus.m_ioErrorcode = NO_ERROR; + returnStatus.m_ioErrorCode = NO_ERROR; returnStatus.m_ioStarted = true; returnStatus.m_ioDone = false; } @@ -222,7 +220,7 @@ namespace ctsTraffic returnStatus.m_ioStarted = false; // determine # of bytes transferred, if any DWORD bytesTransferred = 0; - if (NO_ERROR == returnStatus.m_ioErrorcode) + if (NO_ERROR == returnStatus.m_ioErrorCode) { DWORD flags; if (!WSAGetOverlappedResult(socket, pOverlapped, &bytesTransferred, FALSE, &flags)) @@ -233,25 +231,25 @@ namespace ctsTraffic } else { - PRINT_DEBUG_INFO(L"\t\tIO Failed: %hs (%d) [ctsSendRecvIocp]\n", functionName, returnStatus.m_ioErrorcode); + PRINT_DEBUG_INFO(L"\t\tIO Failed: %hs (%d) [ctsSendRecvIocp]\n", functionName, returnStatus.m_ioErrorCode); } // must cancel the IOCP TP since IO is not pended ioThreadPool->cancel_request(pOverlapped); // call back to the socket to see if it wants more IO - switch (const ctsIoStatus protocolStatus = sharedPattern->CompleteIo(nextIo, bytesTransferred, returnStatus.m_ioErrorcode)) + switch (const ctsIoStatus protocolStatus = sharedPattern->CompleteIo(nextIo, bytesTransferred, returnStatus.m_ioErrorCode)) { case ctsIoStatus::ContinueIo: // The protocol layer wants to transfer more data // if the prior IO request failed, the protocol wants to ignore the error - returnStatus.m_ioErrorcode = NO_ERROR; + returnStatus.m_ioErrorCode = NO_ERROR; returnStatus.m_ioDone = false; break; case ctsIoStatus::CompletedIo: // The protocol layer has successfully complete all IO on this connection // if the prior IO request failed, the protocol wants to ignore the error - returnStatus.m_ioErrorcode = NO_ERROR; + returnStatus.m_ioErrorCode = NO_ERROR; returnStatus.m_ioDone = true; break; @@ -259,7 +257,7 @@ namespace ctsTraffic // write out the error ctsConfig::PrintErrorIfFailed(functionName, sharedPattern->GetLastPatternError()); // the protocol acknowledged the failure - socket is done with IO - returnStatus.m_ioErrorcode = sharedPattern->GetLastPatternError(); + returnStatus.m_ioErrorCode = sharedPattern->GetLastPatternError(); returnStatus.m_ioDone = true; break; @@ -270,8 +268,8 @@ namespace ctsTraffic } catch (...) { - returnStatus.m_ioErrorcode = ctsConfig::PrintThrownException(); - returnStatus.m_ioDone = sharedPattern->CompleteIo(nextIo, 0, returnStatus.m_ioErrorcode) != ctsIoStatus::ContinueIo; + returnStatus.m_ioErrorCode = ctsConfig::PrintThrownException(); + returnStatus.m_ioDone = sharedPattern->CompleteIo(nextIo, 0, returnStatus.m_ioErrorCode) != ctsIoStatus::ContinueIo; returnStatus.m_ioStarted = false; } } @@ -279,12 +277,10 @@ namespace ctsTraffic return returnStatus; } - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// - /// This is the callback for the threadpool timer. - /// Processes the given task and then calls ctsSendRecvIocp function to deal with any additional tasks - /// - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // This is the callback for the threadpool timer. + // Processes the given task and then calls ctsSendRecvIocp function to deal with any additional tasks + // static void ctsSendRecvTimerCallback(const std::weak_ptr& weakSocket, const ctsTask& nextIo) noexcept { // attempt to get a reference to the socket @@ -308,7 +304,6 @@ namespace ctsTraffic sharedSocket->IncrementIo(); // run the ctsIOTask (next_io) that was scheduled through the TP timer - // ReSharper disable once CppUseStructuredBinding const ctsSendRecvStatus status = ctsSendRecvProcessTask(lockedSocket.GetSocket(), sharedSocket, lockedPattern, nextIo); // if no IO was started, decrement the IO counter if (!status.m_ioStarted) @@ -317,7 +312,7 @@ namespace ctsTraffic { // this should never be zero since we should be holding a ref-count for this callback FAIL_FAST_MSG( - "The refcount of the ctsSocket object (%p) fell to zero during a scheduled callback", sharedSocket.get()); + "The ref-count of the ctsSocket object (%p) fell to zero during a scheduled callback", sharedSocket.get()); } } // continue requesting IO if this connection still isn't done with all IO after scheduling the prior IO @@ -329,7 +324,7 @@ namespace ctsTraffic if (sharedSocket->DecrementIo() == 0) { // if we have no more IO pended, complete the state - sharedSocket->CompleteState(status.m_ioErrorcode); + sharedSocket->CompleteState(status.m_ioErrorCode); } } @@ -388,7 +383,7 @@ namespace ctsTraffic } catch (...) { - status.m_ioErrorcode = ctsConfig::PrintThrownException(); + status.m_ioErrorCode = ctsConfig::PrintThrownException(); status.m_ioStarted = false; } } @@ -405,14 +400,14 @@ namespace ctsTraffic { // this should never be zero as we are holding a reference outside the loop FAIL_FAST_MSG( - "The ctsSocket (%p) refcount fell to zero while this function was holding a reference", sharedSocket.get()); + "The ctsSocket (%p) ref-count fell to zero while this function was holding a reference", sharedSocket.get()); } } } // decrement IO at the end to release the ref-count held before the loop if (0 == sharedSocket->DecrementIo()) { - sharedSocket->CompleteState(status.m_ioErrorcode); + sharedSocket->CompleteState(status.m_ioErrorCode); } } } // namespace diff --git a/ctsTraffic/ctsSimpleAccept.cpp b/ctsTraffic/ctsSimpleAccept.cpp index 77b37c8..dfe4e6d 100644 --- a/ctsTraffic/ctsSimpleAccept.cpp +++ b/ctsTraffic/ctsSimpleAccept.cpp @@ -244,7 +244,7 @@ namespace details } }; - std::shared_ptr g_pimpl; // NOLINT(clang-diagnostic-exit-time-destructors) + static std::shared_ptr g_pimpl; // NOLINT(clang-diagnostic-exit-time-destructors) // ReSharper disable once CppZeroConstantCanBeReplacedWithNullptr static INIT_ONCE g_ctsSimpleAcceptImplInitOnce = INIT_ONCE_STATIC_INIT; diff --git a/ctsTraffic/ctsSocket.cpp b/ctsTraffic/ctsSocket.cpp index a6a79e6..058f6d7 100644 --- a/ctsTraffic/ctsSocket.cpp +++ b/ctsTraffic/ctsSocket.cpp @@ -139,7 +139,7 @@ namespace ctsTraffic const auto lock = m_lock.lock(); FAIL_FAST_IF_MSG( m_ioCount != 0, - "ctsSocket::complete_state is called with outstanding IO (%d)", m_ioCount); + "ctsSocket::complete_state is called with outstanding IO (%ld)", m_ioCount); if (m_pattern) { @@ -191,7 +191,7 @@ namespace ctsTraffic if (ctsConfig::g_configSettings->PrePostSends == 0) { // user didn't specify a specific # of sends to pend - // start ISB notifications (best effort) + // start ISB notifications (best-effort) InitiateIsbNotification(); } } @@ -241,7 +241,7 @@ namespace ctsTraffic if (0 == idealsendbacklogquery(lambdaSocket, &isb)) { const auto lock = lambdaSharedThis->m_lock.lock(); - PRINT_DEBUG_INFO(L"\t\tctsSocket::process_isb_notification : setting ISB to %u bytes\n", isb); + PRINT_DEBUG_INFO(L"\t\tctsSocket::process_isb_notification : setting ISB to %lu bytes\n", isb); lambdaSharedThis->m_pattern->SetIdealSendBacklog(isb); } else @@ -299,7 +299,7 @@ namespace ctsTraffic --m_ioCount; FAIL_FAST_IF_MSG( m_ioCount < 0, - "ctsSocket: io count fell below zero (%d)\n", m_ioCount); + "ctsSocket: io count fell below zero (%ld)\n", m_ioCount); return m_ioCount; } diff --git a/ctsTraffic/ctsSocket.h b/ctsTraffic/ctsSocket.h index b180dae..6cc3587 100644 --- a/ctsTraffic/ctsSocket.h +++ b/ctsTraffic/ctsSocket.h @@ -80,7 +80,7 @@ class ctsSocket : public std::enable_shared_from_this [[nodiscard]] SocketReference AcquireSocketLock() const noexcept; // - // c'tor requiring a parent ctsSocketState weak reference + // constructor requiring a parent ctsSocketState weak reference // explicit ctsSocket(std::weak_ptr parent) noexcept; diff --git a/ctsTraffic/ctsSocketBroker.cpp b/ctsTraffic/ctsSocketBroker.cpp index be971f5..51d95fc 100644 --- a/ctsTraffic/ctsSocketBroker.cpp +++ b/ctsTraffic/ctsSocketBroker.cpp @@ -173,7 +173,7 @@ bool ctsSocketBroker::Wait(DWORD milliseconds) const noexcept default: FAIL_FAST_MSG( - "ctsSocketBroker - WaitForMultipleObjects(%p) failed [%u]", + "ctsSocketBroker - WaitForMultipleObjects(%p) failed [%lu]", arWait, GetLastError()); } return fReturn; diff --git a/ctsTraffic/ctsSocketBroker.h b/ctsTraffic/ctsSocketBroker.h index e6f885e..8c9b769 100644 --- a/ctsTraffic/ctsSocketBroker.h +++ b/ctsTraffic/ctsSocketBroker.h @@ -39,7 +39,7 @@ class ctsSocketBroker : public std::enable_shared_from_this // - create new sockets static uint32_t m_timerCallbackTimeoutMs; - // only the c'tor can throw + // only the constructor can throw ctsSocketBroker(); ~ctsSocketBroker() noexcept; diff --git a/ctsTraffic/ctsSocketState.h b/ctsTraffic/ctsSocketState.h index d23fe31..266b433 100644 --- a/ctsTraffic/ctsSocketState.h +++ b/ctsTraffic/ctsSocketState.h @@ -45,7 +45,7 @@ class ctsSocket; class ctsSocketState : public std::enable_shared_from_this { public: - enum class InternalState + enum class InternalState : std::uint8_t { Creating, Created, @@ -57,16 +57,14 @@ class ctsSocketState : public std::enable_shared_from_this Closed }; - // - // c'tor requiring a parent ctsSocketBroker - // + // constructor requires a parent ctsSocketBroker explicit ctsSocketState(std::weak_ptr pBroker); ~ctsSocketState() noexcept; // // explicit method to 'start' the state machine - // - this is required to ensure the object is fully instatiated before + // - this is required to ensure the object is fully instantiated before // it is passed to the threadpool thread // void Start() noexcept; @@ -81,9 +79,6 @@ class ctsSocketState : public std::enable_shared_from_this // InternalState GetCurrentState() const noexcept; - // - // copy c'tor and assignment - // ctsSocketState(const ctsSocketState&) = delete; ctsSocketState& operator=(const ctsSocketState&) = delete; ctsSocketState(ctsSocketState&&) = delete; diff --git a/ctsTraffic/ctsStatistics.hpp b/ctsTraffic/ctsStatistics.hpp index ebb3b82..a1375ef 100644 --- a/ctsTraffic/ctsStatistics.hpp +++ b/ctsTraffic/ctsStatistics.hpp @@ -47,7 +47,7 @@ namespace ctsTraffic { namespace ctsStatistics FAIL_FAST_IF_MSG( // ReSharper disable once CppRedundantParentheses strlen(reinterpret_cast(connectionIdString)) != (ConnectionIdLength - 1), - "UuidToString returned a string not 36 characters long (%Iu)", + "UuidToString returned a string not 36 characters long (%zu)", strlen(reinterpret_cast(connectionIdString))); const auto copyError = ::memcpy_s(statisticsObject.m_connectionIdentifier, ConnectionIdLength, connectionIdString, ConnectionIdLength); @@ -247,7 +247,7 @@ namespace ctsTraffic { namespace ctsStatistics ctsConnectionStatistics(const ctsConnectionStatistics&) = default; ctsConnectionStatistics(ctsConnectionStatistics&&) = default; // not implementing the assignment operator - // only implemeting the copy c'tor (due to maintaining memory barriers) + // only implementing the copy constructor (due to maintaining memory barriers) ctsConnectionStatistics& operator=(const ctsConnectionStatistics&) = delete; ctsConnectionStatistics& operator=(ctsConnectionStatistics&&) = delete; diff --git a/ctsTraffic/ctsTraffic.cpp b/ctsTraffic/ctsTraffic.cpp index b88ffab..ce32c84 100644 --- a/ctsTraffic/ctsTraffic.cpp +++ b/ctsTraffic/ctsTraffic.cpp @@ -15,6 +15,7 @@ See the Apache Version 2.0 License for specific language governing permissions a #include "targetver.h" // CRT headers +#include #include #include // os headers @@ -32,9 +33,9 @@ using namespace std; // global ptr for easing debugging -ctsSocketBroker* g_socketBroker = nullptr; +static ctsSocketBroker* g_socketBroker = nullptr; -BOOL WINAPI CtrlBreakHandlerRoutine(DWORD) noexcept +static BOOL WINAPI CtrlBreakHandlerRoutine(DWORD) noexcept { // handle all exit types - notify config that it's time to shut down ctsConfig::PrintSummary(L"\n **** ctrl-break hit -- shutting down ****\n"); @@ -208,9 +209,7 @@ int __cdecl wmain(int argc, _In_reads_z_(argc) const wchar_t** argv) int64_t errorCount = ctsConfig::g_configSettings->ConnectionStatusDetails.m_connectionErrorCount.GetValue() + ctsConfig::g_configSettings->ConnectionStatusDetails.m_protocolErrorCount.GetValue(); - if (errorCount > MAXINT) - { - errorCount = MAXINT; - } + + errorCount = std::min(errorCount, MAXINT); return static_cast(errorCount); } diff --git a/ctsTraffic/ctsTraffic.vcxproj b/ctsTraffic/ctsTraffic.vcxproj index c89244d..6e1acfa 100644 --- a/ctsTraffic/ctsTraffic.vcxproj +++ b/ctsTraffic/ctsTraffic.vcxproj @@ -137,7 +137,7 @@ ..\ctl;%(AdditionalIncludeDirectories) false - /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /permissive- + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" /permissive- true StdCall stdcpplatest @@ -182,7 +182,7 @@ ..\ctl;%(AdditionalIncludeDirectories) false - /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /permissive- + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" /permissive- true StdCall false @@ -228,7 +228,7 @@ ..\ctl;%(AdditionalIncludeDirectories) false - /D "_WIN32_WINNT=_WIN32_WINNT_WIN10" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /permissive- + /D "_WIN32_WINNT=_WIN32_WINNT_WIN10" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" /permissive- true false stdcpplatest @@ -269,7 +269,7 @@ true - /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /Qvec-report:2 /Zc:strictStrings /Gw /permissive- + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" /Qvec-report:2 /Zc:strictStrings /Gw /permissive- true true StdCall @@ -319,7 +319,7 @@ Speed - /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /Zc:strictStrings /Gw /permissive- /Qfast_transcendentals /volatile:iso + /D "_WIN32_WINNT=_WIN32_WINNT_WIN7" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" /Zc:strictStrings /Gw /permissive- /Qfast_transcendentals /volatile:iso true true true @@ -373,7 +373,7 @@ Speed - /D "_WIN32_WINNT=_WIN32_WINNT_WIN10" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /Zc:strictStrings /Gw /permissive- /Qfast_transcendentals /volatile:iso + /D "_WIN32_WINNT=_WIN32_WINNT_WIN10" /D "_WINSOCK_DEPRECATED_NO_WARNINGS" /D "NOMINMAX" /Zc:strictStrings /Gw /permissive- /Qfast_transcendentals /volatile:iso true true true diff --git a/ctsTraffic/ctsTraffic.vcxproj.filters b/ctsTraffic/ctsTraffic.vcxproj.filters index 10e0c47..eade0c4 100644 --- a/ctsTraffic/ctsTraffic.vcxproj.filters +++ b/ctsTraffic/ctsTraffic.vcxproj.filters @@ -252,4 +252,7 @@ Resource Files + + + \ No newline at end of file diff --git a/ctsTraffic/ctsWSASocket.cpp b/ctsTraffic/ctsWSASocket.cpp index 93e88e7..9b23c8f 100644 --- a/ctsTraffic/ctsWSASocket.cpp +++ b/ctsTraffic/ctsWSASocket.cpp @@ -162,7 +162,7 @@ namespace ctsTraffic if (WSAEADDRINUSE == gle) { constexpr uint32_t bindRetrySleepMs = 1000; - PRINT_DEBUG_INFO(L"\t\tctsWSASocket : bind failed on attempt %ld, sleeping %lu ms.\n", bindRetry + 1, bindRetrySleepMs); + PRINT_DEBUG_INFO(L"\t\tctsWSASocket : bind failed on attempt %d, sleeping %u ms.\n", bindRetry + 1, bindRetrySleepMs); Sleep(bindRetrySleepMs); } } @@ -170,7 +170,7 @@ namespace ctsTraffic { // succeeded - exit the loop gle = NO_ERROR; - PRINT_DEBUG_INFO(L"\t\tctsWSASocket : bind succeeded on attempt %ld\n", bindRetry + 1); + PRINT_DEBUG_INFO(L"\t\tctsWSASocket : bind succeeded on attempt %d\n", bindRetry + 1); break; } } diff --git a/ctsTraffic/ctsWinsockLayer.h b/ctsTraffic/ctsWinsockLayer.h index 50da675..8f34a47 100644 --- a/ctsTraffic/ctsWinsockLayer.h +++ b/ctsTraffic/ctsWinsockLayer.h @@ -39,7 +39,7 @@ See the Apache Version 2.0 License for specific language governing permissions a namespace ctsTraffic { // this is only defined in the public header for Windows 10 RS2 and later -enum TCPSTATE +enum TCPSTATE : std::uint8_t { TCPSTATE_CLOSED, TCPSTATE_LISTEN,