PeerNearMe.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / SystemNet / Net / PeerToPeer / Collaboration / PeerNearMe.cs / 2 / PeerNearMe.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 
namespace System.Net.PeerToPeer.Collaboration
{ 
    using System; 
    using System.Collections;
    using System.Collections.Generic; 
    using System.Collections.ObjectModel;
    using System.Runtime.InteropServices;
    using System.Threading;
    using System.ComponentModel; 
    using System.Text;
    using System.Net.Mail; 
    using System.Diagnostics; 
    using System.Runtime.Serialization;
    using System.Security.Permissions; 

    /// 
    /// This is the event args class we give back when
    /// we have a peer near me change event triggered by native 
    /// 
    public class PeerNearMeChangedEventArgs : EventArgs 
    { 
        private PeerNearMe m_peerNearMe;
        private PeerChangeType m_peerChangeType; 

        internal PeerNearMeChangedEventArgs(PeerNearMe peerNearMe, PeerChangeType peerChangeType)
        {
            m_peerNearMe = peerNearMe; 
            m_peerChangeType = peerChangeType;
        } 
 
        public PeerNearMe PeerNearMe
        { 
            get{
                return m_peerNearMe;
            }
        } 

        public PeerChangeType PeerChangeType 
        { 
            get{
                return m_peerChangeType; 
            }
        }
    }
 
    /// 
    /// This class contains the functionality of the people near me concept 
    /// in windows collaboration i.e. people on the same subnet 
    /// 
    [Serializable] 
    public class PeerNearMe : Peer, IEquatable, ISerializable
    {
        private string m_nickname;
        private Guid m_id; 

        //  
        //  
        // 
        [System.Security.SecurityCritical] 
        static PeerNearMe(){
            CollaborationHelperFunctions.Initialize();
        }
 
        public PeerNearMe(){
            OnRefreshDataCompletedDelegate = new SendOrPostCallback(RefreshDataCompletedWaitCallback); 
        } 

        ///  
        /// Constructor to enable serialization
        /// 
        protected PeerNearMe(SerializationInfo serializationInfo, StreamingContext streamingContext)
            :base(serializationInfo, streamingContext) 
        {
            m_id = (Guid) serializationInfo.GetValue("_Id", typeof(Guid)); 
            m_nickname = serializationInfo.GetString("_NickName"); 

            OnRefreshDataCompletedDelegate = new SendOrPostCallback(RefreshDataCompletedWaitCallback); 
        }

        public string Nickname
        { 
            get {
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); 
 
                return m_nickname;
            } 
            internal set {
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);

