Skip to content

Commit

Permalink
Major restructuring.
Browse files Browse the repository at this point in the history
  • Loading branch information
ashmind committed Sep 13, 2016
1 parent 346ff5b commit d662f91
Show file tree
Hide file tree
Showing 65 changed files with 215 additions and 139 deletions.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
"version": "0.9.0-*",

"dependencies": {
"MirrorSharp": "*",
"Microsoft.AspNetCore.Http.Abstractions": "1.0.0"
"Microsoft.AspNetCore.Http.Abstractions": "1.0.0",
"MirrorSharp.Common": "*"
},

"frameworks": {
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>

<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>c130c962-d17f-4741-b2b4-d74263bf380a</ProjectGuid>
Expand All @@ -13,9 +12,8 @@
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
</PropertyGroup>

<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
</Project>
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"Microsoft.Owin": "3.0.1",
"Microsoft.Owin.StaticFiles": "3.0.1",
"Microsoft.Owin.Host.SystemWeb": "3.0.1",
"MirrorSharp.Owin": "0.9.0-*"
"MirrorSharp.Owin": "*"
},

"frameworks": {
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ public Task Invoke(IDictionary<string, object> environment) {
if (!environment.TryGetValue("websocket.Accept", out accept))
return _next(environment);

((WebSocketAccept) accept)(null, e => WebSocketLoopAsync(new OwinWebSocket(e)));
((WebSocketAccept) accept)(null, e => {
var socket = new OwinWebSocket(e);
return Task.WhenAny(WebSocketLoopAsync(socket), socket.AbortedTask);
});
return Done;
}

Expand Down
169 changes: 169 additions & 0 deletions MirrorSharp.Owin/Internal/OwinWebSocket.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Net.WebSockets;
using System.Threading;

namespace MirrorSharp.Owin.Internal {
using WebSocketSendAsync = Func<
ArraySegment<byte> /* data */,
int /* messageType */,
bool /* endOfMessage */,
CancellationToken /* cancel */,
Task
>;

using WebSocketReceiveAsync = Func<
ArraySegment<byte> /* data */,
CancellationToken /* cancel */,
Task<
Tuple<
int /* messageType */,
bool /* endOfMessage */,
int /* count */
>
>
>;

using WebSocketCloseAsync = Func<
int /* closeStatus */,
string /* closeDescription */,
CancellationToken /* cancel */,
Task
>;

internal class OwinWebSocket : WebSocket {
private readonly IDictionary<string, object> _environment;
private readonly WebSocketSendAsync _sendAsync;
private readonly WebSocketReceiveAsync _receiveAsync;
private readonly WebSocketCloseAsync _closeAsync;
private readonly TaskCompletionSource<object> _abortTaskSource;
private WebSocketState _state;
private WebSocketCloseStatus? _closeStatus;
private string _closeDescription;

public OwinWebSocket(IDictionary<string, object> environment) {
_environment = environment;
_state = WebSocketState.Open;
_sendAsync = (WebSocketSendAsync)environment["websocket.SendAsync"];
_receiveAsync = (WebSocketReceiveAsync)environment["websocket.ReceiveAsync"];
_closeAsync = (WebSocketCloseAsync)environment["websocket.CloseAsync"];

var callCancelledToken = (CancellationToken)environment["websocket.CallCancelled"];
callCancelledToken.Register(Abort);

_abortTaskSource = new TaskCompletionSource<object>();
}

public override WebSocketCloseStatus? CloseStatus => _closeStatus;
public override string CloseStatusDescription => _closeDescription;
public override WebSocketState State => _state;

public Task AbortedTask => _abortTaskSource.Task;

public override string SubProtocol
{
get
{
throw new NotImplementedException();
}
}

public override async Task<WebSocketReceiveResult> ReceiveAsync(ArraySegment<byte> buffer, CancellationToken cancellationToken) {
if (_state != WebSocketState.Open && _state != WebSocketState.CloseSent)
throw new InvalidOperationException($"WebSocket state is {_state}: cannot receieve data.");

var tuple = await _receiveAsync(buffer, cancellationToken).ConfigureAwait(false);
var messageType = MapMessageTypeToEnum(tuple.Item1);
if (messageType == WebSocketMessageType.Close) {
_state = (_state == WebSocketState.CloseSent) ? WebSocketState.Closed : WebSocketState.CloseReceived;
_closeStatus = (WebSocketCloseStatus?)(int?)_environment.GetValueOrDefault("websocket.ClientCloseStatus");
_closeDescription = (string)_environment.GetValueOrDefault("websocket.ClientCloseDescription");
return new WebSocketReceiveResult(
tuple.Item3, messageType, tuple.Item2,
_closeStatus, _closeDescription
);
}

if (_state == WebSocketState.CloseSent) {
Abort();
throw new WebSocketException(WebSocketError.InvalidMessageType);
}

return new WebSocketReceiveResult(tuple.Item3, messageType, tuple.Item2);
}

public override async Task SendAsync(ArraySegment<byte> buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken) {
if (_state != WebSocketState.Open && _state != WebSocketState.CloseReceived)
throw new InvalidOperationException($"WebSocket state is {_state}: cannot send data.");

try {
await _sendAsync(buffer, MapMessageTypeFromEnum(messageType), endOfMessage, cancellationToken)
.ConfigureAwait(false);
}
catch (Exception) when (messageType == WebSocketMessageType.Close) {
Abort();
throw;
}

if (messageType == WebSocketMessageType.Close)
_state = (_state == WebSocketState.CloseReceived) ? WebSocketState.Closed : WebSocketState.CloseSent;
}

public override void Abort() {
if (_state == WebSocketState.Aborted)
return;

_state = WebSocketState.Aborted;
_abortTaskSource.SetResult(null);
}

public override async Task CloseAsync(WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken cancellationToken) {
try {
await CloseOutputAsync(closeStatus, statusDescription, cancellationToken).ConfigureAwait(false);
await ReceiveAsync(new ArraySegment<byte>(new byte[123]), cancellationToken).ConfigureAwait(false);
}
catch (Exception) {
Abort();
throw;
}
}

public override async Task CloseOutputAsync(WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken cancellationToken) {
if (_state != WebSocketState.Open)
throw new InvalidOperationException($"WebSocket state is {_state}: cannot close.");

try {
await _closeAsync((int)closeStatus, statusDescription, cancellationToken).ConfigureAwait(false);
}
catch (Exception) {
Abort();
throw;
}
_closeStatus = closeStatus;
_closeDescription = statusDescription;
_state = WebSocketState.CloseSent;
}

private int MapMessageTypeFromEnum(WebSocketMessageType messageType) {
switch (messageType) {
case WebSocketMessageType.Binary: return OwinWebSocketMessageType.Binary;
case WebSocketMessageType.Text: return OwinWebSocketMessageType.Text;
case WebSocketMessageType.Close: return OwinWebSocketMessageType.Close;
default: throw new ArgumentException($"Unknown message type: {messageType}.", nameof(messageType));
}
}

private WebSocketMessageType MapMessageTypeToEnum(int messageType) {
switch (messageType) {
case OwinWebSocketMessageType.Binary: return WebSocketMessageType.Binary;
case OwinWebSocketMessageType.Text: return WebSocketMessageType.Text;
case OwinWebSocketMessageType.Close: return WebSocketMessageType.Close;
default: throw new ArgumentException($"Unknown message type: {messageType}.", nameof(messageType));
}
}

public override void Dispose() {
}
}
}
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

"dependencies": {
"JetBrains.Annotations": "10.1.5",
"MirrorSharp": "0.9.0-*",
"MirrorSharp.Common": "0.9.0-*",
"Owin": "1.0.0"
},

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"xunit": "2.2.0-beta2-build3300",
"dotnet-test-xunit": "2.2.0-preview2-build1029",
"Moq": "4.6.38-alpha",
"MirrorSharp": "*",
"MirrorSharp.Common": "*",
"System.Net.WebSockets": "4.0.0"
},

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
25 changes: 7 additions & 18 deletions MirrorSharp.sln
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,24 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{ED635736-B827-4C88-80B9-EBBE1DDADF12}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F358FD73-4BC9-42AA-BC4B-38DDB81FE813}"
ProjectSection(SolutionItems) = preProject
global.json = global.json
EndProjectSection
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MirrorSharp", "src\MirrorSharp\MirrorSharp.xproj", "{C130C962-D17F-4741-B2B4-D74263BF380A}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MirrorSharp.Common", "MirrorSharp.Common\MirrorSharp.Common.xproj", "{C130C962-D17F-4741-B2B4-D74263BF380A}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MirrorSharp.AspNetCore.Demo", "src\MirrorSharp.Demo\MirrorSharp.AspNetCore.Demo.xproj", "{70BCCC0E-6EEF-40D0-932A-87F9C42BD67B}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MirrorSharp.AspNetCore.Demo", "MirrorSharp.AspNetCore.Demo\MirrorSharp.AspNetCore.Demo.xproj", "{70BCCC0E-6EEF-40D0-932A-87F9C42BD67B}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MirrorSharp.Tests", "src\MirrorSharp.Tests\MirrorSharp.Tests.xproj", "{09F91A91-3DB9-44FF-A65E-5DB5A3F3A7A5}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MirrorSharp.Tests", "MirrorSharp.Tests\MirrorSharp.Tests.xproj", "{09F91A91-3DB9-44FF-A65E-5DB5A3F3A7A5}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MirrorSharp.AspNetCore", "src\MirrorSharp.AspNetCore\MirrorSharp.AspNetCore.xproj", "{EED8CD01-22F8-4E7B-95F0-2C778A6971FC}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MirrorSharp.AspNetCore", "MirrorSharp.AspNetCore\MirrorSharp.AspNetCore.xproj", "{EED8CD01-22F8-4E7B-95F0-2C778A6971FC}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MirrorSharp.Owin", "src\MirrorSharp.Owin\MirrorSharp.Owin.xproj", "{00CC1A50-B233-4045-9540-CB2316808C1B}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MirrorSharp.Owin", "MirrorSharp.Owin\MirrorSharp.Owin.xproj", "{00CC1A50-B233-4045-9540-CB2316808C1B}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MirrorSharp.Owin.Demo", "src\MirrorSharp.Owin.Demo\MirrorSharp.Owin.Demo.xproj", "{D2EB1CDD-12B5-4FDC-A56C-8A327200E759}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MirrorSharp.Owin.Demo", "MirrorSharp.Owin.Demo\MirrorSharp.Owin.Demo.xproj", "{D2EB1CDD-12B5-4FDC-A56C-8A327200E759}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MirrorSharp.WebAssets", "src\MirrorSharp.WebAssets\MirrorSharp.WebAssets.xproj", "{FF13139E-69D3-472E-B4FE-AC2623AD67B9}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MirrorSharp.WebAssets", "MirrorSharp.WebAssets\MirrorSharp.WebAssets.xproj", "{FF13139E-69D3-472E-B4FE-AC2623AD67B9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -62,13 +60,4 @@ Global
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{C130C962-D17F-4741-B2B4-D74263BF380A} = {ED635736-B827-4C88-80B9-EBBE1DDADF12}
{70BCCC0E-6EEF-40D0-932A-87F9C42BD67B} = {ED635736-B827-4C88-80B9-EBBE1DDADF12}
{09F91A91-3DB9-44FF-A65E-5DB5A3F3A7A5} = {ED635736-B827-4C88-80B9-EBBE1DDADF12}
{EED8CD01-22F8-4E7B-95F0-2C778A6971FC} = {ED635736-B827-4C88-80B9-EBBE1DDADF12}
{00CC1A50-B233-4045-9540-CB2316808C1B} = {ED635736-B827-4C88-80B9-EBBE1DDADF12}
{D2EB1CDD-12B5-4FDC-A56C-8A327200E759} = {ED635736-B827-4C88-80B9-EBBE1DDADF12}
{FF13139E-69D3-472E-B4FE-AC2623AD67B9} = {ED635736-B827-4C88-80B9-EBBE1DDADF12}
EndGlobalSection
EndGlobal
Loading

0 comments on commit d662f91

Please sign in to comment.