1468 lines
64 KiB
C#
1468 lines
64 KiB
C#
|
//------------------------------------------------------------------------------
|
||
|
// <copyright file="Peer.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.Text;
|
||
|
using System.Runtime.InteropServices;
|
||
|
using System.Net.Sockets;
|
||
|
using System.Net.Mail;
|
||
|
using System.ComponentModel;
|
||
|
using System.Threading;
|
||
|
using System.Diagnostics;
|
||
|
using System.Diagnostics.CodeAnalysis;
|
||
|
using System.Runtime.Serialization;
|
||
|
using System.Security.Permissions;
|
||
|
using System.IO;
|
||
|
|
||
|
/// <summary>
|
||
|
/// This is the object changed event args class we give back when
|
||
|
/// we have have an object changed event fired by native
|
||
|
/// </summary>
|
||
|
public class ObjectChangedEventArgs : EventArgs
|
||
|
{
|
||
|
private PeerEndPoint m_peerEndPoint;
|
||
|
private PeerContact m_peerContact;
|
||
|
private PeerChangeType m_peerChangeType;
|
||
|
private PeerObject m_peerObject;
|
||
|
|
||
|
internal ObjectChangedEventArgs(PeerEndPoint peerEndPoint, PeerContact peerContact,
|
||
|
PeerChangeType peerChangeType, PeerObject peerObject)
|
||
|
{
|
||
|
m_peerEndPoint = peerEndPoint;
|
||
|
m_peerContact = peerContact;
|
||
|
m_peerChangeType = peerChangeType;
|
||
|
m_peerObject = peerObject;
|
||
|
}
|
||
|
|
||
|
public PeerEndPoint PeerEndPoint
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return m_peerEndPoint;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public PeerContact PeerContact
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return m_peerContact;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public PeerChangeType PeerChangeType
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return m_peerChangeType;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public PeerObject PeerObject
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return m_peerObject;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// This is the presence changed event args class we give back when
|
||
|
/// we have have presence changed event fired by native
|
||
|
/// </summary>
|
||
|
public class PresenceChangedEventArgs : EventArgs
|
||
|
{
|
||
|
private PeerEndPoint m_peerEndPoint;
|
||
|
private PeerContact m_peerContact;
|
||
|
private PeerChangeType m_peerChangeType;
|
||
|
private PeerPresenceInfo m_peerPresenceInfo;
|
||
|
|
||
|
internal PresenceChangedEventArgs(PeerEndPoint peerEndPoint, PeerContact peerContact,
|
||
|
PeerChangeType peerChangeType, PeerPresenceInfo peerPresenceInfo)
|
||
|
{
|
||
|
m_peerEndPoint = peerEndPoint;
|
||
|
m_peerContact = peerContact;
|
||
|
m_peerChangeType = peerChangeType;
|
||
|
m_peerPresenceInfo = peerPresenceInfo;
|
||
|
}
|
||
|
|
||
|
public PeerEndPoint PeerEndPoint
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return m_peerEndPoint;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public PeerContact PeerContact
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return m_peerContact;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public PeerChangeType PeerChangeType
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return m_peerChangeType;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public PeerPresenceInfo PeerPresenceInfo
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return m_peerPresenceInfo;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// This is the event args class we give back when
|
||
|
/// we have completed the subscribeasync call
|
||
|
/// </summary>
|
||
|
public class SubscribeCompletedEventArgs : AsyncCompletedEventArgs
|
||
|
{
|
||
|
private PeerNearMe m_peerNearMe;
|
||
|
private PeerContact m_peerContact;
|
||
|
|
||
|
internal SubscribeCompletedEventArgs(PeerNearMe peerNearMe,
|
||
|
PeerContact peerContact,
|
||
|
Exception error,
|
||
|
bool cancelled,
|
||
|
object userToken)
|
||
|
: base(error, cancelled, userToken)
|
||
|
{
|
||
|
m_peerNearMe = peerNearMe;
|
||
|
m_peerContact = peerContact;
|
||
|
}
|
||
|
|
||
|
public PeerNearMe PeerNearMe
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return m_peerNearMe;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public PeerContact PeerContact
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return m_peerContact;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// This is the event args class we give back when
|
||
|
/// we have completed the refreshendpoint async call
|
||
|
/// </summary>
|
||
|
public class RefreshDataCompletedEventArgs : AsyncCompletedEventArgs
|
||
|
{
|
||
|
private PeerEndPoint m_peerEndPoint;
|
||
|
internal RefreshDataCompletedEventArgs(PeerEndPoint peerEndPoint,
|
||
|
Exception error,
|
||
|
bool cancelled,
|
||
|
object userToken)
|
||
|
: base(error, cancelled, userToken)
|
||
|
{
|
||
|
m_peerEndPoint = peerEndPoint;
|
||
|
}
|
||
|
|
||
|
public PeerEndPoint PeerEndPoint
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return m_peerEndPoint;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// This is the event args class we give back when
|
||
|
/// we have completed the inviteasync call
|
||
|
/// </summary>
|
||
|
public class InviteCompletedEventArgs : AsyncCompletedEventArgs
|
||
|
{
|
||
|
private PeerInvitationResponse m_peerInvResponse;
|
||
|
internal InviteCompletedEventArgs(PeerInvitationResponse peerInvResponse,
|
||
|
Exception error,
|
||
|
bool cancelled,
|
||
|
object userToken)
|
||
|
: base(error, cancelled, userToken)
|
||
|
{
|
||
|
m_peerInvResponse = peerInvResponse;
|
||
|
}
|
||
|
|
||
|
public PeerInvitationResponse InviteResponse
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return m_peerInvResponse;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Has the common interface for PeerNearMe and PeerContact which derive from it
|
||
|
/// </summary>
|
||
|
[Serializable]
|
||
|
public abstract class Peer : IDisposable, IEquatable<Peer>, ISerializable
|
||
|
{
|
||
|
private PeerEndPointCollection m_peerEndPoints = new PeerEndPointCollection();
|
||
|
private ISynchronizeInvoke m_synchronizingObject;
|
||
|
|
||
|
public virtual PeerEndPointCollection PeerEndPoints
|
||
|
{
|
||
|
get {
|
||
|
if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
|
||
|
|
||
|
return m_peerEndPoints;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public bool IsOnline
|
||
|
{
|
||
|
get{
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Get Isonline called.");
|
||
|
if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
|
||
|
|
||
|
bool isOnline = false;
|
||
|
PeerPresenceInfo presenceInfo;
|
||
|
|
||
|
foreach (PeerEndPoint peerEndPoint in PeerEndPoints){
|
||
|
presenceInfo = null;
|
||
|
|
||
|
try{
|
||
|
presenceInfo = GetPresenceInfo(peerEndPoint);
|
||
|
}
|
||
|
catch (Exception e){
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "Exception thrown {0}", e.Message);
|
||
|
}
|
||
|
if ((presenceInfo != null) && (presenceInfo.PresenceStatus == PeerPresenceStatus.Online)){
|
||
|
isOnline = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving Isonline called with {0}.", isOnline);
|
||
|
return isOnline;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Gets and set the object used to marshall event handlers calls for stand alone
|
||
|
/// events
|
||
|
/// </summary>
|
||
|
[Browsable(false), DefaultValue(null), Description(SR.SynchronizingObject)]
|
||
|
public ISynchronizeInvoke SynchronizingObject
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
|
||
|
return m_synchronizingObject;
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
|
||
|
m_synchronizingObject = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static internal Guid CurrentApplicationGuid
|
||
|
{
|
||
|
// <SecurityKernel Critical="True" Ring="0">
|
||
|
// <SatisfiesLinkDemand Name="Process.GetCurrentProcess():System.Diagnostics.Process" />
|
||
|
// <SatisfiesLinkDemand Name="Process.get_ProcessName():System.String" />
|
||
|
// </SecurityKernel>
|
||
|
[System.Security.SecurityCritical]
|
||
|
get{
|
||
|
Guid guid = Guid.Empty;
|
||
|
|
||
|
//
|
||
|
// Get path and args of app
|
||
|
//
|
||
|
string path = Path.Combine( Environment.CurrentDirectory, Process.GetCurrentProcess().ProcessName + ".exe");
|
||
|
string arguments = null;
|
||
|
string[] argsArray = Environment.GetCommandLineArgs();
|
||
|
int length = argsArray.Length;
|
||
|
if (length > 1){
|
||
|
StringBuilder argsBuilder = new StringBuilder();
|
||
|
for (int i = 1; i < length; ++i){
|
||
|
argsBuilder.Append(argsArray[i]);
|
||
|
if (i != (length - 1)) argsBuilder.Append(' ');
|
||
|
}
|
||
|
|
||
|
arguments = argsBuilder.ToString();
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Find a matching registered application and return its guid
|
||
|
//
|
||
|
PeerApplicationCollection peerApplications = PeerCollaboration.GetLocalRegisteredApplications();
|
||
|
|
||
|
foreach (PeerApplication peerApplication in peerApplications){
|
||
|
if ((peerApplication.CommandLineArgs == arguments) &&
|
||
|
(peerApplication.Path == path))
|
||
|
return peerApplication.Id;
|
||
|
}
|
||
|
return guid;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal Peer(){
|
||
|
OnInviteCompletedDelegate = new SendOrPostCallback(InviteCompletedWaitCallback);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Constructor to enable serialization
|
||
|
/// </summary>
|
||
|
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
|
||
|
protected Peer(SerializationInfo serializationInfo, StreamingContext streamingContext):this()
|
||
|
{
|
||
|
m_peerEndPoints = (PeerEndPointCollection)serializationInfo.GetValue("_PeerEndPoints", typeof(PeerEndPointCollection));
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Gets the presence info from collab for a specific endpoint
|
||
|
//
|
||
|
// <SecurityKernel Critical="True" Ring="0">
|
||
|
// <SatisfiesLinkDemand Name="GCHandle.Alloc(System.Object,System.Runtime.InteropServices.GCHandleType):System.Runtime.InteropServices.GCHandle" />
|
||
|
// <SatisfiesLinkDemand Name="GCHandle.AddrOfPinnedObject():System.IntPtr" />
|
||
|
// <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
|
||
|
// <SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
|
||
|
// <SatisfiesLinkDemand Name="GCHandle.Free():System.Void" />
|
||
|
// <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
|
||
|
// <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabGetPresenceInfo(System.IntPtr,System.Net.PeerToPeer.Collaboration.SafeCollabData&):System.Int32" />
|
||
|
// <ReferencesCritical Name="Local presenceInfo of type: SafeCollabData" Ring="1" />
|
||
|
// <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
|
||
|
// </SecurityKernel>
|
||
|
[System.Security.SecurityCritical]
|
||
|
public PeerPresenceInfo GetPresenceInfo(PeerEndPoint peerEndPoint)
|
||
|
{
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "GetPresenceInfo()called.");
|
||
|
if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
|
||
|
PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
|
||
|
|
||
|
if (peerEndPoint == null)
|
||
|
throw new ArgumentNullException("peerEndPoint");
|
||
|
|
||
|
if (peerEndPoint.EndPoint == null)
|
||
|
throw new ArgumentException(SR.GetString(SR.Collab_NoEndPointInPeerEndPoint));
|
||
|
|
||
|
if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Information)){
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Getting presence for the following endpoint.");
|
||
|
peerEndPoint.TracePeerEndPoint();
|
||
|
}
|
||
|
|
||
|
SafeCollabData presenceInfo = null;
|
||
|
PeerPresenceInfo peerPresenceInfo = null;
|
||
|
int errorCode;
|
||
|
|
||
|
PEER_ENDPOINT pep = new PEER_ENDPOINT();
|
||
|
pep.peerAddress = CollaborationHelperFunctions.ConvertIPEndpointToPEER_ADDRESS(peerEndPoint.EndPoint);
|
||
|
|
||
|
//
|
||
|
// Pin all the data to pass to native
|
||
|
//
|
||
|
GCHandle pepName = new GCHandle();
|
||
|
|
||
|
if (peerEndPoint.Name != null){
|
||
|
pepName = GCHandle.Alloc(peerEndPoint.Name, GCHandleType.Pinned);
|
||
|
pep.pwzEndpointName = pepName.AddrOfPinnedObject();
|
||
|
}
|
||
|
|
||
|
GCHandle peerEP = GCHandle.Alloc(pep, GCHandleType.Pinned);
|
||
|
IntPtr ptrPeerEP = peerEP.AddrOfPinnedObject();
|
||
|
|
||
|
//
|
||
|
// Refresh data for getting presence info
|
||
|
//
|
||
|
RefreshIfNeeded();
|
||
|
|
||
|
try{
|
||
|
errorCode = UnsafeCollabNativeMethods.PeerCollabGetPresenceInfo(ptrPeerEP, out presenceInfo);
|
||
|
if (errorCode != 0){
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetPresenceInfo returned with errorcode {0}", errorCode);
|
||
|
throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetPresenceFailed), errorCode);
|
||
|
}
|
||
|
|
||
|
IntPtr ptrPeerPresenceInfo = presenceInfo.DangerousGetHandle();
|
||
|
PEER_PRESENCE_INFO ppi = (PEER_PRESENCE_INFO)Marshal.PtrToStructure(ptrPeerPresenceInfo, typeof(PEER_PRESENCE_INFO));
|
||
|
peerPresenceInfo = new PeerPresenceInfo();
|
||
|
peerPresenceInfo.PresenceStatus = ppi.status;
|
||
|
peerPresenceInfo.DescriptiveText = ppi.descText;
|
||
|
}
|
||
|
finally{
|
||
|
if (pepName.IsAllocated) pepName.Free();
|
||
|
if (peerEP.IsAllocated) peerEP.Free();
|
||
|
if (presenceInfo != null) presenceInfo.Dispose();
|
||
|
}
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving GetPresenceInfo().");
|
||
|
|
||
|
return peerPresenceInfo;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Gets all the objects for all the endpoints
|
||
|
//
|
||
|
// <SecurityKernel Critical="True" Ring="2">
|
||
|
// <ReferencesCritical Name="Method: InternalGetAllObjects(Guid, Boolean):PeerObjectCollection" Ring="2" />
|
||
|
// </SecurityKernel>
|
||
|
[System.Security.SecurityCritical]
|
||
|
public PeerObjectCollection GetObjects()
|
||
|
{
|
||
|
PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
|
||
|
|
||
|
return InternalGetAllObjects(Guid.Empty, false);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Gets specific object for all the endpoints
|
||
|
//
|
||
|
// <SecurityKernel Critical="True" Ring="2">
|
||
|
// <ReferencesCritical Name="Method: InternalGetAllObjects(Guid, Boolean):PeerObjectCollection" Ring="2" />
|
||
|
// </SecurityKernel>
|
||
|
[System.Security.SecurityCritical]
|
||
|
public PeerObjectCollection GetObjects(Guid objectId)
|
||
|
{
|
||
|
PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
|
||
|
|
||
|
return InternalGetAllObjects(objectId, true);
|
||
|
}
|
||
|
|
||
|
internal abstract void RefreshIfNeeded();
|
||
|
|
||
|
// <SecurityKernel Critical="True" Ring="1">
|
||
|
// <ReferencesCritical Name="Method: InternalGetObjects(Guid, Boolean, PeerEndPoint):PeerObjectCollection" Ring="1" />
|
||
|
// </SecurityKernel>
|
||
|
[System.Security.SecurityCritical]
|
||
|
private PeerObjectCollection InternalGetAllObjects(Guid objectId, bool guidSupplied)
|
||
|
{
|
||
|
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering InternalGetAllObjects() with ObjectId {0}.", objectId);
|
||
|
|
||
|
Dictionary<Guid, PeerObject> mergedObjects = new Dictionary<Guid, PeerObject>();
|
||
|
PeerObjectCollection peerObjectCollection;
|
||
|
|
||
|
//
|
||
|
// Refresh the data at the endpoint before calling get objs
|
||
|
//
|
||
|
RefreshIfNeeded();
|
||
|
|
||
|
foreach (PeerEndPoint peerEndPoint in PeerEndPoints)
|
||
|
{
|
||
|
peerObjectCollection = InternalGetObjects(objectId, guidSupplied, peerEndPoint);
|
||
|
|
||
|
//
|
||
|
// Special case. If we have already found an endpoint with the user guid then
|
||
|
// we just return it
|
||
|
//
|
||
|
if (guidSupplied && peerObjectCollection.Count != 0)
|
||
|
return peerObjectCollection;
|
||
|
|
||
|
foreach (PeerObject peerObject in peerObjectCollection)
|
||
|
{
|
||
|
mergedObjects[peerObject.Id] = peerObject;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Return the object collection from the dictionary
|
||
|
//
|
||
|
|
||
|
Dictionary<Guid, PeerObject>.ValueCollection objects = mergedObjects.Values;
|
||
|
peerObjectCollection = new PeerObjectCollection();
|
||
|
foreach (PeerObject peerObject in objects)
|
||
|
{
|
||
|
peerObjectCollection.Add(peerObject);
|
||
|
}
|
||
|
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving InternalGetAllObjects(). " +
|
||
|
"Returning collection with {0} objects.", peerObjectCollection.Count);
|
||
|
|
||
|
return peerObjectCollection;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Gets specific objects for an endpoint
|
||
|
//
|
||
|
// <SecurityKernel Critical="True" Ring="0">
|
||
|
// <UsesUnsafeCode Name="Local pObjects of type: IntPtr*" />
|
||
|
// <UsesUnsafeCode Name="Local pPeerObject of type: PEER_OBJECT*" />
|
||
|
// <UsesUnsafeCode Name="Method: IntPtr.op_Explicit(System.IntPtr):System.Void*" />
|
||
|
// <SatisfiesLinkDemand Name="GCHandle.Alloc(System.Object,System.Runtime.InteropServices.GCHandleType):System.Runtime.InteropServices.GCHandle" />
|
||
|
// <SatisfiesLinkDemand Name="GCHandle.AddrOfPinnedObject():System.IntPtr" />
|
||
|
// <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
|
||
|
// <SatisfiesLinkDemand Name="Marshal.Copy(System.IntPtr,System.Byte[],System.Int32,System.Int32):System.Void" />
|
||
|
// <SatisfiesLinkDemand Name="GCHandle.Free():System.Void" />
|
||
|
// <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
|
||
|
// <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabEnumObjects(System.IntPtr,System.IntPtr,System.Net.PeerToPeer.Collaboration.SafeCollabEnum&):System.Int32" />
|
||
|
// <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerGetItemCount(System.Net.PeerToPeer.Collaboration.SafeCollabEnum,System.UInt32&):System.Int32" />
|
||
|
// <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerGetNextItem(System.Net.PeerToPeer.Collaboration.SafeCollabEnum,System.UInt32&,System.Net.PeerToPeer.Collaboration.SafeCollabData&):System.Int32" />
|
||
|
// <ReferencesCritical Name="Local handlePeerEnum of type: SafeCollabEnum" Ring="1" />
|
||
|
// <ReferencesCritical Name="Local objectArray of type: SafeCollabData" Ring="1" />
|
||
|
// <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
|
||
|
// </SecurityKernel>
|
||
|
[System.Security.SecurityCritical]
|
||
|
internal static PeerObjectCollection InternalGetObjects(Guid objectId, bool guidSupplied, PeerEndPoint peerEndPoint)
|
||
|
{
|
||
|
if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Information)){
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering InternalGetObjects() with the following PeerEndPoint");
|
||
|
peerEndPoint.TracePeerEndPoint();
|
||
|
}
|
||
|
|
||
|
PeerObjectCollection peerObjectColl = new PeerObjectCollection();
|
||
|
SafeCollabEnum handlePeerEnum = null;
|
||
|
UInt32 objectCount = 0;
|
||
|
int errorCode = 0;
|
||
|
|
||
|
|
||
|
GCHandle guidHandle = new GCHandle();
|
||
|
IntPtr guidPtr = IntPtr.Zero;
|
||
|
|
||
|
if (guidSupplied){
|
||
|
GUID guid = CollaborationHelperFunctions.ConvertGuidToGUID(objectId);
|
||
|
guidHandle = GCHandle.Alloc(guid, GCHandleType.Pinned);
|
||
|
guidPtr = guidHandle.AddrOfPinnedObject();
|
||
|
}
|
||
|
|
||
|
PEER_ENDPOINT pep = new PEER_ENDPOINT();
|
||
|
pep.peerAddress = CollaborationHelperFunctions.ConvertIPEndpointToPEER_ADDRESS(peerEndPoint.EndPoint);
|
||
|
|
||
|
//
|
||
|
// Pin data to pass to native
|
||
|
//
|
||
|
|
||
|
GCHandle pepName = new GCHandle();
|
||
|
|
||
|
if (peerEndPoint.Name != null){
|
||
|
pepName = GCHandle.Alloc(peerEndPoint.Name, GCHandleType.Pinned);
|
||
|
pep.pwzEndpointName = pepName.AddrOfPinnedObject();
|
||
|
}
|
||
|
GCHandle peerEP = GCHandle.Alloc(pep, GCHandleType.Pinned);
|
||
|
IntPtr ptrPeerEP = peerEP.AddrOfPinnedObject();
|
||
|
|
||
|
try{
|
||
|
//
|
||
|
// Enumerate through the objects for the endpoint
|
||
|
//
|
||
|
|
||
|
errorCode = UnsafeCollabNativeMethods.PeerCollabEnumObjects(ptrPeerEP, guidPtr, out handlePeerEnum);
|
||
|
|
||
|
if (errorCode != 0){
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabEnumObjects returned with errorcode {0}", errorCode);
|
||
|
throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetObjectsFailed), errorCode);
|
||
|
}
|
||
|
|
||
|
errorCode = UnsafeCollabNativeMethods.PeerGetItemCount(handlePeerEnum, ref objectCount);
|
||
|
if (errorCode != 0){
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerGetItemCount returned with errorcode {0}", errorCode);
|
||
|
throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetObjectsFailed), errorCode);
|
||
|
}
|
||
|
|
||
|
if (objectCount == 0){
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "No PeerObjects found.");
|
||
|
return peerObjectColl;
|
||
|
}
|
||
|
unsafe
|
||
|
{
|
||
|
SafeCollabData objectArray;
|
||
|
errorCode = UnsafeCollabNativeMethods.PeerGetNextItem(handlePeerEnum, ref objectCount, out objectArray);
|
||
|
if (errorCode != 0){
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerGetNextItem returned with errorcode {0}", errorCode);
|
||
|
throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetObjectsFailed), errorCode);
|
||
|
}
|
||
|
|
||
|
IntPtr pPEER_OBJECT = objectArray.DangerousGetHandle();
|
||
|
IntPtr* pObjects = (IntPtr*)pPEER_OBJECT;
|
||
|
|
||
|
//
|
||
|
// Loop through the applications array from native
|
||
|
//
|
||
|
for (ulong i = 0; i < objectCount; i++){
|
||
|
PEER_OBJECT* pPeerObject = (PEER_OBJECT*)pObjects[i];
|
||
|
byte[] data = null;
|
||
|
|
||
|
if (pPeerObject->data.cbData != 0){
|
||
|
data = new byte[pPeerObject->data.cbData];
|
||
|
Marshal.Copy(pPeerObject->data.pbData, data, 0, (int)pPeerObject->data.cbData);
|
||
|
}
|
||
|
|
||
|
PeerObject peerObject = new PeerObject(CollaborationHelperFunctions.ConvertGUIDToGuid(pPeerObject->guid), data, (PeerScope)pPeerObject->dwPublicationScope);
|
||
|
|
||
|
if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Information)){
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Retrieved following Object");
|
||
|
peerObject.TracePeerObject();
|
||
|
}
|
||
|
|
||
|
peerObjectColl.Add(peerObject);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
finally{
|
||
|
if (guidHandle.IsAllocated) guidHandle.Free();
|
||
|
if (pepName.IsAllocated) pepName.Free();
|
||
|
if (peerEP.IsAllocated) peerEP.Free();
|
||
|
if (handlePeerEnum != null) handlePeerEnum.Dispose();
|
||
|
}
|
||
|
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving InternalGetApplications(). " +
|
||
|
"Returning collection with {0} objects.", peerObjectColl.Count);
|
||
|
|
||
|
return peerObjectColl;
|
||
|
}
|
||
|
|
||
|
public abstract PeerInvitationResponse Invite();
|
||
|
|
||
|
public abstract PeerInvitationResponse Invite(PeerApplication applicationToInvite, string message, byte[] invitationData);
|
||
|
|
||
|
//
|
||
|
// Invites an endpoint with passed data. Includes a contact if it was passed in.
|
||
|
//
|
||
|
// <SecurityKernel Critical="True" Ring="0">
|
||
|
// <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
|
||
|
// <SatisfiesLinkDemand Name="Marshal.Copy(System.Byte[],System.Int32,System.IntPtr,System.Int32):System.Void" />
|
||
|
// <SatisfiesLinkDemand Name="GCHandle.Alloc(System.Object,System.Runtime.InteropServices.GCHandleType):System.Runtime.InteropServices.GCHandle" />
|
||
|
// <SatisfiesLinkDemand Name="GCHandle.AddrOfPinnedObject():System.IntPtr" />
|
||
|
// <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
|
||
|
// <SatisfiesLinkDemand Name="SafeHandle.get_IsInvalid():System.Boolean" />
|
||
|
// <SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
|
||
|
// <SatisfiesLinkDemand Name="GCHandle.Free():System.Void" />
|
||
|
// <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabInviteContact(System.Net.PeerToPeer.Collaboration.PEER_CONTACT&,System.IntPtr,System.Net.PeerToPeer.Collaboration.PEER_INVITATION&,System.Net.PeerToPeer.Collaboration.SafeCollabData&):System.Int32" />
|
||
|
// <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabInviteEndpoint(System.IntPtr,System.Net.PeerToPeer.Collaboration.PEER_INVITATION&,System.Net.PeerToPeer.Collaboration.SafeCollabData&):System.Int32" />
|
||
|
// <ReferencesCritical Name="Local data of type: SafeCollabMemory" Ring="1" />
|
||
|
// <ReferencesCritical Name="Local safeResponse of type: SafeCollabData" Ring="1" />
|
||
|
// <ReferencesCritical Name="Local safeCredentials of type: SafeCollabMemory" Ring="1" />
|
||
|
// <ReferencesCritical Name="Method: SafeCollabMemory..ctor(System.Int32)" Ring="1" />
|
||
|
// <ReferencesCritical Name="Method: CollaborationHelperFunctions.ConvertPeerContactToPEER_CONTACT(System.Net.PeerToPeer.Collaboration.PeerContact,System.Net.PeerToPeer.Collaboration.SafeCollabMemory&):System.Net.PeerToPeer.Collaboration.PEER_CONTACT" Ring="1" />
|
||
|
// <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
|
||
|
// </SecurityKernel>
|
||
|
[System.Security.SecurityCritical]
|
||
|
internal static PeerInvitationResponse InternalInviteEndPoint(Guid applicationToInviteGuid,
|
||
|
string message, byte[] invitationData,
|
||
|
PeerEndPoint peerEndPoint, PeerContact peerContact)
|
||
|
{
|
||
|
|
||
|
if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Information)){
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering InternalInviteEndPoint() with the following information.");
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Invitation Message: ", message);
|
||
|
if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Verbose) && (invitationData != null)){
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "\tInvitation data:");
|
||
|
Logging.DumpData(Logging.P2PTraceSource, TraceEventType.Verbose, Logging.P2PTraceSource.MaxDataSize, invitationData, 0, invitationData.Length);
|
||
|
}
|
||
|
else
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Invitation Data length: ", (invitationData != null ? invitationData.Length : 0));
|
||
|
|
||
|
if (peerEndPoint != null) peerEndPoint.TracePeerEndPoint();
|
||
|
}
|
||
|
|
||
|
PEER_INVITATION pi = new PEER_INVITATION();
|
||
|
pi.applicationId = CollaborationHelperFunctions.ConvertGuidToGUID(applicationToInviteGuid);
|
||
|
pi.pwzMessage = message;
|
||
|
|
||
|
SafeCollabMemory data = null;
|
||
|
pi.applicationData.cbData = (invitationData != null) ? (UInt32)invitationData.Length : 0;
|
||
|
|
||
|
//
|
||
|
// Marshal Invitation Data
|
||
|
//
|
||
|
if ((invitationData != null) && (invitationData.Length > 0))
|
||
|
{
|
||
|
data = new SafeCollabMemory(invitationData.Length);
|
||
|
pi.applicationData.pbData = data.DangerousGetHandle();
|
||
|
Marshal.Copy(invitationData, 0, pi.applicationData.pbData, invitationData.Length);
|
||
|
}
|
||
|
else
|
||
|
pi.applicationData.pbData = IntPtr.Zero;
|
||
|
|
||
|
|
||
|
PEER_ENDPOINT pep = new PEER_ENDPOINT();
|
||
|
pep.peerAddress = CollaborationHelperFunctions.ConvertIPEndpointToPEER_ADDRESS(peerEndPoint.EndPoint);
|
||
|
|
||
|
//
|
||
|
// Pin data to pass to native
|
||
|
//
|
||
|
GCHandle pepName = new GCHandle();
|
||
|
|
||
|
if (peerEndPoint.Name != null){
|
||
|
pepName = GCHandle.Alloc(peerEndPoint.Name, GCHandleType.Pinned);
|
||
|
pep.pwzEndpointName = pepName.AddrOfPinnedObject();
|
||
|
}
|
||
|
GCHandle peerEP = GCHandle.Alloc(pep, GCHandleType.Pinned);
|
||
|
IntPtr ptrPeerEP = peerEP.AddrOfPinnedObject();
|
||
|
|
||
|
SafeCollabData safeResponse = null;
|
||
|
PeerInvitationResponse peerInvResponse = null;
|
||
|
int errorCode;
|
||
|
|
||
|
try{
|
||
|
//
|
||
|
// Make native call with endpoint with/without contact
|
||
|
//
|
||
|
if (peerContact != null){
|
||
|
|
||
|
//
|
||
|
// Generate native contact
|
||
|
//
|
||
|
SafeCollabMemory safeCredentials = null;
|
||
|
PEER_CONTACT pc = CollaborationHelperFunctions.ConvertPeerContactToPEER_CONTACT(peerContact, ref safeCredentials);
|
||
|
|
||
|
try{
|
||
|
errorCode = UnsafeCollabNativeMethods.PeerCollabInviteContact(ref pc,
|
||
|
ptrPeerEP,
|
||
|
ref pi,
|
||
|
out safeResponse);
|
||
|
}
|
||
|
finally{
|
||
|
if (safeCredentials != null) safeCredentials.Dispose();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
errorCode = UnsafeCollabNativeMethods.PeerCollabInviteEndpoint(ptrPeerEP, ref pi, out safeResponse);
|
||
|
|
||
|
if (errorCode != 0){
|
||
|
if ((errorCode == UnsafeCollabReturnCodes.PEER_E_TIMEOUT) || (errorCode == UnsafeCollabReturnCodes.ERROR_TIMEOUT)){
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0,
|
||
|
"Timed out. Leaving InternalInviteEndPoint() with InvitationResponseType expired.");
|
||
|
|
||
|
return new PeerInvitationResponse(PeerInvitationResponseType.Expired);
|
||
|
}
|
||
|
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, ((peerContact != null) ? "PeerCollabInviteContact" : "PeerCollabInviteEndpoint")
|
||
|
+ " returned with errorcode {0}", errorCode);
|
||
|
throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_InviteFailed), errorCode);
|
||
|
}
|
||
|
|
||
|
if (!safeResponse.IsInvalid){
|
||
|
PEER_INVITATION_RESPONSE pir = (PEER_INVITATION_RESPONSE)Marshal.PtrToStructure(safeResponse.DangerousGetHandle(),
|
||
|
typeof(PEER_INVITATION_RESPONSE));
|
||
|
peerInvResponse = new PeerInvitationResponse(pir.action);
|
||
|
}
|
||
|
}
|
||
|
finally{
|
||
|
if (safeResponse != null) safeResponse.Dispose();
|
||
|
if (pepName.IsAllocated) pepName.Free();
|
||
|
if (peerEP.IsAllocated) peerEP.Free();
|
||
|
}
|
||
|
|
||
|
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0,
|
||
|
"Leaving InternalInviteEndPoint() with InvitationResponse {0}.", peerInvResponse);
|
||
|
|
||
|
return peerInvResponse;
|
||
|
}
|
||
|
|
||
|
|
||
|
private event EventHandler<InviteCompletedEventArgs> m_inviteCompleted;
|
||
|
public event EventHandler<InviteCompletedEventArgs> InviteCompleted
|
||
|
{
|
||
|
add{
|
||
|
if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
|
||
|
PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
|
||
|
|
||
|
m_inviteCompleted += value;
|
||
|
}
|
||
|
remove{
|
||
|
if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
|
||
|
PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
|
||
|
|
||
|
m_inviteCompleted -= value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public abstract void InviteAsync(Object userToken);
|
||
|
|
||
|
public abstract void InviteAsync( PeerApplication applicationToInvite, string message,
|
||
|
byte[] invitationData, Object userToken);
|
||
|
|
||
|
|
||
|
#region Invite Async variables
|
||
|
SendOrPostCallback OnInviteCompletedDelegate;
|
||
|
|
||
|
internal Dictionary<object, InviteAsyncHelper> m_inviteAsyncHelperList = new Dictionary<object, InviteAsyncHelper>();
|
||
|
#endregion
|
||
|
|
||
|
// <SecurityKernel Critical="True" Ring="1">
|
||
|
// <ReferencesCritical Name="Method: InviteAsyncHelper.InviteAsync():System.Void" Ring="1" />
|
||
|
// </SecurityKernel>
|
||
|
[System.Security.SecurityCritical]
|
||
|
internal void InternalInviteAsync(Guid applicationToInviteGuid,
|
||
|
string message, byte[] invitationData,
|
||
|
PeerEndPointCollection peerEndPoints, PeerContact peerContact,
|
||
|
Object userToken)
|
||
|
{
|
||
|
InviteAsyncHelper inviteAsyncHelper = 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_inviteAsyncHelperList){
|
||
|
if (m_inviteAsyncHelperList.ContainsKey(userToken)){
|
||
|
throw new ArgumentException(SR.GetString(SR.DuplicateUserToken));
|
||
|
}
|
||
|
|
||
|
inviteAsyncHelper = new InviteAsyncHelper( peerContact, this, peerEndPoints,
|
||
|
applicationToInviteGuid, message,
|
||
|
invitationData, userToken, newTraceEventId);
|
||
|
m_inviteAsyncHelperList[userToken] = inviteAsyncHelper;
|
||
|
}
|
||
|
|
||
|
try{
|
||
|
//
|
||
|
//Start resolution on that resolver
|
||
|
//
|
||
|
inviteAsyncHelper.InviteAsync();
|
||
|
}
|
||
|
catch{
|
||
|
//
|
||
|
//If an exception happens clear the userState from the
|
||
|
//list so that that token can be reused
|
||
|
//
|
||
|
lock (m_inviteAsyncHelperList){
|
||
|
m_inviteAsyncHelperList.Remove(userToken);
|
||
|
}
|
||
|
throw;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
protected virtual void OnInviteCompleted(InviteCompletedEventArgs e)
|
||
|
{
|
||
|
EventHandler<InviteCompletedEventArgs> handlerCopy = m_inviteCompleted;
|
||
|
|
||
|
if (handlerCopy != null){
|
||
|
handlerCopy(this, e);
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the invite completed event callback.");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void InviteCompletedWaitCallback(object operationState)
|
||
|
{
|
||
|
OnInviteCompleted((InviteCompletedEventArgs)operationState);
|
||
|
}
|
||
|
|
||
|
internal void PrepareToRaiseInviteCompletedEvent(AsyncOperation asyncOP, InviteCompletedEventArgs args)
|
||
|
{
|
||
|
lock (m_inviteAsyncHelperList){
|
||
|
InviteAsyncHelper helper = m_inviteAsyncHelperList[args.UserState];
|
||
|
if (helper == null){
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Critical, 0, "userState for which we are about to call Completed event does not exist in the pending async list");
|
||
|
}else{
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Critical, helper.TraceEventId,
|
||
|
"userState {0} is being removed from the pending async list", args.UserState.GetHashCode());
|
||
|
m_inviteAsyncHelperList.Remove(args.UserState);
|
||
|
}
|
||
|
}
|
||
|
asyncOP.PostOperationCompleted(OnInviteCompletedDelegate, args);
|
||
|
}
|
||
|
|
||
|
// <SecurityKernel Critical="True" Ring="2">
|
||
|
// <ReferencesCritical Name="Method: InviteAsyncHelper.CancelAsync(System.Object):System.Void" Ring="2" />
|
||
|
// </SecurityKernel>
|
||
|
[System.Security.SecurityCritical]
|
||
|
public void InviteAsyncCancel(Object userToken)
|
||
|
{
|
||
|
if (userToken == null)
|
||
|
throw new ArgumentNullException("userToken");
|
||
|
|
||
|
InviteAsyncHelper helper;
|
||
|
lock (m_inviteAsyncHelperList){
|
||
|
if (!m_inviteAsyncHelperList.TryGetValue(userToken, out helper)){
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Warning, 0, "InviteAsyncCancel called with a userState token that is not in the pending async list - returning");
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, helper.TraceEventId,
|
||
|
"Proceeding to cancel the pending async");
|
||
|
helper.CancelAsync(userToken);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Used to track inviteasynchelpers
|
||
|
//
|
||
|
private static int s_TraceEventId = 1;
|
||
|
internal static int NewTraceEventId
|
||
|
{
|
||
|
get{
|
||
|
Interlocked.CompareExchange(ref s_TraceEventId, 0, int.MaxValue);
|
||
|
Interlocked.Increment(ref s_TraceEventId);
|
||
|
return s_TraceEventId;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public bool Equals(Peer other)
|
||
|
{
|
||
|
if (other != null){
|
||
|
if (other.PeerEndPoints != null){
|
||
|
return other.PeerEndPoints.Equals(PeerEndPoints);
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
public override string ToString()
|
||
|
{
|
||
|
return PeerEndPoints.ToString();
|
||
|
}
|
||
|
|
||
|
private bool m_Disposed;
|
||
|
|
||
|
public void Dispose()
|
||
|
{
|
||
|
|
||
|
Dispose(true);
|
||
|
GC.SuppressFinalize(this);
|
||
|
}
|
||
|
|
||
|
// <SecurityKernel Critical="True" Ring="0">
|
||
|
// <SatisfiesLinkDemand Name="GetObjectData(SerializationInfo, StreamingContext):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>
|
||
|
/// <param name="serializationInfo"></param>
|
||
|
/// <param name="streamingContext"></param>
|
||
|
[SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)]
|
||
|
protected virtual void GetObjectData(SerializationInfo info, StreamingContext context)
|
||
|
{
|
||
|
info.AddValue("_PeerEndPoints", PeerEndPoints);
|
||
|
}
|
||
|
|
||
|
protected virtual void Dispose(bool disposing)
|
||
|
{
|
||
|
if (!m_Disposed){
|
||
|
m_Disposed = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Helps in all the async invites sent from Peer, PeerContact and PeerNearMe
|
||
|
/// </summary>
|
||
|
internal class InviteAsyncHelper : IDisposable
|
||
|
{
|
||
|
internal object m_userState;
|
||
|
internal SafeCollabInvite m_SafeCollabInvite;
|
||
|
internal AutoResetEvent m_InviteEvent = new AutoResetEvent(false);
|
||
|
|
||
|
//
|
||
|
//The WaitHandle that hooks up a callback to the
|
||
|
//event
|
||
|
//
|
||
|
internal RegisteredWaitHandle m_RegisteredWaitHandle;
|
||
|
|
||
|
//
|
||
|
//Disposed or not
|
||
|
//
|
||
|
internal bool m_Disposed;
|
||
|
|
||
|
internal bool m_Cancelled;
|
||
|
|
||
|
//
|
||
|
//Async operation to ensure synchornization
|
||
|
//context
|
||
|
//
|
||
|
AsyncOperation m_AsyncOp;
|
||
|
|
||
|
//
|
||
|
//A link to the resolver to avoid
|
||
|
//circular dependencies and enable GC
|
||
|
//
|
||
|
WeakReference m_peerWeakReference;
|
||
|
|
||
|
//
|
||
|
//Lock to make sure things don't mess up stuff
|
||
|
//
|
||
|
object m_Lock = new Object();
|
||
|
|
||
|
//
|
||
|
//EventID or Just a tracking id
|
||
|
//
|
||
|
int m_TraceEventId;
|
||
|
|
||
|
//
|
||
|
// Store the latest exception
|
||
|
//
|
||
|
Exception m_latestException;
|
||
|
|
||
|
//
|
||
|
// Stores reponses from all endpoints
|
||
|
//
|
||
|
Collection<PeerInvitationResponseType> m_responses = new Collection<PeerInvitationResponseType>();
|
||
|
|
||
|
//
|
||
|
// Callback called
|
||
|
//
|
||
|
bool m_Completed;
|
||
|
|
||
|
//
|
||
|
// Used to ensure only on thread calls the callback
|
||
|
//
|
||
|
bool m_aboutToFireCallback;
|
||
|
object m_aboutToFireCallbackLock = new object();
|
||
|
|
||
|
//
|
||
|
// Number of reponses received
|
||
|
//
|
||
|
int m_numberOfResponses;
|
||
|
|
||
|
PeerContact m_peerContact;
|
||
|
PeerEndPointCollection m_peerEndPoints;
|
||
|
Guid m_applicationId;
|
||
|
string m_message;
|
||
|
byte[] m_inviteData;
|
||
|
|
||
|
internal InviteAsyncHelper( PeerContact peerContact, Peer parentPeer, PeerEndPointCollection peerEndPoints,
|
||
|
Guid applicationId, string message, byte[] inviteData,
|
||
|
object userState, int NewTraceEventId)
|
||
|
{
|
||
|
m_userState = userState;
|
||
|
m_peerContact = peerContact;
|
||
|
m_applicationId = applicationId;
|
||
|
m_message = message;
|
||
|
m_inviteData = inviteData;
|
||
|
m_peerEndPoints = peerEndPoints;
|
||
|
m_TraceEventId = NewTraceEventId;
|
||
|
m_peerWeakReference = new WeakReference(parentPeer);
|
||
|
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "New InviteAsyncHelper created with TraceEventID {0}", m_TraceEventId);
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId,
|
||
|
"\tPeerContact: {0}, App Guid: {1}, userState {2}, ParentReference {3}",
|
||
|
(m_peerContact != null ? m_peerContact.ToString() : "null"),
|
||
|
applicationId.ToString(),
|
||
|
userState.GetHashCode(),
|
||
|
m_peerWeakReference.Target.GetHashCode()
|
||
|
);
|
||
|
|
||
|
}
|
||
|
|
||
|
// <SecurityKernel Critical="True" Ring="0">
|
||
|
// <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
|
||
|
// <SatisfiesLinkDemand Name="Marshal.Copy(System.Byte[],System.Int32,System.IntPtr,System.Int32):System.Void" />
|
||
|
// <SatisfiesLinkDemand Name="SafeHandle.get_IsInvalid():System.Boolean" />
|
||
|
// <SatisfiesLinkDemand Name="SafeHandle.get_IsClosed():System.Boolean" />
|
||
|
// <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
|
||
|
// <ReferencesCritical Name="Local data of type: SafeCollabMemory" Ring="1" />
|
||
|
// <ReferencesCritical Name="Method: InviteCallback(Object, Boolean):Void" Ring="1" />
|
||
|
// <ReferencesCritical Name="Method: SafeCollabMemory..ctor(System.Int32)" Ring="1" />
|
||
|
// <ReferencesCritical Name="Method: InviteAsyncEndPoint(PeerEndPoint, PEER_INVITATION):Void" Ring="1" />
|
||
|
// <ReferencesCritical Name="Field: m_SafeCollabInvite" Ring="1" />
|
||
|
// </SecurityKernel>
|
||
|
[System.Security.SecurityCritical]
|
||
|
internal void InviteAsync()
|
||
|
{
|
||
|
if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
|
||
|
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId,
|
||
|
"InviteAsync called");
|
||
|
//
|
||
|
//First wire up a callback
|
||
|
//
|
||
|
|
||
|
m_RegisteredWaitHandle = ThreadPool.RegisterWaitForSingleObject(m_InviteEvent, //Event that triggers the callback
|
||
|
new WaitOrTimerCallback(InviteCallback), //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
|
||
|
//
|
||
|
|
||
|
PEER_INVITATION pi = new PEER_INVITATION();
|
||
|
pi.applicationId = CollaborationHelperFunctions.ConvertGuidToGUID(m_applicationId);
|
||
|
pi.pwzMessage = m_message;
|
||
|
|
||
|
SafeCollabMemory data = null;
|
||
|
pi.applicationData.cbData = (m_inviteData != null) ? (UInt32)m_inviteData.Length : 0;
|
||
|
|
||
|
if ((m_inviteData != null) && (m_inviteData.Length > 0)){
|
||
|
data = new SafeCollabMemory(m_inviteData.Length);
|
||
|
pi.applicationData.pbData = data.DangerousGetHandle();
|
||
|
Marshal.Copy(m_inviteData, 0, pi.applicationData.pbData, m_inviteData.Length);
|
||
|
}
|
||
|
else
|
||
|
pi.applicationData.pbData = IntPtr.Zero;
|
||
|
|
||
|
foreach (PeerEndPoint peerEndPoint in m_peerEndPoints)
|
||
|
{
|
||
|
try{
|
||
|
InviteAsyncEndPoint(peerEndPoint, pi);
|
||
|
}
|
||
|
catch (PeerToPeerException){
|
||
|
if (!m_SafeCollabInvite.IsInvalid && !m_SafeCollabInvite.IsClosed){
|
||
|
m_SafeCollabInvite.Dispose();
|
||
|
}
|
||
|
m_RegisteredWaitHandle.Unregister(null);
|
||
|
m_RegisteredWaitHandle = null;
|
||
|
throw;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
//Create an async operation with the given
|
||
|
//user state
|
||
|
//
|
||
|
m_AsyncOp = AsyncOperationManager.CreateOperation(m_userState);
|
||
|
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId,
|
||
|
"Leaving InviteAsync.");
|
||
|
}
|
||
|
|
||
|
// <SecurityKernel Critical="True" Ring="0">
|
||
|
// <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabAsyncInviteContact(System.Net.PeerToPeer.Collaboration.PEER_CONTACT&,System.IntPtr,System.Net.PeerToPeer.Collaboration.PEER_INVITATION&,Microsoft.Win32.SafeHandles.SafeWaitHandle,System.Net.PeerToPeer.Collaboration.SafeCollabInvite&):System.Int32" />
|
||
|
// <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabAsyncInviteEndpoint(System.IntPtr,System.Net.PeerToPeer.Collaboration.PEER_INVITATION&,Microsoft.Win32.SafeHandles.SafeWaitHandle,System.Net.PeerToPeer.Collaboration.SafeCollabInvite&):System.Int32" />
|
||
|
// <SatisfiesLinkDemand Name="GCHandle.Alloc(System.Object,System.Runtime.InteropServices.GCHandleType):System.Runtime.InteropServices.GCHandle" />
|
||
|
// <SatisfiesLinkDemand Name="GCHandle.AddrOfPinnedObject():System.IntPtr" />
|
||
|
// <SatisfiesLinkDemand Name="WaitHandle.get_SafeWaitHandle():Microsoft.Win32.SafeHandles.SafeWaitHandle" />
|
||
|
// <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
|
||
|
// <SatisfiesLinkDemand Name="GCHandle.Free():System.Void" />
|
||
|
// <ReferencesCritical Name="Local safeCredentials of type: SafeCollabMemory" Ring="1" />
|
||
|
// <ReferencesCritical Name="Method: CollaborationHelperFunctions.ConvertPeerContactToPEER_CONTACT(System.Net.PeerToPeer.Collaboration.PeerContact,System.Net.PeerToPeer.Collaboration.SafeCollabMemory&):System.Net.PeerToPeer.Collaboration.PEER_CONTACT" Ring="1" />
|
||
|
// <ReferencesCritical Name="Field: m_SafeCollabInvite" Ring="1" />
|
||
|
// <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
|
||
|
// </SecurityKernel>
|
||
|
[System.Security.SecurityCritical]
|
||
|
internal void InviteAsyncEndPoint(PeerEndPoint peerEndPoint, PEER_INVITATION pi)
|
||
|
{
|
||
|
if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Information)){
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "InviteAsyncEndPoint() is called with the following Info");
|
||
|
peerEndPoint.TracePeerEndPoint();
|
||
|
}
|
||
|
|
||
|
PEER_ENDPOINT pep = new PEER_ENDPOINT();
|
||
|
pep.peerAddress = CollaborationHelperFunctions.ConvertIPEndpointToPEER_ADDRESS(peerEndPoint.EndPoint);
|
||
|
|
||
|
//
|
||
|
// Pin all the data to pass to native
|
||
|
//
|
||
|
GCHandle pepName = new GCHandle();
|
||
|
|
||
|
if (peerEndPoint.Name != null){
|
||
|
pepName = GCHandle.Alloc(peerEndPoint.Name, GCHandleType.Pinned);
|
||
|
pep.pwzEndpointName = pepName.AddrOfPinnedObject();
|
||
|
}
|
||
|
GCHandle peerEP = GCHandle.Alloc(pep, GCHandleType.Pinned);
|
||
|
IntPtr ptrPeerEP = peerEP.AddrOfPinnedObject();
|
||
|
|
||
|
int errorCode;
|
||
|
try{
|
||
|
//
|
||
|
// Make native call with endpoint with/without contact
|
||
|
//
|
||
|
if (m_peerContact != null){
|
||
|
|
||
|
//
|
||
|
// Generate native contact
|
||
|
//
|
||
|
SafeCollabMemory safeCredentials = null;
|
||
|
PEER_CONTACT pc = CollaborationHelperFunctions.ConvertPeerContactToPEER_CONTACT(m_peerContact, ref safeCredentials);
|
||
|
|
||
|
try{
|
||
|
errorCode = UnsafeCollabNativeMethods.PeerCollabAsyncInviteContact( ref pc,
|
||
|
ptrPeerEP,
|
||
|
ref pi,
|
||
|
m_InviteEvent.SafeWaitHandle,
|
||
|
out m_SafeCollabInvite);
|
||
|
}
|
||
|
finally{
|
||
|
if (safeCredentials != null) safeCredentials.Dispose();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
errorCode = UnsafeCollabNativeMethods.PeerCollabAsyncInviteEndpoint(ptrPeerEP, ref pi,
|
||
|
m_InviteEvent.SafeWaitHandle,
|
||
|
out m_SafeCollabInvite);
|
||
|
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
if (pepName.IsAllocated) pepName.Free();
|
||
|
if (peerEP.IsAllocated) peerEP.Free();
|
||
|
}
|
||
|
|
||
|
if (errorCode != 0){
|
||
|
throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_AsyncInviteFailed), errorCode);
|
||
|
}
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "Leaving InviteAsyncEndPoint.");
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Invite callback. Will fire only if i has at least one accepted or when it has all the responses
|
||
|
// from all the endpoints
|
||
|
//
|
||
|
// <SecurityKernel Critical="True" Ring="0">
|
||
|
// <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabGetInvitationResponse(System.Net.PeerToPeer.Collaboration.SafeCollabInvite,System.Net.PeerToPeer.Collaboration.SafeCollabData&):System.Int32" />
|
||
|
// <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 response of type: SafeCollabData" Ring="1" />
|
||
|
// <ReferencesCritical Name="Field: m_SafeCollabInvite" Ring="1" />
|
||
|
// <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
|
||
|
// </SecurityKernel>
|
||
|
[System.Security.SecurityCritical]
|
||
|
internal void InviteCallback(object state, bool timedOut)
|
||
|
{
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "Entering InviteCallback.");
|
||
|
|
||
|
SafeCollabData response = null;
|
||
|
|
||
|
int errorCode = 0;
|
||
|
InviteCompletedEventArgs inviteCompletedArgs = null;
|
||
|
Peer peer = null;
|
||
|
bool fireCallback = false;
|
||
|
PEER_INVITATION_RESPONSE pir = new PEER_INVITATION_RESPONSE();
|
||
|
|
||
|
try
|
||
|
{
|
||
|
lock (m_Lock){
|
||
|
if (m_Cancelled || m_Completed){
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "Invite cancelled({0}) or completed({1}). Returning without doing anything.", m_Cancelled, m_Completed);
|
||
|
return;
|
||
|
}
|
||
|
errorCode = UnsafeCollabNativeMethods.PeerCollabGetInvitationResponse(m_SafeCollabInvite, out response);
|
||
|
}
|
||
|
|
||
|
if ((errorCode != 0) && (errorCode != UnsafeCollabReturnCodes.PEER_E_TIMEOUT)){
|
||
|
m_latestException = PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_AsyncInviteException), errorCode);
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "Got an exception {0}. Storing it in latest exception.", m_latestException);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pir = (PEER_INVITATION_RESPONSE)Marshal.PtrToStructure(response.DangerousGetHandle(),
|
||
|
typeof(PEER_INVITATION_RESPONSE));
|
||
|
|
||
|
//
|
||
|
// Store the responses
|
||
|
//
|
||
|
lock (m_responses)
|
||
|
m_responses.Add(pir.action);
|
||
|
|
||
|
if (pir.action == PeerInvitationResponseType.Accepted){
|
||
|
inviteCompletedArgs = new InviteCompletedEventArgs(new PeerInvitationResponse(pir.action), null, false,
|
||
|
m_AsyncOp.UserSuppliedState);
|
||
|
fireCallback = true;
|
||
|
|
||
|
//
|
||
|
// Got an accepted. unregister callback to disable all othe other endpoint callbacks
|
||
|
//
|
||
|
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "Found an accepted. About to fire callback.");
|
||
|
|
||
|
m_RegisteredWaitHandle.Unregister(null);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
Interlocked.Increment(ref m_numberOfResponses);
|
||
|
|
||
|
if ((!fireCallback) && (m_numberOfResponses == m_peerEndPoints.Count) && (!m_aboutToFireCallback)){
|
||
|
//
|
||
|
// Two threads can be here at the same time when all the responses have been
|
||
|
// received and only one should be allowed to call the callback
|
||
|
//
|
||
|
lock (m_aboutToFireCallbackLock){
|
||
|
if (m_aboutToFireCallback)
|
||
|
return;
|
||
|
|
||
|
m_aboutToFireCallback = true;
|
||
|
|
||
|
bool foundDeclined = false;
|
||
|
bool foundExpired = false;
|
||
|
|
||
|
fireCallback = true;
|
||
|
|
||
|
//
|
||
|
// Got all responses; make a decision
|
||
|
//
|
||
|
|
||
|
foreach (PeerInvitationResponseType responseType in m_responses)
|
||
|
{
|
||
|
if (responseType == PeerInvitationResponseType.Expired){
|
||
|
foundExpired = true;
|
||
|
}
|
||
|
else if (responseType == PeerInvitationResponseType.Declined){
|
||
|
foundDeclined = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If at least one is declined, return declined.
|
||
|
//
|
||
|
|
||
|
if (foundDeclined){
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "Got a declined invite response.");
|
||
|
inviteCompletedArgs = new InviteCompletedEventArgs(new PeerInvitationResponse(PeerInvitationResponseType.Declined), null, false,
|
||
|
m_AsyncOp.UserSuppliedState);
|
||
|
}
|
||
|
else if (foundExpired){
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "Got an expired invite response but no accepted or declined.");
|
||
|
inviteCompletedArgs = new InviteCompletedEventArgs(new PeerInvitationResponse(PeerInvitationResponseType.Expired), null, false,
|
||
|
m_AsyncOp.UserSuppliedState);
|
||
|
}
|
||
|
else{
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "Got all error responses");
|
||
|
inviteCompletedArgs = new InviteCompletedEventArgs(null, (m_latestException != null ? m_latestException : new PeerToPeerException("InviteAsync failure.")), false,
|
||
|
m_AsyncOp.UserSuppliedState);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
//Last chance to prevent the callback
|
||
|
//
|
||
|
if (fireCallback){
|
||
|
peer = m_peerWeakReference.Target as Peer;
|
||
|
if (!m_Completed && (peer != null)){
|
||
|
lock (m_Lock){
|
||
|
//
|
||
|
// Async op may be cancelled already
|
||
|
//
|
||
|
if (!m_Completed && !m_Cancelled){
|
||
|
|
||
|
//
|
||
|
//Mark as completed so that this gets fired only once
|
||
|
//
|
||
|
m_Completed = true;
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "Firing callback with response type {0}.", inviteCompletedArgs.InviteResponse);
|
||
|
peer.PrepareToRaiseInviteCompletedEvent(m_AsyncOp, inviteCompletedArgs);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
finally{
|
||
|
if (response != null) response.Dispose();
|
||
|
}
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "Leaving InviteCallback.");
|
||
|
|
||
|
}
|
||
|
|
||
|
// <SecurityKernel Critical="True" Ring="0">
|
||
|
// <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabCancelInvitation(System.Net.PeerToPeer.Collaboration.SafeCollabInvite):System.Int32" />
|
||
|
// <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
|
||
|
// <ReferencesCritical Name="Field: m_SafeCollabInvite" Ring="1" />
|
||
|
// </SecurityKernel>
|
||
|
[System.Security.SecurityCritical]
|
||
|
public void ContinueCancelCallback(object state)
|
||
|
{
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "Entering ContineCancelCallback.");
|
||
|
|
||
|
try{
|
||
|
lock (m_Lock){
|
||
|
if (m_Completed) return;
|
||
|
m_Cancelled = true;
|
||
|
|
||
|
int errorCode = UnsafeCollabNativeMethods.PeerCollabCancelInvitation(m_SafeCollabInvite);
|
||
|
if (errorCode != 0){
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabCancelInvitation returned with errorcode {0}", errorCode);
|
||
|
}
|
||
|
|
||
|
m_SafeCollabInvite.Dispose();
|
||
|
}
|
||
|
|
||
|
Peer peer = m_peerWeakReference.Target as Peer;
|
||
|
if (peer != null){
|
||
|
InviteCompletedEventArgs e = new InviteCompletedEventArgs(null, null, true, m_AsyncOp.UserSuppliedState);
|
||
|
peer.PrepareToRaiseInviteCompletedEvent(m_AsyncOp, e);
|
||
|
}
|
||
|
}
|
||
|
catch (ObjectDisposedException ex){
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Critical, 0, "Exception while cancelling the call {0}", ex);
|
||
|
}
|
||
|
|
||
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, m_TraceEventId, "Leaving ContineCancelCallback.");
|
||
|
|
||
|
}
|
||
|
|
||
|
// <SecurityKernel Critical="True" Ring="1">
|
||
|
// <ReferencesCritical Name="Method: ContinueCancelCallback(Object):Void" Ring="1" />
|
||
|
// </SecurityKernel>
|
||
|
[System.Security.SecurityCritical]
|
||
|
public void CancelAsync(object state)
|
||
|
{
|
||
|
//
|
||
|
//Defer the work to a callback
|
||
|
//
|
||
|
|
||
|
ThreadPool.QueueUserWorkItem(new WaitCallback(ContinueCancelCallback), state);
|
||
|
}
|
||
|
|
||
|
// <SecurityKernel Critical="True" Ring="1">
|
||
|
// <ReferencesCritical Name="Method: Dispose(Boolean):Void" Ring="1" />
|
||
|
// </SecurityKernel>
|
||
|
[System.Security.SecurityCritical]
|
||
|
public void Dispose()
|
||
|
{
|
||
|
Dispose(true);
|
||
|
GC.SuppressFinalize(this);
|
||
|
}
|
||
|
|
||
|
// <SecurityKernel Critical="True" Ring="0">
|
||
|
// <SatisfiesLinkDemand Name="SafeHandle.get_IsInvalid():System.Boolean" />
|
||
|
// <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
|
||
|
// <ReferencesCritical Name="Field: m_SafeCollabInvite" Ring="1" />
|
||
|
// </SecurityKernel>
|
||
|
[System.Security.SecurityCritical]
|
||
|
public void Dispose(bool disposing)
|
||
|
{
|
||
|
if (!m_Disposed){
|
||
|
if (!m_SafeCollabInvite.IsInvalid){
|
||
|
m_SafeCollabInvite.Dispose();
|
||
|
}
|
||
|
|
||
|
if (m_RegisteredWaitHandle != null){
|
||
|
m_RegisteredWaitHandle.Unregister(null);
|
||
|
m_RegisteredWaitHandle = null;
|
||
|
}
|
||
|
|
||
|
if (m_InviteEvent != null){
|
||
|
m_InviteEvent.Close();
|
||
|
}
|
||
|
}
|
||
|
m_Disposed = true;
|
||
|
}
|
||
|
|
||
|
public override int GetHashCode()
|
||
|
{
|
||
|
return m_TraceEventId;
|
||
|
}
|
||
|
|
||
|
internal int TraceEventId
|
||
|
{
|
||
|
get{
|
||
|
return m_TraceEventId;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|