private async Task CleanupAsync(CancellationToken cancellationToken) { if (_isForRead) { if (Interlocked.CompareExchange(ref _messageSourceCleanState, WebSocketHelper.OperationFinished, WebSocketHelper.OperationNotStarted) == WebSocketHelper.OperationNotStarted) { Exception pendingException = null; try { if (!_endofMessageReceived && (_webSocket.State == WebSocketState.Open || _webSocket.State == WebSocketState.CloseSent)) { // Drain the reading stream do { try { WebSocketReceiveResult receiveResult = await _webSocket.ReceiveAsync(new ArraySegment <byte>(_initialReadBuffer.Array), cancellationToken); _endofMessageReceived = receiveResult.EndOfMessage; } catch (Exception ex) { if (Fx.IsFatal(ex)) { throw; } WebSocketHelper.ThrowCorrectException(ex, TimeoutHelper.GetOriginalTimeout(cancellationToken), WebSocketHelper.ReceiveOperation); } }while (!_endofMessageReceived && (_webSocket.State == WebSocketState.Open || _webSocket.State == WebSocketState.CloseSent)); } } catch (Exception ex) { if (Fx.IsFatal(ex)) { throw; } // Not throwing out this exception during stream cleanup. The exception // will be thrown out when we are trying to receive the next message using the same // WebSocket object. pendingException = WebSocketHelper.ConvertAndTraceException(ex, TimeoutHelper.GetOriginalTimeout(cancellationToken), WebSocketHelper.CloseOperation); } _bufferManager.ReturnBuffer(_initialReadBuffer.Array); Fx.Assert(_messageSource != null, "messageSource should not be null."); _messageSource.FinishUsingMessageStream(pendingException); } } else { if (Interlocked.CompareExchange(ref _endOfMessageWritten, WebSocketHelper.OperationFinished, WebSocketHelper.OperationNotStarted) == WebSocketHelper.OperationNotStarted) { await WriteEndOfMessageAsync(cancellationToken); } } }
private Task CloseOutputImplAsync(CancellationToken cancellationToken) { try { return(WebSocket.CloseOutputAsync(_webSocketCloseDetails.OutputCloseStatus, _webSocketCloseDetails.OutputCloseStatusDescription, cancellationToken)); } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } throw WebSocketHelper.ConvertAndTraceException(e); } }
private async void StartNextReceiveAsync() { Fx.Assert(_receiveTask == null || _receiveTask.Task.IsCompleted, "this.receiveTask is not completed."); _receiveTask = new TaskCompletionSource <object>(); int currentState = Interlocked.CompareExchange(ref _asyncReceiveState, AsyncReceiveState.Started, AsyncReceiveState.Finished); Fx.Assert(currentState == AsyncReceiveState.Finished, "currentState is not AsyncReceiveState.Finished: " + currentState); if (currentState != AsyncReceiveState.Finished) { throw Fx.Exception.AsError(new InvalidOperationException()); } try { if (_useStreaming) { if (_streamWaitTask != null) { //// Wait until the previous stream message finished. await _streamWaitTask.Task.ConfigureAwait(false); } _streamWaitTask = new TaskCompletionSource <object>(); } if (_pendingException == null) { if (!_useStreaming) { await ReadBufferedMessageAsync().ConfigureAwait(false); } else { byte[] buffer = _bufferManager.TakeBuffer(_receiveBufferSize); bool success = false; try { //if (TD.WebSocketAsyncReadStartIsEnabled()) //{ // TD.WebSocketAsyncReadStart(this.webSocket.GetHashCode()); //} try { Task <WebSocketReceiveResult> receiveTask = _webSocket.ReceiveAsync( new ArraySegment <byte>(buffer, 0, _receiveBufferSize), CancellationToken.None); await receiveTask.ConfigureAwait(false); WebSocketReceiveResult result = receiveTask.Result; CheckCloseStatus(result); _pendingMessage = await PrepareMessageAsync(result, buffer, result.Count); //if (TD.WebSocketAsyncReadStopIsEnabled()) //{ // TD.WebSocketAsyncReadStop( // this.webSocket.GetHashCode(), // result.Count, // TraceUtility.GetRemoteEndpointAddressPort(this.remoteEndpointMessageProperty)); //} } catch (AggregateException ex) { WebSocketHelper.ThrowCorrectException(ex, _asyncReceiveTimeout, WebSocketHelper.ReceiveOperation); } success = true; } catch (Exception ex) { if (Fx.IsFatal(ex)) { throw; } _pendingException = WebSocketHelper.ConvertAndTraceException(ex, _asyncReceiveTimeout, WebSocketHelper.ReceiveOperation); } finally { if (!success) { _bufferManager.ReturnBuffer(buffer); } } } } } finally { if (Interlocked.CompareExchange(ref _asyncReceiveState, AsyncReceiveState.Finished, AsyncReceiveState.Started) == AsyncReceiveState.Started) { _receiveTask.SetResult(null); } } }
private async Task ReadBufferedMessageAsync() { byte[] internalBuffer = null; try { internalBuffer = _bufferManager.TakeBuffer(_receiveBufferSize); int receivedByteCount = 0; bool endOfMessage = false; WebSocketReceiveResult result = null; do { try { //if (TD.WebSocketAsyncReadStartIsEnabled()) //{ // TD.WebSocketAsyncReadStart(this.webSocket.GetHashCode()); //} Task <WebSocketReceiveResult> receiveTask = _webSocket.ReceiveAsync( new ArraySegment <byte>(internalBuffer, receivedByteCount, internalBuffer.Length - receivedByteCount), CancellationToken.None); await receiveTask.ConfigureAwait(false); result = receiveTask.Result; CheckCloseStatus(result); endOfMessage = result.EndOfMessage; receivedByteCount += result.Count; if (receivedByteCount >= internalBuffer.Length && !result.EndOfMessage) { if (internalBuffer.Length >= _maxBufferSize) { _pendingException = Fx.Exception.AsError(new QuotaExceededException(SR.Format(SR.MaxReceivedMessageSizeExceeded, _maxBufferSize))); return; } int newSize = (int)Math.Min(((double)internalBuffer.Length) * 2, _maxBufferSize); Fx.Assert(newSize > 0, "buffer size should be larger than zero."); byte[] newBuffer = _bufferManager.TakeBuffer(newSize); Buffer.BlockCopy(internalBuffer, 0, newBuffer, 0, receivedByteCount); _bufferManager.ReturnBuffer(internalBuffer); internalBuffer = newBuffer; } //if (TD.WebSocketAsyncReadStopIsEnabled()) //{ // TD.WebSocketAsyncReadStop( // this.webSocket.GetHashCode(), // receivedByteCount, // TraceUtility.GetRemoteEndpointAddressPort(this.RemoteEndpointMessageProperty)); //} } catch (AggregateException ex) { WebSocketHelper.ThrowCorrectException(ex, TimeSpan.MaxValue, WebSocketHelper.ReceiveOperation); } }while (!endOfMessage && !_closureReceived); byte[] buffer = null; bool success = false; try { buffer = _bufferManager.TakeBuffer(receivedByteCount); Buffer.BlockCopy(internalBuffer, 0, buffer, 0, receivedByteCount); Fx.Assert(result != null, "Result should not be null"); _pendingMessage = await PrepareMessageAsync(result, buffer, receivedByteCount); success = true; } finally { if (buffer != null && (!success || _pendingMessage == null)) { _bufferManager.ReturnBuffer(buffer); } } } catch (Exception ex) { if (Fx.IsFatal(ex)) { throw; } _pendingException = WebSocketHelper.ConvertAndTraceException(ex, TimeSpan.MaxValue, WebSocketHelper.ReceiveOperation); } finally { if (internalBuffer != null) { _bufferManager.ReturnBuffer(internalBuffer); } } }