//internal SafePeerNameEndResolve(bool ownsHandle) : base(ownsHandle) { }
 protected override bool ReleaseHandle()
 {
     UnsafeP2PNativeMethods.PeerPnrpEndResolve(handle);
     SetHandleAsInvalid();   //Mark it closed - This does not change the value of the handle it self
     SetHandle(IntPtr.Zero); //Mark it invalid - Change the value to Zero
     return(true);
 }
        internal void StartAsyncResolve()
        {
            //------------------------------------------
            //Check for disposal
            //------------------------------------------
            if (m_Disposed)
            {
                throw new ObjectDisposedException(this.GetType().FullName);
            }

            //------------------------------------------
            //First wire up a callback
            //------------------------------------------
            m_RegisteredWaitHandle = ThreadPool.RegisterWaitForSingleObject(m_EndPointInfoAvailableEvent,                           //Event that triggers the callback
                                                                            new WaitOrTimerCallback(EndPointInfoAvailableCallback), //callback to be called
                                                                            null,                                                   //state to be passed
                                                                            -1,                                                     //Timeout - aplicable only for timers not for events
                                                                            false                                                   //call us everytime the event is set not just one time
                                                                            );

            //------------------------------------------
            //Now call the native API to start the resolution
            //process save the handle for later
            //------------------------------------------
            Int32 result = UnsafeP2PNativeMethods.PeerPnrpStartResolve(m_PeerName.ToString(),
                                                                       m_Cloud.InternalName,
                                                                       (UInt32)m_MaxRecords,
                                                                       m_EndPointInfoAvailableEvent.SafeWaitHandle,
                                                                       out m_SafePeerNameEndResolve);

            if (result != 0)
            {
                if (!m_SafePeerNameEndResolve.IsInvalid && !m_SafePeerNameEndResolve.IsClosed)
                {
                    m_SafePeerNameEndResolve.Dispose();
                }
                m_RegisteredWaitHandle.Unregister(null);
                m_RegisteredWaitHandle = null;
                PeerToPeerException ex = PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotStartNameResolution), result);
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, m_TraceEventId,
                                                  "Exception occurred while starting async resolve");
                throw ex;
            }

            //------------------------------------------
            //Create an async operation with the given
            //user state
            //------------------------------------------
            m_AsyncOp = AsyncOperationManager.CreateOperation(m_userState);

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId,
                                              "Successfully started the async resolve. The native handle is {0}", m_SafePeerNameEndResolve.DangerousGetHandle());
        }
Exemple #3
0
        public static PeerName CreateFromPeerHostName(string peerHostName)
        {
            //-------------------------------------------------
            //Check arguments
            //-------------------------------------------------
            if (peerHostName == null)
            {
                throw new ArgumentNullException("peerHostName");
            }
            if (peerHostName.Length == 0)
            {
                throw new ArgumentException(SR.GetString(SR.Pnrp_InvalidPeerHostName), "peerHostName");
            }

            Int32        result;
            SafePeerData shPeerName = null;
            string       peerName   = null;

            try
            {
                result = UnsafeP2PNativeMethods.PeerHostNameToPeerName(peerHostName, out shPeerName);
                if (result != 0)
                {
                    throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotGetPeerNameFromPeerHostName), result);
                }
                peerName = shPeerName.UnicodeString;
            }
            finally
            {
                if (shPeerName != null)
                {
                    shPeerName.Dispose();
                }
            }

            string authority;
            string classifier;

            WeakParsePeerName(peerName, out authority, out classifier);
            PeerName p = new PeerName(peerName, authority, classifier);

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "PeerName created from PeerHostName - PeerHostName {0} to PeerName PeerName {1} Authority {2} Classfier {3}", peerHostName, peerName, authority, classifier);
            return(p);
        }
