/// <summary> /// Registers a new local peer. The calling function has to pass /// in a Code that is a unique name for the peer. No other peer /// by this name can exist locally. Returns null if it already /// exists, or a new NodePeer object if successful. /// </summary> /// <param name="Code">Unique name for the new peer</param> /// <returns></returns> public static NodePeer RegisterLocalPeer(FieldIdentifier Code) { if (Code == null) { throw new ArgumentNullException("Code"); } lock (Instance.m_localPeerList_Lock) { //make sure "Local.{thisCode}" doesn't exist yet //(no duplicate peer names) bool found = false; foreach (NodePeer p in Instance.m_localPeerList.Peers) { if (p.Code == Code) { found = true; break; } } if (found) { return(null); } else { NodePeer newPeer = NodePeer.BuildWith(Code); LocalPeerList = LocalPeerList.Peers.Append(newPeer); return(newPeer); } } }
/// <summary> /// Unregisters a peer that was created by calling the /// RegisterLocalPeer function. Throws an exception if /// the peer is not a local peer. /// </summary> /// <param name="Peer"></param> /// <returns>True if successful, False otherwise</returns> public static bool UnregisterLocalPeer(NodePeer Peer) { if (Peer == null) { throw new ArgumentNullException("Peer"); } if (!Peer.IsLocal) { throw new ArgumentOutOfRangeException("Peer"); } lock (Instance.m_localPeerList_Lock) { if (Instance.m_localPeerList.Peers.Contains(Peer)) { Peer.Unregister(); //clears all event handlers LocalPeerList = LocalPeerList.Peers.Remove(Peer); return(true); } else { return(false); } } }
/// <summary> /// When the local peer list changes, we have to send updates to /// the other end of this connection. /// </summary> /// <param name="newPeerList"></param> /// <param name="oldPeerList"></param> private void LocalPeerListChangedCallback(NodePeerList newPeerList, NodePeerList oldPeerList) { string s = newPeerList.ToXml(oldPeerList); Send(s); }
public static NodePeerList BuildWith(ReadOnlyCollection <NodePeer> Peers) { //build node NodePeerList Builder = BuildWith(); //add the peer list Builder = Builder.Peers.Append(Peers); return(Builder); }
public static NodePeerList BuildWith() { //build fields Dictionary <FieldIdentifier, FieldBase> mutableFields = new Dictionary <FieldIdentifier, FieldBase>(); //build children KeyedNodeCollection <NodeBase> mutableChildren = new KeyedNodeCollection <NodeBase>(); //build node NodePeerList Builder = new NodePeerList( new ReadOnlyDictionary <FieldIdentifier, FieldBase>(mutableFields), new ReadOnlyCollection <NodeBase>(mutableChildren)); return(Builder); }
internal void ThreadStart(Object o) { SslStream sslStream = o as SslStream; if (sslStream != null) { //Have to send the local peer list to the other end of //the connection, and we also need to be notified of any //changes to the local peer list. This has to be done //in one operation so a new node can't sneak in between //us reading the nodelist, and us registering the event. lock (m_OutgoingQueue_Lock) //don't let the callback enqueue a message first { NodePeerList localPeerList = CommunicationManager.RegisterLocalPeerListChangedCallback( new CommunicationManager.LocalPeerListChangedHandler( LocalPeerListChangedCallback)); Send(localPeerList.ToXml()); } //kick off a read callback chain of threads lock (m_ReadCallback_Lock) { sslStream.BeginRead(m_newData, 0, m_newData.Length, new AsyncCallback(ReadCallback), sslStream); } bool stop = false; while (!stop) { //send any queued messages int outgoingCount = 0; lock (m_OutgoingQueue_Lock) { outgoingCount = m_OutgoingQueue.Count; } while (outgoingCount > 0) { string data = null; lock (m_OutgoingQueue_Lock) { data = m_OutgoingQueue.Dequeue(); } //encode it to base 64 so we don't have to worry about control codes byte[] encbuf = System.Text.Encoding.Unicode.GetBytes(data); string encodedData = Convert.ToBase64String(encbuf) + "\n"; //terminate in newline to denote the end of the message //convert to a byte array byte[] writebuf = System.Text.Encoding.ASCII.GetBytes(encodedData); sslStream.Write(writebuf); sslStream.Flush(); outgoingCount--; } //process any received messages int incomingCount = 0; lock (m_IncomingQueue_Lock) { incomingCount = m_IncomingQueue.Count; } while (incomingCount > 0) { string data = null; lock (m_IncomingQueue_Lock) { data = m_IncomingQueue.Dequeue(); } //message is in base 64, so convert back to a string byte[] decbuff = Convert.FromBase64String(data); string message = System.Text.Encoding.Unicode.GetString(decbuff); Receive(message); incomingCount--; } //wait System.Threading.Thread.Sleep(100); lock (m_CloseRequest_Lock) { if (stop == false) { stop = m_CloseRequest; } } } //See if we closed due to an exception in the reader thread Exception readException = null; lock (m_readException_Lock) { readException = m_readException; } if (readException != null) { //TODO propagate this exception to higher code } //clean up the stream sslStream.Close(); } }
private void Receive(string message) { //TextWriter tw = new StreamWriter("receive_" + this.ID.ToString() + ".txt", true); //tw.WriteLine(message); //tw.Close(); if (ValidateXmlToSchema(message)) { FieldGuid toPeerID = NodeBase.ToPeerFromXML(message); FieldGuid fromPeerID = NodeBase.FromPeerFromXML(message); if (toPeerID != null && fromPeerID != null) { //it's a peer-to-peer message //find the ToPeer in the local peer list NodePeer ToPeer = CommunicationManager.LocalPeerList.FindPeerByID(toPeerID); //find the FromPeer in the remote peer list NodePeer FromPeer = RemotePeerList.FindPeerByID(fromPeerID); if (ToPeer != null && FromPeer != null) { //see if this message is based on another node FieldGuid BasedOnNodeID = NodeBase.BasedOnNodeIDFromXML(message); NodeBase basedOnNode = null; if (BasedOnNodeID != null) { basedOnNode = ToPeer.ReceiveDeltaFromPeer(FromPeer, BasedOnNodeID); NodeBase msg = NodeBase.NodeFromXML(message, basedOnNode.GetChildrenRecursive()); CommunicationManager.SendDeltaToPeer(ToPeer, FromPeer, msg, basedOnNode); } else { NodeBase msg = NodeBase.NodeFromXML(message, null); CommunicationManager.SendToPeer(ToPeer, FromPeer, msg); } } else { //TODO - log this - undeliverable message (peer lists not up to date?) } } else { //it's a system message (not peer-to-peer) FieldNodeType nodeType = NodeBase.NodeTypeFromXML(message); if (nodeType.ToString() == typeof(NodePeerList).FullName) { lock (m_remotePeerList_Lock) //lock so we read/write in one operation { //When we receive a remote peer list, it is generally just a diff //from the last peer list. RemotePeerList = (NodePeerList)NodeBase.NodeFromXML( message, RemotePeerList.GetChildrenRecursive()); } } else { //TODO - log this? Unknown root message type? } } } else { //TODO - log this? Unknown garbage message? } }