                m_nickname = value; 
            }
        } 
 
        internal Guid Id
        { 
            get{
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);

                return m_id; 
            }
            set 
            { 
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
                m_id = value;
            }
        }
 
        //
        // Adds this peer to the contact manager 
        // 
        public PeerContact AddToContactManager()
        { 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering AddToContactManager.");
            PeerContact peerContact = null;
            try{
                peerContact = PeerCollaboration.ContactManager.CreateContact(this); 
                PeerCollaboration.ContactManager.AddContact(peerContact);
            } 
            catch (Exception e){ 
                throw new PeerToPeerException(SR.GetString(SR.Collab_AddToContactMgrFailed), (e.InnerException != null ? e.InnerException : e));
            } 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving AddToContactManager.");
            return peerContact;
        }
 
        //
        // Adds this peer to the contact manager 
        // 
        public PeerContact AddToContactManager(string displayName, string nickname, MailAddress emailAddress)
        { 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering AddToContactManager with Display name: {0}" +
                " Nickname: {1} and Email Address: {2}", displayName, nickname, emailAddress);

            PeerContact peerContact = null; 

            try{ 
                peerContact = PeerCollaboration.ContactManager.CreateContact(this); 
                PeerCollaboration.ContactManager.AddContact(peerContact);
            } 
            catch (Exception e){
                throw new PeerToPeerException(SR.GetString(SR.Collab_AddToContactMgrFailed), (e.InnerException != null ? e.InnerException : e));
            }
 
            peerContact.DisplayName = displayName;
            peerContact.Nickname = nickname; 
            peerContact.EmailAddress = emailAddress; 

            try{ 
                PeerCollaboration.ContactManager.UpdateContact(peerContact);
            }
            catch (Exception e){
                throw new PeerToPeerException(SR.GetString(SR.Collab_AddToContactMgrFailed) + " " + SR.GetString(SR.Collab_AddToContactMgrFailedUpdate), (e.InnerException != null ? e.InnerException : e)); 
            }
 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving AddToContactManager."); 
            return peerContact;
        } 

        // 
        // 
        //  
        [System.Security.SecurityCritical]
        public static PeerNearMe CreateFromPeerEndPoint(PeerEndPoint peerEndPoint) 
        { 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering CreateFromPeerEndPoint.");
            CollaborationHelperFunctions.Initialize(); 

            if (peerEndPoint == null)
                throw new ArgumentNullException("peerEndPoint");
            if (peerEndPoint.EndPoint == null) 
                throw new PeerToPeerException(SR.GetString(SR.Collab_NoEndPointInPeerEndPoint));
 
            PeerNearMeCollection peers = PeerCollaboration.GetPeersNearMe(); 
            PeerNearMe peer = null;
 
            foreach (PeerNearMe peerNearMe in peers){
                PeerEndPointCollection peerEndPoints = peerNearMe.PeerEndPoints;
                if ((peerEndPoints != null) && (peerEndPoints.Count != 0) && (peerEndPoints[0].Equals(peerEndPoint)))
                    peer = peerNearMe; 
            }
            if (peer == null){ 
                // 
                // No peer found, throw
                // 
                throw new PeerToPeerException(SR.GetString(SR.Collab_EndPointNotAPeerNearMe));
            }

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving CreateFromPeerEndPoint."); 
            return peer;
        } 
 
        //
        // Checks if we need refreshing of an unsubscribed peer near me 
        //
        internal override void RefreshIfNeeded()
        {
            RefreshData(); 
        }
 
        // 
        // Refresh the endpoint with new data from collab
        // 
        // 
        // 
        // 
        [System.Security.SecurityCritical] 
        public void RefreshData()
        { 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); 
            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
 
            InternalRefreshData(false);
        }

        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        [System.Security.SecurityCritical] 
        internal protected void InternalRefreshData(object state)
        { 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "InternalRefreshEndpointData called.");

            int errorCode = 0;
            bool isAsync = (bool)state; 
            Exception exception = null;
 
            AutoResetEvent refreshedEPDataEvent = new AutoResetEvent(false); 
            SafeCollabEvent safeRefreshedEPDataEvent;
 
            PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION();
            pcer.eventType = PeerCollabEventType.RequestStatusChanged;
            pcer.pInstance = IntPtr.Zero;
 
            //
            // Register to receive status changed event from collab 
            // 
            errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent(
                                                                refreshedEPDataEvent.SafeWaitHandle, 
                                                                1,
                                                                ref pcer,
                                                                out safeRefreshedEPDataEvent);
            if (errorCode != 0){ 
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
                exception = PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_ReqStatusChangedRegFailed), errorCode); 
                if (!isAsync) 
                    throw exception;
            } 

            PeerEndPointCollection peerEndPoints = PeerEndPoints;

            if (peerEndPoints.Count == 0) return; 

            try{ 
            InternalRefreshData(peerEndPoints[0]); 
            }
            catch (Exception e){ 
                if (!isAsync)
                    throw;
                else
                    exception = e; 
            }
 
            // 
            // Wait till all the endpoints are refreshed
            // 
            while (exception == null){
                refreshedEPDataEvent.WaitOne();

                SafeCollabData eventData; 

                errorCode = UnsafeCollabNativeMethods.PeerCollabGetEventData(safeRefreshedEPDataEvent, 
                                                                                    out eventData); 
                if (errorCode != 0){
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetEventData returned with errorcode {0}", errorCode); 
                    exception = PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_RefreshDataFailed), errorCode);
                    if (!isAsync)
                        throw exception;
                    else 
                        break;
                } 
 
                PEER_COLLAB_EVENT_DATA ped = (PEER_COLLAB_EVENT_DATA)Marshal.PtrToStructure(eventData.DangerousGetHandle(),
                                                                                            typeof(PEER_COLLAB_EVENT_DATA)); 

                if (ped.eventType == PeerCollabEventType.RequestStatusChanged){
                    PEER_EVENT_REQUEST_STATUS_CHANGED_DATA statusData = ped.requestStatusChangedData;
 
                    PeerEndPoint peerEndPoint = null;
 
                    if (statusData.pEndPoint != IntPtr.Zero){ 
                        PEER_ENDPOINT pe = (PEER_ENDPOINT)Marshal.PtrToStructure(statusData.pEndPoint, typeof(PEER_ENDPOINT));
                        peerEndPoint = CollaborationHelperFunctions.ConvertPEER_ENDPOINTToPeerEndPoint(pe); 
                    }

                    if (statusData.hrChange < 0){
                        exception = PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_RefreshDataFailed), statusData.hrChange); 
                    }
 
                    if (exception != null){ 
                        //
                        // Throw exception for [....] but call callback for async with exception 
                        //
                        if (!isAsync)
                            throw exception;
                    } 

                    // 
                    // Check if this is our endpoint 
                    //
                    if (PeerEndPoints[0].Equals(peerEndPoint)){ 
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Found endpoint match in Request status changed.");

                        //
                        // For async call the callback and for [....] just return 
                        //
                        if (isAsync){ 
                            RefreshDataCompletedEventArgs args = new 
                                        RefreshDataCompletedEventArgs(  peerEndPoint,
                                                                        null, 
                                                                        false,
                                                                        m_refreshDataAsyncOp.UserSuppliedState);

                            if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Information)){ 
                                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Firing RefreshDataCompleted event with folloding peer endpoint.");
                                peerEndPoint.TracePeerEndPoint(); 
                            } 

                            this.PrepareToRaiseRefreshDataCompletedEvent(m_refreshDataAsyncOp, args); 
                        }

                        break;
                    } 
                }
            } 
 
            //
            // Async case with exception fire callback here 
            // [....] would have already thrown this by now
            //
            if (exception != null){
                RefreshDataCompletedEventArgs args = new 
                            RefreshDataCompletedEventArgs(null,
                                                            exception, 
                                                            false, 
                                                            m_refreshDataAsyncOp.UserSuppliedState);
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Firing RefreshDataCompleted event with exception {0}.", exception); 
                this.PrepareToRaiseRefreshDataCompletedEvent(m_refreshDataAsyncOp, args);
            }

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving InternalRefreshEndpointData."); 
        }
 
        // 
        // Refreshes on endpoint
        // 

        // 
        // 
        //  
        // 
        //  
        //  
        // 
        [System.Security.SecurityCritical] 
        internal static void InternalRefreshData(PeerEndPoint peerEndPoint)
        {
            int errorCode;
            PEER_ENDPOINT pep = new PEER_ENDPOINT(); 
            pep.peerAddress = CollaborationHelperFunctions.ConvertIPEndpointToPEER_ADDRESS(peerEndPoint.EndPoint);
 
            GCHandle pepName = GCHandle.Alloc(peerEndPoint.Name, GCHandleType.Pinned); 
            pep.pwzEndpointName = pepName.AddrOfPinnedObject();
 
            GCHandle peerEP = GCHandle.Alloc(pep, GCHandleType.Pinned);
            IntPtr ptrPeerEP = peerEP.AddrOfPinnedObject();

            try{ 
                errorCode = UnsafeCollabNativeMethods.PeerCollabRefreshEndpointData(ptrPeerEP);
            } 
            finally{ 
                if (pepName.IsAllocated) pepName.Free();
                if (peerEP.IsAllocated) peerEP.Free(); 
            }

            if (errorCode != 0){
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRefreshEndpointData returned with errorcode {0}", errorCode); 
                throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_RefreshDataFailed), errorCode);
            } 
        } 

        #region RefreshEndpoint Async variables 
        AsyncOperation m_refreshDataAsyncOp;
        private object m_refreshDataAsyncOpLock;
        private object RefreshDataAsyncOpLock
        { 
            get{
                if (m_refreshDataAsyncOpLock == null){ 
                    object o = new object(); 
                    Interlocked.CompareExchange(ref m_refreshDataAsyncOpLock, o, null);
                } 
                return m_refreshDataAsyncOpLock;
            }
        }
        SendOrPostCallback OnRefreshDataCompletedDelegate; 
        #endregion
 
        private event EventHandler m_refreshDataCompleted; 
        public event EventHandler RefreshDataCompleted
        { 
            add
            {
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

                m_refreshDataCompleted += value; 
            } 
            remove
            { 
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();

                m_refreshDataCompleted -= value; 
            }
        } 
 
        //
        // Async refresh endpoint data 
        //
        // 
        // 
        //  
        [System.Security.SecurityCritical]
        public void RefreshDataAsync(object userToken) 
        { 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

            if (userToken == null)
                throw new ArgumentNullException("userToken");
 
            lock (RefreshDataAsyncOpLock){
                if (m_refreshDataAsyncOp != null) 
                    throw new PeerToPeerException(SR.GetString(SR.Collab_DuplicateRefreshAsync)); 
                m_refreshDataAsyncOp = AsyncOperationManager.CreateOperation(userToken);
            } 
            ThreadPool.QueueUserWorkItem(new WaitCallback(InternalRefreshData), true);

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving RefreshDataAsync().");
        } 

        protected void OnRefreshDataCompleted(RefreshDataCompletedEventArgs e) 
        { 
            EventHandler handlerCopy = m_refreshDataCompleted;
 
            if (handlerCopy != null){
                handlerCopy(this, e);
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the refresh endpoint completed event callback.");
            } 
        }
 
        void RefreshDataCompletedWaitCallback(object operationState) 
        {
            m_refreshDataAsyncOp = null; 
            OnRefreshDataCompleted((RefreshDataCompletedEventArgs)operationState);
        }

        internal void PrepareToRaiseRefreshDataCompletedEvent(AsyncOperation asyncOP, RefreshDataCompletedEventArgs args) 
        {
            asyncOP.PostOperationCompleted(OnRefreshDataCompletedDelegate, args); 
        } 

        private static event EventHandler s_peerNearMeChanged; 
        public static event EventHandler PeerNearMeChanged
        {
            // 
            //  
            // 
            //  
            [System.Security.SecurityCritical] 
            add
            { 
                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
                CollaborationHelperFunctions.Initialize();

                AddPeerNearMeChanged(value); 
            }
            //  
            //  
            // 
            //  
            [System.Security.SecurityCritical]
            remove
            {
                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 
                CollaborationHelperFunctions.Initialize();
 
                RemovePeerNearMeChanged(value); 
            }
        } 

        #region PeerNearMe changed event variables
        private static object s_lockPNMChangedEvent;
        private static object LockPNMChangedEvent 
        {
            get{ 
                if (s_lockPNMChangedEvent == null){ 
                    object o = new object();
                    Interlocked.CompareExchange(ref s_lockPNMChangedEvent, o, null); 
                }
                return s_lockPNMChangedEvent;
            }
        } 
        private static RegisteredWaitHandle s_registeredPNMWaitHandle;
        private static AutoResetEvent s_peerNearMeChangedEvent; 
        private static SafeCollabEvent s_safePeerNearMeChangedEvent; 
        #endregion
 
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        [System.Security.SecurityCritical]
        private static void AddPeerNearMeChanged(EventHandler cb) 
        {
            //
            // Register a wait handle if one has not been registered already
            // 

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering AddPeerNearMeChanged()."); 
 
            lock (LockPNMChangedEvent){
                if (s_peerNearMeChanged == null){ 

                    s_peerNearMeChangedEvent = new AutoResetEvent(false);

                    // 
                    // Register callback with a wait handle
                    // 
 
                    s_registeredPNMWaitHandle = ThreadPool.RegisterWaitForSingleObject(s_peerNearMeChangedEvent, //Event that triggers the callback
                                            new WaitOrTimerCallback(PeerNearMeChangedCallback), //callback to be called 
                                            null, //state to be passed
                                            -1,   //Timeout - aplicable only for timers
                                            false //call us everytime the event is set
                                            ); 
                    PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION();
                    pcer.eventType = PeerCollabEventType.PeopleNearMeChanged; 
                    pcer.pInstance = IntPtr.Zero; 

                    // 
                    // Register event with collab
                    //

                    int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent( 
                                                                        s_peerNearMeChangedEvent.SafeWaitHandle,
                                                                        1, 
                                                                        ref pcer, 
                                                                        out s_safePeerNearMeChangedEvent);
                    if (errorCode != 0){ 
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_PeerNearMeChangedRegFailed), errorCode);
                    }
                } 
                s_peerNearMeChanged += cb;
            } 
 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddPeerNearMeChanged() successful.");
        } 

        // 
        // 
        //  
        // 
        [System.Security.SecurityCritical] 
        private static void RemovePeerNearMeChanged(EventHandler cb) 
        {
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemovePeerNearMeChanged() called."); 
            lock (LockPNMChangedEvent){
                s_peerNearMeChanged -= cb;
                if (s_peerNearMeChanged == null){
                    CollaborationHelperFunctions.CleanEventVars(ref s_registeredPNMWaitHandle, 
                                                                ref s_safePeerNearMeChangedEvent,
                                                                ref s_peerNearMeChangedEvent); 
 
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean PeerNearMeChanged variables successful.");
                } 
            }
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemovePeerNearMeChanged() successful.");
        }
 
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        [System.Security.SecurityCritical] 
        private static void PeerNearMeChangedCallback(object state, bool timedOut)
        { 
            SafeCollabData eventData = null;
            int errorCode = 0;

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "PeerNearMeChangedCallback() called."); 

            while (true){ 
                PeerNearMeChangedEventArgs peerNearMeChangedArgs = null; 

                // 
                // Get the event data for the fired event
                //

                try{ 
                    lock (LockPNMChangedEvent){
                        if (s_safePeerNearMeChangedEvent.IsInvalid) return; 
                        errorCode = UnsafeCollabNativeMethods.PeerCollabGetEventData(s_safePeerNearMeChangedEvent, 
                                                                                     out eventData);
                    } 
                    if (errorCode == UnsafeCollabReturnCodes.PEER_S_NO_EVENT_DATA)
                        break;
                    else if (errorCode != 0){
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetEventData returned with errorcode {0}", errorCode); 
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetPeerNearMeChangedDataFailed), errorCode);
                    } 
 
                    PEER_COLLAB_EVENT_DATA ped = (PEER_COLLAB_EVENT_DATA)Marshal.PtrToStructure(eventData.DangerousGetHandle(),
                                                                                                typeof(PEER_COLLAB_EVENT_DATA)); 
                    if (ped.eventType == PeerCollabEventType.PeopleNearMeChanged){
                        PEER_EVENT_PEOPLE_NEAR_ME_CHANGED_DATA pnmData = ped.peopleNearMeChangedData;
                        PeerNearMe peerNearMe = null;
                        if (pnmData.pPeopleNearMe != IntPtr.Zero){ 
                            PEER_PEOPLE_NEAR_ME pnm = (PEER_PEOPLE_NEAR_ME)Marshal.PtrToStructure(pnmData.pPeopleNearMe, typeof(PEER_PEOPLE_NEAR_ME));
                            peerNearMe = CollaborationHelperFunctions.PEER_PEOPLE_NEAR_METoPeerNearMe(pnm); 
                        } 

                        peerNearMeChangedArgs = new PeerNearMeChangedEventArgs(peerNearMe, pnmData.changeType); 
                    }
                }
                finally{
                    if (eventData != null) eventData.Dispose(); 
                }
 
                // 
                // Fire the callback with the marshalled event args data
                // 

                EventHandler handlerCopy = s_peerNearMeChanged;

                if ((peerNearMeChangedArgs != null) && (handlerCopy != null)){ 
                    handlerCopy(null, peerNearMeChangedArgs);
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the peer near me changed event callback."); 
                } 
            }
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving PeerNearMeChangedCallback()."); 
        }

        // 
        //  
        // 
        [System.Security.SecurityCritical] 
        public override PeerInvitationResponse Invite(PeerApplication applicationToInvite, string message, 
                                                      byte[] invitationData)
        { 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);

            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
 
            if (applicationToInvite == null)
                throw new ArgumentNullException("applicationToInvite"); 
            if (applicationToInvite.Id == Guid.Empty) 
                throw new PeerToPeerException(SR.GetString(SR.Collab_EmptyGuidError));
 
            //
            // We need at least one endpoint to send invitation to
            //
            PeerEndPointCollection peerEndPoints = PeerEndPoints; 

            if ((peerEndPoints == null) || (peerEndPoints.Count == 0)) 
                throw new PeerToPeerException(SR.GetString(SR.Collab_NoEndpointFound)); 

            PeerEndPoint peerEndPoint = PeerEndPoints[0]; 

            PeerInvitationResponse response = InternalInviteEndPoint(applicationToInvite.Id, message, invitationData,
                                                                     peerEndPoint, null);
 
            // throw an exception if the response type is ERROR
            CollaborationHelperFunctions.ThrowIfInvitationResponseInvalid(response); 
            return response; 
        }
 
        // 
        // 
        // 
        //  
        [System.Security.SecurityCritical]
        public override PeerInvitationResponse Invite() 
        { 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();

            Guid appGuid = CurrentApplicationGuid;
 
            if (appGuid.Equals(Guid.Empty))
                throw new PeerToPeerException(SR.GetString(SR.Collab_NoGuidForCurrApp)); 
 
            //
            // We need at least one endpoint to send invitation to 
            //
            PeerEndPointCollection peerEndPoints = PeerEndPoints;

            if ((peerEndPoints == null) || (peerEndPoints.Count == 0)) 
                throw new PeerToPeerException(SR.GetString(SR.Collab_NoEndpointFound));
 
            PeerEndPoint peerEndPoint = PeerEndPoints[0]; 

            PeerInvitationResponse response = InternalInviteEndPoint(appGuid, null, null, peerEndPoint, null); 

            // throw an exception if the response type is ERROR
            CollaborationHelperFunctions.ThrowIfInvitationResponseInvalid(response);
            return response; 
        }
 
        //  
        // 
        //  
        // 
        [System.Security.SecurityCritical]
        public override void InviteAsync(Object userToken)
        { 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

            if (userToken == null) 
                throw new ArgumentException(SR.GetString(SR.NullUserToken));

            Guid appGuid = CurrentApplicationGuid;
 
            if (appGuid.Equals(Guid.Empty))
                throw new PeerToPeerException(SR.GetString(SR.Collab_NoGuidForCurrApp)); 
 
            //
            // We need at least one endpoint to send invitation to 
            //
            PeerEndPointCollection peerEndPoints = PeerEndPoints;

            if ((peerEndPoints == null) || (peerEndPoints.Count == 0)) 
                throw new PeerToPeerException(SR.GetString(SR.Collab_NoEndpointFound));
 
            InternalInviteAsync(appGuid, null, null, PeerEndPoints, null, userToken); 
        }
 
        // 
        // 
        // 
        [System.Security.SecurityCritical] 
        public override void InviteAsync(   PeerApplication applicationToInvite, string message,
                                            byte[] invitationData, Object userToken) 
        { 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();

            if (applicationToInvite == null)
                throw new ArgumentNullException("applicationToInvite"); 
            if (applicationToInvite.Id == Guid.Empty)
                throw new PeerToPeerException(SR.GetString(SR.Collab_EmptyGuidError)); 
            if (userToken == null) 
                throw new ArgumentException(SR.GetString(SR.NullUserToken));
 
            //
            // We need at least one endpoint to send invitation to
            //
            PeerEndPointCollection peerEndPoints = PeerEndPoints; 

            if ((peerEndPoints == null) || (peerEndPoints.Count == 0)) 
                throw new PeerToPeerException(SR.GetString(SR.Collab_NoEndpointFound)); 

            InternalInviteAsync(applicationToInvite.Id, message, invitationData, 
                                peerEndPoints, null, userToken);
        }

        public bool Equals(PeerNearMe other) 
        {
            if (other == null) 
                throw new ArgumentNullException("other"); 

            return other.Id.Equals(Id); 
        }

        public override bool Equals(object obj)
        { 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
            PeerNearMe comparandPeerNearMe = obj as PeerNearMe; 
            if (comparandPeerNearMe != null){
                return Guid.Equals(comparandPeerNearMe.Id, Id); 
            }

            return false;
        } 

        public new static bool Equals(object objA, object objB) 
        { 
            PeerNearMe comparandPeerNearMe1 = objA as PeerNearMe;
            PeerNearMe comparandPeerNearMe2 = objB as PeerNearMe; 

            if ((comparandPeerNearMe1 != null) && (comparandPeerNearMe2 != null)){
                return Guid.Equals(comparandPeerNearMe1.Id, comparandPeerNearMe2.Id);
            } 

            return false; 
        } 

        public override int GetHashCode() 
        {
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);

            return Id.GetHashCode(); 
        }
 
        public override string ToString() 
        {
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); 

            return Nickname;
        }
 
        private bool m_Disposed;
 
        protected override void Dispose(bool disposing) 
        {
            if (!m_Disposed){ 
                try{
                    m_Disposed = true;
                }
                finally{ 
                    base.Dispose(disposing);
                } 
            } 
        }
 
        // 
        // 
        // 
        [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
        ///  
        // 
        //  
        //  
        [System.Security.SecurityCritical]
        [SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)] 
        protected override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);
            info.AddValue("_Id", m_id); 
            info.AddValue("_NickName", m_nickname);
        } 
 
        //
        // Tracing information for Peer Near Me 
        //
        internal void TracePeerNearMe()
        {
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Contents of the PeerNearMe"); 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "\tNickname: {0}", Nickname);
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "\tID: {0}", Id); 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "\tNumber of Endpoints: {0}", PeerEndPoints.Count); 
            if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Verbose)){
 
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "\tEndPoints:");
                foreach (PeerEndPoint peerEndPoint in PeerEndPoints)
                    peerEndPoint.TracePeerEndPoint();
            } 
        }
 
 
    }
 
    //
    // Manages collection of peer near me classes
    //
    [Serializable] 
    public class PeerNearMeCollection : Collection
    { 
        internal PeerNearMeCollection() { } 
        protected override void SetItem(int index, PeerNearMe item)
        { 
            // nulls not allowed
            if (item == null){
                throw new ArgumentNullException("item");
            } 
            base.SetItem(index, item);
        } 
 
        protected override void InsertItem(int index, PeerNearMe item)
        { 
            // nulls not allowed
            if (item == null){
                throw new ArgumentNullException("item");
            } 
            base.InsertItem(index, item);
        } 
 
        public override string ToString()
        { 
            bool first = true;
            StringBuilder builder = new StringBuilder();

            foreach (PeerNearMe peerNearMe in this){ 
                if (!first){
                    builder.Append(", "); 
                } 
                else{
                    first = false; 
                }
                builder.Append(peerNearMe.ToString());
            }
            return builder.ToString(); 
        }
    } 
 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 
