private int _lockReadState;
private object _queuedReadStateRequest;
- /// <summary>Set as the _exception when the instance is disposed.</summary>
- private static readonly ExceptionDispatchInfo s_disposedSentinel = ExceptionDispatchInfo.Capture(new ObjectDisposedException(nameof(SslStream), (string)null));
-
- private void ThrowIfExceptional()
- {
- ExceptionDispatchInfo e = _exception;
- if (e != null)
- {
- // If the stored exception just indicates disposal, throw a new ODE rather than the stored one,
- // so as to not continually build onto the shared exception's stack.
- if (ReferenceEquals(e, s_disposedSentinel))
- {
- throw new ObjectDisposedException(nameof(SslStream));
- }
-
- // Throw the stored exception.
- e.Throw();
- }
- }
-
private void ValidateCreateContext(SslClientAuthenticationOptions sslClientAuthenticationOptions, RemoteCertValidationCallback remoteCallback, LocalCertSelectionCallback localCallback)
{
ThrowIfExceptional();
_context?.Close();
}
- private void CheckThrow(bool authSuccessCheck, bool shutdownCheck = false)
- {
- ThrowIfExceptional();
-
- if (authSuccessCheck && !IsAuthenticated)
- {
- throw new InvalidOperationException(SR.net_auth_noauth);
- }
-
- if (shutdownCheck && _shutdown)
- {
- throw new InvalidOperationException(SR.net_ssl_io_already_shutdown);
- }
- }
-
//
// This is to not depend on GC&SafeHandle class if the context is not needed anymore.
//
private SecurityStatusPal EncryptData(ReadOnlyMemory<byte> buffer, ref byte[] outBuffer, out int outSize)
{
- CheckThrow(true);
+ ThrowIfExceptionalOrNotAuthenticated();
return _context.Encrypt(buffer, ref outBuffer, out outSize);
}
private SecurityStatusPal DecryptData()
{
- CheckThrow(true);
+ ThrowIfExceptionalOrNotAuthenticated();
return PrivateDecryptData(_internalBuffer, ref _decryptedBytesOffset, ref _decryptedBytesCount);
}
//
private int CheckOldKeyDecryptedData(Memory<byte> buffer)
{
- CheckThrow(true);
+ ThrowIfExceptionalOrNotAuthenticated();
if (_queuedReadData != null)
{
// This is inefficient yet simple and should be a REALLY rare case.
try
{
- CheckThrow(false);
+ ThrowIfExceptional();
AsyncProtocolRequest asyncRequest = null;
if (lazyResult != null)
{
{
if (_lockWriteState != LockHandshake)
{
- CheckThrow(authSuccessCheck: true);
+ ThrowIfExceptionalOrNotAuthenticated();
return Task.CompletedTask;
}
if (_lockWriteState != LockHandshake)
{
// Handshake has completed before we grabbed the lock.
- CheckThrow(authSuccessCheck: true);
+ ThrowIfExceptionalOrNotAuthenticated();
return;
}
// Need to exit from lock before waiting.
lazyResult.InternalWaitForCompletion();
- CheckThrow(authSuccessCheck: true);
+ ThrowIfExceptionalOrNotAuthenticated();
return;
}
private async Task WriteAsyncInternal<TWriteAdapter>(TWriteAdapter writeAdapter, ReadOnlyMemory<byte> buffer)
where TWriteAdapter : struct, ISslWriteAdapter
{
- CheckThrow(authSuccessCheck: true, shutdownCheck: true);
+ ThrowIfExceptionalOrNotAuthenticatedOrShutdown();
if (buffer.Length == 0 && !SslStreamPal.CanEncryptEmptyMessage)
{
using System.Diagnostics;
using System.IO;
+using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Security.Authentication;
using System.Security.Authentication.ExtendedProtection;
public partial class SslStream : AuthenticatedStream
{
+ /// <summary>Set as the _exception when the instance is disposed.</summary>
+ private static readonly ExceptionDispatchInfo s_disposedSentinel = ExceptionDispatchInfo.Capture(new ObjectDisposedException(nameof(SslStream), (string)null));
+
private X509Certificate2 _remoteCertificate;
private bool _remoteCertificateExposed;
internal IAsyncResult BeginShutdown(AsyncCallback asyncCallback, object asyncState)
{
- CheckThrow(authSuccessCheck: true, shutdownCheck: true);
+ ThrowIfExceptionalOrNotAuthenticatedOrShutdown();
ProtocolToken message = _context.CreateShutdownToken();
return TaskToApm.Begin(InnerStream.WriteAsync(message.Payload, 0, message.Payload.Length), asyncCallback, asyncState);
internal void EndShutdown(IAsyncResult asyncResult)
{
- CheckThrow(authSuccessCheck: true, shutdownCheck: true);
+ ThrowIfExceptionalOrNotAuthenticatedOrShutdown();
TaskToApm.End(asyncResult);
_shutdown = true;
{
get
{
- CheckThrow(true);
+ ThrowIfExceptionalOrNotAuthenticated();
SslConnectionInfo info = _context.ConnectionInfo;
if (info == null)
{
{
get
{
- CheckThrow(true);
+ ThrowIfExceptionalOrNotAuthenticated();
return _context.IsServer ? _context.LocalServerCertificate : _context.LocalClientCertificate;
}
}
{
get
{
- CheckThrow(true);
+ ThrowIfExceptionalOrNotAuthenticated();
_remoteCertificateExposed = true;
return _remoteCertificate;
}
{
get
{
- CheckThrow(true);
+ ThrowIfExceptionalOrNotAuthenticated();
return _context.ConnectionInfo?.TlsCipherSuite ?? default(TlsCipherSuite);
}
}
{
get
{
- CheckThrow(true);
+ ThrowIfExceptionalOrNotAuthenticated();
SslConnectionInfo info = _context.ConnectionInfo;
if (info == null)
{
{
get
{
- CheckThrow(true);
+ ThrowIfExceptionalOrNotAuthenticated();
SslConnectionInfo info = _context.ConnectionInfo;
if (info == null)
{
{
get
{
- CheckThrow(true);
+ ThrowIfExceptionalOrNotAuthenticated();
SslConnectionInfo info = _context.ConnectionInfo;
if (info == null)
{
{
get
{
- CheckThrow(true);
+ ThrowIfExceptionalOrNotAuthenticated();
SslConnectionInfo info = _context.ConnectionInfo;
if (info == null)
{
{
get
{
- CheckThrow(true);
+ ThrowIfExceptionalOrNotAuthenticated();
SslConnectionInfo info = _context.ConnectionInfo;
if (info == null)
{
{
get
{
- CheckThrow(true);
+ ThrowIfExceptionalOrNotAuthenticated();
SslConnectionInfo info = _context.ConnectionInfo;
if (info == null)
{
public override int ReadByte()
{
- CheckThrow(true);
+ ThrowIfExceptionalOrNotAuthenticated();
if (Interlocked.Exchange(ref _nestedRead, 1) == 1)
{
throw new NotSupportedException(SR.Format(SR.net_io_invalidnestedcall, "ReadByte", "read"));
public override int Read(byte[] buffer, int offset, int count)
{
- CheckThrow(true);
+ ThrowIfExceptionalOrNotAuthenticated();
ValidateParameters(buffer, offset, count);
SslReadSync reader = new SslReadSync(this);
return ReadAsyncInternal(reader, new Memory<byte>(buffer, offset, count)).GetAwaiter().GetResult();
public override void Write(byte[] buffer, int offset, int count)
{
- CheckThrow(true);
+ ThrowIfExceptionalOrNotAuthenticated();
ValidateParameters(buffer, offset, count);
SslWriteSync writeAdapter = new SslWriteSync(this);
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState)
{
- CheckThrow(true);
+ ThrowIfExceptionalOrNotAuthenticated();
return TaskToApm.Begin(ReadAsync(buffer, offset, count, CancellationToken.None), asyncCallback, asyncState);
}
public override int EndRead(IAsyncResult asyncResult)
{
- CheckThrow(true);
+ ThrowIfExceptionalOrNotAuthenticated();
return TaskToApm.End<int>(asyncResult);
}
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState)
{
- CheckThrow(true);
+ ThrowIfExceptionalOrNotAuthenticated();
return TaskToApm.Begin(WriteAsync(buffer, offset, count, CancellationToken.None), asyncCallback, asyncState);
}
public override void EndWrite(IAsyncResult asyncResult)
{
- CheckThrow(true);
+ ThrowIfExceptionalOrNotAuthenticated();
TaskToApm.End(asyncResult);
}
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
- CheckThrow(true);
+ ThrowIfExceptionalOrNotAuthenticated();
ValidateParameters(buffer, offset, count);
return WriteAsync(new ReadOnlyMemory<byte>(buffer, offset, count), cancellationToken).AsTask();
}
public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken)
{
- CheckThrow(true);
+ ThrowIfExceptionalOrNotAuthenticated();
SslWriteAsync writeAdapter = new SslWriteAsync(this, cancellationToken);
return new ValueTask(WriteAsyncInternal(writeAdapter, buffer));
}
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
- CheckThrow(true);
+ ThrowIfExceptionalOrNotAuthenticated();
ValidateParameters(buffer, offset, count);
SslReadAsync read = new SslReadAsync(this, cancellationToken);
return ReadAsyncInternal(read, new Memory<byte>(buffer, offset, count)).AsTask();
public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
{
- CheckThrow(true);
+ ThrowIfExceptionalOrNotAuthenticated();
SslReadAsync read = new SslReadAsync(this, cancellationToken);
return ReadAsyncInternal(read, buffer);
}
+
+ private void ThrowIfExceptional()
+ {
+ ExceptionDispatchInfo e = _exception;
+ if (e != null)
+ {
+ ThrowExceptional(e);
+ }
+
+ // Local function to make the check method more inline friendly.
+ static void ThrowExceptional(ExceptionDispatchInfo e)
+ {
+ // If the stored exception just indicates disposal, throw a new ODE rather than the stored one,
+ // so as to not continually build onto the shared exception's stack.
+ if (ReferenceEquals(e, s_disposedSentinel))
+ {
+ throw new ObjectDisposedException(nameof(SslStream));
+ }
+
+ // Throw the stored exception.
+ e.Throw();
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private void ThrowIfExceptionalOrNotAuthenticated()
+ {
+ ThrowIfExceptional();
+
+ if (!IsAuthenticated)
+ {
+ ThrowNotAuthenticated();
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private void ThrowIfExceptionalOrNotAuthenticatedOrShutdown()
+ {
+ ThrowIfExceptional();
+
+ if (!IsAuthenticated)
+ {
+ ThrowNotAuthenticated();
+ }
+
+ if (_shutdown)
+ {
+ ThrowAlreadyShutdown();
+ }
+
+ // Local function to make the check method more inline friendly.
+ static void ThrowAlreadyShutdown()
+ {
+ throw new InvalidOperationException(SR.net_ssl_io_already_shutdown);
+ }
+ }
+
+ // Static non-returning throw method to make the check methods more inline friendly.
+ private static void ThrowNotAuthenticated()
+ {
+ throw new InvalidOperationException(SR.net_auth_noauth);
+ }
}
}