PeerNameRegistration.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / SystemNet / Net / PeerToPeer / PeerNameRegistration.cs / 1305376 / PeerNameRegistration.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 
namespace System.Net.PeerToPeer
{ 
    using System; 
    using System.Collections.Generic;
    using System.Text; 
    using System.Security.Permissions;
    using System.Runtime.InteropServices;
    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis; 
    using System.Runtime.Serialization;
 
 
    /// 
    /// The PeerNameRegistration class registers a peer name record 
    /// 
    [Serializable]
    public class PeerNameRegistration : IDisposable, ISerializable
    { 
        //-----------------------------------------------------------------------
        //Native constant to indicate auto address selection 
        //----------------------------------------------------------------------- 
        private const UInt32 PEER_PNRP_AUTO_ADDRESSES  =  unchecked((UInt32)(-1));
 

        //------------------------------------------------------------------------
        //Internal PeerNameRecord to hold information.
        //----------------------------------------------------------------------- 
        private PeerNameRecord m_PeerNameRecord = new PeerNameRecord();
        private int m_Port; 
        private Cloud m_Cloud; 

        //------------------------------------------------------------------------ 
        //Flag to keep whether We registered or not
        //------------------------------------------------------------------------
        private bool m_IsRegistered;
 
        //-----------------------------------------------------------------------
        //The native handle to the registration 
        //------------------------------------------------------------------------ 
        private SafePeerNameUnregister m_RegistrationHandle;
 
        //-----------------------------------------------------------------------
        //PeerName that is associated with this registation
        //If they update the PeerName in the PeerNameRecord and call update we
        //should throw 
        //-----------------------------------------------------------------------
        private PeerName m_RegisteredPeerName; 
 
        //-----------------------------------------------------------------------
        //We should support the scenario where you publish just the data 
        //but no end points. This flag tells us whether to use auto endpoint selection
        //or not
        //------------------------------------------------------------------------
        private bool m_UseAutoEndPointSelection = true; 

        static PeerNameRegistration() 
        { 
            //-------------------------------------------------
            //Check for the availability of the simpler PNRP APIs 
            //-------------------------------------------------
            if (!PeerToPeerOSHelper.SupportsP2P)
            {
                throw new PlatformNotSupportedException(SR.GetString(SR.P2P_NotAvailable)); 
            }
        } 
 
        /// 
        /// Empty constructor so that users can populate the 
        /// information later
        /// 
        public PeerNameRegistration()
        { 
        }
 
        ///  
        /// This constuctor popuates the PeerNameRecord and registers automatically
        /// Registers in all clouds with automatic address selection 
        /// 
        /// PeerName to register
        /// Port to register on
        public PeerNameRegistration(PeerName name, int port) : this(name, port, null) 
        {
        } 
        ///  
        /// This constuctor popuates the PeerNameRecord and registers automatically
        /// Registers with automatic address selection within the cloud 
        /// 
        /// PeerName to register
        /// Port to register on
        /// A specific cloud to regster in/// 
        public PeerNameRegistration(PeerName name, int port, Cloud cloud)
        { 
            if (name == null) 
            {
                throw new ArgumentNullException("name"); 
            }
            if (cloud == null)
            {
                cloud = Cloud.Available; 
            }
            if (port < IPEndPoint.MinPort || port > IPEndPoint.MaxPort) 
            { 
                throw new ArgumentOutOfRangeException("port", SR.GetString(SR.Pnrp_PortOutOfRange));
            } 


            m_PeerNameRecord.PeerName = name;
            m_Port = port; 
            m_Cloud = cloud;
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Created a PeerNameRegistration with PeerName {0}, Port {1}, Cloud {2} - Proceeding to register", name, port, cloud); 
        } 

        ///  
        /// Property accessor to examine/change and perhaps call
        /// Update() to update the registration information
        /// 
        internal PeerNameRecord PeerNameRecord 
        {
            get 
            { 
                if (m_Disposed)
                { 
                    throw new ObjectDisposedException(this.GetType().FullName);
                }
                return m_PeerNameRecord;
            } 
        }
 
        public int Port 
        {
            get 
            {
                return m_Port;
            }
            set 
            {
                if (value < IPEndPoint.MinPort || value > IPEndPoint.MaxPort) 
                { 
                    throw new ArgumentOutOfRangeException("port", SR.GetString(SR.Pnrp_PortOutOfRange));
                } 

                m_Port = value;
            }
        } 

 
        public PeerName PeerName 
        {
            get 
            {
                return m_PeerNameRecord.PeerName;
            }
            set 
            {
 
                m_PeerNameRecord.PeerName = value; 

            } 
        }

        public IPEndPointCollection EndPointCollection
        { 
            get
            { 
                return m_PeerNameRecord.EndPointCollection; 
            }
        } 

        public Cloud Cloud
        {
            get 
            {
                return m_Cloud; 
            } 
            set
            { 
                m_Cloud = value;
            }
        }
 
        public string Comment
        { 
            get 
            {
                return m_PeerNameRecord.Comment; 
            }
            set
            {
                m_PeerNameRecord.Comment = value; 
            }
        } 
        public byte[] Data 
        {
            get 
            {
                return m_PeerNameRecord.Data;
            }
            set 
            {
                m_PeerNameRecord.Data = value; 
            } 
        }
 
