try
{
- Debug.Assert(!Monitor.IsEntered(_state));
+ Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
MsQuicApi.Api.SetCallbackHandlerDelegate(
_state.Handle,
s_connectionDelegate,
_state.StateGCHandle = GCHandle.Alloc(_state);
try
{
- Debug.Assert(!Monitor.IsEntered(_state));
+ Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
uint status = MsQuicApi.Api.ConnectionOpenDelegate(
MsQuicApi.Api.Registration,
s_connectionDelegate,
private static uint HandleEventPeerCertificateReceived(State state, ref ConnectionEvent connectionEvent)
{
- SslPolicyErrors sslPolicyErrors = SslPolicyErrors.None;
+ SslPolicyErrors sslPolicyErrors = SslPolicyErrors.None;
X509Chain? chain = null;
X509Certificate2? certificate = null;
X509Certificate2Collection? additionalCertificates = null;
internal override int GetRemoteAvailableUnidirectionalStreamCount()
{
- Debug.Assert(!Monitor.IsEntered(_state));
+ Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
return MsQuicParameterHelpers.GetUShortParam(MsQuicApi.Api, _state.Handle, QUIC_PARAM_LEVEL.CONNECTION, (uint)QUIC_PARAM_CONN.LOCAL_UNIDI_STREAM_COUNT);
}
internal override int GetRemoteAvailableBidirectionalStreamCount()
{
- Debug.Assert(!Monitor.IsEntered(_state));
+ Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
return MsQuicParameterHelpers.GetUShortParam(MsQuicApi.Api, _state.Handle, QUIC_PARAM_LEVEL.CONNECTION, (uint)QUIC_PARAM_CONN.LOCAL_BIDI_STREAM_COUNT);
}
SOCKADDR_INET address = MsQuicAddressHelpers.IPEndPointToINet((IPEndPoint)_remoteEndPoint);
unsafe
{
- Debug.Assert(!Monitor.IsEntered(_state));
+ Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
status = MsQuicApi.Api.SetParamDelegate(_state.Handle, QUIC_PARAM_LEVEL.CONNECTION, (uint)QUIC_PARAM_CONN.REMOTE_ADDRESS, (uint)sizeof(SOCKADDR_INET), (byte*)&address);
QuicExceptionHelpers.ThrowIfFailed(status, "Failed to connect to peer.");
}
SOCKADDR_INET quicAddress = MsQuicAddressHelpers.IPEndPointToINet(new IPEndPoint(address, port));
unsafe
{
- Debug.Assert(!Monitor.IsEntered(_state));
+ Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
status = MsQuicApi.Api.SetParamDelegate(_state.Handle, QUIC_PARAM_LEVEL.CONNECTION, (uint)QUIC_PARAM_CONN.REMOTE_ADDRESS, (uint)sizeof(SOCKADDR_INET), (byte*)&quicAddress);
QuicExceptionHelpers.ThrowIfFailed(status, "Failed to connect to peer.");
}
try
{
- Debug.Assert(!Monitor.IsEntered(_state));
+ Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
status = MsQuicApi.Api.ConnectionStartDelegate(
_state.Handle,
_configuration,
try
{
- Debug.Assert(!Monitor.IsEntered(_state));
+ Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
MsQuicApi.Api.ConnectionShutdownDelegate(
_state.Handle,
Flags,
if (_state.Handle != null && !_state.Handle.IsInvalid && !_state.Handle.IsClosed)
{
// Handle can be null if outbound constructor failed and we are called from finalizer.
- Debug.Assert(!Monitor.IsEntered(_state));
+ Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
MsQuicApi.Api.ConnectionShutdownDelegate(
_state.Handle,
QUIC_CONNECTION_SHUTDOWN_FLAGS.SILENT,
_stateHandle = GCHandle.Alloc(_state);
try
{
+ Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
uint status = MsQuicApi.Api.ListenerOpenDelegate(
MsQuicApi.Api.Registration,
s_listenerDelegate,
QuicBuffer[]? buffers = null;
try
{
+ Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
MsQuicAlpnHelper.Prepare(applicationProtocols, out handles, out buffers);
status = MsQuicApi.Api.ListenerStartDelegate(_state.Handle, (QuicBuffer*)Marshal.UnsafeAddrOfPinnedArrayElement(buffers, 0), (uint)applicationProtocols.Count, ref address);
}
QuicExceptionHelpers.ThrowIfFailed(status, "ListenerStart failed.");
+ Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
SOCKADDR_INET inetAddress = MsQuicParameterHelpers.GetINetParam(MsQuicApi.Api, _state.Handle, QUIC_PARAM_LEVEL.LISTENER, (uint)QUIC_PARAM_LISTENER.LOCAL_ADDRESS);
return MsQuicAddressHelpers.INetToIPEndPoint(ref inetAddress);
}
if (_state.Handle != null)
{
+ Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
MsQuicApi.Api.ListenerStopDelegate(_state.Handle);
}
}
connectionHandle = new SafeMsQuicConnectionHandle(evt->Data.NewConnection.Connection);
+ Debug.Assert(!Monitor.IsEntered(state), "!Monitor.IsEntered(state)");
uint status = MsQuicApi.Api.ConnectionSetConfigurationDelegate(connectionHandle, connectionConfiguration);
if (MsQuicStatusHelper.SuccessfulStatusCode(status))
{
_state.StateGCHandle = GCHandle.Alloc(_state);
try
{
+ Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
MsQuicApi.Api.SetCallbackHandlerDelegate(
_state.Handle,
s_streamDelegate,
try
{
+ Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
uint status = MsQuicApi.Api.StreamOpenDelegate(
connectionState.Handle,
flags,
QuicExceptionHelpers.ThrowIfFailed(status, "Failed to open stream to peer.");
+ Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
status = MsQuicApi.Api.StreamStartDelegate(_state.Handle, QUIC_STREAM_START_FLAGS.FAIL_BLOCKED);
QuicExceptionHelpers.ThrowIfFailed(status, "Could not start stream.");
}
get
{
ThrowIfDisposed();
- return _writeTimeout;
+ return _writeTimeout;
}
set
{
long abortError;
bool preCanceled = false;
+ int bytesRead = -1;
+ bool reenableReceive = false;
lock (_state)
{
initialReadState = _state.ReadState;
{
_state.ReadState = ReadState.None;
- int taken = CopyMsQuicBuffersToUserBuffer(_state.ReceiveQuicBuffers.AsSpan(0, _state.ReceiveQuicBuffersCount), destination.Span);
- ReceiveComplete(taken);
+ bytesRead = CopyMsQuicBuffersToUserBuffer(_state.ReceiveQuicBuffers.AsSpan(0, _state.ReceiveQuicBuffersCount), destination.Span);
- if (taken != _state.ReceiveQuicBuffersTotalBytes)
+ if (bytesRead != _state.ReceiveQuicBuffersTotalBytes)
{
// Need to re-enable receives because MsQuic will pause them when we don't consume the entire buffer.
- EnableReceive();
+ reenableReceive = true;
}
else if (_state.ReceiveIsFinal)
{
// This was a final message and we've consumed everything. We can complete the state without waiting for PEER_SEND_SHUTDOWN
_state.ReadState = ReadState.ReadsCompleted;
}
+ }
+ }
+
+ // methods below need to be called outside of the lock
+ if (bytesRead > -1)
+ {
+ ReceiveComplete(bytesRead);
- return new ValueTask<int>(taken);
+ if (reenableReceive)
+ {
+ EnableReceive();
}
+
+ return new ValueTask<int>(bytesRead);
}
// All success scenarios returned at this point. Failure scenarios below:
ex = new InvalidOperationException("Only one read is supported at a time.");
break;
case ReadState.Aborted:
- ex = preCanceled ? new OperationCanceledException(cancellationToken) :
+ ex = preCanceled ? new OperationCanceledException(cancellationToken) :
ThrowHelper.GetStreamAbortedException(abortError);
break;
case ReadState.ConnectionClosed:
private void StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS flags, long errorCode)
{
+ Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
uint status = MsQuicApi.Api.StreamShutdownDelegate(_state.Handle, flags, errorCode);
QuicExceptionHelpers.ThrowIfFailed(status, "StreamShutdown failed.");
}
{
// Handle race condition when stream can be closed handling SHUTDOWN_COMPLETE.
StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.GRACEFUL, errorCode: 0);
- } catch (ObjectDisposedException) { };
+ }
+ catch (ObjectDisposedException) { };
}
if (abortRead)
try
{
StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.ABORT_RECEIVE, 0xffffffff);
- } catch (ObjectDisposedException) { };
+ }
+ catch (ObjectDisposedException) { };
}
if (completeRead)
private void EnableReceive()
{
+ Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
uint status = MsQuicApi.Api.StreamReceiveSetEnabledDelegate(_state.Handle, enabled: true);
QuicExceptionHelpers.ThrowIfFailed(status, "StreamReceiveSetEnabled failed.");
}
_state.BufferArrays[0] = handle;
_state.SendBufferCount = 1;
+ Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
uint status = MsQuicApi.Api.StreamSendDelegate(
_state.Handle,
quicBuffers,
++count;
}
+ Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
uint status = MsQuicApi.Api.StreamSendDelegate(
_state.Handle,
quicBuffers,
_state.BufferArrays[i] = handle;
}
+ Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
uint status = MsQuicApi.Api.StreamSendDelegate(
_state.Handle,
quicBuffers,
private void ReceiveComplete(int bufferLength)
{
+ Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
uint status = MsQuicApi.Api.StreamReceiveCompleteDelegate(_state.Handle, (ulong)bufferLength);
QuicExceptionHelpers.ThrowIfFailed(status, "Could not complete receive call.");
}