PeerName.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / SystemNet / Net / PeerToPeer / PeerName.cs / 1 / PeerName.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 
namespace System.Net.PeerToPeer
{ 
 
    using System;
    using System.Globalization; 
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;
    using System.Text.RegularExpressions; 
    using System.Runtime.InteropServices;
    using System.Diagnostics; 
    using System.Runtime.Serialization; 
    using System.Security.Permissions;
    using Microsoft.Win32; 
    /// 
    /// The PeerName class represents the native PeerName construct.
    /// 
    [Serializable] 
    public class PeerName : ISerializable, IEquatable
    { 
        //=================================================== 
        //constants
        //=================================================== 
        private const int PEER_MAX_CLASSIFIER_LENGTH = 149;
        private const int SECURE_AUTHORITY_LENGTH = 40;
        private const int INSECURE_AUTHORITY_LENGTH = 1;
        private const int PEER_MAX_PEERNAME_LENGTH = SECURE_AUTHORITY_LENGTH + 1 + PEER_MAX_CLASSIFIER_LENGTH; 
        private const string PEERNAME_UNSECURED_AUTHORITY = "0";
 
        //==================================================== 
        //private member variables
        //=================================================== 
        private string m_PeerName;
        private string m_Authority;
        private string m_Classifier;
        private string m_PeerHostName; 

        // ==================================================== 
        //     Constructors 
        // ====================================================
 
        static PeerName()
        {
            //-------------------------------------------------
            //Check for the availability of the simpler PNRP APIs 
            //-------------------------------------------------
            if (!PeerToPeerOSHelper.SupportsP2P) 
            { 
                throw new PlatformNotSupportedException(SR.GetString(SR.P2P_NotAvailable));
            } 
        }

        /// 
        /// We use this constructor to create an PeerName 
        /// for internal implementation
        ///  
        private PeerName(string peerName, string authority, string classifier) { 
            m_PeerName = peerName;
            m_Classifier = classifier; 
            m_Authority = authority;
        }