        public bool UseAutoEndPointSelection
        {
            get
            { 
                return m_UseAutoEndPointSelection;
            } 
            set 
            {
                m_UseAutoEndPointSelection = value; 
            }
        }

        ///  
        /// Return the flag to indicate whether we
        /// registered or not 
        ///  
        /// 
        public bool IsRegistered() 
        {
            if (m_Disposed)
            {
                throw new ObjectDisposedException(this.GetType().FullName); 
            }
 
            //------------------------------------------------- 
            //Demand for the Unrestricted Pnrp Permission
            //------------------------------------------------- 
            PnrpPermission.UnrestrictedPnrpPermission.Demand();

            return m_IsRegistered;
        } 

        ///  
        /// This method is called if empty constructor is used and the 
        /// information in the PeerNameRecord is set. Register needs to
        /// be called since we did not automatically register through the 
        /// constructor
        /// 
        // 
        //  
        // 
        [System.Security.SecurityCritical] 
        public void Start() 
        {
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); 

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Proceeding to register through the Register method()");
            InternalRegister();
        } 

        ///  
        /// This is where the real registration happens 
        /// 
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        [System.Security.SecurityCritical] 
        private void InternalRegister() 
        {
            //------------------------------------------ 
            //If we already registered, get out this place
            //------------------------------------------
            if (m_IsRegistered)
            { 
                throw new PeerToPeerException(SR.GetString(SR.Pnrp_UseUpdateInsteadOfRegister));
            } 
 
            //------------------------------------------
            //Make sure you have the required info 
            //------------------------------------------
            if (m_PeerNameRecord.PeerName == null)
            {
                throw new ArgumentNullException("PeerName"); 
            }
 
            //------------------------------------------ 
            //If auto address selection is turned off
            //then there must be atleast Data or Endpoints 
            //specified
            //------------------------------------------
            if (!m_UseAutoEndPointSelection)
            { 
                if ((EndPointCollection.Count == 0) &&
                     (Data == null || Data.Length <= 0)) 
                { 
                    throw new PeerToPeerException(SR.GetString(SR.Pnrp_BlobOrEndpointListNeeded));
                } 
            }


            //------------------------------------------------- 
            //Demand for the Unrestricted Pnrp Permission
            //------------------------------------------------- 
            PnrpPermission.UnrestrictedPnrpPermission.Demand(); 

            //--------------------------------------------------------------- 
            //No perf hit here, real native call happens only one time if it
            //did not already happen
            //----------------------------------------------------------------
            UnsafeP2PNativeMethods.PnrpStartup(); 

            //---------------------------------------------------------------- 
            //Log trace info 
            //---------------------------------------------------------------
            if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Information)) 
            {
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "InternalRegister() is called with the following Info");
                m_PeerNameRecord.TracePeerNameRecord();
            } 

            PEER_PNRP_REGISTRATION_INFO regInfo = new PEER_PNRP_REGISTRATION_INFO(); 
            GCHandle handle; 
            //-------------------------------------------------
            //Set data 
            //-------------------------------------------------
            if (m_PeerNameRecord.Data != null)
            {
                regInfo.payLoad.cbPayload = (UInt32)m_PeerNameRecord.Data.Length; 
                handle = GCHandle.Alloc(m_PeerNameRecord.Data, GCHandleType.Pinned);
                regInfo.payLoad.pbPayload = handle.AddrOfPinnedObject(); //m_PeerNameRecord.Data; 
            } 
            else
            { 
                handle = new GCHandle();
            }
            //-------------------------------------------------
            //Set comment 
            //-------------------------------------------------
            if (m_PeerNameRecord.Comment != null && m_PeerNameRecord.Comment.Length > 0) 
            { 
                regInfo.pwszComment = m_PeerNameRecord.Comment;
            } 
            //-------------------------------------------------
            //Set cloud name
            //-------------------------------------------------
            if (m_Cloud != null) 
            {
                regInfo.pwszCloudName = m_Cloud.InternalName; 
            } 
            try
            { 
                if (m_PeerNameRecord.EndPointCollection.Count == 0)
                {
                    //-------------------------------------------------
                    //Set port only if the addresses are null 
                    //and then set the selection to auto addresses
                    //------------------------------------------------- 
                    regInfo.wport = (ushort)m_Port; 

                    if(m_UseAutoEndPointSelection) 
                        regInfo.cAddresses = PEER_PNRP_AUTO_ADDRESSES;

                    //-------------------------------------------------
                    //Call the native API to register 
                    //-------------------------------------------------
                    int result = UnsafeP2PNativeMethods.PeerPnrpRegister(m_PeerNameRecord.PeerName.ToString(), 
                                        ref regInfo, 
                                        out m_RegistrationHandle);
                    if (result != 0) 
                    {
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotRegisterPeerName), result);
                    }
                } 
                else
                { 
                    //------------------------------------------------- 
                    //Set the Endpoint List
                    //------------------------------------------------- 
                    int numAddresses = m_PeerNameRecord.EndPointCollection.Count;
                    int cbRequriedBytes = numAddresses * Marshal.SizeOf(typeof(IntPtr));
                    IntPtr pSocketAddrList = Marshal.AllocHGlobal(cbRequriedBytes);
                    GCHandle[] GCHandles = new GCHandle[numAddresses]; 
                    try
                    { 
                        unsafe 
                        {
                            IntPtr* pAddress = (IntPtr*)pSocketAddrList; 
                            for (int i = 0; i < m_PeerNameRecord.EndPointCollection.Count; i++)
                            {
                                byte[] sockaddr = SystemNetHelpers.SOCKADDRFromIPEndPoint(m_PeerNameRecord.EndPointCollection[i]);
                                GCHandles[i] = GCHandle.Alloc(sockaddr, GCHandleType.Pinned); 
                                IntPtr psockAddr = GCHandles[i].AddrOfPinnedObject();
                                pAddress[i] = psockAddr; 
                            } 
                        }
                        regInfo.ArrayOfSOCKADDRIN6Pointers = pSocketAddrList; 
                        regInfo.cAddresses = (UInt32)numAddresses;
                        int result = UnsafeP2PNativeMethods.PeerPnrpRegister(m_PeerNameRecord.PeerName.ToString(),
                                            ref regInfo,
                                            out m_RegistrationHandle); 
                        if (result != 0)
                        { 
                            throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotRegisterPeerName), result); 
                        }
                    } 
                    finally
                    {
                        if (pSocketAddrList != IntPtr.Zero)
                            Marshal.FreeHGlobal(pSocketAddrList); 

                        for (int i = 0; i < GCHandles.Length; i++) 
                        { 
                            if (GCHandles[i].IsAllocated)
                                GCHandles[i].Free(); 
                        }
                    }
                }
            } 
            finally
            { 
                if (handle.IsAllocated) 
                {
                    handle.Free(); 
                }

            }
            m_RegisteredPeerName = m_PeerNameRecord.PeerName; 
            m_IsRegistered = true;
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Registration is successful. The handle is {0}", m_RegistrationHandle.DangerousGetHandle()); 
        } 

        ///  
        /// Update is called if an existing registration needs to be updated
        /// 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        [System.Security.SecurityCritical]
        public void Update() 
        {
            //-------------------------------------------------
            //Check for the dead object
            //------------------------------------------------- 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
            //------------------------------------------------- 
            //If there is no existing registration to update
            //get out 
            //-------------------------------------------------
            if (!IsRegistered())
            {
                throw new InvalidOperationException(SR.GetString(SR.Pnrp_CallRegisterBeforeUpdate)); 
            }
 
            //------------------------------------------------- 
            //Check for parameters
            //------------------------------------------------- 
            if (m_PeerNameRecord.PeerName == null)
            {
                throw new ArgumentNullException(SR.GetString(SR.Pnrp_InvalidPeerName));
            } 

            //------------------------------------------------- 
            //If the current PeerName associated with the 
            //current registration is not the same as the
            //PeerName given now - throw 
            //-------------------------------------------------
            if (!m_RegisteredPeerName.Equals(m_PeerNameRecord.PeerName))
            {
                throw new InvalidOperationException(SR.GetString(SR.Pnrp_CantChangePeerNameAfterRegistration)); 
            }
 
            //------------------------------------------ 
            //If auto address selection is turned off
            //then there must be atleast Data or Endpoints 
            //specified
            //------------------------------------------
            if (!m_UseAutoEndPointSelection)
            { 
                if ((EndPointCollection.Count == 0) ||
                     (Data == null || Data.Length <= 0)) 
                { 
                    throw new PeerToPeerException(SR.GetString(SR.Pnrp_BlobOrEndpointListNeeded));
                } 
            }

            //-------------------------------------------------
            //Demand for the Unrestricted Pnrp Permission 
            //-------------------------------------------------
            PnrpPermission.UnrestrictedPnrpPermission.Demand(); 
 
            //----------------------------------------------------------------
            //Log trace info 
            //---------------------------------------------------------------
            if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Information))
            {
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Update() is called with the following Info"); 
                m_PeerNameRecord.TracePeerNameRecord();
            } 
 
            PEER_PNRP_REGISTRATION_INFO regInfo = new PEER_PNRP_REGISTRATION_INFO();
            //------------------------------------------------- 
            //Set data
            //-------------------------------------------------
            if (m_PeerNameRecord.Data != null)
            { 
                regInfo.payLoad.cbPayload = (UInt32)m_PeerNameRecord.Data.Length;
                //Marshal.All 
                //regInfo.payLoad.pbPayload = m_PeerNameRecord.Data; 
                GCHandle handle = GCHandle.Alloc(m_PeerNameRecord.Data, GCHandleType.Pinned);
                regInfo.payLoad.pbPayload = handle.AddrOfPinnedObject(); //m_PeerNameRecord.Data; 
                handle.Free();
            };
            //-------------------------------------------------
            //Set comment 
            //-------------------------------------------------
            if (m_PeerNameRecord.Comment != null && m_PeerNameRecord.Comment.Length > 0) 
            { 
                regInfo.pwszComment = m_PeerNameRecord.Comment;
            } 
            //-------------------------------------------------
            //Set cloud name
            //-------------------------------------------------
            regInfo.pwszCloudName = null; 
            if (m_Cloud != null)
            { 
                regInfo.pwszCloudName = m_Cloud.InternalName; 
            }
 
            if (m_PeerNameRecord.EndPointCollection.Count == 0)
            {
                //-------------------------------------------------
                //Set port only if the addresses are null 
                //and then set the selection to auto addresses
                //------------------------------------------------- 
                regInfo.wport = (ushort)m_Port; 
                regInfo.cAddresses = PEER_PNRP_AUTO_ADDRESSES;
 
                int result = UnsafeP2PNativeMethods.PeerPnrpUpdateRegistration(m_RegistrationHandle, ref regInfo);
                if (result != 0)
                {
                    throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotRegisterPeerName), result); 
                }
                return; 
            } 
            else
            { 
                //-------------------------------------------------
                //Set the Endpoint List
                //-------------------------------------------------
                int numAddresses = m_PeerNameRecord.EndPointCollection.Count; 
                int cbRequriedBytes = numAddresses * Marshal.SizeOf(typeof(IntPtr));
                IntPtr pSocketAddrList = Marshal.AllocHGlobal(cbRequriedBytes); 
                GCHandle[] GCHandles = new GCHandle[numAddresses]; 
                try
                { 
                    unsafe
                    {
                        IntPtr* pAddress = (IntPtr*)pSocketAddrList;
                        for (int i = 0; i < m_PeerNameRecord.EndPointCollection.Count; i++) 
                        {
                            byte[] sockaddr = SystemNetHelpers.SOCKADDRFromIPEndPoint(m_PeerNameRecord.EndPointCollection[i]); 
                            GCHandles[i] = GCHandle.Alloc(sockaddr, GCHandleType.Pinned); 
                            IntPtr psockAddr = GCHandles[i].AddrOfPinnedObject();
                            pAddress[i] = psockAddr; 
                        }
                    }
                    regInfo.ArrayOfSOCKADDRIN6Pointers = pSocketAddrList;
                    regInfo.cAddresses = (UInt32)numAddresses; 
                    int result = UnsafeP2PNativeMethods.PeerPnrpUpdateRegistration(m_RegistrationHandle, ref regInfo);
                    if (result != 0) 
                    { 
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotRegisterPeerName), result);
                    } 
                }
                finally
                {
                    if (pSocketAddrList != IntPtr.Zero) 
                        Marshal.FreeHGlobal(pSocketAddrList);
 
                    for (int i = 0; i < GCHandles.Length; i++) 
                    {
                        if (GCHandles[i].IsAllocated) 
                            GCHandles[i].Free();
                    }
                }
 
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Update of existing registration is successful. The handle is {0}", m_RegistrationHandle.DangerousGetHandle());
            } 
 
        }
 
        /// 
        /// Unregister the existing registration.
        /// 
        //  
        // 
        //  
        //  
        // 
        //  
        [System.Security.SecurityCritical]
        public void Stop()
        {
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); 

            //------------------------------------------------- 
            //No registration happened previously - throw 
            //-------------------------------------------------
 			if(m_RegistrationHandle.IsInvalid || m_RegistrationHandle.IsClosed) 
			{
				throw new InvalidOperationException(SR.GetString(SR.Pnrp_NoRegistrationFound));
			}
 
            //-------------------------------------------------
            //Demand for the Unrestricted Pnrp Permission 
            //------------------------------------------------- 
            PnrpPermission.UnrestrictedPnrpPermission.Demand();
 
            m_RegistrationHandle.Dispose();

 			m_PeerNameRecord = new PeerNameRecord();
 
            m_RegisteredPeerName = null;
			 
            m_IsRegistered = false; 
        }
 
        private bool m_Disposed;
        /// 
        /// Dispose explicit
        ///  
        public void Dispose()
        { 
            Dispose(true); 
            GC.SuppressFinalize(this);
        } 
        /// 
        /// Dispose impl
        /// 
        ///  Whether we are disposing(true) or the system is disposing (false) 
        protected virtual void Dispose(bool disposing)
        { 
            if (!m_Disposed) 
            {
                try 
                {
                    Stop();
                }
                catch (ObjectDisposedException) 
                {
                } 
                catch (InvalidOperationException) 
                {
                } 
                //rest throw since we don't expect any other exceptions
            }
            m_Disposed = true;
        } 

 
        ///  
        /// Constructor to enable serialization
        ///  
        /// 
        /// 
        protected PeerNameRegistration(SerializationInfo info, StreamingContext context)
        { 
            m_Port = info.GetInt32("_Port");
            m_UseAutoEndPointSelection = info.GetBoolean("_UseAutoEndPointSelection"); 
            m_Cloud = info.GetValue("_Cloud", typeof(Cloud)) as Cloud; 
            m_PeerNameRecord = info.GetValue("_PeerNameRecord", typeof(PeerNameRecord)) as PeerNameRecord;
        } 


        // 
        //  
        // 
        [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Justification = "System.Net.dll is still using pre-v4 security model and needs this demand")] 
        [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("_Port", m_Port); 
            info.AddValue("_UseAutoEndPointSelection", m_UseAutoEndPointSelection);
            info.AddValue("_Cloud", m_Cloud); 
            info.AddValue("_PeerNameRecord", m_PeerNameRecord); 
        }
 

    }
}
 

 

