зеркало из https://github.com/Azure/DotNetty.git
[0.7.3] Target net5 and net6 (#588)
* [0.7.2] Start threads as background in HashedWheelTimer, LoopExecutor, ThreadDeathWatcher * + code formatting * [0.7.3] Target net5 and net6 (#2) target net5 and net6 Adopted TlsHandler for the case when Handshake completion callback is dispatched asynchronously to thread pool Introduced SingleThreadedEmbededChannel for TlsHandler and SniHandler tests * + Update DotNetVersion to "6.0.302" in build.ps1
This commit is contained in:
Родитель
54fd364a93
Коммит
f754c83069
55
DotNetty.sln
55
DotNetty.sln
|
@ -111,180 +111,235 @@ Global
|
|||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Package|Any CPU = Package|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{DF4FF0D0-A5CE-471F-B946-538C28C21CBB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DF4FF0D0-A5CE-471F-B946-538C28C21CBB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DF4FF0D0-A5CE-471F-B946-538C28C21CBB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DF4FF0D0-A5CE-471F-B946-538C28C21CBB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DF4FF0D0-A5CE-471F-B946-538C28C21CBB}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{DF4FF0D0-A5CE-471F-B946-538C28C21CBB}.Package|Any CPU.Build.0 = Package|Any CPU
|
||||
{64508DA2-40F1-4CC3-93E8-EA3B18A64E7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{64508DA2-40F1-4CC3-93E8-EA3B18A64E7E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{64508DA2-40F1-4CC3-93E8-EA3B18A64E7E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{64508DA2-40F1-4CC3-93E8-EA3B18A64E7E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{64508DA2-40F1-4CC3-93E8-EA3B18A64E7E}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{64508DA2-40F1-4CC3-93E8-EA3B18A64E7E}.Package|Any CPU.Build.0 = Package|Any CPU
|
||||
{82796E9E-1331-4858-90C3-8E74BA4CC383}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{82796E9E-1331-4858-90C3-8E74BA4CC383}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{82796E9E-1331-4858-90C3-8E74BA4CC383}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{82796E9E-1331-4858-90C3-8E74BA4CC383}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{82796E9E-1331-4858-90C3-8E74BA4CC383}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{82796E9E-1331-4858-90C3-8E74BA4CC383}.Package|Any CPU.Build.0 = Package|Any CPU
|
||||
{25F7AD69-7836-46E8-9B29-0FBB3C128FFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{25F7AD69-7836-46E8-9B29-0FBB3C128FFB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{25F7AD69-7836-46E8-9B29-0FBB3C128FFB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{25F7AD69-7836-46E8-9B29-0FBB3C128FFB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{25F7AD69-7836-46E8-9B29-0FBB3C128FFB}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{25F7AD69-7836-46E8-9B29-0FBB3C128FFB}.Package|Any CPU.Build.0 = Package|Any CPU
|
||||
{12DCCEFD-623B-46CC-979C-407FA265E239}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{12DCCEFD-623B-46CC-979C-407FA265E239}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{12DCCEFD-623B-46CC-979C-407FA265E239}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{12DCCEFD-623B-46CC-979C-407FA265E239}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{12DCCEFD-623B-46CC-979C-407FA265E239}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{12DCCEFD-623B-46CC-979C-407FA265E239}.Package|Any CPU.Build.0 = Package|Any CPU
|
||||
{5ADB0FF5-8EFC-475A-BF08-6B35EF728329}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5ADB0FF5-8EFC-475A-BF08-6B35EF728329}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5ADB0FF5-8EFC-475A-BF08-6B35EF728329}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5ADB0FF5-8EFC-475A-BF08-6B35EF728329}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5ADB0FF5-8EFC-475A-BF08-6B35EF728329}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{5ADB0FF5-8EFC-475A-BF08-6B35EF728329}.Package|Any CPU.Build.0 = Package|Any CPU
|
||||
{D284C2BF-E06E-481B-B301-503A9D477B0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D284C2BF-E06E-481B-B301-503A9D477B0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D284C2BF-E06E-481B-B301-503A9D477B0E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D284C2BF-E06E-481B-B301-503A9D477B0E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D284C2BF-E06E-481B-B301-503A9D477B0E}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{D284C2BF-E06E-481B-B301-503A9D477B0E}.Package|Any CPU.Build.0 = Package|Any CPU
|
||||
{75A1BCC1-A7F3-4893-99C5-3235F87DB00E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{75A1BCC1-A7F3-4893-99C5-3235F87DB00E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{75A1BCC1-A7F3-4893-99C5-3235F87DB00E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{75A1BCC1-A7F3-4893-99C5-3235F87DB00E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{75A1BCC1-A7F3-4893-99C5-3235F87DB00E}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{75A1BCC1-A7F3-4893-99C5-3235F87DB00E}.Package|Any CPU.Build.0 = Package|Any CPU
|
||||
{1F442118-A665-4891-B056-FE9E54C5B049}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1F442118-A665-4891-B056-FE9E54C5B049}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1F442118-A665-4891-B056-FE9E54C5B049}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1F442118-A665-4891-B056-FE9E54C5B049}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1F442118-A665-4891-B056-FE9E54C5B049}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{1F442118-A665-4891-B056-FE9E54C5B049}.Package|Any CPU.Build.0 = Package|Any CPU
|
||||
{572E1914-489F-402D-944F-71EE0632E5D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{572E1914-489F-402D-944F-71EE0632E5D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{572E1914-489F-402D-944F-71EE0632E5D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{572E1914-489F-402D-944F-71EE0632E5D8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{572E1914-489F-402D-944F-71EE0632E5D8}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{DA54DBAF-CCDA-4AD1-9FF9-EB6F890D1091}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DA54DBAF-CCDA-4AD1-9FF9-EB6F890D1091}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DA54DBAF-CCDA-4AD1-9FF9-EB6F890D1091}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DA54DBAF-CCDA-4AD1-9FF9-EB6F890D1091}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DA54DBAF-CCDA-4AD1-9FF9-EB6F890D1091}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{72C92F76-F804-4300-BFF1-459420D9EF0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{72C92F76-F804-4300-BFF1-459420D9EF0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{72C92F76-F804-4300-BFF1-459420D9EF0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{72C92F76-F804-4300-BFF1-459420D9EF0B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{72C92F76-F804-4300-BFF1-459420D9EF0B}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{E31A5D46-71B7-4B7E-A9F8-3F011822F28A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E31A5D46-71B7-4B7E-A9F8-3F011822F28A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E31A5D46-71B7-4B7E-A9F8-3F011822F28A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E31A5D46-71B7-4B7E-A9F8-3F011822F28A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E31A5D46-71B7-4B7E-A9F8-3F011822F28A}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{3AF8A62F-F5CE-4C2D-B356-8B9FDFA51668}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3AF8A62F-F5CE-4C2D-B356-8B9FDFA51668}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3AF8A62F-F5CE-4C2D-B356-8B9FDFA51668}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3AF8A62F-F5CE-4C2D-B356-8B9FDFA51668}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3AF8A62F-F5CE-4C2D-B356-8B9FDFA51668}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{A7FC497E-790A-4980-B57C-32AF4AD4AB9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A7FC497E-790A-4980-B57C-32AF4AD4AB9D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A7FC497E-790A-4980-B57C-32AF4AD4AB9D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A7FC497E-790A-4980-B57C-32AF4AD4AB9D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A7FC497E-790A-4980-B57C-32AF4AD4AB9D}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{08C19033-23B2-47D7-8332-86273AE287BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{08C19033-23B2-47D7-8332-86273AE287BC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{08C19033-23B2-47D7-8332-86273AE287BC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{08C19033-23B2-47D7-8332-86273AE287BC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{08C19033-23B2-47D7-8332-86273AE287BC}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{CE97D2EC-3EA9-4FEC-B304-F57646DB54FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CE97D2EC-3EA9-4FEC-B304-F57646DB54FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CE97D2EC-3EA9-4FEC-B304-F57646DB54FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CE97D2EC-3EA9-4FEC-B304-F57646DB54FD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CE97D2EC-3EA9-4FEC-B304-F57646DB54FD}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{D0DBB346-BDDA-4E28-A335-6D3E1F9902DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D0DBB346-BDDA-4E28-A335-6D3E1F9902DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D0DBB346-BDDA-4E28-A335-6D3E1F9902DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D0DBB346-BDDA-4E28-A335-6D3E1F9902DF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D0DBB346-BDDA-4E28-A335-6D3E1F9902DF}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{5D5A3137-F118-4F6C-ABE7-2523184A3A2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5D5A3137-F118-4F6C-ABE7-2523184A3A2D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5D5A3137-F118-4F6C-ABE7-2523184A3A2D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5D5A3137-F118-4F6C-ABE7-2523184A3A2D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5D5A3137-F118-4F6C-ABE7-2523184A3A2D}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{BDA099C5-E435-49DF-9922-58D63E11B764}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BDA099C5-E435-49DF-9922-58D63E11B764}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BDA099C5-E435-49DF-9922-58D63E11B764}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BDA099C5-E435-49DF-9922-58D63E11B764}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BDA099C5-E435-49DF-9922-58D63E11B764}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{3DA49C12-3614-40F5-B5CE-8B95F872EFC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3DA49C12-3614-40F5-B5CE-8B95F872EFC1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3DA49C12-3614-40F5-B5CE-8B95F872EFC1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3DA49C12-3614-40F5-B5CE-8B95F872EFC1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3DA49C12-3614-40F5-B5CE-8B95F872EFC1}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{9AE188E0-F328-4A88-AF5F-CE0C1D4D0036}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9AE188E0-F328-4A88-AF5F-CE0C1D4D0036}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9AE188E0-F328-4A88-AF5F-CE0C1D4D0036}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9AE188E0-F328-4A88-AF5F-CE0C1D4D0036}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9AE188E0-F328-4A88-AF5F-CE0C1D4D0036}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{66491D47-2BFB-45CF-A582-C11860219512}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{66491D47-2BFB-45CF-A582-C11860219512}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{66491D47-2BFB-45CF-A582-C11860219512}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{66491D47-2BFB-45CF-A582-C11860219512}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{66491D47-2BFB-45CF-A582-C11860219512}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{664ECD06-26EB-4F8F-8D88-5444A5E766E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{664ECD06-26EB-4F8F-8D88-5444A5E766E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{664ECD06-26EB-4F8F-8D88-5444A5E766E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{664ECD06-26EB-4F8F-8D88-5444A5E766E0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{664ECD06-26EB-4F8F-8D88-5444A5E766E0}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{EAE5000B-9A97-4308-B791-0B71DE0A8219}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EAE5000B-9A97-4308-B791-0B71DE0A8219}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EAE5000B-9A97-4308-B791-0B71DE0A8219}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EAE5000B-9A97-4308-B791-0B71DE0A8219}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EAE5000B-9A97-4308-B791-0B71DE0A8219}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{E854F61B-548A-4100-A766-35B972B9EE11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E854F61B-548A-4100-A766-35B972B9EE11}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E854F61B-548A-4100-A766-35B972B9EE11}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E854F61B-548A-4100-A766-35B972B9EE11}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E854F61B-548A-4100-A766-35B972B9EE11}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{22C53CFB-B54A-438E-820F-42C94D557345}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{22C53CFB-B54A-438E-820F-42C94D557345}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{22C53CFB-B54A-438E-820F-42C94D557345}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{22C53CFB-B54A-438E-820F-42C94D557345}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{22C53CFB-B54A-438E-820F-42C94D557345}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{A4E85E94-383F-40EA-9478-0545070E52F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A4E85E94-383F-40EA-9478-0545070E52F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A4E85E94-383F-40EA-9478-0545070E52F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A4E85E94-383F-40EA-9478-0545070E52F5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A4E85E94-383F-40EA-9478-0545070E52F5}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{928090A9-AAC7-496C-A8E3-D242D2D8BC74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{928090A9-AAC7-496C-A8E3-D242D2D8BC74}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{928090A9-AAC7-496C-A8E3-D242D2D8BC74}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{928090A9-AAC7-496C-A8E3-D242D2D8BC74}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{928090A9-AAC7-496C-A8E3-D242D2D8BC74}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{D69B9924-5C2E-41BC-9354-A12DA7D03FDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D69B9924-5C2E-41BC-9354-A12DA7D03FDF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D69B9924-5C2E-41BC-9354-A12DA7D03FDF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D69B9924-5C2E-41BC-9354-A12DA7D03FDF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D69B9924-5C2E-41BC-9354-A12DA7D03FDF}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{ED307D87-E1BF-49B6-9591-5250D431C758}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{ED307D87-E1BF-49B6-9591-5250D431C758}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{ED307D87-E1BF-49B6-9591-5250D431C758}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{ED307D87-E1BF-49B6-9591-5250D431C758}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{ED307D87-E1BF-49B6-9591-5250D431C758}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{0E4B622A-063B-4A39-87CF-F18AEACBDDC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0E4B622A-063B-4A39-87CF-F18AEACBDDC5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0E4B622A-063B-4A39-87CF-F18AEACBDDC5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0E4B622A-063B-4A39-87CF-F18AEACBDDC5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0E4B622A-063B-4A39-87CF-F18AEACBDDC5}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{E2BEAAAE-497B-49F4-AD27-03BE20924311}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E2BEAAAE-497B-49F4-AD27-03BE20924311}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E2BEAAAE-497B-49F4-AD27-03BE20924311}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E2BEAAAE-497B-49F4-AD27-03BE20924311}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E2BEAAAE-497B-49F4-AD27-03BE20924311}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{F2490822-51F7-4B65-8B21-EE0082B76745}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F2490822-51F7-4B65-8B21-EE0082B76745}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F2490822-51F7-4B65-8B21-EE0082B76745}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F2490822-51F7-4B65-8B21-EE0082B76745}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F2490822-51F7-4B65-8B21-EE0082B76745}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{07C97A77-61B6-4BB5-9436-3A7FC379B75E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{07C97A77-61B6-4BB5-9436-3A7FC379B75E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{07C97A77-61B6-4BB5-9436-3A7FC379B75E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{07C97A77-61B6-4BB5-9436-3A7FC379B75E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{07C97A77-61B6-4BB5-9436-3A7FC379B75E}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{7155D1E6-00CE-4081-B922-E6C5524EE600}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7155D1E6-00CE-4081-B922-E6C5524EE600}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7155D1E6-00CE-4081-B922-E6C5524EE600}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7155D1E6-00CE-4081-B922-E6C5524EE600}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7155D1E6-00CE-4081-B922-E6C5524EE600}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{9FE6A783-C20D-4097-9988-4178E2C4CE75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9FE6A783-C20D-4097-9988-4178E2C4CE75}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9FE6A783-C20D-4097-9988-4178E2C4CE75}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9FE6A783-C20D-4097-9988-4178E2C4CE75}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9FE6A783-C20D-4097-9988-4178E2C4CE75}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{9FE6A783-C20D-4097-9988-4178E2C4CE75}.Package|Any CPU.Build.0 = Package|Any CPU
|
||||
{1012C962-7F6D-4EC5-A0EC-0741A95BAD6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1012C962-7F6D-4EC5-A0EC-0741A95BAD6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1012C962-7F6D-4EC5-A0EC-0741A95BAD6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1012C962-7F6D-4EC5-A0EC-0741A95BAD6B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1012C962-7F6D-4EC5-A0EC-0741A95BAD6B}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{A7CACAE7-66E7-43DA-948B-28EB0DDDB582}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A7CACAE7-66E7-43DA-948B-28EB0DDDB582}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A7CACAE7-66E7-43DA-948B-28EB0DDDB582}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A7CACAE7-66E7-43DA-948B-28EB0DDDB582}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A7CACAE7-66E7-43DA-948B-28EB0DDDB582}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{5F68A5B1-7907-4B16-8AFE-326E9DD7D65B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5F68A5B1-7907-4B16-8AFE-326E9DD7D65B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5F68A5B1-7907-4B16-8AFE-326E9DD7D65B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5F68A5B1-7907-4B16-8AFE-326E9DD7D65B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5F68A5B1-7907-4B16-8AFE-326E9DD7D65B}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{5F68A5B1-7907-4B16-8AFE-326E9DD7D65B}.Package|Any CPU.Build.0 = Package|Any CPU
|
||||
{16C89E7C-1575-4685-8DFA-8E7E2C6101BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{16C89E7C-1575-4685-8DFA-8E7E2C6101BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{16C89E7C-1575-4685-8DFA-8E7E2C6101BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{16C89E7C-1575-4685-8DFA-8E7E2C6101BF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{16C89E7C-1575-4685-8DFA-8E7E2C6101BF}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{EA387B4B-DAD0-4E34-B8A3-79EA4616726A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EA387B4B-DAD0-4E34-B8A3-79EA4616726A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EA387B4B-DAD0-4E34-B8A3-79EA4616726A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EA387B4B-DAD0-4E34-B8A3-79EA4616726A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EA387B4B-DAD0-4E34-B8A3-79EA4616726A}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
{3326DB6E-023E-483F-9A1C-5905D3091B57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3326DB6E-023E-483F-9A1C-5905D3091B57}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3326DB6E-023E-483F-9A1C-5905D3091B57}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3326DB6E-023E-483F-9A1C-5905D3091B57}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3326DB6E-023E-483F-9A1C-5905D3091B57}.Package|Any CPU.ActiveCfg = Package|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
#### 0.7.3 July 28, 2022
|
||||
- target net5 and net6
|
||||
- Adopted TlsHandler for the case when Handshake completion callback is dispatched asynchronously to thread pool
|
||||
- Introduced SingleThreadedEmbededChannel for TlsHandler and SniHandler tests
|
||||
|
||||
#### 0.7.2 February 14, 2022
|
||||
- Start threads as background in HashedWheelTimer, LoopExecutor, ThreadDeathWatcher
|
||||
- Google.Protobuf 3.19.4 (latest)
|
||||
|
|
|
@ -33,7 +33,7 @@ Param(
|
|||
|
||||
$CakeVersion = "0.27.1"
|
||||
$DotNetChannel = "Current";
|
||||
$DotNetVersion = "3.1.411";
|
||||
$DotNetVersion = "6.0.302";
|
||||
$DotNetInstallerUri = "https://dot.net/v1/dotnet-install.ps1";
|
||||
$NugetUrl = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
|
||||
# Temporarily skip verification of addins.
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">2.0.3</NetStandardImplicitPackageVersion>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">2.0.3</NetStandardImplicitPackageVersion>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">2.0.3</NetStandardImplicitPackageVersion>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">2.0.3</NetStandardImplicitPackageVersion>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace Examples.Common
|
|||
{
|
||||
get
|
||||
{
|
||||
#if NETSTANDARD2_0
|
||||
#if NETSTANDARD2_0 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER
|
||||
return AppContext.BaseDirectory;
|
||||
#else
|
||||
return AppDomain.CurrentDomain.BaseDirectory;
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netstandard2.0;net472;net5;net6</TargetFrameworks>
|
||||
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard2.0' ">2.0.3</NetStandardImplicitPackageVersion>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">2.0.3</NetStandardImplicitPackageVersion>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">2.0.3</NetStandardImplicitPackageVersion>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netstandard2.0;net472;net5;net6</TargetFrameworks>
|
||||
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard2.0' ">2.0.3</NetStandardImplicitPackageVersion>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\DotNetty.Common\DotNetty.Common.csproj" />
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">2.0.3</NetStandardImplicitPackageVersion>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<ServerGarbageCollection>true</ServerGarbageCollection>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">2.0.3</NetStandardImplicitPackageVersion>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">2.0.3</NetStandardImplicitPackageVersion>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">2.0.3</NetStandardImplicitPackageVersion>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">2.0.3</NetStandardImplicitPackageVersion>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">2.0.3</NetStandardImplicitPackageVersion>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">2.0.3</NetStandardImplicitPackageVersion>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
|
|
|
@ -11,6 +11,7 @@ namespace WebSockets.Client
|
|||
using DotNetty.Common.Concurrency;
|
||||
using DotNetty.Common.Utilities;
|
||||
using DotNetty.Transport.Channels;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
public class WebSocketClientHandler : SimpleChannelInboundHandler<object>
|
||||
{
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">2.0.3</NetStandardImplicitPackageVersion>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
|
|
|
@ -2,10 +2,12 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">2.0.3</NetStandardImplicitPackageVersion>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<ServerGarbageCollection>true</ServerGarbageCollection>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<!-- Build Settings -->
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<DebugType Condition="'$(Configuration)'=='Release'">pdbonly</DebugType>
|
||||
<DebugSymbols>True</DebugSymbols>
|
||||
<Deterministic>true</Deterministic>
|
||||
|
||||
<!-- Package Settings -->
|
||||
<DebugType Condition="'$(Configuration)'=='Package'">pdbonly</DebugType>
|
||||
<Optimize Condition="'$(Configuration)'=='Package'">true</Optimize>
|
||||
<PackageOutputPath>$(SolutionDir)build_output\packages</PackageOutputPath>
|
||||
<GeneratePackageOnBuild Condition="'$(Configuration)'=='Package'">True</GeneratePackageOnBuild>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
|
||||
<PackageVersion>0.7.3</PackageVersion>
|
||||
<Version>$(PackageVersion)</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
|
@ -1,12 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup Label="NuGet">
|
||||
<TargetFrameworks>netstandard2.0;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netstandard2.0;net472;net5;net6</TargetFrameworks>
|
||||
<IsPackable>true</IsPackable>
|
||||
<Description>Buffer management in DotNetty</Description>
|
||||
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
|
||||
<AssemblyTitle>DotNetty: buffer management</AssemblyTitle>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<VersionPrefix>0.7.2</VersionPrefix>
|
||||
<VersionPrefix>0.7.3</VersionPrefix>
|
||||
<Authors>Microsoft</Authors>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||
|
|
|
@ -386,7 +386,7 @@ namespace DotNetty.Buffers
|
|||
|
||||
internal static string GetString(byte* src, int length, Encoding encoding)
|
||||
{
|
||||
#if NETSTANDARD2_0
|
||||
#if NETSTANDARD2_0 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER
|
||||
return encoding.GetString(src, length);
|
||||
#else
|
||||
int charCount = encoding.GetCharCount(src, length);
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup Label="NuGet">
|
||||
<TargetFrameworks>netstandard2.0;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netstandard2.0;net472;net5;net6</TargetFrameworks>
|
||||
<IsPackable>true</IsPackable>
|
||||
<PackageId>DotNetty.Codecs.Http</PackageId>
|
||||
<Description>Http codec for DotNetty</Description>
|
||||
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
|
||||
<AssemblyTitle>DotNetty: Http codec</AssemblyTitle>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<VersionPrefix>0.7.2</VersionPrefix>
|
||||
<VersionPrefix>0.7.3</VersionPrefix>
|
||||
<Authors>Microsoft</Authors>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
|
|
|
@ -11,6 +11,7 @@ namespace DotNetty.Codecs.Http.WebSockets
|
|||
using DotNetty.Common.Concurrency;
|
||||
using DotNetty.Common.Utilities;
|
||||
using DotNetty.Transport.Channels;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
public abstract class WebSocketClientHandshaker
|
||||
{
|
||||
|
|
|
@ -15,6 +15,7 @@ namespace DotNetty.Codecs.Http.WebSockets
|
|||
using DotNetty.Common.Internal.Logging;
|
||||
using DotNetty.Common.Utilities;
|
||||
using DotNetty.Transport.Channels;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
public abstract class WebSocketServerHandshaker
|
||||
{
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup Label="NuGet">
|
||||
<TargetFrameworks>netstandard2.0;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netstandard2.0;net472;net5;net6</TargetFrameworks>
|
||||
<IsPackable>true</IsPackable>
|
||||
<PackageId>DotNetty.Codecs.Mqtt</PackageId>
|
||||
<Description>MQTT codec for DotNetty</Description>
|
||||
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
|
||||
<AssemblyTitle>DotNetty: MQTT codec</AssemblyTitle>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<VersionPrefix>0.7.2</VersionPrefix>
|
||||
<VersionPrefix>0.7.3</VersionPrefix>
|
||||
<Authors>Microsoft</Authors>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup Label="NuGet">
|
||||
<TargetFrameworks>netstandard2.0;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netstandard2.0;net472;net5;net6</TargetFrameworks>
|
||||
<IsPackable>true</IsPackable>
|
||||
<PackageId>DotNetty.Codecs.Protobuf</PackageId>
|
||||
<Description>Protobuf Proto3 codec for DotNetty</Description>
|
||||
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
|
||||
<AssemblyTitle>DotNetty: Protobuf Proto3 codec</AssemblyTitle>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<VersionPrefix>0.7.2</VersionPrefix>
|
||||
<VersionPrefix>0.7.3</VersionPrefix>
|
||||
<Authors>Microsoft</Authors>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup Label="NuGet">
|
||||
<TargetFrameworks>netstandard2.0;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netstandard2.0;net472;net5;net6</TargetFrameworks>
|
||||
<IsPackable>true</IsPackable>
|
||||
<PackageId>DotNetty.Codecs.ProtocolBuffers</PackageId>
|
||||
<Description>ProtocolBuffers Proto2 codec for DotNetty</Description>
|
||||
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
|
||||
<AssemblyTitle>DotNetty: ProtocolBuffers Proto2 codec</AssemblyTitle>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<VersionPrefix>0.7.2</VersionPrefix>
|
||||
<VersionPrefix>0.7.3</VersionPrefix>
|
||||
<Authors>Microsoft</Authors>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup Label="NuGet">
|
||||
<TargetFrameworks>netstandard2.0;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netstandard2.0;net472;net5;net6</TargetFrameworks>
|
||||
<IsPackable>true</IsPackable>
|
||||
<PackageId>DotNetty.Codecs.Redis</PackageId>
|
||||
<Description>Redis codec for DotNetty</Description>
|
||||
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
|
||||
<AssemblyTitle>DotNetty: Redis codec</AssemblyTitle>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<VersionPrefix>0.7.2</VersionPrefix>
|
||||
<VersionPrefix>0.7.3</VersionPrefix>
|
||||
<Authors>Microsoft</Authors>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netstandard2.0;net472;net5;net6</TargetFrameworks>
|
||||
<IsPackable>true</IsPackable>
|
||||
<PackageId>DotNetty.Codecs</PackageId>
|
||||
<Description>General purpose codecs for DotNetty</Description>
|
||||
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
|
||||
<AssemblyTitle>DotNetty: codecs</AssemblyTitle>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<VersionPrefix>0.7.2</VersionPrefix>
|
||||
<VersionPrefix>0.7.3</VersionPrefix>
|
||||
<Authors>Microsoft</Authors>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup Label="NuGet">
|
||||
<TargetFrameworks>netstandard2.0;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netstandard2.0;net472;net5;net6</TargetFrameworks>
|
||||
<IsPackable>true</IsPackable>
|
||||
<PackageId>DotNetty.Common</PackageId>
|
||||
<Description>DotNetty common routines</Description>
|
||||
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
|
||||
<AssemblyTitle>DotNetty: common routines</AssemblyTitle>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<VersionPrefix>0.7.2</VersionPrefix>
|
||||
<VersionPrefix>0.7.3</VersionPrefix>
|
||||
<Authors>Microsoft</Authors>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||
|
|
|
@ -15,6 +15,7 @@ namespace DotNetty.Common.Utilities
|
|||
using DotNetty.Common.Concurrency;
|
||||
using DotNetty.Common.Internal;
|
||||
using DotNetty.Common.Internal.Logging;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
public sealed class HashedWheelTimer : ITimer
|
||||
{
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace DotNetty.Common.Utilities
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using DotNetty.Common.Concurrency;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
public static class TaskEx
|
||||
{
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup Label="NuGet">
|
||||
<TargetFrameworks>netstandard2.0;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netstandard2.0;net472;net5;net6</TargetFrameworks>
|
||||
<IsPackable>true</IsPackable>
|
||||
<PackageId>DotNetty.Handlers</PackageId>
|
||||
<Description>Application handlers for DotNetty</Description>
|
||||
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
|
||||
<AssemblyTitle>DotNetty: handlers</AssemblyTitle>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<VersionPrefix>0.7.2</VersionPrefix>
|
||||
<VersionPrefix>0.7.3</VersionPrefix>
|
||||
<Authors>Microsoft</Authors>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
|
|
|
@ -11,6 +11,7 @@ namespace DotNetty.Handlers.Streams
|
|||
using DotNetty.Common.Internal.Logging;
|
||||
using DotNetty.Common.Utilities;
|
||||
using DotNetty.Transport.Channels;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
public class ChunkedWriteHandler<T> : ChannelDuplexHandler
|
||||
{
|
||||
|
|
|
@ -214,7 +214,7 @@ namespace DotNetty.Handlers.Tls
|
|||
};
|
||||
|
||||
hostname = idn.GetAscii(hostname);
|
||||
#if NETSTANDARD2_0
|
||||
#if NETSTANDARD2_0 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER
|
||||
// TODO: netcore does not have culture sensitive tolower()
|
||||
hostname = hostname.ToLowerInvariant();
|
||||
#else
|
||||
|
|
|
@ -0,0 +1,302 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
#if NET5_0_OR_GREATER
|
||||
namespace DotNetty.Handlers.Tls
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
partial class TlsHandler
|
||||
{
|
||||
sealed class MediationStreamNet : MediationStreamBase
|
||||
{
|
||||
readonly CompositeSource source = new();
|
||||
TaskCompletionSource<int> readCompletionSource;
|
||||
Memory<byte> sslOwnedMemory;
|
||||
int readByteCount;
|
||||
|
||||
public MediationStreamNet(TlsHandler owner)
|
||||
: base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool SourceIsReadable => this.source.IsReadable;
|
||||
public override int SourceReadableBytes => this.source.GetTotalReadableBytes();
|
||||
|
||||
public override void SetSource(byte[] source, int offset) => this.source.AddSource(source, offset);
|
||||
public override void ResetSource() => this.source.ResetSources();
|
||||
|
||||
public override void ExpandSource(int count)
|
||||
{
|
||||
this.source.Expand(count);
|
||||
|
||||
Memory<byte> sslMemory = this.sslOwnedMemory;
|
||||
if (sslMemory.IsEmpty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.sslOwnedMemory = default;
|
||||
|
||||
this.readByteCount = this.ReadFromInput(sslMemory);
|
||||
// hack: this tricks SslStream's continuation to run synchronously instead of dispatching to TP. Remove once Begin/EndRead are available.
|
||||
new Task(
|
||||
ms =>
|
||||
{
|
||||
var self = (MediationStreamNet)ms;
|
||||
TaskCompletionSource<int> p = self.readCompletionSource;
|
||||
self.readCompletionSource = null;
|
||||
p.TrySetResult(self.readByteCount);
|
||||
},
|
||||
this)
|
||||
.RunSynchronously(TaskScheduler.Default);
|
||||
}
|
||||
|
||||
public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
|
||||
=> this.owner.capturedContext.Executor.InEventLoop
|
||||
? this.InLoopReadAsync(buffer, cancellationToken)
|
||||
: new ValueTask<int>(this.OutOfLoopReadAsync(buffer, cancellationToken));
|
||||
|
||||
ValueTask<int> InLoopReadAsync(Memory<byte> buffer, CancellationToken cancellationToken)
|
||||
{
|
||||
if (this.SourceIsReadable)
|
||||
{
|
||||
// we have the bytes available upfront - write out synchronously
|
||||
int read = this.ReadFromInput(buffer);
|
||||
return new ValueTask<int>(read);
|
||||
}
|
||||
|
||||
Contract.Assert(this.sslOwnedMemory.IsEmpty);
|
||||
// take note of buffer - we will pass bytes there once available
|
||||
this.sslOwnedMemory = buffer;
|
||||
this.readCompletionSource = new TaskCompletionSource<int>();
|
||||
return new ValueTask<int>(this.readCompletionSource.Task);
|
||||
}
|
||||
|
||||
Task<int> OutOfLoopReadAsync(Memory<byte> buffer, CancellationToken cancellationToken)
|
||||
{
|
||||
return this.owner.capturedContext.Executor.SubmitAsync(
|
||||
() =>
|
||||
{
|
||||
if (this.SourceIsReadable)
|
||||
{
|
||||
// we have the bytes available upfront - write out synchronously
|
||||
int read = this.ReadFromInput(buffer);
|
||||
return Task.FromResult(read);
|
||||
}
|
||||
|
||||
Contract.Assert(this.sslOwnedMemory.IsEmpty);
|
||||
// take note of buffer - we will pass bytes there once available
|
||||
this.sslOwnedMemory = buffer;
|
||||
this.readCompletionSource = new TaskCompletionSource<int>();
|
||||
return this.readCompletionSource.Task;
|
||||
},
|
||||
cancellationToken).Unwrap();
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (this.owner.capturedContext.Executor.InEventLoop)
|
||||
{
|
||||
this.owner.FinishWrap(buffer, offset, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.owner.capturedContext.Executor.Execute(() => this.owner.FinishWrap(buffer, offset, count));
|
||||
}
|
||||
}
|
||||
|
||||
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||
{
|
||||
if (this.owner.capturedContext.Executor.InEventLoop)
|
||||
{
|
||||
return this.owner.FinishWrapNonAppDataAsync(buffer, offset, count);
|
||||
}
|
||||
|
||||
return this.owner.capturedContext.Executor.SubmitAsync(
|
||||
() => this.owner.FinishWrapNonAppDataAsync(buffer, offset, count),
|
||||
cancellationToken
|
||||
).Unwrap();
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
// NOOP: called on SslStream.Close
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
if (disposing)
|
||||
{
|
||||
TaskCompletionSource<int> p = this.readCompletionSource;
|
||||
if (p != null)
|
||||
{
|
||||
this.readCompletionSource = null;
|
||||
p.TrySetResult(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ReadFromInput(Memory<byte> destination) => this.source.Read(destination);
|
||||
|
||||
#region Source
|
||||
|
||||
sealed class Source
|
||||
{
|
||||
byte[] input;
|
||||
int startOffset;
|
||||
int offset;
|
||||
int length;
|
||||
bool retained;
|
||||
|
||||
public Source(byte[] input, int offset)
|
||||
{
|
||||
this.input = input;
|
||||
this.startOffset = offset;
|
||||
this.offset = 0;
|
||||
this.length = 0;
|
||||
}
|
||||
|
||||
public int ReadableBytes => this.length - this.offset;
|
||||
|
||||
public bool IsReadable => this.ReadableBytes > 0;
|
||||
|
||||
public void Expand(int count)
|
||||
{
|
||||
Contract.Assert(!this.retained); // Retained source is not expected to be Expanded
|
||||
this.length += count;
|
||||
Contract.Assert(this.length <= this.input.Length);
|
||||
}
|
||||
|
||||
public int Read(Memory<byte> destination)
|
||||
{
|
||||
int len = Math.Min(this.ReadableBytes, destination.Length);
|
||||
new ReadOnlySpan<byte>(this.input, this.startOffset + this.offset, len).CopyTo(destination.Span);
|
||||
this.offset += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
// This is to avoid input bytes to be discarded by ref counting mechanism
|
||||
public void Retain()
|
||||
{
|
||||
int readableBytes = this.ReadableBytes;
|
||||
if (this.retained || readableBytes <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// todo: is there a way to not discard those bytes till they are read??? If not, then use context.Allocator???
|
||||
|
||||
// Copy only readable bytes to a new buffer
|
||||
byte[] copy = new byte[readableBytes];
|
||||
Buffer.BlockCopy(this.input, this.startOffset + this.offset, copy, 0, readableBytes);
|
||||
this.input = copy;
|
||||
|
||||
// Set both offsets to 0 and length to readableBytes (so that this.ReadableBytes stays the same)
|
||||
this.startOffset = 0;
|
||||
this.offset = 0;
|
||||
this.length = readableBytes;
|
||||
|
||||
this.retained = true;
|
||||
}
|
||||
}
|
||||
|
||||
sealed class CompositeSource
|
||||
{
|
||||
// Why not List?
|
||||
// 1. It's unlikely this list to grow more than 10 nodes. In fact in most cases it'll have one element only
|
||||
// 2. Cleanup removes from head, so it's cheaper compared to List which shifts elements in this case.
|
||||
readonly LinkedList<Source> sources = new LinkedList<Source>();
|
||||
|
||||
public bool IsReadable
|
||||
{
|
||||
get
|
||||
{
|
||||
// The composite source is readable if any readable sources, so
|
||||
// it's enough to check on last one as we always AddLast
|
||||
LinkedListNode<Source> last = this.sources.Last;
|
||||
return last != null && last.Value.IsReadable;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddSource(byte[] input, int offset)
|
||||
{
|
||||
// Always add to the tail
|
||||
this.sources.AddLast(new Source(input, offset));
|
||||
}
|
||||
|
||||
public void Expand(int count)
|
||||
{
|
||||
Contract.Assert(this.sources.Last != null); // AddSource is always called before
|
||||
|
||||
// Always expand the last added source
|
||||
this.sources.Last.Value.Expand(count);
|
||||
}
|
||||
|
||||
public int GetTotalReadableBytes()
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
LinkedListNode<Source> node = this.sources.First;
|
||||
while (node != null)
|
||||
{
|
||||
count += node.Value.ReadableBytes;
|
||||
node = node.Next;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// Read from all readable sources to the destination starting from head (oldest)
|
||||
public int Read(Memory<byte> destination)
|
||||
{
|
||||
int totalRead = 0;
|
||||
|
||||
LinkedListNode<Source> node = this.sources.First;
|
||||
while (node != null && totalRead < destination.Length)
|
||||
{
|
||||
Source source = node.Value;
|
||||
int read = source.Read(destination.Slice(totalRead, destination.Length - totalRead));
|
||||
totalRead += read;
|
||||
|
||||
if (!source.IsReadable)
|
||||
{
|
||||
node = node.Next;
|
||||
// Do not remove the node here as it can be expanded. Instead,
|
||||
// remove in the CleanUp method below
|
||||
}
|
||||
}
|
||||
|
||||
return totalRead;
|
||||
}
|
||||
|
||||
// Remove all not readable sources and retain readable. Start from first as it's the oldest
|
||||
public void ResetSources()
|
||||
{
|
||||
LinkedListNode<Source> node = this.sources.First;
|
||||
while (node != null)
|
||||
{
|
||||
if (!node.Value.IsReadable)
|
||||
{
|
||||
this.sources.RemoveFirst();
|
||||
node = this.sources.First;
|
||||
}
|
||||
else
|
||||
{
|
||||
node.Value.Retain();
|
||||
node = node.Next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,338 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace DotNetty.Handlers.Tls
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.IO;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
partial class TlsHandler
|
||||
{
|
||||
sealed class MediationStream : MediationStreamBase
|
||||
{
|
||||
byte[] input;
|
||||
int inputStartOffset;
|
||||
int inputOffset;
|
||||
int inputLength;
|
||||
TaskCompletionSource<int> readCompletionSource;
|
||||
ArraySegment<byte> sslOwnedBuffer;
|
||||
#if NETSTANDARD2_0 || NETCOREAPP3_1
|
||||
int readByteCount;
|
||||
#else
|
||||
SynchronousAsyncResult<int> syncReadResult;
|
||||
AsyncCallback readCallback;
|
||||
TaskCompletionSource writeCompletion;
|
||||
AsyncCallback writeCallback;
|
||||
#endif
|
||||
|
||||
public MediationStream(TlsHandler owner)
|
||||
: base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
public override int SourceReadableBytes => this.inputLength - this.inputOffset;
|
||||
|
||||
public override bool SourceIsReadable => this.SourceReadableBytes > 0;
|
||||
|
||||
public override void SetSource(byte[] source, int offset)
|
||||
{
|
||||
this.input = source;
|
||||
this.inputStartOffset = offset;
|
||||
this.inputOffset = 0;
|
||||
this.inputLength = 0;
|
||||
}
|
||||
|
||||
public override void ResetSource()
|
||||
{
|
||||
this.input = null;
|
||||
this.inputLength = 0;
|
||||
this.inputOffset = 0;
|
||||
}
|
||||
|
||||
public override void ExpandSource(int count)
|
||||
{
|
||||
Contract.Assert(this.input != null);
|
||||
|
||||
this.inputLength += count;
|
||||
|
||||
ArraySegment<byte> sslBuffer = this.sslOwnedBuffer;
|
||||
if (sslBuffer.Array == null)
|
||||
{
|
||||
// there is no pending read operation - keep for future
|
||||
return;
|
||||
}
|
||||
|
||||
this.sslOwnedBuffer = default(ArraySegment<byte>);
|
||||
|
||||
#if NETSTANDARD2_0 || NETCOREAPP3_1
|
||||
this.readByteCount = this.ReadFromInput(sslBuffer.Array, sslBuffer.Offset, sslBuffer.Count);
|
||||
// hack: this tricks SslStream's continuation to run synchronously instead of dispatching to TP. Remove once Begin/EndRead are available.
|
||||
new Task(
|
||||
ms =>
|
||||
{
|
||||
var self = (MediationStream)ms;
|
||||
TaskCompletionSource<int> p = self.readCompletionSource;
|
||||
self.readCompletionSource = null;
|
||||
p.TrySetResult(self.readByteCount);
|
||||
},
|
||||
this)
|
||||
.RunSynchronously(TaskScheduler.Default);
|
||||
#else
|
||||
int read = this.ReadFromInput(sslBuffer.Array, sslBuffer.Offset, sslBuffer.Count);
|
||||
|
||||
TaskCompletionSource<int> promise = this.readCompletionSource;
|
||||
this.readCompletionSource = null;
|
||||
promise.TrySetResult(read);
|
||||
|
||||
AsyncCallback callback = this.readCallback;
|
||||
this.readCallback = null;
|
||||
callback?.Invoke(promise.Task);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NETSTANDARD2_0 || NETCOREAPP3_1
|
||||
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||
{
|
||||
if (this.SourceReadableBytes > 0)
|
||||
{
|
||||
// we have the bytes available upfront - write out synchronously
|
||||
int read = this.ReadFromInput(buffer, offset, count);
|
||||
return Task.FromResult(read);
|
||||
}
|
||||
|
||||
Contract.Assert(this.sslOwnedBuffer.Array == null);
|
||||
// take note of buffer - we will pass bytes there once available
|
||||
this.sslOwnedBuffer = new ArraySegment<byte>(buffer, offset, count);
|
||||
this.readCompletionSource = new TaskCompletionSource<int>();
|
||||
return this.readCompletionSource.Task;
|
||||
}
|
||||
#else
|
||||
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
|
||||
{
|
||||
if (this.SourceReadableBytes > 0)
|
||||
{
|
||||
// we have the bytes available upfront - write out synchronously
|
||||
int read = this.ReadFromInput(buffer, offset, count);
|
||||
var res = this.PrepareSyncReadResult(read, state);
|
||||
callback?.Invoke(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
Contract.Assert(this.sslOwnedBuffer.Array == null);
|
||||
// take note of buffer - we will pass bytes there once available
|
||||
this.sslOwnedBuffer = new ArraySegment<byte>(buffer, offset, count);
|
||||
this.readCompletionSource = new TaskCompletionSource<int>(state);
|
||||
this.readCallback = callback;
|
||||
return this.readCompletionSource.Task;
|
||||
}
|
||||
|
||||
public override int EndRead(IAsyncResult asyncResult)
|
||||
{
|
||||
SynchronousAsyncResult<int> syncResult = this.syncReadResult;
|
||||
if (ReferenceEquals(asyncResult, syncResult))
|
||||
{
|
||||
return syncResult.Result;
|
||||
}
|
||||
|
||||
Debug.Assert(this.readCompletionSource == null || this.readCompletionSource.Task == asyncResult);
|
||||
Contract.Assert(!((Task<int>)asyncResult).IsCanceled);
|
||||
|
||||
try
|
||||
{
|
||||
return ((Task<int>)asyncResult).Result;
|
||||
}
|
||||
catch (AggregateException ex)
|
||||
{
|
||||
ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
|
||||
throw; // unreachable
|
||||
}
|
||||
}
|
||||
|
||||
IAsyncResult PrepareSyncReadResult(int readBytes, object state)
|
||||
{
|
||||
// it is safe to reuse sync result object as it can't lead to leak (no way to attach to it via handle)
|
||||
SynchronousAsyncResult<int> result = this.syncReadResult ?? (this.syncReadResult = new SynchronousAsyncResult<int>());
|
||||
result.Result = readBytes;
|
||||
result.AsyncState = state;
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count) => this.owner.FinishWrap(buffer, offset, count);
|
||||
|
||||
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||
=> this.owner.FinishWrapNonAppDataAsync(buffer, offset, count);
|
||||
|
||||
#if !(NETSTANDARD2_0 || NETCOREAPP3_1)
|
||||
static readonly Action<Task, object> WriteCompleteCallback = HandleChannelWriteComplete;
|
||||
|
||||
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
|
||||
{
|
||||
Task task = this.WriteAsync(buffer, offset, count);
|
||||
switch (task.Status)
|
||||
{
|
||||
case TaskStatus.RanToCompletion:
|
||||
// write+flush completed synchronously (and successfully)
|
||||
var result = new SynchronousAsyncResult<int>();
|
||||
result.AsyncState = state;
|
||||
callback?.Invoke(result);
|
||||
return result;
|
||||
default:
|
||||
if (callback != null || state != task.AsyncState)
|
||||
{
|
||||
Contract.Assert(this.writeCompletion == null);
|
||||
this.writeCallback = callback;
|
||||
var tcs = new TaskCompletionSource(state);
|
||||
this.writeCompletion = tcs;
|
||||
task.ContinueWith(WriteCompleteCallback, this, TaskContinuationOptions.ExecuteSynchronously);
|
||||
return tcs.Task;
|
||||
}
|
||||
else
|
||||
{
|
||||
return task;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void HandleChannelWriteComplete(Task writeTask, object state)
|
||||
{
|
||||
var self = (MediationStream)state;
|
||||
|
||||
AsyncCallback callback = self.writeCallback;
|
||||
self.writeCallback = null;
|
||||
|
||||
var promise = self.writeCompletion;
|
||||
self.writeCompletion = null;
|
||||
|
||||
switch (writeTask.Status)
|
||||
{
|
||||
case TaskStatus.RanToCompletion:
|
||||
promise.TryComplete();
|
||||
break;
|
||||
case TaskStatus.Canceled:
|
||||
promise.TrySetCanceled();
|
||||
break;
|
||||
case TaskStatus.Faulted:
|
||||
promise.TrySetException(writeTask.Exception);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("Unexpected task status: " + writeTask.Status);
|
||||
}
|
||||
|
||||
callback?.Invoke(promise.Task);
|
||||
}
|
||||
|
||||
public override void EndWrite(IAsyncResult asyncResult)
|
||||
{
|
||||
if (asyncResult is SynchronousAsyncResult<int>)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
((Task)asyncResult).Wait();
|
||||
}
|
||||
catch (AggregateException ex)
|
||||
{
|
||||
ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int ReadFromInput(byte[] destination, int destinationOffset, int destinationCapacity)
|
||||
{
|
||||
Contract.Assert(destination != null);
|
||||
|
||||
byte[] source = this.input;
|
||||
int readableBytes = this.SourceReadableBytes;
|
||||
int length = Math.Min(readableBytes, destinationCapacity);
|
||||
Buffer.BlockCopy(source, this.inputStartOffset + this.inputOffset, destination, destinationOffset, length);
|
||||
this.inputOffset += length;
|
||||
return length;
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
// NOOP: called on SslStream.Close
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
if (disposing)
|
||||
{
|
||||
TaskCompletionSource<int> p = this.readCompletionSource;
|
||||
if (p != null)
|
||||
{
|
||||
this.readCompletionSource = null;
|
||||
p.TrySetResult(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region plumbing
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override bool CanRead => true;
|
||||
|
||||
public override bool CanSeek => false;
|
||||
|
||||
public override bool CanWrite => true;
|
||||
|
||||
public override long Length
|
||||
{
|
||||
get { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get { throw new NotSupportedException(); }
|
||||
set { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region sync result
|
||||
|
||||
sealed class SynchronousAsyncResult<T> : IAsyncResult
|
||||
{
|
||||
public T Result { get; set; }
|
||||
|
||||
public bool IsCompleted => true;
|
||||
|
||||
public WaitHandle AsyncWaitHandle
|
||||
{
|
||||
get { throw new InvalidOperationException("Cannot wait on a synchronous result."); }
|
||||
}
|
||||
|
||||
public object AsyncState { get; set; }
|
||||
|
||||
public bool CompletedSynchronously => true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace DotNetty.Handlers.Tls
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
partial class TlsHandler
|
||||
{
|
||||
abstract class MediationStreamBase : Stream
|
||||
{
|
||||
protected readonly TlsHandler owner;
|
||||
|
||||
public MediationStreamBase(TlsHandler owner)
|
||||
{
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public static MediationStreamBase Create(TlsHandler owner)
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
return new TlsHandler.MediationStreamNet(owner);
|
||||
#else
|
||||
return new MediationStream(owner);
|
||||
#endif
|
||||
}
|
||||
|
||||
public abstract bool SourceIsReadable { get; }
|
||||
public abstract int SourceReadableBytes { get; }
|
||||
|
||||
public abstract void SetSource(byte[] source, int offset);
|
||||
public abstract void ExpandSource(int count);
|
||||
public abstract void ResetSource();
|
||||
|
||||
#region plumbing
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override bool CanRead => true;
|
||||
public override bool CanSeek => false;
|
||||
public override bool CanWrite => true;
|
||||
public override long Length
|
||||
{
|
||||
get { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get { throw new NotSupportedException(); }
|
||||
set { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,21 +5,19 @@ namespace DotNetty.Handlers.Tls
|
|||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.IO;
|
||||
using System.Net.Security;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using DotNetty.Buffers;
|
||||
using DotNetty.Codecs;
|
||||
using DotNetty.Common.Concurrency;
|
||||
using DotNetty.Common;
|
||||
using DotNetty.Common.Utilities;
|
||||
using DotNetty.Transport.Channels;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
public sealed class TlsHandler : ByteToMessageDecoder
|
||||
public sealed partial class TlsHandler : ByteToMessageDecoder
|
||||
{
|
||||
readonly TlsSettings settings;
|
||||
const int FallbackReadBufferSize = 256;
|
||||
|
@ -29,11 +27,12 @@ namespace DotNetty.Handlers.Tls
|
|||
static readonly Action<Task, object> HandshakeCompletionCallback = new Action<Task, object>(HandleHandshakeCompleted);
|
||||
|
||||
readonly SslStream sslStream;
|
||||
readonly MediationStream mediationStream;
|
||||
readonly MediationStreamBase mediationStream;
|
||||
readonly TaskCompletionSource closeFuture;
|
||||
|
||||
TlsHandlerState state;
|
||||
int packetLength;
|
||||
(int packetLength, byte packetContentType) packetInfo;
|
||||
List<(int packetLength, byte packetContentType)> pendingDataPackets;
|
||||
volatile IChannelHandlerContext capturedContext;
|
||||
BatchingPendingWriteQueue pendingUnencryptedWrites;
|
||||
Task lastContextWriteTask;
|
||||
|
@ -53,7 +52,7 @@ namespace DotNetty.Handlers.Tls
|
|||
|
||||
this.settings = settings;
|
||||
this.closeFuture = new TaskCompletionSource();
|
||||
this.mediationStream = new MediationStream(this);
|
||||
this.mediationStream = MediationStreamBase.Create(this);
|
||||
this.sslStream = sslStreamFactory(this.mediationStream);
|
||||
}
|
||||
|
||||
|
@ -118,38 +117,74 @@ namespace DotNetty.Handlers.Tls
|
|||
static void HandleHandshakeCompleted(Task task, object state)
|
||||
{
|
||||
var self = (TlsHandler)state;
|
||||
if (self.capturedContext.Executor.InEventLoop)
|
||||
{
|
||||
HandleHandshakeCompletedInternal(task, self);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.capturedContext.Executor.Execute(() => HandleHandshakeCompletedInternal(task, self));
|
||||
}
|
||||
}
|
||||
|
||||
static void HandleHandshakeCompletedInternal(Task task, TlsHandler self)
|
||||
{
|
||||
switch (task.Status)
|
||||
{
|
||||
case TaskStatus.RanToCompletion:
|
||||
{
|
||||
TlsHandlerState oldState = self.state;
|
||||
|
||||
Contract.Assert(!oldState.HasAny(TlsHandlerState.AuthenticationCompleted));
|
||||
self.state = (oldState | TlsHandlerState.Authenticated) & ~(TlsHandlerState.Authenticating | TlsHandlerState.FlushedBeforeHandshake);
|
||||
|
||||
self.capturedContext.FireUserEventTriggered(TlsHandshakeCompletionEvent.Success);
|
||||
|
||||
// Due to possible async execution of HandleHandshakeCompleted continuation, we need to
|
||||
// Unwrap any pending app data packets in case, when read completed and no more messages in the channel.
|
||||
if (self.pendingDataPackets != null && self.pendingDataPackets.Count > 0)
|
||||
{
|
||||
TlsHandlerState oldState = self.state;
|
||||
|
||||
Contract.Assert(!oldState.HasAny(TlsHandlerState.AuthenticationCompleted));
|
||||
self.state = (oldState | TlsHandlerState.Authenticated) & ~(TlsHandlerState.Authenticating | TlsHandlerState.FlushedBeforeHandshake);
|
||||
|
||||
self.capturedContext.FireUserEventTriggered(TlsHandshakeCompletionEvent.Success);
|
||||
|
||||
if (oldState.Has(TlsHandlerState.ReadRequestedBeforeAuthenticated) && !self.capturedContext.Channel.Configuration.AutoRead)
|
||||
ThreadLocalObjectList output = ThreadLocalObjectList.NewInstance();
|
||||
try
|
||||
{
|
||||
self.capturedContext.Read();
|
||||
self.Unwrap(self.capturedContext, Unpooled.Empty, 0, 0, new List<(int packetLength, byte packetContentType)>(0), output);
|
||||
for (int i = 0; i < output.Count; i++)
|
||||
{
|
||||
self.capturedContext.FireChannelRead(output[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (oldState.Has(TlsHandlerState.FlushedBeforeHandshake))
|
||||
catch (Exception ex)
|
||||
{
|
||||
self.Wrap(self.capturedContext);
|
||||
self.capturedContext.Flush();
|
||||
throw new DecoderException(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
output.Return();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (oldState.Has(TlsHandlerState.ReadRequestedBeforeAuthenticated) && !self.capturedContext.Channel.Configuration.AutoRead)
|
||||
{
|
||||
self.capturedContext.Read();
|
||||
}
|
||||
|
||||
if (oldState.Has(TlsHandlerState.FlushedBeforeHandshake))
|
||||
{
|
||||
self.Wrap(self.capturedContext);
|
||||
self.capturedContext.Flush();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case TaskStatus.Canceled:
|
||||
case TaskStatus.Faulted:
|
||||
{
|
||||
// ReSharper disable once AssignNullToNotNullAttribute -- task.Exception will be present as task is faulted
|
||||
TlsHandlerState oldState = self.state;
|
||||
Contract.Assert(!oldState.HasAny(TlsHandlerState.Authenticated));
|
||||
self.HandleFailure(task.Exception);
|
||||
break;
|
||||
}
|
||||
{
|
||||
// ReSharper disable once AssignNullToNotNullAttribute -- task.Exception will be present as task is faulted
|
||||
TlsHandlerState oldState = self.state;
|
||||
Contract.Assert(!oldState.HasAny(TlsHandlerState.Authenticated));
|
||||
self.HandleFailure(task.Exception);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(task), "Unexpected task status: " + task.Status);
|
||||
}
|
||||
|
@ -183,27 +218,27 @@ namespace DotNetty.Handlers.Tls
|
|||
int offset = startOffset;
|
||||
int totalLength = 0;
|
||||
|
||||
List<int> packetLengths;
|
||||
List<(int, byte)> packetInfos;
|
||||
// if we calculated the length of the current SSL record before, use that information.
|
||||
if (this.packetLength > 0)
|
||||
if (this.packetInfo.packetLength > 0)
|
||||
{
|
||||
if (endOffset - startOffset < this.packetLength)
|
||||
if (endOffset - startOffset < this.packetInfo.packetLength)
|
||||
{
|
||||
// input does not contain a single complete SSL record
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
packetLengths = new List<int>(4);
|
||||
packetLengths.Add(this.packetLength);
|
||||
offset += this.packetLength;
|
||||
totalLength = this.packetLength;
|
||||
this.packetLength = 0;
|
||||
packetInfos = new List<(int, byte)>(4);
|
||||
packetInfos.Add(this.packetInfo);
|
||||
offset += this.packetInfo.packetLength;
|
||||
totalLength = this.packetInfo.packetLength;
|
||||
this.packetInfo = default;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
packetLengths = new List<int>(4);
|
||||
packetInfos = new List<(int, byte)>(4);
|
||||
}
|
||||
|
||||
bool nonSslRecord = false;
|
||||
|
@ -216,7 +251,7 @@ namespace DotNetty.Handlers.Tls
|
|||
break;
|
||||
}
|
||||
|
||||
int encryptedPacketLength = TlsUtils.GetEncryptedPacketLength(input, offset);
|
||||
int encryptedPacketLength = TlsUtils.GetEncryptedPacketLength(input, offset, out byte contentType);
|
||||
if (encryptedPacketLength == -1)
|
||||
{
|
||||
nonSslRecord = true;
|
||||
|
@ -228,7 +263,7 @@ namespace DotNetty.Handlers.Tls
|
|||
if (encryptedPacketLength > readableBytes)
|
||||
{
|
||||
// wait until the whole packet can be read
|
||||
this.packetLength = encryptedPacketLength;
|
||||
this.packetInfo = (encryptedPacketLength, contentType);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -244,7 +279,7 @@ namespace DotNetty.Handlers.Tls
|
|||
|
||||
// We have a whole packet.
|
||||
// Increment the offset to handle the next packet.
|
||||
packetLengths.Add(encryptedPacketLength);
|
||||
packetInfos.Add((encryptedPacketLength, contentType));
|
||||
offset += encryptedPacketLength;
|
||||
totalLength = newTotalLength;
|
||||
}
|
||||
|
@ -263,7 +298,7 @@ namespace DotNetty.Handlers.Tls
|
|||
// See https://github.com/netty/netty/issues/1534
|
||||
|
||||
input.SkipBytes(totalLength);
|
||||
this.Unwrap(context, input, startOffset, totalLength, packetLengths, output);
|
||||
this.Unwrap(context, input, startOffset, totalLength, packetInfos, output);
|
||||
|
||||
if (!this.firedChannelRead)
|
||||
{
|
||||
|
@ -306,10 +341,17 @@ namespace DotNetty.Handlers.Tls
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Unwraps inbound SSL records.</summary>
|
||||
void Unwrap(IChannelHandlerContext ctx, IByteBuffer packet, int offset, int length, List<int> packetLengths, List<object> output)
|
||||
void Unwrap(
|
||||
IChannelHandlerContext ctx,
|
||||
IByteBuffer packet,
|
||||
int offset,
|
||||
int length,
|
||||
List<(int packetLength, byte packetContentType)> packetInfos,
|
||||
List<object> output)
|
||||
{
|
||||
Contract.Requires(packetLengths.Count > 0);
|
||||
Contract.Requires(packetInfos.Count > 0 || this.pendingDataPackets != null);
|
||||
|
||||
//bool notifyClosure = false; // todo: netty/issues/137
|
||||
bool pending = false;
|
||||
|
@ -318,17 +360,30 @@ namespace DotNetty.Handlers.Tls
|
|||
|
||||
try
|
||||
{
|
||||
ArraySegment<byte> inputIoBuffer = packet.GetIoBuffer(offset, length);
|
||||
this.mediationStream.SetSource(inputIoBuffer.Array, inputIoBuffer.Offset);
|
||||
|
||||
int packetIndex = 0;
|
||||
|
||||
while (!this.EnsureAuthenticated())
|
||||
if (packetInfos.Count > 0)
|
||||
{
|
||||
this.mediationStream.ExpandSource(packetLengths[packetIndex]);
|
||||
if (++packetIndex == packetLengths.Count)
|
||||
ArraySegment<byte> inputIoBuffer = packet.GetIoBuffer(offset, length);
|
||||
this.mediationStream.SetSource(inputIoBuffer.Array, inputIoBuffer.Offset);
|
||||
|
||||
while (!this.EnsureAuthenticated())
|
||||
{
|
||||
return;
|
||||
(int packetLength, byte type) = packetInfos[packetIndex];
|
||||
this.mediationStream.ExpandSource(packetLength);
|
||||
|
||||
if (type == TlsUtils.SSL_CONTENT_TYPE_APPLICATION_DATA)
|
||||
{
|
||||
// Due to SslStream's implementation, it's possible that we expand after handshake completed. Hence, we
|
||||
// need to make sure we call ReadFromSslStreamAsync for these packets later
|
||||
this.pendingDataPackets = this.pendingDataPackets ?? new List<(int packetLength, byte packetContentType)>(8);
|
||||
this.pendingDataPackets.Add((packetLength, type));
|
||||
}
|
||||
|
||||
if (++packetIndex == packetInfos.Count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -353,10 +408,33 @@ namespace DotNetty.Handlers.Tls
|
|||
}
|
||||
|
||||
// go through packets one by one (because SslStream does not consume more than 1 packet at a time)
|
||||
for (; packetIndex < packetLengths.Count; packetIndex++)
|
||||
// account pendingDataPackets
|
||||
int skipExpandPacketCount = 0;
|
||||
if (this.pendingDataPackets != null)
|
||||
{
|
||||
int currentPacketLength = packetLengths[packetIndex];
|
||||
this.mediationStream.ExpandSource(currentPacketLength);
|
||||
// We already expanded the source for all pendingDataPackets, so skip expand further below
|
||||
skipExpandPacketCount = this.pendingDataPackets.Count;
|
||||
|
||||
// add packetLengths to pending except already processed
|
||||
for (int i = packetIndex; i < packetInfos.Count; i++)
|
||||
{
|
||||
this.pendingDataPackets.Add(packetInfos[i]);
|
||||
}
|
||||
|
||||
packetInfos = this.pendingDataPackets;
|
||||
this.pendingDataPackets = null;
|
||||
packetIndex = 0;
|
||||
}
|
||||
|
||||
for (; packetIndex < packetInfos.Count; packetIndex++)
|
||||
{
|
||||
int currentPacketLength = packetInfos[packetIndex].packetLength;
|
||||
|
||||
if (--skipExpandPacketCount < 0)
|
||||
{
|
||||
// For pending packets we already expended, so skip expand
|
||||
this.mediationStream.ExpandSource(currentPacketLength);
|
||||
}
|
||||
|
||||
if (currentReadFuture != null)
|
||||
{
|
||||
|
@ -365,12 +443,10 @@ namespace DotNetty.Handlers.Tls
|
|||
if (!currentReadFuture.IsCompleted)
|
||||
{
|
||||
// we did feed the whole current packet to SslStream yet it did not produce any result -> move to the next packet in input
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
int read = currentReadFuture.Result;
|
||||
|
||||
if (read == 0)
|
||||
{
|
||||
//Stream closed
|
||||
|
@ -382,7 +458,7 @@ namespace DotNetty.Handlers.Tls
|
|||
|
||||
currentReadFuture = null;
|
||||
outputBuffer = null;
|
||||
if (this.mediationStream.SourceReadableBytes == 0)
|
||||
if (!this.mediationStream.SourceIsReadable)
|
||||
{
|
||||
// we just made a frame available for reading but there was already pending read so SslStream read it out to make further progress there
|
||||
|
||||
|
@ -428,9 +504,11 @@ namespace DotNetty.Handlers.Tls
|
|||
{
|
||||
break;
|
||||
}
|
||||
|
||||
int read = currentReadFuture.Result;
|
||||
AddBufferToOutput(outputBuffer, read, output);
|
||||
}
|
||||
|
||||
outputBuffer = ctx.Allocator.Buffer(FallbackReadBufferSize);
|
||||
currentReadFuture = this.ReadFromSslStreamAsync(outputBuffer, FallbackReadBufferSize);
|
||||
}
|
||||
|
@ -514,6 +592,7 @@ namespace DotNetty.Handlers.Tls
|
|||
{
|
||||
return TaskEx.FromException(new UnsupportedMessageTypeException(message, typeof(IByteBuffer)));
|
||||
}
|
||||
|
||||
return this.pendingUnencryptedWrites.Add(message);
|
||||
}
|
||||
|
||||
|
@ -569,6 +648,7 @@ namespace DotNetty.Handlers.Tls
|
|||
buffer.Release();
|
||||
}
|
||||
}
|
||||
|
||||
buf.ReadBytes(this.sslStream, buf.ReadableBytes); // this leads to FinishWrap being called 0+ times
|
||||
buf.Release();
|
||||
|
||||
|
@ -627,7 +707,6 @@ namespace DotNetty.Handlers.Tls
|
|||
{
|
||||
// Release all resources such as internal buffers that SSLEngine
|
||||
// is managing.
|
||||
|
||||
this.mediationStream.Dispose();
|
||||
try
|
||||
{
|
||||
|
@ -664,323 +743,6 @@ namespace DotNetty.Handlers.Tls
|
|||
this.CloseAsync(this.capturedContext);
|
||||
}
|
||||
}
|
||||
|
||||
sealed class MediationStream : Stream
|
||||
{
|
||||
readonly TlsHandler owner;
|
||||
byte[] input;
|
||||
int inputStartOffset;
|
||||
int inputOffset;
|
||||
int inputLength;
|
||||
TaskCompletionSource<int> readCompletionSource;
|
||||
ArraySegment<byte> sslOwnedBuffer;
|
||||
#if NETSTANDARD2_0
|
||||
int readByteCount;
|
||||
#else
|
||||
SynchronousAsyncResult<int> syncReadResult;
|
||||
AsyncCallback readCallback;
|
||||
TaskCompletionSource writeCompletion;
|
||||
AsyncCallback writeCallback;
|
||||
#endif
|
||||
|
||||
public MediationStream(TlsHandler owner)
|
||||
{
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public int SourceReadableBytes => this.inputLength - this.inputOffset;
|
||||
|
||||
public void SetSource(byte[] source, int offset)
|
||||
{
|
||||
this.input = source;
|
||||
this.inputStartOffset = offset;
|
||||
this.inputOffset = 0;
|
||||
this.inputLength = 0;
|
||||
}
|
||||
|
||||
public void ResetSource()
|
||||
{
|
||||
this.input = null;
|
||||
this.inputLength = 0;
|
||||
}
|
||||
|
||||
public void ExpandSource(int count)
|
||||
{
|
||||
Contract.Assert(this.input != null);
|
||||
|
||||
this.inputLength += count;
|
||||
|
||||
ArraySegment<byte> sslBuffer = this.sslOwnedBuffer;
|
||||
if (sslBuffer.Array == null)
|
||||
{
|
||||
// there is no pending read operation - keep for future
|
||||
return;
|
||||
}
|
||||
this.sslOwnedBuffer = default(ArraySegment<byte>);
|
||||
|
||||
#if NETSTANDARD2_0
|
||||
this.readByteCount = this.ReadFromInput(sslBuffer.Array, sslBuffer.Offset, sslBuffer.Count);
|
||||
// hack: this tricks SslStream's continuation to run synchronously instead of dispatching to TP. Remove once Begin/EndRead are available.
|
||||
new Task(
|
||||
ms =>
|
||||
{
|
||||
var self = (MediationStream)ms;
|
||||
TaskCompletionSource<int> p = self.readCompletionSource;
|
||||
self.readCompletionSource = null;
|
||||
p.TrySetResult(self.readByteCount);
|
||||
},
|
||||
this)
|
||||
.RunSynchronously(TaskScheduler.Default);
|
||||
#else
|
||||
int read = this.ReadFromInput(sslBuffer.Array, sslBuffer.Offset, sslBuffer.Count);
|
||||
|
||||
TaskCompletionSource<int> promise = this.readCompletionSource;
|
||||
this.readCompletionSource = null;
|
||||
promise.TrySetResult(read);
|
||||
|
||||
AsyncCallback callback = this.readCallback;
|
||||
this.readCallback = null;
|
||||
callback?.Invoke(promise.Task);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NETSTANDARD2_0
|
||||
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||
{
|
||||
if (this.SourceReadableBytes > 0)
|
||||
{
|
||||
// we have the bytes available upfront - write out synchronously
|
||||
int read = this.ReadFromInput(buffer, offset, count);
|
||||
return Task.FromResult(read);
|
||||
}
|
||||
|
||||
Contract.Assert(this.sslOwnedBuffer.Array == null);
|
||||
// take note of buffer - we will pass bytes there once available
|
||||
this.sslOwnedBuffer = new ArraySegment<byte>(buffer, offset, count);
|
||||
this.readCompletionSource = new TaskCompletionSource<int>();
|
||||
return this.readCompletionSource.Task;
|
||||
}
|
||||
#else
|
||||
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
|
||||
{
|
||||
if (this.SourceReadableBytes > 0)
|
||||
{
|
||||
// we have the bytes available upfront - write out synchronously
|
||||
int read = this.ReadFromInput(buffer, offset, count);
|
||||
var res = this.PrepareSyncReadResult(read, state);
|
||||
callback?.Invoke(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
Contract.Assert(this.sslOwnedBuffer.Array == null);
|
||||
// take note of buffer - we will pass bytes there once available
|
||||
this.sslOwnedBuffer = new ArraySegment<byte>(buffer, offset, count);
|
||||
this.readCompletionSource = new TaskCompletionSource<int>(state);
|
||||
this.readCallback = callback;
|
||||
return this.readCompletionSource.Task;
|
||||
}
|
||||
|
||||
public override int EndRead(IAsyncResult asyncResult)
|
||||
{
|
||||
SynchronousAsyncResult<int> syncResult = this.syncReadResult;
|
||||
if (ReferenceEquals(asyncResult, syncResult))
|
||||
{
|
||||
return syncResult.Result;
|
||||
}
|
||||
|
||||
Debug.Assert(this.readCompletionSource == null || this.readCompletionSource.Task == asyncResult);
|
||||
Contract.Assert(!((Task<int>)asyncResult).IsCanceled);
|
||||
|
||||
try
|
||||
{
|
||||
return ((Task<int>)asyncResult).Result;
|
||||
}
|
||||
catch (AggregateException ex)
|
||||
{
|
||||
ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
|
||||
throw; // unreachable
|
||||
}
|
||||
}
|
||||
|
||||
IAsyncResult PrepareSyncReadResult(int readBytes, object state)
|
||||
{
|
||||
// it is safe to reuse sync result object as it can't lead to leak (no way to attach to it via handle)
|
||||
SynchronousAsyncResult<int> result = this.syncReadResult ?? (this.syncReadResult = new SynchronousAsyncResult<int>());
|
||||
result.Result = readBytes;
|
||||
result.AsyncState = state;
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count) => this.owner.FinishWrap(buffer, offset, count);
|
||||
|
||||
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||
=> this.owner.FinishWrapNonAppDataAsync(buffer, offset, count);
|
||||
|
||||
#if !NETSTANDARD2_0
|
||||
static readonly Action<Task, object> WriteCompleteCallback = HandleChannelWriteComplete;
|
||||
|
||||
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
|
||||
{
|
||||
Task task = this.WriteAsync(buffer, offset, count);
|
||||
switch (task.Status)
|
||||
{
|
||||
case TaskStatus.RanToCompletion:
|
||||
// write+flush completed synchronously (and successfully)
|
||||
var result = new SynchronousAsyncResult<int>();
|
||||
result.AsyncState = state;
|
||||
callback?.Invoke(result);
|
||||
return result;
|
||||
default:
|
||||
if (callback != null || state != task.AsyncState)
|
||||
{
|
||||
Contract.Assert(this.writeCompletion == null);
|
||||
this.writeCallback = callback;
|
||||
var tcs = new TaskCompletionSource(state);
|
||||
this.writeCompletion = tcs;
|
||||
task.ContinueWith(WriteCompleteCallback, this, TaskContinuationOptions.ExecuteSynchronously);
|
||||
return tcs.Task;
|
||||
}
|
||||
else
|
||||
{
|
||||
return task;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void HandleChannelWriteComplete(Task writeTask, object state)
|
||||
{
|
||||
var self = (MediationStream)state;
|
||||
|
||||
AsyncCallback callback = self.writeCallback;
|
||||
self.writeCallback = null;
|
||||
|
||||
var promise = self.writeCompletion;
|
||||
self.writeCompletion = null;
|
||||
|
||||
switch (writeTask.Status)
|
||||
{
|
||||
case TaskStatus.RanToCompletion:
|
||||
promise.TryComplete();
|
||||
break;
|
||||
case TaskStatus.Canceled:
|
||||
promise.TrySetCanceled();
|
||||
break;
|
||||
case TaskStatus.Faulted:
|
||||
promise.TrySetException(writeTask.Exception);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("Unexpected task status: " + writeTask.Status);
|
||||
}
|
||||
|
||||
callback?.Invoke(promise.Task);
|
||||
}
|
||||
|
||||
public override void EndWrite(IAsyncResult asyncResult)
|
||||
{
|
||||
if (asyncResult is SynchronousAsyncResult<int>)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
((Task)asyncResult).Wait();
|
||||
}
|
||||
catch (AggregateException ex)
|
||||
{
|
||||
ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int ReadFromInput(byte[] destination, int destinationOffset, int destinationCapacity)
|
||||
{
|
||||
Contract.Assert(destination != null);
|
||||
|
||||
byte[] source = this.input;
|
||||
int readableBytes = this.SourceReadableBytes;
|
||||
int length = Math.Min(readableBytes, destinationCapacity);
|
||||
Buffer.BlockCopy(source, this.inputStartOffset + this.inputOffset, destination, destinationOffset, length);
|
||||
this.inputOffset += length;
|
||||
return length;
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
// NOOP: called on SslStream.Close
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
if (disposing)
|
||||
{
|
||||
TaskCompletionSource<int> p = this.readCompletionSource;
|
||||
if (p != null)
|
||||
{
|
||||
this.readCompletionSource = null;
|
||||
p.TrySetResult(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region plumbing
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override bool CanRead => true;
|
||||
|
||||
public override bool CanSeek => false;
|
||||
|
||||
public override bool CanWrite => true;
|
||||
|
||||
public override long Length
|
||||
{
|
||||
get { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get { throw new NotSupportedException(); }
|
||||
set { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region sync result
|
||||
sealed class SynchronousAsyncResult<T> : IAsyncResult
|
||||
{
|
||||
public T Result { get; set; }
|
||||
|
||||
public bool IsCompleted => true;
|
||||
|
||||
public WaitHandle AsyncWaitHandle
|
||||
{
|
||||
get { throw new InvalidOperationException("Cannot wait on a synchronous result."); }
|
||||
}
|
||||
|
||||
public object AsyncState { get; set; }
|
||||
|
||||
public bool CompletedSynchronously => true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
|
|
@ -53,12 +53,13 @@ namespace DotNetty.Handlers.Tls
|
|||
/// The length of the encrypted packet that is included in the buffer. This will
|
||||
/// return <c>-1</c> if the given <see cref="IByteBuffer"/> is not encrypted at all.
|
||||
/// </returns>
|
||||
public static int GetEncryptedPacketLength(IByteBuffer buffer, int offset)
|
||||
public static int GetEncryptedPacketLength(IByteBuffer buffer, int offset, out byte contentType)
|
||||
{
|
||||
int packetLength = 0;
|
||||
|
||||
// SSLv3 or TLS - Check ContentType
|
||||
switch (buffer.GetByte(offset))
|
||||
contentType = buffer.GetByte(offset);
|
||||
switch (contentType)
|
||||
{
|
||||
case SSL_CONTENT_TYPE_CHANGE_CIPHER_SPEC:
|
||||
case SSL_CONTENT_TYPE_ALERT:
|
||||
|
@ -90,6 +91,11 @@ namespace DotNetty.Handlers.Tls
|
|||
return packetLength;
|
||||
}
|
||||
|
||||
public static int GetEncryptedPacketLength(IByteBuffer buffer, int offset)
|
||||
{
|
||||
return GetEncryptedPacketLength(buffer, offset, out _);
|
||||
}
|
||||
|
||||
public static void NotifyHandshakeFailure(IChannelHandlerContext ctx, Exception cause)
|
||||
{
|
||||
// We have may haven written some parts of data before an exception was thrown so ensure we always flush.
|
||||
|
@ -98,5 +104,23 @@ namespace DotNetty.Handlers.Tls
|
|||
ctx.FireUserEventTriggered(new TlsHandshakeCompletionEvent(cause));
|
||||
ctx.CloseAsync();
|
||||
}
|
||||
|
||||
public static string FormatContentType(byte contentType)
|
||||
{
|
||||
switch (contentType)
|
||||
{
|
||||
case SSL_CONTENT_TYPE_CHANGE_CIPHER_SPEC:
|
||||
return nameof(SSL_CONTENT_TYPE_CHANGE_CIPHER_SPEC);
|
||||
case SSL_CONTENT_TYPE_ALERT:
|
||||
return nameof(SSL_CONTENT_TYPE_ALERT);
|
||||
case SSL_CONTENT_TYPE_HANDSHAKE:
|
||||
return nameof(SSL_CONTENT_TYPE_HANDSHAKE);
|
||||
case SSL_CONTENT_TYPE_APPLICATION_DATA:
|
||||
return nameof(SSL_CONTENT_TYPE_APPLICATION_DATA);
|
||||
default:
|
||||
// SSLv2 or bad data
|
||||
return "non-ssl";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup Label="NuGet">
|
||||
<TargetFrameworks>netstandard2.0;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netstandard2.0;net472;net5;net6</TargetFrameworks>
|
||||
<IsPackable>true</IsPackable>
|
||||
<PackageId>DotNetty.Transport.Libuv</PackageId>
|
||||
<Description>Libuv transport model in DotNetty</Description>
|
||||
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
|
||||
<AssemblyTitle>DotNetty: libuv transport model Experimental</AssemblyTitle>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<VersionPrefix>0.7.2</VersionPrefix>
|
||||
<VersionPrefix>0.7.3</VersionPrefix>
|
||||
<Authors>Microsoft</Authors>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||
|
|
|
@ -19,6 +19,7 @@ namespace DotNetty.Transport.Libuv
|
|||
using DotNetty.Common;
|
||||
using DotNetty.Transport.Libuv.Native;
|
||||
using Timer = Native.Timer;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
class LoopExecutor : AbstractScheduledEventExecutor
|
||||
{
|
||||
|
|
|
@ -331,7 +331,7 @@ namespace DotNetty.Transport.Libuv.Native
|
|||
{
|
||||
Debug.Assert(handle != IntPtr.Zero);
|
||||
|
||||
#if NETSTANDARD2_0
|
||||
#if NETSTANDARD2_0 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER
|
||||
int namelen = Marshal.SizeOf<sockaddr>();
|
||||
#else
|
||||
int namelen = Marshal.SizeOf(typeof(sockaddr));
|
||||
|
@ -344,7 +344,7 @@ namespace DotNetty.Transport.Libuv.Native
|
|||
{
|
||||
Debug.Assert(handle != IntPtr.Zero);
|
||||
|
||||
#if NETSTANDARD2_0
|
||||
#if NETSTANDARD2_0 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER
|
||||
int namelen = Marshal.SizeOf<sockaddr>();
|
||||
#else
|
||||
int namelen = Marshal.SizeOf(typeof(sockaddr));
|
||||
|
@ -354,7 +354,7 @@ namespace DotNetty.Transport.Libuv.Native
|
|||
return sockaddr.GetIPEndPoint();
|
||||
}
|
||||
|
||||
#if NETSTANDARD2_0
|
||||
#if NETSTANDARD2_0 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER
|
||||
internal static IntPtr Allocate(int size) => Marshal.AllocCoTaskMem(size);
|
||||
|
||||
internal static void FreeMemory(IntPtr ptr) => Marshal.FreeCoTaskMem(ptr);
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace DotNetty.Transport.Libuv.Native
|
|||
IntPtr socket = IntPtr.Zero;
|
||||
NativeMethods.uv_fileno(handle.Handle, ref socket);
|
||||
|
||||
#if NETSTANDARD2_0
|
||||
#if NETSTANDARD2_0 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER
|
||||
uint len = (uint)Marshal.SizeOf<FILE_COMPLETION_INFORMATION>();
|
||||
#else
|
||||
uint len = (uint)Marshal.SizeOf(typeof(FILE_COMPLETION_INFORMATION));
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace DotNetty.Transport.Libuv.Native
|
|||
|
||||
static WriteRequest()
|
||||
{
|
||||
#if NETSTANDARD2_0
|
||||
#if NETSTANDARD2_0 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER
|
||||
BufferSize = Marshal.SizeOf<uv_buf_t>();
|
||||
#else
|
||||
BufferSize = Marshal.SizeOf(typeof(uv_buf_t));
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace DotNetty.Transport.Libuv
|
|||
using DotNetty.Common.Utilities;
|
||||
using DotNetty.Transport.Channels;
|
||||
using DotNetty.Transport.Libuv.Native;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
public abstract class NativeChannel : AbstractChannel
|
||||
{
|
||||
|
|
|
@ -15,6 +15,7 @@ namespace DotNetty.Transport.Libuv
|
|||
using DotNetty.Common.Utilities;
|
||||
using DotNetty.Transport.Channels;
|
||||
using DotNetty.Transport.Libuv.Native;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
sealed class WorkerEventLoop : LoopExecutor, IEventLoop
|
||||
{
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace DotNetty.Transport.Bootstrapping
|
|||
using DotNetty.Common.Internal.Logging;
|
||||
using DotNetty.Common.Utilities;
|
||||
using DotNetty.Transport.Channels;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
/// <summary>
|
||||
/// This is a helper class that makes it easy to bootstrap an <see cref="IChannel"/>. It supports method-
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace DotNetty.Transport.Bootstrapping
|
|||
using DotNetty.Common.Internal.Logging;
|
||||
using DotNetty.Common.Utilities;
|
||||
using DotNetty.Transport.Channels;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="Bootstrap"/> that makes it easy to bootstrap an <see cref="IChannel"/> to use for clients.
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace DotNetty.Transport.Channels
|
|||
using DotNetty.Common.Concurrency;
|
||||
using DotNetty.Common.Internal.Logging;
|
||||
using DotNetty.Common.Utilities;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
public abstract class AbstractChannel : DefaultAttributeMap, IChannel
|
||||
{
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace DotNetty.Transport.Channels
|
|||
using DotNetty.Common.Concurrency;
|
||||
using DotNetty.Common.Internal;
|
||||
using DotNetty.Common.Utilities;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
abstract class AbstractChannelHandlerContext : IChannelHandlerContext, IResourceLeakHint
|
||||
{
|
||||
|
|
|
@ -11,6 +11,7 @@ namespace DotNetty.Transport.Channels
|
|||
using DotNetty.Common.Concurrency;
|
||||
using DotNetty.Common.Internal.Logging;
|
||||
using DotNetty.Common.Utilities;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
/// <summary>
|
||||
/// A queue of write operations which are pending for later execution. It also updates the
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace DotNetty.Transport.Channels
|
|||
using DotNetty.Common.Concurrency;
|
||||
using DotNetty.Common.Internal.Logging;
|
||||
using DotNetty.Common.Utilities;
|
||||
using ReferenceEqualityComparer = DotNetty.Common.Utilities.ReferenceEqualityComparer;
|
||||
|
||||
public class DefaultChannelPipeline : IChannelPipeline
|
||||
{
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace DotNetty.Transport.Channels.Embedded
|
|||
using DotNetty.Common.Internal.Logging;
|
||||
using DotNetty.Common.Utilities;
|
||||
|
||||
public class EmbeddedChannel : AbstractChannel
|
||||
public class EmbeddedChannel : AbstractChannel, IEmbeddedChannel
|
||||
{
|
||||
static readonly EndPoint LOCAL_ADDRESS = new EmbeddedSocketAddress();
|
||||
static readonly EndPoint REMOTE_ADDRESS = new EmbeddedSocketAddress();
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace DotNetty.Transport.Channels.Embedded
|
||||
{
|
||||
public interface IEmbeddedChannel : IChannel
|
||||
{
|
||||
bool WriteInbound(params object[] msgs);
|
||||
|
||||
bool WriteOutbound(params object[] msgs);
|
||||
|
||||
T ReadInbound<T>();
|
||||
|
||||
T ReadOutbound<T>();
|
||||
|
||||
bool Finish();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,468 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace DotNetty.Transport.Channels.Embedded
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Net;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Threading.Tasks;
|
||||
using DotNetty.Common;
|
||||
using DotNetty.Common.Internal.Logging;
|
||||
using DotNetty.Common.Utilities;
|
||||
|
||||
public class SingleThreadedEmbeddedChannel : AbstractChannel, IEmbeddedChannel
|
||||
{
|
||||
static readonly EndPoint LOCAL_ADDRESS = new EmbeddedSocketAddress();
|
||||
static readonly EndPoint REMOTE_ADDRESS = new EmbeddedSocketAddress();
|
||||
|
||||
enum State
|
||||
{
|
||||
Open,
|
||||
Active,
|
||||
Closed
|
||||
};
|
||||
|
||||
static readonly IChannelHandler[] EMPTY_HANDLERS = new IChannelHandler[0];
|
||||
|
||||
static readonly IInternalLogger logger = InternalLoggerFactory.GetInstance<EmbeddedChannel>();
|
||||
|
||||
static readonly ChannelMetadata METADATA_NO_DISCONNECT = new ChannelMetadata(false);
|
||||
static readonly ChannelMetadata METADATA_DISCONNECT = new ChannelMetadata(true);
|
||||
|
||||
readonly IEventLoop loop = new SingleThreadEventLoop();
|
||||
|
||||
Queue<object> inboundMessages;
|
||||
Queue<object> outboundMessages;
|
||||
Exception lastException;
|
||||
State state;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance with an empty pipeline.
|
||||
/// </summary>
|
||||
public SingleThreadedEmbeddedChannel(IEventLoop eventLoop = null)
|
||||
: this(EmbeddedChannelId.Instance, eventLoop, EMPTY_HANDLERS)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance with an empty pipeline with the specified <see cref="IChannelId" />.
|
||||
/// </summary>
|
||||
/// <param name="channelId">The <see cref="IChannelId" /> of this channel. </param>
|
||||
public SingleThreadedEmbeddedChannel(IChannelId channelId, IEventLoop eventLoop = null)
|
||||
: this(channelId, eventLoop, EMPTY_HANDLERS)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance with the pipeline initialized with the specified handlers.
|
||||
/// </summary>
|
||||
/// <param name="handlers">
|
||||
/// The <see cref="IChannelHandler" />s that will be added to the <see cref="IChannelPipeline" />
|
||||
/// </param>
|
||||
public SingleThreadedEmbeddedChannel(IEventLoop eventLoop = null, params IChannelHandler[] handlers)
|
||||
: this(EmbeddedChannelId.Instance, eventLoop, handlers)
|
||||
{
|
||||
}
|
||||
|
||||
public SingleThreadedEmbeddedChannel(IChannelId id, IEventLoop eventLoop = null, params IChannelHandler[] handlers)
|
||||
: this(id, false, eventLoop, handlers)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Create a new instance with the pipeline initialized with the specified handlers.</summary>
|
||||
/// <param name="id">The <see cref="IChannelId" /> of this channel.</param>
|
||||
/// <param name="hasDisconnect">
|
||||
/// <c>false</c> if this <see cref="IChannel" /> will delegate <see cref="DisconnectAsync" />
|
||||
/// to <see cref="CloseAsync" />, <c>true</c> otherwise.
|
||||
/// </param>
|
||||
/// <param name="handlers">
|
||||
/// The <see cref="IChannelHandler" />s that will be added to the <see cref="IChannelPipeline" />
|
||||
/// </param>
|
||||
public SingleThreadedEmbeddedChannel(IChannelId id, bool hasDisconnect, IEventLoop eventLoop = null, params IChannelHandler[] handlers)
|
||||
: this(id, hasDisconnect, true, eventLoop, handlers)
|
||||
{ }
|
||||
|
||||
public SingleThreadedEmbeddedChannel(IChannelId id, bool hasDisconnect, bool register, IEventLoop eventLoop = null, params IChannelHandler[] handlers)
|
||||
: base(null, id)
|
||||
{
|
||||
if (eventLoop != null)
|
||||
{
|
||||
this.loop = eventLoop;
|
||||
}
|
||||
|
||||
this.Metadata = GetMetadata(hasDisconnect);
|
||||
this.Configuration = new DefaultChannelConfiguration(this);
|
||||
this.Setup(register, handlers);
|
||||
}
|
||||
|
||||
public SingleThreadedEmbeddedChannel(IChannelId id, bool hasDisconnect, IChannelConfiguration config, IEventLoop eventLoop = null,
|
||||
params IChannelHandler[] handlers)
|
||||
: base(null, id)
|
||||
{
|
||||
Contract.Requires(config != null);
|
||||
|
||||
if (eventLoop != null)
|
||||
{
|
||||
this.loop = eventLoop;
|
||||
}
|
||||
this.Metadata = GetMetadata(hasDisconnect);
|
||||
this.Configuration = config;
|
||||
this.Setup(true, handlers);
|
||||
}
|
||||
|
||||
static ChannelMetadata GetMetadata(bool hasDisconnect) => hasDisconnect ? METADATA_DISCONNECT : METADATA_NO_DISCONNECT;
|
||||
|
||||
void Setup(bool register, params IChannelHandler[] handlers)
|
||||
{
|
||||
Contract.Requires(handlers != null);
|
||||
|
||||
IChannelPipeline p = this.Pipeline;
|
||||
p.AddLast(new ActionChannelInitializer<IChannel>(channel =>
|
||||
{
|
||||
IChannelPipeline pipeline = channel.Pipeline;
|
||||
foreach (IChannelHandler h in handlers)
|
||||
{
|
||||
if (h == null)
|
||||
{
|
||||
break;
|
||||
|
||||
}
|
||||
pipeline.AddLast(h);
|
||||
}
|
||||
}));
|
||||
|
||||
if (register)
|
||||
{
|
||||
Task future = this.loop.RegisterAsync(this);
|
||||
future.GetAwaiter().GetResult();
|
||||
Debug.Assert(future.IsCompleted);
|
||||
}
|
||||
}
|
||||
|
||||
public void Register()
|
||||
{
|
||||
Task future = this.loop.RegisterAsync(this);
|
||||
// Debug.Assert(future.IsCompleted);
|
||||
this.Pipeline.AddLast(new LastInboundHandler(this.InboundMessages, this.RecordException));
|
||||
future.GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
protected sealed override DefaultChannelPipeline NewChannelPipeline() => new SingleThreadedEmbeddedChannelPipeline(this);
|
||||
|
||||
public override ChannelMetadata Metadata { get; }
|
||||
|
||||
public override IChannelConfiguration Configuration { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the <see cref="Queue{T}" /> which holds all of the <see cref="object" />s that
|
||||
/// were received by this <see cref="IChannel" />.
|
||||
/// </summary>
|
||||
public Queue<object> InboundMessages => this.inboundMessages ?? (this.inboundMessages = new Queue<object>());
|
||||
|
||||
/// <summary>
|
||||
/// Returns the <see cref="Queue{T}" /> which holds all of the <see cref="object" />s that
|
||||
/// were written by this <see cref="IChannel" />.
|
||||
/// </summary>
|
||||
public Queue<object> OutboundMessages => this.outboundMessages ?? (this.outboundMessages = new Queue<object>());
|
||||
|
||||
/// <summary>
|
||||
/// Return received data from this <see cref="IChannel"/>.
|
||||
/// </summary>
|
||||
public T ReadInbound<T>() => (T)Poll(this.inboundMessages);
|
||||
|
||||
/// <summary>
|
||||
/// Read data from the outbound. This may return <c>null</c> if nothing is readable.
|
||||
/// </summary>
|
||||
public T ReadOutbound<T>() => (T)Poll(this.outboundMessages);
|
||||
|
||||
protected override EndPoint LocalAddressInternal => this.Active ? LOCAL_ADDRESS : null;
|
||||
|
||||
protected override EndPoint RemoteAddressInternal => this.Active ? REMOTE_ADDRESS : null;
|
||||
|
||||
protected override IChannelUnsafe NewUnsafe() => new DefaultUnsafe(this);
|
||||
|
||||
protected override bool IsCompatible(IEventLoop eventLoop) => true;
|
||||
|
||||
protected override void DoBind(EndPoint localAddress)
|
||||
{
|
||||
//NOOP
|
||||
}
|
||||
|
||||
protected override void DoRegister() => this.state = State.Active;
|
||||
|
||||
protected override void DoDisconnect() => this.DoClose();
|
||||
|
||||
protected override void DoClose() => this.state = State.Closed;
|
||||
|
||||
protected override void DoBeginRead()
|
||||
{
|
||||
//NOOP
|
||||
}
|
||||
|
||||
protected override void DoWrite(ChannelOutboundBuffer input)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
object msg = input.Current;
|
||||
if (msg == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ReferenceCountUtil.Retain(msg);
|
||||
this.OutboundMessages.Enqueue(msg);
|
||||
input.Remove();
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Open => this.state != State.Closed;
|
||||
|
||||
public override bool Active => this.state == State.Active;
|
||||
|
||||
/// <summary>
|
||||
/// Write messages to the inbound of this <see cref="IChannel" />
|
||||
/// </summary>
|
||||
/// <param name="msgs">The messages to be written.</param>
|
||||
/// <returns><c>true</c> if the write operation did add something to the inbound buffer</returns>
|
||||
public bool WriteInbound(params object[] msgs)
|
||||
{
|
||||
this.EnsureOpen();
|
||||
if (msgs.Length == 0)
|
||||
{
|
||||
return IsNotEmpty(this.inboundMessages);
|
||||
}
|
||||
|
||||
IChannelPipeline p = this.Pipeline;
|
||||
foreach (object m in msgs)
|
||||
{
|
||||
p.FireChannelRead(m);
|
||||
}
|
||||
p.FireChannelReadComplete();
|
||||
this.CheckException();
|
||||
return IsNotEmpty(this.inboundMessages);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write messages to the outbound of this <see cref="IChannel" />.
|
||||
/// </summary>
|
||||
/// <param name="msgs">The messages to be written.</param>
|
||||
/// <returns><c>true</c> if the write operation did add something to the inbound buffer</returns>
|
||||
public bool WriteOutbound(params object[] msgs)
|
||||
{
|
||||
this.EnsureOpen();
|
||||
if (msgs.Length == 0)
|
||||
{
|
||||
return IsNotEmpty(this.outboundMessages);
|
||||
}
|
||||
|
||||
ThreadLocalObjectList futures = ThreadLocalObjectList.NewInstance(msgs.Length);
|
||||
|
||||
foreach (object m in msgs)
|
||||
{
|
||||
if (m == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
futures.Add(this.WriteAsync(m));
|
||||
}
|
||||
this.Flush();
|
||||
|
||||
int size = futures.Count;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
var future = (Task)futures[i];
|
||||
if (future.IsCompleted)
|
||||
{
|
||||
this.RecordException(future);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The write may be delayed to run later by runPendingTasks()
|
||||
future.ContinueWith(t => this.RecordException(t));
|
||||
}
|
||||
}
|
||||
futures.Return();
|
||||
|
||||
this.CheckException();
|
||||
return IsNotEmpty(this.outboundMessages);
|
||||
}
|
||||
|
||||
void RecordException(Task future)
|
||||
{
|
||||
switch (future.Status)
|
||||
{
|
||||
case TaskStatus.Canceled:
|
||||
case TaskStatus.Faulted:
|
||||
this.RecordException(future.Exception);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RecordException(Exception cause)
|
||||
{
|
||||
if (this.lastException == null)
|
||||
{
|
||||
this.lastException = cause;
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Warn("More than one exception was raised. " + "Will report only the first one and log others.", cause);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mark this <see cref="IChannel" /> as finished. Any further try to write data to it will fail.
|
||||
/// </summary>
|
||||
/// <returns>bufferReadable returns <c>true</c></returns>
|
||||
public bool Finish() => this.Finish(false);
|
||||
|
||||
/// <summary>
|
||||
/// Marks this <see cref="IChannel"/> as finished and releases all pending message in the inbound and outbound
|
||||
/// buffer. Any futher try to write data to it will fail.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if any of the used buffers has something left to read, otherwise <c>false</c>.</returns>
|
||||
public bool FinishAndReleaseAll() => this.Finish(true);
|
||||
|
||||
/// <summary>
|
||||
/// Marks this <see cref="IChannel"/> as finished. Any futher attempt to write data to it will fail.
|
||||
/// </summary>
|
||||
/// <param name="releaseAll">If <c>true</c>, all pending messages in the inbound and outbound buffer are released.</param>
|
||||
/// <returns><c>true</c> if any of the used buffers has something left to read, otherwise <c>false</c>.</returns>
|
||||
bool Finish(bool releaseAll)
|
||||
{
|
||||
this.CloseSafe();
|
||||
try
|
||||
{
|
||||
this.CheckException();
|
||||
return IsNotEmpty(this.inboundMessages) || IsNotEmpty(this.outboundMessages);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (releaseAll)
|
||||
{
|
||||
ReleaseAll(this.inboundMessages);
|
||||
ReleaseAll(this.outboundMessages);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases all buffered inbound messages.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if any were in the inbound buffer, otherwise <c>false</c>.</returns>
|
||||
public bool ReleaseInbound() => ReleaseAll(this.inboundMessages);
|
||||
|
||||
/// <summary>
|
||||
/// Releases all buffered outbound messages.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if any were in the outbound buffer, otherwise <c>false</c>.</returns>
|
||||
public bool ReleaseOutbound() => ReleaseAll(this.outboundMessages);
|
||||
|
||||
static bool ReleaseAll(Queue<object> queue)
|
||||
{
|
||||
if (queue != null && queue.Count > 0)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (queue.Count == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
object msg = queue.Dequeue();
|
||||
ReferenceCountUtil.Release(msg);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override Task CloseAsync()
|
||||
{
|
||||
// We need to call RunPendingTasks() before calling super.CloseAsync() as there may be something in the queue
|
||||
// that needs to be run before the actual close takes place.
|
||||
Task future = base.CloseAsync();
|
||||
return future;
|
||||
}
|
||||
|
||||
public override Task DisconnectAsync()
|
||||
{
|
||||
Task future = base.DisconnectAsync();
|
||||
return future;
|
||||
}
|
||||
|
||||
static bool IsNotEmpty(Queue<object> queue) => queue != null && queue.Count > 0;
|
||||
|
||||
/// <summary>
|
||||
/// Check to see if there was any <see cref="Exception" /> and rethrow if so.
|
||||
/// </summary>
|
||||
public void CheckException()
|
||||
{
|
||||
Exception e = this.lastException;
|
||||
if (e == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.lastException = null;
|
||||
ExceptionDispatchInfo.Capture(e).Throw();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensure the <see cref="IChannel" /> is open and if not throw an exception.
|
||||
/// </summary>
|
||||
protected void EnsureOpen()
|
||||
{
|
||||
if (!this.Open)
|
||||
{
|
||||
this.RecordException(new ClosedChannelException());
|
||||
this.CheckException();
|
||||
}
|
||||
}
|
||||
|
||||
static object Poll(Queue<object> queue) => IsNotEmpty(queue) ? queue.Dequeue() : null;
|
||||
|
||||
class DefaultUnsafe : AbstractUnsafe
|
||||
{
|
||||
public DefaultUnsafe(AbstractChannel channel)
|
||||
: base(channel)
|
||||
{
|
||||
}
|
||||
|
||||
public override Task ConnectAsync(EndPoint remoteAddress, EndPoint localAddress) => TaskEx.Completed;
|
||||
}
|
||||
|
||||
internal sealed class LastInboundHandler : ChannelHandlerAdapter
|
||||
{
|
||||
readonly Queue<object> inboundMessages;
|
||||
readonly Action<Exception> recordException;
|
||||
|
||||
public LastInboundHandler(Queue<object> inboundMessages, Action<Exception> recordException)
|
||||
{
|
||||
this.inboundMessages = inboundMessages;
|
||||
this.recordException = recordException;
|
||||
}
|
||||
|
||||
public override void ChannelRead(IChannelHandlerContext context, object message) => this.inboundMessages.Enqueue(message);
|
||||
|
||||
public override void ExceptionCaught(IChannelHandlerContext context, Exception exception) => this.recordException(exception);
|
||||
}
|
||||
|
||||
sealed class SingleThreadedEmbeddedChannelPipeline : DefaultChannelPipeline
|
||||
{
|
||||
public SingleThreadedEmbeddedChannelPipeline(SingleThreadedEmbeddedChannel channel)
|
||||
: base(channel)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnUnhandledInboundException(Exception cause) => ((SingleThreadedEmbeddedChannel)this.Channel).RecordException(cause);
|
||||
|
||||
protected override void OnUnhandledInboundMessage(object msg) => ((SingleThreadedEmbeddedChannel)this.Channel).InboundMessages.Enqueue(msg);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ namespace DotNetty.Transport.Channels.Local
|
|||
using DotNetty.Common.Internal;
|
||||
using DotNetty.Common.Internal.Logging;
|
||||
using DotNetty.Common.Utilities;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="IChannel"/> for the local transport.
|
||||
|
|
|
@ -11,6 +11,7 @@ namespace DotNetty.Transport.Channels
|
|||
using DotNetty.Common.Concurrency;
|
||||
using DotNetty.Common.Internal.Logging;
|
||||
using DotNetty.Common.Utilities;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
/// <summary>
|
||||
/// A queue of write operations which are pending for later execution. It also updates the writability of the
|
||||
|
|
|
@ -154,7 +154,7 @@ namespace DotNetty.Transport.Channels.Sockets
|
|||
{
|
||||
SocketChannelAsyncOperation operation = this.ReadOperation;
|
||||
bool pending;
|
||||
#if NETSTANDARD2_0
|
||||
#if NETSTANDARD2_0 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER
|
||||
pending = this.Socket.ReceiveAsync(operation);
|
||||
#else
|
||||
if (ExecutionContext.IsFlowSuppressed())
|
||||
|
@ -308,7 +308,7 @@ namespace DotNetty.Transport.Channels.Sockets
|
|||
this.SetState(StateFlags.WriteScheduled);
|
||||
bool pending;
|
||||
|
||||
#if NETSTANDARD2_0
|
||||
#if NETSTANDARD2_0 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER
|
||||
pending = this.Socket.SendAsync(operation);
|
||||
#else
|
||||
if (ExecutionContext.IsFlowSuppressed())
|
||||
|
|
|
@ -12,6 +12,7 @@ namespace DotNetty.Transport.Channels.Sockets
|
|||
using DotNetty.Common.Concurrency;
|
||||
using DotNetty.Common.Internal.Logging;
|
||||
using DotNetty.Common.Utilities;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
public abstract class AbstractSocketChannel : AbstractChannel
|
||||
{
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace DotNetty.Transport.Channels.Sockets
|
|||
using System.Net.NetworkInformation;
|
||||
using System.Threading.Tasks;
|
||||
using DotNetty.Common.Concurrency;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
public interface IDatagramChannel : IChannel
|
||||
{
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace DotNetty.Transport.Channels.Sockets
|
|||
using DotNetty.Common.Concurrency;
|
||||
using DotNetty.Common.Internal.Logging;
|
||||
using DotNetty.Common.Utilities;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
public class SocketDatagramChannel : AbstractSocketMessageChannel, IDatagramChannel
|
||||
{
|
||||
|
@ -115,7 +116,7 @@ namespace DotNetty.Transport.Channels.Sockets
|
|||
operation.SetBuffer(bytes.Array, bytes.Offset, bytes.Count);
|
||||
|
||||
bool pending;
|
||||
#if NETSTANDARD2_0
|
||||
#if NETSTANDARD2_0 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER
|
||||
pending = this.Socket.ReceiveFromAsync(operation);
|
||||
#else
|
||||
if (ExecutionContext.IsFlowSuppressed())
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace DotNetty.Transport.Channels.Sockets
|
|||
using System.Threading.Tasks;
|
||||
using DotNetty.Buffers;
|
||||
using DotNetty.Common.Concurrency;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="ISocketChannel" /> which uses Socket-based implementation.
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace DotNetty.Transport.Channels
|
|||
using System.Threading.Tasks;
|
||||
using DotNetty.Common.Concurrency;
|
||||
using DotNetty.Common.Internal.Logging;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
static class Util
|
||||
{
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup Label="NuGet">
|
||||
<TargetFrameworks>netstandard2.0;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netstandard2.0;net472;net5;net6</TargetFrameworks>
|
||||
<IsPackable>true</IsPackable>
|
||||
<PackageId>DotNetty.Transport</PackageId>
|
||||
<Description>Transport model in DotNetty</Description>
|
||||
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
|
||||
<AssemblyTitle>DotNetty: transport model</AssemblyTitle>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<VersionPrefix>0.7.2</VersionPrefix>
|
||||
<VersionPrefix>0.7.3</VersionPrefix>
|
||||
<Authors>Microsoft</Authors>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
|
|
|
@ -7,7 +7,7 @@ using System.Reflection;
|
|||
|
||||
[assembly: AssemblyCompany("Microsoft")]
|
||||
[assembly: AssemblyProduct("DotNetty")]
|
||||
[assembly: AssemblyVersion("0.7.2")]
|
||||
[assembly: AssemblyFileVersion("0.7.2")]
|
||||
[assembly: AssemblyVersion("0.7.3")]
|
||||
[assembly: AssemblyFileVersion("0.7.3")]
|
||||
[assembly: AssemblyCopyright("(c) Microsoft 2015 - 2021")]
|
||||
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<AssemblyOriginatorKeyFile>../../DotNetty.snk</AssemblyOriginatorKeyFile>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<AssemblyOriginatorKeyFile>../../DotNetty.snk</AssemblyOriginatorKeyFile>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
|
||||
|
|
|
@ -17,6 +17,7 @@ namespace DotNetty.Codecs.Http.Tests
|
|||
using Xunit;
|
||||
|
||||
using HttpVersion = DotNetty.Codecs.Http.HttpVersion;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
public sealed class HttpClientCodecTest
|
||||
{
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace DotNetty.Codecs.Http.Tests
|
|||
using DotNetty.Transport.Channels;
|
||||
using DotNetty.Transport.Channels.Embedded;
|
||||
using Xunit;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
public class HttpServerUpgradeHandlerTest
|
||||
{
|
||||
|
|
|
@ -12,6 +12,7 @@ namespace DotNetty.Codecs.Http.Tests.WebSockets
|
|||
using DotNetty.Transport.Channels;
|
||||
using DotNetty.Transport.Channels.Embedded;
|
||||
using Xunit;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
public class WebSocketHandshakeHandOverTest
|
||||
{
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<AssemblyOriginatorKeyFile>../../DotNetty.snk</AssemblyOriginatorKeyFile>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<AssemblyOriginatorKeyFile>../../DotNetty.snk</AssemblyOriginatorKeyFile>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<AssemblyOriginatorKeyFile>../../DotNetty.snk</AssemblyOriginatorKeyFile>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<AssemblyOriginatorKeyFile>../../DotNetty.snk</AssemblyOriginatorKeyFile>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace DotNetty.Common.Tests.Concurrency
|
|||
using DotNetty.Tests.Common;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
public class SingleThreadEventExecutorTests : TestBase
|
||||
{
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<AssemblyOriginatorKeyFile>../../DotNetty.snk</AssemblyOriginatorKeyFile>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace DotNetty.Handlers.Tests
|
|||
|
||||
class AsIsWriteStrategy : IWriteStrategy
|
||||
{
|
||||
public Task WriteToChannelAsync(EmbeddedChannel channel, ArraySegment<byte> input)
|
||||
public Task WriteToChannelAsync(IEmbeddedChannel channel, ArraySegment<byte> input)
|
||||
{
|
||||
channel.WriteInbound(Unpooled.WrappedBuffer(input.Array, input.Offset, input.Count));
|
||||
return TaskEx.Completed;
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace DotNetty.Handlers.Tests
|
|||
readonly TimeSpan timeWindow;
|
||||
readonly bool forceSizing;
|
||||
IByteBuffer pendingBuffer;
|
||||
EmbeddedChannel channel;
|
||||
IEmbeddedChannel channel;
|
||||
|
||||
public BatchingWriteStrategy(int maxBatchSize, TimeSpan timeWindow, bool forceSizing)
|
||||
{
|
||||
|
@ -23,7 +23,7 @@ namespace DotNetty.Handlers.Tests
|
|||
this.forceSizing = forceSizing;
|
||||
}
|
||||
|
||||
public async Task WriteToChannelAsync(EmbeddedChannel ch, ArraySegment<byte> input)
|
||||
public async Task WriteToChannelAsync(IEmbeddedChannel ch, ArraySegment<byte> input)
|
||||
{
|
||||
this.channel = ch;
|
||||
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<AssemblyOriginatorKeyFile>../../DotNetty.snk</AssemblyOriginatorKeyFile>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
|
||||
|
|
|
@ -9,6 +9,6 @@ namespace DotNetty.Handlers.Tests
|
|||
|
||||
public interface IWriteStrategy
|
||||
{
|
||||
Task WriteToChannelAsync(EmbeddedChannel channel, ArraySegment<byte> input);
|
||||
Task WriteToChannelAsync(IEmbeddedChannel channel, ArraySegment<byte> input);
|
||||
}
|
||||
}
|
|
@ -72,13 +72,13 @@ namespace DotNetty.Handlers.Tests
|
|||
this.Output.WriteLine($"protocol: {protocol}");
|
||||
this.Output.WriteLine($"targetHost: {targetHost}");
|
||||
|
||||
var executor = new SingleThreadEventExecutor("test executor", TimeSpan.FromMilliseconds(10));
|
||||
var executor = new SingleThreadEventLoop("test executor", TimeSpan.FromMilliseconds(10));
|
||||
|
||||
try
|
||||
{
|
||||
var writeTasks = new List<Task>();
|
||||
var pair = await SetupStreamAndChannelAsync(isClient, executor, writeStrategy, protocol, writeTasks, targetHost).WithTimeout(TimeSpan.FromSeconds(10));
|
||||
EmbeddedChannel ch = pair.Item1;
|
||||
IEmbeddedChannel ch = pair.Item1;
|
||||
SslStream driverStream = pair.Item2;
|
||||
|
||||
int randomSeed = Environment.TickCount;
|
||||
|
@ -139,13 +139,13 @@ namespace DotNetty.Handlers.Tests
|
|||
this.Output.WriteLine($"targetHost: {targetHost}");
|
||||
|
||||
var writeStrategy = new AsIsWriteStrategy();
|
||||
var executor = new SingleThreadEventExecutor("test executor", TimeSpan.FromMilliseconds(10));
|
||||
var executor = new SingleThreadEventLoop("test executor", TimeSpan.FromMilliseconds(10));
|
||||
|
||||
try
|
||||
{
|
||||
var writeTasks = new List<Task>();
|
||||
var pair = await SetupStreamAndChannelAsync(isClient, executor, writeStrategy, protocol, writeTasks, targetHost);
|
||||
EmbeddedChannel ch = pair.Item1;
|
||||
IEmbeddedChannel ch = pair.Item1;
|
||||
SslStream driverStream = pair.Item2;
|
||||
|
||||
int randomSeed = Environment.TickCount;
|
||||
|
@ -189,7 +189,7 @@ namespace DotNetty.Handlers.Tests
|
|||
}
|
||||
}
|
||||
|
||||
static async Task<Tuple<EmbeddedChannel, SslStream>> SetupStreamAndChannelAsync(bool isClient, IEventExecutor executor, IWriteStrategy writeStrategy, SslProtocols protocol, List<Task> writeTasks, string targetHost)
|
||||
static async Task<Tuple<IEmbeddedChannel, SslStream>> SetupStreamAndChannelAsync(bool isClient, IEventLoop executor, IWriteStrategy writeStrategy, SslProtocols protocol, List<Task> writeTasks, string targetHost)
|
||||
{
|
||||
IChannelHandler tlsHandler = isClient ?
|
||||
(IChannelHandler)new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) =>
|
||||
|
@ -199,13 +199,19 @@ namespace DotNetty.Handlers.Tests
|
|||
}), new ClientTlsSettings(protocol, false, new List<X509Certificate>(), targetHost)) :
|
||||
new SniHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true), new ServerTlsSniSettings(CertificateSelector));
|
||||
//var ch = new EmbeddedChannel(new LoggingHandler("BEFORE"), tlsHandler, new LoggingHandler("AFTER"));
|
||||
var ch = new EmbeddedChannel(tlsHandler);
|
||||
|
||||
#if NET5_0_OR_GREATER
|
||||
IEmbeddedChannel ch = new SingleThreadedEmbeddedChannel(executor, tlsHandler);
|
||||
#else
|
||||
IEmbeddedChannel ch = new EmbeddedChannel(tlsHandler);
|
||||
#endif
|
||||
if (!isClient)
|
||||
{
|
||||
// check if in the beginning snihandler exists in the pipeline, but not tls handler
|
||||
Assert.NotNull(ch.Pipeline.Get<SniHandler>());
|
||||
Assert.Null(ch.Pipeline.Get<TlsHandler>());
|
||||
await AssertEx.EventuallyAsync(
|
||||
() => ch.Pipeline.Get<SniHandler>() != null && ch.Pipeline.Get<TlsHandler>() == null,
|
||||
TimeSpan.FromMilliseconds(10),
|
||||
TimeSpan.FromSeconds(5)
|
||||
);
|
||||
}
|
||||
|
||||
IByteBuffer readResultBuffer = Unpooled.Buffer(4 * 1024);
|
||||
|
|
|
@ -69,7 +69,6 @@ namespace DotNetty.Handlers.Tests
|
|||
select new object[] { frameLengths, isClient, writeStrategyFactory(), protocol.Item1, protocol.Item2 };
|
||||
}
|
||||
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(GetTlsReadTestData))]
|
||||
public async Task TlsRead(int[] frameLengths, bool isClient, IWriteStrategy writeStrategy, SslProtocols serverProtocol, SslProtocols clientProtocol)
|
||||
|
@ -80,13 +79,13 @@ namespace DotNetty.Handlers.Tests
|
|||
this.Output.WriteLine($"serverProtocol: {serverProtocol}");
|
||||
this.Output.WriteLine($"clientProtocol: {clientProtocol}");
|
||||
|
||||
var executor = new SingleThreadEventExecutor("test executor", TimeSpan.FromMilliseconds(10));
|
||||
var executor = new SingleThreadEventLoop("test executor", TimeSpan.FromMilliseconds(10));
|
||||
|
||||
try
|
||||
{
|
||||
var writeTasks = new List<Task>();
|
||||
var pair = await SetupStreamAndChannelAsync(isClient, executor, writeStrategy, serverProtocol, clientProtocol, writeTasks).WithTimeout(TimeSpan.FromSeconds(10));
|
||||
EmbeddedChannel ch = pair.Item1;
|
||||
IEmbeddedChannel ch = pair.Item1;
|
||||
SslStream driverStream = pair.Item2;
|
||||
|
||||
int randomSeed = Environment.TickCount;
|
||||
|
@ -101,6 +100,7 @@ namespace DotNetty.Handlers.Tests
|
|||
}
|
||||
await Task.WhenAll(writeTasks).WithTimeout(TimeSpan.FromSeconds(5));
|
||||
IByteBuffer finalReadBuffer = Unpooled.Buffer(16 * 1024);
|
||||
|
||||
await ReadOutboundAsync(async () => ch.ReadInbound<IByteBuffer>(), expectedBuffer.ReadableBytes, finalReadBuffer, TestTimeout);
|
||||
bool isEqual = ByteBufferUtil.Equals(expectedBuffer, finalReadBuffer);
|
||||
if (!isEqual)
|
||||
|
@ -160,13 +160,13 @@ namespace DotNetty.Handlers.Tests
|
|||
var writeStrategy = new AsIsWriteStrategy();
|
||||
this.Output.WriteLine($"writeStrategy: {writeStrategy}");
|
||||
|
||||
var executor = new SingleThreadEventExecutor("test executor", TimeSpan.FromMilliseconds(10));
|
||||
var executor = new SingleThreadEventLoop("test executor", TimeSpan.FromMilliseconds(10));
|
||||
|
||||
try
|
||||
{
|
||||
var writeTasks = new List<Task>();
|
||||
var pair = await SetupStreamAndChannelAsync(isClient, executor, writeStrategy, serverProtocol, clientProtocol, writeTasks);
|
||||
EmbeddedChannel ch = pair.Item1;
|
||||
IEmbeddedChannel ch = pair.Item1;
|
||||
SslStream driverStream = pair.Item2;
|
||||
|
||||
int randomSeed = Environment.TickCount;
|
||||
|
@ -206,7 +206,7 @@ namespace DotNetty.Handlers.Tests
|
|||
}
|
||||
}
|
||||
|
||||
static async Task<Tuple<EmbeddedChannel, SslStream>> SetupStreamAndChannelAsync(bool isClient, IEventExecutor executor, IWriteStrategy writeStrategy, SslProtocols serverProtocol, SslProtocols clientProtocol, List<Task> writeTasks)
|
||||
static async Task<Tuple<IEmbeddedChannel, SslStream>> SetupStreamAndChannelAsync(bool isClient, IEventLoop executor, IWriteStrategy writeStrategy, SslProtocols serverProtocol, SslProtocols clientProtocol, List<Task> writeTasks)
|
||||
{
|
||||
X509Certificate2 tlsCertificate = TestResourceHelper.GetTestCertificate();
|
||||
string targetHost = tlsCertificate.GetNameInfo(X509NameType.DnsName, false);
|
||||
|
@ -214,7 +214,12 @@ namespace DotNetty.Handlers.Tests
|
|||
new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true), new ClientTlsSettings(clientProtocol, false, new List<X509Certificate>(), targetHost)) :
|
||||
new TlsHandler(new ServerTlsSettings(tlsCertificate, false, false, serverProtocol));
|
||||
//var ch = new EmbeddedChannel(new LoggingHandler("BEFORE"), tlsHandler, new LoggingHandler("AFTER"));
|
||||
var ch = new EmbeddedChannel(tlsHandler);
|
||||
|
||||
#if NET5_0_OR_GREATER
|
||||
IEmbeddedChannel ch = new SingleThreadedEmbeddedChannel(executor, tlsHandler);
|
||||
#else
|
||||
IEmbeddedChannel ch = new EmbeddedChannel(tlsHandler);
|
||||
#endif
|
||||
|
||||
IByteBuffer readResultBuffer = Unpooled.Buffer(4 * 1024);
|
||||
Func<ArraySegment<byte>, Task<int>> readDataFunc = async output =>
|
||||
|
@ -228,21 +233,40 @@ namespace DotNetty.Handlers.Tests
|
|||
if (readResultBuffer.ReadableBytes < output.Count)
|
||||
{
|
||||
if (ch.Active)
|
||||
await ReadOutboundAsync(async () => ch.ReadOutbound<IByteBuffer>(), output.Count - readResultBuffer.ReadableBytes, readResultBuffer, TestTimeout, readResultBuffer.ReadableBytes != 0 ? 0 : 1);
|
||||
{
|
||||
await ReadOutboundAsync(
|
||||
async () => ch.ReadOutbound<IByteBuffer>(),
|
||||
output.Count - readResultBuffer.ReadableBytes,
|
||||
readResultBuffer,
|
||||
TestTimeout,
|
||||
readResultBuffer.ReadableBytes != 0 ? 0 : 1
|
||||
);
|
||||
}
|
||||
}
|
||||
int read = Math.Min(output.Count, readResultBuffer.ReadableBytes);
|
||||
readResultBuffer.ReadBytes(output.Array, output.Offset, read);
|
||||
return read;
|
||||
};
|
||||
var mediationStream = new MediationStream(readDataFunc, input =>
|
||||
{
|
||||
Task task = executor.SubmitAsync(() => writeStrategy.WriteToChannelAsync(ch, input)).Unwrap();
|
||||
writeTasks.Add(task);
|
||||
return task;
|
||||
}, () =>
|
||||
{
|
||||
ch.CloseAsync();
|
||||
});
|
||||
var mediationStream = new MediationStream(
|
||||
output =>
|
||||
{
|
||||
Task<int> task = executor.SubmitAsync(
|
||||
() => readDataFunc(output)
|
||||
).Unwrap();
|
||||
return task;
|
||||
},
|
||||
input =>
|
||||
{
|
||||
Task task = executor.SubmitAsync(
|
||||
() => writeStrategy.WriteToChannelAsync(ch, input)
|
||||
).Unwrap();
|
||||
writeTasks.Add(task);
|
||||
return task;
|
||||
},
|
||||
() =>
|
||||
{
|
||||
ch.CloseAsync();
|
||||
});
|
||||
|
||||
var driverStream = new SslStream(mediationStream, true, (_1, _2, _3, _4) => true);
|
||||
if (isClient)
|
||||
|
|
|
@ -2,10 +2,12 @@
|
|||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<AssemblyOriginatorKeyFile>../../DotNetty.snk</AssemblyOriginatorKeyFile>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<AssemblyOriginatorKeyFile>../../DotNetty.snk</AssemblyOriginatorKeyFile>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="..\..\shared\dotnetty.com.pfx" />
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<AssemblyOriginatorKeyFile>../../DotNetty.snk</AssemblyOriginatorKeyFile>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace DotNetty.Tests.End2End
|
|||
using DotNetty.Transport.Channels.Sockets;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
public class End2EndTests : TestBase
|
||||
{
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace DotNetty.Transport.Libuv.Tests
|
|||
using Xunit;
|
||||
|
||||
using static TestUtil;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
[Collection(LibuvTransport)]
|
||||
public sealed class BufReleaseTests : IDisposable
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace DotNetty.Transport.Libuv.Tests
|
|||
using Xunit;
|
||||
|
||||
using static TestUtil;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
[Collection(LibuvTransport)]
|
||||
public sealed class CompositeBufferGatheringWriteTests : IDisposable
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace DotNetty.Transport.Libuv.Tests
|
|||
using Xunit;
|
||||
|
||||
using static TestUtil;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
[Collection(LibuvTransport)]
|
||||
public sealed class DetectPeerCloseWithoutReadTests : IDisposable
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;net472;net5;net6</TargetFrameworks>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<AssemblyOriginatorKeyFile>../../DotNetty.snk</AssemblyOriginatorKeyFile>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<Configurations>Debug;Release;Package</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace DotNetty.Transport.Libuv.Tests
|
|||
using Xunit.Abstractions;
|
||||
|
||||
using static TestUtil;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
[Collection(LibuvTransport)]
|
||||
public sealed class EchoTests : IDisposable
|
||||
|
|
|
@ -11,6 +11,7 @@ namespace DotNetty.Transport.Libuv.Tests
|
|||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
using static TestUtil;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
public sealed class EventLoopTests : TestBase, IDisposable
|
||||
{
|
||||
|
|
|
@ -15,6 +15,7 @@ namespace DotNetty.Transport.Libuv.Tests
|
|||
using Xunit;
|
||||
|
||||
using static TestUtil;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
[Collection(LibuvTransport)]
|
||||
public sealed class ExceptionHandlingTests : IDisposable
|
||||
|
|
|
@ -15,6 +15,7 @@ namespace DotNetty.Transport.Libuv.Tests
|
|||
using Xunit;
|
||||
|
||||
using static TestUtil;
|
||||
using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource;
|
||||
|
||||
[Collection(LibuvTransport)]
|
||||
public sealed class ReadPendingTests : IDisposable
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче