protected override void WriteCore(byte[] buffer, int offset, int size, bool immediate, TimeSpan timeout) { // as per http://support.microsoft.com/default.aspx?scid=kb%3ben-us%3b201213 // we shouldn't write more than 64K synchronously to a socket const int maxSocketWrite = 64 * 1024; ConnectionUtilities.ValidateBufferBounds(buffer, offset, size); TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); try { int bytesToWrite = size; using (timeoutHelper.GetCancellationToken().Register(SendCancellationCallback, this)) { while (bytesToWrite > 0) { size = Math.Min(bytesToWrite, maxSocketWrite); _outputStream.Write(buffer, offset, size); if (immediate) { _outputStream.Flush(); } bytesToWrite -= size; offset += size; } } } catch (ObjectDisposedException objectDisposedException) { Exception exceptionToThrow = ConvertObjectDisposedException(objectDisposedException, TransferOperation.Write); if (ReferenceEquals(exceptionToThrow, objectDisposedException)) { throw; } else { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exceptionToThrow); } } catch (Exception exception) { if (RTSocketError.GetStatus(exception.HResult) != SocketErrorStatus.Unknown) { SocketException socketException = new SocketException(exception.HResult & 0x0000FFFF); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( ConvertSendException(socketException, timeoutHelper.RemainingTime())); } throw; } }
protected override int ReadCore(byte[] buffer, int offset, int size, TimeSpan timeout, bool closing) { int bytesRead = 0; TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); try { using (timeoutHelper.GetCancellationToken().Register(ReceiveCancellationCallback, this)) { bytesRead = _inputStream.Read(buffer, offset, size); } } catch (ObjectDisposedException objectDisposedException) { Exception exceptionToThrow = ConvertObjectDisposedException(objectDisposedException, TransferOperation.Read); if (ReferenceEquals(exceptionToThrow, objectDisposedException)) { throw; } else { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exceptionToThrow); } } catch (Exception exception) { if (RTSocketError.GetStatus(exception.HResult) != SocketErrorStatus.Unknown) { SocketException socketException = new SocketException(exception.HResult & 0x0000FFFF); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( ConvertReceiveException(socketException, timeoutHelper.RemainingTime())); } throw; } return bytesRead; }
internal override async Task OpenAsync(TimeSpan timeout) { TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); base.Open(timeoutHelper.RemainingTime()); OutWrapper<TokenImpersonationLevel> impersonationLevelWrapper = new OutWrapper<TokenImpersonationLevel>(); OutWrapper<bool> allowNtlmWrapper = new OutWrapper<bool>(); SecurityUtils.OpenTokenProviderIfRequired(_clientTokenProvider, timeoutHelper.RemainingTime()); _credential = await TransportSecurityHelpers.GetSspiCredentialAsync( _clientTokenProvider, impersonationLevelWrapper, allowNtlmWrapper, timeoutHelper.GetCancellationToken()); _impersonationLevel = impersonationLevelWrapper.Value; _allowNtlm = allowNtlmWrapper; return; }
protected override void ShutdownCore(TimeSpan timeout) { try { // All the steps of a socket shutdown are not possible with StreamSocket. As part of a socket shutdown // any pending data to write is given the chance to be sent so we'll attempt that. var toh = new TimeoutHelper(timeout); _outputStream.FlushAsync(toh.GetCancellationToken()).GetAwaiter().GetResult(); } catch (ObjectDisposedException objectDisposedException) { Exception exceptionToThrow = ConvertObjectDisposedException(objectDisposedException, TransferOperation.Undefined); if (ReferenceEquals(exceptionToThrow, objectDisposedException)) { throw; } else { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exceptionToThrow); } } catch (Exception exception) { if (RTSocketError.GetStatus(exception.HResult) != SocketErrorStatus.Unknown) { SocketException socketException = new SocketException(exception.HResult & 0x0000FFFF); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( ConvertSendException(socketException, TimeSpan.MaxValue)); } throw; } }
protected override void OnSendCore(Message message, TimeSpan timeout) { Fx.Assert(message != null, "message should not be null."); TimeoutHelper helper = new TimeoutHelper(timeout); WebSocketMessageType outgoingMessageType = GetWebSocketMessageType(message); if (IsStreamedOutput) { WebSocketStream webSocketStream = new WebSocketStream(WebSocket, outgoingMessageType, ((IDefaultCommunicationTimeouts)this).CloseTimeout); TimeoutStream timeoutStream = new TimeoutStream(webSocketStream, timeout); MessageEncoder.WriteMessage(message, timeoutStream); webSocketStream.WriteEndOfMessage(); } else { ArraySegment<byte> messageData = EncodeMessage(message); bool success = false; try { if (TD.WebSocketAsyncWriteStartIsEnabled()) { TD.WebSocketAsyncWriteStart( WebSocket.GetHashCode(), messageData.Count, RemoteAddress != null ? RemoteAddress.ToString() : string.Empty); } Task task = WebSocket.SendAsync(messageData, outgoingMessageType, true, helper.GetCancellationToken()); task.Wait(helper.RemainingTime(), WebSocketHelper.ThrowCorrectException, WebSocketHelper.SendOperation); if (TD.WebSocketAsyncWriteStopIsEnabled()) { TD.WebSocketAsyncWriteStop(_webSocket.GetHashCode()); } success = true; } finally { try { BufferManager.ReturnBuffer(messageData.Array); } catch (Exception ex) { if (Fx.IsFatal(ex) || success) { throw; } FxTrace.Exception.TraceUnhandledException(ex); } } } }
// TODO: Make TimeoutHelper disposeable which disposes it's cancellation token source protected override AsyncCompletionResult BeginCloseOutput(TimeSpan timeout, Action<object> callback, object state) { Fx.Assert(callback != null, "callback should not be null."); var helper = new TimeoutHelper(timeout); Task task = CloseOutputAsync(helper.GetCancellationToken()); Fx.Assert(_pendingWritingMessageException == null, "'pendingWritingMessageException' MUST be NULL at this point."); if (task.IsCompleted) { _pendingWritingMessageException = WebSocketHelper.CreateExceptionOnTaskFailure(task, timeout, WebSocketHelper.CloseOperation); return AsyncCompletionResult.Completed; } HandleCloseOutputAsyncCompletion(task, timeout, callback, state); return AsyncCompletionResult.Queued; }
protected override AsyncCompletionResult StartWritingBufferedMessage(Message message, ArraySegment<byte> messageData, bool allowOutputBatching, TimeSpan timeout, Action<object> callback, object state) { Contract.Assert(callback != null, "callback should not be null."); ConnectionUtilities.ValidateBufferBounds(messageData); TimeoutHelper helper = new TimeoutHelper(timeout); WebSocketMessageType outgoingMessageType = GetWebSocketMessageType(message); if (TD.WebSocketAsyncWriteStartIsEnabled()) { TD.WebSocketAsyncWriteStart( WebSocket.GetHashCode(), messageData.Count, RemoteAddress != null ? RemoteAddress.ToString() : string.Empty); } Task task = WebSocket.SendAsync(messageData, outgoingMessageType, true, helper.GetCancellationToken()); Contract.Assert(_pendingWritingMessageException == null, "'pendingWritingMessageException' MUST be NULL at this point."); if (task.IsCompleted) { if (TD.WebSocketAsyncWriteStopIsEnabled()) { TD.WebSocketAsyncWriteStop(WebSocket.GetHashCode()); } _pendingWritingMessageException = WebSocketHelper.CreateExceptionOnTaskFailure(task, timeout, WebSocketHelper.SendOperation); return AsyncCompletionResult.Completed; } HandleSendAsyncCompletion(task, timeout, callback, state); return AsyncCompletionResult.Queued; }
void Cleanup() { 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 var closeTimeoutHelper = new TimeoutHelper(_closeTimeout); do { Task<WebSocketReceiveResult> receiveTask = _webSocket.ReceiveAsync(new ArraySegment<byte>(_initialReadBuffer.Array), closeTimeoutHelper.GetCancellationToken()); receiveTask.Wait(closeTimeoutHelper.RemainingTime(), WebSocketHelper.ThrowCorrectException, WebSocketHelper.ReceiveOperation); _endofMessageReceived = receiveTask.GetAwaiter().GetResult().EndOfMessage; } 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, _closeTimeout, 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) { WriteEndOfMessage(); } } }
public void WriteEndOfMessage() { if (TD.WebSocketAsyncWriteStartIsEnabled()) { TD.WebSocketAsyncWriteStart( _webSocket.GetHashCode(), 0, string.Empty); } var timeoutHelper = new TimeoutHelper(_closeTimeout); if (Interlocked.CompareExchange(ref _endOfMessageWritten, WebSocketHelper.OperationFinished, WebSocketHelper.OperationNotStarted) == WebSocketHelper.OperationNotStarted) { Task task = _webSocket.SendAsync(new ArraySegment<byte>(Array.Empty<byte>(), 0, 0), _outgoingMessageType, true, timeoutHelper.GetCancellationToken()); task.Wait(timeoutHelper.RemainingTime(), WebSocketHelper.ThrowCorrectException, WebSocketHelper.SendOperation); } if (TD.WebSocketAsyncWriteStopIsEnabled()) { TD.WebSocketAsyncWriteStop(_webSocket.GetHashCode()); } }