Exemple #4
0
        public static PeerName CreateRelativePeerName(
            PeerName peerName,
            string classifier)
        {
            //-------------------------------------------------
            //Check arguments
            //-------------------------------------------------
            if (peerName == null)
            {
                throw new ArgumentNullException("peerName", SR.GetString(SR.Pnrp_PeerNameCantBeNull));
            }
            if (!peerName.IsSecured && (classifier == null || classifier.Length == 0))
            {
                throw new ArgumentException(SR.GetString(SR.Pnrp_InvalidClassifier), "classifier");
            }
            if (classifier != null && classifier.Length > PEER_MAX_CLASSIFIER_LENGTH)
            {
                throw new ArgumentException(SR.GetString(SR.Pnrp_InvalidClassifier), "classifier");
            }

            //--------------------------------------------------
            //Normalize using NFC
            //--------------------------------------------------
            if (classifier != null && classifier.Length > 0)
            {
                classifier = classifier.Normalize(NormalizationForm.FormC);
            }

            Int32        result;
            SafePeerData shNewPeerName = null;
            string       newPeerName   = null;

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

            string authority;
            string newClassifier;

            WeakParsePeerName(newPeerName, out authority, out newClassifier);
            PeerName p = new PeerName(newPeerName, authority, newClassifier);

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "A new PeerName created from existing PeerName with a new classfier. Existing PeerName {0} Classifier {1} New PeerName {2}", peerName, classifier, p);
            return(p);
        }
