Click here to Skip to main content
15,886,258 members
Articles / Hosted Services / Serverless

Associating Attribute Meta-Data in a Peer Graph using Microsoft's Peer-to-Peer technology

Rate me:
Please Sign up or sign in to vote.
4.17/5 (2 votes)
6 Jan 20067 min read 25.6K   177   19  
Associating attribute meta-data in a Peer Graph using Microsoft's Peer-to-Peer technology.
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;
			}
		}

	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Canada Canada
Adrian Moore is the Development Manager for the SCADA Vision system developed by ABB Inc in Calgary, Alberta.

He has been interested in compilers, parsers, real-time database systems and peer-to-peer solutions since the early 90's. In his spare time, he is currently working on a SQL parser for querying .NET DataSets (http://www.queryadataset.com).

Adrian is a Microsoft MVP for Windows Networking.

Comments and Discussions