1 //------------------------------------------------------------------------------
2 // <copyright file="PeerNearMe.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //------------------------------------------------------------------------------
6 namespace System.Net.PeerToPeer.Collaboration
9 using System.Collections;
10 using System.Collections.Generic;
11 using System.Collections.ObjectModel;
12 using System.Runtime.InteropServices;
13 using System.Threading;
14 using System.ComponentModel;
16 using System.Net.Mail;
17 using System.Diagnostics;
18 using System.Diagnostics.CodeAnalysis;
19 using System.Runtime.Serialization;
20 using System.Security.Permissions;
23 /// This is the event args class we give back when
24 /// we have a peer near me change event triggered by native
26 public class PeerNearMeChangedEventArgs : EventArgs
28 private PeerNearMe m_peerNearMe;
29 private PeerChangeType m_peerChangeType;
31 internal PeerNearMeChangedEventArgs(PeerNearMe peerNearMe, PeerChangeType peerChangeType)
33 m_peerNearMe = peerNearMe;
34 m_peerChangeType = peerChangeType;
37 public PeerNearMe PeerNearMe
44 public PeerChangeType PeerChangeType
47 return m_peerChangeType;
53 /// This class contains the functionality of the people near me concept
54 /// in windows collaboration i.e. people on the same subnet
57 public class PeerNearMe : Peer, IEquatable<PeerNearMe>, ISerializable
59 private string m_nickname;
62 // <SecurityKernel Critical="True" Ring="1">
63 // <ReferencesCritical Name="Method: CollaborationHelperFunctions.Initialize():System.Void" Ring="1" />
65 [System.Security.SecurityCritical]
67 CollaborationHelperFunctions.Initialize();
71 OnRefreshDataCompletedDelegate = new SendOrPostCallback(RefreshDataCompletedWaitCallback);
75 /// Constructor to enable serialization
77 [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
78 protected PeerNearMe(SerializationInfo serializationInfo, StreamingContext streamingContext)
79 :base(serializationInfo, streamingContext)
81 m_id = (Guid) serializationInfo.GetValue("_Id", typeof(Guid));
82 m_nickname = serializationInfo.GetString("_NickName");
84 OnRefreshDataCompletedDelegate = new SendOrPostCallback(RefreshDataCompletedWaitCallback);
87 public string Nickname
90 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
95 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
104 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
110 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
117 // Adds this peer to the contact manager
119 public PeerContact AddToContactManager()
121 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering AddToContactManager.");
122 PeerContact peerContact = null;
124 peerContact = PeerCollaboration.ContactManager.CreateContact(this);
125 PeerCollaboration.ContactManager.AddContact(peerContact);
128 throw new PeerToPeerException(SR.GetString(SR.Collab_AddToContactMgrFailed), (e.InnerException != null ? e.InnerException : e));
130 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving AddToContactManager.");
135 // Adds this peer to the contact manager
137 public PeerContact AddToContactManager(string displayName, string nickname, MailAddress emailAddress)
139 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering AddToContactManager with Display name: {0}" +
140 " Nickname: {1} and Email Address: {2}", displayName, nickname, emailAddress);
142 PeerContact peerContact = null;
145 peerContact = PeerCollaboration.ContactManager.CreateContact(this);
146 PeerCollaboration.ContactManager.AddContact(peerContact);
149 throw new PeerToPeerException(SR.GetString(SR.Collab_AddToContactMgrFailed), (e.InnerException != null ? e.InnerException : e));
152 peerContact.DisplayName = displayName;
153 peerContact.Nickname = nickname;
154 peerContact.EmailAddress = emailAddress;
157 PeerCollaboration.ContactManager.UpdateContact(peerContact);
160 throw new PeerToPeerException(SR.GetString(SR.Collab_AddToContactMgrFailed) + " " + SR.GetString(SR.Collab_AddToContactMgrFailedUpdate), (e.InnerException != null ? e.InnerException : e));
163 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving AddToContactManager.");
167 // <SecurityKernel Critical="True" Ring="1">
168 // <ReferencesCritical Name="Method: CollaborationHelperFunctions.Initialize():System.Void" Ring="1" />
170 [System.Security.SecurityCritical]
171 public static PeerNearMe CreateFromPeerEndPoint(PeerEndPoint peerEndPoint)
173 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering CreateFromPeerEndPoint.");
174 CollaborationHelperFunctions.Initialize();
176 if (peerEndPoint == null)
177 throw new ArgumentNullException("peerEndPoint");
178 if (peerEndPoint.EndPoint == null)
179 throw new PeerToPeerException(SR.GetString(SR.Collab_NoEndPointInPeerEndPoint));
181 PeerNearMeCollection peers = PeerCollaboration.GetPeersNearMe();
182 PeerNearMe peer = null;
184 foreach (PeerNearMe peerNearMe in peers){
185 PeerEndPointCollection peerEndPoints = peerNearMe.PeerEndPoints;
186 if ((peerEndPoints != null) && (peerEndPoints.Count != 0) && (peerEndPoints[0].Equals(peerEndPoint)))
191 // No peer found, throw
193 throw new PeerToPeerException(SR.GetString(SR.Collab_EndPointNotAPeerNearMe));
196 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving CreateFromPeerEndPoint.");
201 // Checks if we need refreshing of an unsubscribed peer near me
203 internal override void RefreshIfNeeded()
209 // Refresh the endpoint with new data from collab
211 // <SecurityKernel Critical="True" Ring="1">
212 // <ReferencesCritical Name="Method: InternalRefreshData(Object):Void" Ring="1" />
214 [System.Security.SecurityCritical]
215 public void RefreshData()
217 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
218 PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
220 InternalRefreshData(false);
223 // <SecurityKernel Critical="True" Ring="0">
224 // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabRegisterEvent(Microsoft.Win32.SafeHandles.SafeWaitHandle,System.UInt32,System.Net.PeerToPeer.Collaboration.PEER_COLLAB_EVENT_REGISTRATION&,System.Net.PeerToPeer.Collaboration.SafeCollabEvent&):System.Int32" />
225 // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabGetEventData(System.Net.PeerToPeer.Collaboration.SafeCollabEvent,System.Net.PeerToPeer.Collaboration.SafeCollabData&):System.Int32" />
226 // <SatisfiesLinkDemand Name="WaitHandle.get_SafeWaitHandle():Microsoft.Win32.SafeHandles.SafeWaitHandle" />
227 // <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
228 // <SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
229 // <ReferencesCritical Name="Local safeRefreshedEPDataEvent of type: SafeCollabEvent" Ring="1" />
230 // <ReferencesCritical Name="Local eventData of type: SafeCollabData" Ring="1" />
231 // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
232 // <ReferencesCritical Name="Method: InternalRefreshData(PeerEndPoint):Void" Ring="1" />
233 // <ReferencesCritical Name="Method: CollaborationHelperFunctions.ConvertPEER_ENDPOINTToPeerEndPoint(System.Net.PeerToPeer.Collaboration.PEER_ENDPOINT):System.Net.PeerToPeer.Collaboration.PeerEndPoint" Ring="1" />
235 [System.Security.SecurityCritical]
236 internal protected void InternalRefreshData(object state)
238 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "InternalRefreshEndpointData called.");
241 bool isAsync = (bool)state;
242 Exception exception = null;
244 AutoResetEvent refreshedEPDataEvent = new AutoResetEvent(false);
245 SafeCollabEvent safeRefreshedEPDataEvent;
247 PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION();
248 pcer.eventType = PeerCollabEventType.RequestStatusChanged;
249 pcer.pInstance = IntPtr.Zero;
252 // Register to receive status changed event from collab
254 errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent(
255 refreshedEPDataEvent.SafeWaitHandle,
258 out safeRefreshedEPDataEvent);
260 Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
261 exception = PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_ReqStatusChangedRegFailed), errorCode);
266 PeerEndPointCollection peerEndPoints = PeerEndPoints;
268 if (peerEndPoints.Count == 0) return;
271 InternalRefreshData(peerEndPoints[0]);
281 // Wait till all the endpoints are refreshed
283 while (exception == null){
284 refreshedEPDataEvent.WaitOne();
286 SafeCollabData eventData;
288 errorCode = UnsafeCollabNativeMethods.PeerCollabGetEventData(safeRefreshedEPDataEvent,
291 Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetEventData returned with errorcode {0}", errorCode);
292 exception = PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_RefreshDataFailed), errorCode);
299 PEER_COLLAB_EVENT_DATA ped = (PEER_COLLAB_EVENT_DATA)Marshal.PtrToStructure(eventData.DangerousGetHandle(),
300 typeof(PEER_COLLAB_EVENT_DATA));
302 if (ped.eventType == PeerCollabEventType.RequestStatusChanged){
303 PEER_EVENT_REQUEST_STATUS_CHANGED_DATA statusData = ped.requestStatusChangedData;
305 PeerEndPoint peerEndPoint = null;
307 if (statusData.pEndPoint != IntPtr.Zero){
308 PEER_ENDPOINT pe = (PEER_ENDPOINT)Marshal.PtrToStructure(statusData.pEndPoint, typeof(PEER_ENDPOINT));
309 peerEndPoint = CollaborationHelperFunctions.ConvertPEER_ENDPOINTToPeerEndPoint(pe);
312 if (statusData.hrChange < 0){
313 exception = PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_RefreshDataFailed), statusData.hrChange);
316 if (exception != null){
318 // Throw exception for sync but call callback for async with exception
325 // Check if this is our endpoint
327 if (PeerEndPoints[0].Equals(peerEndPoint)){
328 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Found endpoint match in Request status changed.");
331 // For async call the callback and for sync just return
334 RefreshDataCompletedEventArgs args = new
335 RefreshDataCompletedEventArgs( peerEndPoint,
338 m_refreshDataAsyncOp.UserSuppliedState);
340 if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Information)){
341 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Firing RefreshDataCompleted event with folloding peer endpoint.");
342 peerEndPoint.TracePeerEndPoint();
345 this.PrepareToRaiseRefreshDataCompletedEvent(m_refreshDataAsyncOp, args);
354 // Async case with exception fire callback here
355 // Sync would have already thrown this by now
357 if (exception != null){
358 RefreshDataCompletedEventArgs args = new
359 RefreshDataCompletedEventArgs(null,
362 m_refreshDataAsyncOp.UserSuppliedState);
363 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Firing RefreshDataCompleted event with exception {0}.", exception);
364 this.PrepareToRaiseRefreshDataCompletedEvent(m_refreshDataAsyncOp, args);
367 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving InternalRefreshEndpointData.");
371 // Refreshes on endpoint
374 // <SecurityKernel Critical="True" Ring="0">
375 // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabRefreshEndpointData(System.IntPtr):System.Int32" />
376 // <SatisfiesLinkDemand Name="GCHandle.Alloc(System.Object,System.Runtime.InteropServices.GCHandleType):System.Runtime.InteropServices.GCHandle" />
377 // <SatisfiesLinkDemand Name="GCHandle.AddrOfPinnedObject():System.IntPtr" />
378 // <SatisfiesLinkDemand Name="GCHandle.Free():System.Void" />
379 // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
381 [System.Security.SecurityCritical]
382 internal static void InternalRefreshData(PeerEndPoint peerEndPoint)
385 PEER_ENDPOINT pep = new PEER_ENDPOINT();
386 pep.peerAddress = CollaborationHelperFunctions.ConvertIPEndpointToPEER_ADDRESS(peerEndPoint.EndPoint);
388 GCHandle pepName = GCHandle.Alloc(peerEndPoint.Name, GCHandleType.Pinned);
389 pep.pwzEndpointName = pepName.AddrOfPinnedObject();
391 GCHandle peerEP = GCHandle.Alloc(pep, GCHandleType.Pinned);
392 IntPtr ptrPeerEP = peerEP.AddrOfPinnedObject();
395 errorCode = UnsafeCollabNativeMethods.PeerCollabRefreshEndpointData(ptrPeerEP);
398 if (pepName.IsAllocated) pepName.Free();
399 if (peerEP.IsAllocated) peerEP.Free();
403 Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRefreshEndpointData returned with errorcode {0}", errorCode);
404 throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_RefreshDataFailed), errorCode);
408 #region RefreshEndpoint Async variables
409 AsyncOperation m_refreshDataAsyncOp;
410 private object m_refreshDataAsyncOpLock;
411 private object RefreshDataAsyncOpLock
414 if (m_refreshDataAsyncOpLock == null){
415 object o = new object();
416 Interlocked.CompareExchange(ref m_refreshDataAsyncOpLock, o, null);
418 return m_refreshDataAsyncOpLock;
421 SendOrPostCallback OnRefreshDataCompletedDelegate;
424 private event EventHandler<RefreshDataCompletedEventArgs> m_refreshDataCompleted;
425 public event EventHandler<RefreshDataCompletedEventArgs> RefreshDataCompleted
429 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
430 PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
432 m_refreshDataCompleted += value;
436 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
437 PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
439 m_refreshDataCompleted -= value;
444 // Async refresh endpoint data
446 // <SecurityKernel Critical="True" Ring="1">
447 // <ReferencesCritical Name="Method: InternalRefreshData(Object):Void" Ring="1" />
449 [System.Security.SecurityCritical]
450 public void RefreshDataAsync(object userToken)
452 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
453 PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
455 if (userToken == null)
456 throw new ArgumentNullException("userToken");
458 lock (RefreshDataAsyncOpLock){
459 if (m_refreshDataAsyncOp != null)
460 throw new PeerToPeerException(SR.GetString(SR.Collab_DuplicateRefreshAsync));
461 m_refreshDataAsyncOp = AsyncOperationManager.CreateOperation(userToken);
463 ThreadPool.QueueUserWorkItem(new WaitCallback(InternalRefreshData), true);
465 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving RefreshDataAsync().");
468 protected void OnRefreshDataCompleted(RefreshDataCompletedEventArgs e)
470 EventHandler<RefreshDataCompletedEventArgs> handlerCopy = m_refreshDataCompleted;
472 if (handlerCopy != null){
473 handlerCopy(this, e);
474 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the refresh endpoint completed event callback.");
478 void RefreshDataCompletedWaitCallback(object operationState)
480 m_refreshDataAsyncOp = null;
481 OnRefreshDataCompleted((RefreshDataCompletedEventArgs)operationState);
484 internal void PrepareToRaiseRefreshDataCompletedEvent(AsyncOperation asyncOP, RefreshDataCompletedEventArgs args)
486 asyncOP.PostOperationCompleted(OnRefreshDataCompletedDelegate, args);
489 private static event EventHandler<PeerNearMeChangedEventArgs> s_peerNearMeChanged;
490 public static event EventHandler<PeerNearMeChangedEventArgs> PeerNearMeChanged
492 // <SecurityKernel Critical="True" Ring="1">
493 // <ReferencesCritical Name="Method: CollaborationHelperFunctions.Initialize():System.Void" Ring="1" />
494 // <ReferencesCritical Name="Method: AddPeerNearMeChanged(EventHandler`1<System.Net.PeerToPeer.Collaboration.PeerNearMeChangedEventArgs>):Void" Ring="1" />
496 [System.Security.SecurityCritical]
499 PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
500 CollaborationHelperFunctions.Initialize();
502 AddPeerNearMeChanged(value);
504 // <SecurityKernel Critical="True" Ring="1">
505 // <ReferencesCritical Name="Method: CollaborationHelperFunctions.Initialize():System.Void" Ring="1" />
506 // <ReferencesCritical Name="Method: RemovePeerNearMeChanged(EventHandler`1<System.Net.PeerToPeer.Collaboration.PeerNearMeChangedEventArgs>):Void" Ring="2" />
508 [System.Security.SecurityCritical]
511 PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
512 CollaborationHelperFunctions.Initialize();
514 RemovePeerNearMeChanged(value);
518 #region PeerNearMe changed event variables
519 private static object s_lockPNMChangedEvent;
520 private static object LockPNMChangedEvent
523 if (s_lockPNMChangedEvent == null){
524 object o = new object();
525 Interlocked.CompareExchange(ref s_lockPNMChangedEvent, o, null);
527 return s_lockPNMChangedEvent;
530 private static RegisteredWaitHandle s_registeredPNMWaitHandle;
531 private static AutoResetEvent s_peerNearMeChangedEvent;
532 private static SafeCollabEvent s_safePeerNearMeChangedEvent;
535 // <SecurityKernel Critical="True" Ring="0">
536 // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabRegisterEvent(Microsoft.Win32.SafeHandles.SafeWaitHandle,System.UInt32,System.Net.PeerToPeer.Collaboration.PEER_COLLAB_EVENT_REGISTRATION&,System.Net.PeerToPeer.Collaboration.SafeCollabEvent&):System.Int32" />
537 // <SatisfiesLinkDemand Name="WaitHandle.get_SafeWaitHandle():Microsoft.Win32.SafeHandles.SafeWaitHandle" />
538 // <ReferencesCritical Name="Method: PeerNearMeChangedCallback(Object, Boolean):Void" Ring="1" />
539 // <ReferencesCritical Name="Field: s_safePeerNearMeChangedEvent" Ring="1" />
540 // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
542 [System.Security.SecurityCritical]
543 private static void AddPeerNearMeChanged(EventHandler<PeerNearMeChangedEventArgs> cb)
546 // Register a wait handle if one has not been registered already
549 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering AddPeerNearMeChanged().");
551 lock (LockPNMChangedEvent){
552 if (s_peerNearMeChanged == null){
554 s_peerNearMeChangedEvent = new AutoResetEvent(false);
557 // Register callback with a wait handle
560 s_registeredPNMWaitHandle = ThreadPool.RegisterWaitForSingleObject(s_peerNearMeChangedEvent, //Event that triggers the callback
561 new WaitOrTimerCallback(PeerNearMeChangedCallback), //callback to be called
562 null, //state to be passed
563 -1, //Timeout - aplicable only for timers
564 false //call us everytime the event is set
566 PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION();
567 pcer.eventType = PeerCollabEventType.PeopleNearMeChanged;
568 pcer.pInstance = IntPtr.Zero;
571 // Register event with collab
574 int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent(
575 s_peerNearMeChangedEvent.SafeWaitHandle,
578 out s_safePeerNearMeChangedEvent);
580 Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
581 throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_PeerNearMeChangedRegFailed), errorCode);
584 s_peerNearMeChanged += cb;
587 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddPeerNearMeChanged() successful.");
590 // <SecurityKernel Critical="True" Ring="1">
591 // <ReferencesCritical Name="Field: s_safePeerNearMeChangedEvent" Ring="1" />
592 // <ReferencesCritical Name="Method: CollaborationHelperFunctions.CleanEventVars(System.Threading.RegisteredWaitHandle&,System.Net.PeerToPeer.Collaboration.SafeCollabEvent&,System.Threading.AutoResetEvent&):System.Void" Ring="1" />
594 [System.Security.SecurityCritical]
595 private static void RemovePeerNearMeChanged(EventHandler<PeerNearMeChangedEventArgs> cb)
597 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemovePeerNearMeChanged() called.");
598 lock (LockPNMChangedEvent){
599 s_peerNearMeChanged -= cb;
600 if (s_peerNearMeChanged == null){
601 CollaborationHelperFunctions.CleanEventVars(ref s_registeredPNMWaitHandle,
602 ref s_safePeerNearMeChangedEvent,
603 ref s_peerNearMeChangedEvent);
605 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean PeerNearMeChanged variables successful.");
608 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemovePeerNearMeChanged() successful.");
611 // <SecurityKernel Critical="True" Ring="0">
612 // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabGetEventData(System.Net.PeerToPeer.Collaboration.SafeCollabEvent,System.Net.PeerToPeer.Collaboration.SafeCollabData&):System.Int32" />
613 // <SatisfiesLinkDemand Name="SafeHandle.get_IsInvalid():System.Boolean" />
614 // <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
615 // <SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
616 // <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
617 // <ReferencesCritical Name="Local eventData of type: SafeCollabData" Ring="1" />
618 // <ReferencesCritical Name="Field: s_safePeerNearMeChangedEvent" Ring="1" />
619 // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
620 // <ReferencesCritical Name="Method: CollaborationHelperFunctions.PEER_PEOPLE_NEAR_METoPeerNearMe(System.Net.PeerToPeer.Collaboration.PEER_PEOPLE_NEAR_ME):System.Net.PeerToPeer.Collaboration.PeerNearMe" Ring="1" />
622 [System.Security.SecurityCritical]
623 private static void PeerNearMeChangedCallback(object state, bool timedOut)
625 SafeCollabData eventData = null;
628 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "PeerNearMeChangedCallback() called.");
631 PeerNearMeChangedEventArgs peerNearMeChangedArgs = null;
634 // Get the event data for the fired event
638 lock (LockPNMChangedEvent){
639 if (s_safePeerNearMeChangedEvent.IsInvalid) return;
640 errorCode = UnsafeCollabNativeMethods.PeerCollabGetEventData(s_safePeerNearMeChangedEvent,
643 if (errorCode == UnsafeCollabReturnCodes.PEER_S_NO_EVENT_DATA)
645 else if (errorCode != 0){
646 Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetEventData returned with errorcode {0}", errorCode);
647 throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetPeerNearMeChangedDataFailed), errorCode);
650 PEER_COLLAB_EVENT_DATA ped = (PEER_COLLAB_EVENT_DATA)Marshal.PtrToStructure(eventData.DangerousGetHandle(),
651 typeof(PEER_COLLAB_EVENT_DATA));
652 if (ped.eventType == PeerCollabEventType.PeopleNearMeChanged){
653 PEER_EVENT_PEOPLE_NEAR_ME_CHANGED_DATA pnmData = ped.peopleNearMeChangedData;
654 PeerNearMe peerNearMe = null;
655 if (pnmData.pPeopleNearMe != IntPtr.Zero){
656 PEER_PEOPLE_NEAR_ME pnm = (PEER_PEOPLE_NEAR_ME)Marshal.PtrToStructure(pnmData.pPeopleNearMe, typeof(PEER_PEOPLE_NEAR_ME));
657 peerNearMe = CollaborationHelperFunctions.PEER_PEOPLE_NEAR_METoPeerNearMe(pnm);
660 peerNearMeChangedArgs = new PeerNearMeChangedEventArgs(peerNearMe, pnmData.changeType);
664 if (eventData != null) eventData.Dispose();
668 // Fire the callback with the marshalled event args data
671 EventHandler<PeerNearMeChangedEventArgs> handlerCopy = s_peerNearMeChanged;
673 if ((peerNearMeChangedArgs != null) && (handlerCopy != null)){
674 handlerCopy(null, peerNearMeChangedArgs);
675 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the peer near me changed event callback.");
678 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving PeerNearMeChangedCallback().");
681 // <SecurityKernel Critical="True" Ring="1">
682 // <ReferencesCritical Name="Method: Peer.InternalInviteEndPoint(System.Guid,System.String,System.Byte[],System.Net.PeerToPeer.Collaboration.PeerEndPoint,System.Net.PeerToPeer.Collaboration.PeerContact):System.Net.PeerToPeer.Collaboration.PeerInvitationResponse" Ring="1" />
684 [System.Security.SecurityCritical]
685 public override PeerInvitationResponse Invite(PeerApplication applicationToInvite, string message,
686 byte[] invitationData)
688 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
690 PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
692 if (applicationToInvite == null)
693 throw new ArgumentNullException("applicationToInvite");
694 if (applicationToInvite.Id == Guid.Empty)
695 throw new PeerToPeerException(SR.GetString(SR.Collab_EmptyGuidError));
698 // We need at least one endpoint to send invitation to
700 PeerEndPointCollection peerEndPoints = PeerEndPoints;
702 if ((peerEndPoints == null) || (peerEndPoints.Count == 0))
703 throw new PeerToPeerException(SR.GetString(SR.Collab_NoEndpointFound));
705 PeerEndPoint peerEndPoint = PeerEndPoints[0];
707 PeerInvitationResponse response = InternalInviteEndPoint(applicationToInvite.Id, message, invitationData,
710 // throw an exception if the response type is ERROR
711 CollaborationHelperFunctions.ThrowIfInvitationResponseInvalid(response);
715 // <SecurityKernel Critical="True" Ring="1">
716 // <ReferencesCritical Name="Method: Peer.get_CurrentApplicationGuid():System.Guid" Ring="1" />
717 // <ReferencesCritical Name="Method: Peer.InternalInviteEndPoint(System.Guid,System.String,System.Byte[],System.Net.PeerToPeer.Collaboration.PeerEndPoint,System.Net.PeerToPeer.Collaboration.PeerContact):System.Net.PeerToPeer.Collaboration.PeerInvitationResponse" Ring="1" />
719 [System.Security.SecurityCritical]
720 public override PeerInvitationResponse Invite()
722 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
724 PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
726 Guid appGuid = CurrentApplicationGuid;
728 if (appGuid.Equals(Guid.Empty))
729 throw new PeerToPeerException(SR.GetString(SR.Collab_NoGuidForCurrApp));
732 // We need at least one endpoint to send invitation to
734 PeerEndPointCollection peerEndPoints = PeerEndPoints;
736 if ((peerEndPoints == null) || (peerEndPoints.Count == 0))
737 throw new PeerToPeerException(SR.GetString(SR.Collab_NoEndpointFound));
739 PeerEndPoint peerEndPoint = PeerEndPoints[0];
741 PeerInvitationResponse response = InternalInviteEndPoint(appGuid, null, null, peerEndPoint, null);
743 // throw an exception if the response type is ERROR
744 CollaborationHelperFunctions.ThrowIfInvitationResponseInvalid(response);
748 // <SecurityKernel Critical="True" Ring="1">
749 // <ReferencesCritical Name="Method: Peer.get_CurrentApplicationGuid():System.Guid" Ring="1" />
750 // <ReferencesCritical Name="Method: Peer.InternalInviteAsync(System.Guid,System.String,System.Byte[],System.Net.PeerToPeer.Collaboration.PeerEndPointCollection,System.Net.PeerToPeer.Collaboration.PeerContact,System.Object):System.Void" Ring="2" />
752 [System.Security.SecurityCritical]
753 public override void InviteAsync(Object userToken)
755 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
757 PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
759 if (userToken == null)
760 throw new ArgumentException(SR.GetString(SR.NullUserToken));
762 Guid appGuid = CurrentApplicationGuid;
764 if (appGuid.Equals(Guid.Empty))
765 throw new PeerToPeerException(SR.GetString(SR.Collab_NoGuidForCurrApp));
768 // We need at least one endpoint to send invitation to
770 PeerEndPointCollection peerEndPoints = PeerEndPoints;
772 if ((peerEndPoints == null) || (peerEndPoints.Count == 0))
773 throw new PeerToPeerException(SR.GetString(SR.Collab_NoEndpointFound));
775 InternalInviteAsync(appGuid, null, null, PeerEndPoints, null, userToken);
778 // <SecurityKernel Critical="True" Ring="2">
779 // <ReferencesCritical Name="Method: Peer.InternalInviteAsync(System.Guid,System.String,System.Byte[],System.Net.PeerToPeer.Collaboration.PeerEndPointCollection,System.Net.PeerToPeer.Collaboration.PeerContact,System.Object):System.Void" Ring="2" />
781 [System.Security.SecurityCritical]
782 public override void InviteAsync( PeerApplication applicationToInvite, string message,
783 byte[] invitationData, Object userToken)
785 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
787 PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
789 if (applicationToInvite == null)
790 throw new ArgumentNullException("applicationToInvite");
791 if (applicationToInvite.Id == Guid.Empty)
792 throw new PeerToPeerException(SR.GetString(SR.Collab_EmptyGuidError));
793 if (userToken == null)
794 throw new ArgumentException(SR.GetString(SR.NullUserToken));
797 // We need at least one endpoint to send invitation to
799 PeerEndPointCollection peerEndPoints = PeerEndPoints;
801 if ((peerEndPoints == null) || (peerEndPoints.Count == 0))
802 throw new PeerToPeerException(SR.GetString(SR.Collab_NoEndpointFound));
804 InternalInviteAsync(applicationToInvite.Id, message, invitationData,
805 peerEndPoints, null, userToken);
808 public bool Equals(PeerNearMe other)
811 throw new ArgumentNullException("other");
813 return other.Id.Equals(Id);
816 public override bool Equals(object obj)
818 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
820 PeerNearMe comparandPeerNearMe = obj as PeerNearMe;
821 if (comparandPeerNearMe != null){
822 return Guid.Equals(comparandPeerNearMe.Id, Id);
828 public new static bool Equals(object objA, object objB)
830 PeerNearMe comparandPeerNearMe1 = objA as PeerNearMe;
831 PeerNearMe comparandPeerNearMe2 = objB as PeerNearMe;
833 if ((comparandPeerNearMe1 != null) && (comparandPeerNearMe2 != null)){
834 return Guid.Equals(comparandPeerNearMe1.Id, comparandPeerNearMe2.Id);
840 public override int GetHashCode()
842 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
844 return Id.GetHashCode();
847 public override string ToString()
849 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
854 private bool m_Disposed;
856 protected override void Dispose(bool disposing)
863 base.Dispose(disposing);
868 // <SecurityKernel Critical="True" Ring="0">
869 // <SatisfiesLinkDemand Name="Peer.GetObjectData(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext):System.Void" />
871 [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Justification = "System.Net.dll is still using pre-v4 security model and needs this demand")]
872 [System.Security.SecurityCritical]
873 [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter, SerializationFormatter = true)]
874 void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
876 GetObjectData(info, context);
880 /// This is made virtual so that derived types can be implemented correctly
882 // <SecurityKernel Critical="True" Ring="0">
883 // <SatisfiesLinkDemand Name="Peer.GetObjectData(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext):System.Void" />
885 [System.Security.SecurityCritical]
886 [SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)]
887 protected override void GetObjectData(SerializationInfo info, StreamingContext context)
889 base.GetObjectData(info, context);
890 info.AddValue("_Id", m_id);
891 info.AddValue("_NickName", m_nickname);
895 // Tracing information for Peer Near Me
897 internal void TracePeerNearMe()
899 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Contents of the PeerNearMe");
900 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "\tNickname: {0}", Nickname);
901 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "\tID: {0}", Id);
902 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "\tNumber of Endpoints: {0}", PeerEndPoints.Count);
903 if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Verbose)){
905 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "\tEndPoints:");
906 foreach (PeerEndPoint peerEndPoint in PeerEndPoints)
907 peerEndPoint.TracePeerEndPoint();
915 // Manages collection of peer near me classes
918 public class PeerNearMeCollection : Collection<PeerNearMe>
920 internal PeerNearMeCollection() { }
921 protected override void SetItem(int index, PeerNearMe item)
925 throw new ArgumentNullException("item");
927 base.SetItem(index, item);
930 protected override void InsertItem(int index, PeerNearMe item)
934 throw new ArgumentNullException("item");
936 base.InsertItem(index, item);
939 public override string ToString()
942 StringBuilder builder = new StringBuilder();
944 foreach (PeerNearMe peerNearMe in this){
946 builder.Append(", ");
951 builder.Append(peerNearMe.ToString());
953 return builder.ToString();