Exemple #5
0
        public PeerName(string classifier, PeerNameType peerNameType)
        {
            //-------------------------------------------------
            //Check arguments
            //-------------------------------------------------
            if ((classifier == null || classifier.Length == 0) &&
                peerNameType == PeerNameType.Unsecured)
            {
                throw new ArgumentNullException("classifier");
            }
            if (classifier != null && classifier.Length > PEER_MAX_CLASSIFIER_LENGTH)
            {
                throw new ArgumentException(SR.GetString(SR.Pnrp_InvalidClassifier), "classifier");
            }
            //--------------------------------------------------
            //Normalize using NFC
            //--------------------------------------------------
            if (classifier != null && classifier.Length > 0)
            {
                classifier = classifier.Normalize(NormalizationForm.FormC);
            }
            //-------------------------------------------------
            //call the helper to create the PeerName
            //-------------------------------------------------
            Int32        result;
            SafePeerData shNewPeerName     = null;
            SafePeerData shDefaultIdentity = null;

            try
            {
                if (peerNameType == PeerNameType.Unsecured)
                {
                    result = UnsafeP2PNativeMethods.PeerCreatePeerName((string)null, classifier, out shNewPeerName);
                    if (result != 0)
                    {
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotCreateUnsecuredPeerName), result);
                    }
                    m_Authority = PEERNAME_UNSECURED_AUTHORITY;
                }
                else
                {
                    result = UnsafeP2PNativeMethods.PeerIdentityGetDefault(out shDefaultIdentity);
                    if (result != 0)
                    {
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotGetDefaultIdentity), result);
                    }
                    m_Authority = shDefaultIdentity.UnicodeString;
                    //}

                    result = UnsafeP2PNativeMethods.PeerCreatePeerName(m_Authority, classifier, out shNewPeerName);
                    if (result != 0)
                    {
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotCreateSecuredPeerName), result);
                    }
                }
                m_PeerName   = shNewPeerName.UnicodeString;
                m_Classifier = classifier;
            }
            finally
            {
                if (shNewPeerName != null)
                {
                    shNewPeerName.Dispose();
                }
                if (shDefaultIdentity != null)
                {
                    shDefaultIdentity.Dispose();
                }
            }
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "PeerName instance created - PeerName {0} Authority {1} Classfier {2}", m_PeerName, m_Authority, m_Classifier);
        }
        public void ResolveAsync(PeerName peerName, Cloud cloud, int maxRecords, object userState)
        {
            //-------------------------------------------------
            //Check arguments
            //-------------------------------------------------
            if (peerName == null)
            {
                throw new ArgumentNullException(SR.GetString(SR.Pnrp_PeerNameCantBeNull), "peerName");
            }
            if (cloud == null)
            {
                cloud = Cloud.Available;
            }
            if (maxRecords <= 0)
            {
                throw new ArgumentOutOfRangeException("maxRecords", SR.GetString(SR.Pnrp_MaxRecordsParameterMustBeGreaterThanZero));
            }

            if (m_ResolveCompleted == null)
            {
                throw new PeerToPeerException(SR.GetString(SR.Pnrp_AtleastOneEvenHandlerNeeded));
            }
            //---------------------------------------------------
            //Demand CAS permissions
            //---------------------------------------------------
            PnrpPermission.UnrestrictedPnrpPermission.Demand();

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

            //----------------------------------------------------
            //userToken can't be null
            //----------------------------------------------------
            if (userState == null)
            {
                throw new ArgumentNullException(SR.GetString(SR.NullUserToken), "userState");
            }

            PeerNameResolverHelper peerNameResolverHelper = null;
            //---------------------------------------------------
            //The userToken can't be duplicate of what is in the
            //current list. These are the requriments for the new Async model
            //that supports multiple outstanding async calls
            //---------------------------------------------------
            int newTraceEventId = NewTraceEventId;

            lock (m_PeerNameResolverHelperListLock)
            {
                if (m_PeerNameResolverHelperList.ContainsKey(userState))
                {
                    throw new ArgumentException(SR.GetString(SR.DuplicateUserToken));
                }
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, newTraceEventId,
                                                  "PeerNameResolverHelper is being created with TraceEventId {0}", newTraceEventId);
                peerNameResolverHelper = new PeerNameResolverHelper(peerName, cloud, maxRecords, userState, this, newTraceEventId);
                m_PeerNameResolverHelperList[userState] = peerNameResolverHelper;
            }

            try
            {
                //---------------------------------------------------
                //Start resolution on that resolver
                //---------------------------------------------------
                peerNameResolverHelper.StartAsyncResolve();
            }
            catch
            {
                //---------------------------------------------------
                //If an exception happens clear the userState from the
                //list so that that token can be reused
                //---------------------------------------------------
                lock (m_PeerNameResolverHelperListLock)
                {
                    m_PeerNameResolverHelperList.Remove(userState);
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, newTraceEventId,
                                                      "Removing userState token from pending list {0}", userState.GetHashCode());
                }
                throw;
            }
        }
        public PeerNameRecordCollection Resolve(PeerName peerName, Cloud cloud, int maxRecords)
        {
            //---------------------------------------------------
            //Check arguments
            //---------------------------------------------------
            if (peerName == null)
            {
                throw new ArgumentNullException(SR.GetString(SR.Pnrp_PeerNameCantBeNull), "peerName");
            }

            if (maxRecords <= 0)
            {
                throw new ArgumentOutOfRangeException("maxRecords", SR.GetString(SR.Pnrp_MaxRecordsParameterMustBeGreaterThanZero));
            }

            //---------------------------------------------------
            //Assume all clouds if the clould passed is null?
            //---------------------------------------------------
            if (cloud == null)
            {
                cloud = Cloud.Available;
            }

            //---------------------------------------------------
            //Demand CAS permissions
            //---------------------------------------------------
            PnrpPermission.UnrestrictedPnrpPermission.Demand();

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

            //---------------------------------------------------------------
            //Trace log
            //---------------------------------------------------------------
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Sync Resolve called with PeerName: {0}, Cloud: {1}, MaxRecords {2}", peerName, cloud, maxRecords);

            SafePeerData shEndPointInfoArray;
            string       NativeCloudName        = cloud.InternalName;
            UInt32       ActualCountOfEndPoints = (UInt32)maxRecords;
            int          result = UnsafeP2PNativeMethods.PeerPnrpResolve(peerName.ToString(),
                                                                         NativeCloudName,
                                                                         ref ActualCountOfEndPoints,
                                                                         out shEndPointInfoArray);

            if (result != 0)
            {
                throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotStartNameResolution), result);
            }

            //---------------------------------------------------
            //If there are no endpoints returned, return
            //an empty PeerNameRecord Collection
            //---------------------------------------------------
            PeerNameRecordCollection PeerNameRecords = new PeerNameRecordCollection();

            if (ActualCountOfEndPoints != 0)
            {
                try
                {
                    unsafe
                    {
                        IntPtr pEndPointInfoArray           = shEndPointInfoArray.DangerousGetHandle();
                        PEER_PNRP_ENDPOINT_INFO *pEndPoints = (PEER_PNRP_ENDPOINT_INFO *)pEndPointInfoArray;
                        for (int i = 0; i < ActualCountOfEndPoints; i++)
                        {
                            PeerNameRecord           record        = new PeerNameRecord();
                            PEER_PNRP_ENDPOINT_INFO *pEndPointInfo = &pEndPoints[i];
                            record.PeerName = new PeerName(Marshal.PtrToStringUni(pEndPointInfo->pwszPeerName));
                            string comment = Marshal.PtrToStringUni(pEndPointInfo->pwszComment);
                            if (comment != null && comment.Length > 0)
                            {
                                record.Comment = comment;
                            }

                            if (pEndPointInfo->payLoad.cbPayload != 0)
                            {
                                record.Data = new byte[pEndPointInfo->payLoad.cbPayload];
                                Marshal.Copy(pEndPointInfo->payLoad.pbPayload, record.Data, 0, (int)pEndPointInfo->payLoad.cbPayload);
                            }
                            //record.EndPointList = new IPEndPoint[pEndPointInfo->cAddresses];
                            IntPtr ppSOCKADDRs = pEndPointInfo->ArrayOfSOCKADDRIN6Pointers;
                            for (UInt32 j = 0; j < pEndPointInfo->cAddresses; j++)
                            {
                                IntPtr pSOCKADDR = Marshal.ReadIntPtr(ppSOCKADDRs);

                                byte[] AddressFamilyBuffer = new byte[2];
                                Marshal.Copy(pSOCKADDR, AddressFamilyBuffer, 0, 2);
                                int addressFamily = 0;
    #if BIGENDIAN
                                addressFamily = AddressFamilyBuffer[1] + ((int)AddressFamilyBuffer[0] << 8);
    #else
                                addressFamily = AddressFamilyBuffer[0] + ((int)AddressFamilyBuffer[1] << 8);
    #endif
                                byte[] buffer = new byte[((AddressFamily)addressFamily == AddressFamily.InterNetwork) ? SystemNetHelpers.IPv4AddressSize : SystemNetHelpers.IPv6AddressSize];
                                Marshal.Copy(pSOCKADDR, buffer, 0, buffer.Length);
                                IPEndPoint ipe = SystemNetHelpers.IPEndPointFromSOCKADDRBuffer(buffer);
                                record.EndPointCollection.Add(ipe);
                                ppSOCKADDRs = (IntPtr)((long)ppSOCKADDRs + Marshal.SizeOf(typeof(IntPtr)));
                            }
                            //----------------------------------
                            //Dump for trace
                            //----------------------------------
                            record.TracePeerNameRecord();
                            //----------------------------------
                            //Add to collection
                            //----------------------------------
                            PeerNameRecords.Add(record);
                        }
                    }
                }
                finally
                {
                    shEndPointInfoArray.Dispose();
                }
            }
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Sync Resolve returnig with PeerNameRecord count :{0}", PeerNameRecords.Count);
            return(PeerNameRecords);
        }
        public void EndPointInfoAvailableCallback(object state, bool timedOut)
        {
            //------------------------------------------
            //This callback is called whenever there is an endpoint info
            //available or the resultion is completed
            //------------------------------------------
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId,
                                              "EndPointInfoAvailableCallback called");
            PeerNameRecord   record = null;
            SafePeerData     shEndPointInfo;
            Int32            result = 0;
            PeerNameResolver parent = null;

            if (m_Cancelled)
            {
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId,
                                                  "Detected that the async operation is already canceled  - before entering the lock");
                return;
            }
            lock (m_Lock)
            {
                if (m_Cancelled)
                {
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId,
                                                      "Detected that the async operation is already canceled - after entering the lock");
                    return;
                }
                result = UnsafeP2PNativeMethods.PeerPnrpGetEndpoint(m_SafePeerNameEndResolve.DangerousGetHandle(), out shEndPointInfo);
                if (result != 0)
                {
                    if (result == PEER_E_NO_MORE)
                    {
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId,
                                                          "Native API returned that there are no more records - resolve completed successfully");
                    }
                    m_CompletedOrException = true;
                    m_SafePeerNameEndResolve.Dispose();
                }
                else
                {
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId,
                                                      "Proceeding to retrieve the endpoint information from incremental resolve");
                    try
                    {
                        unsafe
                        {
                            PEER_PNRP_ENDPOINT_INFO *pEndPointInfo = (PEER_PNRP_ENDPOINT_INFO *)shEndPointInfo.DangerousGetHandle();
                            record          = new PeerNameRecord();
                            record.PeerName = new PeerName(Marshal.PtrToStringUni(pEndPointInfo->pwszPeerName));
                            string comment = Marshal.PtrToStringUni(pEndPointInfo->pwszComment);
                            if (comment != null && comment.Length > 0)
                            {
                                record.Comment = comment;
                            }
                            if (pEndPointInfo->payLoad.cbPayload != 0)
                            {
                                record.Data = new byte[pEndPointInfo->payLoad.cbPayload];
                                Marshal.Copy(pEndPointInfo->payLoad.pbPayload, record.Data, 0, (int)pEndPointInfo->payLoad.cbPayload);
                            }
                            //record.EndPointList = new IPEndPoint[pEndPointInfo->cAddresses];
                            IntPtr ppSOCKADDRs = pEndPointInfo->ArrayOfSOCKADDRIN6Pointers;
                            for (UInt32 j = 0; j < pEndPointInfo->cAddresses; j++)
                            {
                                IntPtr pSOCKADDR = Marshal.ReadIntPtr(ppSOCKADDRs);

                                byte[] AddressFamilyBuffer = new byte[2];
                                Marshal.Copy(pSOCKADDR, AddressFamilyBuffer, 0, 2);
                                int addressFamily = 0;
#if BIGENDIAN
                                addressFamily = AddressFamilyBuffer[1] + ((int)AddressFamilyBuffer[0] << 8);
#else
                                addressFamily = AddressFamilyBuffer[0] + ((int)AddressFamilyBuffer[1] << 8);
#endif
                                byte[] buffer = new byte[((AddressFamily)addressFamily == AddressFamily.InterNetwork) ? SystemNetHelpers.IPv4AddressSize : SystemNetHelpers.IPv6AddressSize];
                                Marshal.Copy(pSOCKADDR, buffer, 0, buffer.Length);
                                IPEndPoint ipe = SystemNetHelpers.IPEndPointFromSOCKADDRBuffer(buffer);
                                record.EndPointCollection.Add(ipe);
                                ppSOCKADDRs = (IntPtr)((long)ppSOCKADDRs + Marshal.SizeOf(typeof(IntPtr)));
                            }
                        }
                    }
                    finally
                    {
                        shEndPointInfo.Dispose();
                    }
                    record.TracePeerNameRecord();
                    m_PeerNameRecordCollection.Add(record);

                    ResolveProgressChangedEventArgs resolveProgressChangedEventArgs = new ResolveProgressChangedEventArgs(
                        record, m_AsyncOp.UserSuppliedState);


                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId,
                                                      "Proceeding to call progress changed event callback");
                    parent = m_PeerNameResolverWeakReference.Target as PeerNameResolver;
                    if (parent != null)
                    {
                        parent.PrepareToRaiseProgressChangedEvent(m_AsyncOp, resolveProgressChangedEventArgs);
                    }
                    return;
                }
            }

            ResolveCompletedEventArgs resolveCompletedEventArgs;
            if (result == PEER_E_NO_MORE)
            {
                resolveCompletedEventArgs = new ResolveCompletedEventArgs(m_PeerNameRecordCollection,
                                                                          null, false, m_AsyncOp.UserSuppliedState);
            }
            else
            {
                PeerToPeerException ex = PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_ExceptionWhileResolvingAPeerName), result);
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId,
                                                  "Exception occurred when the native API is called to harvest an incremental resolve notification");
                resolveCompletedEventArgs = new ResolveCompletedEventArgs(null,
                                                                          ex, false, m_AsyncOp.UserSuppliedState);
            }
            parent = m_PeerNameResolverWeakReference.Target as PeerNameResolver;
            if (parent != null)
            {
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId,
                                                  "Proceeding to call the ResolveCompleted callback");
                parent.PrepareToRaiseCompletedEvent(m_AsyncOp, resolveCompletedEventArgs);
            }
            return;
        }
        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());
            }
        }
        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());
        }
        private static void GetCloudOrClouds(string cloudName, bool bGlobalCloudOnly, out CloudCollection clouds, out Cloud cloud)
        {
            cloud  = null;
            clouds = null;

            Logging.Enter(Logging.P2PTraceSource, "Cloud::GetCloudOrClouds()");

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

            Int32        result    = 0;
            UInt32       numClouds = 0;
            SafePeerData ArrayOfCloudInfoStructures = null;

            if (cloudName == null)
            {
                //-----------------------------------------
                //We need the collection only when we are not
                //getting a specific cloud
                //-----------------------------------------
                clouds = new CloudCollection();
            }
            try
            {
                //---------------------------------------------------------------
                //No perf hit here, real native call happens only one time if it
                //did not already happen
                //---------------------------------------------------------------
                UnsafeP2PNativeMethods.PnrpStartup();

                result = UnsafeP2PNativeMethods.PeerPnrpGetCloudInfo(out numClouds, out ArrayOfCloudInfoStructures);
                if (result != 0)
                {
                    throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Pnrp_CouldNotEnumerateClouds), result);
                }
                if (numClouds != 0)
                {
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Number of clouds returned {0}", numClouds);
                    IntPtr pPEER_PNRP_CLOUD_INFO = ArrayOfCloudInfoStructures.DangerousGetHandle();
                    for (ulong i = 0; i < numClouds; i++)
                    {
                        PEER_PNRP_CLOUD_INFO cloudinfo = (PEER_PNRP_CLOUD_INFO)Marshal.PtrToStructure(pPEER_PNRP_CLOUD_INFO, typeof(PEER_PNRP_CLOUD_INFO));
                        string nativeCloudName         = Marshal.PtrToStringUni(cloudinfo.pwzCloudName);
                        pPEER_PNRP_CLOUD_INFO = (IntPtr)((long)pPEER_PNRP_CLOUD_INFO + Marshal.SizeOf(typeof(PEER_PNRP_CLOUD_INFO)));
                        Cloud c = new Cloud(nativeCloudName, (PnrpScope)((int)cloudinfo.dwScope), (int)cloudinfo.dwScopeId);
                        if (cloudName == null && !bGlobalCloudOnly)
                        {
                            clouds.Add(c);
                            continue;
                        }
                        //If a specific cloud by name is required, then test for name
                        //note that scope is PnrpScope.All but we don't test that now
                        if (cloudName != null && cloudName == nativeCloudName)
                        {
                            cloud = c;
                            break;
                        }

                        if (bGlobalCloudOnly && c.Scope == PnrpScope.Global)
                        {
                            cloud = c;
                            break;
                        }
                    }
                }
                else
                {
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Warning, 0, "No Clouds returned from the native call");
                }
            }
            finally
            {
                if (ArrayOfCloudInfoStructures != null)
                {
                    ArrayOfCloudInfoStructures.Dispose();
                }
            }
            if (cloudName != null && cloud == null)
            {
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "The specific cloud name {0} asked for is not found", cloudName);
            }
            Logging.Leave(Logging.P2PTraceSource, "Cloud::GetCloudOrClouds()");
        }