The Labs \ Source Viewer \ SSCLI \ System.Net \ SocketAddress

  1. //------------------------------------------------------------------------------
  2. // <copyright file="SocketAddress.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.Net
  16. {
  17.    
  18.     using System;
  19.     using System.Runtime.InteropServices;
  20.     using System.Net.Sockets;
  21.     using System.Text;
  22.     using System.Globalization;
  23.    
  24.     // a little perf app measured these times when comparing the internal
  25.     // buffer implemented as a managed byte[] or unmanaged memory IntPtr
  26.     // that's why we use byte[]
  27.     // byte[] total ms:19656
  28.     // IntPtr total ms:25671
  29.    
  30.     /// <devdoc>
  31.     /// <para>
  32.     /// This class is used when subclassing EndPoint, and provides indication
  33.     /// on how to format the memeory buffers that winsock uses for network addresses.
  34.     /// </para>
  35.     /// </devdoc>
  36.     public class SocketAddress
  37.     {
  38.        
  39.         internal const int IPv6AddressSize = 28;
  40.         internal const int IPv4AddressSize = 16;
  41.        
  42.         internal int m_Size;
  43.         internal byte[] m_Buffer;
  44.        
  45.         private const int WriteableOffset = 2;
  46.         private const int MaxSize = 32;
  47.         // IrDA requires 32 bytes
  48.         private bool m_changed = true;
  49.         private int m_hash;
  50.        
  51.         //
  52.         // Address Family
  53.         //
  54.         /// <devdoc>
  55.         /// <para>[To be supplied.]</para>
  56.         /// </devdoc>
  57.         public AddressFamily Family {
  58.             get {
  59.                 int family;
  60.                 #if BIGENDIAN
  61.                 family = ((int)m_Buffer[0] << 8) | m_Buffer[1];
  62.                 #else
  63.                 family = m_Buffer[0] | ((int)m_Buffer[1] << 8);
  64.                 #endif
  65.                 return (AddressFamily)family;
  66.             }
  67.         }
  68.         //
  69.         // Size of this SocketAddress
  70.         //
  71.         /// <devdoc>
  72.         /// <para>[To be supplied.]</para>
  73.         /// </devdoc>
  74.         public int Size {
  75.             get { return m_Size; }
  76.         }
  77.        
  78.         //
  79.         // access to unmanaged serialized data. this doesn't
  80.         // allow access to the first 2 bytes of unmanaged memory
  81.         // that are supposed to contain the address family which
  82.         // is readonly.
  83.         //
  84.         //
  85.         /// <devdoc>
  86.         /// <para>[To be supplied.]</para>
  87.         /// </devdoc>
  88.         public byte this[int offset]
  89.         {
  90.             get {
  91.                 //
  92.                 // access
  93.                 //
  94.                 if (offset < 0 || offset >= Size) {
  95.                     throw new IndexOutOfRangeException();
  96.                 }
  97.                 return m_Buffer[offset];
  98.             }
  99.             set {
  100.                 if (offset < 0 || offset >= Size) {
  101.                     throw new IndexOutOfRangeException();
  102.                 }
  103.                 if (m_Buffer[offset] != value) {
  104.                     m_changed = true;
  105.                 }
  106.                 m_Buffer[offset] = value;
  107.             }
  108.         }
  109.        
  110.         /// <devdoc>
  111.         /// <para>[To be supplied.]</para>
  112.         /// </devdoc>
  113.         public SocketAddress(AddressFamily family) : this(family, MaxSize)
  114.         {
  115.         }
  116.        
  117.         /// <devdoc>
  118.         /// <para>[To be supplied.]</para>
  119.         /// </devdoc>
  120.         public SocketAddress(AddressFamily family, int size)
  121.         {
  122.             if (size < WriteableOffset) {
  123.                 //
  124.                 // it doesn't make sense to create a socket address with less tha
  125.                 // 2 bytes, that's where we store the address family.
  126.                 //
  127.                 throw new ArgumentOutOfRangeException("size");
  128.             }
  129.             m_Size = size;
  130.             m_Buffer = new byte[(size / IntPtr.Size + 2) * IntPtr.Size];
  131.             //sizeof DWORD
  132.             #if BIGENDIAN
  133.             m_Buffer[0] = unchecked((byte)((int)family >> 8));
  134.             m_Buffer[1] = unchecked((byte)((int)family));
  135.             #else
  136.             m_Buffer[0] = unchecked((byte)((int)family));
  137.             m_Buffer[1] = unchecked((byte)((int)family >> 8));
  138.             #endif
  139.         }
  140.         //
  141.         // For ReceiveFrom we need to pin address size, using reserved m_Buffer space
  142.         //
  143.         internal void CopyAddressSizeIntoBuffer()
  144.         {
  145.             m_Buffer[m_Buffer.Length - IntPtr.Size] = unchecked((byte)(m_Size));
  146.             m_Buffer[m_Buffer.Length - IntPtr.Size + 1] = unchecked((byte)(m_Size >> 8));
  147.             m_Buffer[m_Buffer.Length - IntPtr.Size + 2] = unchecked((byte)(m_Size >> 16));
  148.             m_Buffer[m_Buffer.Length - IntPtr.Size + 3] = unchecked((byte)(m_Size >> 24));
  149.         }
  150.         //
  151.         // Can be called after the above method did work
  152.         //
  153.         internal int GetAddressSizeOffset()
  154.         {
  155.             return m_Buffer.Length - IntPtr.Size;
  156.         }
  157.         //
  158.         //
  159.         // For ReceiveFrom we need to update the address size upon IO return
  160.         //
  161.         unsafe internal void SetSize(IntPtr ptr)
  162.         {
  163.             // Apparently it must be less or equal the original value since ReceiveFrom cannot reallocate the address buffer
  164.             m_Size = *(int*)ptr;
  165.         }
  166.         public override bool Equals(object comparand)
  167.         {
  168.             SocketAddress castedComparand = comparand as SocketAddress;
  169.             if (castedComparand == null || this.Size != castedComparand.Size) {
  170.                 return false;
  171.             }
  172.             for (int i = 0; i < this.Size; i++) {
  173.                 if (this[i] != castedComparand[i]) {
  174.                     return false;
  175.                 }
  176.             }
  177.             return true;
  178.         }
  179.        
  180.         public override int GetHashCode()
  181.         {
  182.             if (m_changed) {
  183.                 m_changed = false;
  184.                 m_hash = 0;
  185.                
  186.                 int i;
  187.                 int size = Size & ~3;
  188.                
  189.                 for (i = 0; i < size; i += 4) {
  190.                     m_hash ^= (int)m_Buffer[i] | ((int)m_Buffer[i + 1] << 8) | ((int)m_Buffer[i + 2] << 16) | ((int)m_Buffer[i + 3] << 24);
  191.                 }
  192.                 if ((Size & 3) != 0) {
  193.                    
  194.                     int remnant = 0;
  195.                     int shift = 0;
  196.                    
  197.                     for (; i < Size; ++i) {
  198.                         remnant |= ((int)m_Buffer[i]) << shift;
  199.                         shift += 8;
  200.                     }
  201.                     m_hash ^= remnant;
  202.                 }
  203.             }
  204.             return m_hash;
  205.         }
  206.        
  207.         public override string ToString()
  208.         {
  209.             StringBuilder bytes = new StringBuilder();
  210.             for (int i = WriteableOffset; i < this.Size; i++) {
  211.                 if (i > WriteableOffset) {
  212.                     bytes.Append(",");
  213.                 }
  214.                 bytes.Append(this[i].ToString(NumberFormatInfo.InvariantInfo));
  215.             }
  216.             return Family.ToString() + ":" + Size.ToString(NumberFormatInfo.InvariantInfo) + ":{" + bytes.ToString() + "}";
  217.         }
  218.        
  219.     }
  220.     // class SocketAddress
  221.    
  222. }
  223. // namespace System.Net

Developer Fusion