Merge remote-tracking branch 'SignalR/rybrande/release21ToSrc' into rybrande/Mondo2.1
This commit is contained in:
commit
5eae7ec020
|
|
@ -0,0 +1,57 @@
|
|||
[Oo]bj/
|
||||
[Bb]in/
|
||||
TestResults/
|
||||
.nuget/
|
||||
*.sln.ide/
|
||||
_ReSharper.*/
|
||||
packages/
|
||||
artifacts/
|
||||
PublishProfiles/
|
||||
.vs/
|
||||
*.user
|
||||
*.suo
|
||||
*.cache
|
||||
*.docstates
|
||||
_ReSharper.*
|
||||
nuget.exe
|
||||
*net45.csproj
|
||||
*net451.csproj
|
||||
*k10.csproj
|
||||
*.psess
|
||||
*.vsp
|
||||
*.pidb
|
||||
*.userprefs
|
||||
*DS_Store
|
||||
*.ncrunchsolution
|
||||
*.*sdf
|
||||
*.ipch
|
||||
project.lock.json
|
||||
runtimes/
|
||||
.build/
|
||||
.testPublish/
|
||||
launchSettings.json
|
||||
node_modules/
|
||||
npm-debug.log
|
||||
*.tmp
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
autobahnreports/
|
||||
site.min.css
|
||||
.idea/
|
||||
.vscode/
|
||||
dist/
|
||||
global.json
|
||||
BenchmarkDotNet.Artifacts/
|
||||
.rpt2_cache/
|
||||
*.orig
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
*.opensdf
|
||||
Debug/
|
||||
Release/
|
||||
ipch/
|
||||
*.vcxproj.user
|
||||
*.exe
|
||||
*.aps
|
||||
*.opendb
|
||||
*.db
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<Project>
|
||||
<Import
|
||||
Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), AspNetCoreSettings.props))\AspNetCoreSettings.props"
|
||||
Condition=" '$(CI)' != 'true' AND '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), AspNetCoreSettings.props))' != '' " />
|
||||
|
||||
<Import Project="version.props" />
|
||||
<Import Project="build\dependencies.props" />
|
||||
<Import Project="build\sources.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<Product>Microsoft ASP.NET Core</Product>
|
||||
<RepositoryUrl>https://github.com/aspnet/SignalR</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<RepositoryRoot>$(MSBuildThisFileDirectory)</RepositoryRoot>
|
||||
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)build\Key.snk</AssemblyOriginatorKeyFile>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<PublicSign Condition="'$(OS)' != 'Windows_NT'">true</PublicSign>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">$(MicrosoftNETCoreApp20PackageVersion)</RuntimeFrameworkVersion>
|
||||
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.1' ">$(MicrosoftNETCoreApp21PackageVersion)</RuntimeFrameworkVersion>
|
||||
<NETStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard2.0' ">$(NETStandardLibrary20PackageVersion)</NETStandardImplicitPackageVersion>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"Default": {
|
||||
"rules": [
|
||||
"DefaultCompositeRule"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
ASP.NET Core SignalR
|
||||
========
|
||||
|
||||
AppVeyor: [](https://ci.appveyor.com/project/aspnetci/signalr/branch/dev)
|
||||
|
||||
Travis: [](https://travis-ci.org/aspnet/SignalR)
|
||||
|
||||
ASP.NET Core SignalR is a new library for ASP.NET Core developers that makes it incredibly simple to add real-time web functionality to your applications. What is "real-time web" functionality? It's the ability to have your server-side code push content to the connected clients as it happens, in real-time.
|
||||
|
||||
You can watch an introductory presentation here - [Introducing ASP.NET Core SignalR](https://www.youtube.com/watch?v=fgTu-xYFDdM)
|
||||
|
||||
This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [Home](https://github.com/aspnet/home) repo.
|
||||
|
||||
## TypeScript Version
|
||||
|
||||
If you are encountering TypeScript definition issues with SignalR, please ensure you are using the latest version of TypeScript to compile your application. If the issue occurs in the latest TypeScript, please let us know.
|
||||
|
||||
When in doubt, check the version of TypeScript referenced by our [package.json](clients/ts/package.json) file. That version is the minimum TypeScript version expected to work with SignalR.
|
||||
|
||||
## Packages
|
||||
|
||||
You can install the latest released JavaScript client from npm with the following command:
|
||||
|
||||
```bash
|
||||
npm install @aspnet/signalr
|
||||
```
|
||||
|
||||
The `@aspnet/signalr` package (and it's dependencies) require NPM 5.6.0 or higher.
|
||||
|
||||
**NOTE:** Previous previews of the SignalR client library for JavaScript were named `@aspnet/signalr-client`. This has been deprecated as of Preview 1.
|
||||
|
||||
**IMPORTANT:** When using preview builds, you should always ensure you are using the same version of both the JavaScript client and the Server. The version numbers should align as they are produced in the same build process.
|
||||
|
||||
The CI build publishes the latest dev version of the JavaScript client to our dev npm registry as @aspnet/signalr. You can install the module as follows:
|
||||
|
||||
- Create an .npmrc file with the following line:
|
||||
`@aspnet:registry=https://dotnet.myget.org/f/aspnetcore-dev/npm/`
|
||||
- Run:
|
||||
`npm install @aspnet/signalr`
|
||||
|
||||
Alternatively, if you don't want to create the .npmrc file run the following commands:
|
||||
```
|
||||
npm install @aspnet/signalr --registry https://dotnet.myget.org/f/aspnetcore-dev/npm/
|
||||
```
|
||||
|
||||
We also have a MsgPack protocol library which is installed via:
|
||||
|
||||
```bash
|
||||
npm install @aspnet/signalr-protocol-msgpack
|
||||
```
|
||||
|
||||
## Deploying
|
||||
|
||||
Once you've installed the NPM modules, they will be located in the `node_modules/@aspnet/signalr` and `node_modules/@aspnet/signalr-protocol-msgpack` folders. If you are building a NodeJS application or using an ECMAScript module loader/bundler (such as [webpack](https://webpack.js.org)), you can load them directly. If you are building a browser application without using a module bundler, you can find UMD-compatible bundles in the `dist/browser` folder; minified versions are provided as well. Simply copy these to your project as appropriate and use a build task to keep them up-to-date.
|
||||
|
||||
## Building from source
|
||||
|
||||
To run a complete build on command line only, execute `build.cmd` or `build.sh` without arguments.
|
||||
|
||||
If this is your first time building *SignalR* please see the [Getting Started](docs/GettingStarted.md) for more information about project dependencies and other build-related information specific to *SignalR*.
|
||||
|
||||
See [developer documentation](https://github.com/aspnet/Home/wiki) for general information on building and contributing to this and other [aspnet](https://github.com/aspnet) repositories.
|
||||
|
|
@ -0,0 +1,247 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27110.0
|
||||
MinimumVisualStudioVersion = 15.0.26730.03
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{DA69F624-5398-4884-87E4-B816698CDE65}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
src\Directory.Build.props = src\Directory.Build.props
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{83B2C3EB-A3D8-4E6F-9A3C-A380B005EF31}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
benchmarkapps\BenchmarkServer\BenchmarkServer.csproj = benchmarkapps\BenchmarkServer\BenchmarkServer.csproj
|
||||
build\dependencies.props = build\dependencies.props
|
||||
Directory.Build.props = Directory.Build.props
|
||||
Directory.Build.targets = Directory.Build.targets
|
||||
build\Key.snk = build\Key.snk
|
||||
NuGet.config = NuGet.config
|
||||
build\repo.props = build\repo.props
|
||||
build\repo.targets = build\repo.targets
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{C4BC9889-B49F-41B6-806B-F84941B2549B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SignalRSamples", "samples\SignalRSamples\SignalRSamples.csproj", "{C4AEAB04-F341-4539-B6C0-52368FB4BF9E}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{6A35B453-52EC-48AF-89CA-D4A69800F131}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
test\Directory.Build.props = test\Directory.Build.props
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Http.Connections.Tests", "test\Microsoft.AspNetCore.Http.Connections.Tests\Microsoft.AspNetCore.Http.Connections.Tests.csproj", "{AAD719D5-5E31-4ED1-A60F-6EB92EFA66D9}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Core", "src\Microsoft.AspNetCore.SignalR.Core\Microsoft.AspNetCore.SignalR.Core.csproj", "{42E76F87-92B6-45AB-BF07-6B811C0F2CAC}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Redis", "src\Microsoft.AspNetCore.SignalR.Redis\Microsoft.AspNetCore.SignalR.Redis.csproj", "{59319B72-38BE-4041-8E5C-FF6938874CE8}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SocialWeather", "samples\SocialWeather\SocialWeather.csproj", "{8D789F94-CB74-45FD-ACE7-92AF6E55042E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Tests", "test\Microsoft.AspNetCore.SignalR.Tests\Microsoft.AspNetCore.SignalR.Tests.csproj", "{1CE2B3BE-056C-41E3-A5F5-6A1EF1D288BA}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClientSample", "samples\ClientSample\ClientSample.csproj", "{BA99C2A1-48F9-4FA5-B95A-9687A73B7CC9}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebSocketSample", "samples\WebSocketSample\WebSocketSample.csproj", "{EE790D50-C632-46B9-A430-06FA2F2FDCD7}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Client.Tests", "test\Microsoft.AspNetCore.SignalR.Client.Tests\Microsoft.AspNetCore.SignalR.Client.Tests.csproj", "{B19C15A5-F5EA-4CA7-936B-1166ABEE35C4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Common", "src\Microsoft.AspNetCore.SignalR.Common\Microsoft.AspNetCore.SignalR.Common.csproj", "{E37324FF-6BAF-4243-BA80-7C024CF5F29D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Client.Core", "src\Microsoft.AspNetCore.SignalR.Client.Core\Microsoft.AspNetCore.SignalR.Client.Core.csproj", "{354335AB-CEE9-4434-A641-78058F6EFE56}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Client.FunctionalTests", "test\Microsoft.AspNetCore.SignalR.Client.FunctionalTests\Microsoft.AspNetCore.SignalR.Client.FunctionalTests.csproj", "{455B68D2-C5B6-4BF4-A685-964B07AFAAF8}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "clients", "clients", "{3A76C5A2-79ED-49BC-8BDC-6A3A766FFA1B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Microbenchmarks", "benchmarks\Microsoft.AspNetCore.SignalR.Microbenchmarks\Microsoft.AspNetCore.SignalR.Microbenchmarks.csproj", "{96771B3F-4D18-41A7-A75B-FF38E76AAC89}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Common.Tests", "test\Microsoft.AspNetCore.SignalR.Common.Tests\Microsoft.AspNetCore.SignalR.Common.Tests.csproj", "{75E342F6-5445-4E7E-9143-6D9AE62C2B1E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR", "src\Microsoft.AspNetCore.SignalR\Microsoft.AspNetCore.SignalR.csproj", "{FD80BB0F-0876-4F11-8D84-6657C8EF84CA}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Http.Connections", "src\Microsoft.AspNetCore.Http.Connections\Microsoft.AspNetCore.Http.Connections.csproj", "{9E403E93-3284-486F-9A5F-1E15FCE426A5}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Http.Connections.Client", "src\Microsoft.AspNetCore.Http.Connections.Client\Microsoft.AspNetCore.Http.Connections.Client.csproj", "{B0243F99-2D3F-4CC6-AD71-E3F891B64724}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Http.Connections.Common", "src\Microsoft.AspNetCore.Http.Connections.Common\Microsoft.AspNetCore.Http.Connections.Common.csproj", "{E081EE41-D95F-4AD2-BC0B-4B562C0A2A47}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarks", "benchmarks", "{8A4582C8-DC59-4B61-BCE7-119FBAA99EFB}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Client", "src\Microsoft.AspNetCore.SignalR.Client\Microsoft.AspNetCore.SignalR.Client.csproj", "{BE982591-F4BB-42D9-ABD4-A5D44C65971E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Redis.Tests", "test\Microsoft.AspNetCore.SignalR.Redis.Tests\Microsoft.AspNetCore.SignalR.Redis.Tests.csproj", "{0B083AE6-86CA-4E0B-AE02-59154D1FD005}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JwtSample", "samples\JwtSample\JwtSample.csproj", "{6A7491D3-3C97-49BD-A71C-433AED657F30}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JwtClientSample", "samples\JwtClientSample\JwtClientSample.csproj", "{1A953296-E869-4DE2-A693-FD5FCDE27057}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Tests.Utils", "test\Microsoft.AspNetCore.SignalR.Tests.Utils\Microsoft.AspNetCore.SignalR.Tests.Utils.csproj", "{0A0A6135-EA24-4307-95C2-CE1B7E164A5E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Protocols.MessagePack", "src\Microsoft.AspNetCore.SignalR.Protocols.MessagePack\Microsoft.AspNetCore.SignalR.Protocols.MessagePack.csproj", "{55DB4B6F-12E5-4A27-97F4-E97E135470FF}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FunctionalTests", "clients\ts\FunctionalTests\FunctionalTests.csproj", "{D0C7B22E-B0B6-4D62-BF7D-79EE4AAF1981}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Protocols.Json", "src\Microsoft.AspNetCore.SignalR.Protocols.Json\Microsoft.AspNetCore.SignalR.Protocols.Json.csproj", "{896FA5EE-63A5-4EAC-9F09-346584BB4830}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BenchmarkServer", "benchmarkapps\BenchmarkServer\BenchmarkServer.csproj", "{8C75AC94-C980-4FE1-9F79-6CED3C8665CE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Crankier", "benchmarkapps\Crankier\Crankier.csproj", "{8D3E3E7D-452B-44F4-86CA-111003EA11ED}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarkapps", "benchmarkapps", "{43F352F3-4E2B-4ED7-901B-36E6671251F5}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{C4AEAB04-F341-4539-B6C0-52368FB4BF9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C4AEAB04-F341-4539-B6C0-52368FB4BF9E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C4AEAB04-F341-4539-B6C0-52368FB4BF9E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C4AEAB04-F341-4539-B6C0-52368FB4BF9E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AAD719D5-5E31-4ED1-A60F-6EB92EFA66D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AAD719D5-5E31-4ED1-A60F-6EB92EFA66D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AAD719D5-5E31-4ED1-A60F-6EB92EFA66D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AAD719D5-5E31-4ED1-A60F-6EB92EFA66D9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{42E76F87-92B6-45AB-BF07-6B811C0F2CAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{42E76F87-92B6-45AB-BF07-6B811C0F2CAC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{42E76F87-92B6-45AB-BF07-6B811C0F2CAC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{42E76F87-92B6-45AB-BF07-6B811C0F2CAC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{59319B72-38BE-4041-8E5C-FF6938874CE8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{59319B72-38BE-4041-8E5C-FF6938874CE8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{59319B72-38BE-4041-8E5C-FF6938874CE8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{59319B72-38BE-4041-8E5C-FF6938874CE8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8D789F94-CB74-45FD-ACE7-92AF6E55042E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8D789F94-CB74-45FD-ACE7-92AF6E55042E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8D789F94-CB74-45FD-ACE7-92AF6E55042E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8D789F94-CB74-45FD-ACE7-92AF6E55042E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1CE2B3BE-056C-41E3-A5F5-6A1EF1D288BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1CE2B3BE-056C-41E3-A5F5-6A1EF1D288BA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1CE2B3BE-056C-41E3-A5F5-6A1EF1D288BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1CE2B3BE-056C-41E3-A5F5-6A1EF1D288BA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BA99C2A1-48F9-4FA5-B95A-9687A73B7CC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BA99C2A1-48F9-4FA5-B95A-9687A73B7CC9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BA99C2A1-48F9-4FA5-B95A-9687A73B7CC9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BA99C2A1-48F9-4FA5-B95A-9687A73B7CC9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EE790D50-C632-46B9-A430-06FA2F2FDCD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EE790D50-C632-46B9-A430-06FA2F2FDCD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EE790D50-C632-46B9-A430-06FA2F2FDCD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EE790D50-C632-46B9-A430-06FA2F2FDCD7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B19C15A5-F5EA-4CA7-936B-1166ABEE35C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B19C15A5-F5EA-4CA7-936B-1166ABEE35C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B19C15A5-F5EA-4CA7-936B-1166ABEE35C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B19C15A5-F5EA-4CA7-936B-1166ABEE35C4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E37324FF-6BAF-4243-BA80-7C024CF5F29D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E37324FF-6BAF-4243-BA80-7C024CF5F29D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E37324FF-6BAF-4243-BA80-7C024CF5F29D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E37324FF-6BAF-4243-BA80-7C024CF5F29D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{354335AB-CEE9-4434-A641-78058F6EFE56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{354335AB-CEE9-4434-A641-78058F6EFE56}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{354335AB-CEE9-4434-A641-78058F6EFE56}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{354335AB-CEE9-4434-A641-78058F6EFE56}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{455B68D2-C5B6-4BF4-A685-964B07AFAAF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{455B68D2-C5B6-4BF4-A685-964B07AFAAF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{455B68D2-C5B6-4BF4-A685-964B07AFAAF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{455B68D2-C5B6-4BF4-A685-964B07AFAAF8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{96771B3F-4D18-41A7-A75B-FF38E76AAC89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{96771B3F-4D18-41A7-A75B-FF38E76AAC89}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{96771B3F-4D18-41A7-A75B-FF38E76AAC89}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{96771B3F-4D18-41A7-A75B-FF38E76AAC89}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{75E342F6-5445-4E7E-9143-6D9AE62C2B1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{75E342F6-5445-4E7E-9143-6D9AE62C2B1E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{75E342F6-5445-4E7E-9143-6D9AE62C2B1E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{75E342F6-5445-4E7E-9143-6D9AE62C2B1E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FD80BB0F-0876-4F11-8D84-6657C8EF84CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FD80BB0F-0876-4F11-8D84-6657C8EF84CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FD80BB0F-0876-4F11-8D84-6657C8EF84CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FD80BB0F-0876-4F11-8D84-6657C8EF84CA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9E403E93-3284-486F-9A5F-1E15FCE426A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9E403E93-3284-486F-9A5F-1E15FCE426A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9E403E93-3284-486F-9A5F-1E15FCE426A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9E403E93-3284-486F-9A5F-1E15FCE426A5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B0243F99-2D3F-4CC6-AD71-E3F891B64724}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B0243F99-2D3F-4CC6-AD71-E3F891B64724}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B0243F99-2D3F-4CC6-AD71-E3F891B64724}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B0243F99-2D3F-4CC6-AD71-E3F891B64724}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E081EE41-D95F-4AD2-BC0B-4B562C0A2A47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E081EE41-D95F-4AD2-BC0B-4B562C0A2A47}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E081EE41-D95F-4AD2-BC0B-4B562C0A2A47}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E081EE41-D95F-4AD2-BC0B-4B562C0A2A47}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BE982591-F4BB-42D9-ABD4-A5D44C65971E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BE982591-F4BB-42D9-ABD4-A5D44C65971E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BE982591-F4BB-42D9-ABD4-A5D44C65971E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BE982591-F4BB-42D9-ABD4-A5D44C65971E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0B083AE6-86CA-4E0B-AE02-59154D1FD005}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0B083AE6-86CA-4E0B-AE02-59154D1FD005}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0B083AE6-86CA-4E0B-AE02-59154D1FD005}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0B083AE6-86CA-4E0B-AE02-59154D1FD005}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6A7491D3-3C97-49BD-A71C-433AED657F30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6A7491D3-3C97-49BD-A71C-433AED657F30}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6A7491D3-3C97-49BD-A71C-433AED657F30}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6A7491D3-3C97-49BD-A71C-433AED657F30}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1A953296-E869-4DE2-A693-FD5FCDE27057}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1A953296-E869-4DE2-A693-FD5FCDE27057}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1A953296-E869-4DE2-A693-FD5FCDE27057}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1A953296-E869-4DE2-A693-FD5FCDE27057}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0A0A6135-EA24-4307-95C2-CE1B7E164A5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0A0A6135-EA24-4307-95C2-CE1B7E164A5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0A0A6135-EA24-4307-95C2-CE1B7E164A5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0A0A6135-EA24-4307-95C2-CE1B7E164A5E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{55DB4B6F-12E5-4A27-97F4-E97E135470FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{55DB4B6F-12E5-4A27-97F4-E97E135470FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{55DB4B6F-12E5-4A27-97F4-E97E135470FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{55DB4B6F-12E5-4A27-97F4-E97E135470FF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D0C7B22E-B0B6-4D62-BF7D-79EE4AAF1981}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D0C7B22E-B0B6-4D62-BF7D-79EE4AAF1981}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D0C7B22E-B0B6-4D62-BF7D-79EE4AAF1981}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D0C7B22E-B0B6-4D62-BF7D-79EE4AAF1981}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{896FA5EE-63A5-4EAC-9F09-346584BB4830}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{896FA5EE-63A5-4EAC-9F09-346584BB4830}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{896FA5EE-63A5-4EAC-9F09-346584BB4830}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{896FA5EE-63A5-4EAC-9F09-346584BB4830}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8C75AC94-C980-4FE1-9F79-6CED3C8665CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8C75AC94-C980-4FE1-9F79-6CED3C8665CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8C75AC94-C980-4FE1-9F79-6CED3C8665CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8C75AC94-C980-4FE1-9F79-6CED3C8665CE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8D3E3E7D-452B-44F4-86CA-111003EA11ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8D3E3E7D-452B-44F4-86CA-111003EA11ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8D3E3E7D-452B-44F4-86CA-111003EA11ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8D3E3E7D-452B-44F4-86CA-111003EA11ED}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{C4AEAB04-F341-4539-B6C0-52368FB4BF9E} = {C4BC9889-B49F-41B6-806B-F84941B2549B}
|
||||
{AAD719D5-5E31-4ED1-A60F-6EB92EFA66D9} = {6A35B453-52EC-48AF-89CA-D4A69800F131}
|
||||
{42E76F87-92B6-45AB-BF07-6B811C0F2CAC} = {DA69F624-5398-4884-87E4-B816698CDE65}
|
||||
{59319B72-38BE-4041-8E5C-FF6938874CE8} = {DA69F624-5398-4884-87E4-B816698CDE65}
|
||||
{8D789F94-CB74-45FD-ACE7-92AF6E55042E} = {C4BC9889-B49F-41B6-806B-F84941B2549B}
|
||||
{1CE2B3BE-056C-41E3-A5F5-6A1EF1D288BA} = {6A35B453-52EC-48AF-89CA-D4A69800F131}
|
||||
{BA99C2A1-48F9-4FA5-B95A-9687A73B7CC9} = {C4BC9889-B49F-41B6-806B-F84941B2549B}
|
||||
{EE790D50-C632-46B9-A430-06FA2F2FDCD7} = {C4BC9889-B49F-41B6-806B-F84941B2549B}
|
||||
{B19C15A5-F5EA-4CA7-936B-1166ABEE35C4} = {6A35B453-52EC-48AF-89CA-D4A69800F131}
|
||||
{E37324FF-6BAF-4243-BA80-7C024CF5F29D} = {DA69F624-5398-4884-87E4-B816698CDE65}
|
||||
{354335AB-CEE9-4434-A641-78058F6EFE56} = {DA69F624-5398-4884-87E4-B816698CDE65}
|
||||
{455B68D2-C5B6-4BF4-A685-964B07AFAAF8} = {6A35B453-52EC-48AF-89CA-D4A69800F131}
|
||||
{96771B3F-4D18-41A7-A75B-FF38E76AAC89} = {8A4582C8-DC59-4B61-BCE7-119FBAA99EFB}
|
||||
{75E342F6-5445-4E7E-9143-6D9AE62C2B1E} = {6A35B453-52EC-48AF-89CA-D4A69800F131}
|
||||
{FD80BB0F-0876-4F11-8D84-6657C8EF84CA} = {DA69F624-5398-4884-87E4-B816698CDE65}
|
||||
{9E403E93-3284-486F-9A5F-1E15FCE426A5} = {DA69F624-5398-4884-87E4-B816698CDE65}
|
||||
{B0243F99-2D3F-4CC6-AD71-E3F891B64724} = {DA69F624-5398-4884-87E4-B816698CDE65}
|
||||
{E081EE41-D95F-4AD2-BC0B-4B562C0A2A47} = {DA69F624-5398-4884-87E4-B816698CDE65}
|
||||
{BE982591-F4BB-42D9-ABD4-A5D44C65971E} = {DA69F624-5398-4884-87E4-B816698CDE65}
|
||||
{0B083AE6-86CA-4E0B-AE02-59154D1FD005} = {6A35B453-52EC-48AF-89CA-D4A69800F131}
|
||||
{6A7491D3-3C97-49BD-A71C-433AED657F30} = {C4BC9889-B49F-41B6-806B-F84941B2549B}
|
||||
{1A953296-E869-4DE2-A693-FD5FCDE27057} = {C4BC9889-B49F-41B6-806B-F84941B2549B}
|
||||
{0A0A6135-EA24-4307-95C2-CE1B7E164A5E} = {6A35B453-52EC-48AF-89CA-D4A69800F131}
|
||||
{55DB4B6F-12E5-4A27-97F4-E97E135470FF} = {DA69F624-5398-4884-87E4-B816698CDE65}
|
||||
{D0C7B22E-B0B6-4D62-BF7D-79EE4AAF1981} = {3A76C5A2-79ED-49BC-8BDC-6A3A766FFA1B}
|
||||
{896FA5EE-63A5-4EAC-9F09-346584BB4830} = {DA69F624-5398-4884-87E4-B816698CDE65}
|
||||
{8C75AC94-C980-4FE1-9F79-6CED3C8665CE} = {43F352F3-4E2B-4ED7-901B-36E6671251F5}
|
||||
{8D3E3E7D-452B-44F4-86CA-111003EA11ED} = {43F352F3-4E2B-4ED7-901B-36E6671251F5}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {7945A4E4-ACDB-4F6E-95CA-6AC6E7C2CD59}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
@ -0,0 +1,432 @@
|
|||
.NET Core uses third-party libraries or other resources that may be
|
||||
distributed under licenses different than the .NET Core software.
|
||||
|
||||
In the event that we accidentally failed to list a required notice, please
|
||||
bring it to our attention. Post an issue or email us:
|
||||
|
||||
dotnet@microsoft.com
|
||||
|
||||
The attached notices are provided for information only.
|
||||
|
||||
|
||||
License notice for googletest
|
||||
------------------------------------
|
||||
|
||||
"Copyright 2008, Google Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
|
||||
|
||||
License notice for es6-promise
|
||||
------------------------------------------------------------------------------
|
||||
"Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE."
|
||||
|
||||
|
||||
License notice for buffer
|
||||
------------------------------------------------------------------------------
|
||||
"The MIT License (MIT)
|
||||
|
||||
Copyright (c) Feross Aboukhadijeh, and other contributors.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE."
|
||||
|
||||
|
||||
License notice for base64-js
|
||||
------------------------------------------------------------------------------
|
||||
"The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE."
|
||||
|
||||
|
||||
License notice for ieee754
|
||||
------------------------------------------------------------------------------
|
||||
"Copyright (c) 2008, Fair Oaks Labs, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE."
|
||||
|
||||
|
||||
License notice for msgpack5
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
"The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Matteo Collina
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE."
|
||||
|
||||
|
||||
License notice for bl
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
"The MIT License (MIT)
|
||||
=====================
|
||||
|
||||
Copyright (c) 2013-2016 bl contributors
|
||||
----------------------------------
|
||||
|
||||
*bl contributors listed at <https://github.com/rvagg/bl#contributors>*
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
|
||||
|
||||
|
||||
License notice for inherits
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
"The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE."
|
||||
|
||||
|
||||
License notice for readable-stream
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
"Node.js is licensed for use as follows:
|
||||
|
||||
"""
|
||||
Copyright Node.js contributors. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
"""
|
||||
|
||||
This license applies to parts of Node.js originating from the
|
||||
https://github.com/joyent/node repository:
|
||||
|
||||
"""
|
||||
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
""""
|
||||
|
||||
|
||||
License notice for core-util-is
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
"Copyright Node.js contributors. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE."
|
||||
|
||||
|
||||
License notice for isarray
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
"(MIT)
|
||||
|
||||
Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
|
||||
|
||||
|
||||
License notice for process-nextick-args
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
"# Copyright (c) 2015 Calvin Metcalf
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
**THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.**"
|
||||
|
||||
|
||||
License notice for string_decoder
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
"Node.js is licensed for use as follows:
|
||||
|
||||
"""
|
||||
Copyright Node.js contributors. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
"""
|
||||
|
||||
This license applies to parts of Node.js originating from the
|
||||
https://github.com/joyent/node repository:
|
||||
|
||||
"""
|
||||
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
""""
|
||||
|
||||
|
||||
License notice for util-deprecate
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
"(The MIT License)
|
||||
|
||||
Copyright (c) 2014 Nathan Rajlich <nathan@tootallnate.net>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE."
|
||||
|
||||
|
||||
License notice for safe-buffer
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
"The MIT License (MIT)
|
||||
|
||||
Copyright (c) Feross Aboukhadijeh
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE."
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<!-- SignalR is versioned 1.0 alongside the 2.1 version of AspNetCore.All, this converts the .All version to the SignalR version -->
|
||||
<MessagePackPackageVersion Condition=" '$(BenchmarksTargetFramework)' != '' ">$([System.String]::Copy($(MicrosoftAspNetCoreAllPackageVersion)).Replace('2.1', '1.0'))</MessagePackPackageVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="wwwroot\" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- These references are used when running locally -->
|
||||
<ItemGroup Condition="'$(BenchmarksTargetFramework)' == ''">
|
||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR\Microsoft.AspNetCore.SignalR.csproj" />
|
||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Protocols.MessagePack\Microsoft.AspNetCore.SignalR.Protocols.MessagePack.csproj" />
|
||||
|
||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="$(MicrosoftExtensionsConfigurationCommandLinePackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- These references are used when running on the Benchmarks Server -->
|
||||
<ItemGroup Condition="'$(BenchmarksTargetFramework)' != ''">
|
||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="$(MicrosoftAspNetCoreAllPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="$(MessagePackPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
|
||||
namespace BenchmarkServer.Hubs
|
||||
{
|
||||
public class EchoHub : Hub
|
||||
{
|
||||
public async Task Broadcast(int duration)
|
||||
{
|
||||
var sent = 0;
|
||||
try
|
||||
{
|
||||
var t = new CancellationTokenSource();
|
||||
t.CancelAfter(TimeSpan.FromSeconds(duration));
|
||||
while (!t.IsCancellationRequested && !Context.ConnectionAborted.IsCancellationRequested)
|
||||
{
|
||||
await Clients.All.SendAsync("send", DateTime.UtcNow);
|
||||
sent++;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
Console.WriteLine("Broadcast exited: Sent {0} messages", sent);
|
||||
}
|
||||
|
||||
public Task Echo(DateTime time)
|
||||
{
|
||||
return Clients.Client(Context.ConnectionId).SendAsync("send", time);
|
||||
}
|
||||
|
||||
public Task EchoAll(DateTime time)
|
||||
{
|
||||
return Clients.All.SendAsync("send", time);
|
||||
}
|
||||
|
||||
public void SendPayload(string payload)
|
||||
{
|
||||
// Dump the payload, we don't care
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace BenchmarkServer
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine($"Process ID: {Process.GetCurrentProcess().Id}");
|
||||
|
||||
var config = new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables(prefix: "ASPNETCORE_")
|
||||
.AddCommandLine(args)
|
||||
.Build();
|
||||
|
||||
var host = new WebHostBuilder()
|
||||
.UseConfiguration(config)
|
||||
.ConfigureLogging(loggerFactory =>
|
||||
{
|
||||
if (Enum.TryParse(config["LogLevel"], out LogLevel logLevel))
|
||||
{
|
||||
loggerFactory.AddConsole().SetMinimumLevel(logLevel);
|
||||
}
|
||||
})
|
||||
.UseKestrel()
|
||||
.UseStartup<Startup>();
|
||||
|
||||
host.Build().Run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
## Purpose
|
||||
|
||||
This project is to assist in Benchmarking SignalR.
|
||||
It makes it easier to test local changes than having the App in the Benchmarks repo by letting us make changes in signalr branches and using the example commandline below to run the benchmarks against our branches.
|
||||
|
||||
The SignalRWorker that runs against this server is located at https://github.com/aspnet/benchmarks/blob/dev/src/BenchmarksWorkers/Workers/SignalRWorker.cs.
|
||||
|
||||
## Usage
|
||||
|
||||
1. Push changes you would like to test to a branch on GitHub
|
||||
2. Clone aspnet/benchmarks repo to your machine or install the global BenchmarksDriver tool https://www.nuget.org/packages/BenchmarksDriver/
|
||||
3. If cloned go to the BenchmarksDriver project
|
||||
4. Use the following command as a guideline for running a test using your changes
|
||||
|
||||
`benchmarks --server <server-endpoint> --client <client-endpoint> -p TransportType=WebSockets -p HubProtocol=messagepack -j https://raw.githubusercontent.com/aspnet/SignalR/dev/benchmarks/BenchmarkServer/signalr.json`
|
||||
|
||||
5. For more info/commands see https://github.com/aspnet/benchmarks/blob/dev/src/BenchmarksDriver/README.md
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using BenchmarkServer.Hubs;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace BenchmarkServer
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddSignalR()
|
||||
.AddMessagePackProtocol();
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
|
||||
{
|
||||
app.UseSignalR(routes =>
|
||||
{
|
||||
routes.MapHub<EchoHub>("/echo");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"Default": {
|
||||
"Client": "SignalR",
|
||||
"Source": {
|
||||
"Repository": "https://github.com/aspnet/SignalR.git",
|
||||
"BranchOrCommit": "dev",
|
||||
"Project": "benchmarkapps/BenchmarkServer/BenchmarkServer.csproj"
|
||||
},
|
||||
"Connections": 10,
|
||||
"Duration": 20,
|
||||
"Warmup": 2,
|
||||
"Path": "/echo"
|
||||
},
|
||||
"SignalRBroadcast": {
|
||||
"ClientProperties": { "Scenario": "broadcast" }
|
||||
},
|
||||
"SignalREcho": {
|
||||
"ClientProperties": { "Scenario": "echo" }
|
||||
},
|
||||
"SignalREchoAll": {
|
||||
"ClientProperties": { "Scenario": "echoAll" }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,302 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http.Connections;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Crankier
|
||||
{
|
||||
public class Agent : IAgent
|
||||
{
|
||||
private readonly bool _workerWaitForDebugger;
|
||||
private readonly string _hostName;
|
||||
|
||||
private readonly ConcurrentDictionary<int, AgentWorker> _workers;
|
||||
private readonly string _executable;
|
||||
|
||||
public Agent(string executable = null, bool workerWaitForDebugger = false)
|
||||
{
|
||||
_workerWaitForDebugger = workerWaitForDebugger;
|
||||
_executable = executable ?? GetMyExecutable();
|
||||
|
||||
Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));
|
||||
|
||||
_hostName = Dns.GetHostName();
|
||||
|
||||
_workers = new ConcurrentDictionary<int, AgentWorker>();
|
||||
|
||||
Trace.WriteLine("Agent created");
|
||||
}
|
||||
|
||||
private string GetMyExecutable()
|
||||
{
|
||||
var mainModuleFile = Process.GetCurrentProcess().MainModule.FileName;
|
||||
if (Path.GetFileNameWithoutExtension(mainModuleFile).Equals("dotnet"))
|
||||
{
|
||||
// We're running in 'dotnet'
|
||||
return Path.Combine(AppContext.BaseDirectory, $"{typeof(Program).Assembly.GetName().Name}.dll");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Standalone deployment
|
||||
return mainModuleFile;
|
||||
}
|
||||
}
|
||||
|
||||
public IRunner Runner { get; set; }
|
||||
|
||||
public string TargetAddress { get; private set; }
|
||||
|
||||
public int TotalConnectionsRequested { get; private set; }
|
||||
|
||||
public bool ApplyingLoad { get; private set; }
|
||||
|
||||
public AgentHeartbeatInformation GetHeartbeatInformation()
|
||||
{
|
||||
return new AgentHeartbeatInformation
|
||||
{
|
||||
HostName = _hostName,
|
||||
TargetAddress = TargetAddress,
|
||||
TotalConnectionsRequested = TotalConnectionsRequested,
|
||||
ApplyingLoad = ApplyingLoad,
|
||||
Workers = _workers.Select(worker => worker.Value.GetHeartbeatInformation()).ToList()
|
||||
};
|
||||
}
|
||||
|
||||
public Dictionary<int, StatusInformation> GetWorkerStatus()
|
||||
{
|
||||
return _workers.Values.ToDictionary(
|
||||
k => k.Id,
|
||||
v => v.StatusInformation);
|
||||
}
|
||||
|
||||
private AgentWorker CreateWorker()
|
||||
{
|
||||
var fileName = _executable;
|
||||
var arguments = $"worker --agent {Process.GetCurrentProcess().Id}";
|
||||
if (_workerWaitForDebugger)
|
||||
{
|
||||
arguments += " --wait-for-debugger";
|
||||
}
|
||||
if (fileName.EndsWith(".dll"))
|
||||
{
|
||||
// Execute using dotnet.exe
|
||||
fileName = GetDotNetHost();
|
||||
arguments = _executable + " " + arguments;
|
||||
}
|
||||
|
||||
var startInfo = new ProcessStartInfo()
|
||||
{
|
||||
FileName = fileName,
|
||||
Arguments = arguments,
|
||||
CreateNoWindow = true,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardInput = true,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true
|
||||
};
|
||||
|
||||
var worker = new AgentWorker(startInfo, this);
|
||||
|
||||
worker.StatusInformation = new StatusInformation();
|
||||
|
||||
worker.Start();
|
||||
|
||||
worker.OnError += OnError;
|
||||
worker.OnExit += OnExit;
|
||||
|
||||
_workers.TryAdd(worker.Id, worker);
|
||||
|
||||
return worker;
|
||||
}
|
||||
|
||||
private static string GetDotNetHost() => RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "dotnet.exe" : "dotnet";
|
||||
|
||||
private async Task StartWorker(int id, string targetAddress, HttpTransportType transportType, int numberOfConnectionsPerWorker)
|
||||
{
|
||||
if (_workers.TryGetValue(id, out var worker))
|
||||
{
|
||||
await worker.Worker.ConnectAsync(targetAddress, transportType, numberOfConnectionsPerWorker);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task StartWorkersAsync(string targetAddress, int numberOfWorkers, HttpTransportType transportType, int numberOfConnections)
|
||||
{
|
||||
TargetAddress = targetAddress;
|
||||
TotalConnectionsRequested = numberOfConnections;
|
||||
|
||||
var connectionsPerWorker = numberOfConnections / numberOfWorkers;
|
||||
var remainingConnections = numberOfConnections % numberOfWorkers;
|
||||
|
||||
async Task RunWorker(int index, AgentWorker worker)
|
||||
{
|
||||
if (index == 0)
|
||||
{
|
||||
await StartWorker(worker.Id, targetAddress, transportType, connectionsPerWorker + remainingConnections);
|
||||
}
|
||||
else
|
||||
{
|
||||
await StartWorker(worker.Id, targetAddress, transportType, connectionsPerWorker);
|
||||
}
|
||||
|
||||
await Runner.LogAgentAsync("Agent started listening to worker {0} ({1} of {2}).", worker.Id, index, numberOfWorkers);
|
||||
}
|
||||
|
||||
var workerTasks = new Task<AgentWorker>[numberOfWorkers];
|
||||
for (var index = 0; index < numberOfWorkers; index++)
|
||||
{
|
||||
workerTasks[index] = Task.Run(() => CreateWorker());
|
||||
}
|
||||
|
||||
await Task.WhenAll(workerTasks);
|
||||
|
||||
for (var index = 0; index < numberOfWorkers; index++)
|
||||
{
|
||||
_ = RunWorker(index, workerTasks[index].Result);
|
||||
}
|
||||
}
|
||||
|
||||
public void KillWorker(int workerId)
|
||||
{
|
||||
if (_workers.TryGetValue(workerId, out var worker))
|
||||
{
|
||||
worker.Kill();
|
||||
Runner.LogAgentAsync("Agent killed Worker {0}.", workerId);
|
||||
}
|
||||
}
|
||||
|
||||
public void KillWorkers(int numberOfWorkersToKill)
|
||||
{
|
||||
var keys = _workers.Keys.Take(numberOfWorkersToKill).ToList();
|
||||
|
||||
foreach (var key in keys)
|
||||
{
|
||||
if (_workers.TryGetValue(key, out var worker))
|
||||
{
|
||||
worker.Kill();
|
||||
Runner.LogAgentAsync("Agent killed Worker {0}.", key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void KillConnections()
|
||||
{
|
||||
var keys = _workers.Keys.ToList();
|
||||
|
||||
foreach (var key in keys)
|
||||
{
|
||||
if (_workers.TryGetValue(key, out var worker))
|
||||
{
|
||||
worker.Kill();
|
||||
Runner.LogAgentAsync("Agent killed Worker {0}.", key);
|
||||
}
|
||||
}
|
||||
|
||||
TotalConnectionsRequested = 0;
|
||||
ApplyingLoad = false;
|
||||
}
|
||||
|
||||
public void PingWorker(int workerId, int value)
|
||||
{
|
||||
if (_workers.TryGetValue(workerId, out var worker))
|
||||
{
|
||||
worker.Worker.PingAsync(value);
|
||||
Runner.LogAgentAsync("Agent sent ping command to Worker {0} with value {1}.", workerId, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Runner.LogAgentAsync("Agent failed to send ping command, Worker {0} not found.", workerId);
|
||||
}
|
||||
}
|
||||
|
||||
public void StartTest(int messageSize, TimeSpan sendInterval)
|
||||
{
|
||||
ApplyingLoad = true;
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
foreach (var worker in _workers.Values)
|
||||
{
|
||||
worker.Worker.StartTestAsync(sendInterval, messageSize);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void StopWorker(int workerId)
|
||||
{
|
||||
if (_workers.TryGetValue(workerId, out var worker))
|
||||
{
|
||||
worker.Worker.StopAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task StopWorkersAsync()
|
||||
{
|
||||
var keys = _workers.Keys.ToList();
|
||||
|
||||
foreach (var key in keys)
|
||||
{
|
||||
if (_workers.TryGetValue(key, out var worker))
|
||||
{
|
||||
await worker.Worker.StopAsync();
|
||||
await Runner.LogAgentAsync("Agent stopped Worker {0}.", key);
|
||||
}
|
||||
}
|
||||
TotalConnectionsRequested = 0;
|
||||
ApplyingLoad = false;
|
||||
|
||||
// Wait for workers to terminate
|
||||
while (_workers.Count > 0)
|
||||
{
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task PongAsync(int id, int value)
|
||||
{
|
||||
await Runner.LogAgentAsync("Agent received pong message from Worker {0} with value {1}.", id, value);
|
||||
await Runner.PongWorkerAsync(id, value);
|
||||
}
|
||||
|
||||
public async Task LogAsync(int id, string text)
|
||||
{
|
||||
await Runner.LogWorkerAsync(id, text);
|
||||
}
|
||||
|
||||
public Task StatusAsync(
|
||||
int id,
|
||||
StatusInformation statusInformation)
|
||||
{
|
||||
if (_workers.TryGetValue(id, out var worker))
|
||||
{
|
||||
worker.StatusInformation = statusInformation;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void OnError(int workerId, Exception ex)
|
||||
{
|
||||
Runner.LogWorkerAsync(workerId, ex.Message);
|
||||
}
|
||||
|
||||
private void OnExit(int workerId, int exitCode)
|
||||
{
|
||||
_workers.TryRemove(workerId, out _);
|
||||
var message = $"Worker {workerId} exited with exit code {exitCode}.";
|
||||
Trace.WriteLine(message);
|
||||
if (exitCode != 0)
|
||||
{
|
||||
throw new Exception(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Crankier
|
||||
{
|
||||
public class AgentHeartbeatInformation
|
||||
{
|
||||
public string HostName { get; set; }
|
||||
|
||||
public string TargetAddress { get; set; }
|
||||
|
||||
public int TotalConnectionsRequested { get; set; }
|
||||
|
||||
public bool ApplyingLoad { get; set; }
|
||||
|
||||
public List<WorkerHeartbeatInformation> Workers { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Crankier
|
||||
{
|
||||
public class AgentReceiver
|
||||
{
|
||||
private readonly StreamReader _reader;
|
||||
private readonly IAgent _agent;
|
||||
|
||||
public AgentReceiver(StreamReader reader, IAgent agent)
|
||||
{
|
||||
_reader = reader;
|
||||
_agent = agent;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var messageString = await _reader.ReadLineAsync();
|
||||
while (messageString != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var message = JsonConvert.DeserializeObject<Message>(messageString);
|
||||
|
||||
switch (message.Command.ToLowerInvariant())
|
||||
{
|
||||
case "pong":
|
||||
await _agent.PongAsync(
|
||||
message.Value["Id"].ToObject<int>(),
|
||||
message.Value["Value"].ToObject<int>());
|
||||
break;
|
||||
case "log":
|
||||
await _agent.LogAsync(
|
||||
message.Value["Id"].ToObject<int>(),
|
||||
message.Value["Text"].ToObject<string>());
|
||||
break;
|
||||
case "status":
|
||||
await _agent.StatusAsync(
|
||||
message.Value["Id"].ToObject<int>(),
|
||||
message.Value["StatusInformation"].ToObject<StatusInformation>());
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.WriteLine($"Error parsing '{messageString}': {ex.Message}");
|
||||
}
|
||||
|
||||
messageString = await _reader.ReadLineAsync();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Crankier
|
||||
{
|
||||
public class AgentSender : IAgent
|
||||
{
|
||||
private readonly SemaphoreSlim _lock = new SemaphoreSlim(1, 1);
|
||||
private readonly StreamWriter _outputStreamWriter;
|
||||
|
||||
public AgentSender(StreamWriter outputStreamWriter)
|
||||
{
|
||||
_outputStreamWriter = outputStreamWriter;
|
||||
}
|
||||
|
||||
public async Task PongAsync(int id, int value)
|
||||
{
|
||||
var parameters = new
|
||||
{
|
||||
Id = id,
|
||||
Value = value
|
||||
};
|
||||
|
||||
await SendAsync("pong", JToken.FromObject(parameters));
|
||||
}
|
||||
|
||||
public async Task LogAsync(int id, string text)
|
||||
{
|
||||
var parameters = new
|
||||
{
|
||||
Id = id,
|
||||
Text = text
|
||||
};
|
||||
|
||||
await SendAsync("log", JToken.FromObject(parameters));
|
||||
}
|
||||
|
||||
public async Task StatusAsync(
|
||||
int id,
|
||||
StatusInformation statusInformation)
|
||||
{
|
||||
var parameters = new
|
||||
{
|
||||
Id = id,
|
||||
StatusInformation = statusInformation
|
||||
};
|
||||
|
||||
await SendAsync("status", JToken.FromObject(parameters)); ;
|
||||
}
|
||||
|
||||
private async Task SendAsync(string method, JToken parameters)
|
||||
{
|
||||
await _lock.WaitAsync();
|
||||
try
|
||||
{
|
||||
await _outputStreamWriter.WriteLineAsync(
|
||||
JsonConvert.SerializeObject(new Message
|
||||
{
|
||||
Command = method,
|
||||
Value = parameters
|
||||
}));
|
||||
await _outputStreamWriter.FlushAsync();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Crankier
|
||||
{
|
||||
public class AgentWorker
|
||||
{
|
||||
private readonly Process _workerProcess;
|
||||
private readonly IAgent _agent;
|
||||
|
||||
public AgentWorker(ProcessStartInfo startInfo, IAgent agent)
|
||||
{
|
||||
_workerProcess = new Process();
|
||||
_workerProcess.StartInfo = startInfo;
|
||||
_workerProcess.EnableRaisingEvents = true;
|
||||
_workerProcess.Exited += OnExited;
|
||||
_agent = agent;
|
||||
}
|
||||
|
||||
public int Id { get; private set; }
|
||||
|
||||
public StatusInformation StatusInformation { get; set; }
|
||||
|
||||
public Action<int, Exception> OnError;
|
||||
|
||||
public Action<int, int> OnExit;
|
||||
|
||||
public IWorker Worker { get; private set; }
|
||||
|
||||
public WorkerHeartbeatInformation GetHeartbeatInformation()
|
||||
{
|
||||
return new WorkerHeartbeatInformation
|
||||
{
|
||||
Id = Id,
|
||||
ConnectedCount = StatusInformation.ConnectedCount,
|
||||
DisconnectedCount = StatusInformation.DisconnectedCount,
|
||||
ReconnectingCount = StatusInformation.ReconnectingCount,
|
||||
TargetConnectionCount = StatusInformation.TargetConnectionCount
|
||||
};
|
||||
}
|
||||
|
||||
public bool Start()
|
||||
{
|
||||
bool success = _workerProcess.Start();
|
||||
|
||||
if (success)
|
||||
{
|
||||
Id = _workerProcess.Id;
|
||||
|
||||
var receiver = new AgentReceiver(_workerProcess.StandardOutput, _agent);
|
||||
receiver.Start();
|
||||
|
||||
Worker = new WorkerSender(_workerProcess.StandardInput);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
public void Kill()
|
||||
{
|
||||
_workerProcess.Kill();
|
||||
}
|
||||
|
||||
private void OnExited(object sender, EventArgs args)
|
||||
{
|
||||
OnExit(Id, _workerProcess.ExitCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http.Connections;
|
||||
using Microsoft.AspNetCore.SignalR.Client;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Crankier
|
||||
{
|
||||
public class Client
|
||||
{
|
||||
private HubConnection _connection;
|
||||
private CancellationTokenSource _sendCts;
|
||||
private bool _sendInProgress;
|
||||
private volatile ConnectionState _connectionState = ConnectionState.Connecting;
|
||||
|
||||
public ConnectionState State => _connectionState;
|
||||
public async Task CreateAndStartConnectionAsync(string url, HttpTransportType transportType)
|
||||
{
|
||||
_connection = new HubConnectionBuilder()
|
||||
.WithUrl(url, options => options.Transports = transportType)
|
||||
.Build();
|
||||
|
||||
_connection.Closed += (ex) =>
|
||||
{
|
||||
if (ex == null)
|
||||
{
|
||||
Trace.WriteLine("Connection terminated");
|
||||
_connectionState = ConnectionState.Disconnected;
|
||||
}
|
||||
else
|
||||
{
|
||||
Trace.WriteLine($"Connection terminated with error: {ex.GetType()}: {ex.Message}");
|
||||
_connectionState = ConnectionState.Faulted;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
_sendCts = new CancellationTokenSource();
|
||||
|
||||
await ConnectAsync();
|
||||
}
|
||||
|
||||
private async Task ConnectAsync()
|
||||
{
|
||||
for (int connectCount = 0; connectCount <= 3; connectCount++)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _connection.StartAsync();
|
||||
_connectionState = ConnectionState.Connected;
|
||||
break;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.WriteLine($"Connection.Start Failed: {ex.GetType()}: {ex.Message}");
|
||||
|
||||
if (connectCount == 3)
|
||||
{
|
||||
_connectionState = ConnectionState.Faulted;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
public void StartTest(int sendSize, TimeSpan sendInterval)
|
||||
{
|
||||
var payload = (sendSize == 0) ? String.Empty : new string('a', sendSize);
|
||||
|
||||
if (_sendInProgress)
|
||||
{
|
||||
_sendCts.Cancel();
|
||||
_sendCts = new CancellationTokenSource();
|
||||
}
|
||||
else
|
||||
{
|
||||
_sendInProgress = true;
|
||||
}
|
||||
|
||||
if (!String.IsNullOrEmpty(payload))
|
||||
{
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
while (!_sendCts.Token.IsCancellationRequested && State != ConnectionState.Disconnected)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _connection.InvokeAsync("SendPayload", payload, _sendCts.Token);
|
||||
}
|
||||
// REVIEW: This is bad. We need a way to detect a closed connection when an Invocation fails!
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
// The connection was closed.
|
||||
Trace.WriteLine("Connection closed");
|
||||
break;
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// The connection was closed.
|
||||
Trace.WriteLine("Connection closed");
|
||||
break;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Connection failed
|
||||
Trace.WriteLine($"Connection failed: {ex.GetType()}: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
|
||||
await Task.Delay(sendInterval);
|
||||
}
|
||||
}, _sendCts.Token);
|
||||
}
|
||||
}
|
||||
|
||||
public Task StopConnectionAsync()
|
||||
{
|
||||
_sendCts.Cancel();
|
||||
|
||||
return _connection.StopAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.Extensions.CommandLineUtils;
|
||||
|
||||
using static Microsoft.AspNetCore.SignalR.Crankier.Commands.CommandLineUtilities;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Crankier.Commands
|
||||
{
|
||||
internal class AgentCommand
|
||||
{
|
||||
public static void Register(CommandLineApplication app)
|
||||
{
|
||||
app.Command("agent", cmd => cmd.OnExecute(() => Fail("Not yet implemented")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.Extensions.CommandLineUtils;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Crankier.Commands
|
||||
{
|
||||
internal static class CommandLineUtilities
|
||||
{
|
||||
public static int Fail(string message)
|
||||
{
|
||||
Error(message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static void Error(string message)
|
||||
{
|
||||
Console.WriteLine($"error: {message}");
|
||||
}
|
||||
|
||||
public static int MissingRequiredArg(CommandOption option)
|
||||
{
|
||||
return Fail($"Missing required argument: {option.LongName}");
|
||||
}
|
||||
|
||||
public static int InvalidArg(CommandOption option)
|
||||
{
|
||||
return Fail($"Invalid value '{option.Value()}' for argument: {option.LongName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Http.Connections;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Crankier.Commands
|
||||
{
|
||||
internal static class Defaults
|
||||
{
|
||||
public static readonly int NumberOfWorkers = 1;
|
||||
public static readonly int NumberOfConnections = 10_000;
|
||||
public static readonly int SendDurationInSeconds = 300;
|
||||
public static readonly HttpTransportType TransportType = HttpTransportType.WebSockets;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http.Connections;
|
||||
using Microsoft.Extensions.CommandLineUtils;
|
||||
|
||||
using static Microsoft.AspNetCore.SignalR.Crankier.Commands.CommandLineUtilities;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Crankier.Commands
|
||||
{
|
||||
internal class LocalCommand
|
||||
{
|
||||
public static void Register(CommandLineApplication app)
|
||||
{
|
||||
app.Command("local", cmd =>
|
||||
{
|
||||
var targetUrlOption = cmd.Option("--target-url <TARGET_URL>", "The URL to run the test against.", CommandOptionType.SingleValue);
|
||||
var numberOfWorkersOption = cmd.Option("--workers <WORKER_COUNT>", "The number of workers to use.", CommandOptionType.SingleValue);
|
||||
var numberOfConnectionsOption = cmd.Option("--connections <CONNECTION_COUNT>", "The number of connections per worker to use.", CommandOptionType.SingleValue);
|
||||
var sendDurationInSecondsOption = cmd.Option("--send-duration <SEND_DURATION_IN_SECONDS>", "The send duration to use.", CommandOptionType.SingleValue);
|
||||
var transportTypeOption = cmd.Option("--transport <TRANSPORT>", "The transport to use (defaults to WebSockets).", CommandOptionType.SingleValue);
|
||||
var workerWaitForDebuggerOption = cmd.Option("--worker-debug", "Provide this switch to have the worker wait for the debugger.", CommandOptionType.NoValue);
|
||||
|
||||
cmd.OnExecute(async () =>
|
||||
{
|
||||
if (!targetUrlOption.HasValue())
|
||||
{
|
||||
return MissingRequiredArg(targetUrlOption);
|
||||
}
|
||||
|
||||
var numberOfWorkers = Defaults.NumberOfWorkers;
|
||||
var numberOfConnections = Defaults.NumberOfConnections;
|
||||
var sendDurationInSeconds = Defaults.SendDurationInSeconds;
|
||||
var transportType = Defaults.TransportType;
|
||||
|
||||
if (numberOfWorkersOption.HasValue() && !int.TryParse(numberOfWorkersOption.Value(), out numberOfWorkers))
|
||||
{
|
||||
return MissingRequiredArg(numberOfWorkersOption);
|
||||
}
|
||||
|
||||
if (numberOfConnectionsOption.HasValue() && !int.TryParse(numberOfConnectionsOption.Value(), out numberOfConnections))
|
||||
{
|
||||
return InvalidArg(numberOfConnectionsOption);
|
||||
}
|
||||
|
||||
if (sendDurationInSecondsOption.HasValue() && !int.TryParse(sendDurationInSecondsOption.Value(), out sendDurationInSeconds))
|
||||
{
|
||||
return InvalidArg(sendDurationInSecondsOption);
|
||||
}
|
||||
|
||||
if (transportTypeOption.HasValue() && !Enum.TryParse(transportTypeOption.Value(), out transportType))
|
||||
{
|
||||
return InvalidArg(transportTypeOption);
|
||||
}
|
||||
|
||||
return await Execute(targetUrlOption.Value(), numberOfWorkers, numberOfConnections, sendDurationInSeconds, transportType, workerWaitForDebuggerOption.HasValue());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private static async Task<int> Execute(string targetUrl, int numberOfWorkers, int numberOfConnections, int sendDurationInSeconds, HttpTransportType transportType, bool workerWaitForDebugger)
|
||||
{
|
||||
var agent = new Agent(workerWaitForDebugger: workerWaitForDebugger);
|
||||
var runner = new Runner(agent, targetUrl, numberOfWorkers, numberOfConnections, sendDurationInSeconds, transportType);
|
||||
try
|
||||
{
|
||||
await runner.RunAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Fail(ex.ToString());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.CommandLineUtils;
|
||||
|
||||
using static Microsoft.AspNetCore.SignalR.Crankier.Commands.CommandLineUtilities;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Crankier.Commands
|
||||
{
|
||||
internal class WorkerCommand
|
||||
{
|
||||
public static void Register(CommandLineApplication app)
|
||||
{
|
||||
app.Command("worker", cmd =>
|
||||
{
|
||||
var agentOption = cmd.Option("--agent <PARENT_PID>", "The process ID of the agent controlling this worker", CommandOptionType.SingleValue);
|
||||
var waitForDebuggerOption = cmd.Option("--wait-for-debugger", "Provide this flag to have the worker wait for the debugger.", CommandOptionType.NoValue);
|
||||
|
||||
cmd.OnExecute(async () =>
|
||||
{
|
||||
if (!agentOption.HasValue())
|
||||
{
|
||||
return MissingRequiredArg(agentOption);
|
||||
}
|
||||
|
||||
if (!int.TryParse(agentOption.Value(), out var agentPid))
|
||||
{
|
||||
return InvalidArg(agentOption);
|
||||
}
|
||||
|
||||
if (waitForDebuggerOption.HasValue())
|
||||
{
|
||||
SpinWait.SpinUntil(() => Debugger.IsAttached);
|
||||
}
|
||||
|
||||
return await Execute(agentPid);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private static async Task<int> Execute(int agentPid)
|
||||
{
|
||||
try
|
||||
{
|
||||
var worker = new Worker(agentPid);
|
||||
await worker.RunAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Fail(ex.ToString());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Crankier
|
||||
{
|
||||
public enum ConnectionState
|
||||
{
|
||||
Connecting,
|
||||
Connected,
|
||||
Reconnecting,
|
||||
Disconnected,
|
||||
Faulted,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<RootNamespace>Microsoft.AspNetCore.SignalR.CranksRevenge</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.CommandLineUtils.Sources" Version="$(MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion)" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="$(NewtonsoftJsonPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Client\Microsoft.AspNetCore.SignalR.Client.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Crankier
|
||||
{
|
||||
public interface IAgent
|
||||
{
|
||||
Task PongAsync(int id, int value);
|
||||
Task LogAsync(int id, string text);
|
||||
Task StatusAsync(int id, StatusInformation statusInformation);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Crankier
|
||||
{
|
||||
public interface IRunner
|
||||
{
|
||||
Task PongWorkerAsync(int workerId, int value);
|
||||
|
||||
Task LogAgentAsync(string format, params object[] arguments);
|
||||
|
||||
Task LogWorkerAsync(int workerId, string format, params object[] arguments);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http.Connections;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Crankier
|
||||
{
|
||||
public interface IWorker
|
||||
{
|
||||
Task PingAsync(int value);
|
||||
Task ConnectAsync(string targetAddress, HttpTransportType transportType, int numberOfConnections);
|
||||
Task StartTestAsync(TimeSpan sendInterval, int sendBytes);
|
||||
Task StopAsync();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Crankier
|
||||
{
|
||||
public class Message
|
||||
{
|
||||
public string Command { get; set; }
|
||||
|
||||
public JToken Value { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.SignalR.Crankier.Commands;
|
||||
using Microsoft.Extensions.CommandLineUtils;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Crankier
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
#if DEBUG
|
||||
if (args.Any(a => string.Equals(a, "--debug", StringComparison.Ordinal)))
|
||||
{
|
||||
args = args.Where(a => !string.Equals(a, "--debug", StringComparison.Ordinal)).ToArray();
|
||||
Console.WriteLine($"Waiting for debugger. Process ID: {Process.GetCurrentProcess().Id}");
|
||||
Console.WriteLine("Press ENTER to continue");
|
||||
Console.ReadLine();
|
||||
}
|
||||
#endif
|
||||
|
||||
var app = new CommandLineApplication();
|
||||
app.Description = "Crank's Revenge";
|
||||
app.HelpOption("-h|--help");
|
||||
|
||||
LocalCommand.Register(app);
|
||||
AgentCommand.Register(app);
|
||||
WorkerCommand.Register(app);
|
||||
|
||||
app.Command("help", cmd =>
|
||||
{
|
||||
var commandArgument = cmd.Argument("<COMMAND>", "The command to get help for.");
|
||||
|
||||
cmd.OnExecute(() =>
|
||||
{
|
||||
app.ShowHelp(commandArgument.Value);
|
||||
return 0;
|
||||
});
|
||||
});
|
||||
|
||||
app.OnExecute(() =>
|
||||
{
|
||||
app.ShowHelp();
|
||||
return 0;
|
||||
});
|
||||
|
||||
app.Execute(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http.Connections;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Crankier
|
||||
{
|
||||
public class Runner : IRunner
|
||||
{
|
||||
private readonly Agent _agent;
|
||||
private readonly string _targetUrl;
|
||||
private readonly int _numberOfWorkers;
|
||||
private readonly int _numberOfConnections;
|
||||
private readonly int _sendDurationSeconds;
|
||||
private readonly HttpTransportType _transportType;
|
||||
|
||||
public Runner(Agent agent, string targetUrl, int numberOfWorkers, int numberOfConnections, int sendDurationInSeconds, HttpTransportType transportType)
|
||||
{
|
||||
_agent = agent;
|
||||
_targetUrl = targetUrl;
|
||||
_numberOfWorkers = numberOfWorkers;
|
||||
_numberOfConnections = numberOfConnections;
|
||||
_sendDurationSeconds = sendDurationInSeconds;
|
||||
_transportType = transportType;
|
||||
}
|
||||
|
||||
public async Task RunAsync()
|
||||
{
|
||||
_agent.Runner = this;
|
||||
|
||||
await _agent.StartWorkersAsync(_targetUrl, _numberOfWorkers, _transportType, _numberOfConnections);
|
||||
|
||||
// Begin writing worker status information
|
||||
var writeStatusCts = new CancellationTokenSource();
|
||||
var writeStatusTask = WriteConnectionStatusAsync(writeStatusCts.Token);
|
||||
|
||||
// Wait until all connections are connected
|
||||
while (_agent.GetWorkerStatus().Aggregate(0, (state, status) => state + status.Value.ConnectedCount) <
|
||||
_agent.TotalConnectionsRequested)
|
||||
{
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
|
||||
// Stay connected for the duration of the send phase
|
||||
await Task.Delay(TimeSpan.FromSeconds(_sendDurationSeconds));
|
||||
|
||||
// Disconnect
|
||||
await _agent.StopWorkersAsync();
|
||||
|
||||
// Stop writing worker status information
|
||||
writeStatusCts.Cancel();
|
||||
await writeStatusTask;
|
||||
}
|
||||
|
||||
private Task WriteConnectionStatusAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.Run(async () =>
|
||||
{
|
||||
var peakConnections = 0;
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
var statusDictionary = _agent.GetWorkerStatus();
|
||||
|
||||
// Total things up
|
||||
var status = new StatusInformation();
|
||||
foreach (var value in statusDictionary.Values)
|
||||
{
|
||||
status = status.Add(value);
|
||||
}
|
||||
|
||||
peakConnections = Math.Max(peakConnections, status.ConnectedCount);
|
||||
status.PeakConnections = peakConnections;
|
||||
|
||||
Trace.WriteLine(JsonConvert.SerializeObject(status));
|
||||
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Task PongWorkerAsync(int workerId, int value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task LogAgentAsync(string format, params object[] arguments)
|
||||
{
|
||||
Trace.WriteLine(string.Format(format, arguments));
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task LogWorkerAsync(int workerId, string format, params object[] arguments)
|
||||
{
|
||||
Trace.WriteLine(string.Format("({0}) {1}", workerId, string.Format(format, arguments)));
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Crankier
|
||||
{
|
||||
public class StatusInformation
|
||||
{
|
||||
public int ConnectingCount { get; set; }
|
||||
public int ConnectedCount { get; set; }
|
||||
public int DisconnectedCount { get; set; }
|
||||
public int ReconnectingCount { get; set; }
|
||||
public int FaultedCount { get; set; }
|
||||
public int TargetConnectionCount { get; set; }
|
||||
|
||||
|
||||
// Set by agent.
|
||||
public int PeakConnections { get; set;}
|
||||
|
||||
public StatusInformation Add(StatusInformation value)
|
||||
{
|
||||
return new StatusInformation()
|
||||
{
|
||||
ConnectingCount = ConnectingCount + value.ConnectingCount,
|
||||
ConnectedCount = ConnectedCount + value.ConnectedCount,
|
||||
DisconnectedCount = DisconnectedCount + value.DisconnectedCount,
|
||||
ReconnectingCount = ReconnectingCount + value.ReconnectingCount,
|
||||
FaultedCount = FaultedCount + value.FaultedCount,
|
||||
TargetConnectionCount = TargetConnectionCount + value.TargetConnectionCount,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http.Connections;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Crankier
|
||||
{
|
||||
public class Worker : IWorker
|
||||
{
|
||||
private readonly Process _agentProcess;
|
||||
private readonly IAgent _agent;
|
||||
private readonly int _processId;
|
||||
private readonly ConcurrentBag<Client> _clients;
|
||||
private readonly CancellationTokenSource _sendStatusCts;
|
||||
private int _targetConnectionCount;
|
||||
|
||||
public Worker(int agentProcessId)
|
||||
{
|
||||
_agentProcess = Process.GetProcessById(agentProcessId);
|
||||
_agent = new AgentSender(new StreamWriter(Console.OpenStandardOutput()));
|
||||
_processId = Process.GetCurrentProcess().Id;
|
||||
_clients = new ConcurrentBag<Client>();
|
||||
_sendStatusCts = new CancellationTokenSource();
|
||||
}
|
||||
|
||||
public async Task RunAsync()
|
||||
{
|
||||
_agentProcess.EnableRaisingEvents = true;
|
||||
_agentProcess.Exited += OnExited;
|
||||
|
||||
Log("Worker created");
|
||||
|
||||
var receiver = new WorkerReceiver(
|
||||
new StreamReader(Console.OpenStandardInput()),
|
||||
this);
|
||||
|
||||
receiver.Start();
|
||||
|
||||
await SendStatusUpdateAsync(_sendStatusCts.Token);
|
||||
|
||||
receiver.Stop();
|
||||
}
|
||||
|
||||
public async Task PingAsync(int value)
|
||||
{
|
||||
Log("Worker received ping command with value {0}.", value);
|
||||
|
||||
await _agent.PongAsync(_processId, value);
|
||||
Log("Worker sent pong command with value {0}.", value);
|
||||
}
|
||||
|
||||
public async Task ConnectAsync(string targetAddress, HttpTransportType transportType, int numberOfConnections)
|
||||
{
|
||||
Log("Worker received connect command with target address {0} and number of connections {1}", targetAddress, numberOfConnections);
|
||||
|
||||
_targetConnectionCount += numberOfConnections;
|
||||
for (var count = 0; count < numberOfConnections; count++)
|
||||
{
|
||||
var client = new Client();
|
||||
_clients.Add(client);
|
||||
|
||||
await client.CreateAndStartConnectionAsync(targetAddress, transportType);
|
||||
}
|
||||
|
||||
Log("Connections connected succesfully");
|
||||
}
|
||||
|
||||
public Task StartTestAsync(TimeSpan sendInterval, int sendBytes)
|
||||
{
|
||||
Log("Worker received start test command with interval {0} and message size {1}.", sendInterval, sendBytes);
|
||||
|
||||
foreach (var client in _clients)
|
||||
{
|
||||
client.StartTest(sendBytes, sendInterval);
|
||||
}
|
||||
|
||||
Log("Test started succesfully");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task StopAsync()
|
||||
{
|
||||
Log("Worker received stop command");
|
||||
_targetConnectionCount = 0;
|
||||
|
||||
while (!_clients.IsEmpty)
|
||||
{
|
||||
if (_clients.TryTake(out var client))
|
||||
{
|
||||
client.StopConnectionAsync();
|
||||
}
|
||||
}
|
||||
|
||||
_sendStatusCts.Cancel();
|
||||
Log("Connections stopped succesfully");
|
||||
_targetConnectionCount = 0;
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void OnExited(object sender, EventArgs args)
|
||||
{
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
private void Log(string format, params object[] arguments)
|
||||
{
|
||||
_agent.LogAsync(_processId, string.Format(format, arguments));
|
||||
}
|
||||
|
||||
private async Task SendStatusUpdateAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
var connectedCount = 0;
|
||||
var connectingCount = 0;
|
||||
var disconnectedCount = 0;
|
||||
var reconnectingCount = 0;
|
||||
var faultedCount = 0;
|
||||
|
||||
foreach (var client in _clients)
|
||||
{
|
||||
switch (client.State)
|
||||
{
|
||||
case ConnectionState.Connecting:
|
||||
connectingCount++;
|
||||
break;
|
||||
case ConnectionState.Connected:
|
||||
connectedCount++;
|
||||
break;
|
||||
case ConnectionState.Disconnected:
|
||||
disconnectedCount++;
|
||||
break;
|
||||
case ConnectionState.Reconnecting:
|
||||
reconnectingCount++;
|
||||
break;
|
||||
case ConnectionState.Faulted:
|
||||
faultedCount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
await _agent.StatusAsync(
|
||||
_processId,
|
||||
new StatusInformation
|
||||
{
|
||||
ConnectingCount = connectingCount,
|
||||
ConnectedCount = connectedCount,
|
||||
DisconnectedCount = disconnectedCount,
|
||||
ReconnectingCount = reconnectingCount,
|
||||
TargetConnectionCount = _targetConnectionCount,
|
||||
FaultedCount = faultedCount,
|
||||
}
|
||||
);
|
||||
|
||||
// Sending once per 5 seconds to avoid overloading the Test Controller
|
||||
try
|
||||
{
|
||||
await Task.Delay(5000, cancellationToken);
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Crankier
|
||||
{
|
||||
public class WorkerHeartbeatInformation
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int ConnectedCount { get; set; }
|
||||
|
||||
public int DisconnectedCount { get; set; }
|
||||
|
||||
public int ReconnectingCount { get; set; }
|
||||
|
||||
public int TargetConnectionCount { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http.Connections;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Crankier
|
||||
{
|
||||
public class WorkerReceiver
|
||||
{
|
||||
private readonly StreamReader _reader;
|
||||
private readonly IWorker _worker;
|
||||
private CancellationTokenSource _receiveMessageCts;
|
||||
|
||||
public WorkerReceiver(StreamReader reader, IWorker worker)
|
||||
{
|
||||
_reader = reader;
|
||||
_worker = worker;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (_receiveMessageCts != null)
|
||||
{
|
||||
_receiveMessageCts.Cancel();
|
||||
}
|
||||
|
||||
_receiveMessageCts = new CancellationTokenSource();
|
||||
Task.Run(async () =>
|
||||
{
|
||||
while (!_receiveMessageCts.Token.IsCancellationRequested)
|
||||
{
|
||||
var messageString = await _reader.ReadLineAsync();
|
||||
try
|
||||
{
|
||||
var message = JsonConvert.DeserializeObject<Message>(messageString);
|
||||
|
||||
switch (message.Command.ToLowerInvariant())
|
||||
{
|
||||
case "ping":
|
||||
await _worker.PingAsync(
|
||||
message.Value["Value"].ToObject<int>());
|
||||
break;
|
||||
case "connect":
|
||||
await _worker.ConnectAsync(
|
||||
message.Value["TargetAddress"].ToObject<string>(),
|
||||
message.Value["TransportType"].ToObject<HttpTransportType>(),
|
||||
message.Value["NumberOfConnections"].ToObject<int>());
|
||||
break;
|
||||
case "starttest":
|
||||
await _worker.StartTestAsync(
|
||||
TimeSpan.FromMilliseconds(message.Value.Value<double>("SendInterval")),
|
||||
message.Value["SendBytes"].ToObject<int>());
|
||||
break;
|
||||
case "stop":
|
||||
await _worker.StopAsync();
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.WriteLine(ex.Message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
_receiveMessageCts.Cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http.Connections;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Crankier
|
||||
{
|
||||
public class WorkerSender : IWorker
|
||||
{
|
||||
private readonly StreamWriter _outputStreamWriter;
|
||||
|
||||
public WorkerSender(StreamWriter outputStreamWriter)
|
||||
{
|
||||
_outputStreamWriter = outputStreamWriter;
|
||||
}
|
||||
|
||||
public async Task PingAsync(int value)
|
||||
{
|
||||
await Send("ping", JToken.FromObject(
|
||||
new
|
||||
{
|
||||
Value = value
|
||||
}));
|
||||
}
|
||||
|
||||
public async Task ConnectAsync(string targetAddress, HttpTransportType transportType, int numberOfConnections)
|
||||
{
|
||||
await Send("connect", JToken.FromObject(
|
||||
new
|
||||
{
|
||||
TargetAddress = targetAddress,
|
||||
TransportType = transportType,
|
||||
NumberOfConnections = numberOfConnections
|
||||
}));
|
||||
}
|
||||
|
||||
public async Task StartTestAsync(TimeSpan sendInterval, int sendBytes)
|
||||
{
|
||||
var parameters = new
|
||||
{
|
||||
SendInterval = sendInterval.TotalMilliseconds,
|
||||
SendBytes = sendBytes
|
||||
};
|
||||
|
||||
await Send("starttest", JToken.FromObject(parameters));
|
||||
}
|
||||
|
||||
public async Task StopAsync()
|
||||
{
|
||||
await Send("stop", null);
|
||||
}
|
||||
|
||||
private async Task Send(string method, JToken parameters)
|
||||
{
|
||||
await _outputStreamWriter.WriteLineAsync(
|
||||
JsonConvert.SerializeObject(new Message()
|
||||
{
|
||||
Command = method,
|
||||
Value = parameters
|
||||
}));
|
||||
|
||||
await _outputStreamWriter.FlushAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
[assembly: BenchmarkDotNet.Attributes.AspNetCoreBenchmark]
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.Connections;
|
||||
using Microsoft.AspNetCore.SignalR.Internal;
|
||||
using Microsoft.AspNetCore.SignalR.Protocol;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
||||
{
|
||||
public class BroadcastBenchmark
|
||||
{
|
||||
private const string TestGroupName = "TestGroup";
|
||||
private DefaultHubLifetimeManager<Hub> _hubLifetimeManager;
|
||||
private HubContext<Hub> _hubContext;
|
||||
|
||||
[Params(1, 10, 1000)]
|
||||
public int Connections;
|
||||
|
||||
[Params("json", "msgpack")]
|
||||
public string Protocol;
|
||||
|
||||
[GlobalSetup]
|
||||
public void GlobalSetup()
|
||||
{
|
||||
_hubLifetimeManager = new DefaultHubLifetimeManager<Hub>(NullLogger<DefaultHubLifetimeManager<Hub>>.Instance);
|
||||
|
||||
IHubProtocol protocol;
|
||||
|
||||
if (Protocol == "json")
|
||||
{
|
||||
protocol = new JsonHubProtocol();
|
||||
}
|
||||
else
|
||||
{
|
||||
protocol = new MessagePackHubProtocol();
|
||||
}
|
||||
|
||||
var options = new PipeOptions();
|
||||
for (var i = 0; i < Connections; ++i)
|
||||
{
|
||||
var pair = DuplexPipe.CreateConnectionPair(options, options);
|
||||
var connection = new DefaultConnectionContext(Guid.NewGuid().ToString(), pair.Application, pair.Transport);
|
||||
var hubConnection = new HubConnectionContext(connection, Timeout.InfiniteTimeSpan, NullLoggerFactory.Instance);
|
||||
hubConnection.Protocol = protocol;
|
||||
_hubLifetimeManager.OnConnectedAsync(hubConnection).GetAwaiter().GetResult();
|
||||
_hubLifetimeManager.AddToGroupAsync(connection.ConnectionId, TestGroupName).GetAwaiter().GetResult();
|
||||
|
||||
_ = ConsumeAsync(connection.Application);
|
||||
}
|
||||
|
||||
_hubContext = new HubContext<Hub>(_hubLifetimeManager);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task SendAsyncGroup()
|
||||
{
|
||||
return _hubContext.Clients.Group(TestGroupName).SendAsync("Method");
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task SendAsyncAll()
|
||||
{
|
||||
return _hubContext.Clients.All.SendAsync("Method");
|
||||
}
|
||||
|
||||
// Consume the data written to the transport
|
||||
private static async Task ConsumeAsync(IDuplexPipe application)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var result = await application.Input.ReadAsync();
|
||||
var buffer = result.Buffer;
|
||||
|
||||
if (!buffer.IsEmpty)
|
||||
{
|
||||
application.Input.AdvanceTo(buffer.End);
|
||||
}
|
||||
else if (result.IsCompleted)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
application.Input.Complete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.SignalR.Internal;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
||||
{
|
||||
public class DefaultHubActivatorBenchmark
|
||||
{
|
||||
private DefaultHubActivator<MyHub> _activator;
|
||||
|
||||
[GlobalSetup]
|
||||
public void GlobalSetup()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
|
||||
_activator = new DefaultHubActivator<MyHub>(services.BuildServiceProvider());
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public int Create()
|
||||
{
|
||||
var hub = _activator.Create();
|
||||
var result = hub.Addition();
|
||||
return result;
|
||||
}
|
||||
|
||||
public class MyHub : Hub
|
||||
{
|
||||
public int Addition()
|
||||
{
|
||||
return 1 + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,233 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO;
|
||||
using System.IO.Pipelines;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Channels;
|
||||
using System.Threading.Tasks;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.Connections;
|
||||
using Microsoft.AspNetCore.SignalR.Internal;
|
||||
using Microsoft.AspNetCore.SignalR.Protocol;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
||||
{
|
||||
public class DefaultHubDispatcherBenchmark
|
||||
{
|
||||
private DefaultHubDispatcher<TestHub> _dispatcher;
|
||||
private HubConnectionContext _connectionContext;
|
||||
|
||||
[GlobalSetup]
|
||||
public void GlobalSetup()
|
||||
{
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddSignalRCore();
|
||||
|
||||
var provider = serviceCollection.BuildServiceProvider();
|
||||
|
||||
var serviceScopeFactory = provider.GetService<IServiceScopeFactory>();
|
||||
|
||||
_dispatcher = new DefaultHubDispatcher<TestHub>(
|
||||
serviceScopeFactory,
|
||||
new HubContext<TestHub>(new DefaultHubLifetimeManager<TestHub>(NullLogger<DefaultHubLifetimeManager<TestHub>>.Instance)),
|
||||
Options.Create(new HubOptions<TestHub>()),
|
||||
Options.Create(new HubOptions()),
|
||||
new Logger<DefaultHubDispatcher<TestHub>>(NullLoggerFactory.Instance));
|
||||
|
||||
var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
|
||||
var connection = new DefaultConnectionContext(Guid.NewGuid().ToString(), pair.Application, pair.Transport);
|
||||
|
||||
_connectionContext = new NoErrorHubConnectionContext(connection, TimeSpan.Zero, NullLoggerFactory.Instance);
|
||||
|
||||
_connectionContext.Protocol = new FakeHubProtocol();
|
||||
}
|
||||
|
||||
public class FakeHubProtocol : IHubProtocol
|
||||
{
|
||||
public string Name { get; }
|
||||
public int Version => 1;
|
||||
public TransferFormat TransferFormat { get; }
|
||||
|
||||
public bool IsVersionSupported(int version)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryParseMessage(ref ReadOnlySequence<byte> input, IInvocationBinder binder, out HubMessage message)
|
||||
{
|
||||
message = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void WriteMessage(HubMessage message, IBufferWriter<byte> output)
|
||||
{
|
||||
}
|
||||
|
||||
public ReadOnlyMemory<byte> GetMessageBytes(HubMessage message)
|
||||
{
|
||||
return HubProtocolExtensions.GetMessageBytes(this, message);
|
||||
}
|
||||
}
|
||||
|
||||
public class NoErrorHubConnectionContext : HubConnectionContext
|
||||
{
|
||||
public NoErrorHubConnectionContext(ConnectionContext connectionContext, TimeSpan keepAliveInterval, ILoggerFactory loggerFactory) : base(connectionContext, keepAliveInterval, loggerFactory)
|
||||
{
|
||||
}
|
||||
|
||||
public override ValueTask WriteAsync(HubMessage message, CancellationToken cancellationToken)
|
||||
{
|
||||
if (message is CompletionMessage completionMessage)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(completionMessage.Error))
|
||||
{
|
||||
throw new Exception("Error invoking hub method: " + completionMessage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
public class TestHub : Hub
|
||||
{
|
||||
public void Invocation()
|
||||
{
|
||||
}
|
||||
|
||||
public Task InvocationAsync()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public int InvocationReturnValue()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public Task<int> InvocationReturnAsync()
|
||||
{
|
||||
return Task.FromResult(1);
|
||||
}
|
||||
|
||||
public ValueTask<int> InvocationValueTaskAsync()
|
||||
{
|
||||
return new ValueTask<int>(1);
|
||||
}
|
||||
|
||||
public ChannelReader<int> StreamChannelReader()
|
||||
{
|
||||
var channel = Channel.CreateUnbounded<int>();
|
||||
channel.Writer.Complete();
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
public Task<ChannelReader<int>> StreamChannelReaderAsync()
|
||||
{
|
||||
var channel = Channel.CreateUnbounded<int>();
|
||||
channel.Writer.Complete();
|
||||
|
||||
return Task.FromResult<ChannelReader<int>>(channel);
|
||||
}
|
||||
|
||||
public ValueTask<ChannelReader<int>> StreamChannelReaderValueTaskAsync()
|
||||
{
|
||||
var channel = Channel.CreateUnbounded<int>();
|
||||
channel.Writer.Complete();
|
||||
|
||||
return new ValueTask<ChannelReader<int>>(channel);
|
||||
}
|
||||
|
||||
public ChannelReader<int> StreamChannelReaderCount(int count)
|
||||
{
|
||||
var channel = Channel.CreateUnbounded<int>();
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
await channel.Writer.WriteAsync(i);
|
||||
}
|
||||
channel.Writer.Complete();
|
||||
});
|
||||
|
||||
return channel.Reader;
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task Invocation()
|
||||
{
|
||||
return _dispatcher.DispatchMessageAsync(_connectionContext, new InvocationMessage("123", "Invocation", Array.Empty<object>()));
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task InvocationAsync()
|
||||
{
|
||||
return _dispatcher.DispatchMessageAsync(_connectionContext, new InvocationMessage("123", "InvocationAsync", Array.Empty<object>()));
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task InvocationReturnValue()
|
||||
{
|
||||
return _dispatcher.DispatchMessageAsync(_connectionContext, new InvocationMessage("123", "InvocationReturnValue", Array.Empty<object>()));
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task InvocationReturnAsync()
|
||||
{
|
||||
return _dispatcher.DispatchMessageAsync(_connectionContext, new InvocationMessage("123", "InvocationReturnAsync", Array.Empty<object>()));
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task InvocationValueTaskAsync()
|
||||
{
|
||||
return _dispatcher.DispatchMessageAsync(_connectionContext, new InvocationMessage("123", "InvocationValueTaskAsync", Array.Empty<object>()));
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task StreamChannelReader()
|
||||
{
|
||||
return _dispatcher.DispatchMessageAsync(_connectionContext, new StreamInvocationMessage("123", "StreamChannelReader", Array.Empty<object>()));
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task StreamChannelReaderAsync()
|
||||
{
|
||||
return _dispatcher.DispatchMessageAsync(_connectionContext, new StreamInvocationMessage("123", "StreamChannelReaderAsync", Array.Empty<object>()));
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task StreamChannelReaderValueTaskAsync()
|
||||
{
|
||||
return _dispatcher.DispatchMessageAsync(_connectionContext, new StreamInvocationMessage("123", "StreamChannelReaderValueTaskAsync", Array.Empty<object>()));
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task StreamChannelReaderCount_Zero()
|
||||
{
|
||||
return _dispatcher.DispatchMessageAsync(_connectionContext, new StreamInvocationMessage("123", "StreamChannelReaderCount", new object[] { 0 }));
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task StreamChannelReaderCount_One()
|
||||
{
|
||||
return _dispatcher.DispatchMessageAsync(_connectionContext, new StreamInvocationMessage("123", "StreamChannelReaderCount", new object[] { 1 }));
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task StreamChannelReaderCount_Thousand()
|
||||
{
|
||||
return _dispatcher.DispatchMessageAsync(_connectionContext, new StreamInvocationMessage("123", "StreamChannelReaderCount", new object[] { 1000 }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.SignalR.Protocol;
|
||||
using Microsoft.AspNetCore.SignalR.Microbenchmarks.Shared;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
||||
{
|
||||
public class DefaultHubLifetimeManagerBenchmark
|
||||
{
|
||||
private DefaultHubLifetimeManager<Hub> _hubLifetimeManager;
|
||||
private List<string> _connectionIds;
|
||||
private List<string> _subsetConnectionIds;
|
||||
private List<string> _groupNames;
|
||||
private List<string> _userIdentifiers;
|
||||
|
||||
[Params(true, false)]
|
||||
public bool ForceAsync { get; set; }
|
||||
|
||||
[GlobalSetup]
|
||||
public void GlobalSetup()
|
||||
{
|
||||
_hubLifetimeManager = new DefaultHubLifetimeManager<Hub>(NullLogger<DefaultHubLifetimeManager<Hub>>.Instance);
|
||||
_connectionIds = new List<string>();
|
||||
_subsetConnectionIds = new List<string>();
|
||||
_groupNames = new List<string>();
|
||||
_userIdentifiers = new List<string>();
|
||||
|
||||
var jsonHubProtocol = new JsonHubProtocol();
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
string connectionId = "connection-" + i;
|
||||
string groupName = "group-" + i % 10;
|
||||
string userIdentifier = "user-" + i % 20;
|
||||
AddUnique(_connectionIds, connectionId);
|
||||
AddUnique(_groupNames, groupName);
|
||||
AddUnique(_userIdentifiers, userIdentifier);
|
||||
if (i % 3 == 0)
|
||||
{
|
||||
_subsetConnectionIds.Add(connectionId);
|
||||
}
|
||||
|
||||
var connectionContext = new TestConnectionContext
|
||||
{
|
||||
ConnectionId = connectionId,
|
||||
Transport = new TestDuplexPipe(ForceAsync)
|
||||
};
|
||||
var hubConnectionContext = new HubConnectionContext(connectionContext, TimeSpan.Zero, NullLoggerFactory.Instance);
|
||||
hubConnectionContext.UserIdentifier = userIdentifier;
|
||||
hubConnectionContext.Protocol = jsonHubProtocol;
|
||||
|
||||
_hubLifetimeManager.OnConnectedAsync(hubConnectionContext).GetAwaiter().GetResult();
|
||||
_hubLifetimeManager.AddToGroupAsync(connectionId, groupName);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddUnique(List<string> list, string connectionId)
|
||||
{
|
||||
if (!list.Contains(connectionId))
|
||||
{
|
||||
list.Add(connectionId);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task SendAllAsync()
|
||||
{
|
||||
return _hubLifetimeManager.SendAllAsync("MethodName", Array.Empty<object>());
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task SendGroupAsync()
|
||||
{
|
||||
return _hubLifetimeManager.SendGroupAsync(_groupNames[0], "MethodName", Array.Empty<object>());
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task SendGroupsAsync()
|
||||
{
|
||||
return _hubLifetimeManager.SendGroupsAsync(_groupNames, "MethodName", Array.Empty<object>());
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task SendGroupExceptAsync()
|
||||
{
|
||||
return _hubLifetimeManager.SendGroupExceptAsync(_groupNames[0], "MethodName", Array.Empty<object>(), _subsetConnectionIds);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task SendAllExceptAsync()
|
||||
{
|
||||
return _hubLifetimeManager.SendAllExceptAsync("MethodName", Array.Empty<object>(), _subsetConnectionIds);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task SendConnectionAsync()
|
||||
{
|
||||
return _hubLifetimeManager.SendConnectionAsync(_connectionIds[0], "MethodName", Array.Empty<object>());
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task SendConnectionsAsync()
|
||||
{
|
||||
return _hubLifetimeManager.SendConnectionsAsync(_subsetConnectionIds, "MethodName", Array.Empty<object>());
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task SendUserAsync()
|
||||
{
|
||||
return _hubLifetimeManager.SendUserAsync(_userIdentifiers[0], "MethodName", Array.Empty<object>());
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task SendUsersAsync()
|
||||
{
|
||||
return _hubLifetimeManager.SendUsersAsync(_userIdentifiers, "MethodName", Array.Empty<object>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.Connections;
|
||||
using Microsoft.AspNetCore.SignalR.Internal;
|
||||
using Microsoft.AspNetCore.Internal;
|
||||
using Microsoft.AspNetCore.SignalR.Protocol;
|
||||
using Microsoft.AspNetCore.SignalR.Microbenchmarks.Shared;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
||||
{
|
||||
public class HubConnectionContextBenchmark
|
||||
{
|
||||
private HubConnectionContext _hubConnectionContext;
|
||||
private TestHubProtocolResolver _successHubProtocolResolver;
|
||||
private TestHubProtocolResolver _failureHubProtocolResolver;
|
||||
private TestUserIdProvider _userIdProvider;
|
||||
private List<string> _supportedProtocols;
|
||||
private TestDuplexPipe _pipe;
|
||||
private ReadResult _handshakeRequestResult;
|
||||
|
||||
[GlobalSetup]
|
||||
public void GlobalSetup()
|
||||
{
|
||||
var memoryBufferWriter = MemoryBufferWriter.Get();
|
||||
try
|
||||
{
|
||||
HandshakeProtocol.WriteRequestMessage(new HandshakeRequestMessage("json", 1), memoryBufferWriter);
|
||||
_handshakeRequestResult = new ReadResult(new ReadOnlySequence<byte>(memoryBufferWriter.ToArray()), false, false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
MemoryBufferWriter.Return(memoryBufferWriter);
|
||||
}
|
||||
|
||||
_pipe = new TestDuplexPipe();
|
||||
|
||||
var connection = new DefaultConnectionContext(Guid.NewGuid().ToString(), _pipe, _pipe);
|
||||
_hubConnectionContext = new HubConnectionContext(connection, Timeout.InfiniteTimeSpan, NullLoggerFactory.Instance);
|
||||
|
||||
_successHubProtocolResolver = new TestHubProtocolResolver(new JsonHubProtocol());
|
||||
_failureHubProtocolResolver = new TestHubProtocolResolver(null);
|
||||
_userIdProvider = new TestUserIdProvider();
|
||||
_supportedProtocols = new List<string> { "json" };
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public async Task SuccessHandshakeAsync()
|
||||
{
|
||||
_pipe.AddReadResult(new ValueTask<ReadResult>(_handshakeRequestResult));
|
||||
|
||||
await _hubConnectionContext.HandshakeAsync(TimeSpan.FromSeconds(5), _supportedProtocols, _successHubProtocolResolver,
|
||||
_userIdProvider, enableDetailedErrors: true);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public async Task ErrorHandshakeAsync()
|
||||
{
|
||||
_pipe.AddReadResult(new ValueTask<ReadResult>(_handshakeRequestResult));
|
||||
|
||||
await _hubConnectionContext.HandshakeAsync(TimeSpan.FromSeconds(5), _supportedProtocols, _failureHubProtocolResolver,
|
||||
_userIdProvider, enableDetailedErrors: true);
|
||||
}
|
||||
}
|
||||
|
||||
public class TestUserIdProvider : IUserIdProvider
|
||||
{
|
||||
public string GetUserId(HubConnectionContext connection)
|
||||
{
|
||||
return "UserId!";
|
||||
}
|
||||
}
|
||||
|
||||
public class TestHubProtocolResolver : IHubProtocolResolver
|
||||
{
|
||||
private readonly IHubProtocol _instance;
|
||||
|
||||
public IReadOnlyList<IHubProtocol> AllProtocols { get; }
|
||||
|
||||
public TestHubProtocolResolver(IHubProtocol instance)
|
||||
{
|
||||
AllProtocols = new[] { instance };
|
||||
_instance = instance;
|
||||
}
|
||||
|
||||
public IHubProtocol GetProtocol(string protocolName, IReadOnlyList<string> supportedProtocols)
|
||||
{
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading.Tasks;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.Connections;
|
||||
using Microsoft.AspNetCore.Connections.Features;
|
||||
using Microsoft.AspNetCore.SignalR.Client;
|
||||
using Microsoft.AspNetCore.Internal;
|
||||
using Microsoft.AspNetCore.SignalR.Microbenchmarks.Shared;
|
||||
using Microsoft.AspNetCore.SignalR.Tests;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.AspNetCore.SignalR.Protocol;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
||||
{
|
||||
public class HubConnectionSendBenchmark
|
||||
{
|
||||
private HubConnection _hubConnection;
|
||||
private TestDuplexPipe _pipe;
|
||||
private TaskCompletionSource<ReadResult> _tcs;
|
||||
private object[] _arguments;
|
||||
|
||||
[GlobalSetup]
|
||||
public void GlobalSetup()
|
||||
{
|
||||
var writer = MemoryBufferWriter.Get();
|
||||
try
|
||||
{
|
||||
HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, writer);
|
||||
var handshakeResponseResult = new ReadResult(new ReadOnlySequence<byte>(writer.ToArray()), false, false);
|
||||
|
||||
_pipe = new TestDuplexPipe();
|
||||
_pipe.AddReadResult(new ValueTask<ReadResult>(handshakeResponseResult));
|
||||
}
|
||||
finally
|
||||
{
|
||||
MemoryBufferWriter.Return(writer);
|
||||
}
|
||||
|
||||
_tcs = new TaskCompletionSource<ReadResult>();
|
||||
_pipe.AddReadResult(new ValueTask<ReadResult>(_tcs.Task));
|
||||
|
||||
var hubConnectionBuilder = new HubConnectionBuilder();
|
||||
if (Protocol == "json")
|
||||
{
|
||||
// JSON protocol added by default
|
||||
}
|
||||
else
|
||||
{
|
||||
hubConnectionBuilder.AddMessagePackProtocol();
|
||||
}
|
||||
|
||||
var delegateConnectionFactory = new DelegateConnectionFactory(format =>
|
||||
{
|
||||
var connection = new DefaultConnectionContext();
|
||||
// prevents keep alive time being activated
|
||||
connection.Features.Set<IConnectionInherentKeepAliveFeature>(new TestConnectionInherentKeepAliveFeature());
|
||||
connection.Transport = _pipe;
|
||||
return Task.FromResult<ConnectionContext>(connection);
|
||||
},
|
||||
connection =>
|
||||
{
|
||||
connection.Transport.Output.Complete();
|
||||
connection.Transport.Input.Complete();
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
hubConnectionBuilder.Services.AddSingleton<IConnectionFactory>(delegateConnectionFactory);
|
||||
|
||||
_hubConnection = hubConnectionBuilder.Build();
|
||||
_hubConnection.StartAsync().GetAwaiter().GetResult();
|
||||
|
||||
_arguments = new object[ArgumentCount];
|
||||
for (var i = 0; i < _arguments.Length; i++)
|
||||
{
|
||||
_arguments[i] = "Hello world!";
|
||||
}
|
||||
}
|
||||
|
||||
[Params(0, 1, 10, 100)]
|
||||
public int ArgumentCount;
|
||||
|
||||
[Params("json", "messagepack")]
|
||||
public string Protocol;
|
||||
|
||||
[GlobalCleanup]
|
||||
public void GlobalCleanup()
|
||||
{
|
||||
_tcs.SetResult(new ReadResult(default, false, true));
|
||||
_hubConnection.StopAsync().GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task SendAsync()
|
||||
{
|
||||
return _hubConnection.SendCoreAsync("Dummy", _arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading.Tasks;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.Connections;
|
||||
using Microsoft.AspNetCore.Connections.Features;
|
||||
using Microsoft.AspNetCore.SignalR.Client;
|
||||
using Microsoft.AspNetCore.Internal;
|
||||
using Microsoft.AspNetCore.SignalR.Protocol;
|
||||
using Microsoft.AspNetCore.SignalR.Microbenchmarks.Shared;
|
||||
using Microsoft.AspNetCore.SignalR.Tests;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
||||
{
|
||||
public class HubConnectionStartBenchmark
|
||||
{
|
||||
private HubConnection _hubConnection;
|
||||
private TestDuplexPipe _pipe;
|
||||
private ReadResult _handshakeResponseResult;
|
||||
|
||||
[GlobalSetup]
|
||||
public void GlobalSetup()
|
||||
{
|
||||
var writer = MemoryBufferWriter.Get();
|
||||
try
|
||||
{
|
||||
HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, writer);
|
||||
_handshakeResponseResult = new ReadResult(new ReadOnlySequence<byte>(writer.ToArray()), false, false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
MemoryBufferWriter.Return(writer);
|
||||
}
|
||||
|
||||
_pipe = new TestDuplexPipe();
|
||||
|
||||
var hubConnectionBuilder = new HubConnectionBuilder();
|
||||
var delegateConnectionFactory = new DelegateConnectionFactory(format =>
|
||||
{
|
||||
var connection = new DefaultConnectionContext();
|
||||
// prevents keep alive time being activated
|
||||
connection.Features.Set<IConnectionInherentKeepAliveFeature>(new TestConnectionInherentKeepAliveFeature());
|
||||
connection.Transport = _pipe;
|
||||
return Task.FromResult<ConnectionContext>(connection);
|
||||
},
|
||||
connection =>
|
||||
{
|
||||
connection.Transport.Output.Complete();
|
||||
connection.Transport.Input.Complete();
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
hubConnectionBuilder.Services.AddSingleton<IConnectionFactory>(delegateConnectionFactory);
|
||||
|
||||
_hubConnection = hubConnectionBuilder.Build();
|
||||
}
|
||||
|
||||
private void AddHandshakeResponse()
|
||||
{
|
||||
_pipe.AddReadResult(new ValueTask<ReadResult>(_handshakeResponseResult));
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public async Task StartAsync()
|
||||
{
|
||||
AddHandshakeResponse();
|
||||
|
||||
await _hubConnection.StartAsync();
|
||||
await _hubConnection.StopAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public class TestConnectionInherentKeepAliveFeature : IConnectionInherentKeepAliveFeature
|
||||
{
|
||||
public bool HasInherentKeepAlive { get; } = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.SignalR.Protocol;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
||||
{
|
||||
public class HubProtocolBenchmark
|
||||
{
|
||||
private IHubProtocol _hubProtocol;
|
||||
private ReadOnlyMemory<byte> _binaryInput;
|
||||
private TestBinder _binder;
|
||||
private HubMessage _hubMessage;
|
||||
|
||||
[Params(Message.NoArguments, Message.FewArguments, Message.ManyArguments, Message.LargeArguments)]
|
||||
public Message Input { get; set; }
|
||||
|
||||
[Params(Protocol.MsgPack, Protocol.Json)]
|
||||
public Protocol HubProtocol { get; set; }
|
||||
|
||||
[GlobalSetup]
|
||||
public void GlobalSetup()
|
||||
{
|
||||
switch (HubProtocol)
|
||||
{
|
||||
case Protocol.MsgPack:
|
||||
_hubProtocol = new MessagePackHubProtocol();
|
||||
break;
|
||||
case Protocol.Json:
|
||||
_hubProtocol = new JsonHubProtocol();
|
||||
break;
|
||||
}
|
||||
|
||||
switch (Input)
|
||||
{
|
||||
case Message.NoArguments:
|
||||
_hubMessage = new InvocationMessage("Target", Array.Empty<object>());
|
||||
break;
|
||||
case Message.FewArguments:
|
||||
_hubMessage = new InvocationMessage("Target", new object[] { 1, "Foo", 2.0f });
|
||||
break;
|
||||
case Message.ManyArguments:
|
||||
_hubMessage = new InvocationMessage("Target", new object[] { 1, "string", 2.0f, true, (byte)9, new byte[] { 5, 4, 3, 2, 1 }, 'c', 123456789101112L });
|
||||
break;
|
||||
case Message.LargeArguments:
|
||||
_hubMessage = new InvocationMessage("Target", new object[] { new string('F', 10240), new byte[10240] });
|
||||
break;
|
||||
}
|
||||
|
||||
_binaryInput = _hubProtocol.GetMessageBytes(_hubMessage);
|
||||
_binder = new TestBinder(_hubMessage);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void ReadSingleMessage()
|
||||
{
|
||||
var data = new ReadOnlySequence<byte>(_binaryInput);
|
||||
if (!_hubProtocol.TryParseMessage(ref data, _binder, out _))
|
||||
{
|
||||
throw new InvalidOperationException("Failed to read message");
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void WriteSingleMessage()
|
||||
{
|
||||
var bytes = _hubProtocol.GetMessageBytes(_hubMessage);
|
||||
if (bytes.Length != _binaryInput.Length)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to write message");
|
||||
}
|
||||
}
|
||||
|
||||
public enum Protocol
|
||||
{
|
||||
MsgPack = 0,
|
||||
Json = 1
|
||||
}
|
||||
|
||||
public enum Message
|
||||
{
|
||||
NoArguments = 0,
|
||||
FewArguments = 1,
|
||||
ManyArguments = 2,
|
||||
LargeArguments = 3
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
||||
{
|
||||
public class MessageParserBenchmark
|
||||
{
|
||||
private static readonly Random Random = new Random();
|
||||
private byte[] _binaryInput;
|
||||
private byte[] _textInput;
|
||||
|
||||
[Params(32, 64)]
|
||||
public int ChunkSize { get; set; }
|
||||
|
||||
[Params(64, 128)]
|
||||
public int MessageLength { get; set; }
|
||||
|
||||
[IterationSetup]
|
||||
public void Setup()
|
||||
{
|
||||
var buffer = new byte[MessageLength];
|
||||
Random.NextBytes(buffer);
|
||||
var writer = MemoryBufferWriter.Get();
|
||||
try
|
||||
{
|
||||
BinaryMessageFormatter.WriteLengthPrefix(buffer.Length, writer);
|
||||
writer.Write(buffer);
|
||||
_binaryInput = writer.ToArray();
|
||||
}
|
||||
finally
|
||||
{
|
||||
MemoryBufferWriter.Return(writer);
|
||||
}
|
||||
|
||||
buffer = new byte[MessageLength];
|
||||
Random.NextBytes(buffer);
|
||||
writer = MemoryBufferWriter.Get();
|
||||
try
|
||||
{
|
||||
writer.Write(buffer);
|
||||
TextMessageFormatter.WriteRecordSeparator(writer);
|
||||
|
||||
_textInput = writer.ToArray();
|
||||
}
|
||||
finally
|
||||
{
|
||||
MemoryBufferWriter.Return(writer);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void SingleBinaryMessage()
|
||||
{
|
||||
var data = new ReadOnlySequence<byte>(_binaryInput);
|
||||
if (!BinaryMessageParser.TryParseMessage(ref data, out _))
|
||||
{
|
||||
throw new InvalidOperationException("Failed to parse");
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void SingleTextMessage()
|
||||
{
|
||||
var data = new ReadOnlySequence<byte>(_textInput);
|
||||
if (!TextMessageParser.TryParseMessage(ref data, out _))
|
||||
{
|
||||
throw new InvalidOperationException("Failed to parse");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\src\Common\BinaryMessageFormatter.cs" Link="BinaryMessageFormatter.cs" />
|
||||
<Compile Include="..\..\src\Common\BinaryMessageParser.cs" Link="BinaryMessageParser.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Http.Connections.Client\Microsoft.AspNetCore.Http.Connections.Client.csproj" />
|
||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Http.Connections\Microsoft.AspNetCore.Http.Connections.csproj" />
|
||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Core\Microsoft.AspNetCore.SignalR.Core.csproj" />
|
||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Common\Microsoft.AspNetCore.SignalR.Common.csproj" />
|
||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Client.Core\Microsoft.AspNetCore.SignalR.Client.Core.csproj" />
|
||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Protocols.MessagePack\Microsoft.AspNetCore.SignalR.Protocols.MessagePack.csproj" />
|
||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Redis\Microsoft.AspNetCore.SignalR.Redis.csproj" />
|
||||
<ProjectReference Include="..\..\test\Microsoft.AspNetCore.SignalR.Tests.Utils\Microsoft.AspNetCore.SignalR.Tests.Utils.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BenchmarkDotNet" Version="$(BenchmarkDotNetPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.BenchmarkRunner.Sources" Version="$(MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftExtensionsDependencyInjectionPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.ValueStopwatch.Sources" Version="$(MicrosoftExtensionsValueStopwatchSourcesPackageVersion)" PrivateAssets="All" />
|
||||
<PackageReference Include="Moq" Version="$(MoqPackageVersion)" />
|
||||
<PackageReference Include="System.Threading.Channels" Version="$(SystemThreadingChannelsPackageVersion)" />
|
||||
<PackageReference Include="System.Threading.Tasks.Extensions" Version="$(SystemThreadingTasksExtensionsPackageVersion)" />
|
||||
<PackageReference Include="System.Reactive.Linq" Version="$(SystemReactiveLinqPackageVersion)" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.Http.Connections;
|
||||
using Microsoft.AspNetCore.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
||||
{
|
||||
public class NegotiateProtocolBenchmark
|
||||
{
|
||||
private NegotiationResponse _negotiateResponse;
|
||||
private Stream _stream;
|
||||
|
||||
[GlobalSetup]
|
||||
public void GlobalSetup()
|
||||
{
|
||||
_negotiateResponse = new NegotiationResponse
|
||||
{
|
||||
ConnectionId = "d100338e-8c01-4281-92c2-9a967fdeebcb",
|
||||
AvailableTransports = new List<AvailableTransport>
|
||||
{
|
||||
new AvailableTransport
|
||||
{
|
||||
Transport = "WebSockets",
|
||||
TransferFormats = new List<string>
|
||||
{
|
||||
"Text",
|
||||
"Binary"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
_stream = Stream.Null;
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task WriteResponse_MemoryBufferWriter()
|
||||
{
|
||||
var writer = new MemoryBufferWriter();
|
||||
try
|
||||
{
|
||||
NegotiateProtocol.WriteResponse(_negotiateResponse, writer);
|
||||
return writer.CopyToAsync(_stream);
|
||||
}
|
||||
finally
|
||||
{
|
||||
writer.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,210 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.Connections;
|
||||
using Microsoft.AspNetCore.SignalR.Internal;
|
||||
using Microsoft.AspNetCore.SignalR.Protocol;
|
||||
using Microsoft.AspNetCore.SignalR.Redis;
|
||||
using Microsoft.AspNetCore.SignalR.Tests;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using StackExchange.Redis;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
||||
{
|
||||
public class RedisHubLifetimeManagerBenchmark
|
||||
{
|
||||
private RedisHubLifetimeManager<TestHub> _manager1;
|
||||
private RedisHubLifetimeManager<TestHub> _manager2;
|
||||
private TestClient[] _clients;
|
||||
private object[] _args;
|
||||
private readonly List<string> _excludedConnectionIds = new List<string>();
|
||||
private readonly List<string> _sendIds = new List<string>();
|
||||
private readonly List<string> _groups = new List<string>();
|
||||
private readonly List<string> _users = new List<string>();
|
||||
|
||||
private const int ClientCount = 20;
|
||||
|
||||
[Params(2, 20)]
|
||||
public int ProtocolCount { get; set; }
|
||||
|
||||
[GlobalSetup]
|
||||
public void GlobalSetup()
|
||||
{
|
||||
var server = new TestRedisServer();
|
||||
var logger = NullLogger<RedisHubLifetimeManager<TestHub>>.Instance;
|
||||
var protocols = GenerateProtocols(ProtocolCount).ToArray();
|
||||
var options = Options.Create(new RedisOptions()
|
||||
{
|
||||
ConnectionFactory = _ => Task.FromResult<IConnectionMultiplexer>(new TestConnectionMultiplexer(server))
|
||||
});
|
||||
var resolver = new DefaultHubProtocolResolver(protocols, NullLogger<DefaultHubProtocolResolver>.Instance);
|
||||
|
||||
_manager1 = new RedisHubLifetimeManager<TestHub>(logger, options, resolver);
|
||||
_manager2 = new RedisHubLifetimeManager<TestHub>(logger, options, resolver);
|
||||
|
||||
async Task ConnectClient(TestClient client, IHubProtocol protocol, string userId, string groupName)
|
||||
{
|
||||
await _manager2.OnConnectedAsync(HubConnectionContextUtils.Create(client.Connection, protocol, userId));
|
||||
await _manager2.AddToGroupAsync(client.Connection.ConnectionId, "Everyone");
|
||||
await _manager2.AddToGroupAsync(client.Connection.ConnectionId, groupName);
|
||||
}
|
||||
|
||||
// Connect clients
|
||||
_clients = new TestClient[ClientCount];
|
||||
var tasks = new Task[ClientCount];
|
||||
for (var i = 0; i < _clients.Length; i++)
|
||||
{
|
||||
var protocol = protocols[i % ProtocolCount];
|
||||
_clients[i] = new TestClient(protocol: protocol);
|
||||
|
||||
string group;
|
||||
string user;
|
||||
if ((i % 2) == 0)
|
||||
{
|
||||
group = "Evens";
|
||||
user = "EvenUser";
|
||||
_excludedConnectionIds.Add(_clients[i].Connection.ConnectionId);
|
||||
}
|
||||
else
|
||||
{
|
||||
group = "Odds";
|
||||
user = "OddUser";
|
||||
_sendIds.Add(_clients[i].Connection.ConnectionId);
|
||||
}
|
||||
|
||||
tasks[i] = ConnectClient(_clients[i], protocol, user, group);
|
||||
_ = ConsumeAsync(_clients[i]);
|
||||
}
|
||||
|
||||
Task.WaitAll(tasks);
|
||||
|
||||
_groups.Add("Evens");
|
||||
_groups.Add("Odds");
|
||||
_users.Add("EvenUser");
|
||||
_users.Add("OddUser");
|
||||
|
||||
_args = new object[] {"Foo"};
|
||||
}
|
||||
|
||||
private IEnumerable<IHubProtocol> GenerateProtocols(int protocolCount)
|
||||
{
|
||||
for (var i = 0; i < protocolCount; i++)
|
||||
{
|
||||
yield return ((i % 2) == 0)
|
||||
? new WrappedHubProtocol($"json_{i}", new JsonHubProtocol())
|
||||
: new WrappedHubProtocol($"messagepack_{i}", new MessagePackHubProtocol());
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ConsumeAsync(TestClient testClient)
|
||||
{
|
||||
while (await testClient.ReadAsync() != null)
|
||||
{
|
||||
// Just dump the message
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public async Task SendAll()
|
||||
{
|
||||
await _manager1.SendAllAsync("Test", _args);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public async Task SendGroup()
|
||||
{
|
||||
await _manager1.SendGroupAsync("Everyone", "Test", _args);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public async Task SendUser()
|
||||
{
|
||||
await _manager1.SendUserAsync("EvenUser", "Test", _args);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public async Task SendConnection()
|
||||
{
|
||||
await _manager1.SendConnectionAsync(_clients[0].Connection.ConnectionId, "Test", _args);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public async Task SendConnections()
|
||||
{
|
||||
await _manager1.SendConnectionsAsync(_sendIds, "Test", _args);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public async Task SendAllExcept()
|
||||
{
|
||||
await _manager1.SendAllExceptAsync("Test", _args, _excludedConnectionIds);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public async Task SendGroupExcept()
|
||||
{
|
||||
await _manager1.SendGroupExceptAsync("Everyone", "Test", _args, _excludedConnectionIds);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public async Task SendGroups()
|
||||
{
|
||||
await _manager1.SendGroupsAsync(_groups, "Test", _args);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public async Task SendUsers()
|
||||
{
|
||||
await _manager1.SendUsersAsync(_users, "Test", _args);
|
||||
}
|
||||
|
||||
public class TestHub : Hub
|
||||
{
|
||||
}
|
||||
|
||||
private class WrappedHubProtocol : IHubProtocol
|
||||
{
|
||||
private readonly string _name;
|
||||
private readonly IHubProtocol _innerProtocol;
|
||||
|
||||
public string Name => _name;
|
||||
|
||||
public int Version => _innerProtocol.Version;
|
||||
|
||||
public TransferFormat TransferFormat => _innerProtocol.TransferFormat;
|
||||
|
||||
public WrappedHubProtocol(string name, IHubProtocol innerProtocol)
|
||||
{
|
||||
_name = name;
|
||||
_innerProtocol = innerProtocol;
|
||||
}
|
||||
|
||||
public bool TryParseMessage(ref ReadOnlySequence<byte> input, IInvocationBinder binder, out HubMessage message)
|
||||
{
|
||||
return _innerProtocol.TryParseMessage(ref input, binder, out message);
|
||||
}
|
||||
|
||||
public void WriteMessage(HubMessage message, IBufferWriter<byte> output)
|
||||
{
|
||||
_innerProtocol.WriteMessage(message, output);
|
||||
}
|
||||
|
||||
public ReadOnlyMemory<byte> GetMessageBytes(HubMessage message)
|
||||
{
|
||||
return HubProtocolExtensions.GetMessageBytes(this, message);
|
||||
}
|
||||
|
||||
public bool IsVersionSupported(int version)
|
||||
{
|
||||
return _innerProtocol.IsVersionSupported(version);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.Connections;
|
||||
using Microsoft.AspNetCore.SignalR.Protocol;
|
||||
using Microsoft.AspNetCore.SignalR.Redis.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
||||
{
|
||||
public class RedisProtocolBenchmark
|
||||
{
|
||||
private RedisProtocol _protocol;
|
||||
private RedisGroupCommand _groupCommand;
|
||||
private object[] _args;
|
||||
private string _methodName;
|
||||
private IReadOnlyList<string> _excludedConnectionIdsSmall;
|
||||
private IReadOnlyList<string> _excludedConnectionIdsLarge;
|
||||
private byte[] _writtenAck;
|
||||
private byte[] _writtenGroupCommand;
|
||||
private byte[] _writtenInvocationNoExclusions;
|
||||
private byte[] _writtenInvocationSmallExclusions;
|
||||
private byte[] _writtenInvocationLargeExclusions;
|
||||
|
||||
[GlobalSetup]
|
||||
public void GlobalSetup()
|
||||
{
|
||||
_protocol = new RedisProtocol(new [] {
|
||||
new DummyProtocol("protocol1"),
|
||||
new DummyProtocol("protocol2")
|
||||
});
|
||||
|
||||
_groupCommand = new RedisGroupCommand(id: 42, serverName: "Server", GroupAction.Add, groupName: "group", connectionId: "connection");
|
||||
|
||||
// Because of the DummyProtocol, the args don't really matter
|
||||
_args = Array.Empty<object>();
|
||||
_methodName = "Method";
|
||||
|
||||
_excludedConnectionIdsSmall = GenerateIds(2);
|
||||
_excludedConnectionIdsLarge = GenerateIds(20);
|
||||
|
||||
_writtenAck = _protocol.WriteAck(42);
|
||||
_writtenGroupCommand = _protocol.WriteGroupCommand(_groupCommand);
|
||||
_writtenInvocationNoExclusions = _protocol.WriteInvocation(_methodName, _args, null);
|
||||
_writtenInvocationSmallExclusions = _protocol.WriteInvocation(_methodName, _args, _excludedConnectionIdsSmall);
|
||||
_writtenInvocationLargeExclusions = _protocol.WriteInvocation(_methodName, _args, _excludedConnectionIdsLarge);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void WriteAck()
|
||||
{
|
||||
_protocol.WriteAck(42);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void WriteGroupCommand()
|
||||
{
|
||||
_protocol.WriteGroupCommand(_groupCommand);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void WriteInvocationNoExclusions()
|
||||
{
|
||||
_protocol.WriteInvocation(_methodName, _args);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void WriteInvocationSmallExclusions()
|
||||
{
|
||||
_protocol.WriteInvocation(_methodName, _args, _excludedConnectionIdsSmall);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void WriteInvocationLargeExclusions()
|
||||
{
|
||||
_protocol.WriteInvocation(_methodName, _args, _excludedConnectionIdsLarge);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void ReadAck()
|
||||
{
|
||||
_protocol.ReadAck(_writtenAck);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void ReadGroupCommand()
|
||||
{
|
||||
_protocol.ReadGroupCommand(_writtenGroupCommand);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void ReadInvocationNoExclusions()
|
||||
{
|
||||
_protocol.ReadInvocation(_writtenInvocationNoExclusions);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void ReadInvocationSmallExclusions()
|
||||
{
|
||||
_protocol.ReadInvocation(_writtenInvocationSmallExclusions);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void ReadInvocationLargeExclusions()
|
||||
{
|
||||
_protocol.ReadInvocation(_writtenInvocationLargeExclusions);
|
||||
}
|
||||
|
||||
private static IReadOnlyList<string> GenerateIds(int count)
|
||||
{
|
||||
var ids = new string[count];
|
||||
for(var i = 0; i < count; i++)
|
||||
{
|
||||
ids[i] = Guid.NewGuid().ToString("N");
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
private class DummyProtocol: IHubProtocol
|
||||
{
|
||||
private static readonly byte[] _fixedOutput = new byte[] { 0x68, 0x68, 0x6C, 0x6C, 0x6F };
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
public int Version => 1;
|
||||
|
||||
public TransferFormat TransferFormat => TransferFormat.Text;
|
||||
|
||||
public DummyProtocol(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public bool IsVersionSupported(int version) => true;
|
||||
|
||||
public bool TryParseMessage(ref ReadOnlySequence<byte> input, IInvocationBinder binder, out HubMessage message)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void WriteMessage(HubMessage message, IBufferWriter<byte> output)
|
||||
{
|
||||
output.Write(_fixedOutput);
|
||||
}
|
||||
|
||||
public ReadOnlyMemory<byte> GetMessageBytes(HubMessage message)
|
||||
{
|
||||
return HubProtocolExtensions.GetMessageBytes(this, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.Http.Connections.Client.Internal;
|
||||
using Microsoft.AspNetCore.Http.Connections.Internal;
|
||||
using Microsoft.AspNetCore.SignalR.Protocol;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
||||
{
|
||||
public class ServerSentEventsBenchmark
|
||||
{
|
||||
private ServerSentEventsMessageParser _parser;
|
||||
private byte[] _sseFormattedData;
|
||||
private ReadOnlySequence<byte> _rawData;
|
||||
|
||||
[Params(Message.NoArguments, Message.FewArguments, Message.ManyArguments, Message.LargeArguments)]
|
||||
public Message Input { get; set; }
|
||||
|
||||
[Params("json", "json-formatted")]
|
||||
public string Protocol { get; set; }
|
||||
|
||||
[GlobalSetup]
|
||||
public void GlobalSetup()
|
||||
{
|
||||
IHubProtocol protocol;
|
||||
|
||||
if (Protocol == "json")
|
||||
{
|
||||
protocol = new JsonHubProtocol();
|
||||
}
|
||||
else
|
||||
{
|
||||
// New line in result to trigger SSE formatting
|
||||
protocol = new JsonHubProtocol
|
||||
{
|
||||
PayloadSerializer = { Formatting = Formatting.Indented }
|
||||
};
|
||||
}
|
||||
|
||||
HubMessage hubMessage = null;
|
||||
switch (Input)
|
||||
{
|
||||
case Message.NoArguments:
|
||||
hubMessage = new InvocationMessage("Target", Array.Empty<object>());
|
||||
break;
|
||||
case Message.FewArguments:
|
||||
hubMessage = new InvocationMessage("Target", new object[] { 1, "Foo", 2.0f });
|
||||
break;
|
||||
case Message.ManyArguments:
|
||||
hubMessage = new InvocationMessage("Target", new object[] { 1, "string", 2.0f, true, (byte)9, new[] { 5, 4, 3, 2, 1 }, 'c', 123456789101112L });
|
||||
break;
|
||||
case Message.LargeArguments:
|
||||
hubMessage = new InvocationMessage("Target", new object[] { new string('F', 10240), new string('B', 10240) });
|
||||
break;
|
||||
}
|
||||
|
||||
_parser = new ServerSentEventsMessageParser();
|
||||
_rawData = new ReadOnlySequence<byte>(protocol.GetMessageBytes(hubMessage));
|
||||
var ms = new MemoryStream();
|
||||
ServerSentEventsMessageFormatter.WriteMessageAsync(_rawData, ms).GetAwaiter().GetResult();
|
||||
_sseFormattedData = ms.ToArray();
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void ReadSingleMessage()
|
||||
{
|
||||
var buffer = new ReadOnlySequence<byte>(_sseFormattedData);
|
||||
|
||||
if (_parser.ParseMessage(buffer, out _, out _, out _) != ServerSentEventsMessageParser.ParseResult.Completed)
|
||||
{
|
||||
throw new InvalidOperationException("Parse failed!");
|
||||
}
|
||||
|
||||
_parser.Reset();
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task WriteSingleMessage()
|
||||
{
|
||||
return ServerSentEventsMessageFormatter.WriteMessageAsync(_rawData, Stream.Null);
|
||||
}
|
||||
|
||||
public enum Message
|
||||
{
|
||||
NoArguments = 0,
|
||||
FewArguments = 1,
|
||||
ManyArguments = 2,
|
||||
LargeArguments = 3
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Pipelines;
|
||||
using Microsoft.AspNetCore.Connections;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks.Shared
|
||||
{
|
||||
public class TestConnectionContext : ConnectionContext
|
||||
{
|
||||
public override string ConnectionId { get; set; }
|
||||
public override IFeatureCollection Features { get; } = new FeatureCollection();
|
||||
public override IDictionary<object, object> Items { get; set; }
|
||||
public override IDuplexPipe Transport { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks.Shared
|
||||
{
|
||||
public class TestDuplexPipe : IDuplexPipe
|
||||
{
|
||||
private readonly TestPipeReader _input;
|
||||
|
||||
public PipeReader Input => _input;
|
||||
|
||||
public PipeWriter Output { get; }
|
||||
|
||||
public TestDuplexPipe(bool writerForceAsync = false)
|
||||
{
|
||||
_input = new TestPipeReader();
|
||||
Output = new TestPipeWriter
|
||||
{
|
||||
ForceAsync = writerForceAsync
|
||||
};
|
||||
}
|
||||
|
||||
public void AddReadResult(ValueTask<ReadResult> readResult)
|
||||
{
|
||||
_input.ReadResults.Add(readResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks.Shared
|
||||
{
|
||||
public class TestPipeReader : PipeReader
|
||||
{
|
||||
public List<ValueTask<ReadResult>> ReadResults { get; }
|
||||
|
||||
public TestPipeReader()
|
||||
{
|
||||
ReadResults = new List<ValueTask<ReadResult>>();
|
||||
}
|
||||
|
||||
public override void AdvanceTo(SequencePosition consumed)
|
||||
{
|
||||
}
|
||||
|
||||
public override void AdvanceTo(SequencePosition consumed, SequencePosition examined)
|
||||
{
|
||||
}
|
||||
|
||||
public override void CancelPendingRead()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void Complete(Exception exception = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void OnWriterCompleted(Action<Exception, object> callback, object state)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override ValueTask<ReadResult> ReadAsync(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
if (ReadResults.Count == 0)
|
||||
{
|
||||
return new ValueTask<ReadResult>(new ReadResult(default, false, true));
|
||||
}
|
||||
|
||||
var result = ReadResults[0];
|
||||
ReadResults.RemoveAt(0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override bool TryRead(out ReadResult result)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks.Shared
|
||||
{
|
||||
public class TestPipeWriter : PipeWriter
|
||||
{
|
||||
// huge buffer that should be large enough for writing any content
|
||||
private readonly byte[] _buffer = new byte[10000];
|
||||
|
||||
public bool ForceAsync { get; set; }
|
||||
|
||||
public override void Advance(int bytes)
|
||||
{
|
||||
}
|
||||
|
||||
public override Memory<byte> GetMemory(int sizeHint = 0)
|
||||
{
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
public override Span<byte> GetSpan(int sizeHint = 0)
|
||||
{
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
public override void OnReaderCompleted(Action<Exception, object> callback, object state)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void CancelPendingFlush()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void Complete(Exception exception = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override ValueTask<FlushResult> FlushAsync(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
if (!ForceAsync)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
return new ValueTask<FlushResult>(ForceAsyncResult());
|
||||
}
|
||||
|
||||
public async Task<FlushResult> ForceAsyncResult()
|
||||
{
|
||||
return await Task.FromResult<FlushResult>(default).ForceAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.SignalR.Internal;
|
||||
using Microsoft.AspNetCore.SignalR.Protocol;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
||||
{
|
||||
public class TestBinder : IInvocationBinder
|
||||
{
|
||||
private readonly Type[] _paramTypes;
|
||||
private readonly Type _returnType;
|
||||
|
||||
public TestBinder(HubMessage expectedMessage)
|
||||
{
|
||||
switch (expectedMessage)
|
||||
{
|
||||
case StreamInvocationMessage i:
|
||||
_paramTypes = i.Arguments?.Select(a => a?.GetType() ?? typeof(object))?.ToArray();
|
||||
break;
|
||||
case InvocationMessage i:
|
||||
_paramTypes = i.Arguments?.Select(a => a?.GetType() ?? typeof(object))?.ToArray();
|
||||
break;
|
||||
case StreamItemMessage s:
|
||||
_returnType = s.Item?.GetType() ?? typeof(object);
|
||||
break;
|
||||
case CompletionMessage c:
|
||||
_returnType = c.Result?.GetType() ?? typeof(object);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public TestBinder() : this(null, null) { }
|
||||
public TestBinder(Type[] paramTypes) : this(paramTypes, null) { }
|
||||
public TestBinder(Type returnType) : this(null, returnType) { }
|
||||
public TestBinder(Type[] paramTypes, Type returnType)
|
||||
{
|
||||
_paramTypes = paramTypes;
|
||||
_returnType = returnType;
|
||||
}
|
||||
|
||||
public IReadOnlyList<Type> GetParameterTypes(string methodName)
|
||||
{
|
||||
if (_paramTypes != null)
|
||||
{
|
||||
return _paramTypes;
|
||||
}
|
||||
throw new InvalidOperationException("Unexpected binder call");
|
||||
}
|
||||
|
||||
public Type GetReturnType(string invocationId)
|
||||
{
|
||||
if (_returnType != null)
|
||||
{
|
||||
return _returnType;
|
||||
}
|
||||
throw new InvalidOperationException("Unexpected binder call");
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
|
@ -0,0 +1 @@
|
|||
@Library('dotnet-ci') _
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
@Library('dotnet-ci') _
|
||||
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import org.dotnet.ci.pipelines.Pipeline
|
||||
|
||||
def windowsPipeline = Pipeline.createPipeline(this, 'build/buildpipeline/windows.groovy')
|
||||
def linuxPipeline = Pipeline.createPipeline(this, 'build/buildpipeline/linux.groovy')
|
||||
def osxPipeline = Pipeline.createPipeline(this, 'build/buildpipeline/osx.groovy')
|
||||
String configuration = 'Release'
|
||||
def parameters = [
|
||||
'Configuration': configuration
|
||||
]
|
||||
|
||||
windowsPipeline.triggerPipelineOnEveryGithubPR("Windows ${configuration} x64 Build", parameters)
|
||||
windowsPipeline.triggerPipelineOnGithubPush(parameters)
|
||||
|
||||
linuxPipeline.triggerPipelineOnEveryGithubPR("Ubuntu 16.04 ${configuration} Build", parameters)
|
||||
linuxPipeline.triggerPipelineOnGithubPush(parameters)
|
||||
|
||||
osxPipeline.triggerPipelineOnEveryGithubPR("OSX 10.12 ${configuration} Build", parameters)
|
||||
osxPipeline.triggerPipelineOnGithubPush(parameters)
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
@Library('dotnet-ci') _
|
||||
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- These package versions may be overridden or updated by automation. -->
|
||||
<PropertyGroup Label="Package Versions: Auto">
|
||||
<BenchmarkDotNetPackageVersion>0.10.13</BenchmarkDotNetPackageVersion>
|
||||
<GoogleProtobufPackageVersion>3.1.0</GoogleProtobufPackageVersion>
|
||||
<InternalAspNetCoreSdkPackageVersion>2.1.3-rtm-15802</InternalAspNetCoreSdkPackageVersion>
|
||||
<MessagePackPackageVersion>1.7.3.4</MessagePackPackageVersion>
|
||||
<MicrosoftCSharpPackageVersion>4.5.0</MicrosoftCSharpPackageVersion>
|
||||
<MicrosoftNETCoreApp20PackageVersion>2.0.0</MicrosoftNETCoreApp20PackageVersion>
|
||||
<MicrosoftNETCoreApp21PackageVersion>2.1.2</MicrosoftNETCoreApp21PackageVersion>
|
||||
<MicrosoftNETTestSdkPackageVersion>15.6.1</MicrosoftNETTestSdkPackageVersion>
|
||||
<MoqPackageVersion>4.7.49</MoqPackageVersion>
|
||||
<NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion>
|
||||
<NewtonsoftJsonPackageVersion>11.0.2</NewtonsoftJsonPackageVersion>
|
||||
<StackExchangeRedisStrongNamePackageVersion>1.2.4</StackExchangeRedisStrongNamePackageVersion>
|
||||
<SystemBuffersPackageVersion>4.5.0</SystemBuffersPackageVersion>
|
||||
<SystemIOPipelinesPackageVersion>4.5.0</SystemIOPipelinesPackageVersion>
|
||||
<SystemMemoryPackageVersion>4.5.1</SystemMemoryPackageVersion>
|
||||
<SystemNumericsVectorsPackageVersion>4.5.0</SystemNumericsVectorsPackageVersion>
|
||||
<SystemReactiveLinqPackageVersion>3.1.1</SystemReactiveLinqPackageVersion>
|
||||
<SystemReflectionEmitPackageVersion>4.3.0</SystemReflectionEmitPackageVersion>
|
||||
<SystemRuntimeCompilerServicesUnsafePackageVersion>4.5.1</SystemRuntimeCompilerServicesUnsafePackageVersion>
|
||||
<SystemThreadingChannelsPackageVersion>4.5.0</SystemThreadingChannelsPackageVersion>
|
||||
<SystemThreadingTasksExtensionsPackageVersion>4.5.1</SystemThreadingTasksExtensionsPackageVersion>
|
||||
<XunitPackageVersion>2.3.1</XunitPackageVersion>
|
||||
<XunitRunnerVisualStudioPackageVersion>2.4.0-beta.1.build3945</XunitRunnerVisualStudioPackageVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- This may import a generated file which may override the variables above. -->
|
||||
<Import Project="$(DotNetPackageVersionPropsPath)" Condition=" '$(DotNetPackageVersionPropsPath)' != '' " />
|
||||
|
||||
<!-- These are package versions that should not be overridden or updated by automation. -->
|
||||
<PropertyGroup Label="Package Versions: Pinned">
|
||||
<MicrosoftAspNetCoreAllPackageVersion>2.1.2</MicrosoftAspNetCoreAllPackageVersion>
|
||||
<MicrosoftAspNetCoreAuthenticationCookiesPackageVersion>2.1.1</MicrosoftAspNetCoreAuthenticationCookiesPackageVersion>
|
||||
<MicrosoftAspNetCoreAuthenticationCorePackageVersion>2.1.1</MicrosoftAspNetCoreAuthenticationCorePackageVersion>
|
||||
<MicrosoftAspNetCoreAuthenticationJwtBearerPackageVersion>2.1.1</MicrosoftAspNetCoreAuthenticationJwtBearerPackageVersion>
|
||||
<MicrosoftAspNetCoreAuthorizationPackageVersion>2.1.1</MicrosoftAspNetCoreAuthorizationPackageVersion>
|
||||
<MicrosoftAspNetCoreAuthorizationPolicyPackageVersion>2.1.1</MicrosoftAspNetCoreAuthorizationPolicyPackageVersion>
|
||||
<MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>2.1.1</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
|
||||
<MicrosoftAspNetCoreConnectionsAbstractionsPackageVersion>2.1.2</MicrosoftAspNetCoreConnectionsAbstractionsPackageVersion>
|
||||
<MicrosoftAspNetCoreCorsPackageVersion>2.1.1</MicrosoftAspNetCoreCorsPackageVersion>
|
||||
<MicrosoftAspNetCoreDiagnosticsEntityFrameworkCorePackageVersion>2.1.1</MicrosoftAspNetCoreDiagnosticsEntityFrameworkCorePackageVersion>
|
||||
<MicrosoftAspNetCoreDiagnosticsPackageVersion>2.1.1</MicrosoftAspNetCoreDiagnosticsPackageVersion>
|
||||
<MicrosoftAspNetCoreHostingAbstractionsPackageVersion>2.1.1</MicrosoftAspNetCoreHostingAbstractionsPackageVersion>
|
||||
<MicrosoftAspNetCoreHostingPackageVersion>2.1.1</MicrosoftAspNetCoreHostingPackageVersion>
|
||||
<MicrosoftAspNetCoreHttpAbstractionsPackageVersion>2.1.1</MicrosoftAspNetCoreHttpAbstractionsPackageVersion>
|
||||
<MicrosoftAspNetCoreHttpFeaturesPackageVersion>2.1.1</MicrosoftAspNetCoreHttpFeaturesPackageVersion>
|
||||
<MicrosoftAspNetCoreHttpPackageVersion>2.1.1</MicrosoftAspNetCoreHttpPackageVersion>
|
||||
<MicrosoftAspNetCoreIdentityEntityFrameworkCorePackageVersion>2.1.2</MicrosoftAspNetCoreIdentityEntityFrameworkCorePackageVersion>
|
||||
<MicrosoftAspNetCoreMvcPackageVersion>2.1.1</MicrosoftAspNetCoreMvcPackageVersion>
|
||||
<MicrosoftAspNetCoreRoutingPackageVersion>2.1.1</MicrosoftAspNetCoreRoutingPackageVersion>
|
||||
<MicrosoftAspNetCoreServerIISIntegrationPackageVersion>2.1.1</MicrosoftAspNetCoreServerIISIntegrationPackageVersion>
|
||||
<MicrosoftAspNetCoreServerIntegrationTestingPackageVersion>0.5.1</MicrosoftAspNetCoreServerIntegrationTestingPackageVersion>
|
||||
<MicrosoftAspNetCoreServerKestrelPackageVersion>2.1.2</MicrosoftAspNetCoreServerKestrelPackageVersion>
|
||||
<MicrosoftAspNetCoreStaticFilesPackageVersion>2.1.1</MicrosoftAspNetCoreStaticFilesPackageVersion>
|
||||
<MicrosoftAspNetCoreTestHostPackageVersion>2.1.1</MicrosoftAspNetCoreTestHostPackageVersion>
|
||||
<MicrosoftAspNetCoreTestingPackageVersion>2.1.0</MicrosoftAspNetCoreTestingPackageVersion>
|
||||
<MicrosoftAspNetCoreWebSocketsPackageVersion>2.1.1</MicrosoftAspNetCoreWebSocketsPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreDesignPackageVersion>2.1.1</MicrosoftEntityFrameworkCoreDesignPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>2.1.1</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreToolsPackageVersion>2.1.1</MicrosoftEntityFrameworkCoreToolsPackageVersion>
|
||||
<MicrosoftExtensionsBuffersTestingSourcesPackageVersion>2.1.1</MicrosoftExtensionsBuffersTestingSourcesPackageVersion>
|
||||
<MicrosoftExtensionsClosedGenericMatcherSourcesPackageVersion>2.1.1</MicrosoftExtensionsClosedGenericMatcherSourcesPackageVersion>
|
||||
<MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>2.1.1</MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>2.1.1</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
|
||||
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>2.1.1</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationUserSecretsPackageVersion>2.1.1</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
|
||||
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>2.1.1</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsDependencyInjectionPackageVersion>2.1.1</MicrosoftExtensionsDependencyInjectionPackageVersion>
|
||||
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>2.1.1</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsLoggingConfigurationPackageVersion>2.1.1</MicrosoftExtensionsLoggingConfigurationPackageVersion>
|
||||
<MicrosoftExtensionsLoggingConsolePackageVersion>2.1.1</MicrosoftExtensionsLoggingConsolePackageVersion>
|
||||
<MicrosoftExtensionsLoggingDebugPackageVersion>2.1.1</MicrosoftExtensionsLoggingDebugPackageVersion>
|
||||
<MicrosoftExtensionsLoggingPackageVersion>2.1.1</MicrosoftExtensionsLoggingPackageVersion>
|
||||
<MicrosoftExtensionsLoggingTestingPackageVersion>2.1.1</MicrosoftExtensionsLoggingTestingPackageVersion>
|
||||
<MicrosoftExtensionsObjectMethodExecutorSourcesPackageVersion>2.1.1</MicrosoftExtensionsObjectMethodExecutorSourcesPackageVersion>
|
||||
<MicrosoftExtensionsOptionsPackageVersion>2.1.1</MicrosoftExtensionsOptionsPackageVersion>
|
||||
<MicrosoftExtensionsSecurityHelperSourcesPackageVersion>2.1.1</MicrosoftExtensionsSecurityHelperSourcesPackageVersion>
|
||||
<MicrosoftExtensionsValueStopwatchSourcesPackageVersion>2.1.1</MicrosoftExtensionsValueStopwatchSourcesPackageVersion>
|
||||
<MicrosoftExtensionsWebEncodersSourcesPackageVersion>2.1.1</MicrosoftExtensionsWebEncodersSourcesPackageVersion>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<Project>
|
||||
<Import Project="dependencies.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<EnableBenchmarkValidation>true</EnableBenchmarkValidation>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectsToPack Include="$(RepositoryRoot)client-ts\Microsoft.AspNetCore.SignalR.Client.TS\*.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ExcludeFromTest Include="$(RepositoryRoot)test\Microsoft.AspNetCore.SignalR.Tests.Utils\*.csproj" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<!-- These properties are use by the automation that updates dependencies.props -->
|
||||
<LineupPackageId>Internal.AspNetCore.Universe.Lineup</LineupPackageId>
|
||||
<LineupPackageVersion>2.1.0-rc1-*</LineupPackageVersion>
|
||||
<LineupPackageRestoreSource>https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json</LineupPackageRestoreSource>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<DotNetCoreRuntime Include="$(MicrosoftNETCoreApp20PackageVersion)" />
|
||||
<DotNetCoreRuntime Include="$(MicrosoftNETCoreApp21PackageVersion)" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
<Project>
|
||||
<ItemGroup>
|
||||
<NPMPackage Include="$(RepositoryRoot)clients/ts/signalr">
|
||||
<TarName>aspnet-signalr</TarName>
|
||||
<PackageId>@aspnet/signalr</PackageId>
|
||||
</NPMPackage>
|
||||
<NPMPackage Include="$(RepositoryRoot)clients/ts/signalr-protocol-msgpack">
|
||||
<TarName>aspnet-signalr-protocol-msgpack</TarName>
|
||||
<PackageId>@aspnet/signalr-protocol-msgpack</PackageId>
|
||||
</NPMPackage>
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<RestoreDependsOn>$(RestoreDependsOn);RestoreNpm</RestoreDependsOn>
|
||||
</PropertyGroup>
|
||||
<Target Name="RestoreNpm" Condition="'$(PreflightRestore)' != 'True'">
|
||||
<Message Text="Restoring NPM modules" Importance="high" />
|
||||
<Exec Command="npm install --no-optional" WorkingDirectory="$(RepositoryRoot)clients/ts/common" />
|
||||
<Exec Command="npm install --no-optional" WorkingDirectory="$(RepositoryRoot)clients/ts/FunctionalTests" />
|
||||
<Exec Command="npm install --no-optional" WorkingDirectory="$(RepositoryRoot)clients/ts/signalr" />
|
||||
<Exec Command="npm install --no-optional" WorkingDirectory="$(RepositoryRoot)clients/ts/signalr-protocol-msgpack" />
|
||||
<Exec Command="npm install --no-optional" WorkingDirectory="$(RepositoryRoot)clients/ts/webdriver-tap-runner" />
|
||||
</Target>
|
||||
|
||||
<PropertyGroup>
|
||||
<TestDependsOn>$(TestDependsOn);RunTSClientNodeTests;RunBrowserTests</TestDependsOn>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="RunTSClientNodeTests">
|
||||
<Message Text="Running TypeScript client Node tests" Importance="high" />
|
||||
<Exec Command="npm test" WorkingDirectory="$(RepositoryRoot)clients/ts" IgnoreStandardErrorWarningFormat="true" />
|
||||
</Target>
|
||||
|
||||
<Target Name="RunBrowserTests">
|
||||
<Message Text="Running TypeScript client Browser tests" Importance="high" />
|
||||
<Exec Command="npm run build" WorkingDirectory="$(RepositoryRoot)clients/ts/FunctionalTests" IgnoreStandardErrorWarningFormat="true" />
|
||||
<Exec Command="npm run ci-test -- --configuration $(Configuration)" WorkingDirectory="$(RepositoryRoot)clients/ts/FunctionalTests" IgnoreStandardErrorWarningFormat="true" />
|
||||
</Target>
|
||||
|
||||
<PropertyGroup>
|
||||
<GetArtifactInfoDependsOn>$(GetArtifactInfoDependsOn);GetNpmArtifactInfo</GetArtifactInfoDependsOn>
|
||||
<PrepareDependsOn>$(PrepareDependsOn);GetNpmArtifactInfo</PrepareDependsOn>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="GetNpmArtifactInfo">
|
||||
<ItemGroup>
|
||||
<NPMPackage Update="%(NPMPackage)">
|
||||
<PackageJson>$([System.IO.Path]::Combine(%(NPMPackage.FullPath), 'package.json'))</PackageJson>
|
||||
<OutputTar>$([System.IO.Path]::Combine(%(NPMPackage.FullPath), '%(NPMPackage.TarName)-$(PackageVersion).tgz'))</OutputTar>
|
||||
<ArtifactPath>$([System.IO.Path]::Combine($(BuildDir), '%(NPMPackage.TarName)-$(PackageVersion).tgz'))</ArtifactPath>
|
||||
</NPMPackage>
|
||||
|
||||
<ArtifactInfo Include="%(NPMPackage.ArtifactPath)">
|
||||
<ArtifactType>NpmPackage</ArtifactType>
|
||||
<PackageId>%(NPMPackage.PackageId)</PackageId>
|
||||
<Version>$(PackageVersion)</Version>
|
||||
<Category>ship</Category>
|
||||
</ArtifactInfo>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<FilesToExcludeFromSigning Include="%(NPMPackage.ArtifactPath)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<PropertyGroup>
|
||||
<CompileDependsOn>Restore;BuildNPMPackages;$(CompileDependsOn)</CompileDependsOn>
|
||||
</PropertyGroup>
|
||||
<Target Name="BuildNPMPackages" DependsOnTargets="RestoreNpm;GetNpmArtifactInfo">
|
||||
<Message Text="Building %(NPMPackage.PackageId)..." Importance="high" />
|
||||
<Exec Command="npm run build" WorkingDirectory="%(NPMPackage.FullPath)" />
|
||||
</Target>
|
||||
|
||||
<PropertyGroup>
|
||||
<PackageDependsOn>Compile;PackNPMPackages;$(PackageDependsOn)</PackageDependsOn>
|
||||
</PropertyGroup>
|
||||
<Target Name="PackNPMPackages" DependsOnTargets="BuildNPMPackages">
|
||||
<Message Text="Packing %(NPMPackage.PackageId)..." Importance="high" />
|
||||
<Copy SourceFiles="%(NPMPackage.PackageJson)" DestinationFiles="%(NPMPackage.PackageJson).bak" />
|
||||
<Exec Command="npm --no-git-tag-version --allow-same-version version $(PackageVersion)" WorkingDirectory="%(NPMPackage.FullPath)" />
|
||||
<Exec Command="npm pack" WorkingDirectory="%(NPMPackage.FullPath)" />
|
||||
<Delete Files="%(NPMPackage.ArtifactPath)" Condition="Exists('%(NPMPackage.ArtifactPath)')" />
|
||||
<Move SourceFiles="%(NPMPackage.OutputTar)" DestinationFiles="%(NPMPackage.ArtifactPath)" />
|
||||
<Move SourceFiles="%(NPMPackage.PackageJson).bak" DestinationFiles="%(NPMPackage.PackageJson)" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<Project>
|
||||
<Import Project="$(DotNetRestoreSourcePropsPath)" Condition="'$(DotNetRestoreSourcePropsPath)' != ''"/>
|
||||
|
||||
<PropertyGroup Label="RestoreSources">
|
||||
<RestoreSources>$(DotNetRestoreSources)</RestoreSources>
|
||||
<RestoreSources Condition="'$(DotNetBuildOffline)' != 'true' AND '$(AspNetUniverseBuildOffline)' != 'true' ">
|
||||
$(RestoreSources);
|
||||
https://dotnet.myget.org/F/dotnet-core/api/v3/index.json;
|
||||
https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json;
|
||||
https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json;
|
||||
</RestoreSources>
|
||||
<RestoreSources Condition="'$(DotNetBuildOffline)' != 'true'">
|
||||
$(RestoreSources);
|
||||
https://api.nuget.org/v3/index.json;
|
||||
</RestoreSources>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<solution>
|
||||
<add key="disableSourceControlIntegration" value="true" />
|
||||
</solution>
|
||||
</configuration>
|
||||
Binary file not shown.
|
|
@ -0,0 +1,144 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">$(MSBuildProjectDirectory)\..\</SolutionDir>
|
||||
|
||||
<!-- Enable the restore command to run before builds -->
|
||||
<RestorePackages Condition=" '$(RestorePackages)' == '' ">false</RestorePackages>
|
||||
|
||||
<!-- Property that enables building a package from a project -->
|
||||
<BuildPackage Condition=" '$(BuildPackage)' == '' ">false</BuildPackage>
|
||||
|
||||
<!-- Determines if package restore consent is required to restore packages -->
|
||||
<RequireRestoreConsent Condition=" '$(RequireRestoreConsent)' != 'false' ">true</RequireRestoreConsent>
|
||||
|
||||
<!-- Download NuGet.exe if it does not already exist -->
|
||||
<DownloadNuGetExe Condition=" '$(DownloadNuGetExe)' == '' ">false</DownloadNuGetExe>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(PackageSources)' == '' ">
|
||||
<!-- Package sources used to restore packages. By default, registered sources under %APPDATA%\NuGet\NuGet.Config will be used -->
|
||||
<!-- The official NuGet package source (https://www.nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list -->
|
||||
<!--
|
||||
<PackageSource Include="https://www.nuget.org/api/v2/" />
|
||||
<PackageSource Include="https://my-nuget-source/nuget/" />
|
||||
-->
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT'">
|
||||
<!-- Windows specific commands -->
|
||||
<NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(OS)' != 'Windows_NT'">
|
||||
<!-- We need to launch nuget.exe with the mono command if we're not on windows -->
|
||||
<NuGetToolsPath>$(SolutionDir).nuget</NuGetToolsPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<PackagesProjectConfig Condition=" '$(OS)' == 'Windows_NT'">$(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config</PackagesProjectConfig>
|
||||
<PackagesProjectConfig Condition=" '$(OS)' != 'Windows_NT'">$(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config</PackagesProjectConfig>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<PackagesConfig Condition="Exists('$(MSBuildProjectDirectory)\packages.config')">$(MSBuildProjectDirectory)\packages.config</PackagesConfig>
|
||||
<PackagesConfig Condition="Exists('$(PackagesProjectConfig)')">$(PackagesProjectConfig)</PackagesConfig>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- NuGet command -->
|
||||
<NuGetExePath Condition=" '$(NuGetExePath)' == '' ">$(NuGetToolsPath)\NuGet.exe</NuGetExePath>
|
||||
<PackageSources Condition=" $(PackageSources) == '' ">@(PackageSource)</PackageSources>
|
||||
|
||||
<NuGetCommand Condition=" '$(OS)' == 'Windows_NT'">"$(NuGetExePath)"</NuGetCommand>
|
||||
<NuGetCommand Condition=" '$(OS)' != 'Windows_NT' ">mono --runtime=v4.0.30319 "$(NuGetExePath)"</NuGetCommand>
|
||||
|
||||
<PackageOutputDir Condition="$(PackageOutputDir) == ''">$(TargetDir.Trim('\\'))</PackageOutputDir>
|
||||
|
||||
<RequireConsentSwitch Condition=" $(RequireRestoreConsent) == 'true' ">-RequireConsent</RequireConsentSwitch>
|
||||
<NonInteractiveSwitch Condition=" '$(VisualStudioVersion)' != '' AND '$(OS)' == 'Windows_NT' ">-NonInteractive</NonInteractiveSwitch>
|
||||
|
||||
<PaddedSolutionDir Condition=" '$(OS)' == 'Windows_NT'">"$(SolutionDir) "</PaddedSolutionDir>
|
||||
<PaddedSolutionDir Condition=" '$(OS)' != 'Windows_NT' ">"$(SolutionDir)"</PaddedSolutionDir>
|
||||
|
||||
<!-- Commands -->
|
||||
<RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)</RestoreCommand>
|
||||
<BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols</BuildCommand>
|
||||
|
||||
<!-- We need to ensure packages are restored prior to assembly resolve -->
|
||||
<BuildDependsOn Condition="$(RestorePackages) == 'true'">
|
||||
RestorePackages;
|
||||
$(BuildDependsOn);
|
||||
</BuildDependsOn>
|
||||
|
||||
<!-- Make the build depend on restore packages -->
|
||||
<BuildDependsOn Condition="$(BuildPackage) == 'true'">
|
||||
$(BuildDependsOn);
|
||||
BuildPackage;
|
||||
</BuildDependsOn>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="CheckPrerequisites">
|
||||
<!-- Raise an error if we're unable to locate nuget.exe -->
|
||||
<Error Condition="'$(DownloadNuGetExe)' != 'true' AND !Exists('$(NuGetExePath)')" Text="Unable to locate '$(NuGetExePath)'" />
|
||||
<!--
|
||||
Take advantage of MsBuild's build dependency tracking to make sure that we only ever download nuget.exe once.
|
||||
This effectively acts as a lock that makes sure that the download operation will only happen once and all
|
||||
parallel builds will have to wait for it to complete.
|
||||
-->
|
||||
<MsBuild Targets="_DownloadNuGet" Projects="$(MSBuildThisFileFullPath)" Properties="Configuration=NOT_IMPORTANT;DownloadNuGetExe=$(DownloadNuGetExe)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_DownloadNuGet">
|
||||
<DownloadNuGet OutputFilename="$(NuGetExePath)" Condition=" '$(DownloadNuGetExe)' == 'true' AND !Exists('$(NuGetExePath)')" />
|
||||
</Target>
|
||||
|
||||
<Target Name="RestorePackages" DependsOnTargets="CheckPrerequisites">
|
||||
<Exec Command="$(RestoreCommand)"
|
||||
Condition="'$(OS)' != 'Windows_NT' And Exists('$(PackagesConfig)')" />
|
||||
|
||||
<Exec Command="$(RestoreCommand)"
|
||||
LogStandardErrorAsError="true"
|
||||
Condition="'$(OS)' == 'Windows_NT' And Exists('$(PackagesConfig)')" />
|
||||
</Target>
|
||||
|
||||
<Target Name="BuildPackage" DependsOnTargets="CheckPrerequisites">
|
||||
<Exec Command="$(BuildCommand)"
|
||||
Condition=" '$(OS)' != 'Windows_NT' " />
|
||||
|
||||
<Exec Command="$(BuildCommand)"
|
||||
LogStandardErrorAsError="true"
|
||||
Condition=" '$(OS)' == 'Windows_NT' " />
|
||||
</Target>
|
||||
|
||||
<UsingTask TaskName="DownloadNuGet" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
|
||||
<ParameterGroup>
|
||||
<OutputFilename ParameterType="System.String" Required="true" />
|
||||
</ParameterGroup>
|
||||
<Task>
|
||||
<Reference Include="System.Core" />
|
||||
<Using Namespace="System" />
|
||||
<Using Namespace="System.IO" />
|
||||
<Using Namespace="System.Net" />
|
||||
<Using Namespace="Microsoft.Build.Framework" />
|
||||
<Using Namespace="Microsoft.Build.Utilities" />
|
||||
<Code Type="Fragment" Language="cs">
|
||||
<![CDATA[
|
||||
try {
|
||||
OutputFilename = Path.GetFullPath(OutputFilename);
|
||||
|
||||
Log.LogMessage("Downloading latest version of NuGet.exe...");
|
||||
WebClient webClient = new WebClient();
|
||||
webClient.DownloadFile("https://dist.nuget.org/win-x86-commandline/latest/nuget.exe", OutputFilename);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Log.LogErrorFromException(ex);
|
||||
return false;
|
||||
}
|
||||
]]>
|
||||
</Code>
|
||||
</Task>
|
||||
</UsingTask>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildThisFileDirectory)Version.props" />
|
||||
<PropertyGroup>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or '$(SolutionDir)' == '*Undefined*'">$(MSBuildThisFileDirectory)..\</SolutionDir>
|
||||
<Configuration Condition="'$(Configuration)'==''">Debug</Configuration>
|
||||
<Platform Condition="'$(Platform)'==''">Win32</Platform>
|
||||
<PlatformToolset Condition=" '$(PlatformToolset)' == '' And '$(VisualStudioVersion)' == '12.0'">v120</PlatformToolset>
|
||||
<PlatformToolset Condition=" '$(PlatformToolset)' == '' And '$(VisualStudioVersion)' == '14.0'">v140</PlatformToolset>
|
||||
<PlatformToolset Condition=" '$(PlatformToolset)' == ''">v140</PlatformToolset>
|
||||
<SubSystem Condition="'$(SubSystem)' != 'UWP'">Desktop</SubSystem>
|
||||
<OutDir Condition="'$(OutDir)' == ''">$(SolutionDir)bin\$(SubSystem)\$(Platform)\$(Configuration)\</OutDir>
|
||||
<SignalrClientTargetName>signalrclient</SignalrClientTargetName>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Test" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<UsingTask TaskName="ExecAsync" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll">
|
||||
<ParameterGroup>
|
||||
<Executable ParameterType="System.String" Required="true" />
|
||||
<Arguments ParameterType="System.String" Required="false" />
|
||||
</ParameterGroup>
|
||||
<Task>
|
||||
<Using Namespace="System.IO" />
|
||||
<Using Namespace="System.Diagnostics" />
|
||||
<Code Type="Fragment" Language="cs">
|
||||
<![CDATA[
|
||||
Log.LogMessage("Executable {0}...", Executable);
|
||||
var name = System.IO.Path.GetFileNameWithoutExtension(Executable);
|
||||
Log.LogMessage("Starting {0}...", name);
|
||||
var processStartInfo = new ProcessStartInfo(Executable, Arguments) { UseShellExecute = true };
|
||||
Process.Start(processStartInfo);
|
||||
Log.LogMessage("Finished starting process {0}.", name);
|
||||
]]>
|
||||
</Code>
|
||||
</Task>
|
||||
</UsingTask>
|
||||
|
||||
<UsingTask TaskName="Sleep" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll">
|
||||
<ParameterGroup>
|
||||
<TimeoutMs ParameterType="System.Int32" Required="true" />
|
||||
</ParameterGroup>
|
||||
<Task>
|
||||
<Code Type="Fragment" Language="cs">
|
||||
<![CDATA[System.Threading.Thread.Sleep(TimeoutMs);]]>
|
||||
</Code>
|
||||
</Task>
|
||||
</UsingTask>
|
||||
|
||||
<UsingTask TaskName="ZipDir" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll">
|
||||
<ParameterGroup>
|
||||
<InputDir ParameterType="System.String" Required="true" />
|
||||
<OutputFileName ParameterType="System.String" Required="true" />
|
||||
<IncludeBaseDir ParameterType="System.Boolean" Required="false" />
|
||||
</ParameterGroup>
|
||||
<Task>
|
||||
<Reference Include="System.IO.Compression.FileSystem" />
|
||||
<Using Namespace="System.IO.Compression" />
|
||||
<Code Type="Fragment" Language="cs">
|
||||
<![CDATA[ ZipFile.CreateFromDirectory(InputDir, OutputFileName, CompressionLevel.Optimal, IncludeBaseDir); ]]>
|
||||
</Code>
|
||||
</Task>
|
||||
</UsingTask>
|
||||
|
||||
<UsingTask TaskName="RegexReplaceInFile" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll">
|
||||
<ParameterGroup>
|
||||
<InputFilename ParameterType="System.String" Required="true" />
|
||||
<OutputFilename ParameterType="System.String" Required="true" />
|
||||
<Pattern ParameterType="System.String" Required="true" />
|
||||
<Replacement ParameterType="System.String" Required="true" />
|
||||
</ParameterGroup>
|
||||
<Task>
|
||||
<Using Namespace="System.IO" />
|
||||
<Using Namespace="System.Linq" />
|
||||
<Using Namespace="System.Text.RegularExpressions" />
|
||||
<Code Type="Fragment" Language="cs">
|
||||
<![CDATA[
|
||||
string contents;
|
||||
using (var input = new StreamReader(InputFilename))
|
||||
{
|
||||
contents = input.ReadToEnd();
|
||||
}
|
||||
|
||||
contents = new Regex(Pattern, RegexOptions.Compiled | RegexOptions.Multiline)
|
||||
.Replace(contents, Replacement);
|
||||
|
||||
using (var output = new StreamWriter(OutputFilename))
|
||||
{
|
||||
output.Write(contents);
|
||||
}
|
||||
]]>
|
||||
</Code>
|
||||
</Task>
|
||||
</UsingTask>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildThisFileDirectory)\Common.Build.Settings" />
|
||||
<PropertyGroup>
|
||||
<DownloadNuGetExe Condition=" '$(DownloadNuGetExe)' == '' ">true</DownloadNuGetExe>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(SubSystem)' == 'UWP'">
|
||||
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
|
||||
<AppContainerApplication>true</AppContainerApplication>
|
||||
<ApplicationType>Windows Store</ApplicationType>
|
||||
<WindowsTargetPlatformVersion>10.0.10586.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformMinVersion>10.0.10240.0</WindowsTargetPlatformMinVersion>
|
||||
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
|
||||
<GenerateProjectSpecificOutputFolder>False</GenerateProjectSpecificOutputFolder>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError Condition="'$(TreatWarningsAsErrors)' != ''">true</TreatWarningAsError>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<StringPooling>true</StringPooling>
|
||||
<CompileAsWinRT Condition="'$(SubSystem)' == 'UWP'">true</CompileAsWinRT>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem Condition="'$(SubSystem)' != 'UWP'">Windows</SubSystem>
|
||||
<SubSystem Condition="'$(SubSystem)' == 'UWP'">Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
|
||||
<StripPrivateSymbols>$(OutDir)$(TargetName).pub.pdb</StripPrivateSymbols>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<Profile>true</Profile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_WIN64;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_WIN64;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<!-- When changing version remember to update version in $src\signalrclient\constants.h -->
|
||||
<SignalRClientCppVersionMajor>1</SignalRClientCppVersionMajor>
|
||||
<SignalRClientCppVersionMinor>0</SignalRClientCppVersionMinor>
|
||||
<SignalRClientCppVersionPatch>0</SignalRClientCppVersionPatch>
|
||||
<SignalRClientCppVersionSuffix>-alpha0</SignalRClientCppVersionSuffix>
|
||||
<!-- $(build_number) generated by Team City -->
|
||||
<SignalRClientCppVersionSuffix Condition="'$(build_number)' != '' And '$(build_branch)' != 'release'">$(SignalRClientCppVersionSuffix)-$(build_number)</SignalRClientCppVersionSuffix>
|
||||
<SignalRClientCppVersionString>$(SignalRClientCppVersionMajor).$(SignalRClientCppVersionMinor).$(SignalRClientCppVersionPatch)$(SignalRClientCppVersionSuffix)</SignalRClientCppVersionString>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Test" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildThisFileDirectory)\Common.tasks" />
|
||||
<Import Project="$(MSBuildThisFileDirectory)\Common.Build.Settings" />
|
||||
|
||||
<ItemGroup>
|
||||
<Projects Include="$(SolutionDir)src\signalrclientdll\Build\VS\signalrclientdll.vcxproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<TestProjects Include="$(SolutionDir)src\signalrclient\Build\VS\signalrclient.vcxproj" />
|
||||
<TestProjects Include="$(SolutionDir)test\signalrclienttests\Build\VS\signalrclienttests.vcxproj" />
|
||||
<TestProjects Include="$(SolutionDir)test\signalrclient-e2e-tests\Build\VS\signalrclient-e2e-tests.vcxproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ManagedProjects Include="$(SolutionDir)test\signalrclient-testhost\signalrclient-testhost.csproj" />
|
||||
<!--
|
||||
<ManagedProjects Include="$(SolutionDir)\samples\SignalRServer\SignalRServer.csproj" />
|
||||
-->
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!--
|
||||
<SampleProjects Include="$(SolutionDir)\samples\PersistentConnectionSample\PersistentConnectionSample.vcxproj" />
|
||||
<SampleProjects Include="$(SolutionDir)\samples\HubConnectionSample\HubConnectionSample.vcxproj" />
|
||||
-->
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
|
||||
|
||||
<Target Name="Build">
|
||||
<MSBuild Targets="RestorePackages" Projects="@(Projects)" />
|
||||
<MSBuild Targets="RestorePackages" Projects="@(SampleProjects)" />
|
||||
<MSBuild Targets="RestorePackages" Projects="@(ManagedProjects)" />
|
||||
|
||||
<MSBuild Targets="$(BuildTargets)"
|
||||
Projects="@(Projects)"
|
||||
Properties="Configuration=$(Configuration);Platform=$(Platform);PlatformToolset=$(PlatformToolset);SubSystem=$(SubSystem)" />
|
||||
|
||||
<MSBuild Targets="$(BuildTargets)"
|
||||
Projects="@(TestProjects)"
|
||||
Properties="Configuration=$(Configuration);Platform=$(Platform);PlatformToolset=$(PlatformToolset)" Condition="'$(SubSystem)' == 'Desktop'"/>
|
||||
|
||||
<MSBuild Targets="$(BuildTargets)"
|
||||
Projects="@(SampleProjects)"
|
||||
Properties="Configuration=$(Configuration);Platform=$(Platform);PlatformToolset=$(PlatformToolset)" Condition="'$(SubSystem)' == 'Desktop'"/>
|
||||
|
||||
<MSBuild Targets="$(BuildTargets)"
|
||||
Projects="@(ManagedProjects)"
|
||||
Properties="Configuration=$(Configuration)" Condition="'$(SubSystem)' == 'Desktop'"/>
|
||||
</Target>
|
||||
|
||||
<Target Name="Clean">
|
||||
<MSBuild Targets="Clean"
|
||||
Projects="@(Projects)" />
|
||||
<MSBuild Targets="Clean"
|
||||
Projects="@(TestProjects)" />
|
||||
<MSBuild Targets="Clean"
|
||||
Projects="@(SampleProjects)" />
|
||||
<MSBuild Targets="Clean"
|
||||
Projects="@(ManagedProjects)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="Rebuild">
|
||||
<MSBuild Targets="Clean;Build"
|
||||
Projects="$(MSBuildProjectFile)"
|
||||
Properties="BuildTargets=Rebuild;Configuration=$(Configuration);Platform=$(Platform);PlatformToolset=$(PlatformToolset);SubSystem=$(SubSystem)"/>
|
||||
</Target>
|
||||
|
||||
<Target Name="Test" DependsOnTargets="Build" Condition="'$(SubSystem)' == 'Desktop'">
|
||||
<Exec Command="$(OutDir)\signalrclienttests.exe --gtest_output=xml:$(OutDir)test_results.xml" />
|
||||
<ExecAsync Executable="$(SolutionDir)test\signalrclient-testhost\bin\$(Configuration)\signalrclient-testhost.exe" Arguments="60000" />
|
||||
<!-- give the host some time to open the port otherwise the first tests may fail on slow machines-->
|
||||
<Sleep TimeoutMs="3000" />
|
||||
<Exec Command="$(OutDir)\signalrclient-e2e-tests.exe --gtest_output=xml:$(OutDir)e2e_test_results.xml" />
|
||||
<Exec Command="taskkill /IM signalrclient-testhost.exe /F" ContinueOnError="true" />
|
||||
</Target>
|
||||
|
||||
<Import Project="Config.Definitions.Props" />
|
||||
|
||||
<Target Name="CreatePackage">
|
||||
<PropertyGroup>
|
||||
<PlatformToolset Condition="'$(PlatformToolset)' == ''">v140</PlatformToolset>
|
||||
<SubSystem Condition="'$(SubSystem)' != 'UWP'">Desktop</SubSystem>
|
||||
<PackageSource>$(SolutionDir)bin\Package\$(SubSystem)\$(PlatformToolset)\</PackageSource>
|
||||
<PackageSourceNative>$(PackageSource)build\native\</PackageSourceNative>
|
||||
<NuGetArtifactsPath>$(MSBuildThisFileDirectory)..\NuGet\</NuGetArtifactsPath>
|
||||
<NuSpecTemplatePath>$(NuGetArtifactsPath)signalrclientcpp.nuspec.template</NuSpecTemplatePath>
|
||||
<PackageOutputDir>$(SolutionDir)artifacts\build</PackageOutputDir>
|
||||
<PrivateSymbols>$(SolutionDir)bin\Symbols\$(SubSystem)\$(PlatformToolset)\</PrivateSymbols>
|
||||
</PropertyGroup>
|
||||
|
||||
<Error Text="UWP not supported with v120 toolset" Condition="'$(SubSystem)' == 'UWP' And '$(PlatformToolset)' != 'v140'" />
|
||||
|
||||
<ItemGroup>
|
||||
<Include Include="$(SolutionDir)include\**\*.*" />
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="@(Include)" DestinationFolder="$(PackageSourceNative)include\%(RecursiveDir)" />
|
||||
<MakeDir Directories="$(PackageSource)" />
|
||||
|
||||
<RegexReplaceInFile InputFileName="$(NuSpecTemplatePath)" OutputFileName="$(PackageSource)signalrclientcpp.nuspec" Pattern="#Toolset#" Replacement="$(PlatformToolset)" />
|
||||
<RegexReplaceInFile InputFileName="$(PackageSource)signalrclientcpp.nuspec" OutputFileName="$(PackageSource)signalrclientcpp.nuspec" Pattern="#casablanca-subsystem#" Replacement="windesktop" Condition="'$(SubSystem)' == 'Desktop'" />
|
||||
<RegexReplaceInFile InputFileName="$(PackageSource)signalrclientcpp.nuspec" OutputFileName="$(PackageSource)signalrclientcpp.nuspec" Pattern="#SubSystem#" Replacement="WinDesktop" Condition="'$(SubSystem)' == 'Desktop'" />
|
||||
<RegexReplaceInFile InputFileName="$(PackageSource)signalrclientcpp.nuspec" OutputFileName="$(PackageSource)signalrclientcpp.nuspec" Pattern="#casablanca-subsystem#" Replacement="winapp" Condition="'$(SubSystem)' == 'UWP'" />
|
||||
<RegexReplaceInFile InputFileName="$(PackageSource)signalrclientcpp.nuspec" OutputFileName="$(PackageSource)signalrclientcpp.nuspec" Pattern="#SubSystem#" Replacement="UWP" Condition="'$(SubSystem)' == 'UWP'" />
|
||||
|
||||
<RegexReplaceInFile InputFileName="$(NuGetArtifactsPath)\Microsoft.AspNet.SignalR.Client.Cpp.WinDesktop.targets.template"
|
||||
OutputFileName="$(PackageSourceNative)Microsoft.AspNet.SignalR.Client.Cpp.$(PlatformToolset).WinDesktop.targets" Pattern="#Toolset#" Replacement="$(PlatformToolset)" Condition="'$(SubSystem)' == 'Desktop'" />
|
||||
<RegexReplaceInFile InputFileName="$(NuGetArtifactsPath)\Microsoft.AspNet.SignalR.Client.Cpp.UWP.targets.template"
|
||||
OutputFileName="$(PackageSourceNative)Microsoft.AspNet.SignalR.Client.Cpp.$(PlatformToolset).UWP.targets" Pattern="#Toolset#" Replacement="$(PlatformToolset)" Condition="'$(SubSystem)' == 'UWP'" />
|
||||
|
||||
<MSBuild Targets="RestorePackages" Projects="@(Projects)" />
|
||||
|
||||
<MSBuild Targets="BuildForNuget"
|
||||
Projects="$(MSBuildThisFile)" Properties="PackageSourceNative=$(PackageSourceNative);PrivateSymbols=$(PrivateSymbols);Configuration=%(ProjectConfiguration.Configuration);Platform=%(ProjectConfiguration.Platform);PlatformToolset=$(PlatformToolset);SubSystem=$(SubSystem);SignalrClientTargetName=$(SignalrClientTargetName)" />
|
||||
|
||||
<MakeDir Directories="$(PackageOutputDir)" />
|
||||
<Exec Command="$(NuGetCommand) pack $(PackageSource)signalrclientcpp.nuspec -BasePath $(PackageSource) -OutputDirectory $(PackageOutputDir) -Version $(SignalRClientCppVersionString)" LogStandardErrorAsError="true" />
|
||||
|
||||
<ZipDir InputDir="$(PrivateSymbols)" OutputFileName="$(PackageOutputDir)\Symbols_$(PlatformToolset)_$(SubSystem).zip" IncludeBaseDir="false"/>
|
||||
</Target>
|
||||
|
||||
<Target Name="BuildForNuget">
|
||||
<MSBuild Targets="$(BuildTargets)"
|
||||
Projects="@(Projects)"
|
||||
Properties="Configuration=$(Configuration);Platform=$(Platform);PlatformToolset=$(PlatformToolset);SubSystem=$(SubSystem)" />
|
||||
|
||||
<Copy SourceFiles="$(OutDir)dll\$(SignalrClientTargetName).lib" DestinationFolder="$(PackageSourceNative)lib\$(Platform)\$(PlatformToolset)\$(Configuration)" />
|
||||
|
||||
<Copy SourceFiles="$(OutDir)dll\$(SignalrClientTargetName).dll" DestinationFolder="$(PackageSourceNative)dll\$(Platform)\$(PlatformToolset)\$(Configuration)" />
|
||||
<Copy SourceFiles="$(OutDir)dll\$(SignalrClientTargetName).pub.pdb" DestinationFiles="$(PackageSourceNative)dll\$(Platform)\$(PlatformToolset)\$(Configuration)\$(SignalrClientTargetName).pdb" />
|
||||
<Copy SourceFiles="$(OutDir)dll\$(SignalrClientTargetName).pdb" DestinationFiles="$(PrivateSymbols)$(Platform)\$(PlatformToolset)\$(Configuration)\$(SignalrClientTargetName).pdb" />
|
||||
</Target>
|
||||
|
||||
<Target Name="NuGetPush">
|
||||
<PropertyGroup>
|
||||
<NuGetExePath Condition="'$(NuGetExePath)' == ''">$(PUSH_NUGET_EXE)</NuGetExePath>
|
||||
<NuGetExePath Condition="'$(NuGetExePath)' == ''">$(MSBuildThisFileDirectory)..\.nuget\NuGet.exe</NuGetExePath>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Package Include="$(SolutionDir)artifacts\build\*.nupkg" />
|
||||
<Package Include="$(SolutionDir)artifacts\build\*.symbols.nupkg" />
|
||||
</ItemGroup>
|
||||
<Exec Command="$(NuGetExePath) push -nosymbols %(Package.Identity) -Source $(NUGET_PUBLISH_FEED) -ApiKey $(APIKEY)" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
cmake_minimum_required (VERSION 2.8.11)
|
||||
project (signalrclient)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC -L -lcpprest")
|
||||
|
||||
set(CPPREST_INCLUDE_DIR "" CACHE FILEPATH "Path to casablanca include dir")
|
||||
|
||||
include_directories (
|
||||
include
|
||||
"${CPPREST_INCLUDE_DIR}")
|
||||
|
||||
find_library(CPPREST_SO NAMES "cpprest" PATHS ${CPPREST_LIB_DIR} REQUIRED)
|
||||
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
|
||||
|
||||
add_subdirectory(src/signalrclient)
|
||||
add_subdirectory(test)
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
Contributing
|
||||
======
|
||||
|
||||
Information on contributing to this repo is in the [Contributing Guide](https://github.com/aspnet/Home/blob/dev/CONTRIBUTING.md) in the Home repo.
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="nuget" value="https://api.nuget.org/v3/index.json" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" InitialTargets="signalrclient_uwp_inittarget">
|
||||
|
||||
<PropertyGroup Condition="'$(PlatformToolset)' != 'v140' Or '$(ApplicationType)' != 'Windows Store'">
|
||||
<DisableUwp>True</DisableUwp>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemDefinitionGroup Condition="'$(DisableUwp)' == ''">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemDefinitionGroup Label="x64 and #Toolset# and Release" Condition="'$(DisableUwp)' == '' And '$(Platform)' == 'x64' And '$(PlatformToolset)' == '#Toolset#' And $(Configuration.ToLower().IndexOf('debug')) == -1">
|
||||
<Link>
|
||||
<AdditionalDependencies>$(MSBuildThisFileDirectory)lib\x64\#Toolset#\Release\signalrclient.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Label="x64 and #Toolset# and Debug" Condition="'$(DisableUwp)' == '' And '$(Platform)' == 'x64' And '$(PlatformToolset)' == '#Toolset#' And $(Configuration.ToLower().IndexOf('debug')) > -1">
|
||||
<Link>
|
||||
<AdditionalDependencies>$(MSBuildThisFileDirectory)lib\x64\#Toolset#\Debug\signalrclient.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Label="Win32 and #Toolset# and Release" Condition="'$(DisableUwp)' == '' And '$(Platform)' == 'Win32' And '$(PlatformToolset)' == '#Toolset#' And $(Configuration.ToLower().IndexOf('debug')) == -1">
|
||||
<Link>
|
||||
<AdditionalDependencies>$(MSBuildThisFileDirectory)lib\Win32\#Toolset#\Release\signalrclient.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Label="Win32 and #Toolset# and Debug" Condition="'$(DisableUwp)' == '' And '$(Platform)' == 'Win32' And '$(PlatformToolset)' == '#Toolset#' And $(Configuration.ToLower().IndexOf('debug')) > -1">
|
||||
<Link>
|
||||
<AdditionalDependencies>$(MSBuildThisFileDirectory)lib\Win32\#Toolset#\Debug\signalrclient.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<Target Name="signalrclient_uwp_AfterBuild" AfterTargets="AfterBuild" Condition="'$(DisableUwp)' == ''">
|
||||
<PropertyGroup>
|
||||
<UseHardlinksIfPossible Condition="'$(UseHardlinksIfPossible)' == ''">true</UseHardlinksIfPossible>
|
||||
</PropertyGroup>
|
||||
|
||||
<Copy DestinationFolder="$(TargetDir)" SourceFiles="@(CopyToOutput)" SkipUnchangedFiles="true" UseHardlinksIfPossible="$(UseHardlinksIfPossible)">
|
||||
<Output TaskParameter="DestinationFiles" PropertyName="DestinationFiles" />
|
||||
<Output TaskParameter="DestinationFiles" ItemName="DestinationFiles" />
|
||||
<Output TaskParameter="CopiedFiles" PropertyName="CopiedFiles" />
|
||||
<Output TaskParameter="CopiedFiles" ItemName="CopiedFiles" />
|
||||
</Copy>
|
||||
</Target>
|
||||
|
||||
<Target Name="signalrclient_uwp_inittarget" Condition="'$(DisableUwp)' == ''">
|
||||
<ItemGroup Label="x64 and #Toolset# and Debug" Condition="'$(Platform)' == 'x64' And '$(PlatformToolset)' == '#Toolset#' And $(Configuration.ToLower().IndexOf('debug')) > -1">
|
||||
<ReferenceCopyLocalPaths Include="$(MSBuildThisFileDirectory)dll\x64\#Toolset#\Debug\signalrclient.dll" />
|
||||
<ReferenceCopyLocalPaths Include="$(MSBuildThisFileDirectory)dll\x64\#Toolset#\Debug\signalrclient.pdb" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="x64 and #Toolset# and Release" Condition="'$(Platform)' == 'x64' And '$(PlatformToolset)' == '#Toolset#' And $(Configuration.ToLower().IndexOf('debug')) == -1">
|
||||
<ReferenceCopyLocalPaths Include="$(MSBuildThisFileDirectory)dll\x64\#Toolset#\Release\signalrclient.dll" />
|
||||
<ReferenceCopyLocalPaths Include="$(MSBuildThisFileDirectory)dll\x64\#Toolset#\Release\signalrclient.pdb" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Win32 and #Toolset# and Debug" Condition="'$(Platform)' == 'Win32' And '$(PlatformToolset)' == '#Toolset#' And $(Configuration.ToLower().IndexOf('debug')) > -1">
|
||||
<ReferenceCopyLocalPaths Include="$(MSBuildThisFileDirectory)dll\Win32\#Toolset#\Debug\signalrclient.dll" />
|
||||
<ReferenceCopyLocalPaths Include="$(MSBuildThisFileDirectory)dll\Win32\#Toolset#\Debug\signalrclient.pdb" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Win32 and #Toolset# and Release" Condition="'$(Platform)' == 'Win32' And '$(PlatformToolset)' == '#Toolset#' And $(Configuration.ToLower().IndexOf('debug')) == -1">
|
||||
<ReferenceCopyLocalPaths Include="$(MSBuildThisFileDirectory)dll\Win32\#Toolset#\Release\signalrclient.dll" />
|
||||
<ReferenceCopyLocalPaths Include="$(MSBuildThisFileDirectory)dll\Win32\#Toolset#\Release\signalrclient.pdb" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" InitialTargets="signalrclient_inittarget">
|
||||
|
||||
<PropertyGroup Condition="'$(ApplicationType)' != ''">
|
||||
<DisableDesktop>True</DisableDesktop>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemDefinitionGroup Condition="'$(DisableDesktop)' == ''">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemDefinitionGroup Label="x64 and #Toolset# and Release" Condition="'$(DisableDesktop)' == '' And '$(Platform)' == 'x64' And '$(PlatformToolset)' == '#Toolset#' And $(Configuration.ToLower().IndexOf('debug')) == -1">
|
||||
<Link>
|
||||
<AdditionalDependencies>$(MSBuildThisFileDirectory)lib\x64\#Toolset#\Release\signalrclient.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Label="x64 and #Toolset# and Debug" Condition="'$(DisableDesktop)' == '' And '$(Platform)' == 'x64' And '$(PlatformToolset)' == '#Toolset#' And $(Configuration.ToLower().IndexOf('debug')) > -1">
|
||||
<Link>
|
||||
<AdditionalDependencies>$(MSBuildThisFileDirectory)lib\x64\#Toolset#\Debug\signalrclient.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Label="Win32 and #Toolset# and Release" Condition="'$(DisableDesktop)' == '' And '$(Platform)' == 'Win32' And '$(PlatformToolset)' == '#Toolset#' And $(Configuration.ToLower().IndexOf('debug')) == -1">
|
||||
<Link>
|
||||
<AdditionalDependencies>$(MSBuildThisFileDirectory)lib\Win32\#Toolset#\Release\signalrclient.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Label="Win32 and #Toolset# and Debug" Condition="'$(DisableDesktop)' == '' And '$(Platform)' == 'Win32' And '$(PlatformToolset)' == '#Toolset#' And $(Configuration.ToLower().IndexOf('debug')) > -1">
|
||||
<Link>
|
||||
<AdditionalDependencies>$(MSBuildThisFileDirectory)lib\Win32\#Toolset#\Debug\signalrclient.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<Target Name="signalrclient_AfterBuild" AfterTargets="AfterBuild" Condition="'$(DisableDesktop)' == ''">
|
||||
<PropertyGroup>
|
||||
<UseHardlinksIfPossible Condition="'$(UseHardlinksIfPossible)' == ''">true</UseHardlinksIfPossible>
|
||||
</PropertyGroup>
|
||||
|
||||
<Copy DestinationFolder="$(TargetDir)" SourceFiles="@(CopyToOutput)" SkipUnchangedFiles="true" UseHardlinksIfPossible="$(UseHardlinksIfPossible)">
|
||||
<Output TaskParameter="DestinationFiles" PropertyName="DestinationFiles" />
|
||||
<Output TaskParameter="DestinationFiles" ItemName="DestinationFiles" />
|
||||
<Output TaskParameter="CopiedFiles" PropertyName="CopiedFiles" />
|
||||
<Output TaskParameter="CopiedFiles" ItemName="CopiedFiles" />
|
||||
</Copy>
|
||||
</Target>
|
||||
|
||||
<Target Name="signalrclient_inittarget" Condition="'$(DisableDesktop)' == ''">
|
||||
<ItemGroup Label="x64 and #Toolset# and Debug" Condition="'$(Platform)' == 'x64' And '$(PlatformToolset)' == '#Toolset#' And $(Configuration.ToLower().IndexOf('debug')) > -1">
|
||||
<CopyToOutput Include="$(MSBuildThisFileDirectory)dll\x64\#Toolset#\Debug\signalrclient.dll" />
|
||||
<CopyToOutput Include="$(MSBuildThisFileDirectory)dll\x64\#Toolset#\Debug\signalrclient.pdb" />
|
||||
<None Include="$(MSBuildThisFileDirectory)dll\x64\#Toolset#\Debug\signalrclient.dll">
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="x64 and #Toolset# and Release" Condition="'$(Platform)' == 'x64' And '$(PlatformToolset)' == '#Toolset#' And $(Configuration.ToLower().IndexOf('debug')) == -1">
|
||||
<CopyToOutput Include="$(MSBuildThisFileDirectory)dll\x64\#Toolset#\Release\signalrclient.dll" />
|
||||
<CopyToOutput Include="$(MSBuildThisFileDirectory)dll\x64\#Toolset#\Release\signalrclient.pdb" />
|
||||
<None Include="$(MSBuildThisFileDirectory)dll\x64\#Toolset#\Release\signalrclient.dll">
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Win32 and #Toolset# and Debug" Condition="'$(Platform)' == 'Win32' And '$(PlatformToolset)' == '#Toolset#' And $(Configuration.ToLower().IndexOf('debug')) > -1">
|
||||
<CopyToOutput Include="$(MSBuildThisFileDirectory)dll\Win32\#Toolset#\Debug\signalrclient.dll" />
|
||||
<CopyToOutput Include="$(MSBuildThisFileDirectory)dll\Win32\#Toolset#\Debug\signalrclient.pdb" />
|
||||
<None Include="$(MSBuildThisFileDirectory)dll\Win32\#Toolset#\Debug\signalrclient.dll">
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Win32 and #Toolset# and Release" Condition="'$(Platform)' == 'Win32' And '$(PlatformToolset)' == '#Toolset#' And $(Configuration.ToLower().IndexOf('debug')) == -1">
|
||||
<CopyToOutput Include="$(MSBuildThisFileDirectory)dll\Win32\#Toolset#\Release\signalrclient.dll" />
|
||||
<CopyToOutput Include="$(MSBuildThisFileDirectory)dll\Win32\#Toolset#\Release\signalrclient.pdb" />
|
||||
<None Include="$(MSBuildThisFileDirectory)dll\Win32\#Toolset#\Release\signalrclient.dll">
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0"?>
|
||||
<package>
|
||||
<metadata>
|
||||
<id>Microsoft.AspNet.SignalR.Client.Cpp.#Toolset#.#SubSystem#</id>
|
||||
<title>Microsoft ASP.NET SignalR C++ Client</title>
|
||||
<version>0.0.0</version>
|
||||
<authors>Microsoft</authors>
|
||||
<owners>Microsoft</owners>
|
||||
<licenseUrl>http://www.microsoft.com/web/webpi/eula/net_library_eula_ENU.htm</licenseUrl>
|
||||
<copyright>© Microsoft Corporation. All rights reserved.</copyright>
|
||||
<projectUrl>http://www.asp.net/signalr</projectUrl>
|
||||
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
||||
<description>C++ client for ASP.NET SignalR.</description>
|
||||
<language>en-US</language>
|
||||
<tags>Microsoft AspNet SignalR AspNetSignalR Client C++ native</tags>
|
||||
<releaseNotes>https://github.com/aspnet/SignalR-Client-Cpp/releases</releaseNotes>
|
||||
<dependencies>
|
||||
<dependency id="cpprestsdk.#Toolset#.#casablanca-subsystem#.msvcstl.dyn.rt-dyn" version="2.9.1" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
</package>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
ASP.NET Core SignalR C++ Client
|
||||
========
|
||||
|
||||
This folder contains a C++ client for ASP.NET Core SignalR.
|
||||
|
||||
**There are no plans to ship this client at this time.**
|
||||
|
|
@ -0,0 +1 @@
|
|||
msbuild "%~dp0\Build\build.msbuild" /v:minimal /maxcpucount /nodeReuse:false %*
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef NO_SIGNALRCLIENT_EXPORTS
|
||||
#define SIGNALRCLIENT_API
|
||||
#else
|
||||
#ifdef SIGNALRCLIENT_EXPORTS
|
||||
#define SIGNALRCLIENT_API __declspec(dllexport)
|
||||
#else
|
||||
#define SIGNALRCLIENT_API __declspec(dllimport)
|
||||
#endif // SIGNALRCLIENT_EXPORTS
|
||||
#endif // NO_SIGNALRCLIENT_EXPORTS
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "_exports.h"
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include "connection_state.h"
|
||||
#include "trace_level.h"
|
||||
#include "log_writer.h"
|
||||
#include "signalr_client_config.h"
|
||||
|
||||
namespace signalr
|
||||
{
|
||||
class connection_impl;
|
||||
|
||||
class connection
|
||||
{
|
||||
public:
|
||||
typedef std::function<void __cdecl(const utility::string_t&)> message_received_handler;
|
||||
|
||||
SIGNALRCLIENT_API explicit connection(const utility::string_t& url, const utility::string_t& query_string = _XPLATSTR(""),
|
||||
trace_level trace_level = trace_level::all, std::shared_ptr<log_writer> log_writer = nullptr);
|
||||
|
||||
SIGNALRCLIENT_API ~connection();
|
||||
|
||||
connection(const connection&) = delete;
|
||||
|
||||
connection& operator=(const connection&) = delete;
|
||||
|
||||
SIGNALRCLIENT_API pplx::task<void> __cdecl start();
|
||||
|
||||
SIGNALRCLIENT_API pplx::task<void> __cdecl send(const utility::string_t& data);
|
||||
|
||||
SIGNALRCLIENT_API void __cdecl set_message_received(const message_received_handler& message_received_callback);
|
||||
SIGNALRCLIENT_API void __cdecl set_reconnecting(const std::function<void __cdecl()>& reconnecting_callback);
|
||||
SIGNALRCLIENT_API void __cdecl set_reconnected(const std::function<void __cdecl()>& reconnected_callback);
|
||||
SIGNALRCLIENT_API void __cdecl set_disconnected(const std::function<void __cdecl()>& disconnected_callback);
|
||||
|
||||
SIGNALRCLIENT_API void __cdecl set_client_config(const signalr_client_config& config);
|
||||
|
||||
SIGNALRCLIENT_API pplx::task<void> __cdecl stop();
|
||||
|
||||
SIGNALRCLIENT_API connection_state __cdecl get_connection_state() const;
|
||||
SIGNALRCLIENT_API utility::string_t __cdecl get_connection_id() const;
|
||||
|
||||
private:
|
||||
// The recommended smart pointer to use when doing pImpl is the `std::unique_ptr`. However
|
||||
// we are capturing the m_pImpl instance in the lambdas used by tasks which can outlive
|
||||
// the connection instance. Using `std::shared_ptr` guarantees that we won't be using
|
||||
// a deleted object if the task is run after the `connection` instance goes away.
|
||||
std::shared_ptr<connection_impl> m_pImpl;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace signalr
|
||||
{
|
||||
enum class connection_state
|
||||
{
|
||||
connecting,
|
||||
connected,
|
||||
reconnecting,
|
||||
disconnecting,
|
||||
disconnected
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "_exports.h"
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include "cpprest/json.h"
|
||||
#include "connection_state.h"
|
||||
#include "trace_level.h"
|
||||
#include "log_writer.h"
|
||||
#include "signalr_client_config.h"
|
||||
|
||||
namespace signalr
|
||||
{
|
||||
class hub_connection_impl;
|
||||
|
||||
class hub_connection
|
||||
{
|
||||
public:
|
||||
typedef std::function<void __cdecl (const web::json::value&)> method_invoked_handler;
|
||||
|
||||
SIGNALRCLIENT_API explicit hub_connection(const utility::string_t& url, const utility::string_t& query_string = _XPLATSTR(""),
|
||||
trace_level trace_level = trace_level::all, std::shared_ptr<log_writer> log_writer = nullptr, bool use_default_url = true);
|
||||
|
||||
SIGNALRCLIENT_API ~hub_connection();
|
||||
|
||||
hub_connection(const hub_connection&) = delete;
|
||||
|
||||
hub_connection& operator=(const hub_connection&) = delete;
|
||||
|
||||
SIGNALRCLIENT_API pplx::task<void> __cdecl start();
|
||||
SIGNALRCLIENT_API pplx::task<void> __cdecl stop();
|
||||
|
||||
SIGNALRCLIENT_API connection_state __cdecl get_connection_state() const;
|
||||
SIGNALRCLIENT_API utility::string_t __cdecl get_connection_id() const;
|
||||
|
||||
SIGNALRCLIENT_API void __cdecl set_reconnecting(const std::function<void __cdecl()>& reconnecting_callback);
|
||||
SIGNALRCLIENT_API void __cdecl set_reconnected(const std::function<void __cdecl()>& reconnected_callback);
|
||||
SIGNALRCLIENT_API void __cdecl set_disconnected(const std::function<void __cdecl()>& disconnected_callback);
|
||||
|
||||
SIGNALRCLIENT_API void __cdecl set_client_config(const signalr_client_config& config);
|
||||
|
||||
SIGNALRCLIENT_API void __cdecl on(const utility::string_t& event_name, const method_invoked_handler& handler);
|
||||
|
||||
pplx::task<web::json::value> invoke(const utility::string_t& method_name, const web::json::value& arguments = web::json::value::array())
|
||||
{
|
||||
return invoke_json(method_name, arguments);
|
||||
}
|
||||
|
||||
pplx::task<void> send(const utility::string_t& method_name, const web::json::value& arguments = web::json::value::array())
|
||||
{
|
||||
return invoke_void(method_name, arguments);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<hub_connection_impl> m_pImpl;
|
||||
|
||||
SIGNALRCLIENT_API pplx::task<web::json::value> __cdecl invoke_json(const utility::string_t& method_name, const web::json::value& arguments);
|
||||
SIGNALRCLIENT_API pplx::task<void> __cdecl invoke_void(const utility::string_t& method_name, const web::json::value& arguments);
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdexcept>
|
||||
#include "cpprest/details/basic_types.h"
|
||||
#include "cpprest/json.h"
|
||||
#include "cpprest/asyncrt_utils.h"
|
||||
#include "signalr_exception.h"
|
||||
|
||||
namespace signalr
|
||||
{
|
||||
class hub_exception : public signalr_exception
|
||||
{
|
||||
public:
|
||||
hub_exception(const utility::string_t &what, const web::json::value& error_data)
|
||||
: signalr_exception(what), m_error_data(error_data)
|
||||
{}
|
||||
|
||||
web::json::value error_data() const
|
||||
{
|
||||
return m_error_data;
|
||||
}
|
||||
|
||||
private:
|
||||
web::json::value m_error_data;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/details/basic_types.h"
|
||||
|
||||
namespace signalr
|
||||
{
|
||||
class log_writer
|
||||
{
|
||||
public:
|
||||
// NOTE: the caller does not enforce thread safety of this call
|
||||
virtual void __cdecl write(const utility::string_t &entry) = 0;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/http_client.h"
|
||||
#include "cpprest/ws_client.h"
|
||||
#include "_exports.h"
|
||||
|
||||
namespace signalr
|
||||
{
|
||||
class signalr_client_config
|
||||
{
|
||||
public:
|
||||
SIGNALRCLIENT_API void __cdecl set_proxy(const web::web_proxy &proxy);
|
||||
// Please note that setting credentials does not work in all cases.
|
||||
// For example, Basic Authentication fails under Win32.
|
||||
// As a workaround, you can set the required authorization headers directly
|
||||
// using signalr_client_config::set_http_headers
|
||||
SIGNALRCLIENT_API void __cdecl set_credentials(const web::credentials &credentials);
|
||||
|
||||
SIGNALRCLIENT_API web::http::client::http_client_config __cdecl get_http_client_config() const;
|
||||
SIGNALRCLIENT_API void __cdecl set_http_client_config(const web::http::client::http_client_config& http_client_config);
|
||||
|
||||
SIGNALRCLIENT_API web::websockets::client::websocket_client_config __cdecl get_websocket_client_config() const;
|
||||
SIGNALRCLIENT_API void __cdecl set_websocket_client_config(const web::websockets::client::websocket_client_config& websocket_client_config);
|
||||
|
||||
SIGNALRCLIENT_API web::http::http_headers __cdecl get_http_headers() const;
|
||||
SIGNALRCLIENT_API void __cdecl set_http_headers(const web::http::http_headers& http_headers);
|
||||
|
||||
private:
|
||||
web::http::client::http_client_config m_http_client_config;
|
||||
web::websockets::client::websocket_client_config m_websocket_client_config;
|
||||
web::http::http_headers m_http_headers;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdexcept>
|
||||
#include "cpprest/details/basic_types.h"
|
||||
#include "cpprest/asyncrt_utils.h"
|
||||
|
||||
namespace signalr
|
||||
{
|
||||
class signalr_exception : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit signalr_exception(const utility::string_t &what)
|
||||
: runtime_error(utility::conversions::to_utf8string(what))
|
||||
{}
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace signalr
|
||||
{
|
||||
enum class trace_level : int
|
||||
{
|
||||
none = 0,
|
||||
messages = 1,
|
||||
events = 2,
|
||||
state_changes = 4,
|
||||
errors = 8,
|
||||
info = 16,
|
||||
all = messages | events | state_changes | errors | info
|
||||
};
|
||||
|
||||
inline trace_level operator|(trace_level lhs, trace_level rhs)
|
||||
{
|
||||
return static_cast<trace_level>(static_cast<int>(lhs) | static_cast<int>(rhs));
|
||||
}
|
||||
|
||||
inline trace_level operator&(trace_level lhs, trace_level rhs)
|
||||
{
|
||||
return static_cast<trace_level>(static_cast<int>(lhs) & static_cast<int>(rhs));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace signalr
|
||||
{
|
||||
enum class transport_type
|
||||
{
|
||||
long_polling,
|
||||
websockets
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdexcept>
|
||||
#include "cpprest/details/basic_types.h"
|
||||
#include "cpprest/asyncrt_utils.h"
|
||||
|
||||
namespace signalr
|
||||
{
|
||||
class web_exception : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
web_exception(const utility::string_t &what, unsigned short status_code)
|
||||
: runtime_error(utility::conversions::to_utf8string(what)), m_status_code(status_code)
|
||||
{}
|
||||
|
||||
unsigned short status_code() const
|
||||
{
|
||||
return m_status_code;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned short m_status_code;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.31101.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PersistentConnectionSample", "samples\PersistentConnectionSample\PersistentConnectionSample.vcxproj", "{BD075706-11E9-403B-A2E3-A5E1397E53EF}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HubConnectionSample", "samples\HubConnectionSample\HubConnectionSample.vcxproj", "{3C9BD092-18E6-4C6E-A887-CDFC80ACB206}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SignalRServer", "samples\SignalRServer\SignalRServer.csproj", "{A6782DC4-7435-4DB2-9E34-3F0390BC3FDE}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{4AA7C02A-A2E9-4E22-A026-B43D623C272F}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.nuget\NuGet.Config = .nuget\NuGet.Config
|
||||
.nuget\NuGet.exe = .nuget\NuGet.exe
|
||||
.nuget\NuGet.targets = .nuget\NuGet.targets
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|Mixed Platforms = Debug|Mixed Platforms
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|Mixed Platforms = Release|Mixed Platforms
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{BD075706-11E9-403B-A2E3-A5E1397E53EF}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{BD075706-11E9-403B-A2E3-A5E1397E53EF}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
|
||||
{BD075706-11E9-403B-A2E3-A5E1397E53EF}.Debug|Mixed Platforms.Build.0 = Debug|Win32
|
||||
{BD075706-11E9-403B-A2E3-A5E1397E53EF}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{BD075706-11E9-403B-A2E3-A5E1397E53EF}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{BD075706-11E9-403B-A2E3-A5E1397E53EF}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{BD075706-11E9-403B-A2E3-A5E1397E53EF}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{BD075706-11E9-403B-A2E3-A5E1397E53EF}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{BD075706-11E9-403B-A2E3-A5E1397E53EF}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{BD075706-11E9-403B-A2E3-A5E1397E53EF}.Release|Win32.Build.0 = Release|Win32
|
||||
{3C9BD092-18E6-4C6E-A887-CDFC80ACB206}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{3C9BD092-18E6-4C6E-A887-CDFC80ACB206}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
|
||||
{3C9BD092-18E6-4C6E-A887-CDFC80ACB206}.Debug|Mixed Platforms.Build.0 = Debug|Win32
|
||||
{3C9BD092-18E6-4C6E-A887-CDFC80ACB206}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{3C9BD092-18E6-4C6E-A887-CDFC80ACB206}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{3C9BD092-18E6-4C6E-A887-CDFC80ACB206}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{3C9BD092-18E6-4C6E-A887-CDFC80ACB206}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{3C9BD092-18E6-4C6E-A887-CDFC80ACB206}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{3C9BD092-18E6-4C6E-A887-CDFC80ACB206}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{3C9BD092-18E6-4C6E-A887-CDFC80ACB206}.Release|Win32.Build.0 = Release|Win32
|
||||
{A6782DC4-7435-4DB2-9E34-3F0390BC3FDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A6782DC4-7435-4DB2-9E34-3F0390BC3FDE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A6782DC4-7435-4DB2-9E34-3F0390BC3FDE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{A6782DC4-7435-4DB2-9E34-3F0390BC3FDE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{A6782DC4-7435-4DB2-9E34-3F0390BC3FDE}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||
{A6782DC4-7435-4DB2-9E34-3F0390BC3FDE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A6782DC4-7435-4DB2-9E34-3F0390BC3FDE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A6782DC4-7435-4DB2-9E34-3F0390BC3FDE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{A6782DC4-7435-4DB2-9E34-3F0390BC3FDE}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{A6782DC4-7435-4DB2-9E34-3F0390BC3FDE}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include "hub_connection.h"
|
||||
#include "log_writer.h"
|
||||
|
||||
class logger : public signalr::log_writer
|
||||
{
|
||||
// Inherited via log_writer
|
||||
virtual void __cdecl write(const utility::string_t & entry) override
|
||||
{
|
||||
//std::cout << utility::conversions::to_utf8string(entry) << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
void send_message(signalr::hub_connection& connection, const utility::string_t& name, const utility::string_t& message)
|
||||
{
|
||||
web::json::value args{};
|
||||
args[0] = web::json::value::string(name);
|
||||
args[1] = web::json::value(message);
|
||||
|
||||
// if you get an internal compiler error uncomment the lambda below or install VS Update 4
|
||||
connection.invoke(U("Invoke"), args/*, [](const web::json::value&){}*/)
|
||||
.then([](pplx::task<web::json::value> invoke_task) // fire and forget but we need to observe exceptions
|
||||
{
|
||||
try
|
||||
{
|
||||
auto val = invoke_task.get();
|
||||
ucout << U("Received: ") << val.serialize() << std::endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
ucout << U("Error while sending data: ") << e.what() << std::endl;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void chat(const utility::string_t& name)
|
||||
{
|
||||
signalr::hub_connection connection(U("http://localhost:5000/default"), U(""), signalr::trace_level::all, std::make_shared<logger>());
|
||||
connection.on(U("Send"), [](const web::json::value& m)
|
||||
{
|
||||
ucout << std::endl << m.at(0).as_string() << /*U(" wrote:") << m.at(1).as_string() <<*/ std::endl << U("Enter your message: ");
|
||||
});
|
||||
|
||||
connection.start()
|
||||
.then([&connection, name]()
|
||||
{
|
||||
ucout << U("Enter your message:");
|
||||
for (;;)
|
||||
{
|
||||
utility::string_t message;
|
||||
std::getline(ucin, message);
|
||||
|
||||
if (message == U(":q"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
send_message(connection, name, message);
|
||||
}
|
||||
})
|
||||
.then([&connection]() // fine to capture by reference - we are blocking so it is guaranteed to be valid
|
||||
{
|
||||
return connection.stop();
|
||||
})
|
||||
.then([](pplx::task<void> stop_task)
|
||||
{
|
||||
try
|
||||
{
|
||||
stop_task.get();
|
||||
ucout << U("connection stopped successfully") << std::endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
ucout << U("exception when starting or stopping connection: ") << e.what() << std::endl;
|
||||
}
|
||||
}).get();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
ucout << U("Enter your name: ");
|
||||
utility::string_t name;
|
||||
std::getline(ucin, name);
|
||||
|
||||
chat(name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{3C9BD092-18E6-4C6E-A887-CDFC80ACB206}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>HubConnectionSample</RootNamespace>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
|
||||
<DownloadNuGetExe Condition=" '$(DownloadNuGetExe)' == '' ">true</DownloadNuGetExe>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
|
||||
<Import Project="..\..\packages\cpprestsdk.v140.windesktop.msvcstl.dyn.rt-dyn.2.9.1\build\native\cpprestsdk.v140.windesktop.msvcstl.dyn.rt-dyn.targets" Condition="Exists('..\..\packages\cpprestsdk.v140.windesktop.msvcstl.dyn.rt-dyn.2.9.1\build\native\cpprestsdk.v140.windesktop.msvcstl.dyn.rt-dyn.targets')" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\include\signalrclient;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>
|
||||
</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>$(MSBuildThisFileDirectory)..\..\packages\cpprestsdk.v140.windesktop.msvcstl.dyn.rt-dyn.2.9.1\lib\native\v140\windesktop\msvcstl\dyn\rt-dyn\x86\Debug\cpprest140d_2_9.lib;$(MSBuildThisFileDirectory)..\..\bin\Desktop\Win32\Debug\dll\signalrclient.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="HubConnectionSample.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\signalrclient\Build\VS\signalrclient.vcxproj">
|
||||
<Project>{87ed3ad4-d820-48cd-8382-a12564213a12}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
|
||||
<Error Condition="!Exists('..\..\packages\cpprestsdk.v140.windesktop.msvcstl.dyn.rt-dyn.2.9.1\build\native\cpprestsdk.v140.windesktop.msvcstl.dyn.rt-dyn.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\cpprestsdk.v140.windesktop.msvcstl.dyn.rt-dyn.2.9.1\build\native\cpprestsdk.v140.windesktop.msvcstl.dyn.rt-dyn.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HubConnectionSample.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="cpprestsdk.v140.windesktop.msvcstl.dyn.rt-dyn" version="2.9.1" targetFramework="native" />
|
||||
</packages>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
#include "stdafx.h"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue