private static async Task <HttpListenerWebSocketContext> AcceptWebSocketAsyncCore(HttpListenerContext context,
string subProtocol,
int receiveBufferSize,
TimeSpan keepAliveInterval,
ArraySegment <byte> internalBuffer)
{
HttpListenerWebSocketContext webSocketContext = null;
if (NetEventSource.IsEnabled)
{
NetEventSource.Enter(null, context);
}
try
{
// get property will create a new response if one doesn't exist.
HttpListenerResponse response = context.Response;
HttpListenerRequest request = context.Request;
ValidateWebSocketHeaders(context);
string secWebSocketVersion = request.Headers[HttpKnownHeaderNames.SecWebSocketVersion];
// Optional for non-browser client
string origin = request.Headers[HttpKnownHeaderNames.Origin];
List <string> secWebSocketProtocols = new List <string>();
string outgoingSecWebSocketProtocolString;
bool shouldSendSecWebSocketProtocolHeader =
ProcessWebSocketProtocolHeader(
request.Headers[HttpKnownHeaderNames.SecWebSocketProtocol],
subProtocol,
out outgoingSecWebSocketProtocolString);
if (shouldSendSecWebSocketProtocolHeader)
{
secWebSocketProtocols.Add(outgoingSecWebSocketProtocolString);
response.Headers.Add(HttpKnownHeaderNames.SecWebSocketProtocol,
outgoingSecWebSocketProtocolString);
}
// negotiate the websocket key return value
string secWebSocketKey = request.Headers[HttpKnownHeaderNames.SecWebSocketKey];
string secWebSocketAccept = HttpWebSocket.GetSecWebSocketAcceptString(secWebSocketKey);
response.Headers.Add(HttpKnownHeaderNames.Connection, HttpKnownHeaderNames.Upgrade);
response.Headers.Add(HttpKnownHeaderNames.Upgrade, WebSocketUpgradeToken);
response.Headers.Add(HttpKnownHeaderNames.SecWebSocketAccept, secWebSocketAccept);
response.StatusCode = (int)HttpStatusCode.SwitchingProtocols; // HTTP 101
response.ComputeCoreHeaders();
ulong hresult = SendWebSocketHeaders(response);
if (hresult != 0)
{
throw new WebSocketException((int)hresult,
SR.Format(SR.net_WebSockets_NativeSendResponseHeaders,
nameof(AcceptWebSocketAsync),
hresult));
}
if (NetEventSource.IsEnabled)
{
NetEventSource.Info(null, $"{HttpKnownHeaderNames.Origin} = {origin}");
NetEventSource.Info(null, $"{HttpKnownHeaderNames.SecWebSocketVersion} = {secWebSocketVersion}");
NetEventSource.Info(null, $"{HttpKnownHeaderNames.SecWebSocketKey} = {secWebSocketKey}");
NetEventSource.Info(null, $"{HttpKnownHeaderNames.SecWebSocketAccept} = {secWebSocketAccept}");
NetEventSource.Info(null, $"{HttpKnownHeaderNames.SecWebSocketProtocol} = {request.Headers[HttpKnownHeaderNames.SecWebSocketProtocol]}");
NetEventSource.Info(null, $"{HttpKnownHeaderNames.SecWebSocketProtocol} = {outgoingSecWebSocketProtocolString}");
}
await response.OutputStream.FlushAsync().SuppressContextFlow();
HttpResponseStream responseStream = response.OutputStream as HttpResponseStream;
Debug.Assert(responseStream != null, "'responseStream' MUST be castable to System.Net.HttpResponseStream.");
((HttpResponseStream)response.OutputStream).SwitchToOpaqueMode();
HttpRequestStream requestStream = new HttpRequestStream(context);
requestStream.SwitchToOpaqueMode();
WebSocketHttpListenerDuplexStream webSocketStream =
new WebSocketHttpListenerDuplexStream(requestStream, responseStream, context);
WebSocket webSocket = ServerWebSocket.Create(webSocketStream,
subProtocol,
receiveBufferSize,
keepAliveInterval,
internalBuffer);
webSocketContext = new HttpListenerWebSocketContext(
request.Url,
request.Headers,
request.Cookies,
context.User,
request.IsAuthenticated,
request.IsLocal,
request.IsSecureConnection,
origin,
secWebSocketProtocols.AsReadOnly(),
secWebSocketVersion,
secWebSocketKey,
webSocket);
if (NetEventSource.IsEnabled)
{
NetEventSource.Associate(context, webSocketContext);
NetEventSource.Associate(webSocketContext, webSocket);
}
}
catch (Exception ex)
{
if (NetEventSource.IsEnabled)
{
NetEventSource.Error(context, ex);
}
throw;
}
finally
{
if (NetEventSource.IsEnabled)
{
NetEventSource.Exit(context);
}
}
return(webSocketContext);
}