2016-08-03 10:59:49 +00:00
//------------------------------------------------------------------------------
// <copyright file="PeerNearMe.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
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.Diagnostics.CodeAnalysis ;
using System.Runtime.Serialization ;
using System.Security.Permissions ;
/// <summary>
/// This is the event args class we give back when
/// we have a peer near me change event triggered by native
/// </summary>
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 ;
}
}
}
/// <summary>
/// This class contains the functionality of the people near me concept
/// in windows collaboration i.e. people on the same subnet
/// </summary>
[Serializable]
public class PeerNearMe : Peer , IEquatable < PeerNearMe > , ISerializable
{
private string m_nickname ;
private Guid m_id ;
// <SecurityKernel Critical="True" Ring="1">
// <ReferencesCritical Name="Method: CollaborationHelperFunctions.Initialize():System.Void" Ring="1" />
// </SecurityKernel>
[System.Security.SecurityCritical]
static PeerNearMe ( ) {
CollaborationHelperFunctions . Initialize ( ) ;
}
public PeerNearMe ( ) {
OnRefreshDataCompletedDelegate = new SendOrPostCallback ( RefreshDataCompletedWaitCallback ) ;
}
/// <summary>
/// Constructor to enable serialization
/// </summary>
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
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 ;
}
// <SecurityKernel Critical="True" Ring="1">
// <ReferencesCritical Name="Method: CollaborationHelperFunctions.Initialize():System.Void" Ring="1" />
// </SecurityKernel>
[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
//
// <SecurityKernel Critical="True" Ring="1">
// <ReferencesCritical Name="Method: InternalRefreshData(Object):Void" Ring="1" />
// </SecurityKernel>
[System.Security.SecurityCritical]
public void RefreshData ( )
{
if ( m_Disposed ) throw new ObjectDisposedException ( this . GetType ( ) . FullName ) ;
PeerCollaborationPermission . UnrestrictedPeerCollaborationPermission . Demand ( ) ;
InternalRefreshData ( false ) ;
}
// <SecurityKernel Critical="True" Ring="0">
// <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" />
// <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabGetEventData(System.Net.PeerToPeer.Collaboration.SafeCollabEvent,System.Net.PeerToPeer.Collaboration.SafeCollabData&):System.Int32" />
// <SatisfiesLinkDemand Name="WaitHandle.get_SafeWaitHandle():Microsoft.Win32.SafeHandles.SafeWaitHandle" />
// <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
// <SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
// <ReferencesCritical Name="Local safeRefreshedEPDataEvent of type: SafeCollabEvent" Ring="1" />
// <ReferencesCritical Name="Local eventData of type: SafeCollabData" Ring="1" />
// <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
// <ReferencesCritical Name="Method: InternalRefreshData(PeerEndPoint):Void" Ring="1" />
// <ReferencesCritical Name="Method: CollaborationHelperFunctions.ConvertPEER_ENDPOINTToPeerEndPoint(System.Net.PeerToPeer.Collaboration.PEER_ENDPOINT):System.Net.PeerToPeer.Collaboration.PeerEndPoint" Ring="1" />
// </SecurityKernel>
[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 ) {
//
2017-08-21 15:34:15 +00:00
// Throw exception for sync but call callback for async with exception
2016-08-03 10:59:49 +00:00
//
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." ) ;
//
2017-08-21 15:34:15 +00:00
// For async call the callback and for sync just return
2016-08-03 10:59:49 +00:00
//
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
2017-08-21 15:34:15 +00:00
// Sync would have already thrown this by now
2016-08-03 10:59:49 +00:00
//
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
//
// <SecurityKernel Critical="True" Ring="0">
// <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabRefreshEndpointData(System.IntPtr):System.Int32" />
// <SatisfiesLinkDemand Name="GCHandle.Alloc(System.Object,System.Runtime.InteropServices.GCHandleType):System.Runtime.InteropServices.GCHandle" />
// <SatisfiesLinkDemand Name="GCHandle.AddrOfPinnedObject():System.IntPtr" />
// <SatisfiesLinkDemand Name="GCHandle.Free():System.Void" />
// <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
// </SecurityKernel>
[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 < RefreshDataCompletedEventArgs > m_refreshDataCompleted ;
public event EventHandler < RefreshDataCompletedEventArgs > 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
//
// <SecurityKernel Critical="True" Ring="1">
// <ReferencesCritical Name="Method: InternalRefreshData(Object):Void" Ring="1" />
// </SecurityKernel>
[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 < RefreshDataCompletedEventArgs > 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 < PeerNearMeChangedEventArgs > s_peerNearMeChanged ;
public static event EventHandler < PeerNearMeChangedEventArgs > PeerNearMeChanged
{
// <SecurityKernel Critical="True" Ring="1">
// <ReferencesCritical Name="Method: CollaborationHelperFunctions.Initialize():System.Void" Ring="1" />
// <ReferencesCritical Name="Method: AddPeerNearMeChanged(EventHandler`1<System.Net.PeerToPeer.Collaboration.PeerNearMeChangedEventArgs>):Void" Ring="1" />
// </SecurityKernel>
[System.Security.SecurityCritical]
add
{
PeerCollaborationPermission . UnrestrictedPeerCollaborationPermission . Demand ( ) ;
CollaborationHelperFunctions . Initialize ( ) ;
AddPeerNearMeChanged ( value ) ;
}
// <SecurityKernel Critical="True" Ring="1">
// <ReferencesCritical Name="Method: CollaborationHelperFunctions.Initialize():System.Void" Ring="1" />
// <ReferencesCritical Name="Method: RemovePeerNearMeChanged(EventHandler`1<System.Net.PeerToPeer.Collaboration.PeerNearMeChangedEventArgs>):Void" Ring="2" />
// </SecurityKernel>
[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
// <SecurityKernel Critical="True" Ring="0">
// <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" />
// <SatisfiesLinkDemand Name="WaitHandle.get_SafeWaitHandle():Microsoft.Win32.SafeHandles.SafeWaitHandle" />
// <ReferencesCritical Name="Method: PeerNearMeChangedCallback(Object, Boolean):Void" Ring="1" />
// <ReferencesCritical Name="Field: s_safePeerNearMeChangedEvent" Ring="1" />
// <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
// </SecurityKernel>
[System.Security.SecurityCritical]
private static void AddPeerNearMeChanged ( EventHandler < PeerNearMeChangedEventArgs > 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." ) ;
}
// <SecurityKernel Critical="True" Ring="1">
// <ReferencesCritical Name="Field: s_safePeerNearMeChangedEvent" Ring="1" />
// <ReferencesCritical Name="Method: CollaborationHelperFunctions.CleanEventVars(System.Threading.RegisteredWaitHandle&,System.Net.PeerToPeer.Collaboration.SafeCollabEvent&,System.Threading.AutoResetEvent&):System.Void" Ring="1" />
// </SecurityKernel>
[System.Security.SecurityCritical]
private static void RemovePeerNearMeChanged ( EventHandler < PeerNearMeChangedEventArgs > 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." ) ;
}
// <SecurityKernel Critical="True" Ring="0">
// <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabGetEventData(System.Net.PeerToPeer.Collaboration.SafeCollabEvent,System.Net.PeerToPeer.Collaboration.SafeCollabData&):System.Int32" />
// <SatisfiesLinkDemand Name="SafeHandle.get_IsInvalid():System.Boolean" />
// <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
// <SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
// <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
// <ReferencesCritical Name="Local eventData of type: SafeCollabData" Ring="1" />
// <ReferencesCritical Name="Field: s_safePeerNearMeChangedEvent" Ring="1" />
// <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
// <ReferencesCritical Name="Method: CollaborationHelperFunctions.PEER_PEOPLE_NEAR_METoPeerNearMe(System.Net.PeerToPeer.Collaboration.PEER_PEOPLE_NEAR_ME):System.Net.PeerToPeer.Collaboration.PeerNearMe" Ring="1" />
// </SecurityKernel>
[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 < PeerNearMeChangedEventArgs > 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()." ) ;
}
// <SecurityKernel Critical="True" Ring="1">
// <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" />
// </SecurityKernel>
[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 ;
}
// <SecurityKernel Critical="True" Ring="1">
// <ReferencesCritical Name="Method: Peer.get_CurrentApplicationGuid():System.Guid" Ring="1" />
// <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" />
// </SecurityKernel>
[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 ;
}
// <SecurityKernel Critical="True" Ring="1">
// <ReferencesCritical Name="Method: Peer.get_CurrentApplicationGuid():System.Guid" Ring="1" />
// <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" />
// </SecurityKernel>
[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 ) ;
}
// <SecurityKernel Critical="True" Ring="2">
// <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" />
// </SecurityKernel>
[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 ) ;
}
}
}
// <SecurityKernel Critical="True" Ring="0">
// <SatisfiesLinkDemand Name="Peer.GetObjectData(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext):System.Void" />
// </SecurityKernel>
[SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Justification = "System.Net.dll is still using pre-v4 security model and needs this demand")]
[System.Security.SecurityCritical]
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter, SerializationFormatter = true)]
void ISerializable . GetObjectData ( SerializationInfo info , StreamingContext context )
{
GetObjectData ( info , context ) ;
}
/// <summary>
/// This is made virtual so that derived types can be implemented correctly
/// </summary>
// <SecurityKernel Critical="True" Ring="0">
// <SatisfiesLinkDemand Name="Peer.GetObjectData(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext):System.Void" />
// </SecurityKernel>
[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 < PeerNearMe >
{
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 ( ) ;
}
}
}