private static void OnReadCompleted(object sender, HttpListenerAsyncEventArgs eventArgs) { Debug.Assert(eventArgs != null, "'eventArgs' MUST NOT be NULL."); WebSocketHttpListenerDuplexStream thisPtr = eventArgs.CurrentStream; Debug.Assert(thisPtr != null, "'thisPtr' MUST NOT be NULL."); #if DEBUG Debug.Assert(Interlocked.Decrement(ref thisPtr._outstandingOperations._reads) >= 0, "'thisPtr.m_OutstandingOperations.m_Reads' MUST NOT be negative."); #endif if (NetEventSource.IsEnabled) { NetEventSource.Enter(thisPtr); } if (eventArgs.Exception != null) { thisPtr._readTaskCompletionSource.TrySetException(eventArgs.Exception); } else { thisPtr._readTaskCompletionSource.TrySetResult(eventArgs.BytesTransferred); } if (NetEventSource.IsEnabled) { NetEventSource.Exit(thisPtr); } }
private static void OnCancel(object state) { Debug.Assert(state != null, "'state' MUST NOT be NULL."); WebSocketHttpListenerDuplexStream thisPtr = state as WebSocketHttpListenerDuplexStream; Debug.Assert(thisPtr != null, "'thisPtr' MUST NOT be NULL."); if (NetEventSource.Log.IsEnabled()) { NetEventSource.Enter(state); } try { thisPtr._outputStream.SetClosedFlag(); thisPtr._context.Abort(); } catch { } thisPtr._readTaskCompletionSource?.TrySetCanceled(); thisPtr._writeTaskCompletionSource?.TrySetCanceled(); if (NetEventSource.Log.IsEnabled()) { NetEventSource.Exit(state); } }
// Method called to prepare for a native async http.sys call. // This method performs the tasks common to all http.sys operations. internal void StartOperationCommon(WebSocketHttpListenerDuplexStream currentStream, ThreadPoolBoundHandle boundHandle) { // Change status to "in-use". if (Interlocked.CompareExchange(ref _operating, InProgress, Free) != Free) { // If it was already "in-use" check if Dispose was called. if (_disposeCalled) { // Dispose was called - throw ObjectDisposed. throw new ObjectDisposedException(GetType().FullName); } Debug.Fail("Only one outstanding async operation is allowed per HttpListenerAsyncEventArgs instance."); // Only one at a time. throw new InvalidOperationException(); } // HttpSendResponseEntityBody can return ERROR_INVALID_PARAMETER if the InternalHigh field of the overlapped // is not IntPtr.Zero, so we have to reset this field because we are reusing the Overlapped. // When using the IAsyncResult based approach of HttpListenerResponseStream the Overlapped is reinitialized // for each operation by the CLR when returned from the OverlappedDataCache. InitializeOverlapped(boundHandle); _exception = null; _bytesTransferred = 0; }
public HttpListenerAsyncEventArgs(WebSocketBase webSocket, WebSocketHttpListenerDuplexStream stream) : base() { m_WebSocket = webSocket; m_CurrentStream = stream; InitializeOverlapped(); }
private static void OnReadCompleted(object sender, HttpListenerAsyncEventArgs eventArgs) { Contract.Assert(eventArgs != null, "'eventArgs' MUST NOT be NULL."); WebSocketHttpListenerDuplexStream thisPtr = eventArgs.CurrentStream; Contract.Assert(thisPtr != null, "'thisPtr' MUST NOT be NULL."); #if DEBUG Contract.Assert(Interlocked.Decrement(ref thisPtr.m_OutstandingOperations.m_Reads) >= 0, "'thisPtr.m_OutstandingOperations.m_Reads' MUST NOT be negative."); #endif if (WebSocketBase.LoggingEnabled) { Logging.Enter(Logging.WebSockets, thisPtr, Methods.OnReadCompleted, string.Empty); } if (eventArgs.Exception != null) { thisPtr.m_ReadTaskCompletionSource.TrySetException(eventArgs.Exception); } else { thisPtr.m_ReadTaskCompletionSource.TrySetResult(eventArgs.BytesTransferred); } if (WebSocketBase.LoggingEnabled) { Logging.Exit(Logging.WebSockets, thisPtr, Methods.OnReadCompleted, string.Empty); } }
private static void OnCancel(object?state) { Debug.Assert(state != null, "'state' MUST NOT be NULL."); WebSocketHttpListenerDuplexStream thisPtr = (state as WebSocketHttpListenerDuplexStream) !; Debug.Assert(thisPtr != null, "'thisPtr' MUST NOT be NULL."); try { thisPtr._outputStream.SetClosedFlag(); thisPtr._context.Abort(); } catch { } thisPtr._readTaskCompletionSource?.TrySetCanceled(); thisPtr._writeTaskCompletionSource?.TrySetCanceled(); }
private static void OnWriteCompleted(object?sender, HttpListenerAsyncEventArgs eventArgs) { Debug.Assert(eventArgs != null, "'eventArgs' MUST NOT be NULL."); WebSocketHttpListenerDuplexStream thisPtr = eventArgs.CurrentStream; Debug.Assert(thisPtr != null, "'thisPtr' MUST NOT be NULL."); #if DEBUG Debug.Assert(Interlocked.Decrement(ref thisPtr._outstandingOperations._writes) >= 0, "'thisPtr.m_OutstandingOperations.m_Writes' MUST NOT be negative."); #endif if (eventArgs.Exception != null) { thisPtr._writeTaskCompletionSource !.TrySetException(eventArgs.Exception); } else { thisPtr._writeTaskCompletionSource !.TrySetResult(); } }
private static void OnCancel(object state) { Contract.Assert(state != null, "'state' MUST NOT be NULL."); WebSocketHttpListenerDuplexStream thisPtr = state as WebSocketHttpListenerDuplexStream; Contract.Assert(thisPtr != null, "'thisPtr' MUST NOT be NULL."); if (WebSocketBase.LoggingEnabled) { Logging.Enter(Logging.WebSockets, state, Methods.OnCancel, string.Empty); } try { thisPtr.m_OutputStream.SetClosedFlag(); thisPtr.m_Context.Abort(); } catch { } TaskCompletionSource <int> readTaskCompletionSourceSnapshot = thisPtr.m_ReadTaskCompletionSource; if (readTaskCompletionSourceSnapshot != null) { readTaskCompletionSourceSnapshot.TrySetCanceled(); } TaskCompletionSource <object> writeTaskCompletionSourceSnapshot = thisPtr.m_WriteTaskCompletionSource; if (writeTaskCompletionSourceSnapshot != null) { writeTaskCompletionSourceSnapshot.TrySetCanceled(); } if (WebSocketBase.LoggingEnabled) { Logging.Exit(Logging.WebSockets, state, Methods.OnCancel, string.Empty); } }
public HttpListenerAsyncEventArgs(WebSocketBase webSocket, WebSocketHttpListenerDuplexStream stream) : base() { _webSocket = webSocket; _currentStream = stream; }
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); }
public HttpListenerAsyncEventArgs(WebSocketBase webSocket, WebSocketHttpListenerDuplexStream stream) : base() { _webSocket = webSocket; _currentStream = stream; }
// Method called to prepare for a native async http.sys call. // This method performs the tasks common to all http.sys operations. internal void StartOperationCommon(WebSocketHttpListenerDuplexStream currentStream, ThreadPoolBoundHandle boundHandle) { // Change status to "in-use". if (Interlocked.CompareExchange(ref _operating, InProgress, Free) != Free) { // If it was already "in-use" check if Dispose was called. if (_disposeCalled) { // Dispose was called - throw ObjectDisposed. throw new ObjectDisposedException(GetType().FullName); } Debug.Assert(false, "Only one outstanding async operation is allowed per HttpListenerAsyncEventArgs instance."); // Only one at a time. throw new InvalidOperationException(); } // HttpSendResponseEntityBody can return ERROR_INVALID_PARAMETER if the InternalHigh field of the overlapped // is not IntPtr.Zero, so we have to reset this field because we are reusing the Overlapped. // When using the IAsyncResult based approach of HttpListenerResponseStream the Overlapped is reinitialized // for each operation by the CLR when returned from the OverlappedDataCache. InitializeOverlapped(boundHandle); _exception = null; _bytesTransferred = 0; }
public HttpListenerAsyncEventArgs(WebSocketBase webSocket, WebSocketHttpListenerDuplexStream stream) : base() { m_WebSocket = webSocket; m_CurrentStream = stream; InitializeOverlapped(); }
public HttpListenerAsyncEventArgs(WebSocketBase webSocket, WebSocketHttpListenerDuplexStream stream) : base() { m_WebSocket = webSocket; m_CurrentStream = stream; m_AllocateOverlappedOnDemand = LocalAppContextSwitches.AllocateOverlappedOnDemand; if (!m_AllocateOverlappedOnDemand) { InitializeOverlapped(); } }