        ///  
        /// This constructor is to create a peername from an
        /// arbitrary string. The Identity is not necessarily 
        /// the same as the current user 
        /// 
        /// string form of the peer name 
        /// 
        ///     1. We assume that the peername is already normalized according to the
        ///         Unicode rules
        ///     2. The PeerName given has nothig to do with the default Identity 
        ///         It is just a way to create a PeerName instance given a string
        ///  
        public PeerName(string remotePeerName) 
        {
            //------------------------------------------------- 
            //Check arguments
            //-------------------------------------------------
            if (remotePeerName == null)
                throw new ArgumentNullException("remotePeerName"); 

            //------------------------------------------------- 
            //Check PeerName format 
            //NOTE: Currentlt thre is no native API to check
            //the format of the PeerName string. The 
            //StrongParsePeerName implements the logic
            //-------------------------------------------------
            string authority;
            string classifier; 
            if (!StrongParsePeerName(remotePeerName, out authority, out classifier))
            { 
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "PeerName string {0} failed the check for a valid peer name", remotePeerName); 
                throw new ArgumentException(SR.GetString(SR.Pnrp_InvalidPeerName), "remotePeerName");
            } 
            //authrority would have been lower cased
            //so we must ste the m_PeerName to authority + classifier
            if (classifier != null)
                m_PeerName = authority + "." + classifier; 
            else
                m_PeerName = authority; 
            m_Authority = authority; 
            m_Classifier = classifier;
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "PeerName instance created - PeerName {0} Authority {1} Classfier {2}", m_PeerName, m_Authority, ((m_Classifier == null)? "null" : m_Classifier)); 
        }

        /// 
        /// Given a classifier creates a secured or unsecured name 
        /// 
        ///  
        ///  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        [System.Security.SecurityCritical]
        public PeerName(string classifier, PeerNameType peerNameType) 
        {
            //-------------------------------------------------
            //Check arguments
            //------------------------------------------------- 
            if ((classifier == null || classifier.Length == 0)&&
                peerNameType == PeerNameType.Unsecured) 
            { 
                throw new ArgumentNullException("classifier");
            } 
            if (classifier != null && classifier.Length > PEER_MAX_CLASSIFIER_LENGTH)
            {
                throw new ArgumentException(SR.GetString(SR.Pnrp_InvalidClassifier), "classifier");
            } 
 			//--------------------------------------------------
			//Normalize using NFC 
			//-------------------------------------------------- 
            if (classifier != null && classifier.Length > 0)
            { 
                classifier = classifier.Normalize(NormalizationForm.FormC);
            }
            //-------------------------------------------------
            //call the helper to create the PeerName 
            //-------------------------------------------------
            Int32 result; 
            SafePeerData shNewPeerName = null; 
            SafePeerData shDefaultIdentity = null;
            try 
            {
                if (peerNameType == PeerNameType.Unsecured)
                {
                    result = UnsafeP2PNativeMethods.PeerCreatePeerName((string)null, classifier, out shNewPeerName); 
                    if (result != 0)
                    { 
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotCreateUnsecuredPeerName), result); 
                    }
                    m_Authority = PEERNAME_UNSECURED_AUTHORITY; 
                }
                else
                {
                    result = UnsafeP2PNativeMethods.PeerIdentityGetDefault(out shDefaultIdentity); 
                    if (result != 0)
                    { 
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotGetDefaultIdentity), result); 
                    }
                    m_Authority = shDefaultIdentity.UnicodeString; 
                    //}

                    result = UnsafeP2PNativeMethods.PeerCreatePeerName(m_Authority, classifier, out shNewPeerName);
                    if (result != 0) 
                    {
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotCreateSecuredPeerName), result); 
                    } 
                }
                m_PeerName = shNewPeerName.UnicodeString; 
                m_Classifier = classifier;
            }
            finally
            { 
                if (shNewPeerName != null) shNewPeerName.Dispose();
                if (shDefaultIdentity != null) shDefaultIdentity.Dispose(); 
            } 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "PeerName instance created - PeerName {0} Authority {1} Classfier {2}", m_PeerName, m_Authority, m_Classifier);
        } 

        /// 
        /// Given a peerHostName string [the dns safe version of the PeerName]
        /// Get the PeerName for it 
        /// 
        /// string form (dns safe form) of the peer name 
        /// a PeerName instance 
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        [System.Security.SecurityCritical] 
        public static PeerName CreateFromPeerHostName(string peerHostName) 
        {
            //------------------------------------------------- 
            //Check arguments
            //-------------------------------------------------
            if (peerHostName == null)
                throw new ArgumentNullException("peerHostName"); 
            if (peerHostName.Length == 0)
                throw new ArgumentException(SR.GetString(SR.Pnrp_InvalidPeerHostName), "peerHostName"); 
 
            Int32 result;
            SafePeerData shPeerName = null; 
            string peerName = null;
            try
            {
                result = UnsafeP2PNativeMethods.PeerHostNameToPeerName(peerHostName, out shPeerName); 
                if (result != 0)
                { 
                    throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotGetPeerNameFromPeerHostName), result); 
                }
                peerName = shPeerName.UnicodeString; 
            }
            finally
            {
                if (shPeerName != null) shPeerName.Dispose(); 
            }
 
            string authority; 
            string classifier;
            WeakParsePeerName(peerName, out authority, out classifier); 
            PeerName p = new PeerName(peerName, authority, classifier);
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "PeerName created from PeerHostName - PeerHostName {0} to PeerName PeerName {1} Authority {2} Classfier {3}", peerHostName, peerName, authority, classifier);
            return p;
        } 

        ///  
        /// Given a PeerName, change the classifier. 
        /// This is simply replacing the classifier, but we will
        /// let the native APIs do the right thing since they 
        /// might change the concept in future
        /// 
        /// a PeerName instance
        /// a new classfier string 
        /// 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        [System.Security.SecurityCritical] 
        public static PeerName CreateRelativePeerName(
                                        PeerName peerName, 
                                        string classifier) 
        {
            //------------------------------------------------- 
            //Check arguments
            //-------------------------------------------------
            if (peerName == null)
            { 
                throw new ArgumentNullException("peerName", SR.GetString(SR.Pnrp_PeerNameCantBeNull));
            } 
            if (!peerName.IsSecured && (classifier == null || classifier.Length == 0)) 
            {
                throw new ArgumentException(SR.GetString(SR.Pnrp_InvalidClassifier), "classifier"); 
            }
            if (classifier != null && classifier.Length > PEER_MAX_CLASSIFIER_LENGTH)
            {
                throw new ArgumentException(SR.GetString(SR.Pnrp_InvalidClassifier), "classifier"); 
            }
 
			//-------------------------------------------------- 
 			//Normalize using NFC
			//-------------------------------------------------- 
            if (classifier != null && classifier.Length > 0)
            {
                classifier = classifier.Normalize(NormalizationForm.FormC);
            } 

            Int32 result; 
            SafePeerData shNewPeerName = null; 
            string newPeerName = null;
            try 
            {
                //Here there is change made on the native side
                //when passing secured peer names, it takes string of the form [40hexdigits].claasisifer and a newclassifier
                //returns [40hexdigits.newclassifier] 
                //But for unsecured peer names it does not take 0.clasfier and newclassfier to return 0.newclassfier.
                //It expects NULL as the first param. To satisfy this broken finctionality, we are passing null if the 
                //peer name is unsecured. 
                result = UnsafeP2PNativeMethods.PeerCreatePeerName(peerName.IsSecured? peerName.m_PeerName : null, classifier, out shNewPeerName);
                if (result != 0) 
                {
                    throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotCreateRelativePeerName), result);
                }
                newPeerName = shNewPeerName.UnicodeString; 
            }
            finally 
            { 
                if (shNewPeerName != null) shNewPeerName.Dispose();
            } 

            string authority;
            string newClassifier;
            WeakParsePeerName(newPeerName, out authority, out newClassifier); 
            PeerName p = new PeerName(newPeerName, authority, newClassifier);
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "A new PeerName created from existing PeerName with a new classfier. Existing PeerName {0} Classifier {1} New PeerName {2}", peerName, classifier, p); 
            return p; 
        }
 
        /// 
        /// Friendly string
        /// 
        ///  
        public override string ToString()
        { 
            return m_PeerName; 
        }
 
        /// 
        /// Notionb of equals is based on same peer name string content
        /// 
        ///  
        /// 
        public bool Equals(PeerName other) 
        { 
            if(other == null) return false;
            return string.Compare(other.m_PeerName, m_PeerName, StringComparison.Ordinal) == 0; 
        }

        public override bool Equals(object obj)
        { 
            if (obj == null) return false;
            PeerName other = obj as PeerName; 
            if (other == null) return false; 
            return Equals(other);
 
        }
        /// 
        /// Hash code comes from m_PeerName since the others are just components of this
        ///  
        /// 
        public override int GetHashCode() 
        { 
            return m_PeerName.GetHashCode();
        } 

        /// 
        /// Authroity
        ///  
        public string Authority
        { 
            get 
            {
                return m_Authority; 
            }
        }
        /// 
        /// Classifier 
        /// 
        public string Classifier 
        { 
            get
            { 
                return m_Classifier;
            }
        }
 
        /// 
        /// A DNS Safe version of the Peer Name 
        ///  
        public string PeerHostName
        { 
            // 
            // 
            // 
            //  
            // 
            //  
            //  
            [System.Security.SecurityCritical]
            get 
            {
                if (m_PeerHostName == null)
                {
                    Int32 result; 
                    SafePeerData shPeerHostName = null;
                    try 
                    { 
 						//This API gives HRESULT > 0 for success instead of S_OK == 0
 						//WINDOWS OS 

                        result = UnsafeP2PNativeMethods.PeerNameToPeerHostName( m_PeerName, out shPeerHostName);
                        if (result < 0)
                        { 
                            throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotGetPeerHostNameFromPeerName), result);
                        } 
                        m_PeerHostName = shPeerHostName.UnicodeString; 
                    }
                    finally 
                    {
                        if (shPeerHostName != null) shPeerHostName.Dispose();
                    }
                } 
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "PeerHostName created for PeerName PeerHostName {0} PeerName {1}", m_PeerHostName, this);
                return m_PeerHostName; 
            } 
        }
 
        /// 
        /// Basically if the authority == 0 or not [unsecured or secured respectively]
        /// 
        public bool IsSecured 
        {
            get 
            { 
                return m_Authority != PEERNAME_UNSECURED_AUTHORITY;
            } 
        }


        // =================================================== 
        // Private methods
        // ==================================================== 
        ///  
        /// I have considered using regular expressions. However, the regular expressions offer
        /// poor performance and or startup cost. Really there is no substiture for custom 
        /// parsing logic. I decided to write this piece of code to parse the peername for now
        /// - [....] 6/6/2005
        /// 
        ///  
        /// 
        ///  
        ///  
        private static bool StrongParsePeerName(string peerName, out string authority, out string classifier)
        { 
            authority = null;
            classifier = null;

            //Rule 0. The max length must not be exeeded 
            if (peerName == null ||
                peerName.Length == 0 || 
                peerName.Length > PEER_MAX_PEERNAME_LENGTH) return false; 

            //Rule 1. The length of the string must be at least 3 
            //as in 0.C for unsecured PeerName with classifier "C"
            if (peerName.Length < 3) return false;

            string tempAuthority = null; 
            int IndexOfPeriod = peerName.IndexOf('.');
            if (IndexOfPeriod == 0) return false; 
            if (IndexOfPeriod < 0) 
            {
                //Rule 2. Secure PeerNames can have just the authority 
                //or Authority. or Authority.Classifier
                //if there is no period, we have to treat the entire string as the authority
                tempAuthority = peerName;
            } 
            else if (IndexOfPeriod == peerName.Length - 1)
            { 
                //May be this is of the form Authority. 
                tempAuthority = peerName.Substring(0, peerName.Length - 1);
            } 
            else
            {
                //Rule 2B. Unsecure peer names must have a classifier
                //There must be a period separating the authority and classifier 
                //and must not be the first character and it must not be the last character
                tempAuthority = peerName.Substring(0, IndexOfPeriod); 
            } 

            //Rule 3. Authority is either SECURE_AUTHORITY_LENGTH hex characters or "0" 
            if (tempAuthority.Length != SECURE_AUTHORITY_LENGTH &&
                tempAuthority.Length != INSECURE_AUTHORITY_LENGTH) return false;

            //Rule 4. If it is length 1 it must be 0 
            if (tempAuthority.Length == INSECURE_AUTHORITY_LENGTH && tempAuthority != PEERNAME_UNSECURED_AUTHORITY)
                return false; 
 
            //Rule 5. the authority must be 40 hex characters
            if(tempAuthority.Length == SECURE_AUTHORITY_LENGTH) 
            {
                foreach (char c in tempAuthority)
                {
                    if (!IsHexDigit(c)) return false; 
                }
            } 
            //Rule 6. The maximum length of the classfier is PEER_MAX_CLASSIFIER_LENGTH 
            string tempClassifier = null;
            if (IndexOfPeriod != peerName.Length - 1 && IndexOfPeriod > 0) 
            {
                tempClassifier = peerName.Substring(IndexOfPeriod + 1);
            }
            if (tempClassifier != null && tempClassifier.Length > PEER_MAX_CLASSIFIER_LENGTH) return false; 

            //Finish 
            authority = tempAuthority.ToLower(CultureInfo.InvariantCulture); //Safe for Hex digits 
            classifier = tempClassifier;
            return true; 
        }
        private static bool IsHexDigit(char character)
        {
            return ((character >= '0') && (character <= '9')) 
                || ((character >= 'A') && (character <= 'F'))
                || ((character >= 'a') && (character <= 'f')); 
        } 

        ///  
        /// WARNING: Don't call this unless you are sure that
        /// the PeerName is a valid string. This is invoked only when
        /// we are sure that the peername is valid and we need to components
        ///  
        /// in: peerName to parse
        /// out: parsed authority value 
        /// out: parsed classfier value 
        /// none
        private static void WeakParsePeerName(string peerName, out string authority, out string classifier) 
        {
            authority = null;
            classifier = null;
            int indexOfPeriod = peerName.IndexOf('.'); 
            if (indexOfPeriod < 0)
            { 
                authority = peerName; 
            }
            else if (indexOfPeriod == peerName.Length - 1) 
            {
                //May be this is of the form Authority.
                authority = peerName.Substring(0, peerName.Length - 1);
            } 
            else
            { 
                authority = peerName.Substring(0, indexOfPeriod); 
            }
 
            if (indexOfPeriod != peerName.Length - 1 && indexOfPeriod > 0)
            {
                classifier = peerName.Substring(indexOfPeriod + 1);
            } 
            authority = authority.ToLower(CultureInfo.InvariantCulture); //safe for hex strings
        } 
 
        /// 
        /// Constructor to enable serialization 
        /// 
        /// 
        /// 
        protected PeerName(SerializationInfo info, StreamingContext context) 
        {
            if (info == null) 
            { 
                throw new ArgumentNullException("info");
            } 
            m_PeerName = info.GetString("_PeerName");
            m_Authority = info.GetString("_Authority");
            m_Classifier = info.GetString("_Classifier");
        } 

 
        //  
        // 
        //  
        [System.Security.SecurityCritical]
        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter, SerializationFormatter = true)]
        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        { 
            GetObjectData(info, context);
        } 
 
        /// 
        /// This is made virtual so that derived types can be implemented correctly 
        /// 
        /// 
        /// 
        [SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)] 
        protected virtual void GetObjectData(SerializationInfo info, StreamingContext context)
        { 
            info.AddValue("_PeerName", m_PeerName); 
            info.AddValue("_Authority", m_Authority);
            info.AddValue("_Classifier", m_Classifier); 
        }
 		
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 
namespace System.Net.PeerToPeer
{ 
 
