#137 Relayer and ifdef WebSockets
Rename Microsoft.Net.WebSockets to Microsoft.Net.WebSockets.Server. Reverse dependency with Microsoft.Net.Http.Server. ifdef out IHttpWebSocketFeature.
This commit is contained in:
parent
7a310a35db
commit
fca0476936
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.22710.0
|
||||
VisualStudioVersion = 14.0.23107.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestClient", "samples\TestClient\TestClient.csproj", "{8B828433-B333-4C19-96AE-00BFFF9D8841}"
|
||||
EndProject
|
||||
|
|
@ -17,7 +17,7 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "HelloWorld", "samples\Hello
|
|||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "SelfHostServer", "samples\SelfHostServer\SelfHostServer.xproj", "{1236F93A-AC5C-4A77-9477-C88F040151CA}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Net.WebSockets", "src\Microsoft.Net.WebSockets\Microsoft.Net.WebSockets.xproj", "{E788AEAE-2CB4-4BFA-8746-D0BB7E93A1BB}"
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Net.WebSockets.Server", "src\Microsoft.Net.WebSockets.Server\Microsoft.Net.WebSockets.Server.xproj", "{E788AEAE-2CB4-4BFA-8746-D0BB7E93A1BB}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Server.WebListener.FunctionalTests", "test\Microsoft.AspNet.Server.WebListener.FunctionalTests\Microsoft.AspNet.Server.WebListener.FunctionalTests.xproj", "{4492FF4C-9032-411D-853F-46B01755E504}"
|
||||
EndProject
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ namespace HelloWorld
|
|||
// Response
|
||||
byte[] bytes = Encoding.ASCII.GetBytes("Hello World: " + DateTime.Now);
|
||||
|
||||
if (context.IsWebSocketRequest)
|
||||
if (context.IsWebSocketRequest())
|
||||
{
|
||||
Console.WriteLine("WebSocket");
|
||||
WebSocket webSocket = await context.AcceptWebSocketAsync();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"Microsoft.Net.Http.Server": "1.0.0-*"
|
||||
"Microsoft.Net.Http.Server": "1.0.0-*",
|
||||
"Microsoft.Net.WebSockets.Server": "1.0.0-*"
|
||||
},
|
||||
"commands": {
|
||||
"sample": "HelloWorld"
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
// permissions and limitations under the License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.WebSockets;
|
||||
|
|
@ -27,8 +26,6 @@ using System.Threading.Tasks;
|
|||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Http.Features;
|
||||
using Microsoft.AspNet.Http.Features.Authentication;
|
||||
using Microsoft.AspNet.Http.Internal;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Microsoft.Net.Http.Server;
|
||||
|
||||
|
|
@ -43,7 +40,9 @@ namespace Microsoft.AspNet.Server.WebListener
|
|||
ITlsTokenBindingFeature,
|
||||
IHttpBufferingFeature,
|
||||
IHttpRequestLifetimeFeature,
|
||||
#if WEBSOCKETS
|
||||
IHttpWebSocketFeature,
|
||||
#endif
|
||||
IHttpAuthenticationFeature,
|
||||
IHttpUpgradeFeature,
|
||||
IHttpRequestIdentifierFeature
|
||||
|
|
@ -422,12 +421,12 @@ namespace Microsoft.AspNet.Server.WebListener
|
|||
{
|
||||
return _requestContext.UpgradeAsync();
|
||||
}
|
||||
|
||||
#if WEBSOCKETS
|
||||
bool IHttpWebSocketFeature.IsWebSocketRequest
|
||||
{
|
||||
get
|
||||
{
|
||||
return _requestContext.IsWebSocketRequest;
|
||||
return _requestContext.IsWebSocketRequest();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -441,7 +440,7 @@ namespace Microsoft.AspNet.Server.WebListener
|
|||
}
|
||||
return _requestContext.AcceptWebSocketAsync(subProtocol);
|
||||
}
|
||||
|
||||
#endif
|
||||
ClaimsPrincipal IHttpAuthenticationFeature.User
|
||||
{
|
||||
get
|
||||
|
|
|
|||
|
|
@ -24,14 +24,11 @@
|
|||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.WebSockets;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Net.WebSockets;
|
||||
|
||||
namespace Microsoft.Net.Http.Server
|
||||
{
|
||||
|
|
@ -174,198 +171,6 @@ namespace Microsoft.Net.Http.Server
|
|||
return Task.FromResult(opaqueStream);
|
||||
}
|
||||
|
||||
public bool IsWebSocketRequest
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!WebSocketHelpers.AreWebSocketsSupported)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsUpgradableRequest)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!string.Equals("GET", Request.Method, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Connection: Upgrade (some odd clients send Upgrade,KeepAlive)
|
||||
string connection = Request.Headers[HttpKnownHeaderNames.Connection];
|
||||
if (connection == null || connection.IndexOf(HttpKnownHeaderNames.Upgrade, StringComparison.OrdinalIgnoreCase) < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Upgrade: websocket
|
||||
string upgrade = Request.Headers[HttpKnownHeaderNames.Upgrade];
|
||||
if (!string.Equals(WebSocketHelpers.WebSocketUpgradeToken, upgrade, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sec-WebSocket-Version: 13
|
||||
string version = Request.Headers[HttpKnownHeaderNames.SecWebSocketVersion];
|
||||
if (!string.Equals(WebSocketConstants.SupportedProtocolVersion, version, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sec-WebSocket-Key: {base64string}
|
||||
string key = Request.Headers[HttpKnownHeaderNames.SecWebSocketKey];
|
||||
if (!WebSocketHelpers.IsValidWebSocketKey(key))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Compare IsWebSocketRequest
|
||||
private void ValidateWebSocketRequest()
|
||||
{
|
||||
if (!WebSocketHelpers.AreWebSocketsSupported)
|
||||
{
|
||||
throw new NotSupportedException("WebSockets are not supported on this platform.");
|
||||
}
|
||||
|
||||
if (!IsUpgradableRequest)
|
||||
{
|
||||
throw new InvalidOperationException("This request is not a valid upgrade request.");
|
||||
}
|
||||
|
||||
if (!string.Equals("GET", Request.Method, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new InvalidOperationException("This request is not a valid upgrade request; invalid verb: " + Request.Method);
|
||||
}
|
||||
|
||||
// Connection: Upgrade (some odd clients send Upgrade,KeepAlive)
|
||||
string connection = Request.Headers[HttpKnownHeaderNames.Connection];
|
||||
if (connection == null || connection.IndexOf(HttpKnownHeaderNames.Upgrade, StringComparison.OrdinalIgnoreCase) < 0)
|
||||
{
|
||||
throw new InvalidOperationException("The Connection header is invalid: " + connection);
|
||||
}
|
||||
|
||||
// Upgrade: websocket
|
||||
string upgrade = Request.Headers[HttpKnownHeaderNames.Upgrade];
|
||||
if (!string.Equals(WebSocketHelpers.WebSocketUpgradeToken, upgrade, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new InvalidOperationException("The Upgrade header is invalid: " + upgrade);
|
||||
}
|
||||
|
||||
// Sec-WebSocket-Version: 13
|
||||
string version = Request.Headers[HttpKnownHeaderNames.SecWebSocketVersion];
|
||||
if (!string.Equals(WebSocketConstants.SupportedProtocolVersion, version, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new InvalidOperationException("The Sec-WebSocket-Version header is invalid or not supported: " + version);
|
||||
}
|
||||
|
||||
// Sec-WebSocket-Key: {base64string}
|
||||
string key = Request.Headers[HttpKnownHeaderNames.SecWebSocketKey];
|
||||
if (!WebSocketHelpers.IsValidWebSocketKey(key))
|
||||
{
|
||||
throw new InvalidOperationException("The Sec-WebSocket-Key header is invalid: " + upgrade);
|
||||
}
|
||||
}
|
||||
|
||||
public Task<WebSocket> AcceptWebSocketAsync()
|
||||
{
|
||||
return AcceptWebSocketAsync(null,
|
||||
WebSocketHelpers.DefaultReceiveBufferSize,
|
||||
WebSocketHelpers.DefaultKeepAliveInterval);
|
||||
}
|
||||
|
||||
public Task<WebSocket> AcceptWebSocketAsync(string subProtocol)
|
||||
{
|
||||
return AcceptWebSocketAsync(subProtocol,
|
||||
WebSocketHelpers.DefaultReceiveBufferSize,
|
||||
WebSocketHelpers.DefaultKeepAliveInterval);
|
||||
}
|
||||
|
||||
public Task<WebSocket> AcceptWebSocketAsync(string subProtocol, TimeSpan keepAliveInterval)
|
||||
{
|
||||
return AcceptWebSocketAsync(subProtocol,
|
||||
WebSocketHelpers.DefaultReceiveBufferSize,
|
||||
keepAliveInterval);
|
||||
}
|
||||
|
||||
public Task<WebSocket> AcceptWebSocketAsync(
|
||||
string subProtocol,
|
||||
int receiveBufferSize,
|
||||
TimeSpan keepAliveInterval)
|
||||
{
|
||||
WebSocketHelpers.ValidateOptions(subProtocol, receiveBufferSize, WebSocketBuffer.MinSendBufferSize, keepAliveInterval);
|
||||
|
||||
ArraySegment<byte> internalBuffer = WebSocketBuffer.CreateInternalBufferArraySegment(receiveBufferSize, WebSocketBuffer.MinSendBufferSize, true);
|
||||
return this.AcceptWebSocketAsync(subProtocol,
|
||||
receiveBufferSize,
|
||||
keepAliveInterval,
|
||||
internalBuffer);
|
||||
}
|
||||
|
||||
public Task<WebSocket> AcceptWebSocketAsync(
|
||||
string subProtocol,
|
||||
int receiveBufferSize,
|
||||
TimeSpan keepAliveInterval,
|
||||
ArraySegment<byte> internalBuffer)
|
||||
{
|
||||
if (!IsUpgradableRequest)
|
||||
{
|
||||
throw new InvalidOperationException("This request is cannot be upgraded.");
|
||||
}
|
||||
WebSocketHelpers.ValidateOptions(subProtocol, receiveBufferSize, WebSocketBuffer.MinSendBufferSize, keepAliveInterval);
|
||||
WebSocketHelpers.ValidateArraySegment<byte>(internalBuffer, "internalBuffer");
|
||||
WebSocketBuffer.Validate(internalBuffer.Count, receiveBufferSize, WebSocketBuffer.MinSendBufferSize, true);
|
||||
|
||||
return AcceptWebSocketAsyncCore(subProtocol, receiveBufferSize, keepAliveInterval, internalBuffer);
|
||||
}
|
||||
|
||||
private async Task<WebSocket> AcceptWebSocketAsyncCore(
|
||||
string subProtocol,
|
||||
int receiveBufferSize,
|
||||
TimeSpan keepAliveInterval,
|
||||
ArraySegment<byte> internalBuffer)
|
||||
{
|
||||
try
|
||||
{
|
||||
ValidateWebSocketRequest();
|
||||
|
||||
var subProtocols = Request.Headers.GetValues(HttpKnownHeaderNames.SecWebSocketProtocol);
|
||||
bool shouldSendSecWebSocketProtocolHeader = WebSocketHelpers.ProcessWebSocketProtocolHeader(subProtocols, subProtocol);
|
||||
if (shouldSendSecWebSocketProtocolHeader)
|
||||
{
|
||||
Response.Headers[HttpKnownHeaderNames.SecWebSocketProtocol] = subProtocol;
|
||||
}
|
||||
|
||||
// negotiate the websocket key return value
|
||||
string secWebSocketKey = Request.Headers[HttpKnownHeaderNames.SecWebSocketKey];
|
||||
string secWebSocketAccept = WebSocketHelpers.GetSecWebSocketAcceptString(secWebSocketKey);
|
||||
|
||||
Response.Headers.Append(HttpKnownHeaderNames.Connection, HttpKnownHeaderNames.Upgrade);
|
||||
Response.Headers.Append(HttpKnownHeaderNames.Upgrade, WebSocketHelpers.WebSocketUpgradeToken);
|
||||
Response.Headers.Append(HttpKnownHeaderNames.SecWebSocketAccept, secWebSocketAccept);
|
||||
|
||||
Stream opaqueStream = await UpgradeAsync();
|
||||
|
||||
return WebSocketHelpers.CreateServerWebSocket(
|
||||
opaqueStream,
|
||||
subProtocol,
|
||||
receiveBufferSize,
|
||||
keepAliveInterval,
|
||||
internalBuffer);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.LogException(Logger, "AcceptWebSocketAsync", ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
public bool TryGetChannelBinding(ref ChannelBinding value)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@
|
|||
"description": "Implementation of WebListener, a successor to HttpListener. It is used in the WebListener server package.",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "1.0.0-*",
|
||||
"Microsoft.Extensions.Primitives": "1.0.0-*",
|
||||
"Microsoft.Net.WebSockets": "1.0.0-*"
|
||||
"Microsoft.Extensions.Primitives": "1.0.0-*"
|
||||
},
|
||||
"compilationOptions": {
|
||||
"allowUnsafe": true,
|
||||
|
|
@ -15,11 +14,16 @@
|
|||
"dotnet5.4": {
|
||||
"dependencies": {
|
||||
"Microsoft.Win32.Primitives": "4.0.1-*",
|
||||
"System.Diagnostics.Contracts": "4.0.1-*",
|
||||
"System.Diagnostics.Debug": "4.0.11-*",
|
||||
"System.Diagnostics.Tools": "4.0.1-*",
|
||||
"System.IO": "4.0.11-*",
|
||||
"System.IO.FileSystem": "4.0.1-*",
|
||||
"System.Net.Primitives": "4.0.11-*",
|
||||
"System.Security.Claims": "4.0.1-*",
|
||||
"System.Security.Cryptography.X509Certificates": "4.0.0-*",
|
||||
"System.Security.Principal.Windows": "4.0.0-*",
|
||||
"System.Text.Encoding.Extensions": "4.0.11-*",
|
||||
"System.Threading.Overlapped": "4.0.0-*"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
namespace Microsoft.Net.WebSockets
|
||||
{
|
||||
public enum WebSocketError
|
||||
internal enum WebSocketError
|
||||
{
|
||||
Success = 0,
|
||||
InvalidMessageType = 1,
|
||||
|
|
@ -115,7 +115,7 @@ namespace Microsoft.Net.WebSockets
|
|||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
#if !DOTNET5_4
|
||||
public override int ErrorCode
|
||||
{
|
||||
get
|
||||
|
|
@ -123,7 +123,7 @@ namespace Microsoft.Net.WebSockets
|
|||
return base.NativeErrorCode;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
public WebSocketError WebSocketErrorCode
|
||||
{
|
||||
get
|
||||
|
|
@ -0,0 +1,217 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc.
|
||||
// All Rights Reserved
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
|
||||
// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
|
||||
// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="WebSocketHelpers.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net.WebSockets;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Net.WebSockets;
|
||||
|
||||
namespace Microsoft.Net.Http.Server
|
||||
{
|
||||
public static class WebSocketExtensions
|
||||
{
|
||||
public static bool IsWebSocketRequest(this RequestContext context)
|
||||
{
|
||||
if (!WebSocketHelpers.AreWebSocketsSupported)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!context.IsUpgradableRequest)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!string.Equals("GET", context.Request.Method, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Connection: Upgrade (some odd clients send Upgrade,KeepAlive)
|
||||
string connection = context.Request.Headers[HttpKnownHeaderNames.Connection];
|
||||
if (connection == null || connection.IndexOf(HttpKnownHeaderNames.Upgrade, StringComparison.OrdinalIgnoreCase) < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Upgrade: websocket
|
||||
string upgrade = context.Request.Headers[HttpKnownHeaderNames.Upgrade];
|
||||
if (!string.Equals(WebSocketHelpers.WebSocketUpgradeToken, upgrade, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sec-WebSocket-Version: 13
|
||||
string version = context.Request.Headers[HttpKnownHeaderNames.SecWebSocketVersion];
|
||||
if (!string.Equals(WebSocketConstants.SupportedProtocolVersion, version, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sec-WebSocket-Key: {base64string}
|
||||
string key = context.Request.Headers[HttpKnownHeaderNames.SecWebSocketKey];
|
||||
if (!WebSocketHelpers.IsValidWebSocketKey(key))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Compare IsWebSocketRequest()
|
||||
private static void ValidateWebSocketRequest(RequestContext context)
|
||||
{
|
||||
if (!WebSocketHelpers.AreWebSocketsSupported)
|
||||
{
|
||||
throw new NotSupportedException("WebSockets are not supported on this platform.");
|
||||
}
|
||||
|
||||
if (!context.IsUpgradableRequest)
|
||||
{
|
||||
throw new InvalidOperationException("This request is not a valid upgrade request.");
|
||||
}
|
||||
|
||||
if (!string.Equals("GET", context.Request.Method, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new InvalidOperationException("This request is not a valid upgrade request; invalid verb: " + context.Request.Method);
|
||||
}
|
||||
|
||||
// Connection: Upgrade (some odd clients send Upgrade,KeepAlive)
|
||||
string connection = context.Request.Headers[HttpKnownHeaderNames.Connection];
|
||||
if (connection == null || connection.IndexOf(HttpKnownHeaderNames.Upgrade, StringComparison.OrdinalIgnoreCase) < 0)
|
||||
{
|
||||
throw new InvalidOperationException("The Connection header is invalid: " + connection);
|
||||
}
|
||||
|
||||
// Upgrade: websocket
|
||||
string upgrade = context.Request.Headers[HttpKnownHeaderNames.Upgrade];
|
||||
if (!string.Equals(WebSocketHelpers.WebSocketUpgradeToken, upgrade, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new InvalidOperationException("The Upgrade header is invalid: " + upgrade);
|
||||
}
|
||||
|
||||
// Sec-WebSocket-Version: 13
|
||||
string version = context.Request.Headers[HttpKnownHeaderNames.SecWebSocketVersion];
|
||||
if (!string.Equals(WebSocketConstants.SupportedProtocolVersion, version, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new InvalidOperationException("The Sec-WebSocket-Version header is invalid or not supported: " + version);
|
||||
}
|
||||
|
||||
// Sec-WebSocket-Key: {base64string}
|
||||
string key = context.Request.Headers[HttpKnownHeaderNames.SecWebSocketKey];
|
||||
if (!WebSocketHelpers.IsValidWebSocketKey(key))
|
||||
{
|
||||
throw new InvalidOperationException("The Sec-WebSocket-Key header is invalid: " + upgrade);
|
||||
}
|
||||
}
|
||||
|
||||
public static Task<WebSocket> AcceptWebSocketAsync(this RequestContext context)
|
||||
{
|
||||
return context.AcceptWebSocketAsync(null,
|
||||
WebSocketHelpers.DefaultReceiveBufferSize,
|
||||
WebSocketHelpers.DefaultKeepAliveInterval);
|
||||
}
|
||||
|
||||
public static Task<WebSocket> AcceptWebSocketAsync(this RequestContext context, string subProtocol)
|
||||
{
|
||||
return context.AcceptWebSocketAsync(subProtocol,
|
||||
WebSocketHelpers.DefaultReceiveBufferSize,
|
||||
WebSocketHelpers.DefaultKeepAliveInterval);
|
||||
}
|
||||
|
||||
public static Task<WebSocket> AcceptWebSocketAsync(this RequestContext context, string subProtocol, TimeSpan keepAliveInterval)
|
||||
{
|
||||
return context.AcceptWebSocketAsync(subProtocol,
|
||||
WebSocketHelpers.DefaultReceiveBufferSize,
|
||||
keepAliveInterval);
|
||||
}
|
||||
|
||||
public static Task<WebSocket> AcceptWebSocketAsync(
|
||||
this RequestContext context,
|
||||
string subProtocol,
|
||||
int receiveBufferSize,
|
||||
TimeSpan keepAliveInterval)
|
||||
{
|
||||
WebSocketHelpers.ValidateOptions(subProtocol, receiveBufferSize, WebSocketBuffer.MinSendBufferSize, keepAliveInterval);
|
||||
|
||||
ArraySegment<byte> internalBuffer = WebSocketBuffer.CreateInternalBufferArraySegment(receiveBufferSize, WebSocketBuffer.MinSendBufferSize, true);
|
||||
return context.AcceptWebSocketAsync(subProtocol,
|
||||
receiveBufferSize,
|
||||
keepAliveInterval,
|
||||
internalBuffer);
|
||||
}
|
||||
|
||||
public static Task<WebSocket> AcceptWebSocketAsync(
|
||||
this RequestContext context,
|
||||
string subProtocol,
|
||||
int receiveBufferSize,
|
||||
TimeSpan keepAliveInterval,
|
||||
ArraySegment<byte> internalBuffer)
|
||||
{
|
||||
if (!context.IsUpgradableRequest)
|
||||
{
|
||||
throw new InvalidOperationException("This request is cannot be upgraded.");
|
||||
}
|
||||
WebSocketHelpers.ValidateOptions(subProtocol, receiveBufferSize, WebSocketBuffer.MinSendBufferSize, keepAliveInterval);
|
||||
WebSocketHelpers.ValidateArraySegment<byte>(internalBuffer, "internalBuffer");
|
||||
WebSocketBuffer.Validate(internalBuffer.Count, receiveBufferSize, WebSocketBuffer.MinSendBufferSize, true);
|
||||
|
||||
return AcceptWebSocketAsyncCore(context, subProtocol, receiveBufferSize, keepAliveInterval, internalBuffer);
|
||||
}
|
||||
|
||||
private static async Task<WebSocket> AcceptWebSocketAsyncCore(
|
||||
RequestContext context,
|
||||
string subProtocol,
|
||||
int receiveBufferSize,
|
||||
TimeSpan keepAliveInterval,
|
||||
ArraySegment<byte> internalBuffer)
|
||||
{
|
||||
ValidateWebSocketRequest(context);
|
||||
|
||||
var subProtocols = context.Request.Headers.GetValues(HttpKnownHeaderNames.SecWebSocketProtocol);
|
||||
bool shouldSendSecWebSocketProtocolHeader = WebSocketHelpers.ProcessWebSocketProtocolHeader(subProtocols, subProtocol);
|
||||
if (shouldSendSecWebSocketProtocolHeader)
|
||||
{
|
||||
context.Response.Headers[HttpKnownHeaderNames.SecWebSocketProtocol] = subProtocol;
|
||||
}
|
||||
|
||||
// negotiate the websocket key return value
|
||||
string secWebSocketKey = context.Request.Headers[HttpKnownHeaderNames.SecWebSocketKey];
|
||||
string secWebSocketAccept = WebSocketHelpers.GetSecWebSocketAcceptString(secWebSocketKey);
|
||||
|
||||
context.Response.Headers.Append(HttpKnownHeaderNames.Connection, HttpKnownHeaderNames.Upgrade);
|
||||
context.Response.Headers.Append(HttpKnownHeaderNames.Upgrade, WebSocketHelpers.WebSocketUpgradeToken);
|
||||
context.Response.Headers.Append(HttpKnownHeaderNames.SecWebSocketAccept, secWebSocketAccept);
|
||||
|
||||
Stream opaqueStream = await context.UpgradeAsync();
|
||||
|
||||
return WebSocketHelpers.CreateServerWebSocket(
|
||||
opaqueStream,
|
||||
subProtocol,
|
||||
receiveBufferSize,
|
||||
keepAliveInterval,
|
||||
internalBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -92,7 +92,6 @@ namespace Microsoft.Net.WebSockets
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static bool IsValidWebSocketKey(string key)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(key))
|
||||
|
|
@ -27,7 +27,7 @@ using System.Net.WebSockets;
|
|||
|
||||
namespace Microsoft.Net.WebSockets
|
||||
{
|
||||
public static class WebSocketReceiveResultExtensions
|
||||
internal static class WebSocketReceiveResultExtensions
|
||||
{
|
||||
internal static WebSocketReceiveResult DecrementAndClone(ref WebSocketReceiveResult original, int count)
|
||||
{
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
{
|
||||
"version": "1.0.0-*",
|
||||
"description": "Implementation of WebSocket abstract base class. Used by WebListener.",
|
||||
"dependencies": {},
|
||||
"dependencies": {
|
||||
"Microsoft.Net.Http.Server": "1.0.0-*"
|
||||
},
|
||||
"compilationOptions": {
|
||||
"allowUnsafe": true,
|
||||
"keyFile": "../../tools/Key.snk"
|
||||
|
|
@ -11,16 +13,11 @@
|
|||
"dotnet5.4": {
|
||||
"dependencies": {
|
||||
"System.Collections": "4.0.11-*",
|
||||
"System.Diagnostics.Contracts": "4.0.1-*",
|
||||
"System.Diagnostics.Tools": "4.0.1-*",
|
||||
"System.IO": "4.0.11-*",
|
||||
"System.Linq": "4.0.1-*",
|
||||
"System.Net.Primitives": "4.0.11-*",
|
||||
"System.Net.WebSockets": "4.0.0-*",
|
||||
"System.Resources.ResourceManager": "4.0.1-*",
|
||||
"System.Runtime.Extensions": "4.0.11-*",
|
||||
"System.Security.Cryptography.Algorithms": "4.0.0-*",
|
||||
"System.Text.Encoding.Extensions": "4.0.11-*",
|
||||
"System.Threading": "4.0.11-*",
|
||||
"System.Threading.Tasks": "4.0.11-*",
|
||||
"System.Threading.Timer": "4.0.1-*",
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc.
|
||||
// All Rights Reserved
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
|
||||
// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
|
||||
// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="HttpListenerException.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#if DOTNET5_4
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace System.ComponentModel
|
||||
{
|
||||
internal class Win32Exception : ExternalException
|
||||
{
|
||||
/// <devdoc>
|
||||
/// <para>Represents the Win32 error code associated with this exception. This
|
||||
/// field is read-only.</para>
|
||||
/// </devdoc>
|
||||
private readonly int nativeErrorCode;
|
||||
|
||||
/// <devdoc>
|
||||
/// <para>Initializes a new instance of the <see cref='System.ComponentModel.Win32Exception'/> class with the last Win32 error
|
||||
/// that occured.</para>
|
||||
/// </devdoc>
|
||||
public Win32Exception()
|
||||
: this(Marshal.GetLastWin32Error())
|
||||
{
|
||||
}
|
||||
/// <devdoc>
|
||||
/// <para>Initializes a new instance of the <see cref='System.ComponentModel.Win32Exception'/> class with the specified error.</para>
|
||||
/// </devdoc>
|
||||
public Win32Exception(int error)
|
||||
: this(error, GetErrorMessage(error))
|
||||
{
|
||||
}
|
||||
/// <devdoc>
|
||||
/// <para>Initializes a new instance of the <see cref='System.ComponentModel.Win32Exception'/> class with the specified error and the
|
||||
/// specified detailed description.</para>
|
||||
/// </devdoc>
|
||||
public Win32Exception(int error, string message)
|
||||
: base(message)
|
||||
{
|
||||
nativeErrorCode = error;
|
||||
}
|
||||
|
||||
/// <devdoc>
|
||||
/// Initializes a new instance of the Exception class with a specified error message.
|
||||
/// FxCop CA1032: Multiple constructors are required to correctly implement a custom exception.
|
||||
/// </devdoc>
|
||||
public Win32Exception(string message)
|
||||
: this(Marshal.GetLastWin32Error(), message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <devdoc>
|
||||
/// Initializes a new instance of the Exception class with a specified error message and a
|
||||
/// reference to the inner exception that is the cause of this exception.
|
||||
/// FxCop CA1032: Multiple constructors are required to correctly implement a custom exception.
|
||||
/// </devdoc>
|
||||
public Win32Exception(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
nativeErrorCode = Marshal.GetLastWin32Error();
|
||||
}
|
||||
|
||||
|
||||
/// <devdoc>
|
||||
/// <para>Represents the Win32 error code associated with this exception. This
|
||||
/// field is read-only.</para>
|
||||
/// </devdoc>
|
||||
public int NativeErrorCode
|
||||
{
|
||||
get
|
||||
{
|
||||
return nativeErrorCode;
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetErrorMessage(int error)
|
||||
{
|
||||
//get the system error message...
|
||||
string errorMsg = "";
|
||||
StringBuilder sb = new StringBuilder(256);
|
||||
int result = SafeNativeMethods.FormatMessage(
|
||||
SafeNativeMethods.FORMAT_MESSAGE_IGNORE_INSERTS |
|
||||
SafeNativeMethods.FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
SafeNativeMethods.FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
||||
IntPtr.Zero, (uint)error, 0, sb, sb.Capacity + 1,
|
||||
null);
|
||||
if (result != 0)
|
||||
{
|
||||
int i = sb.Length;
|
||||
while (i > 0)
|
||||
{
|
||||
char ch = sb[i - 1];
|
||||
if (ch > 32 && ch != '.') break;
|
||||
i--;
|
||||
}
|
||||
errorMsg = sb.ToString(0, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
errorMsg = "Unknown error (0x" + Convert.ToString(error, 16) + ")";
|
||||
}
|
||||
|
||||
return errorMsg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
// NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
#if WEBSOCKETS
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Net.WebSockets;
|
||||
|
|
@ -22,7 +22,6 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Http.Features;
|
||||
using Microsoft.AspNet.Http.Internal;
|
||||
using Microsoft.AspNet.Testing.xunit;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -165,4 +164,5 @@ namespace Microsoft.AspNet.Server.WebListener
|
|||
return client;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -62,7 +62,7 @@ namespace Microsoft.Net.Http.Server
|
|||
Task<WebSocket> clientTask = SendWebSocketRequestAsync(ConvertToWebSocketAddress(address));
|
||||
|
||||
var context = await server.GetContextAsync();
|
||||
Assert.True(context.IsWebSocketRequest);
|
||||
Assert.True(context.IsWebSocketRequest());
|
||||
WebSocket serverWebSocket = await context.AcceptWebSocketAsync();
|
||||
WebSocket clientWebSocket = await clientTask;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"Microsoft.Net.Http.Server": "1.0.0-*",
|
||||
"Microsoft.Net.WebSockets.Server": "1.0.0-*",
|
||||
"Microsoft.AspNet.Testing": "1.0.0-*",
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue