diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000000..d7636fa329
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,32 @@
+language: csharp
+sudo: required
+dist: trusty
+addons:
+ apt:
+ packages:
+ - gettext
+ - libcurl4-openssl-dev
+ - libicu-dev
+ - libssl-dev
+ - libunwind8
+ - zlib1g
+env:
+ global:
+ - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
+ - DOTNET_CLI_TELEMETRY_OPTOUT: 1
+mono:
+ - 4.0.5
+os:
+ - linux
+ - osx
+osx_image: xcode7.1
+branches:
+ only:
+ - master
+ - release
+ - dev
+ - /^(.*\/)?ci-.*$/
+before_install:
+ - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/; fi
+script:
+ - ./build.sh --quiet verify
diff --git a/Microsoft.AspNetCore.Sockets.sln b/SignalR.sln
similarity index 100%
rename from Microsoft.AspNetCore.Sockets.sln
rename to SignalR.sln
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000000..be95b88d6f
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,13 @@
+init:
+ - git config --global core.autocrlf true
+branches:
+ only:
+ - master
+ - release
+ - dev
+ - /^(.*\/)?ci-.*$/
+build_script:
+ - build.cmd --quiet verify
+clone_depth: 1
+test: off
+deploy: off
\ No newline at end of file
diff --git a/build.cmd b/build.cmd
new file mode 100644
index 0000000000..7d4894cb4a
--- /dev/null
+++ b/build.cmd
@@ -0,0 +1,2 @@
+@ECHO OFF
+PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0build.ps1' %*; exit $LASTEXITCODE"
\ No newline at end of file
diff --git a/build.ps1 b/build.ps1
new file mode 100644
index 0000000000..8f2f99691a
--- /dev/null
+++ b/build.ps1
@@ -0,0 +1,67 @@
+$ErrorActionPreference = "Stop"
+
+function DownloadWithRetry([string] $url, [string] $downloadLocation, [int] $retries)
+{
+ while($true)
+ {
+ try
+ {
+ Invoke-WebRequest $url -OutFile $downloadLocation
+ break
+ }
+ catch
+ {
+ $exceptionMessage = $_.Exception.Message
+ Write-Host "Failed to download '$url': $exceptionMessage"
+ if ($retries -gt 0) {
+ $retries--
+ Write-Host "Waiting 10 seconds before retrying. Retries left: $retries"
+ Start-Sleep -Seconds 10
+
+ }
+ else
+ {
+ $exception = $_.Exception
+ throw $exception
+ }
+ }
+ }
+}
+
+cd $PSScriptRoot
+
+$repoFolder = $PSScriptRoot
+$env:REPO_FOLDER = $repoFolder
+
+$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip"
+if ($env:KOREBUILD_ZIP)
+{
+ $koreBuildZip=$env:KOREBUILD_ZIP
+}
+
+$buildFolder = ".build"
+$buildFile="$buildFolder\KoreBuild.ps1"
+
+if (!(Test-Path $buildFolder)) {
+ Write-Host "Downloading KoreBuild from $koreBuildZip"
+
+ $tempFolder=$env:TEMP + "\KoreBuild-" + [guid]::NewGuid()
+ New-Item -Path "$tempFolder" -Type directory | Out-Null
+
+ $localZipFile="$tempFolder\korebuild.zip"
+
+ DownloadWithRetry -url $koreBuildZip -downloadLocation $localZipFile -retries 6
+
+ Add-Type -AssemblyName System.IO.Compression.FileSystem
+ [System.IO.Compression.ZipFile]::ExtractToDirectory($localZipFile, $tempFolder)
+
+ New-Item -Path "$buildFolder" -Type directory | Out-Null
+ copy-item "$tempFolder\**\build\*" $buildFolder -Recurse
+
+ # Cleanup
+ if (Test-Path $tempFolder) {
+ Remove-Item -Recurse -Force $tempFolder
+ }
+}
+
+&"$buildFile" $args
\ No newline at end of file
diff --git a/build.sh b/build.sh
new file mode 100644
index 0000000000..f4208100eb
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,46 @@
+#!/usr/bin/env bash
+repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+cd $repoFolder
+
+koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip"
+if [ ! -z $KOREBUILD_ZIP ]; then
+ koreBuildZip=$KOREBUILD_ZIP
+fi
+
+buildFolder=".build"
+buildFile="$buildFolder/KoreBuild.sh"
+
+if test ! -d $buildFolder; then
+ echo "Downloading KoreBuild from $koreBuildZip"
+
+ tempFolder="/tmp/KoreBuild-$(uuidgen)"
+ mkdir $tempFolder
+
+ localZipFile="$tempFolder/korebuild.zip"
+
+ retries=6
+ until (wget -O $localZipFile $koreBuildZip 2>/dev/null || curl -o $localZipFile --location $koreBuildZip 2>/dev/null)
+ do
+ echo "Failed to download '$koreBuildZip'"
+ if [ "$retries" -le 0 ]; then
+ exit 1
+ fi
+ retries=$((retries - 1))
+ echo "Waiting 10 seconds before retrying. Retries left: $retries"
+ sleep 10s
+ done
+
+ unzip -q -d $tempFolder $localZipFile
+
+ mkdir $buildFolder
+ cp -r $tempFolder/**/build/** $buildFolder
+
+ chmod +x $buildFile
+
+ # Cleanup
+ if test ! -d $tempFolder; then
+ rm -rf $tempFolder
+ fi
+fi
+
+$buildFile -r $repoFolder "$@"
\ No newline at end of file
diff --git a/src/Microsoft.AspNetCore.SignalR.Redis/project.json b/src/Microsoft.AspNetCore.SignalR.Redis/project.json
index 29ae356ccf..8937acd078 100644
--- a/src/Microsoft.AspNetCore.SignalR.Redis/project.json
+++ b/src/Microsoft.AspNetCore.SignalR.Redis/project.json
@@ -26,7 +26,7 @@
"target": "project"
},
"NETStandard.Library": "1.6.1-*",
- "StackExchange.Redis": "1.1.*"
+ "StackExchange.Redis.StrongName": "1.1.605"
},
"frameworks": {
diff --git a/src/Microsoft.Extensions.WebSockets.Internal/IWebSocketConnection.cs b/src/Microsoft.Extensions.WebSockets.Internal/IWebSocketConnection.cs
index dfb65595d9..7f7d1b4d26 100644
--- a/src/Microsoft.Extensions.WebSockets.Internal/IWebSocketConnection.cs
+++ b/src/Microsoft.Extensions.WebSockets.Internal/IWebSocketConnection.cs
@@ -13,13 +13,13 @@ namespace Microsoft.Extensions.WebSockets.Internal
///
///
/// Implementors of this type are generally considered thread-safe under the following condition: No two threads attempt to call either
- /// or simultaneously. Different threads may call each method, but the same method
+ /// or simultaneously. Different threads may call each method, but the same method
/// cannot be re-entered while it is being run in a different thread. However, ensure you verify that the specific implementor is
/// thread-safe in this way. For example, (including the implementations returned by the
/// static factory methods on that type) is thread-safe in this way.
///
///
- /// The general pattern of having a single thread running and a separate thread running will
+ /// The general pattern of having a single thread running and a separate thread running will
/// be thread-safe, as each method interacts with completely separate state.
///
///
@@ -70,56 +70,63 @@ namespace Microsoft.Extensions.WebSockets.Internal
///
/// Sends the specified frame.
///
+ /// The
/// The message to send.
/// A that completes when the message has been written to the outbound stream.
- public static Task SendAsync(this IWebSocketConnection self, WebSocketFrame message) => self.SendAsync(message, CancellationToken.None);
+ public static Task SendAsync(this IWebSocketConnection connection, WebSocketFrame message) => connection.SendAsync(message, CancellationToken.None);
///
/// Sends a Close frame to the other party. This does not guarantee that the client will send a responding close frame.
///
+ /// The
/// A value to be sent to the client in the close frame.
/// A that completes when the close frame has been sent
- public static Task CloseAsync(this IWebSocketConnection self, WebSocketCloseStatus status) => self.CloseAsync(new WebSocketCloseResult(status), CancellationToken.None);
+ public static Task CloseAsync(this IWebSocketConnection connection, WebSocketCloseStatus status) => connection.CloseAsync(new WebSocketCloseResult(status), CancellationToken.None);
///
/// Sends a Close frame to the other party. This does not guarantee that the client will send a responding close frame.
///
+ /// The
/// A value to be sent to the client in the close frame.
/// A textual description of the reason for closing the connection.
/// A that completes when the close frame has been sent
- public static Task CloseAsync(this IWebSocketConnection self, WebSocketCloseStatus status, string description) => self.CloseAsync(new WebSocketCloseResult(status, description), CancellationToken.None);
+ public static Task CloseAsync(this IWebSocketConnection connection, WebSocketCloseStatus status, string description) => connection.CloseAsync(new WebSocketCloseResult(status, description), CancellationToken.None);
///
/// Sends a Close frame to the other party. This does not guarantee that the client will send a responding close frame.
///
+ /// The
/// A value to be sent to the client in the close frame.
/// A that indicates when/if the send is cancelled.
/// A that completes when the close frame has been sent
- public static Task CloseAsync(this IWebSocketConnection self, WebSocketCloseStatus status, CancellationToken cancellationToken) => self.CloseAsync(new WebSocketCloseResult(status), cancellationToken);
+ public static Task CloseAsync(this IWebSocketConnection connection, WebSocketCloseStatus status, CancellationToken cancellationToken) => connection.CloseAsync(new WebSocketCloseResult(status), cancellationToken);
///
/// Sends a Close frame to the other party. This does not guarantee that the client will send a responding close frame.
///
+ /// The
/// A value to be sent to the client in the close frame.
/// A textual description of the reason for closing the connection.
/// A that indicates when/if the send is cancelled.
/// A that completes when the close frame has been sent
- public static Task CloseAsync(this IWebSocketConnection self, WebSocketCloseStatus status, string description, CancellationToken cancellationToken) => self.CloseAsync(new WebSocketCloseResult(status, description), cancellationToken);
+ public static Task CloseAsync(this IWebSocketConnection connection, WebSocketCloseStatus status, string description, CancellationToken cancellationToken) => connection.CloseAsync(new WebSocketCloseResult(status, description), cancellationToken);
///
/// Sends a Close frame to the other party. This does not guarantee that the client will send a responding close frame.
///
+ /// The
/// A with the payload for the close frame.
/// A that completes when the close frame has been sent
- public static Task CloseAsync(this IWebSocketConnection self, WebSocketCloseResult result) => self.CloseAsync(result, CancellationToken.None);
+ public static Task CloseAsync(this IWebSocketConnection connection, WebSocketCloseResult result) => connection.CloseAsync(result, CancellationToken.None);
///
/// Runs the WebSocket receive loop, using the provided message handler.
///
+ /// The
/// The callback that will be invoked for each new frame
/// A that will complete when the client has sent a close frame, or the connection has been terminated
- public static Task ExecuteAsync(this IWebSocketConnection self, Action messageHandler) =>
- self.ExecuteAsync((frame, _) =>
+ public static Task ExecuteAsync(this IWebSocketConnection connection, Action messageHandler) =>
+ connection.ExecuteAsync((frame, _) =>
{
messageHandler(frame);
return Task.CompletedTask;
@@ -128,10 +135,12 @@ namespace Microsoft.Extensions.WebSockets.Internal
///
/// Runs the WebSocket receive loop, using the provided message handler.
///
+ /// The
/// The callback that will be invoked for each new frame
+ /// The state to pass to the callback when the delegate is invoked. This may be null.
/// A that will complete when the client has sent a close frame, or the connection has been terminated
- public static Task ExecuteAsync(this IWebSocketConnection self, Action messageHandler, object state) =>
- self.ExecuteAsync((frame, s) =>
+ public static Task ExecuteAsync(this IWebSocketConnection connection, Action messageHandler, object state) =>
+ connection.ExecuteAsync((frame, s) =>
{
messageHandler(frame, s);
return Task.CompletedTask;
@@ -140,9 +149,10 @@ namespace Microsoft.Extensions.WebSockets.Internal
///
/// Runs the WebSocket receive loop, using the provided message handler.
///
+ /// The
/// The callback that will be invoked for each new frame
/// A that will complete when the client has sent a close frame, or the connection has been terminated
- public static Task ExecuteAsync(this IWebSocketConnection self, Func messageHandler) =>
- self.ExecuteAsync((frame, _) => messageHandler(frame), null);
+ public static Task ExecuteAsync(this IWebSocketConnection connection, Func messageHandler) =>
+ connection.ExecuteAsync((frame, _) => messageHandler(frame), null);
}
}
diff --git a/src/Microsoft.Extensions.WebSockets.Internal/Properties/AssemblyInfo.cs b/src/Microsoft.Extensions.WebSockets.Internal/Properties/AssemblyInfo.cs
index faeef5ffeb..74635e3701 100644
--- a/src/Microsoft.Extensions.WebSockets.Internal/Properties/AssemblyInfo.cs
+++ b/src/Microsoft.Extensions.WebSockets.Internal/Properties/AssemblyInfo.cs
@@ -12,4 +12,4 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyProduct("Microsoft.Extensions.WebSockets")]
[assembly: AssemblyTrademark("")]
-[assembly: InternalsVisibleTo("Microsoft.Extensions.WebSockets.Tests")]
\ No newline at end of file
+[assembly: InternalsVisibleTo("Microsoft.Extensions.WebSockets.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
diff --git a/src/Microsoft.Extensions.WebSockets.Internal/WebSocketConnection.cs b/src/Microsoft.Extensions.WebSockets.Internal/WebSocketConnection.cs
index 013288658e..b775d59db2 100644
--- a/src/Microsoft.Extensions.WebSockets.Internal/WebSocketConnection.cs
+++ b/src/Microsoft.Extensions.WebSockets.Internal/WebSocketConnection.cs
@@ -18,11 +18,11 @@ namespace Microsoft.Extensions.WebSockets.Internal
///
///
/// This type is thread-safe under the following condition: No two threads attempt to call either
- /// or simultaneously. Different threads may call each method, but the same method
+ /// or simultaneously. Different threads may call each method, but the same method
/// cannot be re-entered while it is being run in a different thread.
///
///
- /// The general pattern of having a single thread running and a separate thread running will
+ /// The general pattern of having a single thread running and a separate thread running will
/// be thread-safe, as each method interacts with completely separate state.
///
///
diff --git a/src/Microsoft.Extensions.WebSockets.Internal/project.json b/src/Microsoft.Extensions.WebSockets.Internal/project.json
index 4bb1ed4244..8af2e39b1f 100644
--- a/src/Microsoft.Extensions.WebSockets.Internal/project.json
+++ b/src/Microsoft.Extensions.WebSockets.Internal/project.json
@@ -1,6 +1,6 @@
{
"version": "0.1.0-*",
- "description": "WebSockets client and server components.",
+ "description": "Low-allocation Push-oriented WebSockets based on Channels",
"packOptions": {
"repository": {
@@ -18,10 +18,10 @@
"nowarn": [
"CS1591"
],
- "xmlDoc": true
+ "xmlDoc": true,
+ "allowUnsafe": true
},
- "description": "Low-allocation Push-oriented WebSockets based on Channels",
"dependencies": {
"Channels": "0.2.0-beta-*",
"Channels.Text.Primitives": "0.2.0-beta-*",