    using System;
    using System.Globalization; 
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;
    using System.Text.RegularExpressions; 
    using System.Runtime.InteropServices;
    using System.Diagnostics; 
    using System.Runtime.Serialization; 
    using System.Security.Permissions;
    using Microsoft.Win32; 
    /// 
    /// The PeerName class represents the native PeerName construct.
    /// 
    [Serializable] 
    public class PeerName : ISerializable, IEquatable
    { 
        //=================================================== 
        //constants
        //=================================================== 
        private const int PEER_MAX_CLASSIFIER_LENGTH = 149;
        private const int SECURE_AUTHORITY_LENGTH = 40;
        private const int INSECURE_AUTHORITY_LENGTH = 1;
        private const int PEER_MAX_PEERNAME_LENGTH = SECURE_AUTHORITY_LENGTH + 1 + PEER_MAX_CLASSIFIER_LENGTH; 
        private const string PEERNAME_UNSECURED_AUTHORITY = "0";
 
        //==================================================== 
        //private member variables
        //=================================================== 
        private string m_PeerName;
        private string m_Authority;
        private string m_Classifier;
        private string m_PeerHostName; 

        // ==================================================== 
        //     Constructors 
        // ====================================================
 
        static PeerName()
        {
            //-------------------------------------------------
            //Check for the availability of the simpler PNRP APIs 
            //-------------------------------------------------
            if (!PeerToPeerOSHelper.SupportsP2P) 
            { 
                throw new PlatformNotSupportedException(SR.GetString(SR.P2P_NotAvailable));
            } 
        }

