Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / SystemNet / Net / PeerToPeer / Collaboration / Peer.cs / 2 / Peer.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------------
namespace System.Net.PeerToPeer.Collaboration
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Runtime.InteropServices;
using System.Net.Sockets;
using System.Net.Mail;
using System.ComponentModel;
using System.Threading;
using System.Diagnostics;
using System.Runtime.Serialization;
using System.Security.Permissions;
using System.IO;
///
/// This is the object changed event args class we give back when
/// we have have an object changed event fired by native
///
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;
}
}
}
///
/// This is the presence changed event args class we give back when
/// we have have presence changed event fired by native
///
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;
}
}
}
///
/// This is the event args class we give back when
/// we have completed the subscribeasync call
///
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;
}
}
}
///
/// This is the event args class we give back when
/// we have completed the refreshendpoint async call
///
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;
}
}
}
///
/// This is the event args class we give back when
/// we have completed the inviteasync call
///
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;
}
}
}
///
/// Has the common interface for PeerNearMe and PeerContact which derive from it
///
[Serializable]
public abstract class Peer : IDisposable, IEquatable, 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;
}
}
///
/// Gets and set the object used to marshall event handlers calls for stand alone
/// events
///
[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
{
//
//
//
//
[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);
}
///
/// Constructor to enable serialization
///
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
//
//
//
//
//
//
//
//
//
//
//
//
[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
//
//
//
//
[System.Security.SecurityCritical]
public PeerObjectCollection GetObjects()
{
PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
return InternalGetAllObjects(Guid.Empty, false);
}
//
// Gets specific object for all the endpoints
//
//
//
//
[System.Security.SecurityCritical]
public PeerObjectCollection GetObjects(Guid objectId)
{
PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
return InternalGetAllObjects(objectId, true);
}
internal abstract void RefreshIfNeeded();
//
//
//
[System.Security.SecurityCritical]
private PeerObjectCollection InternalGetAllObjects(Guid objectId, bool guidSupplied)
{
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering InternalGetAllObjects() with ObjectId {0}.", objectId);
Dictionary mergedObjects = new Dictionary();
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.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
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
[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.
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
[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 m_inviteCompleted;
public event EventHandler 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