namespace System.Net.PeerToPeer.Collaboration
{ 
    using System; 
    using System.Collections;
    using System.Collections.Generic; 
    using System.Collections.ObjectModel;
    using System.Runtime.InteropServices;
    using System.Threading;
    using System.ComponentModel; 
    using System.Text;
    using System.Net.Mail; 
    using System.Diagnostics; 
    using System.Runtime.Serialization;
    using System.Security.Permissions; 

    /// 
    /// This is the event args class we give back when
    /// we have a peer near me change event triggered by native 
    /// 
    public class PeerNearMeChangedEventArgs : EventArgs 
    { 
        private PeerNearMe m_peerNearMe;
        private PeerChangeType m_peerChangeType; 

        internal PeerNearMeChangedEventArgs(PeerNearMe peerNearMe, PeerChangeType peerChangeType)
        {
            m_peerNearMe = peerNearMe; 
            m_peerChangeType = peerChangeType;
        } 
 
        public PeerNearMe PeerNearMe
        { 
            get{
                return m_peerNearMe;
            }
        } 

        public PeerChangeType PeerChangeType 
        { 
            get{
                return m_peerChangeType; 
            }
        }
    }
 
    /// 
    /// This class contains the functionality of the people near me concept 
    /// in windows collaboration i.e. people on the same subnet 
    /// 
    [Serializable] 
    public class PeerNearMe : Peer, IEquatable, ISerializable
    {
        private string m_nickname;
        private Guid m_id; 

