< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 112
Coverable lines: 112
Total lines: 204
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 24
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.cctor()100%110%
GetMaximumAddressSize(...)0%660%
.ctor(...)100%110%
.ctor(...)100%110%
.ctor(...)0%440%
.ctor(...)100%110%
Equals(...)0%220%
Equals(...)0%220%
GetHashCode()100%110%
ToString()0%660%

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/Common/src/System/Net/SocketAddress.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Diagnostics;
 5using System.Net.Sockets;
 6
 7namespace System.Net
 8{
 9    // This class is used when subclassing EndPoint, and provides indication
 10    // on how to format the memory buffers that the platform uses for network addresses.
 11    public class SocketAddress : IEquatable<SocketAddress>
 12    {
 13#pragma warning disable CA1802 // these could be const on Windows but need to be static readonly for Unix
 014        internal static readonly int IPv6AddressSize = SocketAddressPal.IPv6AddressSize;
 015        internal static readonly int IPv4AddressSize = SocketAddressPal.IPv4AddressSize;
 016        internal static readonly int UdsAddressSize = SocketAddressPal.UdsAddressSize;
 017        internal static readonly int MaxAddressSize = SocketAddressPal.MaxAddressSize;
 18#pragma warning restore CA1802
 19
 20        private int _size;
 21        private byte[] _buffer;
 22
 23        private const int MinSize = 2;
 24        private const int DataOffset = 2;
 25
 26        public AddressFamily Family
 27        {
 28            get
 029            {
 030                return SocketAddressPal.GetAddressFamily(_buffer);
 031            }
 32        }
 33
 34        public int Size
 35        {
 36            get
 037            {
 038                return _size;
 039            }
 40            set
 041            {
 042                ArgumentOutOfRangeException.ThrowIfGreaterThan(value, _buffer.Length);
 043                ArgumentOutOfRangeException.ThrowIfLessThan(value, 0);
 044                _size = value;
 045            }
 46        }
 47
 48        // Access to unmanaged serialized data. This doesn't
 49        // allow access to the first 2 bytes of unmanaged memory
 50        // that are supposed to contain the address family which
 51        // is readonly.
 52        public byte this[int offset]
 53        {
 54            get
 055            {
 056                if ((uint)offset >= (uint)Size)
 057                {
 058                    throw new IndexOutOfRangeException();
 59                }
 060                return _buffer[offset];
 061            }
 62            set
 063            {
 064                if ((uint)offset >= (uint)Size)
 065                {
 066                    throw new IndexOutOfRangeException();
 67                }
 068                _buffer[offset] = value;
 069            }
 70        }
 71
 072        public static int GetMaximumAddressSize(AddressFamily addressFamily) => addressFamily switch
 073        {
 074            AddressFamily.InterNetwork => IPv4AddressSize,
 075            AddressFamily.InterNetworkV6 => IPv6AddressSize,
 076            AddressFamily.Unix => UdsAddressSize,
 077            _ => MaxAddressSize
 078        };
 79
 080        public SocketAddress(AddressFamily family) : this(family, GetMaximumAddressSize(family))
 081        {
 082        }
 83
 084        public SocketAddress(AddressFamily family, int size)
 085        {
 086            ArgumentOutOfRangeException.ThrowIfLessThan(size, MinSize);
 87
 088            _size = size;
 089            _buffer = new byte[size];
 090            _buffer[0] = (byte)_size;
 91
 092            SocketAddressPal.SetAddressFamily(_buffer, family);
 093        }
 94
 95        internal unsafe SocketAddress(IPAddress ipAddress)
 096            : this(ipAddress.AddressFamily,
 097                ((ipAddress.AddressFamily == AddressFamily.InterNetwork) ? IPv4AddressSize : IPv6AddressSize))
 098        {
 99
 100            // No Port.
 0101            SocketAddressPal.SetPort(_buffer, 0);
 102
 0103            if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
 0104            {
 0105                Span<byte> addressBytes = stackalloc byte[IPAddressParserStatics.IPv6AddressBytes];
 0106                ipAddress.TryWriteBytes(addressBytes, out int bytesWritten);
 0107                Debug.Assert(bytesWritten == IPAddressParserStatics.IPv6AddressBytes);
 108
 0109                SocketAddressPal.SetIPv6Address(_buffer, addressBytes, (uint)ipAddress.ScopeId);
 0110            }
 111            else
 0112            {
 113#pragma warning disable CS0618 // using Obsolete Address API because it's the more efficient option in this case
 0114                uint address = unchecked((uint)ipAddress.Address);
 115#pragma warning restore CS0618
 116
 0117                Debug.Assert(ipAddress.AddressFamily == AddressFamily.InterNetwork);
 0118                SocketAddressPal.SetIPv4Address(_buffer, address);
 0119            }
 0120        }
 121
 122        internal SocketAddress(IPAddress ipaddress, int port)
 0123            : this(ipaddress)
 0124        {
 0125            SocketAddressPal.SetPort(_buffer, unchecked((ushort)port));
 0126        }
 127
 128        /// <summary>This represents underlying memory that can be passed to native OS calls.</summary>
 129        /// <remarks>
 130        /// Content of the memory can be invalidated if <see cref="Size"/> is changed or if the SocketAddress is used in
 131        /// </remarks>
 132        public Memory<byte> Buffer
 133        {
 134            get
 0135            {
 0136                return new Memory<byte>(_buffer);
 0137            }
 138        }
 139
 140
 141        public override bool Equals(object? comparand) =>
 0142            comparand is SocketAddress other && Equals(other);
 143
 0144        public bool Equals(SocketAddress? comparand) => comparand != null && Buffer.Span.SequenceEqual(comparand.Buffer.
 145
 146        public override int GetHashCode()
 0147        {
 0148            HashCode hash = default;
 0149            hash.AddBytes(new ReadOnlySpan<byte>(_buffer, 0, _size));
 0150            return hash.ToHashCode();
 0151        }
 152
 153        public override unsafe string ToString()
 0154        {
 155            // Get the address family string.  In almost all cases, this should be a cached string
 156            // from the enum and won't actually allocate.
 0157            string familyString = Family.ToString();
 158
 159            // Determine the maximum length needed to format.
 0160            int maxLength =
 0161                checked(
 0162                    familyString.Length + // AddressFamily
 0163                    1 + // :
 0164                    10 + // Size (max length for a positive Int32)
 0165                    2 + // :{
 0166                    (Size - DataOffset) * 4 + // at most ','+3digits per byte
 0167                    1 // }
 0168                );
 169
 0170            Span<char> result = (uint)maxLength <= 256 ? // arbitrary limit that should be large enough for the vast maj
 0171                stackalloc char[256] :
 0172                new char[maxLength];
 173
 0174            familyString.CopyTo(result);
 0175            int length = familyString.Length;
 176
 0177            result[length++] = ':';
 178
 0179            bool formatted = Size.TryFormat(result.Slice(length), out int charsWritten);
 0180            Debug.Assert(formatted);
 0181            length += charsWritten;
 182
 0183            result[length++] = ':';
 0184            result[length++] = '{';
 185
 0186            byte[] buffer = _buffer;
 0187            for (int i = DataOffset; i < Size; i++)
 0188            {
 0189                if (i > DataOffset)
 0190                {
 0191                    result[length++] = ',';
 0192                }
 193
 0194                formatted = buffer[i].TryFormat(result.Slice(length), out charsWritten);
 0195                Debug.Assert(formatted);
 0196                length += charsWritten;
 0197            }
 198
 0199            result[length++] = '}';
 0200            return result.Slice(0, length).ToString();
 0201        }
 202    }
 203}
 204