        /// 
        /// We use this constructor to create an PeerName 
        /// for internal implementation
        ///  
        private PeerName(string peerName, string authority, string classifier) { 
            m_PeerName = peerName;
            m_Classifier = classifier; 
            m_Authority = authority;
        }

        ///  
        /// This constructor is to create a peername from an
        /// arbitrary string. The Identity is not necessarily 
        /// the same as the current user 
        /// 
        /// string form of the peer name 
        /// 
        ///     1. We assume that the peername is already normalized according to the
        ///         Unicode rules
        ///     2. The PeerName given has nothig to do with the default Identity 
        ///         It is just a way to create a PeerName instance given a string
        ///  
        public PeerName(string remotePeerName) 
        {
            //------------------------------------------------- 
            //Check arguments
            //-------------------------------------------------
            if (remotePeerName == null)
                throw new ArgumentNullException("remotePeerName"); 

            //------------------------------------------------- 
            //Check PeerName format 
            //NOTE: Currentlt thre is no native API to check
            //the format of the PeerName string. The 
            //StrongParsePeerName implements the logic
            //-------------------------------------------------
            string authority;
            string classifier; 
            if (!StrongParsePeerName(remotePeerName, out authority, out classifier))
            { 
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "PeerName string {0} failed the check for a valid peer name", remotePeerName); 
                throw new ArgumentException(SR.GetString(SR.Pnrp_InvalidPeerName), "remotePeerName");
            } 
            //authrority would have been lower cased
            //so we must ste the m_PeerName to authority + classifier
            if (classifier != null)
                m_PeerName = authority + "." + classifier; 
            else
                m_PeerName = authority; 
            m_Authority = authority; 
            m_Classifier = classifier;
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "PeerName instance created - PeerName {0} Authority {1} Classfier {2}", m_PeerName, m_Authority, ((m_Classifier == null)? "null" : m_Classifier)); 
        }

        /// 
        /// Given a classifier creates a secured or unsecured name 
        /// 
        ///  
        ///  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        [System.Security.SecurityCritical]
        public PeerName(string classifier, PeerNameType peerNameType) 
        {
            //-------------------------------------------------
            //Check arguments
            //------------------------------------------------- 
            if ((classifier == null || classifier.Length == 0)&&
                peerNameType == PeerNameType.Unsecured) 
            { 
                throw new ArgumentNullException("classifier");
            } 
            if (classifier != null && classifier.Length > PEER_MAX_CLASSIFIER_LENGTH)
            {
                throw new ArgumentException(SR.GetString(SR.Pnrp_InvalidClassifier), "classifier");
            } 
 			//--------------------------------------------------
			//Normalize using NFC 
			//-------------------------------------------------- 
            if (classifier != null && classifier.Length > 0)
            { 
                classifier = classifier.Normalize(NormalizationForm.FormC);
            }
            //-------------------------------------------------
            //call the helper to create the PeerName 
            //-------------------------------------------------
            Int32 result; 
            SafePeerData shNewPeerName = null; 
            SafePeerData shDefaultIdentity = null;
            try 
            {
                if (peerNameType == PeerNameType.Unsecured)
                {
                    result = UnsafeP2PNativeMethods.PeerCreatePeerName((string)null, classifier, out shNewPeerName); 
                    if (result != 0)
                    { 
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotCreateUnsecuredPeerName), result); 
                    }
                    m_Authority = PEERNAME_UNSECURED_AUTHORITY; 
                }
                else
                {
                    result = UnsafeP2PNativeMethods.PeerIdentityGetDefault(out shDefaultIdentity); 
                    if (result != 0)
                    { 
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotGetDefaultIdentity), result); 
                    }
                    m_Authority = shDefaultIdentity.UnicodeString; 
                    //}

                    result = UnsafeP2PNativeMethods.PeerCreatePeerName(m_Authority, classifier, out shNewPeerName);
                    if (result != 0) 
                    {
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotCreateSecuredPeerName), result); 
                    } 
                }
                m_PeerName = shNewPeerName.UnicodeString; 
                m_Classifier = classifier;
            }
            finally
            { 
                if (shNewPeerName != null) shNewPeerName.Dispose();
                if (shDefaultIdentity != null) shDefaultIdentity.Dispose(); 
            } 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "PeerName instance created - PeerName {0} Authority {1} Classfier {2}", m_PeerName, m_Authority, m_Classifier);
        } 

        /// 
        /// Given a peerHostName string [the dns safe version of the PeerName]
        /// Get the PeerName for it 
        /// 
        /// string form (dns safe form) of the peer name 
        /// a PeerName instance 
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        [System.Security.SecurityCritical] 
        public static PeerName CreateFromPeerHostName(string peerHostName) 
        {
            //------------------------------------------------- 
            //Check arguments
            //-------------------------------------------------
            if (peerHostName == null)
                throw new ArgumentNullException("peerHostName"); 
            if (peerHostName.Length == 0)
                throw new ArgumentException(SR.GetString(SR.Pnrp_InvalidPeerHostName), "peerHostName"); 
 
            Int32 result;
            SafePeerData shPeerName = null; 
            string peerName = null;
            try
            {
                result = UnsafeP2PNativeMethods.PeerHostNameToPeerName(peerHostName, out shPeerName); 
                if (result != 0)
                { 
                    throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotGetPeerNameFromPeerHostName), result); 
                }
                peerName = shPeerName.UnicodeString; 
            }
            finally
            {
                if (shPeerName != null) shPeerName.Dispose(); 
            }
 
            string authority; 
            string classifier;
            WeakParsePeerName(peerName, out authority, out classifier); 
            PeerName p = new PeerName(peerName, authority, classifier);
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "PeerName created from PeerHostName - PeerHostName {0} to PeerName PeerName {1} Authority {2} Classfier {3}", peerHostName, peerName, authority, classifier);
            return p;
        } 

        ///  
        /// Given a PeerName, change the classifier. 
        /// This is simply replacing the classifier, but we will
        /// let the native APIs do the right thing since they 
        /// might change the concept in future
        /// 
        /// a PeerName instance
        /// a new classfier string 
        /// 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        [System.Security.SecurityCritical] 
        public static PeerName CreateRelativePeerName(
                                        PeerName peerName, 
                                        string classifier) 
        {
            //------------------------------------------------- 
            //Check arguments
            //-------------------------------------------------
            if (peerName == null)
            { 
                throw new ArgumentNullException("peerName", SR.GetString(SR.Pnrp_PeerNameCantBeNull));
            } 
            if (!peerName.IsSecured && (classifier == null || classifier.Length == 0)) 
            {
                throw new ArgumentException(SR.GetString(SR.Pnrp_InvalidClassifier), "classifier"); 
            }
            if (classifier != null && classifier.Length > PEER_MAX_CLASSIFIER_LENGTH)
            {
                throw new ArgumentException(SR.GetString(SR.Pnrp_InvalidClassifier), "classifier"); 
            }
 
			//-------------------------------------------------- 
 			//Normalize using NFC
			//-------------------------------------------------- 
            if (classifier != null && classifier.Length > 0)
            {
                classifier = classifier.Normalize(NormalizationForm.FormC);
            } 

            Int32 result; 
            SafePeerData shNewPeerName = null; 
            string newPeerName = null;
            try 
            {
                //Here there is change made on the native side
                //when passing secured peer names, it takes string of the form [40hexdigits].claasisifer and a newclassifier
                //returns [40hexdigits.newclassifier] 
                //But for unsecured peer names it does not take 0.clasfier and newclassfier to return 0.newclassfier.
                //It expects NULL as the first param. To satisfy this broken finctionality, we are passing null if the 
                //peer name is unsecured. 
                result = UnsafeP2PNativeMethods.PeerCreatePeerName(peerName.IsSecured? peerName.m_PeerName : null, classifier, out shNewPeerName);
                if (result != 0) 
                {
                    throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotCreateRelativePeerName), result);
                }
                newPeerName = shNewPeerName.UnicodeString; 
            }
            finally 
            { 
                if (shNewPeerName != null) shNewPeerName.Dispose();
            } 

            string authority;
            string newClassifier;
            WeakParsePeerName(newPeerName, out authority, out newClassifier); 
            PeerName p = new PeerName(newPeerName, authority, newClassifier);
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "A new PeerName created from existing PeerName with a new classfier. Existing PeerName {0} Classifier {1} New PeerName {2}", peerName, classifier, p); 
            return p; 
        }
 
        /// 
        /// Friendly string
        /// 
        ///  
        public override string ToString()
        { 
            return m_PeerName; 
        }
 
        /// 
        /// Notionb of equals is based on same peer name string content
        /// 
        ///  
        /// 
        public bool Equals(PeerName other) 
        { 
            if(other == null) return false;
            return string.Compare(other.m_PeerName, m_PeerName, StringComparison.Ordinal) == 0; 
        }

        public override bool Equals(object obj)
        { 
            if (obj == null) return false;
            PeerName other = obj as PeerName; 
            if (other == null) return false; 
            return Equals(other);
 
        }
        /// 
        /// Hash code comes from m_PeerName since the others are just components of this
        ///  
        /// 
        public override int GetHashCode() 
        { 
            return m_PeerName.GetHashCode();
        } 

        /// 
        /// Authroity
        ///  
        public string Authority
        { 
            get 
            {
                return m_Authority; 
            }
        }
        /// 
        /// Classifier 
        /// 
        public string Classifier 
        { 
            get
            { 
                return m_Classifier;
            }
        }
 
        /// 
        /// A DNS Safe version of the Peer Name 
        ///  
        public string PeerHostName
        { 
            // 
            // 
            // 
            //  
            // 
            //  
            //  
            [System.Security.SecurityCritical]
            get 
            {
                if (m_PeerHostName == null)
                {
                    Int32 result; 
                    SafePeerData shPeerHostName = null;
                    try 
                    { 
 						//This API gives HRESULT > 0 for success instead of S_OK == 0
 						//WINDOWS OS 

                        result = UnsafeP2PNativeMethods.PeerNameToPeerHostName( m_PeerName, out shPeerHostName);
                        if (result < 0)
                        { 
                            throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotGetPeerHostNameFromPeerName), result);
                        } 
                        m_PeerHostName = shPeerHostName.UnicodeString; 
                    }
                    finally 
                    {
                        if (shPeerHostName != null) shPeerHostName.Dispose();
                    }
                } 
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "PeerHostName created for PeerName PeerHostName {0} PeerName {1}", m_PeerHostName, this);
                return m_PeerHostName; 
            } 
        }
 
        /// 
        /// Basically if the authority == 0 or not [unsecured or secured respectively]
        /// 
        public bool IsSecured 
        {
            get 
            { 
                return m_Authority != PEERNAME_UNSECURED_AUTHORITY;
            } 
        }


        // =================================================== 
        // Private methods
        // ==================================================== 
        ///  
        /// I have considered using regular expressions. However, the regular expressions offer
        /// poor performance and or startup cost. Really there is no substiture for custom 
        /// parsing logic. I decided to write this piece of code to parse the peername for now
        /// - [....] 6/6/2005
        /// 
        ///  
        /// 
        ///  
        ///  
        private static bool StrongParsePeerName(string peerName, out string authority, out string classifier)
        { 
            authority = null;
            classifier = null;

            //Rule 0. The max length must not be exeeded 
            if (peerName == null ||
                peerName.Length == 0 || 
                peerName.Length > PEER_MAX_PEERNAME_LENGTH) return false; 

            //Rule 1. The length of the string must be at least 3 
            //as in 0.C for unsecured PeerName with classifier "C"
            if (peerName.Length < 3) return false;

            string tempAuthority = null; 
            int IndexOfPeriod = peerName.IndexOf('.');
            if (IndexOfPeriod == 0) return false; 
            if (IndexOfPeriod < 0) 
            {
                //Rule 2. Secure PeerNames can have just the authority 
                //or Authority. or Authority.Classifier
                //if there is no period, we have to treat the entire string as the authority
                tempAuthority = peerName;
            } 
            else if (IndexOfPeriod == peerName.Length - 1)
            { 
                //May be this is of the form Authority. 
                tempAuthority = peerName.Substring(0, peerName.Length - 1);
            } 
            else
            {
                //Rule 2B. Unsecure peer names must have a classifier
                //There must be a period separating the authority and classifier 
                //and must not be the first character and it must not be the last character
                tempAuthority = peerName.Substring(0, IndexOfPeriod); 
            } 

            //Rule 3. Authority is either SECURE_AUTHORITY_LENGTH hex characters or "0" 
            if (tempAuthority.Length != SECURE_AUTHORITY_LENGTH &&
                tempAuthority.Length != INSECURE_AUTHORITY_LENGTH) return false;

            //Rule 4. If it is length 1 it must be 0 
            if (tempAuthority.Length == INSECURE_AUTHORITY_LENGTH && tempAuthority != PEERNAME_UNSECURED_AUTHORITY)
                return false; 
 
            //Rule 5. the authority must be 40 hex characters
            if(tempAuthority.Length == SECURE_AUTHORITY_LENGTH) 
            {
                foreach (char c in tempAuthority)
                {
                    if (!IsHexDigit(c)) return false; 
                }
            } 
            //Rule 6. The maximum length of the classfier is PEER_MAX_CLASSIFIER_LENGTH 
            string tempClassifier = null;
            if (IndexOfPeriod != peerName.Length - 1 && IndexOfPeriod > 0) 
            {
                tempClassifier = peerName.Substring(IndexOfPeriod + 1);
            }
            if (tempClassifier != null && tempClassifier.Length > PEER_MAX_CLASSIFIER_LENGTH) return false; 

            //Finish 
            authority = tempAuthority.ToLower(CultureInfo.InvariantCulture); //Safe for Hex digits 
            classifier = tempClassifier;
            return true; 
        }
        private static bool IsHexDigit(char character)
        {
            return ((character >= '0') && (character <= '9')) 
                || ((character >= 'A') && (character <= 'F'))
                || ((character >= 'a') && (character <= 'f')); 
        } 

        ///  
        /// WARNING: Don't call this unless you are sure that
        /// the PeerName is a valid string. This is invoked only when
        /// we are sure that the peername is valid and we need to components
        ///  
        /// in: peerName to parse
        /// out: parsed authority value 
        /// out: parsed classfier value 
        /// none
        private static void WeakParsePeerName(string peerName, out string authority, out string classifier) 
        {
            authority = null;
            classifier = null;
            int indexOfPeriod = peerName.IndexOf('.'); 
            if (indexOfPeriod < 0)
            { 
                authority = peerName; 
            }
            else if (indexOfPeriod == peerName.Length - 1) 
            {
                //May be this is of the form Authority.
                authority = peerName.Substring(0, peerName.Length - 1);
            } 
            else
            { 
                authority = peerName.Substring(0, indexOfPeriod); 
            }
 
            if (indexOfPeriod != peerName.Length - 1 && indexOfPeriod > 0)
            {
                classifier = peerName.Substring(indexOfPeriod + 1);
            } 
            authority = authority.ToLower(CultureInfo.InvariantCulture); //safe for hex strings
        } 
 
        /// 
        /// Constructor to enable serialization 
        /// 
        /// 
        /// 
        protected PeerName(SerializationInfo info, StreamingContext context) 
        {
            if (info == null) 
            { 
                throw new ArgumentNullException("info");
            } 
            m_PeerName = info.GetString("_PeerName");
            m_Authority = info.GetString("_Authority");
            m_Classifier = info.GetString("_Classifier");
        } 

 
        //  
        // 
        //  
        [System.Security.SecurityCritical]
        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter, SerializationFormatter = true)]
        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        { 
            GetObjectData(info, context);
        } 
 
        /// 
        /// This is made virtual so that derived types can be implemented correctly 
        /// 
        /// 
        /// 
        [SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)] 
        protected virtual void GetObjectData(SerializationInfo info, StreamingContext context)
        { 
            info.AddValue("_PeerName", m_PeerName); 
            info.AddValue("_Authority", m_Authority);
            info.AddValue("_Classifier", m_Classifier); 
        }
 		
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK