Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 9791680

Browse files
author
Lakshmi Priya Sekar
committed
Add System.Net.WebSocket.Protocol initial commit.
1 parent 7a98b8e commit 9791680

20 files changed

+674
-48
lines changed

pkg/Microsoft.Private.PackageBaseline/packageIndex.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2884,6 +2884,11 @@
28842884
"4.0.1.0": "4.3.0"
28852885
}
28862886
},
2887+
"System.Net.WebSockets.WebSocketProtocol": {
2888+
"AssemblyVersionInPackageVersion": {
2889+
"4.0.0.0": "4.5.0"
2890+
}
2891+
},
28872892
"System.Numerics": {
28882893
"InboxOn": {
28892894
"netcoreapp2.0": "4.0.0.0",

pkg/descriptions.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,6 +1039,13 @@
10391039
"System.Net.WebResponse"
10401040
]
10411041
},
1042+
{
1043+
"Name": "System.Net.WebSockets.WebSocketProtocol",
1044+
"Description": "Provides the WebSocketProtocol class, which allows creating a websocket from a connected stream using WebSocketsProtocol.CreateFromConnectedStream.",
1045+
"CommonTypes": [
1046+
"System.Net.WebSockets.WebSocketProtocol"
1047+
]
1048+
},
10421049
{
10431050
"Name": "System.Net.Http.WinHttpHandler",
10441051
"Description": "Provides a message handler for HttpClient based on the WinHTTP interface of Windows. While similar to HttpClientHandler, it provides developers more granular control over the application's HTTP communication than the HttpClientHandler.",

src/System.Net.WebSockets/src/System/Net/WebSockets/ManagedWebSocket.cs renamed to src/Common/src/System/Net/WebSockets/ManagedWebSocket.cs

Lines changed: 5 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
using System.Threading;
1414
using System.Threading.Tasks;
1515

16-
// NOTE: This file is shared between CoreFX and ASP.NET. Be very thoughtful when changing it.
17-
1816
namespace System.Net.WebSockets
1917
{
2018
/// <summary>A managed implementation of a web socket that sends and receives data via a <see cref="Stream"/>.</summary>
@@ -26,7 +24,7 @@ namespace System.Net.WebSockets
2624
/// a send operation while another is in progress or a receive operation while another is in progress will
2725
/// result in an exception.
2826
/// </remarks>
29-
internal sealed class ManagedWebSocket : WebSocket
27+
internal sealed partial class ManagedWebSocket : WebSocket
3028
{
3129
/// <summary>Creates a <see cref="ManagedWebSocket"/> from a <see cref="Stream"/> connected to a websocket endpoint.</summary>
3230
/// <param name="stream">The connected Stream.</param>
@@ -264,10 +262,10 @@ public override Task SendAsync(ArraySegment<byte> buffer, WebSocketMessageType m
264262

265263
WebSocketValidate.ValidateArraySegment(buffer, nameof(buffer));
266264

267-
return SendAsync((ReadOnlyMemory<byte>)buffer, messageType, endOfMessage, cancellationToken);
265+
return SendPrivateAsync((ReadOnlyMemory<byte>)buffer, messageType, endOfMessage, cancellationToken);
268266
}
269267

270-
public override Task SendAsync(ReadOnlyMemory<byte> buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken)
268+
private Task SendPrivateAsync(ReadOnlyMemory<byte> buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken)
271269
{
272270
if (messageType != WebSocketMessageType.Text && messageType != WebSocketMessageType.Binary)
273271
{
@@ -321,29 +319,6 @@ public override Task<WebSocketReceiveResult> ReceiveAsync(ArraySegment<byte> buf
321319
}
322320
}
323321

324-
public override ValueTask<ValueWebSocketReceiveResult> ReceiveAsync(Memory<byte> buffer, CancellationToken cancellationToken)
325-
{
326-
try
327-
{
328-
WebSocketValidate.ThrowIfInvalidState(_state, _disposed, s_validReceiveStates);
329-
330-
Debug.Assert(!Monitor.IsEntered(StateUpdateLock), $"{nameof(StateUpdateLock)} must never be held when acquiring {nameof(ReceiveAsyncLock)}");
331-
lock (ReceiveAsyncLock) // synchronize with receives in CloseAsync
332-
{
333-
ThrowIfOperationInProgress(_lastReceiveAsync);
334-
ValueTask<ValueWebSocketReceiveResult> t = ReceiveAsyncPrivate<ValueWebSocketReceiveResultGetter, ValueWebSocketReceiveResult>(buffer, cancellationToken);
335-
_lastReceiveAsync =
336-
t.IsCompletedSuccessfully ? (t.Result.MessageType == WebSocketMessageType.Close ? s_cachedCloseTask : Task.CompletedTask) :
337-
t.AsTask();
338-
return t;
339-
}
340-
}
341-
catch (Exception exc)
342-
{
343-
return new ValueTask<ValueWebSocketReceiveResult>(Task.FromException<ValueWebSocketReceiveResult>(exc));
344-
}
345-
}
346-
347322
public override Task CloseAsync(WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken cancellationToken)
348323
{
349324
WebSocketValidate.ValidateCloseStatus(closeStatus, statusDescription);
@@ -545,7 +520,7 @@ private void SendKeepAliveFrameAsync()
545520
Task t = SendFrameLockAcquiredNonCancelableAsync(MessageOpcode.Ping, true, Memory<byte>.Empty);
546521

547522
// "Observe" any exception, ignoring it to prevent the unobserved exception event from being raised.
548-
if (!t.IsCompletedSuccessfully)
523+
if (t.Status != TaskStatus.RanToCompletion)
549524
{
550525
t.ContinueWith(p => { Exception ignored = p.Exception; },
551526
CancellationToken.None,
@@ -1068,16 +1043,7 @@ private async Task CloseAsyncPrivate(WebSocketCloseStatus closeStatus, string st
10681043
// a race condition here, e.g. if there's a in-flight receive that completes after we check, but that's fine: worst
10691044
// case is we then await it, find that it's not what we need, and try again.
10701045
receiveTask = _lastReceiveAsync;
1071-
if (receiveTask == null ||
1072-
(receiveTask.Status == TaskStatus.RanToCompletion &&
1073-
!(receiveTask is Task<WebSocketReceiveResult> wsrr && wsrr.Result.MessageType == WebSocketMessageType.Close) &&
1074-
!(receiveTask is Task<ValueWebSocketReceiveResult> vwsrr && vwsrr.Result.MessageType == WebSocketMessageType.Close)))
1075-
{
1076-
ValueTask<ValueWebSocketReceiveResult> vt = ReceiveAsyncPrivate<ValueWebSocketReceiveResultGetter, ValueWebSocketReceiveResult>(closeBuffer, cancellationToken);
1077-
_lastReceiveAsync = receiveTask =
1078-
vt.IsCompletedSuccessfully ? (vt.Result.MessageType == WebSocketMessageType.Close ? s_cachedCloseTask : Task.CompletedTask) :
1079-
vt.AsTask();
1080-
}
1046+
_lastReceiveAsync = receiveTask = ValidateAndReceiveAsync(receiveTask, closeBuffer, cancellationToken);
10811047
}
10821048

10831049
// Wait for whatever receive task we have. We'll then loop around again to re-check our state.
@@ -1453,12 +1419,5 @@ private interface IWebSocketReceiveResultGetter<TResult>
14531419
public WebSocketReceiveResult GetResult(int count, WebSocketMessageType messageType, bool endOfMessage, WebSocketCloseStatus? closeStatus, string closeDescription) =>
14541420
new WebSocketReceiveResult(count, messageType, endOfMessage, closeStatus, closeDescription);
14551421
}
1456-
1457-
/// <summary><see cref="IWebSocketReceiveResultGetter{TResult}"/> implementation for <see cref="ValueWebSocketReceiveResult"/>.</summary>
1458-
private readonly struct ValueWebSocketReceiveResultGetter : IWebSocketReceiveResultGetter<ValueWebSocketReceiveResult>
1459-
{
1460-
public ValueWebSocketReceiveResult GetResult(int count, WebSocketMessageType messageType, bool endOfMessage, WebSocketCloseStatus? closeStatus, string closeDescription) =>
1461-
new ValueWebSocketReceiveResult(count, messageType, endOfMessage); // closeStatus/closeDescription are ignored
1462-
}
14631422
}
14641423
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio 15
4+
VisualStudioVersion = 15.0.27214.1
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Net.WebSockets.WebSocketProtocol", "src\System.Net.WebSockets.WebSocketProtocol.csproj", "{747BE014-7C1D-4460-95AF-B41C35717165}"
7+
EndProject
8+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{D5A36F24-E27C-43DF-8658-10C5290423E0}"
9+
EndProject
10+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{9D10D7AD-2F8C-4F7A-B0FA-E5EB3ECE287F}"
11+
EndProject
12+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Net.WebSockets.WebSocketProtocol", "ref\System.Net.WebSockets.WebSocketProtocol.csproj", "{4EDBE9F5-D10A-4553-AE24-2E0E946B15B0}"
13+
EndProject
14+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{F47347C3-433C-4D3B-90F9-487FE7F4F444}"
15+
EndProject
16+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Net.WebSockets.WebSocketProtocol.Tests", "tests\System.Net.WebSockets.WebSocketProtocol.Tests.csproj", "{CF73547B-07D2-4290-A14A-CA2A354F4D21}"
17+
EndProject
18+
Global
19+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
20+
Debug|Any CPU = Debug|Any CPU
21+
netstandard-Debug|Any CPU = netstandard-Debug|Any CPU
22+
netstandard-Release|Any CPU = netstandard-Release|Any CPU
23+
EndGlobalSection
24+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
25+
{747BE014-7C1D-4460-95AF-B41C35717165}.Debug|Any CPU.ActiveCfg = netstandard-Debug|Any CPU
26+
{747BE014-7C1D-4460-95AF-B41C35717165}.Debug|Any CPU.Build.0 = netstandard-Debug|Any CPU
27+
{747BE014-7C1D-4460-95AF-B41C35717165}.netstandard-Debug|Any CPU.ActiveCfg = netstandard-Debug|Any CPU
28+
{747BE014-7C1D-4460-95AF-B41C35717165}.netstandard-Debug|Any CPU.Build.0 = netstandard-Debug|Any CPU
29+
{747BE014-7C1D-4460-95AF-B41C35717165}.netstandard-Release|Any CPU.ActiveCfg = netstandard-Release|Any CPU
30+
{747BE014-7C1D-4460-95AF-B41C35717165}.netstandard-Release|Any CPU.Build.0 = netstandard-Release|Any CPU
31+
{4EDBE9F5-D10A-4553-AE24-2E0E946B15B0}.Debug|Any CPU.ActiveCfg = netstandard-Debug|Any CPU
32+
{4EDBE9F5-D10A-4553-AE24-2E0E946B15B0}.Debug|Any CPU.Build.0 = netstandard-Debug|Any CPU
33+
{4EDBE9F5-D10A-4553-AE24-2E0E946B15B0}.netstandard-Debug|Any CPU.ActiveCfg = netstandard-Debug|Any CPU
34+
{4EDBE9F5-D10A-4553-AE24-2E0E946B15B0}.netstandard-Debug|Any CPU.Build.0 = netstandard-Debug|Any CPU
35+
{4EDBE9F5-D10A-4553-AE24-2E0E946B15B0}.netstandard-Release|Any CPU.ActiveCfg = netstandard-Release|Any CPU
36+
{4EDBE9F5-D10A-4553-AE24-2E0E946B15B0}.netstandard-Release|Any CPU.Build.0 = netstandard-Release|Any CPU
37+
{CF73547B-07D2-4290-A14A-CA2A354F4D21}.Debug|Any CPU.ActiveCfg = netstandard-Debug|Any CPU
38+
{CF73547B-07D2-4290-A14A-CA2A354F4D21}.Debug|Any CPU.Build.0 = netstandard-Debug|Any CPU
39+
{CF73547B-07D2-4290-A14A-CA2A354F4D21}.netstandard-Debug|Any CPU.ActiveCfg = netstandard-Debug|Any CPU
40+
{CF73547B-07D2-4290-A14A-CA2A354F4D21}.netstandard-Debug|Any CPU.Build.0 = netstandard-Debug|Any CPU
41+
{CF73547B-07D2-4290-A14A-CA2A354F4D21}.netstandard-Release|Any CPU.ActiveCfg = netstandard-Release|Any CPU
42+
{CF73547B-07D2-4290-A14A-CA2A354F4D21}.netstandard-Release|Any CPU.Build.0 = netstandard-Release|Any CPU
43+
EndGlobalSection
44+
GlobalSection(SolutionProperties) = preSolution
45+
HideSolutionNode = FALSE
46+
EndGlobalSection
47+
GlobalSection(NestedProjects) = preSolution
48+
{747BE014-7C1D-4460-95AF-B41C35717165} = {D5A36F24-E27C-43DF-8658-10C5290423E0}
49+
{4EDBE9F5-D10A-4553-AE24-2E0E946B15B0} = {9D10D7AD-2F8C-4F7A-B0FA-E5EB3ECE287F}
50+
{CF73547B-07D2-4290-A14A-CA2A354F4D21} = {F47347C3-433C-4D3B-90F9-487FE7F4F444}
51+
EndGlobalSection
52+
GlobalSection(ExtensibilityGlobals) = postSolution
53+
SolutionGuid = {6618B298-BA53-4E58-9795-756C6DC1BA38}
54+
EndGlobalSection
55+
EndGlobal
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="..\dir.props" />
4+
<PropertyGroup>
5+
<AssemblyVersion>4.0.0.0</AssemblyVersion>
6+
<AssemblyKey>Open</AssemblyKey>
7+
</PropertyGroup>
8+
</Project>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
4+
<ItemGroup>
5+
<ProjectReference Include="..\ref\System.Net.WebSockets.WebSocketProtocol.csproj">
6+
<SupportedFramework>net461;netcoreapp2.0;$(AllXamarinFrameworks)</SupportedFramework>
7+
</ProjectReference>
8+
<ProjectReference Include="..\src\System.Net.WebSockets.WebSocketProtocol.csproj" />
9+
</ItemGroup>
10+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
11+
</Project>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<BuildConfigurations>
5+
netstandard;
6+
</BuildConfigurations>
7+
</PropertyGroup>
8+
</Project>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
// ------------------------------------------------------------------------------
5+
// Changes to this file must follow the http://aka.ms/api-review process.
6+
// ------------------------------------------------------------------------------
7+
8+
using System.IO;
9+
10+
namespace System.Net.WebSockets
11+
{
12+
public static class WebSocketProtocol
13+
{
14+
public static WebSocket CreateFromStream(Stream stream, bool isServer, string subProtocol, TimeSpan keepAliveInterval, Memory<byte> buffer = default) { throw null; }
15+
}
16+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
4+
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Debug|AnyCPU'" />
5+
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Release|AnyCPU'" />
6+
<ItemGroup>
7+
<Compile Include="System.Net.WebSockets.WebSocketProtocol.cs" />
8+
</ItemGroup>
9+
<ItemGroup>
10+
<ProjectReference Include="..\..\System.Memory\ref\System.Memory.csproj" />
11+
</ItemGroup>
12+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
13+
</Project>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<BuildConfigurations>
5+
netstandard;
6+
netcoreapp;
7+
</BuildConfigurations>
8+
</PropertyGroup>
9+
</Project>

0 commit comments

Comments
 (0)