Skip to content

Commit 1c7b419

Browse files
committed
Avoid some defensive copies on readonly structs in System.Net.Quic
1 parent 92b9dca commit 1c7b419

File tree

4 files changed

+11
-9
lines changed

4 files changed

+11
-9
lines changed

src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicConfiguration.Cache.cs

+8-7
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Collections.ObjectModel;
88
using System.Security.Authentication;
99
using System.Net.Security;
10+
using System.Runtime.InteropServices;
1011
using System.Security.Cryptography.X509Certificates;
1112
using System.Threading;
1213
using Microsoft.Quic;
@@ -39,13 +40,13 @@ private static bool GetConfigurationCacheEnabled()
3940

4041
private static readonly ConcurrentDictionary<CacheKey, MsQuicConfigurationSafeHandle> s_configurationCache = new();
4142

42-
private readonly struct CacheKey : IEquatable<CacheKey>
43+
private struct CacheKey : IEquatable<CacheKey>
4344
{
44-
public readonly List<byte[]> CertificateThumbprints;
45-
public readonly QUIC_CREDENTIAL_FLAGS Flags;
46-
public readonly QUIC_SETTINGS Settings;
47-
public readonly List<SslApplicationProtocol> ApplicationProtocols;
48-
public readonly QUIC_ALLOWED_CIPHER_SUITE_FLAGS AllowedCipherSuites;
45+
private readonly List<byte[]> CertificateThumbprints;
46+
private readonly QUIC_CREDENTIAL_FLAGS Flags;
47+
private QUIC_SETTINGS Settings; // not readonly to be able to compare using MemoryMarshal
48+
private readonly List<SslApplicationProtocol> ApplicationProtocols;
49+
private readonly QUIC_ALLOWED_CIPHER_SUITE_FLAGS AllowedCipherSuites;
4950

5051
public CacheKey(QUIC_SETTINGS settings, QUIC_CREDENTIAL_FLAGS flags, X509Certificate? certificate, ReadOnlyCollection<X509Certificate2>? intermediates, List<SslApplicationProtocol> alpnProtocols, QUIC_ALLOWED_CIPHER_SUITE_FLAGS allowedCipherSuites)
5152
{
@@ -98,7 +99,7 @@ public bool Equals(CacheKey other)
9899

99100
return
100101
Flags == other.Flags &&
101-
Settings.Equals(other.Settings) &&
102+
MemoryMarshal.AsBytes(MemoryMarshal.CreateReadOnlySpan(ref Settings, 1)).SequenceEqual(MemoryMarshal.AsBytes(MemoryMarshal.CreateReadOnlySpan(ref other.Settings, 1))) &&
102103
AllowedCipherSuites == other.AllowedCipherSuites;
103104
}
104105

src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicSafeHandle.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ internal sealed class MsQuicContextSafeHandle : MsQuicSafeHandle
8888
/// Holds a weak reference to the managed instance.
8989
/// It allows delegating MsQuic events to the managed object while it still can be collected and finalized.
9090
/// </summary>
91-
private readonly GCHandle _context;
91+
private GCHandle _context;
9292

9393
/// <summary>
9494
/// Optional parent safe handle, used to increment/decrement reference count with the lifetime of this instance.

src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/ReceiveBuffers.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public int CopyFrom(ReadOnlySpan<QUIC_BUFFER> quicBuffers, int totalLength, bool
5252
int totalCopied = 0;
5353
for (int i = 0; i < quicBuffers.Length; ++i)
5454
{
55-
Span<byte> quicBuffer = quicBuffers[i].Span;
55+
ReadOnlySpan<byte> quicBuffer = quicBuffers[i].ReadOnlySpan;
5656
if (totalLength < quicBuffer.Length)
5757
{
5858
quicBuffer = quicBuffer.Slice(0, totalLength);

src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/msquic.cs

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ namespace Microsoft.Quic
2121
internal unsafe partial struct QUIC_BUFFER
2222
{
2323
public Span<byte> Span => new(Buffer, (int)Length);
24+
public readonly ReadOnlySpan<byte> ReadOnlySpan => new(Buffer, (int)Length);
2425
}
2526

2627
internal partial class MsQuic

0 commit comments

Comments
 (0)