// 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.Collections.Generic;
    using System.Text; 
    using System.Security.Permissions;
    using System.Runtime.InteropServices;
    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis; 
    using System.Runtime.Serialization;
 
 
    /// 
    /// The PeerNameRegistration class registers a peer name record 
    /// 
    [Serializable]
    public class PeerNameRegistration : IDisposable, ISerializable
    { 
        //-----------------------------------------------------------------------
        //Native constant to indicate auto address selection 
        //----------------------------------------------------------------------- 
        private const UInt32 PEER_PNRP_AUTO_ADDRESSES  =  unchecked((UInt32)(-1));
 

        //------------------------------------------------------------------------
        //Internal PeerNameRecord to hold information.
        //----------------------------------------------------------------------- 
        private PeerNameRecord m_PeerNameRecord = new PeerNameRecord();
        private int m_Port; 
        private Cloud m_Cloud; 

        //------------------------------------------------------------------------ 
        //Flag to keep whether We registered or not
        //------------------------------------------------------------------------
        private bool m_IsRegistered;
 
        //-----------------------------------------------------------------------
        //The native handle to the registration 
        //------------------------------------------------------------------------ 
        private SafePeerNameUnregister m_RegistrationHandle;
 
        //-----------------------------------------------------------------------
        //PeerName that is associated with this registation
        //If they update the PeerName in the PeerNameRecord and call update we
        //should throw 
        //-----------------------------------------------------------------------
        private PeerName m_RegisteredPeerName; 
 
        //-----------------------------------------------------------------------
        //We should support the scenario where you publish just the data 
        //but no end points. This flag tells us whether to use auto endpoint selection
        //or not
        //------------------------------------------------------------------------
        private bool m_UseAutoEndPointSelection = true; 

        static PeerNameRegistration() 
        { 
            //-------------------------------------------------
            //Check for the availability of the simpler PNRP APIs 
            //-------------------------------------------------
            if (!PeerToPeerOSHelper.SupportsP2P)
            {
                throw new PlatformNotSupportedException(SR.GetString(SR.P2P_NotAvailable)); 
            }
        } 
 
        /// 
        /// Empty constructor so that users can populate the 
        /// information later
        /// 
        public PeerNameRegistration()
        { 
        }
 
        ///  
        /// This constuctor popuates the PeerNameRecord and registers automatically
        /// Registers in all clouds with automatic address selection 
        /// 
        /// PeerName to register
        /// Port to register on
        public PeerNameRegistration(PeerName name, int port) : this(name, port, null) 
        {
        } 
        ///  
        /// This constuctor popuates the PeerNameRecord and registers automatically
        /// Registers with automatic address selection within the cloud 
        /// 
        /// PeerName to register
        /// Port to register on
        /// A specific cloud to regster in/// 
        public PeerNameRegistration(PeerName name, int port, Cloud cloud)
        { 
            if (name == null) 
            {
                throw new ArgumentNullException("name"); 
            }
            if (cloud == null)
            {
                cloud = Cloud.Available; 
            }
            if (port < IPEndPoint.MinPort || port > IPEndPoint.MaxPort) 
            { 
                throw new ArgumentOutOfRangeException("port", SR.GetString(SR.Pnrp_PortOutOfRange));
            } 


            m_PeerNameRecord.PeerName = name;
            m_Port = port; 
            m_Cloud = cloud;
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Created a PeerNameRegistration with PeerName {0}, Port {1}, Cloud {2} - Proceeding to register", name, port, cloud); 
        } 

        ///  
        /// Property accessor to examine/change and perhaps call
        /// Update() to update the registration information
        /// 
        internal PeerNameRecord PeerNameRecord 
        {
            get 
            { 
                if (m_Disposed)
                { 
                    throw new ObjectDisposedException(this.GetType().FullName);
                }
                return m_PeerNameRecord;
            } 
        }
 
        public int Port 
        {
            get 
            {
                return m_Port;
            }
            set 
            {
                if (value < IPEndPoint.MinPort || value > IPEndPoint.MaxPort) 
                { 
                    throw new ArgumentOutOfRangeException("port", SR.GetString(SR.Pnrp_PortOutOfRange));
                } 

                m_Port = value;
            }
        } 

 
        public PeerName PeerName 
        {
            get 
            {
                return m_PeerNameRecord.PeerName;
            }
            set 
            {
 
                m_PeerNameRecord.PeerName = value; 

            } 
        }

        public IPEndPointCollection EndPointCollection
        { 
            get
            { 
                return m_PeerNameRecord.EndPointCollection; 
            }
        } 

        public Cloud Cloud
        {
            get 
            {
                return m_Cloud; 
            } 
            set
            { 
                m_Cloud = value;
            }
        }
 
        public string Comment
        { 
            get 
            {
                return m_PeerNameRecord.Comment; 
            }
            set
            {
                m_PeerNameRecord.Comment = value; 
            }
        } 
        public byte[] Data 
        {
            get 
            {
                return m_PeerNameRecord.Data;
            }
            set 
            {
                m_PeerNameRecord.Data = value; 
            } 
        }
 
        public bool UseAutoEndPointSelection
        {
            get
            { 
                return m_UseAutoEndPointSelection;
            } 
            set 
            {
                m_UseAutoEndPointSelection = value; 
            }
        }

        ///  
        /// Return the flag to indicate whether we
        /// registered or not 
        ///  
        /// 
        public bool IsRegistered() 
        {
            if (m_Disposed)
            {
                throw new ObjectDisposedException(this.GetType().FullName); 
            }
 
            //------------------------------------------------- 
            //Demand for the Unrestricted Pnrp Permission
            //------------------------------------------------- 
            PnrpPermission.UnrestrictedPnrpPermission.Demand();

            return m_IsRegistered;
        } 

        ///  
        /// This method is called if empty constructor is used and the 
        /// information in the PeerNameRecord is set. Register needs to
        /// be called since we did not automatically register through the 
        /// constructor
        /// 
        // 
        //  
        // 
        [System.Security.SecurityCritical] 
        public void Start() 
        {
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); 

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Proceeding to register through the Register method()");
            InternalRegister();
        } 

        ///  
        /// This is where the real registration happens 
        /// 
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        [System.Security.SecurityCritical] 
        private void InternalRegister() 
        {
            //------------------------------------------ 
            //If we already registered, get out this place
            //------------------------------------------
            if (m_IsRegistered)
            { 
                throw new PeerToPeerException(SR.GetString(SR.Pnrp_UseUpdateInsteadOfRegister));
            } 
 
            //------------------------------------------
            //Make sure you have the required info 
            //------------------------------------------
            if (m_PeerNameRecord.PeerName == null)
            {
                throw new ArgumentNullException("PeerName"); 
            }
 
            //------------------------------------------ 
            //If auto address selection is turned off
            //then there must be atleast Data or Endpoints 
            //specified
            //------------------------------------------
            if (!m_UseAutoEndPointSelection)
            { 
                if ((EndPointCollection.Count == 0) &&
                     (Data == null || Data.Length <= 0)) 
                { 
                    throw new PeerToPeerException(SR.GetString(SR.Pnrp_BlobOrEndpointListNeeded));
                } 
            }


            //------------------------------------------------- 
            //Demand for the Unrestricted Pnrp Permission
            //------------------------------------------------- 
            PnrpPermission.UnrestrictedPnrpPermission.Demand(); 

            //--------------------------------------------------------------- 
            //No perf hit here, real native call happens only one time if it
            //did not already happen
            //----------------------------------------------------------------
            UnsafeP2PNativeMethods.PnrpStartup(); 

            //---------------------------------------------------------------- 
            //Log trace info 
            //---------------------------------------------------------------
            if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Information)) 
            {
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "InternalRegister() is called with the following Info");
                m_PeerNameRecord.TracePeerNameRecord();
            } 

            PEER_PNRP_REGISTRATION_INFO regInfo = new PEER_PNRP_REGISTRATION_INFO(); 
            GCHandle handle; 
            //-------------------------------------------------
            //Set data 
            //-------------------------------------------------
            if (m_PeerNameRecord.Data != null)
            {
                regInfo.payLoad.cbPayload = (UInt32)m_PeerNameRecord.Data.Length; 
                handle = GCHandle.Alloc(m_PeerNameRecord.Data, GCHandleType.Pinned);
                regInfo.payLoad.pbPayload = handle.AddrOfPinnedObject(); //m_PeerNameRecord.Data; 
            } 
            else
            { 
                handle = new GCHandle();
            }
            //-------------------------------------------------
            //Set comment 
            //-------------------------------------------------
            if (m_PeerNameRecord.Comment != null && m_PeerNameRecord.Comment.Length > 0) 
            { 
                regInfo.pwszComment = m_PeerNameRecord.Comment;
            } 
            //-------------------------------------------------
            //Set cloud name
            //-------------------------------------------------
            if (m_Cloud != null) 
            {
                regInfo.pwszCloudName = m_Cloud.InternalName; 
            } 
            try
            { 
                if (m_PeerNameRecord.EndPointCollection.Count == 0)
                {
                    //-------------------------------------------------
                    //Set port only if the addresses are null 
                    //and then set the selection to auto addresses
                    //------------------------------------------------- 
                    regInfo.wport = (ushort)m_Port; 

                    if(m_UseAutoEndPointSelection) 
                        regInfo.cAddresses = PEER_PNRP_AUTO_ADDRESSES;

                    //-------------------------------------------------
                    //Call the native API to register 
                    //-------------------------------------------------
                    int result = UnsafeP2PNativeMethods.PeerPnrpRegister(m_PeerNameRecord.PeerName.ToString(), 
                                        ref regInfo, 
                                        out m_RegistrationHandle);
                    if (result != 0) 
                    {
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotRegisterPeerName), result);
                    }
                } 
                else
                { 
                    //------------------------------------------------- 
                    //Set the Endpoint List
                    //------------------------------------------------- 
                    int numAddresses = m_PeerNameRecord.EndPointCollection.Count;
                    int cbRequriedBytes = numAddresses * Marshal.SizeOf(typeof(IntPtr));
                    IntPtr pSocketAddrList = Marshal.AllocHGlobal(cbRequriedBytes);
                    GCHandle[] GCHandles = new GCHandle[numAddresses]; 
                    try
                    { 
                        unsafe 
                        {
                            IntPtr* pAddress = (IntPtr*)pSocketAddrList; 
                            for (int i = 0; i < m_PeerNameRecord.EndPointCollection.Count; i++)
                            {
                                byte[] sockaddr = SystemNetHelpers.SOCKADDRFromIPEndPoint(m_PeerNameRecord.EndPointCollection[i]);
                                GCHandles[i] = GCHandle.Alloc(sockaddr, GCHandleType.Pinned); 
                                IntPtr psockAddr = GCHandles[i].AddrOfPinnedObject();
                                pAddress[i] = psockAddr; 
                            } 
                        }
                        regInfo.ArrayOfSOCKADDRIN6Pointers = pSocketAddrList; 
                        regInfo.cAddresses = (UInt32)numAddresses;
                        int result = UnsafeP2PNativeMethods.PeerPnrpRegister(m_PeerNameRecord.PeerName.ToString(),
                                            ref regInfo,
                                            out m_RegistrationHandle); 
                        if (result != 0)
                        { 
                            throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotRegisterPeerName), result); 
                        }
                    } 
                    finally
                    {
                        if (pSocketAddrList != IntPtr.Zero)
                            Marshal.FreeHGlobal(pSocketAddrList); 

                        for (int i = 0; i < GCHandles.Length; i++) 
                        { 
                            if (GCHandles[i].IsAllocated)
                                GCHandles[i].Free(); 
                        }
                    }
                }
            } 
            finally
            { 
                if (handle.IsAllocated) 
                {
                    handle.Free(); 
                }

            }
            m_RegisteredPeerName = m_PeerNameRecord.PeerName; 
            m_IsRegistered = true;
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Registration is successful. The handle is {0}", m_RegistrationHandle.DangerousGetHandle()); 
        } 

        ///  
        /// Update is called if an existing registration needs to be updated
        /// 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        [System.Security.SecurityCritical]
        public void Update() 
        {
            //-------------------------------------------------
            //Check for the dead object
            //------------------------------------------------- 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
            //------------------------------------------------- 
            //If there is no existing registration to update
            //get out 
            //-------------------------------------------------
            if (!IsRegistered())
            {
                throw new InvalidOperationException(SR.GetString(SR.Pnrp_CallRegisterBeforeUpdate)); 
            }
 
            //------------------------------------------------- 
            //Check for parameters
            //------------------------------------------------- 
            if (m_PeerNameRecord.PeerName == null)
            {
                throw new ArgumentNullException(SR.GetString(SR.Pnrp_InvalidPeerName));
            } 

            //------------------------------------------------- 
            //If the current PeerName associated with the 
            //current registration is not the same as the
            //PeerName given now - throw 
            //-------------------------------------------------
            if (!m_RegisteredPeerName.Equals(m_PeerNameRecord.PeerName))
            {
                throw new InvalidOperationException(SR.GetString(SR.Pnrp_CantChangePeerNameAfterRegistration)); 
            }
 
            //------------------------------------------ 
            //If auto address selection is turned off
            //then there must be atleast Data or Endpoints 
            //specified
            //------------------------------------------
            if (!m_UseAutoEndPointSelection)
            { 
                if ((EndPointCollection.Count == 0) ||
                     (Data == null || Data.Length <= 0)) 
                { 
                    throw new PeerToPeerException(SR.GetString(SR.Pnrp_BlobOrEndpointListNeeded));
                } 
            }

            //-------------------------------------------------
            //Demand for the Unrestricted Pnrp Permission 
            //-------------------------------------------------
            PnrpPermission.UnrestrictedPnrpPermission.Demand(); 
 
            //----------------------------------------------------------------
            //Log trace info 
            //---------------------------------------------------------------
            if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Information))
            {
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Update() is called with the following Info"); 
                m_PeerNameRecord.TracePeerNameRecord();
            } 
 
            PEER_PNRP_REGISTRATION_INFO regInfo = new PEER_PNRP_REGISTRATION_INFO();
            //------------------------------------------------- 
            //Set data
            //-------------------------------------------------
            if (m_PeerNameRecord.Data != null)
            { 
                regInfo.payLoad.cbPayload = (UInt32)m_PeerNameRecord.Data.Length;
                //Marshal.All 
                //regInfo.payLoad.pbPayload = m_PeerNameRecord.Data; 
                GCHandle handle = GCHandle.Alloc(m_PeerNameRecord.Data, GCHandleType.Pinned);
                regInfo.payLoad.pbPayload = handle.AddrOfPinnedObject(); //m_PeerNameRecord.Data; 
                handle.Free();
            };
            //-------------------------------------------------
            //Set comment 
            //-------------------------------------------------
            if (m_PeerNameRecord.Comment != null && m_PeerNameRecord.Comment.Length > 0) 
            { 
                regInfo.pwszComment = m_PeerNameRecord.Comment;
            } 
            //-------------------------------------------------
            //Set cloud name
            //-------------------------------------------------
            regInfo.pwszCloudName = null; 
            if (m_Cloud != null)
            { 
                regInfo.pwszCloudName = m_Cloud.InternalName; 
            }
 
            if (m_PeerNameRecord.EndPointCollection.Count == 0)
            {
                //-------------------------------------------------
                //Set port only if the addresses are null 
                //and then set the selection to auto addresses
                //------------------------------------------------- 
                regInfo.wport = (ushort)m_Port; 
                regInfo.cAddresses = PEER_PNRP_AUTO_ADDRESSES;
 
                int result = UnsafeP2PNativeMethods.PeerPnrpUpdateRegistration(m_RegistrationHandle, ref regInfo);
                if (result != 0)
                {
                    throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotRegisterPeerName), result); 
                }
                return; 
            } 
            else
            { 
                //-------------------------------------------------
                //Set the Endpoint List
                //-------------------------------------------------
                int numAddresses = m_PeerNameRecord.EndPointCollection.Count; 
                int cbRequriedBytes = numAddresses * Marshal.SizeOf(typeof(IntPtr));
                IntPtr pSocketAddrList = Marshal.AllocHGlobal(cbRequriedBytes); 
                GCHandle[] GCHandles = new GCHandle[numAddresses]; 
                try
                { 
                    unsafe
                    {
                        IntPtr* pAddress = (IntPtr*)pSocketAddrList;
                        for (int i = 0; i < m_PeerNameRecord.EndPointCollection.Count; i++) 
                        {
                            byte[] sockaddr = SystemNetHelpers.SOCKADDRFromIPEndPoint(m_PeerNameRecord.EndPointCollection[i]); 
                            GCHandles[i] = GCHandle.Alloc(sockaddr, GCHandleType.Pinned); 
                            IntPtr psockAddr = GCHandles[i].AddrOfPinnedObject();
                            pAddress[i] = psockAddr; 
                        }
                    }
                    regInfo.ArrayOfSOCKADDRIN6Pointers = pSocketAddrList;
                    regInfo.cAddresses = (UInt32)numAddresses; 
                    int result = UnsafeP2PNativeMethods.PeerPnrpUpdateRegistration(m_RegistrationHandle, ref regInfo);
                    if (result != 0) 
                    { 
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotRegisterPeerName), result);
                    } 
                }
                finally
                {
                    if (pSocketAddrList != IntPtr.Zero) 
                        Marshal.FreeHGlobal(pSocketAddrList);
 
                    for (int i = 0; i < GCHandles.Length; i++) 
                    {
                        if (GCHandles[i].IsAllocated) 
                            GCHandles[i].Free();
                    }
                }
 
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Update of existing registration is successful. The handle is {0}", m_RegistrationHandle.DangerousGetHandle());
            } 
 
        }
 
        /// 
        /// Unregister the existing registration.
        /// 
        //  
        // 
        //  
        //  
        // 
        //  
        [System.Security.SecurityCritical]
        public void Stop()
        {
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); 

            //------------------------------------------------- 
            //No registration happened previously - throw 
            //-------------------------------------------------
 			if(m_RegistrationHandle.IsInvalid || m_RegistrationHandle.IsClosed) 
			{
				throw new InvalidOperationException(SR.GetString(SR.Pnrp_NoRegistrationFound));
			}
 
            //-------------------------------------------------
            //Demand for the Unrestricted Pnrp Permission 
            //------------------------------------------------- 
            PnrpPermission.UnrestrictedPnrpPermission.Demand();
 
            m_RegistrationHandle.Dispose();

 			m_PeerNameRecord = new PeerNameRecord();
 
            m_RegisteredPeerName = null;
			 
            m_IsRegistered = false; 
        }
 
        private bool m_Disposed;
        /// 
        /// Dispose explicit
        ///  
        public void Dispose()
        { 
            Dispose(true); 
            GC.SuppressFinalize(this);
        } 
        /// 
        /// Dispose impl
        /// 
        ///  Whether we are disposing(true) or the system is disposing (false) 
        protected virtual void Dispose(bool disposing)
        { 
            if (!m_Disposed) 
            {
                try 
                {
                    Stop();
                }
                catch (ObjectDisposedException) 
                {
                } 
                catch (InvalidOperationException) 
                {
                } 
                //rest throw since we don't expect any other exceptions
            }
            m_Disposed = true;
        } 

 
        ///  
        /// Constructor to enable serialization
        ///  
        /// 
        /// 
        protected PeerNameRegistration(SerializationInfo info, StreamingContext context)
        { 
            m_Port = info.GetInt32("_Port");
            m_UseAutoEndPointSelection = info.GetBoolean("_UseAutoEndPointSelection"); 
            m_Cloud = info.GetValue("_Cloud", typeof(Cloud)) as Cloud; 
            m_PeerNameRecord = info.GetValue("_PeerNameRecord", typeof(PeerNameRecord)) as PeerNameRecord;
        } 


        // 
        //  
        // 
        [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Justification = "System.Net.dll is still using pre-v4 security model and needs this demand")] 
        [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("_Port", m_Port); 
            info.AddValue("_UseAutoEndPointSelection", m_UseAutoEndPointSelection);
            info.AddValue("_Cloud", m_Cloud); 
            info.AddValue("_PeerNameRecord", m_PeerNameRecord); 
        }
 

    }
}
 

 

// 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