        //  
        //  
        // 
        [System.Security.SecurityCritical] 
        static PeerNearMe(){
            CollaborationHelperFunctions.Initialize();
        }
 
        public PeerNearMe(){
            OnRefreshDataCompletedDelegate = new SendOrPostCallback(RefreshDataCompletedWaitCallback); 
        } 

        ///  
        /// Constructor to enable serialization
        /// 
        protected PeerNearMe(SerializationInfo serializationInfo, StreamingContext streamingContext)
            :base(serializationInfo, streamingContext) 
        {
            m_id = (Guid) serializationInfo.GetValue("_Id", typeof(Guid)); 
            m_nickname = serializationInfo.GetString("_NickName"); 

            OnRefreshDataCompletedDelegate = new SendOrPostCallback(RefreshDataCompletedWaitCallback); 
        }

        public string Nickname
        { 
            get {
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); 
 
                return m_nickname;
            } 
            internal set {
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);

                m_nickname = value; 
            }
        } 
 
        internal Guid Id
        { 
            get{
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);

                return m_id; 
            }
            set 
            { 
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
                m_id = value;
            }
        }
 
        //
        // Adds this peer to the contact manager 
        // 
        public PeerContact AddToContactManager()
        { 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering AddToContactManager.");
            PeerContact peerContact = null;
            try{
                peerContact = PeerCollaboration.ContactManager.CreateContact(this); 
                PeerCollaboration.ContactManager.AddContact(peerContact);
            } 
            catch (Exception e){ 
                throw new PeerToPeerException(SR.GetString(SR.Collab_AddToContactMgrFailed), (e.InnerException != null ? e.InnerException : e));
            } 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving AddToContactManager.");
            return peerContact;
        }
 
        //
        // Adds this peer to the contact manager 
        // 
        public PeerContact AddToContactManager(string displayName, string nickname, MailAddress emailAddress)
        { 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering AddToContactManager with Display name: {0}" +
                " Nickname: {1} and Email Address: {2}", displayName, nickname, emailAddress);

            PeerContact peerContact = null; 

            try{ 
                peerContact = PeerCollaboration.ContactManager.CreateContact(this); 
                PeerCollaboration.ContactManager.AddContact(peerContact);
            } 
            catch (Exception e){
                throw new PeerToPeerException(SR.GetString(SR.Collab_AddToContactMgrFailed), (e.InnerException != null ? e.InnerException : e));
            }
 
            peerContact.DisplayName = displayName;
            peerContact.Nickname = nickname; 
            peerContact.EmailAddress = emailAddress; 

            try{ 
                PeerCollaboration.ContactManager.UpdateContact(peerContact);
            }
            catch (Exception e){
                throw new PeerToPeerException(SR.GetString(SR.Collab_AddToContactMgrFailed) + " " + SR.GetString(SR.Collab_AddToContactMgrFailedUpdate), (e.InnerException != null ? e.InnerException : e)); 
            }
 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving AddToContactManager."); 
            return peerContact;
        } 

        // 
        // 
        //  
        [System.Security.SecurityCritical]
        public static PeerNearMe CreateFromPeerEndPoint(PeerEndPoint peerEndPoint) 
        { 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering CreateFromPeerEndPoint.");
            CollaborationHelperFunctions.Initialize(); 

            if (peerEndPoint == null)
                throw new ArgumentNullException("peerEndPoint");
            if (peerEndPoint.EndPoint == null) 
                throw new PeerToPeerException(SR.GetString(SR.Collab_NoEndPointInPeerEndPoint));
 
            PeerNearMeCollection peers = PeerCollaboration.GetPeersNearMe(); 
            PeerNearMe peer = null;
 
            foreach (PeerNearMe peerNearMe in peers){
                PeerEndPointCollection peerEndPoints = peerNearMe.PeerEndPoints;
                if ((peerEndPoints != null) && (peerEndPoints.Count != 0) && (peerEndPoints[0].Equals(peerEndPoint)))
                    peer = peerNearMe; 
            }
            if (peer == null){ 
                // 
                // No peer found, throw
                // 
                throw new PeerToPeerException(SR.GetString(SR.Collab_EndPointNotAPeerNearMe));
            }

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving CreateFromPeerEndPoint."); 
            return peer;
        } 
 
        //
        // Checks if we need refreshing of an unsubscribed peer near me 
        //
        internal override void RefreshIfNeeded()
        {
            RefreshData(); 
        }
 
        // 
        // Refresh the endpoint with new data from collab
        // 
        // 
        // 
        // 
        [System.Security.SecurityCritical] 
        public void RefreshData()
        { 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); 
            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
 
            InternalRefreshData(false);
        }

        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        [System.Security.SecurityCritical] 
        internal protected void InternalRefreshData(object state)
        { 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "InternalRefreshEndpointData called.");

            int errorCode = 0;
            bool isAsync = (bool)state; 
            Exception exception = null;
 
            AutoResetEvent refreshedEPDataEvent = new AutoResetEvent(false); 
            SafeCollabEvent safeRefreshedEPDataEvent;
 
            PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION();
            pcer.eventType = PeerCollabEventType.RequestStatusChanged;
            pcer.pInstance = IntPtr.Zero;
 
            //
            // Register to receive status changed event from collab 
            // 
            errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent(
                                                                refreshedEPDataEvent.SafeWaitHandle, 
                                                                1,
                                                                ref pcer,
                                                                out safeRefreshedEPDataEvent);
            if (errorCode != 0){ 
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
                exception = PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_ReqStatusChangedRegFailed), errorCode); 
                if (!isAsync) 
                    throw exception;
            } 

            PeerEndPointCollection peerEndPoints = PeerEndPoints;

            if (peerEndPoints.Count == 0) return; 

            try{ 
            InternalRefreshData(peerEndPoints[0]); 
            }
            catch (Exception e){ 
                if (!isAsync)
                    throw;
                else
                    exception = e; 
            }
 
            // 
            // Wait till all the endpoints are refreshed
            // 
            while (exception == null){
                refreshedEPDataEvent.WaitOne();

                SafeCollabData eventData; 

                errorCode = UnsafeCollabNativeMethods.PeerCollabGetEventData(safeRefreshedEPDataEvent, 
                                                                                    out eventData); 
                if (errorCode != 0){
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetEventData returned with errorcode {0}", errorCode); 
                    exception = PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_RefreshDataFailed), errorCode);
                    if (!isAsync)
                        throw exception;
                    else 
                        break;
                } 
 
                PEER_COLLAB_EVENT_DATA ped = (PEER_COLLAB_EVENT_DATA)Marshal.PtrToStructure(eventData.DangerousGetHandle(),
                                                                                            typeof(PEER_COLLAB_EVENT_DATA)); 

                if (ped.eventType == PeerCollabEventType.RequestStatusChanged){
                    PEER_EVENT_REQUEST_STATUS_CHANGED_DATA statusData = ped.requestStatusChangedData;
 
                    PeerEndPoint peerEndPoint = null;
 
                    if (statusData.pEndPoint != IntPtr.Zero){ 
                        PEER_ENDPOINT pe = (PEER_ENDPOINT)Marshal.PtrToStructure(statusData.pEndPoint, typeof(PEER_ENDPOINT));
                        peerEndPoint = CollaborationHelperFunctions.ConvertPEER_ENDPOINTToPeerEndPoint(pe); 
                    }

                    if (statusData.hrChange < 0){
                        exception = PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_RefreshDataFailed), statusData.hrChange); 
                    }
 
                    if (exception != null){ 
                        //
                        // Throw exception for [....] but call callback for async with exception 
                        //
                        if (!isAsync)
                            throw exception;
                    } 

                    // 
                    // Check if this is our endpoint 
                    //
                    if (PeerEndPoints[0].Equals(peerEndPoint)){ 
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Found endpoint match in Request status changed.");

                        //
                        // For async call the callback and for [....] just return 
                        //
                        if (isAsync){ 
                            RefreshDataCompletedEventArgs args = new 
                                        RefreshDataCompletedEventArgs(  peerEndPoint,
                                                                        null, 
                                                                        false,
                                                                        m_refreshDataAsyncOp.UserSuppliedState);

                            if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Information)){ 
                                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Firing RefreshDataCompleted event with folloding peer endpoint.");
                                peerEndPoint.TracePeerEndPoint(); 
                            } 

                            this.PrepareToRaiseRefreshDataCompletedEvent(m_refreshDataAsyncOp, args); 
                        }

                        break;
                    } 
                }
            } 
 
            //
            // Async case with exception fire callback here 
            // [....] would have already thrown this by now
            //
            if (exception != null){
                RefreshDataCompletedEventArgs args = new 
                            RefreshDataCompletedEventArgs(null,
                                                            exception, 
                                                            false, 
                                                            m_refreshDataAsyncOp.UserSuppliedState);
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Firing RefreshDataCompleted event with exception {0}.", exception); 
                this.PrepareToRaiseRefreshDataCompletedEvent(m_refreshDataAsyncOp, args);
            }

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving InternalRefreshEndpointData."); 
        }
 
        // 
        // Refreshes on endpoint
        // 

        // 
        // 
        //  
        // 
        //  
        //  
        // 
        [System.Security.SecurityCritical] 
        internal static void InternalRefreshData(PeerEndPoint peerEndPoint)
        {
            int errorCode;
            PEER_ENDPOINT pep = new PEER_ENDPOINT(); 
            pep.peerAddress = CollaborationHelperFunctions.ConvertIPEndpointToPEER_ADDRESS(peerEndPoint.EndPoint);
 
            GCHandle pepName = GCHandle.Alloc(peerEndPoint.Name, GCHandleType.Pinned); 
            pep.pwzEndpointName = pepName.AddrOfPinnedObject();
 
            GCHandle peerEP = GCHandle.Alloc(pep, GCHandleType.Pinned);
            IntPtr ptrPeerEP = peerEP.AddrOfPinnedObject();

            try{ 
                errorCode = UnsafeCollabNativeMethods.PeerCollabRefreshEndpointData(ptrPeerEP);
            } 
            finally{ 
                if (pepName.IsAllocated) pepName.Free();
                if (peerEP.IsAllocated) peerEP.Free(); 
            }

            if (errorCode != 0){
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRefreshEndpointData returned with errorcode {0}", errorCode); 
                throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_RefreshDataFailed), errorCode);
            } 
        } 

        #region RefreshEndpoint Async variables 
        AsyncOperation m_refreshDataAsyncOp;
        private object m_refreshDataAsyncOpLock;
        private object RefreshDataAsyncOpLock
        { 
            get{
                if (m_refreshDataAsyncOpLock == null){ 
                    object o = new object(); 
                    Interlocked.CompareExchange(ref m_refreshDataAsyncOpLock, o, null);
                } 
                return m_refreshDataAsyncOpLock;
            }
        }
        SendOrPostCallback OnRefreshDataCompletedDelegate; 
        #endregion
 
        private event EventHandler m_refreshDataCompleted; 
        public event EventHandler RefreshDataCompleted
        { 
            add
            {
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

                m_refreshDataCompleted += value; 
            } 
            remove
            { 
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();

                m_refreshDataCompleted -= value; 
            }
        } 
 
        //
        // Async refresh endpoint data 
        //
        // 
        // 
        //  
        [System.Security.SecurityCritical]
        public void RefreshDataAsync(object userToken) 
        { 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

            if (userToken == null)
                throw new ArgumentNullException("userToken");
 
            lock (RefreshDataAsyncOpLock){
                if (m_refreshDataAsyncOp != null) 
                    throw new PeerToPeerException(SR.GetString(SR.Collab_DuplicateRefreshAsync)); 
                m_refreshDataAsyncOp = AsyncOperationManager.CreateOperation(userToken);
            } 
            ThreadPool.QueueUserWorkItem(new WaitCallback(InternalRefreshData), true);

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving RefreshDataAsync().");
        } 

        protected void OnRefreshDataCompleted(RefreshDataCompletedEventArgs e) 
        { 
            EventHandler handlerCopy = m_refreshDataCompleted;
 
            if (handlerCopy != null){
                handlerCopy(this, e);
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the refresh endpoint completed event callback.");
            } 
        }
 
        void RefreshDataCompletedWaitCallback(object operationState) 
        {
            m_refreshDataAsyncOp = null; 
            OnRefreshDataCompleted((RefreshDataCompletedEventArgs)operationState);
        }

        internal void PrepareToRaiseRefreshDataCompletedEvent(AsyncOperation asyncOP, RefreshDataCompletedEventArgs args) 
        {
            asyncOP.PostOperationCompleted(OnRefreshDataCompletedDelegate, args); 
        } 

        private static event EventHandler s_peerNearMeChanged; 
        public static event EventHandler PeerNearMeChanged
        {
            // 
            //  
            // 
            //  
            [System.Security.SecurityCritical] 
            add
            { 
                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
                CollaborationHelperFunctions.Initialize();

                AddPeerNearMeChanged(value); 
            }
            //  
            //  
            // 
            //  
            [System.Security.SecurityCritical]
            remove
            {
                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 
                CollaborationHelperFunctions.Initialize();
 
                RemovePeerNearMeChanged(value); 
            }
        } 

        #region PeerNearMe changed event variables
        private static object s_lockPNMChangedEvent;
        private static object LockPNMChangedEvent 
        {
            get{ 
                if (s_lockPNMChangedEvent == null){ 
                    object o = new object();
                    Interlocked.CompareExchange(ref s_lockPNMChangedEvent, o, null); 
                }
                return s_lockPNMChangedEvent;
            }
        } 
        private static RegisteredWaitHandle s_registeredPNMWaitHandle;
        private static AutoResetEvent s_peerNearMeChangedEvent; 
        private static SafeCollabEvent s_safePeerNearMeChangedEvent; 
        #endregion
 
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        [System.Security.SecurityCritical]
        private static void AddPeerNearMeChanged(EventHandler cb) 
        {
            //
            // Register a wait handle if one has not been registered already
            // 

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering AddPeerNearMeChanged()."); 
 
            lock (LockPNMChangedEvent){
                if (s_peerNearMeChanged == null){ 

                    s_peerNearMeChangedEvent = new AutoResetEvent(false);

                    // 
                    // Register callback with a wait handle
                    // 
 
                    s_registeredPNMWaitHandle = ThreadPool.RegisterWaitForSingleObject(s_peerNearMeChangedEvent, //Event that triggers the callback
                                            new WaitOrTimerCallback(PeerNearMeChangedCallback), //callback to be called 
                                            null, //state to be passed
                                            -1,   //Timeout - aplicable only for timers
                                            false //call us everytime the event is set
                                            ); 
                    PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION();
                    pcer.eventType = PeerCollabEventType.PeopleNearMeChanged; 
                    pcer.pInstance = IntPtr.Zero; 

                    // 
                    // Register event with collab
                    //

                    int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent( 
                                                                        s_peerNearMeChangedEvent.SafeWaitHandle,
                                                                        1, 
                                                                        ref pcer, 
                                                                        out s_safePeerNearMeChangedEvent);
                    if (errorCode != 0){ 
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_PeerNearMeChangedRegFailed), errorCode);
                    }
                } 
                s_peerNearMeChanged += cb;
            } 
 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddPeerNearMeChanged() successful.");
        } 

        // 
        // 
        //  
        // 
        [System.Security.SecurityCritical] 
        private static void RemovePeerNearMeChanged(EventHandler cb) 
        {
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemovePeerNearMeChanged() called."); 
            lock (LockPNMChangedEvent){
                s_peerNearMeChanged -= cb;
                if (s_peerNearMeChanged == null){
                    CollaborationHelperFunctions.CleanEventVars(ref s_registeredPNMWaitHandle, 
                                                                ref s_safePeerNearMeChangedEvent,
                                                                ref s_peerNearMeChangedEvent); 
 
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean PeerNearMeChanged variables successful.");
                } 
            }
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemovePeerNearMeChanged() successful.");
        }
 
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        [System.Security.SecurityCritical] 
        private static void PeerNearMeChangedCallback(object state, bool timedOut)
        { 
            SafeCollabData eventData = null;
            int errorCode = 0;

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "PeerNearMeChangedCallback() called."); 

            while (true){ 
                PeerNearMeChangedEventArgs peerNearMeChangedArgs = null; 

                // 
                // Get the event data for the fired event
                //

                try{ 
                    lock (LockPNMChangedEvent){
                        if (s_safePeerNearMeChangedEvent.IsInvalid) return; 
                        errorCode = UnsafeCollabNativeMethods.PeerCollabGetEventData(s_safePeerNearMeChangedEvent, 
                                                                                     out eventData);
                    } 
                    if (errorCode == UnsafeCollabReturnCodes.PEER_S_NO_EVENT_DATA)
                        break;
                    else if (errorCode != 0){
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetEventData returned with errorcode {0}", errorCode); 
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetPeerNearMeChangedDataFailed), errorCode);
                    } 
 
                    PEER_COLLAB_EVENT_DATA ped = (PEER_COLLAB_EVENT_DATA)Marshal.PtrToStructure(eventData.DangerousGetHandle(),
                                                                                                typeof(PEER_COLLAB_EVENT_DATA)); 
                    if (ped.eventType == PeerCollabEventType.PeopleNearMeChanged){
                        PEER_EVENT_PEOPLE_NEAR_ME_CHANGED_DATA pnmData = ped.peopleNearMeChangedData;
                        PeerNearMe peerNearMe = null;
                        if (pnmData.pPeopleNearMe != IntPtr.Zero){ 
                            PEER_PEOPLE_NEAR_ME pnm = (PEER_PEOPLE_NEAR_ME)Marshal.PtrToStructure(pnmData.pPeopleNearMe, typeof(PEER_PEOPLE_NEAR_ME));
                            peerNearMe = CollaborationHelperFunctions.PEER_PEOPLE_NEAR_METoPeerNearMe(pnm); 
                        } 

                        peerNearMeChangedArgs = new PeerNearMeChangedEventArgs(peerNearMe, pnmData.changeType); 
                    }
                }
                finally{
                    if (eventData != null) eventData.Dispose(); 
                }
 
                // 
                // Fire the callback with the marshalled event args data
                // 

                EventHandler handlerCopy = s_peerNearMeChanged;

                if ((peerNearMeChangedArgs != null) && (handlerCopy != null)){ 
                    handlerCopy(null, peerNearMeChangedArgs);
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the peer near me changed event callback."); 
                } 
            }
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving PeerNearMeChangedCallback()."); 
        }

        // 
        //  
        // 
        [System.Security.SecurityCritical] 
        public override PeerInvitationResponse Invite(PeerApplication applicationToInvite, string message, 
                                                      byte[] invitationData)
        { 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);

            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
 
            if (applicationToInvite == null)
                throw new ArgumentNullException("applicationToInvite"); 
            if (applicationToInvite.Id == Guid.Empty) 
                throw new PeerToPeerException(SR.GetString(SR.Collab_EmptyGuidError));
 
            //
            // We need at least one endpoint to send invitation to
            //
            PeerEndPointCollection peerEndPoints = PeerEndPoints; 

            if ((peerEndPoints == null) || (peerEndPoints.Count == 0)) 
                throw new PeerToPeerException(SR.GetString(SR.Collab_NoEndpointFound)); 

            PeerEndPoint peerEndPoint = PeerEndPoints[0]; 

            PeerInvitationResponse response = InternalInviteEndPoint(applicationToInvite.Id, message, invitationData,
                                                                     peerEndPoint, null);
 
            // throw an exception if the response type is ERROR
            CollaborationHelperFunctions.ThrowIfInvitationResponseInvalid(response); 
            return response; 
        }
 
        // 
        // 
        // 
        //  
        [System.Security.SecurityCritical]
        public override PeerInvitationResponse Invite() 
        { 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();

            Guid appGuid = CurrentApplicationGuid;
 
            if (appGuid.Equals(Guid.Empty))
                throw new PeerToPeerException(SR.GetString(SR.Collab_NoGuidForCurrApp)); 
 
            //
            // We need at least one endpoint to send invitation to 
            //
            PeerEndPointCollection peerEndPoints = PeerEndPoints;

            if ((peerEndPoints == null) || (peerEndPoints.Count == 0)) 
                throw new PeerToPeerException(SR.GetString(SR.Collab_NoEndpointFound));
 
            PeerEndPoint peerEndPoint = PeerEndPoints[0]; 

            PeerInvitationResponse response = InternalInviteEndPoint(appGuid, null, null, peerEndPoint, null); 

            // throw an exception if the response type is ERROR
            CollaborationHelperFunctions.ThrowIfInvitationResponseInvalid(response);
            return response; 
        }
 
        //  
        // 
        //  
        // 
        [System.Security.SecurityCritical]
        public override void InviteAsync(Object userToken)
        { 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

            if (userToken == null) 
                throw new ArgumentException(SR.GetString(SR.NullUserToken));

            Guid appGuid = CurrentApplicationGuid;
 
            if (appGuid.Equals(Guid.Empty))
                throw new PeerToPeerException(SR.GetString(SR.Collab_NoGuidForCurrApp)); 
 
            //
            // We need at least one endpoint to send invitation to 
            //
            PeerEndPointCollection peerEndPoints = PeerEndPoints;

            if ((peerEndPoints == null) || (peerEndPoints.Count == 0)) 
                throw new PeerToPeerException(SR.GetString(SR.Collab_NoEndpointFound));
 
            InternalInviteAsync(appGuid, null, null, PeerEndPoints, null, userToken); 
        }
 
        // 
        // 
        // 
        [System.Security.SecurityCritical] 
        public override void InviteAsync(   PeerApplication applicationToInvite, string message,
                                            byte[] invitationData, Object userToken) 
        { 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();

            if (applicationToInvite == null)
                throw new ArgumentNullException("applicationToInvite"); 
            if (applicationToInvite.Id == Guid.Empty)
                throw new PeerToPeerException(SR.GetString(SR.Collab_EmptyGuidError)); 
            if (userToken == null) 
                throw new ArgumentException(SR.GetString(SR.NullUserToken));
 
            //
            // We need at least one endpoint to send invitation to
            //
            PeerEndPointCollection peerEndPoints = PeerEndPoints; 

            if ((peerEndPoints == null) || (peerEndPoints.Count == 0)) 
                throw new PeerToPeerException(SR.GetString(SR.Collab_NoEndpointFound)); 

            InternalInviteAsync(applicationToInvite.Id, message, invitationData, 
                                peerEndPoints, null, userToken);
        }

        public bool Equals(PeerNearMe other) 
        {
            if (other == null) 
                throw new ArgumentNullException("other"); 

            return other.Id.Equals(Id); 
        }

        public override bool Equals(object obj)
        { 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
            PeerNearMe comparandPeerNearMe = obj as PeerNearMe; 
            if (comparandPeerNearMe != null){
                return Guid.Equals(comparandPeerNearMe.Id, Id); 
            }

            return false;
        } 

        public new static bool Equals(object objA, object objB) 
        { 
            PeerNearMe comparandPeerNearMe1 = objA as PeerNearMe;
            PeerNearMe comparandPeerNearMe2 = objB as PeerNearMe; 

            if ((comparandPeerNearMe1 != null) && (comparandPeerNearMe2 != null)){
                return Guid.Equals(comparandPeerNearMe1.Id, comparandPeerNearMe2.Id);
            } 

            return false; 
        } 

        public override int GetHashCode() 
        {
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);

            return Id.GetHashCode(); 
        }
 
        public override string ToString() 
        {
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); 

            return Nickname;
        }
 
        private bool m_Disposed;
 
        protected override void Dispose(bool disposing) 
        {
            if (!m_Disposed){ 
                try{
                    m_Disposed = true;
                }
                finally{ 
                    base.Dispose(disposing);
                } 
            } 
        }
 
        // 
        // 
        // 
        [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
        ///  
        // 
        //  
        //  
        [System.Security.SecurityCritical]
        [SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)] 
        protected override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);
            info.AddValue("_Id", m_id); 
            info.AddValue("_NickName", m_nickname);
        } 
 
        //
        // Tracing information for Peer Near Me 
        //
        internal void TracePeerNearMe()
        {
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Contents of the PeerNearMe"); 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "\tNickname: {0}", Nickname);
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "\tID: {0}", Id); 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "\tNumber of Endpoints: {0}", PeerEndPoints.Count); 
            if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Verbose)){
 
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "\tEndPoints:");
                foreach (PeerEndPoint peerEndPoint in PeerEndPoints)
                    peerEndPoint.TracePeerEndPoint();
            } 
        }
 
 
    }
 
    //
    // Manages collection of peer near me classes
    //
    [Serializable] 
    public class PeerNearMeCollection : Collection
    { 
        internal PeerNearMeCollection() { } 
        protected override void SetItem(int index, PeerNearMe item)
        { 
            // nulls not allowed
            if (item == null){
                throw new ArgumentNullException("item");
            } 
            base.SetItem(index, item);
        } 
 
        protected override void InsertItem(int index, PeerNearMe item)
        { 
            // nulls not allowed
            if (item == null){
                throw new ArgumentNullException("item");
            } 
            base.InsertItem(index, item);
        } 
 
        public override string ToString()
        { 
            bool first = true;
            StringBuilder builder = new StringBuilder();

            foreach (PeerNearMe peerNearMe in this){ 
                if (!first){
                    builder.Append(", "); 
                } 
                else{
                    first = false; 
                }
                builder.Append(peerNearMe.ToString());
            }
            return builder.ToString(); 
        }
    } 
 
}

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