コード例 #1
0
        /// <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);
                }
            }
        }
コード例 #2
0
        /// <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);
                }
            }
        }
コード例 #3
0
        /// <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);
        }
コード例 #4
0
        public static NodePeerList BuildWith(ReadOnlyCollection <NodePeer> Peers)
        {
            //build node
            NodePeerList Builder = BuildWith();

            //add the peer list
            Builder = Builder.Peers.Append(Peers);

            return(Builder);
        }
コード例 #5
0
        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);
        }
コード例 #6
0
        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();
            }
        }
コード例 #7
0
        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?
            }
        }