using System;
using System.Threading;
using System.Runtime.InteropServices;
using System.Net;
using System.Collections;
using Peer.NameResolution;
//TODO: Create and Open support a security interface via callback functions
//TODO: Search builder
//TODO: investigate if C# support cast functions instead of using convert
//TODO: implement IDisposable
//TODO: register for specific types of events?
//TODO: add error code descriptions as resource strings
namespace Peer.Graph
{
public class PeerGraphException : System.ComponentModel.Win32Exception
{
internal PeerGraphException(uint errCode) : base((int)errCode) { }
}
/// <summary>
/// Singleton for PeerGraph to guarantee startup/shudown once.
/// </summary>
sealed class PeerGraphService
{
private PeerGraphService()
{
PEER_VERSION_DATA data;
uint hr = PeerGraphNative.PeerGraphStartup(1, out data);
if (hr != 0) throw new PeerGraphException(hr);
}
~PeerGraphService()
{
PeerGraphNative.PeerGraphShutdown();
}
public static readonly PeerGraphService Instance = new PeerGraphService();
private static readonly Peer.NameResolution.WSAService service = Peer.NameResolution.WSAService.Instance;
}
public class PeerGraphProperties
{
private PeerGraphScope Scope;
private uint maxRecordSize;
private string graphName;
private string identity;
public string FriendlyName = string.Empty;
public string Comment = string.Empty;
private uint presenceLifetime;
private int presenceMax;
private PeerGraph graph;
internal PeerGraphProperties(PeerGraph Graph, string GraphName, string Creator)
{
graph = Graph;
graphName = GraphName;
identity = Creator;
Scope = PeerGraphScope.Global;
presenceLifetime = 300;
presenceMax = -1;
}
public uint MaxRecordSize
{
get
{
return maxRecordSize;
}
// set
// {
// if (value > 0 && value < 1024)
// maxRecordSize = 1024;
// else if (value > 60 * 1024 * 1024)
// maxRecordSize = 60 * 1024 * 1024;
// else
// maxRecordSize = 0;
// }
}
public string GraphName
{
get
{
return graphName;
}
// set
// {
// graphName = value;
// }
}
// internal void SetIdentity(string Identity)
// {
// identity = Identity;
// }
//
public string Creator
{
get
{
return identity;
}
}
public uint PresenceLifetime
{
get
{
return presenceLifetime;
}
// set
// {
// if (value < 300)
// presenceLifetime = 300;
// else
// presenceLifetime = value;
// }
}
public int PresenceMax
{
get
{
return presenceMax;
}
// set
// {
// if (value < -1)
// presenceMax = -1;
// else
// presenceMax = value;
// }
}
internal PeerGraphProperties(PEER_GRAPH_PROPERTIES props)
{
Scope = props.dwScope;
maxRecordSize = props.dwMaxRecordSize;
graphName = props.pwzGraphId;
identity = props.pwzCreatorId;
if (props.pwzFriendlyName != IntPtr.Zero) FriendlyName = Marshal.PtrToStringUni(props.pwzFriendlyName);
if (props.pwzComment != IntPtr.Zero) Comment = Marshal.PtrToStringUni(props.pwzComment);
presenceLifetime = props.ulPresenceLifetime;
presenceMax = props.cPresenceMax;
}
internal PEER_GRAPH_PROPERTIES Convert()
{
PEER_GRAPH_PROPERTIES props = new PEER_GRAPH_PROPERTIES();
props.dwSize = Marshal.SizeOf(typeof(PEER_GRAPH_PROPERTIES));
props.dwFlags = 0;
props.dwScope = Scope;
props.dwMaxRecordSize = maxRecordSize;
props.pwzGraphId = graphName;
props.pwzCreatorId = identity;
if (FriendlyName != String.Empty) props.pwzFriendlyName = Marshal.StringToHGlobalUni(FriendlyName);
if (Comment != String.Empty) props.pwzComment = Marshal.StringToHGlobalUni(Comment);
props.ulPresenceLifetime = presenceLifetime;
props.cPresenceMax = presenceMax;
return props;
}
public void Update()
{
if (graph.hGraph != IntPtr.Zero)
{
PEER_GRAPH_PROPERTIES props = Convert();
uint hr = PeerGraphNative.PeerGraphSetProperties(graph.hGraph, ref props);
if (hr != 0) throw new PeerGraphException(hr);
}
}
}
public class PeerGraph
{
private static PeerGraphService service = PeerGraphService.Instance;
internal IntPtr hGraph;
private PeerGraphProperties properties;
private System.Int64 connectionId;
private string identity;
public PeerGraph(string GraphName)
{
properties = new PeerGraphProperties(this, GraphName, string.Empty);
}
~PeerGraph()
{
InternalClose();
}
private IPEndPoint DiscoverAddress()
{
PeerRegistration registration = new PeerRegistration(properties.GraphName, string.Empty);
if (Pnrp.Lookup(registration))
{
return registration.Address;
}
return null;
}
private void Connect(bool Listen)
{
IPEndPoint endpoint = DiscoverAddress();
if (endpoint != null)
{
PEER_ADDRESS address = new PEER_ADDRESS();
address.dwSize = Marshal.SizeOf(typeof(PEER_ADDRESS));
address.sin6.sin6_addr = endpoint.Address.GetAddressBytes();
address.sin6.sin6_family = (short)endpoint.AddressFamily;
address.sin6.sin6_port = (ushort)endpoint.Port;
uint hr = PeerGraphNative.PeerGraphConnect(hGraph, IntPtr.Zero, ref address, out connectionId);
if (hr != 0 && hr != PeerGraphNative.PEER_E_ALREADY_CONNECTED) throw new PeerGraphException(hr);
}
else if (Listen)
{
this.Listen();
}
}
private void RegisterAddress()
{
PeerRegistration registration = new PeerRegistration(properties.GraphName, string.Empty);
registration.address = GetLocalPeerInfo().addresses[0].sin6;
registration.Comment = properties.Comment;
Pnrp.Register(registration);
}
private void UnregisterAddress()
{
PeerRegistration registration = new PeerRegistration(properties.GraphName, string.Empty);
Pnrp.Unregister(registration);
}
internal void Listen(PeerGraphScope Scope, int ScopeId, short Port)
{
uint hr = PeerGraphNative.PeerGraphListen(hGraph, Scope, ScopeId, Port);
if (hr != 0) throw new PeerGraphException(hr);
// have to be listening to register association between name with endpoint
RegisterAddress();
}
private void Listen()
{
Listen(PeerGraphScope.Global, 0, 0);
}
private void InternalClose()
{
if (hGraph != IntPtr.Zero)
{
// foreach (PeerConnection cn in Connections)
// {
// CloseDirectConnection(cn.ConnectionId);
// }
UnregisterForEvents();
uint hr = PeerGraphNative.PeerGraphClose(hGraph);
if (hr != 0 && hr != PeerGraphNative.PEER_E_NOT_INITIALIZED) throw new PeerGraphException(hr);
hGraph = IntPtr.Zero;
UnregisterAddress();
}
}
public static void Create(string GraphName, string Identity, string DatabaseName)
{
PeerGraphProperties properties = new PeerGraphProperties(null, GraphName, Identity);
//properties.SetIdentity(Identity);
PEER_GRAPH_PROPERTIES props = properties.Convert();
IntPtr hGraph;
uint hr = PeerGraphNative.PeerGraphCreate(ref props, DatabaseName, IntPtr.Zero, out hGraph);
if (hr != 0) throw new PeerGraphException(hr);
hr = PeerGraphNative.PeerGraphClose(hGraph);
if (hr != 0) throw new PeerGraphException(hr);
}
public static void Delete(string GraphName, string Identity, string DatabaseName)
{
uint hr = PeerGraphNative.PeerGraphDelete(GraphName, Identity, DatabaseName);
if (hr != 0) throw new PeerGraphException(hr);
}
public void Open(string DatabaseName, string Identity)
{
if (hGraph != IntPtr.Zero) Close();
uint hr = PeerGraphNative.PeerGraphOpen(properties.GraphName, Identity, DatabaseName, IntPtr.Zero, 0, IntPtr.Zero, out hGraph);
if (hr != 0 && hr != PeerGraphNative.PEER_S_GRAPH_DATA_CREATED) throw new PeerGraphException(hr);
RegisterForEvents();
Connect(true);
identity = Identity;
}
public string Identity
{
get
{
return identity;
}
}
public void Close()
{
InternalClose();
Status = (PeerGraphStatus)0;
}
public PeerGraphStatus Status
{
get
{
PeerGraphStatus status;
uint hr = PeerGraphNative.PeerGraphGetStatus(hGraph, out status);
if (hr != 0) throw new PeerGraphException(hr);
return status;
}
set
{
PeerGraphStatusChangedEventArgs args = new PeerGraphStatusChangedEventArgs(value);
if (StatusChanged != null)
{
StatusChanged(this, args);
}
}
}
public PeerNode GetPeerInfo(System.Int64 peerId)
{
IntPtr pNodeInfo;
uint hr = PeerGraphNative.PeerGraphGetNodeInfo(hGraph, peerId, out pNodeInfo);
if (hr != 0) throw new PeerGraphException(hr);
PeerNode node = new PeerNode(this, (PEER_NODE_INFO)Marshal.PtrToStructure(pNodeInfo, typeof(PEER_NODE_INFO)));
PeerGraphNative.PeerGraphFreeData(pNodeInfo);
return node;
}
public PeerNode GetLocalPeerInfo()
{
return GetPeerInfo(0);
}
public PeerGraphProperties Properties
{
get
{
if (hGraph != IntPtr.Zero)
{
IntPtr ppGraphProperties;
uint hr = PeerGraphNative.PeerGraphGetProperties(hGraph, out ppGraphProperties);
if (hr != 0) throw new PeerGraphException(hr);
properties = new PeerGraphProperties((PEER_GRAPH_PROPERTIES)Marshal.PtrToStructure(ppGraphProperties,typeof(PEER_GRAPH_PROPERTIES)));
}
return properties;
}
}
public PeerCollection Peers
{
get
{
return new PeerCollection(this);
}
}
public PeerCollection GetPeers(string PeerName)
{
return new PeerCollection(this, PeerName);
}
public PeerConnectionCollection Connections
{
get
{
return new PeerConnectionCollection(hGraph);
}
}
public PeerConnection GetConnectionInfo(System.Int64 ConnectionId)
{
foreach (PeerConnection cn in Connections)
{
if (cn.ConnectionId == ConnectionId)
{
return cn;
}
}
return null;
}
public PeerConnectionCollection GetConnections(PeerConnectionType Type)
{
return new PeerConnectionCollection(hGraph, Type);
}
//
// Open connection cache
//
private Hashtable OpenConnections = new Hashtable();
public System.Int64 OpenDirectConnect(PeerNode node)
{
System.Int64 connectId;
uint hr = PeerGraphNative.PeerGraphOpenDirectConnection(hGraph, node.PeerName, ref node.addresses[0], out connectId);
if (hr != 0) throw new PeerGraphException(hr);
return connectId;
}
protected virtual PeerOpenConnection OnNewOpenConnection(System.Int64 ConnectionId)
{
return new PeerOpenConnection(this, ConnectionId);
}
public PeerOpenConnection GetOpenConnectionInfo(System.Int64 ConnectionId)
{
return (PeerOpenConnection)OpenConnections[ConnectionId];
}
internal void SendData(System.Int64 ConnectionId, Guid Type, int Length, IntPtr Data)
{
IntPtr typeptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Guid)));
Marshal.StructureToPtr(Type, typeptr, false);
uint hr = PeerGraphNative.PeerGraphSendData(hGraph, ConnectionId, typeptr, (uint)Length, Data);
if (hr != 0) throw new PeerGraphException(hr);
}
internal void CloseDirectConnection(System.Int64 ConnectionId)
{
uint hr = PeerGraphNative.PeerGraphCloseDirectConnection(hGraph, ConnectionId);
if (hr != 0) throw new PeerGraphException(hr);
}
public PeerRecordCollection Records
{
get
{
return new PeerRecordCollection(hGraph, Guid.Empty, string.Empty);
}
}
public PeerRecordCollection GetRecords(Guid Type, string Identity)
{
return new PeerRecordCollection(hGraph, Type, Identity);
}
public PeerRecordCollection GetRecords(Guid Type)
{
return new PeerRecordCollection(hGraph, Type, string.Empty);
}
public PeerRecordCollection GetRecords(string Identity)
{
return new PeerRecordCollection(hGraph, Guid.Empty, Identity);
}
public PeerRecord CreatePeerRecord(Guid RecordType, System.TimeSpan ExpirationTime)
{
return new PeerRecord(hGraph, RecordType, DateTime.Now+ExpirationTime);
}
public Guid AddRecord(PeerRecord Record)
{
PEER_RECORD record = Record.Convert();
Guid recordId;
uint hr = PeerGraphNative.PeerGraphAddRecord(hGraph, ref record, out recordId);
if (hr != 0) throw new PeerGraphException(hr);
return recordId;
}
public void UpdateRecord(PeerRecord Record, System.TimeSpan ExpirationTime)
{
Record.ExpirationTime += ExpirationTime;
UpdateRecord(Record);
}
public void UpdateRecord(PeerRecord Record)
{
PEER_RECORD record = Record.Convert();
uint hr = PeerGraphNative.PeerGraphUpdateRecord(hGraph, ref record);
if (hr != 0) throw new PeerGraphException(hr);
}
public void DeleteRecord(Guid RecordId)
{
DeleteRecord(RecordId, false);
}
public void DeleteLocalRecord(Guid RecordId)
{
DeleteRecord(RecordId, true);
}
internal void DeleteRecord(Guid RecordId, bool LocalOnly)
{
uint hr = PeerGraphNative.PeerGraphDeleteRecord(hGraph, ref RecordId, LocalOnly);
if (hr != 0) throw new PeerGraphException(hr);
}
public PeerRecord GetRecord(Guid RecordId)
{
IntPtr recptr;
uint hr = PeerGraphNative.PeerGraphGetRecord(hGraph, ref RecordId, out recptr);
if (hr != 0) throw new PeerGraphException(hr);
PeerRecord record = new PeerRecord(hGraph, (PEER_RECORD)Marshal.PtrToStructure(recptr, typeof(PEER_RECORD)));
PeerGraphNative.PeerGraphFreeData(recptr);
return record;
}
internal void SetNodeAttributes(string Attributes)
{
IntPtr ptr = IntPtr.Zero;
if (Attributes != string.Empty) ptr = Marshal.StringToHGlobalUni(Attributes);
uint hr = PeerGraphNative.PeerGraphSetNodeAttributes(hGraph, ptr);
if (hr != 0) throw new PeerGraphException(hr);
}
// public void ExportDatabase(string Path)
// {
// uint hr = PeerGraphNative.PeerGraphExportDatabase(hGraph, Path);
// if (hr != 0) throw new PeerGraphException(hr);
// }
//
// public void ImportDatabase(string Path)
// {
// uint hr = PeerGraphNative.PeerGraphImportDatabase(hGraph, Path);
// if (hr != 0) throw new PeerGraphException(hr);
// }
//
// public void PublishPresence(bool Present)
// {
// uint hr = PeerGraphNative.PeerGraphSetPresence(hGraph, Present);
// if (hr != 0) throw new PeerGraphException(hr);
// }
//
// Events
//
public delegate void GraphSynchronizedHandler(object sender, PeerGraphSynchronizedEventArgs e);
public event GraphSynchronizedHandler GraphSynchronized;
private void HandleEventSynchronized(IntPtr evptr)
{
PEER_EVENT_SYNCHRONIZED_DATA ndata = (PEER_EVENT_SYNCHRONIZED_DATA)Marshal.PtrToStructure(evptr, typeof(PEER_EVENT_SYNCHRONIZED_DATA));
PeerGraphSynchronizedEventArgs args = new PeerGraphSynchronizedEventArgs(ndata.recordType);
if (GraphSynchronized != null)
{
GraphSynchronized(this, args);
}
}
public delegate void StatusChangedHandler(object sender, PeerGraphStatusChangedEventArgs e);
public event StatusChangedHandler StatusChanged;
private void HandleEventStatusChanged(IntPtr evptr)
{
PeerGraphStatus status = (PeerGraphStatus)Marshal.ReadInt32(evptr);
PeerGraphStatusChangedEventArgs args = new PeerGraphStatusChangedEventArgs(status);
if (!args.IsListening) this.Listen();
if (StatusChanged != null)
{
StatusChanged(this, args);
}
}
public delegate void ConnectionOpenedHandler(object sender, PeerGraphConnectionOpenedEventArgs e);
public event ConnectionOpenedHandler ConnectionOpened;
public delegate void ConnectionClosedHandler(object sender, PeerGraphConnectionClosedEventArgs e);
public event ConnectionClosedHandler ConnectionClosed;
public delegate void ConnectionFailedHandler(object sender, PeerGraphConnectionFailedEventArgs e);
public event ConnectionFailedHandler ConnectionFailed;
private void HandleEventConnectionChanged(IntPtr evptr, PeerConnectionType type)
{
PEER_EVENT_CONNECTION_CHANGE_DATA ndata = (PEER_EVENT_CONNECTION_CHANGE_DATA)Marshal.PtrToStructure(evptr, typeof(PEER_EVENT_CONNECTION_CHANGE_DATA));
// if this matches the connection Id return by PeerGraphConnect, then begin listening
if (ndata.ullConnectionId == connectionId)
{
Listen();
connectionId = 0;
}
else
{
switch (ndata.status)
{
case PeerConnectionStatus.Connected:
if (ConnectionOpened != null)
{
PeerOpenConnection cn = OnNewOpenConnection(ndata.ullConnectionId);
PeerGraphConnectionOpenedEventArgs args = new PeerGraphConnectionOpenedEventArgs(type, cn);
OpenConnections.Add(ndata.ullConnectionId, cn);
foreach (ConnectionOpenedHandler opened in ConnectionOpened.GetInvocationList())
opened(this, args);
break;
}
break;
case PeerConnectionStatus.Disconnected:
if (ConnectionClosed != null)
{
PeerGraphConnectionClosedEventArgs args = new PeerGraphConnectionClosedEventArgs(type, ndata.ullConnectionId, ndata.ullNodeId);
foreach (ConnectionClosedHandler closed in ConnectionClosed.GetInvocationList())
closed(this, args);
OpenConnections.Remove(ndata.ullConnectionId);
}
break;
case PeerConnectionStatus.Failed:
if (ConnectionFailed != null)
{
PeerGraphConnectionFailedEventArgs args = new PeerGraphConnectionFailedEventArgs(type, ndata.ullConnectionId);
ConnectionFailed(this, args);
OpenConnections.Remove(ndata.ullConnectionId);
}
break;
}
}
}
private void HandleEventIncomingData(IntPtr evptr)
{
PEER_EVENT_INCOMING_DATA ndata = (PEER_EVENT_INCOMING_DATA)Marshal.PtrToStructure(evptr, typeof(PEER_EVENT_INCOMING_DATA));
PeerOpenConnection cn = (PeerOpenConnection)OpenConnections[ndata.ullConnectionId];
if (cn != null)
{
PeerGraphDataReceiveEventArgs args = new PeerGraphDataReceiveEventArgs(cn, ndata.type, ndata.data.pbData, ndata.data.cbData);
cn.RaiseDataReceivedEvent(args);
}
}
// public delegate void PropertyChangedHandler(object sender, PeerGraphPropertyChangedEventArgs e);
// public event PropertyChangedHandler PropertyChanged;
//
// private void HandleEventPropertyChanged(IntPtr evptr)
// {
// PeerGraphPropertyChangedEventArgs args = new PeerGraphPropertyChangedEventArgs(properties);
// if (PropertyChanged != null)
// {
// PropertyChanged(this, args);
// }
// }
public delegate void PeerConnectedHandler(object sender, PeerGraphPeerChangedEventArgs e);
public event PeerConnectedHandler PeerConnected;
public delegate void PeerDisconnectedHandler(object sender, PeerGraphPeerChangedEventArgs e);
public event PeerDisconnectedHandler PeerDisconnected;
public delegate void PeerUpdatedHandler(object sender, PeerGraphPeerChangedEventArgs e);
public event PeerUpdatedHandler PeerUpdated;
private void HandleEventPeerChanged(IntPtr evptr)
{
PEER_EVENT_NODE_CHANGE_DATA ndata = (PEER_EVENT_NODE_CHANGE_DATA)Marshal.PtrToStructure(evptr, typeof(PEER_EVENT_NODE_CHANGE_DATA));
// if local node address has changed, re-register with PNRP
if (ndata.changeType == PeerNodeAction.Updated && ndata.ullNodeId == 0)
RegisterAddress();
else
{
PeerGraphPeerChangedEventArgs args = new PeerGraphPeerChangedEventArgs(ndata.ullNodeId, ndata.pwzPeerName);
switch (ndata.changeType)
{
case PeerNodeAction.Connected:
if (PeerConnected != null) PeerConnected(this, args);
break;
case PeerNodeAction.Disconnected:
if (PeerDisconnected != null) PeerDisconnected(this, args);
break;
case PeerNodeAction.Updated:
if (PeerUpdated != null) PeerUpdated(this, args);
break;
}
}
}
public delegate void RecordChangedHandler(object sender, PeerGraphRecordChangedEventArgs e);
public event RecordChangedHandler RecordChanged;
private void HandleEventRecordChanged(IntPtr evptr)
{
PEER_EVENT_RECORD_CHANGE_DATA ndata = (PEER_EVENT_RECORD_CHANGE_DATA)Marshal.PtrToStructure(evptr, typeof(PEER_EVENT_RECORD_CHANGE_DATA));
PeerGraphRecordChangedEventArgs args = new PeerGraphRecordChangedEventArgs(ndata.changeType, ndata.recordId, ndata.recordType);
if (RecordChanged != null)
{
RecordChanged(this, args);
}
}
private RegisteredWaitHandle Handle = null;
private IntPtr hPeerEvent;
private void PeerEventWorker(object xdata, bool timedOut)
{
while (true)
{
IntPtr evptr;
uint result = PeerGraphNative.PeerGraphGetEventData(hPeerEvent, out evptr);
if (result == PeerGraphNative.PEER_S_NO_EVENT_DATA || evptr == IntPtr.Zero) break;
if (result != 0) Marshal.ThrowExceptionForHR((int)result);
PEER_GRAPH_EVENT_DATA data = (PEER_GRAPH_EVENT_DATA)Marshal.PtrToStructure(evptr, typeof(PEER_GRAPH_EVENT_DATA));
IntPtr dataptr = (IntPtr)(evptr.ToInt32() + Marshal.SizeOf(typeof(PEER_GRAPH_EVENT_DATA)));
System.Diagnostics.Debug.WriteLine(data.eventType.ToString());
switch (data.eventType)
{
case PEER_GRAPH_EVENT_TYPE.PEER_GRAPH_EVENT_STATUS_CHANGED: // 1
HandleEventStatusChanged(dataptr);
break;
// case PEER_GRAPH_EVENT_TYPE.PEER_GRAPH_EVENT_PROPERTY_CHANGED:
// HandleEventPropertyChanged(dataptr);
// break;
//
case PEER_GRAPH_EVENT_TYPE.PEER_GRAPH_EVENT_RECORD_CHANGED:
HandleEventRecordChanged(dataptr);
break;
case PEER_GRAPH_EVENT_TYPE.PEER_GRAPH_EVENT_DIRECT_CONNECTION:
HandleEventConnectionChanged(dataptr, PeerConnectionType.Direct);
break;
case PEER_GRAPH_EVENT_TYPE.PEER_GRAPH_EVENT_NEIGHBOR_CONNECTION: // 1
HandleEventConnectionChanged(dataptr, PeerConnectionType.Neighbor);
break;
case PEER_GRAPH_EVENT_TYPE.PEER_GRAPH_EVENT_INCOMING_DATA:
HandleEventIncomingData(dataptr);
break;
// case PEER_GRAPH_EVENT_TYPE.PEER_GRAPH_EVENT_CONNECTION_REQUIRED:
// if ((Status & PeerGraphStatus.HasConnections) != PeerGraphStatus.HasConnections) Connect(false);
// break;
case PEER_GRAPH_EVENT_TYPE.PEER_GRAPH_EVENT_NODE_CHANGED: // 1
HandleEventPeerChanged(dataptr);
break;
case PEER_GRAPH_EVENT_TYPE.PEER_GRAPH_EVENT_SYNCHRONIZED: // 1
HandleEventSynchronized(dataptr);
break;
// default:
// throw new NotImplementedException("Unhandled PeerEventType " + data.eventType);
}
PeerGraphNative.PeerGraphFreeData(evptr);
}
}
private void RegisterForEvents()
{
if (hPeerEvent != IntPtr.Zero) return; // already registered
AutoResetEvent sendEvent = new AutoResetEvent(false);
Handle = ThreadPool.RegisterWaitForSingleObject(sendEvent, new WaitOrTimerCallback(PeerEventWorker), null, -1, false);
PEER_GRAPH_EVENT_REGISTRATION[] info =
{
new PEER_GRAPH_EVENT_REGISTRATION(PEER_GRAPH_EVENT_TYPE.PEER_GRAPH_EVENT_STATUS_CHANGED),
new PEER_GRAPH_EVENT_REGISTRATION(PEER_GRAPH_EVENT_TYPE.PEER_GRAPH_EVENT_PROPERTY_CHANGED),
new PEER_GRAPH_EVENT_REGISTRATION(PEER_GRAPH_EVENT_TYPE.PEER_GRAPH_EVENT_RECORD_CHANGED),
new PEER_GRAPH_EVENT_REGISTRATION(PEER_GRAPH_EVENT_TYPE.PEER_GRAPH_EVENT_DIRECT_CONNECTION),
new PEER_GRAPH_EVENT_REGISTRATION(PEER_GRAPH_EVENT_TYPE.PEER_GRAPH_EVENT_NEIGHBOR_CONNECTION),
new PEER_GRAPH_EVENT_REGISTRATION(PEER_GRAPH_EVENT_TYPE.PEER_GRAPH_EVENT_INCOMING_DATA),
new PEER_GRAPH_EVENT_REGISTRATION(PEER_GRAPH_EVENT_TYPE.PEER_GRAPH_EVENT_CONNECTION_REQUIRED),
new PEER_GRAPH_EVENT_REGISTRATION(PEER_GRAPH_EVENT_TYPE.PEER_GRAPH_EVENT_NODE_CHANGED),
new PEER_GRAPH_EVENT_REGISTRATION(PEER_GRAPH_EVENT_TYPE.PEER_GRAPH_EVENT_SYNCHRONIZED)
};
int size = Marshal.SizeOf(info[0]);
IntPtr infoptr = Marshal.AllocCoTaskMem(info.Length*size);
int offset = 0;
foreach (PEER_GRAPH_EVENT_REGISTRATION item in info)
{
Marshal.StructureToPtr(item, (IntPtr)(infoptr.ToInt32()+offset), false);
offset += size;
}
uint result = PeerGraphNative.PeerGraphRegisterEvent(hGraph, sendEvent.Handle, info.Length, infoptr, out hPeerEvent);
if (result != 0) Marshal.ThrowExceptionForHR((int)result);
}
private void UnregisterForEvents()
{
if (hPeerEvent != IntPtr.Zero)
{
uint result = PeerGraphNative.PeerGraphUnregisterEvent(hPeerEvent);
hPeerEvent = IntPtr.Zero;
}
}
}
}