From dae3c13b2eaee45569b2bbfc9db589368202ba6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=93=E3=81=AE=E4=B8=AD=E4=BA=8C=E7=97=85=E3=81=AB?= =?UTF-8?q?=E7=88=86=E7=84=94=E3=82=92=EF=BC=81?= Date: Wed, 3 Mar 2021 16:53:20 +0800 Subject: [PATCH] add RPC source module https://github.com/ExM/OncRpc --- Rpc.sln | 725 ++++++++++++++++++ Rpc/AssemblyInfo.vb | 25 + Rpc/BindingProtocols/ConnectorExtensions.vb | 78 ++ Rpc/BindingProtocols/Protocol.vb | 17 + Rpc/BindingProtocols/ProtocolFamily.vb | 102 +++ Rpc/BindingProtocols/ProtocolName.vb | 25 + .../TaskBuilders/BaseRpcBind.vb | 80 ++ .../TaskBuilders/BaseTaskBuilder.vb | 59 ++ .../TaskBuilders/PortMapper.vb | 92 +++ .../TaskBuilders/RpcBindV3.vb | 48 ++ .../TaskBuilders/RpcBindV4.vb | 83 ++ Rpc/BindingProtocols/TransportSemantics.vb | 25 + Rpc/BindingProtocols/call_args.vb | 33 + Rpc/BindingProtocols/call_result.vb | 21 + Rpc/BindingProtocols/mapping.vb | 40 + Rpc/BindingProtocols/netbuf.vb | 20 + Rpc/BindingProtocols/rpcb.vb | 38 + Rpc/BindingProtocols/rpcb_entry.vb | 36 + Rpc/BindingProtocols/rpcb_rmtcallargs.vb | 30 + Rpc/BindingProtocols/rpcb_rmtcallres.vb | 20 + Rpc/BindingProtocols/rpcb_stat.vb | 41 + Rpc/BindingProtocols/rpcb_stat_byvers.vb | 27 + Rpc/BindingProtocols/rpcbs_addr.vb | 35 + Rpc/BindingProtocols/rpcbs_rmtcall.vb | 45 ++ Rpc/Connectors/IRpcSession.vb | 12 + Rpc/Connectors/ITicket.vb | 12 + Rpc/Connectors/ITicketOwner.vb | 5 + Rpc/Connectors/TcpClientWrapper.vb | 260 +++++++ Rpc/Connectors/TcpSession.vb | 183 +++++ Rpc/Connectors/Ticket.vb | 74 ++ Rpc/Connectors/UdpClientWrapper.vb | 105 +++ Rpc/Connectors/UdpSession.vb | 167 ++++ Rpc/Exceptions/AuthenticateException.vb | 37 + Rpc/Exceptions/Exceptions.vb | 73 ++ Rpc/Exceptions/ReplyException.vb | 53 ++ Rpc/Exceptions/RpcException.vb | 32 + Rpc/IMsgReader.vb | 6 + Rpc/IRpcClient.vb | 28 + Rpc/MessageProtocol/accept_stat.vb | 38 + Rpc/MessageProtocol/accepted_reply.vb | 40 + Rpc/MessageProtocol/auth_flavor.vb | 33 + Rpc/MessageProtocol/auth_stat.vb | 89 +++ Rpc/MessageProtocol/body.vb | 25 + Rpc/MessageProtocol/call_body.vb | 45 ++ Rpc/MessageProtocol/mismatch_info.vb | 21 + Rpc/MessageProtocol/msg_type.vb | 17 + Rpc/MessageProtocol/opaque_auth.vb | 32 + Rpc/MessageProtocol/reject_stat.vb | 17 + Rpc/MessageProtocol/rejected_reply.vb | 27 + Rpc/MessageProtocol/reply_body.vb | 27 + Rpc/MessageProtocol/reply_stat.vb | 17 + Rpc/MessageProtocol/rpc_msg.vb | 20 + Rpc/Rpc.vbproj | 130 ++++ Rpc/RpcClient.vb | 163 ++++ Rpc/TcpStreaming/TcpReader.vb | 101 +++ Rpc/TcpStreaming/TcpWriter.vb | 104 +++ Rpc/Toolkit.vb | 120 +++ Rpc/UdpDatagrams/UdpReader.vb | 64 ++ Rpc/UdpDatagrams/UdpWriter.vb | 95 +++ 59 files changed, 4017 insertions(+) create mode 100644 Rpc.sln create mode 100644 Rpc/AssemblyInfo.vb create mode 100644 Rpc/BindingProtocols/ConnectorExtensions.vb create mode 100644 Rpc/BindingProtocols/Protocol.vb create mode 100644 Rpc/BindingProtocols/ProtocolFamily.vb create mode 100644 Rpc/BindingProtocols/ProtocolName.vb create mode 100644 Rpc/BindingProtocols/TaskBuilders/BaseRpcBind.vb create mode 100644 Rpc/BindingProtocols/TaskBuilders/BaseTaskBuilder.vb create mode 100644 Rpc/BindingProtocols/TaskBuilders/PortMapper.vb create mode 100644 Rpc/BindingProtocols/TaskBuilders/RpcBindV3.vb create mode 100644 Rpc/BindingProtocols/TaskBuilders/RpcBindV4.vb create mode 100644 Rpc/BindingProtocols/TransportSemantics.vb create mode 100644 Rpc/BindingProtocols/call_args.vb create mode 100644 Rpc/BindingProtocols/call_result.vb create mode 100644 Rpc/BindingProtocols/mapping.vb create mode 100644 Rpc/BindingProtocols/netbuf.vb create mode 100644 Rpc/BindingProtocols/rpcb.vb create mode 100644 Rpc/BindingProtocols/rpcb_entry.vb create mode 100644 Rpc/BindingProtocols/rpcb_rmtcallargs.vb create mode 100644 Rpc/BindingProtocols/rpcb_rmtcallres.vb create mode 100644 Rpc/BindingProtocols/rpcb_stat.vb create mode 100644 Rpc/BindingProtocols/rpcb_stat_byvers.vb create mode 100644 Rpc/BindingProtocols/rpcbs_addr.vb create mode 100644 Rpc/BindingProtocols/rpcbs_rmtcall.vb create mode 100644 Rpc/Connectors/IRpcSession.vb create mode 100644 Rpc/Connectors/ITicket.vb create mode 100644 Rpc/Connectors/ITicketOwner.vb create mode 100644 Rpc/Connectors/TcpClientWrapper.vb create mode 100644 Rpc/Connectors/TcpSession.vb create mode 100644 Rpc/Connectors/Ticket.vb create mode 100644 Rpc/Connectors/UdpClientWrapper.vb create mode 100644 Rpc/Connectors/UdpSession.vb create mode 100644 Rpc/Exceptions/AuthenticateException.vb create mode 100644 Rpc/Exceptions/Exceptions.vb create mode 100644 Rpc/Exceptions/ReplyException.vb create mode 100644 Rpc/Exceptions/RpcException.vb create mode 100644 Rpc/IMsgReader.vb create mode 100644 Rpc/IRpcClient.vb create mode 100644 Rpc/MessageProtocol/accept_stat.vb create mode 100644 Rpc/MessageProtocol/accepted_reply.vb create mode 100644 Rpc/MessageProtocol/auth_flavor.vb create mode 100644 Rpc/MessageProtocol/auth_stat.vb create mode 100644 Rpc/MessageProtocol/body.vb create mode 100644 Rpc/MessageProtocol/call_body.vb create mode 100644 Rpc/MessageProtocol/mismatch_info.vb create mode 100644 Rpc/MessageProtocol/msg_type.vb create mode 100644 Rpc/MessageProtocol/opaque_auth.vb create mode 100644 Rpc/MessageProtocol/reject_stat.vb create mode 100644 Rpc/MessageProtocol/rejected_reply.vb create mode 100644 Rpc/MessageProtocol/reply_body.vb create mode 100644 Rpc/MessageProtocol/reply_stat.vb create mode 100644 Rpc/MessageProtocol/rpc_msg.vb create mode 100644 Rpc/Rpc.vbproj create mode 100644 Rpc/RpcClient.vb create mode 100644 Rpc/TcpStreaming/TcpReader.vb create mode 100644 Rpc/TcpStreaming/TcpWriter.vb create mode 100644 Rpc/Toolkit.vb create mode 100644 Rpc/UdpDatagrams/UdpReader.vb create mode 100644 Rpc/UdpDatagrams/UdpWriter.vb diff --git a/Rpc.sln b/Rpc.sln new file mode 100644 index 0000000..f6fe99d --- /dev/null +++ b/Rpc.sln @@ -0,0 +1,725 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31019.194 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Rpc", "Rpc\Rpc.vbproj", "{8F215850-6439-0311-0352-B0720952E0CE}" +EndProject +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "47-dotnet_Microsoft.VisualBasic", "..\sciBASIC#\Microsoft.VisualBasic.Core\src\47-dotnet_Microsoft.VisualBasic.vbproj", "{FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}" +EndProject +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "BinaryData", "..\sciBASIC#\Data\BinaryData\BinaryData\BinaryData.vbproj", "{487D7C92-D05A-4908-BF81-E6BABA0BF592}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "framework", "framework", "{AAD1FC97-3157-4516-A6B4-2B19D673474E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + BioDeep_database|Any CPU = BioDeep_database|Any CPU + BioDeep_database|x64 = BioDeep_database|x64 + BioDeep_database|x86 = BioDeep_database|x86 + Biodeep_UNIX_x64|Any CPU = Biodeep_UNIX_x64|Any CPU + Biodeep_UNIX_x64|x64 = Biodeep_UNIX_x64|x64 + Biodeep_UNIX_x64|x86 = Biodeep_UNIX_x64|x86 + Biodeep|Any CPU = Biodeep|Any CPU + Biodeep|x64 = Biodeep|x64 + Biodeep|x86 = Biodeep|x86 + Biostack|Any CPU = Biostack|Any CPU + Biostack|x64 = Biostack|x64 + Biostack|x86 = Biostack|x86 + Biostack-Debug|Any CPU = Biostack-Debug|Any CPU + Biostack-Debug|x64 = Biostack-Debug|x64 + Biostack-Debug|x86 = Biostack-Debug|x86 + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + DEMO|Any CPU = DEMO|Any CPU + DEMO|x64 = DEMO|x64 + DEMO|x86 = DEMO|x86 + Docker|Any CPU = Docker|Any CPU + Docker|x64 = Docker|x64 + Docker|x86 = Docker|x86 + docs|Any CPU = docs|Any CPU + docs|x64 = docs|x64 + docs|x86 = docs|x86 + GCModeller(Release_X64)|Any CPU = GCModeller(Release_X64)|Any CPU + GCModeller(Release_X64)|x64 = GCModeller(Release_X64)|x64 + GCModeller(Release_X64)|x86 = GCModeller(Release_X64)|x86 + GCModeller(UNIX-Release_X64)|Any CPU = GCModeller(UNIX-Release_X64)|Any CPU + GCModeller(UNIX-Release_X64)|x64 = GCModeller(UNIX-Release_X64)|x64 + GCModeller(UNIX-Release_X64)|x86 = GCModeller(UNIX-Release_X64)|x86 + GTA5-game-test|Any CPU = GTA5-game-test|Any CPU + GTA5-game-test|x64 = GTA5-game-test|x64 + GTA5-game-test|x86 = GTA5-game-test|x86 + installer_x64|Any CPU = installer_x64|Any CPU + installer_x64|x64 = installer_x64|x64 + installer_x64|x86 = installer_x64|x86 + linux-profiler|Any CPU = linux-profiler|Any CPU + linux-profiler|x64 = linux-profiler|x64 + linux-profiler|x86 = linux-profiler|x86 + LipidSearch|Any CPU = LipidSearch|Any CPU + LipidSearch|x64 = LipidSearch|x64 + LipidSearch|x86 = LipidSearch|x86 + MetaCardio|Any CPU = MetaCardio|Any CPU + MetaCardio|x64 = MetaCardio|x64 + MetaCardio|x86 = MetaCardio|x86 + mysqli_X64_release|Any CPU = mysqli_X64_release|Any CPU + mysqli_X64_release|x64 = mysqli_X64_release|x64 + mysqli_X64_release|x86 = mysqli_X64_release|x86 + mzkit_UnixDocker|Any CPU = mzkit_UnixDocker|Any CPU + mzkit_UnixDocker|x64 = mzkit_UnixDocker|x64 + mzkit_UnixDocker|x86 = mzkit_UnixDocker|x86 + mzkit|Any CPU = mzkit|Any CPU + mzkit|x64 = mzkit|x64 + mzkit|x86 = mzkit|x86 + node-debug|Any CPU = node-debug|Any CPU + node-debug|x64 = node-debug|x64 + node-debug|x86 = node-debug|x86 + PlantMAT|Any CPU = PlantMAT|Any CPU + PlantMAT|x64 = PlantMAT|x64 + PlantMAT|x86 = PlantMAT|x86 + ProteoWizard.d|Any CPU = ProteoWizard.d|Any CPU + ProteoWizard.d|x64 = ProteoWizard.d|x64 + ProteoWizard.d|x86 = ProteoWizard.d|x86 + Publish|Any CPU = Publish|Any CPU + Publish|x64 = Publish|x64 + Publish|x86 = Publish|x86 + R-dotnet|Any CPU = R-dotnet|Any CPU + R-dotnet|x64 = R-dotnet|x64 + R-dotnet|x86 = R-dotnet|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + Rsharp_app_release|Any CPU = Rsharp_app_release|Any CPU + Rsharp_app_release|x64 = Rsharp_app_release|x64 + Rsharp_app_release|x86 = Rsharp_app_release|x86 + RsharpDev|Any CPU = RsharpDev|Any CPU + RsharpDev|x64 = RsharpDev|x64 + RsharpDev|x86 = RsharpDev|x86 + sciBASIC.NET-test-release|Any CPU = sciBASIC.NET-test-release|Any CPU + sciBASIC.NET-test-release|x64 = sciBASIC.NET-test-release|x64 + sciBASIC.NET-test-release|x86 = sciBASIC.NET-test-release|x86 + Surveillance-of-infectious-diseases|Any CPU = Surveillance-of-infectious-diseases|Any CPU + Surveillance-of-infectious-diseases|x64 = Surveillance-of-infectious-diseases|x64 + Surveillance-of-infectious-diseases|x86 = Surveillance-of-infectious-diseases|x86 + test|Any CPU = test|Any CPU + test|x64 = test|x64 + test|x86 = test|x86 + Voyager1|Any CPU = Voyager1|Any CPU + Voyager1|x64 = Voyager1|x64 + Voyager1|x86 = Voyager1|x86 + WebAssembly|Any CPU = WebAssembly|Any CPU + WebAssembly|x64 = WebAssembly|x64 + WebAssembly|x86 = WebAssembly|x86 + Yilia-Release_x64|Any CPU = Yilia-Release_x64|Any CPU + Yilia-Release_x64|x64 = Yilia-Release_x64|x64 + Yilia-Release_x64|x86 = Yilia-Release_x64|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8F215850-6439-0311-0352-B0720952E0CE}.BioDeep_database|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.BioDeep_database|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.BioDeep_database|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.BioDeep_database|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.BioDeep_database|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.BioDeep_database|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Biodeep_UNIX_x64|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Biodeep_UNIX_x64|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Biodeep_UNIX_x64|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Biodeep_UNIX_x64|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Biodeep_UNIX_x64|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Biodeep_UNIX_x64|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Biodeep|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Biodeep|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Biodeep|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Biodeep|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Biodeep|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Biodeep|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Biostack|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Biostack|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Biostack|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Biostack|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Biostack|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Biostack|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Biostack-Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Biostack-Debug|Any CPU.Build.0 = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Biostack-Debug|x64.ActiveCfg = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Biostack-Debug|x64.Build.0 = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Biostack-Debug|x86.ActiveCfg = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Biostack-Debug|x86.Build.0 = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Debug|x64.ActiveCfg = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Debug|x64.Build.0 = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Debug|x86.ActiveCfg = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Debug|x86.Build.0 = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.DEMO|Any CPU.ActiveCfg = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.DEMO|Any CPU.Build.0 = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.DEMO|x64.ActiveCfg = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.DEMO|x64.Build.0 = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.DEMO|x86.ActiveCfg = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.DEMO|x86.Build.0 = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Docker|Any CPU.ActiveCfg = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Docker|Any CPU.Build.0 = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Docker|x64.ActiveCfg = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Docker|x64.Build.0 = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Docker|x86.ActiveCfg = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Docker|x86.Build.0 = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.docs|Any CPU.ActiveCfg = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.docs|Any CPU.Build.0 = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.docs|x64.ActiveCfg = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.docs|x64.Build.0 = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.docs|x86.ActiveCfg = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.docs|x86.Build.0 = Debug|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.GCModeller(Release_X64)|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.GCModeller(Release_X64)|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.GCModeller(Release_X64)|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.GCModeller(Release_X64)|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.GCModeller(Release_X64)|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.GCModeller(Release_X64)|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.GCModeller(UNIX-Release_X64)|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.GCModeller(UNIX-Release_X64)|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.GCModeller(UNIX-Release_X64)|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.GCModeller(UNIX-Release_X64)|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.GCModeller(UNIX-Release_X64)|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.GCModeller(UNIX-Release_X64)|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.GTA5-game-test|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.GTA5-game-test|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.GTA5-game-test|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.GTA5-game-test|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.GTA5-game-test|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.GTA5-game-test|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.installer_x64|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.installer_x64|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.installer_x64|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.installer_x64|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.installer_x64|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.installer_x64|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.linux-profiler|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.linux-profiler|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.linux-profiler|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.linux-profiler|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.linux-profiler|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.linux-profiler|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.LipidSearch|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.LipidSearch|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.LipidSearch|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.LipidSearch|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.LipidSearch|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.LipidSearch|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.MetaCardio|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.MetaCardio|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.MetaCardio|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.MetaCardio|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.MetaCardio|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.MetaCardio|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.mysqli_X64_release|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.mysqli_X64_release|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.mysqli_X64_release|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.mysqli_X64_release|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.mysqli_X64_release|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.mysqli_X64_release|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.mzkit_UnixDocker|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.mzkit_UnixDocker|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.mzkit_UnixDocker|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.mzkit_UnixDocker|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.mzkit_UnixDocker|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.mzkit_UnixDocker|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.mzkit|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.mzkit|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.mzkit|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.mzkit|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.mzkit|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.mzkit|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.node-debug|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.node-debug|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.node-debug|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.node-debug|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.node-debug|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.node-debug|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.PlantMAT|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.PlantMAT|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.PlantMAT|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.PlantMAT|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.PlantMAT|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.PlantMAT|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.ProteoWizard.d|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.ProteoWizard.d|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.ProteoWizard.d|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.ProteoWizard.d|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.ProteoWizard.d|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.ProteoWizard.d|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Publish|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Publish|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Publish|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Publish|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Publish|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Publish|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.R-dotnet|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.R-dotnet|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.R-dotnet|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.R-dotnet|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.R-dotnet|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.R-dotnet|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Release|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Release|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Release|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Release|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Release|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Rsharp_app_release|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Rsharp_app_release|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Rsharp_app_release|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Rsharp_app_release|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Rsharp_app_release|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Rsharp_app_release|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.RsharpDev|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.RsharpDev|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.RsharpDev|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.RsharpDev|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.RsharpDev|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.RsharpDev|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.sciBASIC.NET-test-release|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.sciBASIC.NET-test-release|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.sciBASIC.NET-test-release|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.sciBASIC.NET-test-release|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.sciBASIC.NET-test-release|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.sciBASIC.NET-test-release|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Surveillance-of-infectious-diseases|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Surveillance-of-infectious-diseases|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Surveillance-of-infectious-diseases|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Surveillance-of-infectious-diseases|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Surveillance-of-infectious-diseases|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Surveillance-of-infectious-diseases|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.test|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.test|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.test|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.test|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.test|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.test|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Voyager1|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Voyager1|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Voyager1|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Voyager1|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Voyager1|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Voyager1|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.WebAssembly|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.WebAssembly|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.WebAssembly|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.WebAssembly|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.WebAssembly|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.WebAssembly|x86.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Yilia-Release_x64|Any CPU.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Yilia-Release_x64|Any CPU.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Yilia-Release_x64|x64.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Yilia-Release_x64|x64.Build.0 = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Yilia-Release_x64|x86.ActiveCfg = Release|Any CPU + {8F215850-6439-0311-0352-B0720952E0CE}.Yilia-Release_x64|x86.Build.0 = Release|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.BioDeep_database|Any CPU.ActiveCfg = BioDeep_database|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.BioDeep_database|Any CPU.Build.0 = BioDeep_database|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.BioDeep_database|x64.ActiveCfg = BioDeep_database|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.BioDeep_database|x64.Build.0 = BioDeep_database|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.BioDeep_database|x86.ActiveCfg = BioDeep_database|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.BioDeep_database|x86.Build.0 = BioDeep_database|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Biodeep_UNIX_x64|Any CPU.ActiveCfg = Biodeep_UNIX_x64|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Biodeep_UNIX_x64|Any CPU.Build.0 = Biodeep_UNIX_x64|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Biodeep_UNIX_x64|x64.ActiveCfg = Biodeep_UNIX_x64|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Biodeep_UNIX_x64|x64.Build.0 = Biodeep_UNIX_x64|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Biodeep_UNIX_x64|x86.ActiveCfg = Biodeep_UNIX_x64|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Biodeep_UNIX_x64|x86.Build.0 = Biodeep_UNIX_x64|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Biodeep|Any CPU.ActiveCfg = Biodeep|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Biodeep|Any CPU.Build.0 = Biodeep|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Biodeep|x64.ActiveCfg = Biodeep|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Biodeep|x64.Build.0 = Biodeep|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Biodeep|x86.ActiveCfg = Biodeep|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Biodeep|x86.Build.0 = Biodeep|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Biostack|Any CPU.ActiveCfg = Biostack|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Biostack|Any CPU.Build.0 = Biostack|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Biostack|x64.ActiveCfg = Biostack|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Biostack|x64.Build.0 = Biostack|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Biostack|x86.ActiveCfg = Biostack|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Biostack|x86.Build.0 = Biostack|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Biostack-Debug|Any CPU.ActiveCfg = Biostack-Debug|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Biostack-Debug|Any CPU.Build.0 = Biostack-Debug|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Biostack-Debug|x64.ActiveCfg = Biostack-Debug|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Biostack-Debug|x64.Build.0 = Biostack-Debug|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Biostack-Debug|x86.ActiveCfg = Biostack-Debug|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Biostack-Debug|x86.Build.0 = Biostack-Debug|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Debug|x64.ActiveCfg = Debug|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Debug|x64.Build.0 = Debug|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Debug|x86.ActiveCfg = Debug|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Debug|x86.Build.0 = Debug|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.DEMO|Any CPU.ActiveCfg = DEMO|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.DEMO|Any CPU.Build.0 = DEMO|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.DEMO|x64.ActiveCfg = DEMO|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.DEMO|x64.Build.0 = DEMO|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.DEMO|x86.ActiveCfg = DEMO|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.DEMO|x86.Build.0 = DEMO|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Docker|Any CPU.ActiveCfg = Docker|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Docker|Any CPU.Build.0 = Docker|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Docker|x64.ActiveCfg = Docker|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Docker|x64.Build.0 = Docker|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Docker|x86.ActiveCfg = Docker|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Docker|x86.Build.0 = Docker|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.docs|Any CPU.ActiveCfg = docs|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.docs|Any CPU.Build.0 = docs|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.docs|x64.ActiveCfg = docs|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.docs|x64.Build.0 = docs|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.docs|x86.ActiveCfg = docs|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.docs|x86.Build.0 = docs|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.GCModeller(Release_X64)|Any CPU.ActiveCfg = GCModeller(Release_X64)|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.GCModeller(Release_X64)|Any CPU.Build.0 = GCModeller(Release_X64)|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.GCModeller(Release_X64)|x64.ActiveCfg = GCModeller(Release_X64)|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.GCModeller(Release_X64)|x64.Build.0 = GCModeller(Release_X64)|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.GCModeller(Release_X64)|x86.ActiveCfg = GCModeller(Release_X64)|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.GCModeller(Release_X64)|x86.Build.0 = GCModeller(Release_X64)|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.GCModeller(UNIX-Release_X64)|Any CPU.ActiveCfg = GCModeller(UNIX-Release_X64)|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.GCModeller(UNIX-Release_X64)|Any CPU.Build.0 = GCModeller(UNIX-Release_X64)|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.GCModeller(UNIX-Release_X64)|x64.ActiveCfg = GCModeller(UNIX-Release_X64)|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.GCModeller(UNIX-Release_X64)|x64.Build.0 = GCModeller(UNIX-Release_X64)|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.GCModeller(UNIX-Release_X64)|x86.ActiveCfg = GCModeller(UNIX-Release_X64)|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.GCModeller(UNIX-Release_X64)|x86.Build.0 = GCModeller(UNIX-Release_X64)|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.GTA5-game-test|Any CPU.ActiveCfg = GTA5-game-test|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.GTA5-game-test|Any CPU.Build.0 = GTA5-game-test|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.GTA5-game-test|x64.ActiveCfg = GTA5-game-test|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.GTA5-game-test|x64.Build.0 = GTA5-game-test|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.GTA5-game-test|x86.ActiveCfg = GTA5-game-test|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.GTA5-game-test|x86.Build.0 = GTA5-game-test|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.installer_x64|Any CPU.ActiveCfg = installer_x64|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.installer_x64|Any CPU.Build.0 = installer_x64|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.installer_x64|x64.ActiveCfg = installer_x64|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.installer_x64|x64.Build.0 = installer_x64|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.installer_x64|x86.ActiveCfg = installer_x64|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.installer_x64|x86.Build.0 = installer_x64|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.linux-profiler|Any CPU.ActiveCfg = linux-profiler|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.linux-profiler|Any CPU.Build.0 = linux-profiler|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.linux-profiler|x64.ActiveCfg = linux-profiler|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.linux-profiler|x64.Build.0 = linux-profiler|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.linux-profiler|x86.ActiveCfg = linux-profiler|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.linux-profiler|x86.Build.0 = linux-profiler|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.LipidSearch|Any CPU.ActiveCfg = LipidSearch|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.LipidSearch|Any CPU.Build.0 = LipidSearch|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.LipidSearch|x64.ActiveCfg = LipidSearch|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.LipidSearch|x64.Build.0 = LipidSearch|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.LipidSearch|x86.ActiveCfg = LipidSearch|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.LipidSearch|x86.Build.0 = LipidSearch|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.MetaCardio|Any CPU.ActiveCfg = MetaCardio|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.MetaCardio|Any CPU.Build.0 = MetaCardio|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.MetaCardio|x64.ActiveCfg = MetaCardio|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.MetaCardio|x64.Build.0 = MetaCardio|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.MetaCardio|x86.ActiveCfg = MetaCardio|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.MetaCardio|x86.Build.0 = MetaCardio|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.mysqli_X64_release|Any CPU.ActiveCfg = mysqli_X64_release|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.mysqli_X64_release|Any CPU.Build.0 = mysqli_X64_release|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.mysqli_X64_release|x64.ActiveCfg = mysqli_X64_release|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.mysqli_X64_release|x64.Build.0 = mysqli_X64_release|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.mysqli_X64_release|x86.ActiveCfg = mysqli_X64_release|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.mysqli_X64_release|x86.Build.0 = mysqli_X64_release|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.mzkit_UnixDocker|Any CPU.ActiveCfg = mzkit_UnixDocker|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.mzkit_UnixDocker|Any CPU.Build.0 = mzkit_UnixDocker|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.mzkit_UnixDocker|x64.ActiveCfg = mzkit_UnixDocker|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.mzkit_UnixDocker|x64.Build.0 = mzkit_UnixDocker|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.mzkit_UnixDocker|x86.ActiveCfg = mzkit_UnixDocker|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.mzkit_UnixDocker|x86.Build.0 = mzkit_UnixDocker|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.mzkit|Any CPU.ActiveCfg = mzkit|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.mzkit|Any CPU.Build.0 = mzkit|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.mzkit|x64.ActiveCfg = mzkit|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.mzkit|x64.Build.0 = mzkit|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.mzkit|x86.ActiveCfg = mzkit|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.mzkit|x86.Build.0 = mzkit|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.node-debug|Any CPU.ActiveCfg = node-debug|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.node-debug|Any CPU.Build.0 = node-debug|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.node-debug|x64.ActiveCfg = node-debug|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.node-debug|x64.Build.0 = node-debug|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.node-debug|x86.ActiveCfg = node-debug|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.node-debug|x86.Build.0 = node-debug|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.PlantMAT|Any CPU.ActiveCfg = PlantMAT|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.PlantMAT|Any CPU.Build.0 = PlantMAT|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.PlantMAT|x64.ActiveCfg = PlantMAT|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.PlantMAT|x64.Build.0 = PlantMAT|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.PlantMAT|x86.ActiveCfg = PlantMAT|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.PlantMAT|x86.Build.0 = PlantMAT|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.ProteoWizard.d|Any CPU.ActiveCfg = ProteoWizard.d|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.ProteoWizard.d|Any CPU.Build.0 = ProteoWizard.d|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.ProteoWizard.d|x64.ActiveCfg = ProteoWizard.d|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.ProteoWizard.d|x64.Build.0 = ProteoWizard.d|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.ProteoWizard.d|x86.ActiveCfg = ProteoWizard.d|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.ProteoWizard.d|x86.Build.0 = ProteoWizard.d|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Publish|Any CPU.ActiveCfg = Publish|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Publish|Any CPU.Build.0 = Publish|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Publish|x64.ActiveCfg = Publish|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Publish|x64.Build.0 = Publish|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Publish|x86.ActiveCfg = Publish|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Publish|x86.Build.0 = Publish|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.R-dotnet|Any CPU.ActiveCfg = R-dotnet|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.R-dotnet|Any CPU.Build.0 = R-dotnet|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.R-dotnet|x64.ActiveCfg = R-dotnet|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.R-dotnet|x64.Build.0 = R-dotnet|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.R-dotnet|x86.ActiveCfg = R-dotnet|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.R-dotnet|x86.Build.0 = R-dotnet|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Release|Any CPU.Build.0 = Release|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Release|x64.ActiveCfg = Release|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Release|x64.Build.0 = Release|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Release|x86.ActiveCfg = Release|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Release|x86.Build.0 = Release|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Rsharp_app_release|Any CPU.ActiveCfg = Rsharp_app_release|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Rsharp_app_release|Any CPU.Build.0 = Rsharp_app_release|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Rsharp_app_release|x64.ActiveCfg = Rsharp_app_release|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Rsharp_app_release|x64.Build.0 = Rsharp_app_release|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Rsharp_app_release|x86.ActiveCfg = Rsharp_app_release|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Rsharp_app_release|x86.Build.0 = Rsharp_app_release|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.RsharpDev|Any CPU.ActiveCfg = RsharpDev|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.RsharpDev|Any CPU.Build.0 = RsharpDev|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.RsharpDev|x64.ActiveCfg = RsharpDev|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.RsharpDev|x64.Build.0 = RsharpDev|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.RsharpDev|x86.ActiveCfg = RsharpDev|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.RsharpDev|x86.Build.0 = RsharpDev|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.sciBASIC.NET-test-release|Any CPU.ActiveCfg = sciBASIC.NET-test-release|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.sciBASIC.NET-test-release|Any CPU.Build.0 = sciBASIC.NET-test-release|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.sciBASIC.NET-test-release|x64.ActiveCfg = sciBASIC.NET-test-release|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.sciBASIC.NET-test-release|x64.Build.0 = sciBASIC.NET-test-release|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.sciBASIC.NET-test-release|x86.ActiveCfg = sciBASIC.NET-test-release|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.sciBASIC.NET-test-release|x86.Build.0 = sciBASIC.NET-test-release|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Surveillance-of-infectious-diseases|Any CPU.ActiveCfg = Surveillance-of-infectious-diseases|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Surveillance-of-infectious-diseases|Any CPU.Build.0 = Surveillance-of-infectious-diseases|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Surveillance-of-infectious-diseases|x64.ActiveCfg = Surveillance-of-infectious-diseases|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Surveillance-of-infectious-diseases|x64.Build.0 = Surveillance-of-infectious-diseases|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Surveillance-of-infectious-diseases|x86.ActiveCfg = Surveillance-of-infectious-diseases|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Surveillance-of-infectious-diseases|x86.Build.0 = Surveillance-of-infectious-diseases|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.test|Any CPU.ActiveCfg = test|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.test|Any CPU.Build.0 = test|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.test|x64.ActiveCfg = test|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.test|x64.Build.0 = test|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.test|x86.ActiveCfg = test|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.test|x86.Build.0 = test|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Voyager1|Any CPU.ActiveCfg = Voyager1|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Voyager1|Any CPU.Build.0 = Voyager1|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Voyager1|x64.ActiveCfg = Voyager1|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Voyager1|x64.Build.0 = Voyager1|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Voyager1|x86.ActiveCfg = Voyager1|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Voyager1|x86.Build.0 = Voyager1|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.WebAssembly|Any CPU.ActiveCfg = WebAssembly|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.WebAssembly|Any CPU.Build.0 = WebAssembly|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.WebAssembly|x64.ActiveCfg = WebAssembly|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.WebAssembly|x64.Build.0 = WebAssembly|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.WebAssembly|x86.ActiveCfg = WebAssembly|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.WebAssembly|x86.Build.0 = WebAssembly|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Yilia-Release_x64|Any CPU.ActiveCfg = Yilia-Release_x64|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Yilia-Release_x64|Any CPU.Build.0 = Yilia-Release_x64|Any CPU + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Yilia-Release_x64|x64.ActiveCfg = Yilia-Release_x64|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Yilia-Release_x64|x64.Build.0 = Yilia-Release_x64|x64 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Yilia-Release_x64|x86.ActiveCfg = Yilia-Release_x64|x86 + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Yilia-Release_x64|x86.Build.0 = Yilia-Release_x64|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.BioDeep_database|Any CPU.ActiveCfg = BioDeep_database|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.BioDeep_database|Any CPU.Build.0 = BioDeep_database|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.BioDeep_database|x64.ActiveCfg = BioDeep_database|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.BioDeep_database|x64.Build.0 = BioDeep_database|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.BioDeep_database|x86.ActiveCfg = BioDeep_database|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.BioDeep_database|x86.Build.0 = BioDeep_database|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Biodeep_UNIX_x64|Any CPU.ActiveCfg = Biodeep_UNIX_x64|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Biodeep_UNIX_x64|Any CPU.Build.0 = Biodeep_UNIX_x64|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Biodeep_UNIX_x64|x64.ActiveCfg = Biodeep_UNIX_x64|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Biodeep_UNIX_x64|x64.Build.0 = Biodeep_UNIX_x64|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Biodeep_UNIX_x64|x86.ActiveCfg = Biodeep_UNIX_x64|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Biodeep_UNIX_x64|x86.Build.0 = Biodeep_UNIX_x64|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Biodeep|Any CPU.ActiveCfg = Biodeep|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Biodeep|Any CPU.Build.0 = Biodeep|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Biodeep|x64.ActiveCfg = Biodeep|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Biodeep|x64.Build.0 = Biodeep|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Biodeep|x86.ActiveCfg = Biodeep|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Biodeep|x86.Build.0 = Biodeep|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Biostack|Any CPU.ActiveCfg = Biostack|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Biostack|Any CPU.Build.0 = Biostack|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Biostack|x64.ActiveCfg = Biostack|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Biostack|x64.Build.0 = Biostack|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Biostack|x86.ActiveCfg = Biostack|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Biostack|x86.Build.0 = Biostack|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Biostack-Debug|Any CPU.ActiveCfg = Biostack-Debug|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Biostack-Debug|Any CPU.Build.0 = Biostack-Debug|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Biostack-Debug|x64.ActiveCfg = Biostack-Debug|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Biostack-Debug|x64.Build.0 = Biostack-Debug|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Biostack-Debug|x86.ActiveCfg = Biostack-Debug|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Biostack-Debug|x86.Build.0 = Biostack-Debug|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Debug|Any CPU.Build.0 = Debug|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Debug|x64.ActiveCfg = Debug|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Debug|x64.Build.0 = Debug|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Debug|x86.ActiveCfg = Debug|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Debug|x86.Build.0 = Debug|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.DEMO|Any CPU.ActiveCfg = DEMO|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.DEMO|Any CPU.Build.0 = DEMO|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.DEMO|x64.ActiveCfg = DEMO|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.DEMO|x64.Build.0 = DEMO|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.DEMO|x86.ActiveCfg = DEMO|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.DEMO|x86.Build.0 = DEMO|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Docker|Any CPU.ActiveCfg = mzkit_UnixDocker|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Docker|Any CPU.Build.0 = mzkit_UnixDocker|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Docker|x64.ActiveCfg = mzkit_UnixDocker|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Docker|x64.Build.0 = mzkit_UnixDocker|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Docker|x86.ActiveCfg = mzkit_UnixDocker|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Docker|x86.Build.0 = mzkit_UnixDocker|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.docs|Any CPU.ActiveCfg = docs|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.docs|Any CPU.Build.0 = docs|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.docs|x64.ActiveCfg = docs|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.docs|x64.Build.0 = docs|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.docs|x86.ActiveCfg = docs|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.docs|x86.Build.0 = docs|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.GCModeller(Release_X64)|Any CPU.ActiveCfg = GCModeller(Release_X64)|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.GCModeller(Release_X64)|Any CPU.Build.0 = GCModeller(Release_X64)|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.GCModeller(Release_X64)|x64.ActiveCfg = GCModeller(Release_X64)|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.GCModeller(Release_X64)|x64.Build.0 = GCModeller(Release_X64)|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.GCModeller(Release_X64)|x86.ActiveCfg = GCModeller(Release_X64)|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.GCModeller(Release_X64)|x86.Build.0 = GCModeller(Release_X64)|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.GCModeller(UNIX-Release_X64)|Any CPU.ActiveCfg = GCModeller(UNIX-Release_X64)|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.GCModeller(UNIX-Release_X64)|Any CPU.Build.0 = GCModeller(UNIX-Release_X64)|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.GCModeller(UNIX-Release_X64)|x64.ActiveCfg = GCModeller(UNIX-Release_X64)|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.GCModeller(UNIX-Release_X64)|x64.Build.0 = GCModeller(UNIX-Release_X64)|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.GCModeller(UNIX-Release_X64)|x86.ActiveCfg = GCModeller(UNIX-Release_X64)|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.GCModeller(UNIX-Release_X64)|x86.Build.0 = GCModeller(UNIX-Release_X64)|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.GTA5-game-test|Any CPU.ActiveCfg = GCModeller(UNIX-Release_X64)|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.GTA5-game-test|Any CPU.Build.0 = GCModeller(UNIX-Release_X64)|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.GTA5-game-test|x64.ActiveCfg = GCModeller(UNIX-Release_X64)|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.GTA5-game-test|x64.Build.0 = GCModeller(UNIX-Release_X64)|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.GTA5-game-test|x86.ActiveCfg = GCModeller(UNIX-Release_X64)|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.GTA5-game-test|x86.Build.0 = GCModeller(UNIX-Release_X64)|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.installer_x64|Any CPU.ActiveCfg = installer_x64|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.installer_x64|Any CPU.Build.0 = installer_x64|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.installer_x64|x64.ActiveCfg = installer_x64|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.installer_x64|x64.Build.0 = installer_x64|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.installer_x64|x86.ActiveCfg = installer_x64|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.installer_x64|x86.Build.0 = installer_x64|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.linux-profiler|Any CPU.ActiveCfg = LipidSearch|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.linux-profiler|Any CPU.Build.0 = LipidSearch|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.linux-profiler|x64.ActiveCfg = LipidSearch|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.linux-profiler|x64.Build.0 = LipidSearch|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.linux-profiler|x86.ActiveCfg = LipidSearch|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.linux-profiler|x86.Build.0 = LipidSearch|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.LipidSearch|Any CPU.ActiveCfg = LipidSearch|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.LipidSearch|Any CPU.Build.0 = LipidSearch|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.LipidSearch|x64.ActiveCfg = LipidSearch|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.LipidSearch|x64.Build.0 = LipidSearch|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.LipidSearch|x86.ActiveCfg = LipidSearch|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.LipidSearch|x86.Build.0 = LipidSearch|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.MetaCardio|Any CPU.ActiveCfg = MetaCardio|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.MetaCardio|Any CPU.Build.0 = MetaCardio|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.MetaCardio|x64.ActiveCfg = MetaCardio|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.MetaCardio|x64.Build.0 = MetaCardio|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.MetaCardio|x86.ActiveCfg = MetaCardio|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.MetaCardio|x86.Build.0 = MetaCardio|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.mysqli_X64_release|Any CPU.ActiveCfg = mzkit|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.mysqli_X64_release|Any CPU.Build.0 = mzkit|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.mysqli_X64_release|x64.ActiveCfg = mzkit|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.mysqli_X64_release|x64.Build.0 = mzkit|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.mysqli_X64_release|x86.ActiveCfg = mzkit|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.mysqli_X64_release|x86.Build.0 = mzkit|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.mzkit_UnixDocker|Any CPU.ActiveCfg = mzkit_UnixDocker|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.mzkit_UnixDocker|Any CPU.Build.0 = mzkit_UnixDocker|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.mzkit_UnixDocker|x64.ActiveCfg = mzkit_UnixDocker|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.mzkit_UnixDocker|x64.Build.0 = mzkit_UnixDocker|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.mzkit_UnixDocker|x86.ActiveCfg = mzkit_UnixDocker|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.mzkit_UnixDocker|x86.Build.0 = mzkit_UnixDocker|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.mzkit|Any CPU.ActiveCfg = mzkit|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.mzkit|Any CPU.Build.0 = mzkit|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.mzkit|x64.ActiveCfg = mzkit|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.mzkit|x64.Build.0 = mzkit|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.mzkit|x86.ActiveCfg = mzkit|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.mzkit|x86.Build.0 = mzkit|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.node-debug|Any CPU.ActiveCfg = node-debug|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.node-debug|Any CPU.Build.0 = node-debug|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.node-debug|x64.ActiveCfg = node-debug|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.node-debug|x64.Build.0 = node-debug|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.node-debug|x86.ActiveCfg = node-debug|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.node-debug|x86.Build.0 = node-debug|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.PlantMAT|Any CPU.ActiveCfg = Publish|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.PlantMAT|Any CPU.Build.0 = Publish|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.PlantMAT|x64.ActiveCfg = Publish|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.PlantMAT|x64.Build.0 = Publish|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.PlantMAT|x86.ActiveCfg = Publish|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.PlantMAT|x86.Build.0 = Publish|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.ProteoWizard.d|Any CPU.ActiveCfg = Publish|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.ProteoWizard.d|Any CPU.Build.0 = Publish|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.ProteoWizard.d|x64.ActiveCfg = Publish|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.ProteoWizard.d|x64.Build.0 = Publish|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.ProteoWizard.d|x86.ActiveCfg = Publish|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.ProteoWizard.d|x86.Build.0 = Publish|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Publish|Any CPU.ActiveCfg = Publish|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Publish|Any CPU.Build.0 = Publish|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Publish|x64.ActiveCfg = Publish|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Publish|x64.Build.0 = Publish|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Publish|x86.ActiveCfg = Publish|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Publish|x86.Build.0 = Publish|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.R-dotnet|Any CPU.ActiveCfg = Release|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.R-dotnet|Any CPU.Build.0 = Release|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.R-dotnet|x64.ActiveCfg = Release|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.R-dotnet|x64.Build.0 = Release|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.R-dotnet|x86.ActiveCfg = Release|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.R-dotnet|x86.Build.0 = Release|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Release|Any CPU.ActiveCfg = Release|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Release|Any CPU.Build.0 = Release|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Release|x64.ActiveCfg = Release|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Release|x64.Build.0 = Release|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Release|x86.ActiveCfg = Release|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Release|x86.Build.0 = Release|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Rsharp_app_release|Any CPU.ActiveCfg = Rsharp_app_release|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Rsharp_app_release|Any CPU.Build.0 = Rsharp_app_release|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Rsharp_app_release|x64.ActiveCfg = Rsharp_app_release|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Rsharp_app_release|x64.Build.0 = Rsharp_app_release|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Rsharp_app_release|x86.ActiveCfg = Rsharp_app_release|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Rsharp_app_release|x86.Build.0 = Rsharp_app_release|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.RsharpDev|Any CPU.ActiveCfg = Rsharp_app_release|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.RsharpDev|Any CPU.Build.0 = Rsharp_app_release|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.RsharpDev|x64.ActiveCfg = Rsharp_app_release|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.RsharpDev|x64.Build.0 = Rsharp_app_release|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.RsharpDev|x86.ActiveCfg = Rsharp_app_release|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.RsharpDev|x86.Build.0 = Rsharp_app_release|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.sciBASIC.NET-test-release|Any CPU.ActiveCfg = Surveillance-of-infectious-diseases|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.sciBASIC.NET-test-release|Any CPU.Build.0 = Surveillance-of-infectious-diseases|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.sciBASIC.NET-test-release|x64.ActiveCfg = Surveillance-of-infectious-diseases|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.sciBASIC.NET-test-release|x64.Build.0 = Surveillance-of-infectious-diseases|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.sciBASIC.NET-test-release|x86.ActiveCfg = Surveillance-of-infectious-diseases|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.sciBASIC.NET-test-release|x86.Build.0 = Surveillance-of-infectious-diseases|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Surveillance-of-infectious-diseases|Any CPU.ActiveCfg = Surveillance-of-infectious-diseases|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Surveillance-of-infectious-diseases|Any CPU.Build.0 = Surveillance-of-infectious-diseases|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Surveillance-of-infectious-diseases|x64.ActiveCfg = Surveillance-of-infectious-diseases|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Surveillance-of-infectious-diseases|x64.Build.0 = Surveillance-of-infectious-diseases|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Surveillance-of-infectious-diseases|x86.ActiveCfg = Surveillance-of-infectious-diseases|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Surveillance-of-infectious-diseases|x86.Build.0 = Surveillance-of-infectious-diseases|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.test|Any CPU.ActiveCfg = Debug|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.test|Any CPU.Build.0 = Debug|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.test|x64.ActiveCfg = Debug|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.test|x64.Build.0 = Debug|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.test|x86.ActiveCfg = Debug|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.test|x86.Build.0 = Debug|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Voyager1|Any CPU.ActiveCfg = Voyager1|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Voyager1|Any CPU.Build.0 = Voyager1|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Voyager1|x64.ActiveCfg = Voyager1|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Voyager1|x64.Build.0 = Voyager1|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Voyager1|x86.ActiveCfg = Voyager1|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Voyager1|x86.Build.0 = Voyager1|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.WebAssembly|Any CPU.ActiveCfg = Debug|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.WebAssembly|Any CPU.Build.0 = Debug|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.WebAssembly|x64.ActiveCfg = Debug|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.WebAssembly|x64.Build.0 = Debug|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.WebAssembly|x86.ActiveCfg = Debug|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.WebAssembly|x86.Build.0 = Debug|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Yilia-Release_x64|Any CPU.ActiveCfg = Release|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Yilia-Release_x64|Any CPU.Build.0 = Release|Any CPU + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Yilia-Release_x64|x64.ActiveCfg = Release|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Yilia-Release_x64|x64.Build.0 = Release|x64 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Yilia-Release_x64|x86.ActiveCfg = Release|x86 + {487D7C92-D05A-4908-BF81-E6BABA0BF592}.Yilia-Release_x64|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99} = {AAD1FC97-3157-4516-A6B4-2B19D673474E} + {487D7C92-D05A-4908-BF81-E6BABA0BF592} = {AAD1FC97-3157-4516-A6B4-2B19D673474E} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D64B5E9D-E850-4ABE-8FE8-26C90168513D} + EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + StartupItem = Rpc\Rpc.vbproj + EndGlobalSection +EndGlobal diff --git a/Rpc/AssemblyInfo.vb b/Rpc/AssemblyInfo.vb new file mode 100644 index 0000000..1bb9232 --- /dev/null +++ b/Rpc/AssemblyInfo.vb @@ -0,0 +1,25 @@ +Imports System.Reflection + +' Information about this assembly is defined by the following attributes. +' Change them to the values specific to your project. + + + + + + + + + + +' The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +' The form "{Major}.{Minor}.*" will automatically update the build and revision, +' and "{Major}.{Minor}.{Build}.*" will update just the revision. + + +' The following attributes are used to specify the signing key for the assembly, +' if desired. See the Mono documentation for more information about signing. + +'[assembly: AssemblyDelaySign(false)] +'[assembly: AssemblyKeyFile("")] + diff --git a/Rpc/BindingProtocols/ConnectorExtensions.vb b/Rpc/BindingProtocols/ConnectorExtensions.vb new file mode 100644 index 0000000..b0f9c70 --- /dev/null +++ b/Rpc/BindingProtocols/ConnectorExtensions.vb @@ -0,0 +1,78 @@ +Imports System.Threading +Imports Rpc.BindingProtocols.TaskBuilders +Imports System.Runtime.CompilerServices + +Namespace Rpc.BindingProtocols + ''' + ''' Connector extensions. + ''' + Public Module ConnectorExtensions + ''' + ''' The portmapper program currently supports two protocols (UDP and TCP). The portmapper is contacted by talking to it on assigned port + ''' number 111 (SUNRPC) on either of these protocols. + ''' http://tools.ietf.org/html/rfc1833#section-3.2 + ''' + + Public Function PortMapper(ByVal conn As IRpcClient, ByVal token As CancellationToken, ByVal Optional attachedToParent As Boolean = False) As PortMapper + Return New PortMapper(conn, token, attachedToParent) + End Function + + ''' + ''' The portmapper program currently supports two protocols (UDP and TCP). The portmapper is contacted by talking to it on assigned port + ''' number 111 (SUNRPC) on either of these protocols. + ''' http://tools.ietf.org/html/rfc1833#section-3.2 + ''' + + Public Function PortMapper(ByVal conn As IRpcClient, ByVal Optional attachedToParent As Boolean = False) As PortMapper + Return New PortMapper(conn, CancellationToken.None, attachedToParent) + End Function + + ''' + ''' RPCBIND Version 3 + ''' + ''' RPCBIND is contacted by way of an assigned address specific to the transport being used. + ''' For TCP/IP and UDP/IP, for example, it is port number 111. Each transport has such an assigned, well-known address. + ''' http://tools.ietf.org/html/rfc1833#section-2.2.1 + ''' + + Public Function RpcBindV3(ByVal conn As IRpcClient, ByVal token As CancellationToken, ByVal Optional attachedToParent As Boolean = False) As RpcBindV3 + Return New RpcBindV3(conn, token, attachedToParent) + End Function + + ''' + ''' RPCBIND Version 3 + ''' + ''' RPCBIND is contacted by way of an assigned address specific to the transport being used. + ''' For TCP/IP and UDP/IP, for example, it is port number 111. Each transport has such an assigned, well-known address. + ''' http://tools.ietf.org/html/rfc1833#section-2.2.1 + ''' + + Public Function RpcBindV3(ByVal conn As IRpcClient, ByVal Optional attachedToParent As Boolean = False) As RpcBindV3 + Return New RpcBindV3(conn, CancellationToken.None, attachedToParent) + End Function + + ''' + ''' RPCBIND Version 4 + ''' + ''' RPCBIND is contacted by way of an assigned address specific to the transport being used. + ''' For TCP/IP and UDP/IP, for example, it is port number 111. Each transport has such an assigned, well-known address. + ''' http://tools.ietf.org/html/rfc1833#section-2.2.1 + ''' + + Public Function RpcBindV4(ByVal conn As IRpcClient, ByVal token As CancellationToken, ByVal Optional attachedToParent As Boolean = False) As RpcBindV4 + Return New RpcBindV4(conn, token, attachedToParent) + End Function + + ''' + ''' RPCBIND Version 4 + ''' + ''' RPCBIND is contacted by way of an assigned address specific to the transport being used. + ''' For TCP/IP and UDP/IP, for example, it is port number 111. Each transport has such an assigned, well-known address. + ''' http://tools.ietf.org/html/rfc1833#section-2.2.1 + ''' + + Public Function RpcBindV4(ByVal conn As IRpcClient, ByVal Optional attachedToParent As Boolean = False) As RpcBindV4 + Return New RpcBindV4(conn, CancellationToken.None, attachedToParent) + End Function + End Module +End Namespace diff --git a/Rpc/BindingProtocols/Protocol.vb b/Rpc/BindingProtocols/Protocol.vb new file mode 100644 index 0000000..670b100 --- /dev/null +++ b/Rpc/BindingProtocols/Protocol.vb @@ -0,0 +1,17 @@ + +Namespace Rpc.BindingProtocols + ''' + ''' constants of port mapper protocol + ''' http://tools.ietf.org/html/rfc1833#section-3.1 + ''' + Public Enum Protocol As Integer + ''' + ''' protocol number for TCP/IP + ''' + TCP = 6 + ''' + ''' protocol number for UDP/IP + ''' + UDP = 17 + End Enum +End Namespace diff --git a/Rpc/BindingProtocols/ProtocolFamily.vb b/Rpc/BindingProtocols/ProtocolFamily.vb new file mode 100644 index 0000000..cb4ef33 --- /dev/null +++ b/Rpc/BindingProtocols/ProtocolFamily.vb @@ -0,0 +1,102 @@ + +Namespace Rpc.BindingProtocols + ''' + ''' Protocol family (rpcb_entry.r_nc_protofmly): This identifies the family to which the protocol belongs. + ''' http://tools.ietf.org/html/rfc1833#section-2.1 + ''' + Public Module ProtocolFamily + ''' + ''' no protocol family (-) + ''' NC_NOPROTOFMLY + ''' + Public Const NC_NOPROTOFMLY As String = "-" + ''' + ''' loopback + ''' + Public Const NC_LOOPBACK As String = "loopback" + ''' + ''' inet + ''' + Public Const NC_INET As String = "inet" + ''' + ''' implink + ''' + Public Const NC_IMPLINK As String = "implink" + ''' + ''' pup + ''' + Public Const NC_PUP As String = "pup" + ''' + ''' chaos + ''' + Public Const NC_CHAOS As String = "chaos" + ''' + ''' ns + ''' + Public Const NC_NS As String = "ns" + ''' + ''' nbs + ''' + Public Const NC_NBS As String = "nbs" + ''' + ''' ecma + ''' + Public Const NC_ECMA As String = "ecma" + ''' + ''' datakit + ''' + Public Const NC_DATAKIT As String = "datakit" + ''' + ''' ccitt + ''' + Public Const NC_CCITT As String = "ccitt" + ''' + ''' sna + ''' + Public Const NC_SNA As String = "sna" + ''' + ''' decnet + ''' + Public Const NC_DECNET As String = "decnet" + ''' + ''' dli + ''' + Public Const NC_DLI As String = "dli" + ''' + ''' lat + ''' + Public Const NC_LAT As String = "lat" + ''' + ''' hylink + ''' + Public Const NC_HYLINK As String = "hylink" + ''' + ''' appletalk + ''' + Public Const NC_APPLETALK As String = "appletalk" + ''' + ''' nit + ''' + Public Const NC_NIT As String = "nit" + ''' + ''' ieee802 + ''' + Public Const NC_IEEE802 As String = "ieee802" + ''' + ''' osi + ''' + Public Const NC_OSI As String = "osi" + ''' + ''' x25 + ''' + Public Const NC_X25 As String = "x25" + ''' + ''' osinet + ''' + Public Const NC_OSINET As String = "osinet" + ''' + ''' gosip + ''' + Public Const NC_GOSIP As String = "gosip" + End Module +End Namespace diff --git a/Rpc/BindingProtocols/ProtocolName.vb b/Rpc/BindingProtocols/ProtocolName.vb new file mode 100644 index 0000000..08eacda --- /dev/null +++ b/Rpc/BindingProtocols/ProtocolName.vb @@ -0,0 +1,25 @@ + +Namespace Rpc.BindingProtocols + ''' + ''' Protocol name (rpcb_entry.r_nc_proto): This identifies a protocol within a family. + ''' http://tools.ietf.org/html/rfc1833#section-2.1 + ''' + Public Module ProtocolName + ''' + ''' no protocol name (-) + ''' + Public Const NC_NOPROTO As String = "-" + ''' + ''' tcp + ''' + Public Const NC_TCP As String = "tcp" + ''' + ''' udp + ''' + Public Const NC_UDP As String = "udp" + ''' + ''' icmp + ''' + Public Const NC_ICMP As String = "icmp" + End Module +End Namespace diff --git a/Rpc/BindingProtocols/TaskBuilders/BaseRpcBind.vb b/Rpc/BindingProtocols/TaskBuilders/BaseRpcBind.vb new file mode 100644 index 0000000..119de11 --- /dev/null +++ b/Rpc/BindingProtocols/TaskBuilders/BaseRpcBind.vb @@ -0,0 +1,80 @@ +Imports System.Collections.Generic +Imports System.Threading +Imports System.Threading.Tasks + +Namespace Rpc.BindingProtocols.TaskBuilders + ''' + ''' RPCBIND is contacted by way of an assigned address specific to the transport being used. + ''' For TCP/IP and UDP/IP, for example, it is port number 111. Each transport has such an assigned, well-known address. + ''' http://tools.ietf.org/html/rfc1833#section-2.2.1 + ''' + Public MustInherit Class BaseRpcBind + Inherits BaseTaskBuilder + + Friend Sub New(ByVal conn As IRpcClient, ByVal token As CancellationToken, ByVal attachedToParent As Boolean) + MyBase.New(conn, token, attachedToParent) + End Sub + + ''' + ''' When a program first becomes available on a machine, it registers itself with RPCBIND running on the same machine. + ''' The program passes its program number "r_prog", version number "r_vers", network identifier "r_netid", universal address "r_addr", + ''' and the owner of the service "r_owner". + ''' The procedure returns a boolean response whose value is TRUE if the procedure successfully established the mapping and FALSE otherwise. + ''' The procedure refuses to establish a mapping if one already exists for the ordered set ("r_prog", "r_vers", "r_netid"). + ''' Note that neither "r_netid" nor "r_addr" can be NULL, and that "r_netid" should be a valid network identifier on the machine making the call. + ''' + Public Function [Set](ByVal arg As rpcb) As Task(Of Boolean) + Return CreateTask(Of rpcb, Boolean)(1UI, arg) + End Function + + ''' + ''' When a program becomes unavailable, it should unregister itself with the RPCBIND program on the same machine. + ''' The parameters and results have meanings identical to those of RPCBPROC_SET. + ''' The mapping of the ("r_prog", "r_vers", "r_netid") tuple with "r_addr" is deleted. + ''' If "r_netid" is NULL, all mappings specified by the ordered set ("r_prog", "r_vers", *) and the corresponding universal addresses are deleted. + ''' Only the owner of the service or the super-user is allowed to unset a service + ''' + Public Function UnSet(ByVal arg As rpcb) As Task(Of Boolean) + Return CreateTask(Of rpcb, Boolean)(2UI, arg) + End Function + + ''' + ''' Given a program number "r_prog", version number "r_vers", and network identifier "r_netid", this procedure returns the universal address + ''' on which the program is awaiting call requests. The "r_netid" field of the argument is ignored and the "r_netid" is inferred from the + ''' network identifier of the transport on which the request came in. + ''' + Public Function GetAddr(ByVal arg As rpcb) As Task(Of String) + Return CreateTask(Of rpcb, String)(3UI, arg) + End Function + + ''' + ''' This procedure lists all entries in RPCBIND's database. + ''' The procedure takes no parameters and returns a list of program, version, network identifier, and universal addresses. + ''' + Public Function Dump() As Task(Of List(Of rpcb)) + Return CreateTask(Of Xdr.Void, List(Of rpcb))(4UI, New Xdr.Void()) + End Function + + ''' + ''' This procedure returns the local time on its own machine in seconds + ''' since the midnight of the First day of January, 1970. + ''' + Public Function GetTime() As Task(Of UInteger) + Return CreateTask(Of Xdr.Void, UInteger)(6UI, New Xdr.Void()) + End Function + + ''' + ''' This procedure converts universal addresses to transport specific addresses. + ''' + Public Function UAddr2TAddr(ByVal arg As String) As Task(Of netbuf) + Return CreateTask(Of String, netbuf)(7UI, arg) + End Function + + ''' + ''' This procedure converts transport specific addresses to universal addresses. + ''' + Public Function TAddr2Uaddr(ByVal arg As netbuf) As Task(Of String) + Return CreateTask(Of netbuf, String)(8UI, arg) + End Function + End Class +End Namespace diff --git a/Rpc/BindingProtocols/TaskBuilders/BaseTaskBuilder.vb b/Rpc/BindingProtocols/TaskBuilders/BaseTaskBuilder.vb new file mode 100644 index 0000000..070b7fc --- /dev/null +++ b/Rpc/BindingProtocols/TaskBuilders/BaseTaskBuilder.vb @@ -0,0 +1,59 @@ +Imports System.Threading +Imports System.Threading.Tasks +Imports Rpc.MessageProtocol + +Namespace Rpc.BindingProtocols.TaskBuilders + ''' + ''' operations of binding protocols + ''' + Public MustInherit Class BaseTaskBuilder + Private Const Program As UInteger = 100000UI + Private _conn As IRpcClient + Private _attachedToParent As Boolean + Private _token As CancellationToken + + Friend Sub New(ByVal conn As IRpcClient, ByVal token As CancellationToken, ByVal attachedToParent As Boolean) + _conn = conn + _attachedToParent = attachedToParent + _token = token + End Sub + + ''' + ''' Gets the version of protocol + ''' + Protected MustOverride ReadOnly Property Version As UInteger + + Private Function CreateHeader(ByVal procNum As UInteger) As call_body + Return New call_body() With { + .rpcvers = 2, + .prog = Program, + .proc = procNum, + .vers = Version, + .cred = opaque_auth.None, + .verf = opaque_auth.None + } + End Function + + ''' + ''' Creates the task of request. + ''' + ''' + ''' The queued task. + ''' + ''' + ''' procedure number + ''' + ''' + ''' instance of arguments of request + ''' + ''' + ''' type of request + ''' + ''' + ''' type of response + ''' + Protected Function CreateTask(Of TReq, TResp)(ByVal proc As UInteger, ByVal args As TReq) As Task(Of TResp) + Return _conn.CreateTask(Of TReq, TResp)(CreateHeader(proc), args, If(_attachedToParent, TaskCreationOptions.AttachedToParent, TaskCreationOptions.None), _token) + End Function + End Class +End Namespace diff --git a/Rpc/BindingProtocols/TaskBuilders/PortMapper.vb b/Rpc/BindingProtocols/TaskBuilders/PortMapper.vb new file mode 100644 index 0000000..d96e34f --- /dev/null +++ b/Rpc/BindingProtocols/TaskBuilders/PortMapper.vb @@ -0,0 +1,92 @@ +Imports System.Collections.Generic +Imports System.Threading +Imports System.Threading.Tasks + +Namespace Rpc.BindingProtocols.TaskBuilders + ''' + ''' The portmapper program currently supports two protocols (UDP and TCP). The portmapper is contacted by talking to it on assigned port + ''' number 111 (SUNRPC) on either of these protocols. + ''' http://tools.ietf.org/html/rfc1833#section-3.2 + ''' + Public NotInheritable Class PortMapper + Inherits BaseTaskBuilder + ''' + ''' The portmapper program currently supports two protocols (UDP and TCP). The portmapper is contacted by talking to it on assigned port + ''' number 111 (SUNRPC) on either of these protocols. + ''' http://tools.ietf.org/html/rfc1833#section-3.2 + ''' + ''' instance of connector + ''' cancellation token + ''' attache created task to parent task + Public Sub New(ByVal conn As IRpcClient, ByVal token As CancellationToken, ByVal attachedToParent As Boolean) + MyBase.New(conn, token, attachedToParent) + End Sub + + ''' + ''' Gets the version of protocol + ''' + Protected Overrides ReadOnly Property Version As UInteger + Get + Return 2UI + End Get + End Property + + ''' + ''' This procedure does no work. By convention, procedure zero of any protocol takes no parameters and returns no results. + ''' + Public Function Null() As Task(Of Xdr.Void) + Return CreateTask(Of Xdr.Void, Xdr.Void)(0UI, New Xdr.Void()) + End Function + + ''' + ''' When a program first becomes available on a machine, it registers itself with the port mapper program on the same machine. The program + ''' passes its program number "prog", version number "vers", transport protocol number "prot", and the port "port" on which it awaits + ''' service request. + ''' The procedure returns a boolean reply whose value is "TRUE" if the procedure successfully established the mapping and + ''' "FALSE" otherwise. The procedure refuses to establish a mapping if one already exists for the tuple "(prog, vers, prot)". + ''' + Public Function [Set](ByVal args As mapping) As Task(Of Boolean) + Return CreateTask(Of mapping, Boolean)(1UI, args) + End Function + + ''' + ''' When a program becomes unavailable, it should unregister itself with the port mapper program on the same machine. The parameters and + ''' results have meanings identical to those of "PMAPPROC_SET". The protocol and port number fields of the argument are ignored. + ''' + Public Function UnSet(ByVal args As mapping) As Task(Of Boolean) + Return CreateTask(Of mapping, Boolean)(2UI, args) + End Function + + ''' + ''' Given a program number "prog", version number "vers", and transport protocol number "prot", this procedure returns the port number on + ''' which the program is awaiting call requests. A port value of zeros means the program has not been registered. The "port" field of the + ''' argument is ignored. + ''' + Public Function GetPort(ByVal args As mapping) As Task(Of UInteger) + Return CreateTask(Of mapping, UInteger)(3UI, args) + End Function + + ''' + ''' This procedure enumerates all entries in the port mapper's database. + ''' The procedure takes no parameters and returns a list of program, version, protocol, and port values. + ''' + Public Function Dump() As Task(Of List(Of mapping)) + Return CreateTask(Of Xdr.Void, List(Of mapping))(4UI, New Xdr.Void()) + End Function + + ''' + ''' This procedure allows a client to call another remote procedure on the same machine without knowing the remote procedure's port number. + ''' It is intended for supporting broadcasts to arbitrary remote programs via the well-known port mapper's port. The parameters "prog", + ''' "vers", "proc", and the bytes of "args" are the program number, version number, procedure number, and parameters of the remote + ''' procedure. + ''' Note: + ''' (1) This procedure only sends a reply if the procedure was successfully executed and is silent (no reply) otherwise. + ''' (2) The port mapper communicates with the remote program using UDP only. + ''' + ''' The procedure returns the remote program's port number, and the reply is the reply of the remote procedure. + ''' + Public Function CallIt(ByVal args As call_args) As Task(Of call_result) + Return CreateTask(Of call_args, call_result)(5UI, args) + End Function + End Class +End Namespace diff --git a/Rpc/BindingProtocols/TaskBuilders/RpcBindV3.vb b/Rpc/BindingProtocols/TaskBuilders/RpcBindV3.vb new file mode 100644 index 0000000..bacce40 --- /dev/null +++ b/Rpc/BindingProtocols/TaskBuilders/RpcBindV3.vb @@ -0,0 +1,48 @@ +Imports System.Threading +Imports System.Threading.Tasks + +Namespace Rpc.BindingProtocols.TaskBuilders + ''' + ''' RPCBIND Version 3 + ''' + ''' RPCBIND is contacted by way of an assigned address specific to the transport being used. + ''' For TCP/IP and UDP/IP, for example, it is port number 111. Each transport has such an assigned, well-known address. + ''' http://tools.ietf.org/html/rfc1833#section-2.2.1 + ''' + Public NotInheritable Class RpcBindV3 + Inherits BaseRpcBind + ''' + ''' RPCBIND Version 3 + ''' + ''' RPCBIND is contacted by way of an assigned address specific to the transport being used. + ''' For TCP/IP and UDP/IP, for example, it is port number 111. Each transport has such an assigned, well-known address. + ''' http://tools.ietf.org/html/rfc1833#section-2.2.1 + ''' + ''' instance of connector + ''' cancellation token + ''' attache created task to parent task + Public Sub New(ByVal conn As IRpcClient, ByVal token As CancellationToken, ByVal attachedToParent As Boolean) + MyBase.New(conn, token, attachedToParent) + End Sub + + ''' + ''' Gets the version of protocol + ''' + Protected Overrides ReadOnly Property Version As UInteger + Get + Return 3UI + End Get + End Property + + ''' + ''' This procedure allows a caller to call another remote procedure on the same machine without knowing the remote procedure's universal + ''' address. It is intended for supporting broadcasts to arbitrary remote programs via RPCBIND's universal address. The parameters + ''' "prog", "vers", "proc", and args are the program number, version number, procedure number, and parameters of the remote procedure. + ''' Note - This procedure only sends a response if the procedure was successfully executed and is silent (no response) otherwise. + ''' The procedure returns the remote program's universal address, and the results of the remote procedure. + ''' + Public Function CallIt(ByVal arg As rpcb_rmtcallargs) As Task(Of rpcb_rmtcallres) + Return CreateTask(Of rpcb_rmtcallargs, rpcb_rmtcallres)(5UI, arg) + End Function + End Class +End Namespace diff --git a/Rpc/BindingProtocols/TaskBuilders/RpcBindV4.vb b/Rpc/BindingProtocols/TaskBuilders/RpcBindV4.vb new file mode 100644 index 0000000..9ff645d --- /dev/null +++ b/Rpc/BindingProtocols/TaskBuilders/RpcBindV4.vb @@ -0,0 +1,83 @@ +Imports System.Collections.Generic +Imports System.Threading +Imports System.Threading.Tasks + +Namespace Rpc.BindingProtocols.TaskBuilders + ''' + ''' RPCBIND Version 4 + ''' + ''' RPCBIND is contacted by way of an assigned address specific to the transport being used. + ''' For TCP/IP and UDP/IP, for example, it is port number 111. Each transport has such an assigned, well-known address. + ''' http://tools.ietf.org/html/rfc1833#section-2.2.1 + ''' + Public NotInheritable Class RpcBindV4 + Inherits BaseRpcBind + ''' + ''' RPCBIND Version 4 + ''' + ''' RPCBIND is contacted by way of an assigned address specific to the transport being used. + ''' For TCP/IP and UDP/IP, for example, it is port number 111. Each transport has such an assigned, well-known address. + ''' http://tools.ietf.org/html/rfc1833#section-2.2.1 + ''' + ''' instance of connector + ''' cancellation token + ''' attache created task to parent task + Public Sub New(ByVal conn As IRpcClient, ByVal token As CancellationToken, ByVal attachedToParent As Boolean) + MyBase.New(conn, token, attachedToParent) + End Sub + + ''' + ''' Gets the version of protocol + ''' + Protected Overrides ReadOnly Property Version As UInteger + Get + Return 4UI + End Get + End Property + + ''' + ''' This procedure is identical to the version 3 RPCBPROC_CALLIT procedure. The new name indicates that the procedure should be used + ''' for broadcast RPCs only. RPCBPROC_INDIRECT, defined below, should be used for indirect RPC calls. + ''' + Public Function BCast(ByVal arg As rpcb_rmtcallargs) As Task(Of rpcb_rmtcallres) + Return CreateTask(Of rpcb_rmtcallargs, rpcb_rmtcallres)(5UI, arg) + End Function + + ''' + ''' This procedure is similar to RPCBPROC_GETADDR. The difference is the "r_vers" field of the rpcb structure can be used to specify the + ''' version of interest. If that version is not registered, no address is returned. + ''' + Public Function GetVersAddr(ByVal arg As rpcb) As Task(Of String) + Return CreateTask(Of rpcb, String)(9UI, arg) + End Function + + ''' + ''' Similar to RPCBPROC_CALLIT. Instead of being silent about errors (such as the program not being registered on the system), this + ''' procedure returns an indication of the error. This procedure should not be used for broadcast RPC. It is intended to be used with + ''' indirect RPC calls only. + ''' + Public Function Indirect(ByVal arg As rpcb_rmtcallargs) As Task(Of rpcb_rmtcallres) + Return CreateTask(Of rpcb_rmtcallargs, rpcb_rmtcallres)(10UI, arg) + End Function + + ''' + ''' This procedure returns a list of addresses for the given rpcb entry. + ''' The client may be able use the results to determine alternate transports that it can use to communicate with the server. + ''' + Public Function GetAddrList(ByVal arg As rpcb) As Task(Of List(Of rpcb_entry)) + Return CreateTask(Of rpcb, List(Of rpcb_entry))(11UI, arg) + End Function + + ''' + ''' This procedure returns statistics on the activity of the RPCBIND server. The information lists the number and kind of requests the + ''' server has received. + ''' + ''' Note - All procedures except RPCBPROC_SET and RPCBPROC_UNSET can be called by clients running on a machine other than a machine on which + ''' RPCBIND is running. RPCBIND only accepts RPCBPROC_SET and RPCBPROC_UNSET requests by clients running on the same machine as the + ''' RPCBIND program. + ''' + Public Function GetStat() As Task(Of rpcb_stat_byvers) + Return CreateTask(Of Xdr.Void, rpcb_stat_byvers)(12UI, New Xdr.Void()) + End Function + End Class +End Namespace diff --git a/Rpc/BindingProtocols/TransportSemantics.vb b/Rpc/BindingProtocols/TransportSemantics.vb new file mode 100644 index 0000000..8a2d536 --- /dev/null +++ b/Rpc/BindingProtocols/TransportSemantics.vb @@ -0,0 +1,25 @@ + +Namespace Rpc.BindingProtocols + ''' + ''' Transport semantics (rpcb_entry.r_nc_semantics): This represents the type of transport. + ''' http://tools.ietf.org/html/rfc1833#section-2.1 + ''' + Public Module TransportSemantics + ''' + ''' Connectionless + ''' + Public Const NC_TPI_CLTS As ULong = 1 + ''' + ''' Connection oriented + ''' + Public Const NC_TPI_COTS As ULong = 2 + ''' + ''' Connection oriented with graceful close + ''' + Public Const NC_TPI_COTS_ORD As ULong = 3 + ''' + ''' Raw transport + ''' + Public Const NC_TPI_RAW As ULong = 4 + End Module +End Namespace diff --git a/Rpc/BindingProtocols/call_args.vb b/Rpc/BindingProtocols/call_args.vb new file mode 100644 index 0000000..1cdd93d --- /dev/null +++ b/Rpc/BindingProtocols/call_args.vb @@ -0,0 +1,33 @@ +Imports Xdr + +Namespace Rpc.BindingProtocols + ''' + ''' arguments to callit + ''' http://tools.ietf.org/html/rfc1833#section-3.1 + ''' + Public Class call_args + ''' + ''' program + ''' + + Public prog As UInteger + + ''' + ''' version + ''' + + Public vers As UInteger + + ''' + ''' procedure + ''' + + Public proc As UInteger + + ''' + ''' arguments + ''' + + Public args As Byte() + End Class +End Namespace diff --git a/Rpc/BindingProtocols/call_result.vb b/Rpc/BindingProtocols/call_result.vb new file mode 100644 index 0000000..0ae29fb --- /dev/null +++ b/Rpc/BindingProtocols/call_result.vb @@ -0,0 +1,21 @@ +Imports Xdr + +Namespace Rpc.BindingProtocols + ''' + ''' Results of callit + ''' http://tools.ietf.org/html/rfc1833#section-3.1 + ''' + Public Class call_result + ''' + ''' port of called program + ''' + + Public port As UInteger + + ''' + ''' result + ''' + + Public res As Byte() + End Class +End Namespace diff --git a/Rpc/BindingProtocols/mapping.vb b/Rpc/BindingProtocols/mapping.vb new file mode 100644 index 0000000..66cc274 --- /dev/null +++ b/Rpc/BindingProtocols/mapping.vb @@ -0,0 +1,40 @@ +Imports Xdr + +Namespace Rpc.BindingProtocols + ''' + ''' A mapping of (program, version, protocol) to port number + ''' http://tools.ietf.org/html/rfc1833#section-3.1 + ''' + Public Structure mapping + ''' + ''' program number + ''' + + Public prog As UInteger + ''' + ''' version number + ''' + + Public vers As UInteger + ''' + ''' protocol + ''' + + Public prot As Protocol + ''' + ''' port + ''' + + Public port As UInteger + + ''' + ''' Returns a that represents the current . + ''' + ''' + ''' A that represents the current . + ''' + Public Overrides Function ToString() As String + Return String.Format("port:{0} prog:{1} prot:{2} vers:{3}", port, prog, prot, vers) + End Function + End Structure +End Namespace diff --git a/Rpc/BindingProtocols/netbuf.vb b/Rpc/BindingProtocols/netbuf.vb new file mode 100644 index 0000000..d7e1611 --- /dev/null +++ b/Rpc/BindingProtocols/netbuf.vb @@ -0,0 +1,20 @@ +Imports Xdr + +Namespace Rpc.BindingProtocols + ''' + ''' netbuf structure, used to store the transport specific form of a universal transport address. + ''' http://tools.ietf.org/html/rfc1833#section-2.1 + ''' + Public Class netbuf + ''' + ''' fixme: missing comment + ''' + + Public maxlen As UInteger + ''' + ''' fixme: missing comment + ''' + + Public buf As Byte() + End Class +End Namespace diff --git a/Rpc/BindingProtocols/rpcb.vb b/Rpc/BindingProtocols/rpcb.vb new file mode 100644 index 0000000..2b2d1af --- /dev/null +++ b/Rpc/BindingProtocols/rpcb.vb @@ -0,0 +1,38 @@ +Imports Xdr + +Namespace Rpc.BindingProtocols + ''' + ''' A mapping of (program, version, network ID) to address. + ''' The network identifier (r_netid): This is a string that represents a local identification for a network. + ''' This is defined by a system administrator based on local conventions, and cannot be depended on to have + ''' the same value on every system. + ''' http://tools.ietf.org/html/rfc1833#section-2.1 + ''' + Public Structure rpcb + ''' + ''' program number + ''' + + Public r_prog As UInteger + ''' + ''' version number + ''' + + Public r_vers As UInteger + ''' + ''' network id + ''' + + Public r_netid As String + ''' + ''' universal address + ''' + + Public r_addr As String + ''' + ''' owner of this service + ''' + + Public r_owner As String + End Structure +End Namespace diff --git a/Rpc/BindingProtocols/rpcb_entry.vb b/Rpc/BindingProtocols/rpcb_entry.vb new file mode 100644 index 0000000..88e1c53 --- /dev/null +++ b/Rpc/BindingProtocols/rpcb_entry.vb @@ -0,0 +1,36 @@ +Imports Xdr + +Namespace Rpc.BindingProtocols + ''' + ''' contains a merged address of a service on a particular transport, plus associated netconfig information. + ''' http://tools.ietf.org/html/rfc1833#section-2.1 + ''' + Public Class rpcb_entry + ''' + ''' merged address of service + ''' + + Public r_maddr As String + ''' + ''' The network identifier: This is a string that represents a local identification for a network. + ''' This is defined by a system administrator based on local conventions, and cannot be depended on to have the same value on every system. + ''' + + Public r_nc_netid As String + ''' + ''' semantics of transport (see conctants of ) + ''' + + Public r_nc_semantics As ULong + ''' + ''' protocol family (see conctants of ) + ''' + + Public r_nc_protofmly As String + ''' + ''' protocol name (see conctants of ) + ''' + + Public r_nc_proto As String + End Class +End Namespace diff --git a/Rpc/BindingProtocols/rpcb_rmtcallargs.vb b/Rpc/BindingProtocols/rpcb_rmtcallargs.vb new file mode 100644 index 0000000..d653a60 --- /dev/null +++ b/Rpc/BindingProtocols/rpcb_rmtcallargs.vb @@ -0,0 +1,30 @@ +Imports Xdr + +Namespace Rpc.BindingProtocols + ''' + ''' Arguments of remote calls + ''' http://tools.ietf.org/html/rfc1833#section-2.1 + ''' + Public Class rpcb_rmtcallargs + ''' + ''' program number + ''' + + Public prog As ULong + ''' + ''' version number + ''' + + Public vers As ULong + ''' + ''' procedure number + ''' + + Public proc As ULong + ''' + ''' argument + ''' + + Public args As Byte() + End Class +End Namespace diff --git a/Rpc/BindingProtocols/rpcb_rmtcallres.vb b/Rpc/BindingProtocols/rpcb_rmtcallres.vb new file mode 100644 index 0000000..8685327 --- /dev/null +++ b/Rpc/BindingProtocols/rpcb_rmtcallres.vb @@ -0,0 +1,20 @@ +Imports Xdr + +Namespace Rpc.BindingProtocols + ''' + ''' Results of the remote call + ''' http://tools.ietf.org/html/rfc1833#section-2.1 + ''' + Public Class rpcb_rmtcallres + ''' + ''' remote universal address + ''' + + Public addr As String + ''' + ''' result + ''' + + Public results As Byte() + End Class +End Namespace diff --git a/Rpc/BindingProtocols/rpcb_stat.vb b/Rpc/BindingProtocols/rpcb_stat.vb new file mode 100644 index 0000000..654e316 --- /dev/null +++ b/Rpc/BindingProtocols/rpcb_stat.vb @@ -0,0 +1,41 @@ +Imports Xdr +Imports System.Collections.Generic + +Namespace Rpc.BindingProtocols + ''' + ''' rpcbind statistics + ''' http://tools.ietf.org/html/rfc1833#section-2.1 + ''' + Public Class rpcb_stat + ''' + ''' # of procs in rpcbind V4 plus one + ''' + Public Const RPCBSTAT_HIGHPROC As UInteger = 13 + + ''' + ''' number of procedure calls by numbers + ''' + + Public info As Integer() + ''' + ''' fixme: missing comment + ''' + + Public setinfo As Integer + ''' + ''' fixme: missing comment + ''' + + Public unsetinfo As Integer + ''' + ''' list of all the stats about getport and getaddr + ''' + + Public addrinfo As List(Of rpcbs_addr) + ''' + ''' list of all the stats about rmtcall + ''' + + Public rmtinfo As List(Of rpcbs_rmtcall) + End Class +End Namespace diff --git a/Rpc/BindingProtocols/rpcb_stat_byvers.vb b/Rpc/BindingProtocols/rpcb_stat_byvers.vb new file mode 100644 index 0000000..7943201 --- /dev/null +++ b/Rpc/BindingProtocols/rpcb_stat_byvers.vb @@ -0,0 +1,27 @@ +Imports Xdr + +Namespace Rpc.BindingProtocols + ''' + ''' One rpcb_stat structure is returned for each version of rpcbind being monitored. + ''' Provide only for rpcbind V2, V3 and V4. + ''' typedef rpcb_stat rpcb_stat_byvers[RPCBVERS_STAT]; + ''' http://tools.ietf.org/html/rfc1833#section-2.1 + ''' + Public Class rpcb_stat_byvers + ''' + ''' rpcbind V2 statistics + ''' + + Public V2 As rpcb_stat + ''' + ''' rpcbind V3 statistics + ''' + + Public V3 As rpcb_stat + ''' + ''' rpcbind V4 statistics + ''' + + Public V4 As rpcb_stat + End Class +End Namespace diff --git a/Rpc/BindingProtocols/rpcbs_addr.vb b/Rpc/BindingProtocols/rpcbs_addr.vb new file mode 100644 index 0000000..6b24592 --- /dev/null +++ b/Rpc/BindingProtocols/rpcbs_addr.vb @@ -0,0 +1,35 @@ +Imports Xdr + +Namespace Rpc.BindingProtocols + ''' + ''' the stat about getport and getaddr + ''' http://tools.ietf.org/html/rfc1833#section-2.1 + ''' + Public Class rpcbs_addr + ''' + ''' fixme: missing comment + ''' + + Public prog As UInteger + ''' + ''' fixme: missing comment + ''' + + Public vers As UInteger + ''' + ''' fixme: missing comment + ''' + + Public success As Integer + ''' + ''' fixme: missing comment + ''' + + Public failure As Integer + ''' + ''' fixme: missing comment + ''' + + Public netid As String + End Class +End Namespace diff --git a/Rpc/BindingProtocols/rpcbs_rmtcall.vb b/Rpc/BindingProtocols/rpcbs_rmtcall.vb new file mode 100644 index 0000000..8c882c0 --- /dev/null +++ b/Rpc/BindingProtocols/rpcbs_rmtcall.vb @@ -0,0 +1,45 @@ +Imports Xdr + +Namespace Rpc.BindingProtocols + ''' + ''' the stats about rmtcall + ''' http://tools.ietf.org/html/rfc1833#section-2.1 + ''' + Public Class rpcbs_rmtcall + ''' + ''' fixme: missing comment + ''' + + Public prog As UInteger + ''' + ''' fixme: missing comment + ''' + + Public vers As UInteger + ''' + ''' fixme: missing comment + ''' + + Public proc As UInteger + ''' + ''' fixme: missing comment + ''' + + Public success As Integer + ''' + ''' fixme: missing comment + ''' + + Public failure As Integer + ''' + ''' whether callit or indirect + ''' + + Public indirect As Integer + ''' + ''' fixme: missing comment + ''' + + Public netid As String + End Class +End Namespace diff --git a/Rpc/Connectors/IRpcSession.vb b/Rpc/Connectors/IRpcSession.vb new file mode 100644 index 0000000..8e1cc09 --- /dev/null +++ b/Rpc/Connectors/IRpcSession.vb @@ -0,0 +1,12 @@ +Imports System + +Namespace Rpc.Connectors + Friend Interface IRpcSession + Inherits ITicketOwner + + Sub AsyncSend(ByVal ticket As ITicket) + Sub Close(ByVal ex As Exception) + Event OnExcepted As Action(Of IRpcSession, Exception) + Event OnSended As Action(Of IRpcSession) + End Interface +End Namespace diff --git a/Rpc/Connectors/ITicket.vb b/Rpc/Connectors/ITicket.vb new file mode 100644 index 0000000..53ee030 --- /dev/null +++ b/Rpc/Connectors/ITicket.vb @@ -0,0 +1,12 @@ +Imports System +Imports Rpc.MessageProtocol +Imports Xdr + +Namespace Rpc.Connectors + Friend Interface ITicket + Property Xid As UInteger + Sub ReadResult(ByVal mr As IMsgReader, ByVal r As Reader, ByVal respMsg As rpc_msg) + Sub Except(ByVal ex As Exception) + Sub BuildRpcMessage(ByVal bw As IByteWriter) + End Interface +End Namespace diff --git a/Rpc/Connectors/ITicketOwner.vb b/Rpc/Connectors/ITicketOwner.vb new file mode 100644 index 0000000..7298eea --- /dev/null +++ b/Rpc/Connectors/ITicketOwner.vb @@ -0,0 +1,5 @@ +Namespace Rpc.Connectors + Friend Interface ITicketOwner + Sub RemoveTicket(ByVal ticket As ITicket) + End Interface +End Namespace diff --git a/Rpc/Connectors/TcpClientWrapper.vb b/Rpc/Connectors/TcpClientWrapper.vb new file mode 100644 index 0000000..002cc2b --- /dev/null +++ b/Rpc/Connectors/TcpClientWrapper.vb @@ -0,0 +1,260 @@ +Imports System +Imports System.Collections.Generic +Imports System.IO +Imports System.Net +Imports System.Net.Sockets +Imports System.Threading +Imports NLog +Imports Rpc.TcpStreaming + +Namespace Rpc.Connectors + Friend Class TcpClientWrapper + Private Shared Log As Logger = LogManager.GetCurrentClassLogger() + Private ReadOnly _ep As IPEndPoint + Private _connected As Boolean = False + Private _sync As Object = New Object() + Private _disposed As Boolean = False + Private _client As TcpClient + Private _stream As NetworkStream + + Public Sub New(ByVal ep As IPEndPoint) + _ep = ep + _client = New TcpClient(_ep.AddressFamily) + End Sub + + Public ReadOnly Property Connected As Boolean + Get + Return _connected + End Get + End Property + + Private _connectCompleted As Action(Of Exception) = Nothing + + Public Sub AsyncConnect(ByVal completed As Action(Of Exception)) + Try + + SyncLock _sync + If _disposed Then Throw New ObjectDisposedException(GetType(TcpClient).FullName) + If _connected OrElse _connectCompleted IsNot Nothing Then Throw New InvalidOperationException("already connecting") + _connected = True + _connectCompleted = completed + _client.BeginConnect(_ep.Address, _ep.Port, New AsyncCallback(AddressOf OnConnected), Nothing) + End SyncLock + + Catch ex As Exception + Log.Debug("Unable to connected to {0}. Reason: {1}", _ep, ex) + _connectCompleted = Nothing + ThreadPool.QueueUserWorkItem(Sub(__) completed(ex)) + End Try + End Sub + + Private Sub OnConnected(ByVal ar As IAsyncResult) + Dim copy = _connectCompleted + _connectCompleted = Nothing + + Try + + SyncLock _sync + If _disposed Then Throw New ObjectDisposedException(GetType(TcpClient).FullName) + _client.EndConnect(ar) + _stream = _client.GetStream() + End SyncLock + + Catch ex As Exception + Log.Debug("Unable to connected to {0}. Reason: {1}", _ep, ex) + copy(ex) + End Try + + Log.Debug("Sucess connect to {0}", _ep) + copy(Nothing) + End Sub + +#Region "async read" + + Public Sub AsyncRead(ByVal completed As Action(Of Exception, TcpReader)) + 'HACK: here you need to implement a timeout interrupt + Try + If _readCompleted IsNot Nothing Then Throw New InvalidOperationException("already reading") + _tcpReader = New TcpReader() + _readCompleted = completed + BeginReadRecordMark() + Catch ex As Exception + _tcpReader = Nothing + _readCompleted = Nothing + ThreadPool.QueueUserWorkItem(Sub(state) completed(ex, Nothing)) + End Try + End Sub + + Private _tcpReader As TcpReader + Private _readCompleted As Action(Of Exception, TcpReader) + Private _readBuf As Byte() + Private _readPos As Integer + Private _leftToRead As Integer + Private _lastReadBlock As Boolean + + Private Sub BeginReadRecordMark() + _readBuf = New Byte(3) {} + _readPos = 0 + _leftToRead = 4 + SafeBeginRead(New AsyncCallback(AddressOf EndReadRecordMark)) + End Sub + + Private Sub EndReadRecordMark(ByVal ar As IAsyncResult) + Try + Dim read As Integer + + SyncLock _sync + If _disposed Then Throw New ObjectDisposedException(GetType(TcpClient).FullName) + read = _stream.EndRead(ar) + End SyncLock + + Log.Debug("read {0} bytes of Record Mark", read) + If read <= 0 Then Throw New EndOfStreamException() + _leftToRead -= read + _readPos += read + + If _leftToRead <= 0 Then + ExtractRecordMark() + SafeBeginRead(New AsyncCallback(AddressOf EndReadBody)) + Else + SafeBeginRead(New AsyncCallback(AddressOf EndReadRecordMark)) + End If + + Catch ex As Exception + _readCompleted(ex, Nothing) + _tcpReader = Nothing + _readCompleted = Nothing + _readBuf = Nothing + End Try + End Sub + + Private Sub SafeBeginRead(ByVal callback As AsyncCallback) + SyncLock _sync + If _disposed Then Throw New ObjectDisposedException(GetType(TcpClient).FullName) + _stream.BeginRead(_readBuf, _readPos, _leftToRead, callback, Nothing) + End SyncLock + End Sub + + Private Sub EndReadBody(ByVal ar As IAsyncResult) + Dim [error] As Exception = Nothing + + Try + Dim read As Integer + + SyncLock _sync + If _disposed Then Throw New ObjectDisposedException(GetType(TcpClient).FullName) + read = _stream.EndRead(ar) + End SyncLock + + Log.Debug("read {0} bytes of body", read) + If read <= 0 Then Throw New EndOfStreamException() + _leftToRead -= read + _readPos += read + + If _leftToRead <= 0 Then + Call Log.Trace(New Func(Of String, Byte(), String)(AddressOf DumpToLog), "received byte dump: {0}", _readBuf) + _tcpReader.AppendBlock(_readBuf) + + If Not _lastReadBlock Then + Log.Debug("body readed", read) + BeginReadRecordMark() + Return + End If + Else + SafeBeginRead(New AsyncCallback(AddressOf EndReadBody)) + Return + End If + + Catch ex As Exception + [error] = ex + End Try + + If [error] IsNot Nothing Then _tcpReader = Nothing + _readCompleted([error], _tcpReader) + _tcpReader = Nothing + _readCompleted = Nothing + _readBuf = Nothing + End Sub + + Private Sub ExtractRecordMark() + _leftToRead = (_readBuf(0) And &H7F) << &H18 Or _readBuf(1) << &H10 Or _readBuf(2) << &H08 Or _readBuf(3) + _readBuf = New Byte(_leftToRead - 1) {} + _readPos = 0 + _lastReadBlock = (_readBuf(0) And &H80) = 0 + Log.Debug("read Record Mark lenght: {0} is last: {1}", _leftToRead, _lastReadBlock) + End Sub + +#End Region + +#Region "async write" + + Public Sub AsyncWrite(ByVal blocks As LinkedList(Of Byte()), ByVal completed As Action(Of Exception)) + 'HACK: here you need to implement a timeout interrupt + Try + If _writeCompleted IsNot Nothing Then Throw New InvalidOperationException("already writing") + _writeBlocks = blocks + _writeCompleted = completed + If _writeBlocks.First Is Nothing Then Throw New ArgumentException("blocks is empty") + Dim block = _writeBlocks.First.Value + _byteSending = block.Length + _writeBlocks.RemoveFirst() + Call Log.Trace(New Func(Of String, Byte(), String)(AddressOf DumpToLog), "sending byte dump: {0}", block) + SafeBeginWrite(block) + Catch ex As Exception + _writeCompleted = Nothing + _writeBlocks = Nothing + ThreadPool.QueueUserWorkItem(Sub(state) completed(ex)) + End Try + End Sub + + Private _writeBlocks As LinkedList(Of Byte()) + Private _writeCompleted As Action(Of Exception) + Private _byteSending As Integer = 0 + + Private Sub EndWrite(ByVal ar As IAsyncResult) + Dim [error] As Exception = Nothing + + Try + + SyncLock _sync + If _disposed Then Throw New ObjectDisposedException(GetType(TcpClient).FullName) + _stream.EndWrite(ar) + End SyncLock + + Log.Debug("sended {0} bytes", _byteSending) + + If _writeBlocks.First IsNot Nothing Then + Dim block = _writeBlocks.First.Value + _byteSending = block.Length + _writeBlocks.RemoveFirst() + SafeBeginWrite(block) + Return + End If + + Catch ex As Exception + [error] = ex + End Try + + _writeBlocks = Nothing + _writeCompleted([error]) + _writeCompleted = Nothing + End Sub + + Private Sub SafeBeginWrite(ByVal block As Byte()) + SyncLock _sync + If _disposed Then Throw New ObjectDisposedException(GetType(TcpClient).FullName) + _stream.BeginWrite(block, 0, block.Length, New AsyncCallback(AddressOf EndWrite), Nothing) + End SyncLock + End Sub + +#End Region + + Public Sub Close() + SyncLock _sync + If _disposed Then Return + _disposed = True + _client.Close() + End SyncLock + End Sub + End Class +End Namespace diff --git a/Rpc/Connectors/TcpSession.vb b/Rpc/Connectors/TcpSession.vb new file mode 100644 index 0000000..48fd54b --- /dev/null +++ b/Rpc/Connectors/TcpSession.vb @@ -0,0 +1,183 @@ +Imports System +Imports System.Collections.Generic +Imports System.Net +Imports System.Linq +Imports System.Threading +Imports NLog +Imports Rpc.MessageProtocol +Imports Rpc.TcpStreaming +Imports Xdr + +Namespace Rpc.Connectors + Friend Class TcpSession + Implements IRpcSession + + Private Shared Log As Logger = LogManager.GetCurrentClassLogger() + Private ReadOnly _client As TcpClientWrapper + Private ReadOnly _maxBlock As Integer + Private _connected As Boolean = False + Private _sendingTicket As ITicket = Nothing + Private ReadOnly _sync As Object = New Object() + Private _receivingInProgress As Boolean = False + Private _handlers As Dictionary(Of UInteger, ITicket) = New Dictionary(Of UInteger, ITicket)() + + Public Sub New(ByVal ep As IPEndPoint, ByVal Optional blockSize As Integer = 1024 * 4) + _client = New TcpClientWrapper(ep) + _maxBlock = blockSize + End Sub + + Public Sub AsyncSend(ByVal ticket As ITicket) Implements IRpcSession.AsyncSend + If _sendingTicket IsNot Nothing Then Throw New InvalidOperationException("ticket already sending") + _sendingTicket = ticket + + SyncLock _sync + _handlers.Add(_sendingTicket.Xid, _sendingTicket) + End SyncLock + + If _connected Then + Call ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf BuildMessage)) + Else + _connected = True + _client.AsyncConnect(New Action(Of Exception)(AddressOf OnConnected)) + End If + End Sub + + Private Sub OnConnected(ByVal ex As Exception) + If ex IsNot Nothing Then + OnException(ex) + Else + BuildMessage(Nothing) + End If + End Sub + + Private Sub BuildMessage(ByVal state As Object) + Dim blocks As LinkedList(Of Byte()) + + Try + Dim tw As TcpWriter = New TcpWriter(_maxBlock) + _sendingTicket.BuildRpcMessage(tw) + blocks = tw.Build() + Catch ex As Exception + Log.Debug("TCP message not builded (xid:{0}) reason: {1}", _sendingTicket.Xid, ex) + + SyncLock _sync + _handlers.Remove(_sendingTicket.Xid) + End SyncLock + + _sendingTicket.Except(ex) + OnSend() + Return + End Try + + BeginReceive() + Log.Debug("Begin sending TCP message (xid:{0})", _sendingTicket.Xid) + _client.AsyncWrite(blocks, New Action(Of Exception)(AddressOf OnBlocksWrited)) + End Sub + + Private Sub BeginReceive() + SyncLock _sync + If _receivingInProgress Then Return + + If _handlers.Count = 0 Then + Log.Debug("Receive stop. No handlers.") + Return + End If + + _receivingInProgress = True + End SyncLock + + Log.Trace("Wait response.") + _client.AsyncRead(New Action(Of Exception, TcpReader)(AddressOf OnMessageReaded)) + End Sub + + Private Sub OnMessageReaded(ByVal err As Exception, ByVal tcpReader As TcpReader) + If err IsNot Nothing Then + Log.Debug("No receiving TCP messages. Reason: {0}", err) + OnException(err) + Return + End If + + SyncLock _sync + _receivingInProgress = False + End SyncLock + + Dim respMsg As rpc_msg = Nothing + Dim r As Reader = Nothing + + Try + r = CreateReader(tcpReader) + respMsg = r.Read(Of rpc_msg)() + Catch ex As Exception + Log.Info("Parse exception: {0}", ex) + BeginReceive() + Return + End Try + + Log.Trace("Received response xid:{0}", respMsg.xid) + Dim ticket = EnqueueTicket(respMsg.xid) + BeginReceive() + + If ticket Is Nothing Then + Log.Debug("No handler for xid:{0}", respMsg.xid) + Else + ticket.ReadResult(tcpReader, r, respMsg) + End If + End Sub + + Private Function EnqueueTicket(ByVal xid As UInteger) As ITicket + SyncLock _sync + Dim result As ITicket + If Not _handlers.TryGetValue(xid, result) Then Return Nothing + _handlers.Remove(xid) + Return result + End SyncLock + End Function + + Private Sub OnBlocksWrited(ByVal ex As Exception) + If ex IsNot Nothing Then + Log.Debug("TCP message not sended (xid:{0}) reason: {1}", _sendingTicket.Xid, ex) + OnException(ex) + Else + Log.Debug("TCP message sended (xid:{0})", _sendingTicket.Xid) + OnSend() + End If + End Sub + + Public Sub RemoveTicket(ByVal ticket As ITicket) Implements ITicketOwner.RemoveTicket + SyncLock _sync + _handlers.Remove(ticket.Xid) + End SyncLock + End Sub + + Public Sub Close(ByVal ex As Exception) Implements IRpcSession.Close + Log.Debug("Close session.") + Dim tickets As ITicket() + + SyncLock _sync + tickets = _handlers.Values.ToArray() + _handlers.Clear() + End SyncLock + + For Each t In tickets + t.Except(ex) + Next + + _client.Close() + End Sub + + Public Event OnExcepted As Action(Of IRpcSession, Exception) Implements IRpcSession.OnExcepted + + Private Sub OnException(ByVal ex As Exception) + Dim copy = OnExceptedEvent + If copy IsNot Nothing Then copy(Me, ex) + End Sub + + Public Event OnSended As Action(Of IRpcSession) Implements IRpcSession.OnSended + + Private Sub OnSend() + _sendingTicket = Nothing + Dim copy = OnSendedEvent + If copy IsNot Nothing Then copy(Me) + End Sub + End Class +End Namespace diff --git a/Rpc/Connectors/Ticket.vb b/Rpc/Connectors/Ticket.vb new file mode 100644 index 0000000..01191b0 --- /dev/null +++ b/Rpc/Connectors/Ticket.vb @@ -0,0 +1,74 @@ +Imports System +Imports System.Threading +Imports System.Threading.Tasks +Imports Rpc.MessageProtocol +Imports Xdr + +Namespace Rpc.Connectors + Friend Class Ticket(Of TReq, TResp) + Implements ITicket + + Private _owner As ITicketOwner + Private _callBody As call_body + Private _reqArgs As TReq + Private _taskSrc As TaskCompletionSource(Of TResp) + Private _ctr As CancellationTokenRegistration + Public Property Xid As UInteger Implements ITicket.Xid + + Public Sub New(ByVal owner As ITicketOwner, ByVal callBody As call_body, ByVal reqArgs As TReq, ByVal options As TaskCreationOptions, ByVal token As CancellationToken) + _owner = owner + _callBody = callBody + _reqArgs = reqArgs + _taskSrc = New TaskCompletionSource(Of TResp)(options) + + If token.CanBeCanceled Then + _ctr = token.Register(New Action(AddressOf Cancel)) + Else + _ctr = New CancellationTokenRegistration() + End If + End Sub + + Public ReadOnly Property Task As Task(Of TResp) + Get + Return _taskSrc.Task + End Get + End Property + + Public Sub BuildRpcMessage(ByVal bw As IByteWriter) Implements ITicket.BuildRpcMessage + Dim reqHeader As rpc_msg = New rpc_msg() With { + .xid = Xid, + .body = New body() With { + .mtype = msg_type.CALL, + .cbody = _callBody + } + } + Dim xw = CreateWriter(bw) + xw.Write(reqHeader) + xw.Write(_reqArgs) + _callBody = Nothing + _reqArgs = Nothing + End Sub + + Public Sub ReadResult(ByVal mr As IMsgReader, ByVal r As Reader, ByVal respMsg As rpc_msg) Implements ITicket.ReadResult + _ctr.Dispose() + + Try + ReplyMessageValidate(respMsg) + Dim respArgs As TResp = r.Read(Of TResp)() + mr.CheckEmpty() + _taskSrc.TrySetResult(respArgs) + Catch ex As Exception + _taskSrc.TrySetException(ex) + End Try + End Sub + + Public Sub Except(ByVal ex As Exception) Implements ITicket.Except + _ctr.Dispose() + _taskSrc.TrySetException(ex) + End Sub + + Private Sub Cancel() + If _taskSrc.TrySetCanceled() Then _owner.RemoveTicket(Me) + End Sub + End Class +End Namespace diff --git a/Rpc/Connectors/UdpClientWrapper.vb b/Rpc/Connectors/UdpClientWrapper.vb new file mode 100644 index 0000000..07f4d41 --- /dev/null +++ b/Rpc/Connectors/UdpClientWrapper.vb @@ -0,0 +1,105 @@ +Imports System +Imports System.Net +Imports System.Net.Sockets +Imports System.Threading +Imports NLog +Imports Rpc.UdpDatagrams + +Namespace Rpc.Connectors + Friend Class UdpClientWrapper + Private Shared Log As Logger = LogManager.GetCurrentClassLogger() + Private ReadOnly _ep As IPEndPoint + Private _sync As Object = New Object() + Private _disposed As Boolean = False + Private _client As UdpClient + + Public Sub New(ByVal ep As IPEndPoint) + _ep = ep + _client = New UdpClient() + _client.Connect(_ep) + End Sub + + Private _readCompleted As Action(Of Exception, UdpReader) = Nothing + + Public Sub AsyncRead(ByVal completed As Action(Of Exception, UdpReader)) + _readCompleted = completed + + SyncLock _sync + + Try + If _disposed Then Throw New ObjectDisposedException(GetType(UdpClient).FullName) + _client.BeginReceive(New AsyncCallback(AddressOf EndRead), Nothing) + Catch ex As Exception + _readCompleted = Nothing + ThreadPool.QueueUserWorkItem(Sub(state) completed(ex, Nothing)) + End Try + End SyncLock + End Sub + + Private Sub EndRead(ByVal ar As IAsyncResult) + Dim reader As UdpReader = Nothing + Dim err As Exception = Nothing + Dim copy = _readCompleted + _readCompleted = Nothing + + SyncLock _sync + + Try + If _disposed Then Throw New ObjectDisposedException(GetType(UdpClient).FullName) + Dim ep As IPEndPoint = New IPEndPoint(IPAddress.Any, 0) + Dim datagram = _client.EndReceive(ar, ep) + Call Log.Trace(New Func(Of String, Byte(), String)(AddressOf DumpToLog), "received datagram: {0}", datagram) + reader = New UdpReader(datagram) + Catch ex As Exception + err = ex + End Try + End SyncLock + + copy(err, reader) + End Sub + + Private _writeCompleted As Action(Of Exception) = Nothing + + Public Sub AsyncWrite(ByVal datagram As Byte(), ByVal completed As Action(Of Exception)) + Call Log.Trace(New Func(Of String, Byte(), String)(AddressOf DumpToLog), "sending datagram: {0}", datagram) + _writeCompleted = completed + + SyncLock _sync + + Try + If _disposed Then Throw New ObjectDisposedException(GetType(UdpClient).FullName) + _client.BeginSend(datagram, datagram.Length, New AsyncCallback(AddressOf EndWrite), Nothing) + Catch ex As Exception + _writeCompleted = Nothing + ThreadPool.QueueUserWorkItem(Sub(state) completed(ex)) + End Try + End SyncLock + End Sub + + Private Sub EndWrite(ByVal ar As IAsyncResult) + Dim err As Exception = Nothing + Dim copy = _writeCompleted + _writeCompleted = Nothing + + SyncLock _sync + + Try + If _disposed Then Throw New ObjectDisposedException(GetType(UdpClient).FullName) + _client.EndSend(ar) + Catch ex As Exception + err = ex + End Try + End SyncLock + + copy(err) + End Sub + + Public Sub Close() + SyncLock _sync + If _disposed Then Return + _disposed = True + _client.Close() + End SyncLock + End Sub + End Class +End Namespace diff --git a/Rpc/Connectors/UdpSession.vb b/Rpc/Connectors/UdpSession.vb new file mode 100644 index 0000000..231835d --- /dev/null +++ b/Rpc/Connectors/UdpSession.vb @@ -0,0 +1,167 @@ +Imports System +Imports System.Collections.Generic +Imports System.Net +Imports System.Linq +Imports System.Threading +Imports NLog +Imports Rpc.MessageProtocol +Imports Rpc.UdpDatagrams +Imports Xdr + +Namespace Rpc.Connectors + Friend Class UdpSession + Implements IRpcSession + + Private Shared Log As Logger = LogManager.GetCurrentClassLogger() + Private ReadOnly _client As UdpClientWrapper + Private _sendingTicket As ITicket = Nothing + Private ReadOnly _sync As Object = New Object() + Private _receivingInProgress As Boolean = False + Private _handlers As Dictionary(Of UInteger, ITicket) = New Dictionary(Of UInteger, ITicket)() + + Public Sub New(ByVal ep As IPEndPoint) + _client = New UdpClientWrapper(ep) + End Sub + + Public Sub AsyncSend(ByVal ticket As ITicket) Implements IRpcSession.AsyncSend + If _sendingTicket IsNot Nothing Then Throw New InvalidOperationException("ticket already sending") + _sendingTicket = ticket + + SyncLock _sync + _handlers.Add(_sendingTicket.Xid, _sendingTicket) + End SyncLock + + Call ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf BuildMessage)) + End Sub + + Private Sub BuildMessage(ByVal state As Object) + Dim datagram As Byte() + + Try + Dim uw As UdpWriter = New UdpWriter() + _sendingTicket.BuildRpcMessage(uw) + datagram = uw.Build() + Catch ex As Exception + Log.Debug("UDP datagram not builded (xid:{0}) reason: {1}", _sendingTicket.Xid, ex) + + SyncLock _sync + _handlers.Remove(_sendingTicket.Xid) + End SyncLock + + _sendingTicket.Except(ex) + OnSend() + Return + End Try + + Log.Debug("Begin sending UDP datagram (xid:{0})", _sendingTicket.Xid) + _client.AsyncWrite(datagram, New Action(Of Exception)(AddressOf OnDatagramWrited)) + End Sub + + Private Sub BeginReceive() + SyncLock _sync + If _receivingInProgress Then Return + + If _handlers.Count = 0 Then + Log.Debug("Receive stop. No handlers.") + Return + End If + + _receivingInProgress = True + End SyncLock + + Log.Trace("Wait response.") + _client.AsyncRead(New Action(Of Exception, UdpReader)(AddressOf OnMessageReaded)) + End Sub + + Private Sub OnMessageReaded(ByVal err As Exception, ByVal udpReader As UdpReader) + If err IsNot Nothing Then + Log.Debug("No receiving UDP datagrams. Reason: {0}", err) + OnException(err) + Return + End If + + SyncLock _sync + _receivingInProgress = False + End SyncLock + + Dim respMsg As rpc_msg = Nothing + Dim r As Reader = Nothing + + Try + r = CreateReader(udpReader) + respMsg = r.Read(Of rpc_msg)() + Catch ex As Exception + Log.Info("Parse exception: {0}", ex) + BeginReceive() + Return + End Try + + Log.Trace("Received response xid:{0}", respMsg.xid) + Dim ticket = EnqueueTicket(respMsg.xid) + BeginReceive() + + If ticket Is Nothing Then + Log.Debug("No handler for xid:{0}", respMsg.xid) + Else + ticket.ReadResult(udpReader, r, respMsg) + End If + End Sub + + Private Function EnqueueTicket(ByVal xid As UInteger) As ITicket + SyncLock _sync + Dim result As ITicket + If Not _handlers.TryGetValue(xid, result) Then Return Nothing + _handlers.Remove(xid) + Return result + End SyncLock + End Function + + Private Sub OnDatagramWrited(ByVal ex As Exception) + If ex IsNot Nothing Then + Log.Debug("UDP datagram not sended (xid:{0}) reason: {1}", _sendingTicket.Xid, ex) + OnException(ex) + Else + Log.Debug("UDP datagram sended (xid:{0})", _sendingTicket.Xid) + BeginReceive() + OnSend() + End If + End Sub + + Public Sub RemoveTicket(ByVal ticket As ITicket) Implements ITicketOwner.RemoveTicket + SyncLock _sync + _handlers.Remove(ticket.Xid) + End SyncLock + End Sub + + Public Sub Close(ByVal ex As Exception) Implements IRpcSession.Close + Log.Debug("Close session.") + Dim tickets As ITicket() + + SyncLock _sync + tickets = _handlers.Values.ToArray() + _handlers.Clear() + End SyncLock + + For Each t In tickets + t.Except(ex) + Next + + _client.Close() + End Sub + + Public Event OnExcepted As Action(Of IRpcSession, Exception) Implements IRpcSession.OnExcepted + + Private Sub OnException(ByVal ex As Exception) + Dim copy = OnExceptedEvent + If copy IsNot Nothing Then copy(Me, ex) + End Sub + + Public Event OnSended As Action(Of IRpcSession) Implements IRpcSession.OnSended + + Private Sub OnSend() + _sendingTicket = Nothing + Dim copy = OnSendedEvent + If copy IsNot Nothing Then copy(Me) + End Sub + End Class +End Namespace diff --git a/Rpc/Exceptions/AuthenticateException.vb b/Rpc/Exceptions/AuthenticateException.vb new file mode 100644 index 0000000..c73b99d --- /dev/null +++ b/Rpc/Exceptions/AuthenticateException.vb @@ -0,0 +1,37 @@ +Imports System +Imports Rpc.MessageProtocol + +Namespace Rpc + ''' + ''' Authenticate error + ''' + Public Class AuthenticateException + Inherits ReplyException + ''' + ''' Authenticate error + ''' + ''' + Public Sub New(ByVal replyBody As reply_body) + MyBase.New(replyBody) + End Sub + + ''' + ''' Authenticate error + ''' + ''' + ''' + Public Sub New(ByVal replyBody As reply_body, ByVal message As String) + MyBase.New(replyBody, message) + End Sub + + ''' + ''' Authenticate error + ''' + ''' + ''' + ''' + Public Sub New(ByVal replyBody As reply_body, ByVal message As String, ByVal innerEx As Exception) + MyBase.New(replyBody, message, innerEx) + End Sub + End Class +End Namespace diff --git a/Rpc/Exceptions/Exceptions.vb b/Rpc/Exceptions/Exceptions.vb new file mode 100644 index 0000000..94decf2 --- /dev/null +++ b/Rpc/Exceptions/Exceptions.vb @@ -0,0 +1,73 @@ +Imports System +Imports Rpc.MessageProtocol + +Namespace Rpc + Friend Module Exceptions + Friend Function UnexpectedMessageType(ByVal present As msg_type) As FormatException + Return New FormatException(String.Format("unexpected message type: `{0}'", present)) + End Function + + Friend Function NoRFC5531(ByVal paramName As String) As ArgumentException + Return New ArgumentException("structure must be RFC5531", paramName) + End Function + + Friend Function Format(ByVal frm As String, ParamArray args As Object()) As FormatException + Return New FormatException(String.Format(frm, args)) + End Function + + Friend Function SystemError(ByVal replyBody As reply_body) As ReplyException + Return New ReplyException(replyBody, "system error in RPC-server") + End Function + + Friend Function AuthError(ByVal replyBody As reply_body, ByVal state As auth_stat) As AuthenticateException + Return New AuthenticateException(replyBody, GetAuthDescription(state)) + End Function + + Friend Function GetAuthDescription(ByVal state As auth_stat) As String + Select Case state + Case auth_stat.AUTH_BADCRED + Return "bad credential (seal broken)" + Case auth_stat.AUTH_BADVERF + Return "bad verifier (seal broken)" + Case auth_stat.AUTH_FAILED + Return "unknown reason" + Case auth_stat.AUTH_INVALIDRESP + Return "bogus response verifier" + Case auth_stat.AUTH_OK + Return "success" + Case auth_stat.AUTH_REJECTEDCRED + Return "client must begin new session" + Case auth_stat.AUTH_REJECTEDVERF + Return "verifier expired or replayed" + Case auth_stat.AUTH_TOOWEAK + Return "rejected for security reasons" + Case auth_stat.RPCSEC_GSS_CREDPROBLEM + Return "no credentials for user" + Case auth_stat.RPCSEC_GSS_CTXPROBLEM + Return "problem with context" + Case Else + Return String.Format("unknown state: {0}", state) + End Select + End Function + + Friend Function RpcVersionError(ByVal replyBody As reply_body, ByVal info As mismatch_info) As ReplyException + Return New ReplyException(replyBody, String.Format("unsupported RPC version number (supported versions of between {0} and {1})", info.low, info.high)) + End Function + + Friend Function ProgramMismatch(ByVal replyBody As reply_body, ByVal info As mismatch_info) As ReplyException + Return New ReplyException(replyBody, String.Format("remote can't support program version (supported versions of between {0} and {1})", info.low, info.high)) + End Function + + Friend Function ProgramUnavalible(ByVal replyBody As reply_body) As ReplyException + Return New ReplyException(replyBody, "remote hasn't exported program") + End Function + + Friend Function ProcedureUnavalible(ByVal replyBody As reply_body) As RpcException + Return New ReplyException(replyBody, "program can't support procedure") + End Function + + Friend Function GarbageArgs() As RpcException + Return New RpcException("procedure can't decode params") + End Function + End Module +End Namespace diff --git a/Rpc/Exceptions/ReplyException.vb b/Rpc/Exceptions/ReplyException.vb new file mode 100644 index 0000000..78d1db4 --- /dev/null +++ b/Rpc/Exceptions/ReplyException.vb @@ -0,0 +1,53 @@ +Imports System +Imports Rpc.MessageProtocol + +Namespace Rpc + ''' + ''' Error received in response RPC message + ''' + Public Class ReplyException + Inherits RpcException + ''' + ''' Body of a reply to an RPC call for details + ''' + Private _ReplyBody As Rpc.MessageProtocol.reply_body + + Public Property ReplyBody As reply_body + Get + Return _ReplyBody + End Get + Private Set(ByVal value As reply_body) + _ReplyBody = value + End Set + End Property + + ''' + ''' Error received in response RPC message + ''' + ''' + Public Sub New(ByVal replyBody As reply_body) + Me.ReplyBody = replyBody + End Sub + + ''' + ''' Error received in response RPC message + ''' + ''' + ''' + Public Sub New(ByVal replyBody As reply_body, ByVal message As String) + MyBase.New(message) + Me.ReplyBody = replyBody + End Sub + + ''' + ''' Error received in response RPC message + ''' + ''' + ''' + ''' + Public Sub New(ByVal replyBody As reply_body, ByVal message As String, ByVal innerEx As Exception) + MyBase.New(message, innerEx) + Me.ReplyBody = replyBody + End Sub + End Class +End Namespace diff --git a/Rpc/Exceptions/RpcException.vb b/Rpc/Exceptions/RpcException.vb new file mode 100644 index 0000000..293c942 --- /dev/null +++ b/Rpc/Exceptions/RpcException.vb @@ -0,0 +1,32 @@ +Imports System + +Namespace Rpc + ''' + ''' Error associated with work on RPC protocol + ''' + Public Class RpcException + Inherits SystemException + ''' + ''' Error associated with work on RPC protocol + ''' + Public Sub New() + End Sub + + ''' + ''' Error associated with work on RPC protocol + ''' + ''' + Public Sub New(ByVal message As String) + MyBase.New(message) + End Sub + + ''' + ''' Error associated with work on RPC protocol + ''' + ''' + ''' + Public Sub New(ByVal message As String, ByVal innerEx As Exception) + MyBase.New(message, innerEx) + End Sub + End Class +End Namespace diff --git a/Rpc/IMsgReader.vb b/Rpc/IMsgReader.vb new file mode 100644 index 0000000..6e2dbc4 --- /dev/null +++ b/Rpc/IMsgReader.vb @@ -0,0 +1,6 @@ + +Namespace Rpc + Friend Interface IMsgReader + Sub CheckEmpty() + End Interface +End Namespace diff --git a/Rpc/IRpcClient.vb b/Rpc/IRpcClient.vb new file mode 100644 index 0000000..fe3daa3 --- /dev/null +++ b/Rpc/IRpcClient.vb @@ -0,0 +1,28 @@ +Imports System.Threading +Imports System.Threading.Tasks +Imports Rpc.MessageProtocol + +Namespace Rpc + ''' + ''' creates tasks for the control request to the RPC server + ''' + Public Interface IRpcClient + ''' + ''' creates the task for the control request to the RPC server + ''' + ''' + ''' the runned task + ''' + ''' call body structure + ''' instance of request arguments + ''' task creation options + ''' cancellation token + ''' type of request + ''' type of response + Function CreateTask(Of TReq, TResp)(ByVal callBody As call_body, ByVal reqArgs As TReq, ByVal options As TaskCreationOptions, ByVal token As CancellationToken) As Task(Of TResp) + ''' + ''' Close this connection and cancel all queued tasks + ''' + Sub Close() + End Interface +End Namespace diff --git a/Rpc/MessageProtocol/accept_stat.vb b/Rpc/MessageProtocol/accept_stat.vb new file mode 100644 index 0000000..71f4c01 --- /dev/null +++ b/Rpc/MessageProtocol/accept_stat.vb @@ -0,0 +1,38 @@ + +Namespace Rpc.MessageProtocol + ''' + ''' Given that a call message was accepted, the following is the status of an attempt to call a remote procedure. + ''' http://tools.ietf.org/html/rfc5531#section-9 + ''' + Public Enum accept_stat As Integer + ''' + ''' RPC executed successfully + ''' + SUCCESS = 0 + + ''' + ''' remote hasn't exported program + ''' + PROG_UNAVAIL = 1 + + ''' + ''' remote can't support version # + ''' + PROG_MISMATCH = 2 + + ''' + ''' program can't support procedure + ''' + PROC_UNAVAIL = 3 + + ''' + ''' procedure can't decode params + ''' + GARBAGE_ARGS = 4 + + ''' + ''' e.g. memory allocation failure + ''' + SYSTEM_ERR = 5 + End Enum +End Namespace diff --git a/Rpc/MessageProtocol/accepted_reply.vb b/Rpc/MessageProtocol/accepted_reply.vb new file mode 100644 index 0000000..895f0b9 --- /dev/null +++ b/Rpc/MessageProtocol/accepted_reply.vb @@ -0,0 +1,40 @@ +Imports Xdr + +Namespace Rpc.MessageProtocol + ''' + ''' Reply to an RPC call that was accepted by the server + ''' http://tools.ietf.org/html/rfc5531#section-9 + ''' + Public Class accepted_reply + ''' + ''' authentication verifier that the server generates in order to validate itself to the client + ''' + + Public verf As opaque_auth + + ''' + ''' the reply data. + ''' + + Public reply_data As reply_data_union + + ''' + ''' the reply data + ''' + Public Class reply_data_union + ''' + ''' accept state + ''' + + <[Case](accept_stat.SUCCESS)> ' opaque results[0]; - procedure-specific results start here + <[Case](accept_stat.PROG_UNAVAIL), [Case](accept_stat.PROC_UNAVAIL), [Case](accept_stat.GARBAGE_ARGS), [Case](accept_stat.SYSTEM_ERR)> ' void + Public stat As accept_stat + + ''' + ''' the lowest and highest version numbers of the remote program supported by the server + ''' + <[Case](accept_stat.PROG_MISMATCH)> + Public mismatch_info As mismatch_info + End Class + End Class +End Namespace diff --git a/Rpc/MessageProtocol/auth_flavor.vb b/Rpc/MessageProtocol/auth_flavor.vb new file mode 100644 index 0000000..fd2704f --- /dev/null +++ b/Rpc/MessageProtocol/auth_flavor.vb @@ -0,0 +1,33 @@ + +Namespace Rpc.MessageProtocol + ''' + ''' Authentication flavor + ''' http://tools.ietf.org/html/rfc5531#section-8.2 + ''' + Public Enum auth_flavor As Integer + ''' + ''' + ''' + AUTH_NONE = 0 + + ''' + ''' + ''' + AUTH_SYS = 1 + + ''' + ''' + ''' + AUTH_SHORT = 2 + + ''' + ''' + ''' + AUTH_DH = 3 + + ''' + ''' + ''' + RPCSEC_GSS = 6 + End Enum +End Namespace diff --git a/Rpc/MessageProtocol/auth_stat.vb b/Rpc/MessageProtocol/auth_stat.vb new file mode 100644 index 0000000..80a9ac9 --- /dev/null +++ b/Rpc/MessageProtocol/auth_stat.vb @@ -0,0 +1,89 @@ +Imports System + +Namespace Rpc.MessageProtocol + ''' + ''' Cause of authentication failed + ''' http://tools.ietf.org/html/rfc5531#section-9 + ''' + Public Enum auth_stat As Integer + ''' + ''' success + ''' + AUTH_OK = 0 + + ''' + ''' failed at remote end - bad credential (seal broken) + ''' + AUTH_BADCRED = 1 + + ''' + ''' failed at remote end - client must begin new session + ''' + AUTH_REJECTEDCRED = 2 + + ''' + ''' failed at remote end - bad verifier (seal broken) + ''' + AUTH_BADVERF = 3 + + ''' + ''' failed at remote end - verifier expired or replayed + ''' + AUTH_REJECTEDVERF = 4 + + ''' + ''' failed at remote end - rejected for security reasons + ''' + AUTH_TOOWEAK = 5 + + ''' + ''' failed locally - bogus response verifier + ''' + AUTH_INVALIDRESP = 6 + + ''' + ''' failed locally - reason unknown + ''' + AUTH_FAILED = 7 + + ''' + ''' kerberos generic error + ''' + + AUTH_KERB_GENERIC = 8 + + ''' + ''' time of credential expired + ''' + + AUTH_TIMEEXPIRE = 9 + + ''' + ''' problem with ticket file + ''' + + AUTH_TKT_FILE = 10 + + ''' + ''' can't decode authenticator + ''' + + AUTH_DECODE = 11 + + ''' + ''' wrong net address in ticket + ''' + + AUTH_NET_ADDR = 12 + + ''' + ''' GSS related errors - no credentials for user + ''' + RPCSEC_GSS_CREDPROBLEM = 13 + + ''' + ''' GSS related errors - problem with context + ''' + RPCSEC_GSS_CTXPROBLEM = 14 + End Enum +End Namespace diff --git a/Rpc/MessageProtocol/body.vb b/Rpc/MessageProtocol/body.vb new file mode 100644 index 0000000..91ad6d1 --- /dev/null +++ b/Rpc/MessageProtocol/body.vb @@ -0,0 +1,25 @@ +Imports Xdr + +Namespace Rpc.MessageProtocol + ''' + ''' message body + ''' http://tools.ietf.org/html/rfc5531#section-9 + ''' + Public Class body + ''' + ''' message type + ''' + + Public mtype As msg_type + ''' + ''' call body + ''' + <[Case](msg_type.CALL)> + Public cbody As call_body + ''' + ''' reply body + ''' + <[Case](msg_type.REPLY)> + Public rbody As reply_body + End Class +End Namespace diff --git a/Rpc/MessageProtocol/call_body.vb b/Rpc/MessageProtocol/call_body.vb new file mode 100644 index 0000000..d86eaac --- /dev/null +++ b/Rpc/MessageProtocol/call_body.vb @@ -0,0 +1,45 @@ +Imports Xdr + +Namespace Rpc.MessageProtocol + ''' + ''' Body of an RPC call + ''' http://tools.ietf.org/html/rfc5531#section-9 + ''' + Public Class call_body + ''' + ''' MUST be equal to 2 + ''' + + Public rpcvers As UInteger + + ''' + ''' the remote program + ''' + + Public prog As UInteger + + ''' + ''' version number + ''' + + Public vers As UInteger + + ''' + ''' the procedure within the remote program to be called + ''' + + Public proc As UInteger + + ''' + ''' authentication credential + ''' + + Public cred As opaque_auth + + ''' + ''' authentication verifier + ''' + + Public verf As opaque_auth + End Class +End Namespace diff --git a/Rpc/MessageProtocol/mismatch_info.vb b/Rpc/MessageProtocol/mismatch_info.vb new file mode 100644 index 0000000..8900a72 --- /dev/null +++ b/Rpc/MessageProtocol/mismatch_info.vb @@ -0,0 +1,21 @@ +Imports Xdr + +Namespace Rpc.MessageProtocol + ''' + ''' the lowest and highest version numbers of the remote program supported by the server + ''' http://tools.ietf.org/html/rfc5531#section-9 + ''' + Public Class mismatch_info + ''' + ''' lowest version number + ''' + + Public low As UInteger + + ''' + ''' highest version number + ''' + + Public high As UInteger + End Class +End Namespace diff --git a/Rpc/MessageProtocol/msg_type.vb b/Rpc/MessageProtocol/msg_type.vb new file mode 100644 index 0000000..94958f8 --- /dev/null +++ b/Rpc/MessageProtocol/msg_type.vb @@ -0,0 +1,17 @@ + +Namespace Rpc.MessageProtocol + ''' + ''' message type + ''' http://tools.ietf.org/html/rfc5531#section-9 + ''' + Public Enum msg_type As Integer + ''' + ''' call message + ''' + [CALL] = 0 + ''' + ''' reply message + ''' + REPLY = 1 + End Enum +End Namespace diff --git a/Rpc/MessageProtocol/opaque_auth.vb b/Rpc/MessageProtocol/opaque_auth.vb new file mode 100644 index 0000000..6b8865a --- /dev/null +++ b/Rpc/MessageProtocol/opaque_auth.vb @@ -0,0 +1,32 @@ +Imports Xdr + +Namespace Rpc.MessageProtocol + ''' + ''' + ''' http://tools.ietf.org/html/rfc5531#section-8.2 + ''' + Public Structure opaque_auth + ''' + ''' Null Authentication + ''' http://tools.ietf.org/html/rfc5531#section-10.1 + ''' + Public Shared ReadOnly None As opaque_auth = New opaque_auth() With { + .flavor = auth_flavor.AUTH_NONE, + .body = New Byte(-1) {} + } + + ''' + ''' Authentication flavor + ''' + + Public flavor As auth_flavor + + ''' + ''' The interpretation and semantics of the data contained within the + ''' authentication fields are specified by individual, independent + ''' authentication protocol specifications. + ''' + + Public body As Byte() + End Structure +End Namespace diff --git a/Rpc/MessageProtocol/reject_stat.vb b/Rpc/MessageProtocol/reject_stat.vb new file mode 100644 index 0000000..2d43923 --- /dev/null +++ b/Rpc/MessageProtocol/reject_stat.vb @@ -0,0 +1,17 @@ + +Namespace Rpc.MessageProtocol + ''' + ''' Reasons why a call message was rejected + ''' http://tools.ietf.org/html/rfc5531#section-9 + ''' + Public Enum reject_stat As Integer + ''' + ''' RPC version number != 2 + ''' + RPC_MISMATCH = 0 + ''' + ''' remote can't authenticate caller + ''' + AUTH_ERROR = 1 + End Enum +End Namespace diff --git a/Rpc/MessageProtocol/rejected_reply.vb b/Rpc/MessageProtocol/rejected_reply.vb new file mode 100644 index 0000000..8a8ca4f --- /dev/null +++ b/Rpc/MessageProtocol/rejected_reply.vb @@ -0,0 +1,27 @@ +Imports Xdr + +Namespace Rpc.MessageProtocol + ''' + ''' Reply to an RPC call that was rejected by the server + ''' http://tools.ietf.org/html/rfc5531#section-9 + ''' + Public Class rejected_reply + ''' + ''' Reasons why a call message was rejected + ''' + + Public rstat As reject_stat + + ''' + ''' the lowest and highest version numbers of the remote program supported by the server + ''' + <[Case](reject_stat.RPC_MISMATCH)> + Public mismatch_info As mismatch_info + + ''' + ''' the server rejects the identity of the caller + ''' + <[Case](reject_stat.AUTH_ERROR)> + Public astat As auth_stat + End Class +End Namespace diff --git a/Rpc/MessageProtocol/reply_body.vb b/Rpc/MessageProtocol/reply_body.vb new file mode 100644 index 0000000..832c08d --- /dev/null +++ b/Rpc/MessageProtocol/reply_body.vb @@ -0,0 +1,27 @@ +Imports Xdr + +Namespace Rpc.MessageProtocol + ''' + ''' Body of a reply to an RPC call + ''' http://tools.ietf.org/html/rfc5531#section-9 + ''' + Public Class reply_body + ''' + ''' A reply to a call message can take on two forms: the message was either accepted or rejected. + ''' + + Public stat As reply_stat + + ''' + ''' Reply to an RPC call that was accepted by the server + ''' + <[Case](reply_stat.MSG_ACCEPTED)> + Public areply As accepted_reply + + ''' + ''' Reply to an RPC call that was rejected by the server + ''' + <[Case](reply_stat.MSG_DENIED)> + Public rreply As rejected_reply + End Class +End Namespace diff --git a/Rpc/MessageProtocol/reply_stat.vb b/Rpc/MessageProtocol/reply_stat.vb new file mode 100644 index 0000000..f9fe65c --- /dev/null +++ b/Rpc/MessageProtocol/reply_stat.vb @@ -0,0 +1,17 @@ + +Namespace Rpc.MessageProtocol + ''' + ''' A reply to a call message can take on two forms: the message was either accepted or rejected. + ''' http://tools.ietf.org/html/rfc5531#section-9 + ''' + Public Enum reply_stat As Integer + ''' + ''' the message was accepted + ''' + MSG_ACCEPTED = 0 + ''' + ''' the message was rejected + ''' + MSG_DENIED = 1 + End Enum +End Namespace diff --git a/Rpc/MessageProtocol/rpc_msg.vb b/Rpc/MessageProtocol/rpc_msg.vb new file mode 100644 index 0000000..9ed9cbf --- /dev/null +++ b/Rpc/MessageProtocol/rpc_msg.vb @@ -0,0 +1,20 @@ +Imports Xdr + +Namespace Rpc.MessageProtocol + ''' + ''' RPC message + ''' http://tools.ietf.org/html/rfc5531#section-9 + ''' + Public Class rpc_msg + ''' + ''' transaction identifier + ''' + + Public xid As UInteger + ''' + ''' message body + ''' + + Public body As body + End Class +End Namespace diff --git a/Rpc/Rpc.vbproj b/Rpc/Rpc.vbproj new file mode 100644 index 0000000..dc39854 --- /dev/null +++ b/Rpc/Rpc.vbproj @@ -0,0 +1,130 @@ + + + + On + Debug + AnyCPU + 10.0.0 + 2.0 + {8F215850-6439-0311-0352-B0720952E0CE} + Library + + + Rpc + $(DefaultItemExcludes);$(ProjectDir)**\*.cs + v4.8 + + + + true + full + false + bin\Debug + DEBUG + prompt + 4 + false + true + Rpc.xml + false + + + 41999,42016,42017,42018,42019,42020,42021,42022,42032,42036 + true + true + true + + + none + false + bin\Release + prompt + 4 + false + false + + + 41999,42016,42017,42018,42019,42020,42021,42022,42032,42036 + Rpc.xml + + + Off + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {487d7c92-d05a-4908-bf81-e6baba0bf592} + BinaryData + + + {fecce1fd-e1d4-49e3-a668-60bb5e7aed99} + 47-dotnet_Microsoft.VisualBasic + + + \ No newline at end of file diff --git a/Rpc/RpcClient.vb b/Rpc/RpcClient.vb new file mode 100644 index 0000000..fb8a9c2 --- /dev/null +++ b/Rpc/RpcClient.vb @@ -0,0 +1,163 @@ +Imports System +Imports System.Collections.Generic +Imports System.Net +Imports System.Linq +Imports System.Threading +Imports System.Threading.Tasks +Imports NLog +Imports Rpc.Connectors +Imports Rpc.MessageProtocol + +Namespace Rpc + ''' + ''' The RPC client. + ''' + Public Class RpcClient + Implements IDisposable, IRpcClient, ITicketOwner + + Private Shared Log As Logger = LogManager.GetCurrentClassLogger() + Private ReadOnly _sessionCreater As Func(Of IRpcSession) + Private ReadOnly _sync As Object = New Object() + Private _session As IRpcSession = Nothing + Private _nextXid As Integer = 0 + Private _sendingInProgress As Boolean = False + Private _pendingRequests As LinkedList(Of ITicket) = New LinkedList(Of ITicket)() + + Friend Sub New(ByVal sessionCreater As Func(Of IRpcSession)) + _sessionCreater = sessionCreater + NewSession() + End Sub + ''' + ''' Create RPC client from TCP protocol. + ''' + ''' server address + ''' block size + Public Shared Function FromTcp(ByVal ep As IPEndPoint, ByVal Optional blockSize As Integer = 1024 * 4) As RpcClient + Log.Debug("Create RPC client for TCP server:{0}", ep) + Return New RpcClient(Function() New TcpSession(ep, blockSize)) + End Function + + ''' + ''' Create RPC client from UDP protocol. + ''' + ''' server address + Public Shared Function FromUdp(ByVal ep As IPEndPoint) As RpcClient + Log.Debug("Create RPC client for UDP server:{0}", ep) + Return New RpcClient(Function() New UdpSession(ep)) + End Function + + Private Function NewSession() As IRpcSession + Dim prevSession = _session + _session = _sessionCreater() + AddHandler _session.OnExcepted, AddressOf OnSessionExcepted + AddHandler _session.OnSended, AddressOf OnSessionMessageSended + Return prevSession + End Function + + Private Sub RemoveTicket(ByVal ticket As ITicket) Implements ITicketOwner.RemoveTicket + Dim sessionCopy As IRpcSession + + SyncLock _sync + If _pendingRequests.Remove(ticket) Then Return + sessionCopy = _session + End SyncLock + + sessionCopy.RemoveTicket(ticket) + End Sub + + ''' + ''' Close this connection and cancel all queued tasks + ''' + Public Sub Close() Implements IRpcClient.Close + Log.Debug("Close connector.") + Dim tickets As ITicket() + Dim prevSession As IRpcSession + + SyncLock _sync + tickets = _pendingRequests.ToArray() + _pendingRequests.Clear() + prevSession = NewSession() + End SyncLock + + Dim ex = New TaskCanceledException("close connector") + + For Each t In tickets + t.Except(ex) + Next + + prevSession.Close(ex) + End Sub + + ''' + ''' creates the task for the control request to the RPC server + ''' + Public Function CreateTask(Of TReq, TResp)(ByVal callBody As call_body, ByVal reqArgs As TReq, ByVal options As TaskCreationOptions, ByVal token As CancellationToken) As Task(Of TResp) Implements IRpcClient.CreateTask + Dim ticket As Ticket(Of TReq, TResp) = New Ticket(Of TReq, TResp)(Me, callBody, reqArgs, options, token) + + SyncLock _sync + If token.IsCancellationRequested Then Return ticket.Task + _pendingRequests.AddLast(ticket) + End SyncLock + + SendNextQueuedItem() + Return ticket.Task + End Function + + Private Sub SendNextQueuedItem() + Log.Trace("Send next queued item.") + Dim ticket As ITicket = Nothing + Dim sessionCopy As IRpcSession = Nothing + + SyncLock _sync + + If _sendingInProgress Then + Log.Debug("Already sending.") + Return + End If + + If _pendingRequests.Count = 0 Then + Log.Debug("Not pending requests to send.") + Return + End If + + sessionCopy = _session + _sendingInProgress = True + ticket = _pendingRequests.First.Value + _pendingRequests.RemoveFirst() + ticket.Xid = Math.Min(Interlocked.Increment(_nextXid), _nextXid - 1) + End SyncLock + + sessionCopy.AsyncSend(ticket) + End Sub + + Private Sub OnSessionExcepted(ByVal session As IRpcSession, ByVal ex As Exception) + Dim prevSession As IRpcSession + + SyncLock _sync + If session IsNot _session Then Return + _sendingInProgress = False + prevSession = NewSession() + End SyncLock + + Log.Debug("Session excepted: {0}", ex) + SendNextQueuedItem() + prevSession.Close(ex) + End Sub + + Private Sub OnSessionMessageSended(ByVal session As IRpcSession) + SyncLock _sync + If session IsNot _session Then Return + _sendingInProgress = False + End SyncLock + + SendNextQueuedItem() + End Sub + + ''' + ''' dispose this connection + ''' + Public Sub Dispose() Implements IDisposable.Dispose + Close() + End Sub + End Class +End Namespace diff --git a/Rpc/TcpStreaming/TcpReader.vb b/Rpc/TcpStreaming/TcpReader.vb new file mode 100644 index 0000000..e68c656 --- /dev/null +++ b/Rpc/TcpStreaming/TcpReader.vb @@ -0,0 +1,101 @@ +Imports System +Imports System.Collections.Generic +Imports Xdr + +Namespace Rpc.TcpStreaming + ''' + ''' parser of RPC message received from TCP protocol + ''' + Public Class TcpReader + Implements IByteReader + Implements IMsgReader + + Private _blocks As LinkedList(Of Byte()) = New LinkedList(Of Byte())() + Private _pos As Long = 0 + Private _currentBlock As Byte() = Nothing + Private _currentBlockSize As Long = 0 + + ''' + ''' parser of RPC message received from TCP protocol + ''' + Public Sub New() + End Sub + + ''' + ''' append the block of RPC message received from TCP protocol + ''' + Public Sub AppendBlock(ByVal block As Byte()) + If _currentBlock Is Nothing Then + _currentBlock = block + _currentBlockSize = _currentBlock.LongLength + Else + _blocks.AddLast(block) + End If + End Sub + + Private Sub NextBlock() + _pos = 0 + + If _blocks.First Is Nothing Then + _currentBlock = Nothing + _currentBlockSize = 0 + Else + _currentBlock = _blocks.First.Value + _currentBlockSize = _currentBlock.LongLength + _blocks.RemoveFirst() + End If + End Sub + + ''' + ''' read an array of length 'count' bytes + ''' + ''' required bytes + ''' + Public Function Read(ByVal count As UInteger) As Byte() Implements IByteReader.Read + Dim buffer = New Byte(count - 1) {} + Dim offset As Long = 0 + + While True + If _currentBlock Is Nothing Then Throw UnexpectedEnd() + Dim len = count - offset + + If len <= _currentBlockSize - _pos Then + Array.Copy(_currentBlock, _pos, buffer, offset, len) + _pos += len + If _pos >= _currentBlockSize Then NextBlock() + Return buffer + End If + + Array.Copy(_currentBlock, _pos, buffer, offset, _currentBlockSize - _pos) + offset += _currentBlockSize - _pos + NextBlock() + End While + + Throw New Exception("This exception will never happends!") + End Function + + ''' + ''' read one byte + ''' + Public Function Read() As Byte Implements IByteReader.Read + If _currentBlock Is Nothing Then Throw UnexpectedEnd() + Dim result = _currentBlock(_pos) + _pos += 1 + If _pos >= _currentBlockSize Then NextBlock() + Return result + End Function + + Private Shared Function UnexpectedEnd() As Exception + Return New RpcException("unexpected end of RPC message") + End Function + + ''' + ''' check the completeness of parsing + ''' + Public Sub CheckEmpty() Implements IMsgReader.CheckEmpty + If _currentBlock IsNot Nothing Then + Throw New RpcException("RPC message parsed not completely") + End If + End Sub + End Class +End Namespace diff --git a/Rpc/TcpStreaming/TcpWriter.vb b/Rpc/TcpStreaming/TcpWriter.vb new file mode 100644 index 0000000..d720fc2 --- /dev/null +++ b/Rpc/TcpStreaming/TcpWriter.vb @@ -0,0 +1,104 @@ +Imports System +Imports System.Collections.Generic +Imports Xdr + +Namespace Rpc.TcpStreaming + ''' + ''' generator TCP messages with record mark + ''' http://tools.ietf.org/html/rfc5531#section-11 + ''' + Public Class TcpWriter + Implements IByteWriter + + Private ReadOnly _maxBlock As Integer + Private _pos As Long + Private _currentBlock As Byte() + Private _blocks As LinkedList(Of Byte()) + + ''' + ''' generator TCP messages with record mark + ''' + ''' maximum block size in the TCP message + Public Sub New(ByVal maxBlock As Integer) + _maxBlock = maxBlock + _pos = 4 + _currentBlock = New Byte(_maxBlock - 1) {} + _blocks = New LinkedList(Of Byte())() + End Sub + + ''' + ''' write array of bytes + ''' + ''' + Public Sub Write(ByVal buffer As Byte()) Implements IByteWriter.Write + Dim offset As Long = 0 + + While True + Dim len = buffer.LongLength - offset + + If len <= _maxBlock - _pos Then + Array.Copy(buffer, offset, _currentBlock, _pos, len) + _pos += len + If _pos >= _maxBlock Then CreateNextBlock() + Return + End If + + Array.Copy(buffer, offset, _currentBlock, _pos, _maxBlock - _pos) + offset += _maxBlock - _pos + CreateNextBlock() + End While + End Sub + + ''' + ''' write byte + ''' + ''' + Public Sub Write(ByVal b As Byte) Implements IByteWriter.Write + _currentBlock(_pos) = b + _pos += 1 + If _pos >= _maxBlock Then CreateNextBlock() + End Sub + + Private Sub CreateNextBlock() + SetLenth(_currentBlock) + _blocks.AddLast(_currentBlock) + _currentBlock = New Byte(_maxBlock - 1) {} + _pos = 4 + End Sub + + Private Sub SetLastBlock() + Dim last = _blocks.Last + If last Is Nothing Then Return + Dim block = last.Value + block(0) = CByte(block(0) Or &H80) + End Sub + + Private Sub SetLenth(ByVal block As Byte()) + Dim len = block.Length - 4 + block(0) = CByte(len >> &H18 And &HfF) + block(1) = CByte(len >> &H10 And &HfF) + block(2) = CByte(len >> 8 And &HfF) + block(3) = CByte(len And &HfF) + End Sub + + ''' + ''' create the TCP message (the original object is destroyed) + ''' + ''' blocks of TCP message + Public Function Build() As LinkedList(Of Byte()) + If _pos <> 4 Then ' _currentBlock is not empty + Dim shortBlock = New Byte(_pos - 1) {} + Array.Copy(_currentBlock, shortBlock, _pos) + SetLenth(shortBlock) + _blocks.AddLast(shortBlock) + _pos = 4 + End If + + SetLastBlock() + Dim result = _blocks + _currentBlock = Nothing + _blocks = Nothing + Return result + End Function + End Class +End Namespace diff --git a/Rpc/Toolkit.vb b/Rpc/Toolkit.vb new file mode 100644 index 0000000..f54a855 --- /dev/null +++ b/Rpc/Toolkit.vb @@ -0,0 +1,120 @@ +Imports System +Imports System.Text +Imports Rpc.MessageProtocol +Imports Xdr +Imports System.Runtime.CompilerServices + +Namespace Rpc + ''' + ''' set of tools to work with RPC messages + ''' + Public Module Toolkit + Private ReadOnly _wb As WriteBuilder + Private ReadOnly _rb As ReadBuilder + + Sub New() + _wb = New WriteBuilder() + _rb = New ReadBuilder() + End Sub + + ''' + ''' create writer configured for RPC protocol + ''' + ''' + ''' + Public Function CreateWriter(ByVal writer As IByteWriter) As Writer + Return _wb.Create(writer) + End Function + + ''' + ''' create reader configured for RPC protocol + ''' + ''' + ''' + Public Function CreateReader(ByVal reader As IByteReader) As Reader + Return _rb.Create(reader) + End Function + + ''' + ''' To create a delegate output byte array to the log + ''' + Friend Function DumpToLog(ByVal frm As String, ByVal buffer As Byte()) As String + Return String.Format(frm, buffer.ToDisplay()) + End Function + + ''' + ''' convert byte array to text + ''' + ''' + ''' + + Public Function ToDisplay(ByVal buffer As Byte()) As String + ' example: + ' 12345678-12345678-12345678-12345678-12345678-12345678-12345678-12345678 12345678-1234... + + Dim sb As StringBuilder = New StringBuilder() + + For i = 0 To buffer.Length - 1 + + If i Mod 4 = 0 Then + If i Mod 32 = 0 Then + sb.AppendLine() + Else + sb.Append(" "c) + End If + End If + + sb.Append(buffer(i).ToString("X2")) + Next + + Return sb.ToString() + End Function + + ''' + ''' returns the description of the RPC message + ''' + ''' + ''' + Public Sub ReplyMessageValidate(ByVal msg As rpc_msg) + Try + If msg.body.mtype <> msg_type.REPLY Then Throw UnexpectedMessageType(msg.body.mtype) + Dim replyBody = msg.body.rbody + + If replyBody.stat = reply_stat.MSG_ACCEPTED Then + Dim du = replyBody.areply.reply_data + + Select Case du.stat + Case accept_stat.GARBAGE_ARGS + Throw GarbageArgs() + Case accept_stat.PROC_UNAVAIL + Throw ProcedureUnavalible(replyBody) + Case accept_stat.PROG_MISMATCH + Throw ProgramMismatch(replyBody, du.mismatch_info) + Case accept_stat.PROG_UNAVAIL + Throw ProgramUnavalible(replyBody) + Case accept_stat.SUCCESS + Return + Case accept_stat.SYSTEM_ERR + Throw SystemError(replyBody) + Case Else + Throw NoRFC5531("msg") + End Select + End If + + If replyBody.stat = reply_stat.MSG_DENIED Then + If replyBody.rreply.rstat = reject_stat.AUTH_ERROR Then + Throw AuthError(replyBody, replyBody.rreply.astat) + ElseIf replyBody.rreply.rstat = reject_stat.RPC_MISMATCH Then + Throw RpcVersionError(replyBody, replyBody.rreply.mismatch_info) + Else + Throw NoRFC5531("msg") + End If + End If + + Throw NoRFC5531("msg") + Catch __unusedNullReferenceException1__ As NullReferenceException + Throw NoRFC5531("msg") + End Try + End Sub + End Module +End Namespace diff --git a/Rpc/UdpDatagrams/UdpReader.vb b/Rpc/UdpDatagrams/UdpReader.vb new file mode 100644 index 0000000..3bc19be --- /dev/null +++ b/Rpc/UdpDatagrams/UdpReader.vb @@ -0,0 +1,64 @@ +Imports System +Imports Xdr + +Namespace Rpc.UdpDatagrams + ''' + ''' parser of RPC message received from UDP protocol + ''' + Public Class UdpReader + Implements IByteReader + Implements IMsgReader + + Private _pos As Integer = 0 + Private _leftToRead As Integer + Private _bytes As Byte() = Nothing + + ''' + ''' parser of RPC message received from UDP protocol + ''' + ''' UDP datagram + Public Sub New(ByVal bytes As Byte()) + _pos = 0 + _leftToRead = bytes.Length + _bytes = bytes + End Sub + + ''' + ''' read an array of length 'count' bytes + ''' + ''' required bytes + ''' + Public Function Read(ByVal count As UInteger) As Byte() Implements IByteReader.Read + If _leftToRead < count Then Throw UnexpectedEnd() + Dim icount As Integer = count + Dim result = New Byte(count - 1) {} + Array.Copy(_bytes, _pos, result, 0, count) + _pos += icount + _leftToRead -= icount + Return result + End Function + + ''' + ''' read one byte + ''' + ''' + Public Function Read() As Byte Implements IByteReader.Read + If _leftToRead < 1 Then Throw UnexpectedEnd() + Dim result = _bytes(_pos) + _pos += 1 + _leftToRead -= 1 + Return result + End Function + + Private Shared Function UnexpectedEnd() As Exception + Return New RpcException("unexpected end of RPC message") + End Function + + ''' + ''' check the completeness of parsing + ''' + Public Sub CheckEmpty() Implements IMsgReader.CheckEmpty + If _leftToRead > 0 Then Throw New RpcException("RPC message parsed not completely") + End Sub + End Class +End Namespace diff --git a/Rpc/UdpDatagrams/UdpWriter.vb b/Rpc/UdpDatagrams/UdpWriter.vb new file mode 100644 index 0000000..92b4f52 --- /dev/null +++ b/Rpc/UdpDatagrams/UdpWriter.vb @@ -0,0 +1,95 @@ +Imports System +Imports System.Collections.Generic +Imports Xdr + +Namespace Rpc.UdpDatagrams + ''' + ''' generator of UDP datagram + ''' + Public Class UdpWriter + Implements IByteWriter + + Private Const _max As Integer = 65535 + Private Const _blockSize As Integer = 1024 * 4 ' 4k + Private _pos As Integer + Private _totalSize As Integer + Private _currentBlock As Byte() + Private _blocks As LinkedList(Of Byte()) + + ''' + ''' generator of UDP datagram + ''' + Public Sub New() + _pos = 0 + _totalSize = 0 + _currentBlock = New Byte(4095) {} + _blocks = New LinkedList(Of Byte())() + End Sub + + ''' + ''' write array of bytes + ''' + ''' + Public Sub Write(ByVal buffer As Byte()) Implements IByteWriter.Write + _totalSize += buffer.Length + If _totalSize > _max Then Throw SizeIsExceeded() + Dim offset = 0 + + While True + Dim len = buffer.Length - offset + + If len <= _blockSize - _pos Then + Array.Copy(buffer, offset, _currentBlock, _pos, len) + _pos += len + If _pos >= _blockSize Then CreateNextBlock() + Return + End If + + Array.Copy(buffer, offset, _currentBlock, _pos, _blockSize - _pos) + offset += _blockSize - _pos + CreateNextBlock() + End While + End Sub + + ''' + ''' write byte + ''' + ''' + Public Sub Write(ByVal b As Byte) Implements IByteWriter.Write + _totalSize += 1 + If _totalSize > _max Then Throw SizeIsExceeded() + _currentBlock(_pos) = b + _pos += 1 + If _pos >= _blockSize Then CreateNextBlock() + End Sub + + Private Sub CreateNextBlock() + _blocks.AddLast(_currentBlock) + _currentBlock = New Byte(4095) {} + _pos = 0 + End Sub + + Private Shared Function SizeIsExceeded() As Exception + Return New RpcException("UDP datagram size is exceeded") + End Function + + ''' + ''' create the UDP datagram (the original object is destroyed) + ''' + ''' UDP datagram + Public Function Build() As Byte() + Dim result = New Byte(_totalSize - 1) {} + Dim offset = 0 + + For Each block In _blocks + Array.Copy(block, 0, result, offset, _blockSize) + offset += _blockSize + Next + + If _pos <> 0 Then Array.Copy(_currentBlock, 0, result, offset, _pos) ' _currentBlock is not empty + _currentBlock = Nothing + _blocks = Nothing + Return result + End Function + End Class +End Namespace