public override Task <int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { WebSocketHelpers.ValidateBuffer(buffer, offset, count); if (!m_InOpaqueMode) { return(base.ReadAsync(buffer, offset, count, cancellationToken)); } return(ReadAsyncCore(buffer, offset, count, cancellationToken, false)); }
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { WebSocketHelpers.ValidateBuffer(buffer, offset, count); if (!m_InOpaqueMode) { return(base.WriteAsync(buffer, offset, count, cancellationToken)); } if (WebSocketBase.LoggingEnabled) { Logging.Enter(Logging.WebSockets, this, Methods.WriteAsync, WebSocketHelpers.GetTraceMsgForParameters(offset, count, cancellationToken)); } bool completedAsynchronously = false; try { cancellationToken.ThrowIfCancellationRequested(); #if DEBUG // When using fast path only one outstanding read is permitted. By switching into opaque mode // via IWebSocketStream.SwitchToOpaqueMode (see more detailed comments in interface definition) // caller takes responsibility for enforcing this constraint. Contract.Assert(Interlocked.Increment(ref m_OutstandingOperations.m_Writes) == 1, "Only one outstanding write allowed at any given time."); #endif WebSocketHelpers.ThrowIfConnectionAborted(m_InnerStream, false); m_WriteTaskCompletionSource = new TaskCompletionSource <object>(); m_WriteEventArgs.BufferList = null; m_WriteEventArgs.SetBuffer(buffer, offset, count); completedAsynchronously = InnerSocket.SendAsync(m_WriteEventArgs); if (!completedAsynchronously) { if (m_WriteEventArgs.SocketError != SocketError.Success) { throw new SocketException(m_WriteEventArgs.SocketError); } return(Task.CompletedTask); } return(m_WriteTaskCompletionSource.Task); } finally { if (WebSocketBase.LoggingEnabled) { Logging.Exit(Logging.WebSockets, this, Methods.WriteAsync, completedAsynchronously); } } }
// This method is not thread safe. It must only be called after enforcing at most 1 outstanding send operation internal void PinSendBuffer(ArraySegment <byte> payload, out bool bufferHasBeenPinned) { bufferHasBeenPinned = false; WebSocketHelpers.ValidateBuffer(payload.Array, payload.Offset, payload.Count); int previousState = Interlocked.Exchange(ref m_SendBufferState, SendBufferState.SendPayloadSpecified); if (previousState != SendBufferState.None) { Contract.Assert(false, "'m_SendBufferState' MUST BE 'None' at this point."); // Indicates a violation in the API contract that could indicate // memory corruption because the pinned sendbuffer is shared between managed and native code throw new AccessViolationException(); } m_PinnedSendBuffer = payload; m_PinnedSendBufferHandle = GCHandle.Alloc(m_PinnedSendBuffer.Array, GCHandleType.Pinned); bufferHasBeenPinned = true; m_PinnedSendBufferStartAddress = Marshal.UnsafeAddrOfPinnedArrayElement(m_PinnedSendBuffer.Array, m_PinnedSendBuffer.Offset).ToInt64(); m_PinnedSendBufferEndAddress = m_PinnedSendBufferStartAddress + m_PinnedSendBuffer.Count; }
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { WebSocketHelpers.ValidateBuffer(buffer, offset, count); return(WriteAsyncCore(buffer, offset, count, cancellationToken)); }