PeerConnector.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / PeerConnector.cs / 1 / PeerConnector.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------
namespace System.ServiceModel.Channels
{ 
    using System.Collections.Generic;
    using System.Diagnostics; 
    using System.Globalization; 
    using System.Runtime.Serialization;
    using System.ServiceModel; 
    using System.ServiceModel.Description;
    using System.ServiceModel.Diagnostics;
    using System.Threading;
 
    // Connector is responsible for transitioning neighbors to connected state.
    class PeerConnector: IPeerConnectorContract 
    { 
        enum State
        { 
            Created,
            Opened,
            Closed,
            Closing 
        }
 
        PeerNodeConfig config; 
        PeerMaintainer maintainer;
        PeerNeighborManager neighborManager; 
        State state;
        object thisLock;

        // TypedMessageConverters: 
        TypedMessageConverter connectInfoMessageConverter;
        TypedMessageConverter disconnectInfoMessageConverter; 
        TypedMessageConverter refuseInfoMessageConverter; 
        TypedMessageConverter welcomeInfoMessageConverter;
 
        // To keep track of timers to transition neighbors to connected state
        Dictionary timerTable;

        public PeerConnector(PeerNodeConfig config, PeerNeighborManager neighborManager, 
            PeerMaintainer maintainer)
        { 
            DiagnosticUtility.DebugAssert(config != null, "Config is expected to non-null"); 
            DiagnosticUtility.DebugAssert(neighborManager != null, "NeighborManager is expected to be non-null");
            DiagnosticUtility.DebugAssert(maintainer != null, "Maintainer is expected to be non-null"); 
            DiagnosticUtility.DebugAssert(config.NodeId != PeerTransportConstants.InvalidNodeId, "Invalid NodeId");
            DiagnosticUtility.DebugAssert(config.MaxNeighbors > 0, "MaxNeighbors is expected to be non-zero positive value");
            DiagnosticUtility.DebugAssert(config.ConnectTimeout > 0, "ConnectTimeout is expected to be non-zero positive value");
 
            this.thisLock = new object();
            this.config = config; 
            this.neighborManager = neighborManager; 
            this.maintainer = maintainer;
            this.timerTable = new Dictionary(); 
            this.state = State.Created;
        }

        object ThisLock 
        {
            get 
            { 
                return this.thisLock;
            } 
        }


        internal TypedMessageConverter ConnectInfoMessageConverter 
        {
            get 
            { 
                if (connectInfoMessageConverter == null)
                { 
                    connectInfoMessageConverter = TypedMessageConverter.Create(typeof(ConnectInfo), PeerStrings.ConnectAction);
                }
                return connectInfoMessageConverter;
            } 
        }
 
        internal TypedMessageConverter DisconnectInfoMessageConverter 
        {
            get 
            {
                if (disconnectInfoMessageConverter == null)
                {
                    disconnectInfoMessageConverter = TypedMessageConverter.Create(typeof(DisconnectInfo), PeerStrings.DisconnectAction); 
                }
                return disconnectInfoMessageConverter; 
            } 
        }
 
        internal TypedMessageConverter RefuseInfoMessageConverter
        {
            get
            { 
                if (refuseInfoMessageConverter == null)
                { 
                    refuseInfoMessageConverter = TypedMessageConverter.Create(typeof(RefuseInfo), PeerStrings.RefuseAction); 
                }
                return refuseInfoMessageConverter; 
            }
        }

        internal TypedMessageConverter WelcomeInfoMessageConverter 
        {
            get 
            { 
                if (welcomeInfoMessageConverter == null)
                { 
                    welcomeInfoMessageConverter = TypedMessageConverter.Create(typeof(WelcomeInfo), PeerStrings.WelcomeAction);
                }
                return welcomeInfoMessageConverter;
            } 
        }
 
        // Add a timer for the specified neighbor to the timer table. The timer is only added 
        // if Connector is open and the neighbor is in Connecting state.
        bool AddTimer (IPeerNeighbor neighbor) 
        {
            bool added = false;

            lock (ThisLock) 
            {
                if (state == State.Opened && neighbor.State == PeerNeighborState.Connecting) 
                { 
                    IOThreadTimer timer = new IOThreadTimer(new WaitCallback(OnConnectTimeout), neighbor, true);
                    timer.Set(this.config.ConnectTimeout); 
                    this.timerTable.Add(neighbor, timer);
                    added = true;
                }
            } 

            return added; 
        } 

        //this method takes care of closing the message. 
        void SendMessageToNeighbor(IPeerNeighbor neighbor, Message message, PeerMessageHelpers.CleanupCallback cleanupCallback)
        {
            bool fatal = false;
            try 
            {
                neighbor.Send(message); 
            } 
            catch (Exception e)
            { 
                if (DiagnosticUtility.IsFatal(e))
                {
                    fatal = true;
                    throw; 
                }
                if (e is CommunicationException || 
                    e is QuotaExceededException || 
                    e is ObjectDisposedException ||
                    e is TimeoutException) 
                {
                    DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information);
                    // Message failed to transmit due to quota exceeding or channel failure
                    if (cleanupCallback != null) 
                    {
                        cleanupCallback(neighbor, PeerCloseReason.InternalFailure, e); 
                    } 
                }
                else 
                {
                    throw;
                }
            } 
            finally
            { 
                if(!fatal) 
                    message.Close();
            } 
        }

        // If neighbor cannot transition to connected state, this method cleans up the timer and
        // closes the neighbor 
        void CleanupOnConnectFailure(IPeerNeighbor neighbor, PeerCloseReason reason,
            Exception exception) 
        { 
            // timer will not be found if neighbor is already closed or connected.
            if (RemoveTimer(neighbor)) 
            {
                this.neighborManager.CloseNeighbor(neighbor, reason,
                    PeerCloseInitiator.LocalNode, exception);
            } 
        }
 
        public void Close() 
        {
            Dictionary table; 

            lock (ThisLock)
            {
                table = this.timerTable; 
                this.timerTable = null;
                this.state = State.Closed; 
 
            }
 
            // Cancel each timer
            if (table != null)
            {
                foreach (IOThreadTimer timer in table.Values) 
                    timer.Cancel();
            } 
        } 

        public void Closing() 
        {
            lock (ThisLock)
            {
                this.state = State.Closing; 
            }
        } 
 
        // Complete processing of Disconnect or Refuse message from the neighbor
        void CompleteTerminateMessageProcessing(IPeerNeighbor neighbor, 
            PeerCloseReason closeReason, IList referrals)
        {
            // Close the neighbor after setting the neighbor state to Disconnected.
            // The set can fail if the neighbor is already being closed and that is ok. 
            if (neighbor.TrySetState(PeerNeighborState.Disconnected))
                this.neighborManager.CloseNeighbor(neighbor, closeReason, PeerCloseInitiator.RemoteNode); 
            else 
                if (!(neighbor.State >= PeerNeighborState.Disconnected))
                { 
                    DiagnosticUtility.DebugAssert("Unexpected neighbor state");
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false);
                }
 
            // Hand over the referrals to maintainer
            this.maintainer.AddReferrals(referrals, neighbor); 
        } 

        void OnConnectFailure (IPeerNeighbor neighbor, PeerCloseReason reason, 
            Exception exception)
        {
            CleanupOnConnectFailure(neighbor, reason, exception);
        } 

        void OnConnectTimeout (object asyncState) 
        { 
            CleanupOnConnectFailure( (IPeerNeighbor)asyncState, PeerCloseReason.ConnectTimedOut, null);
        } 

        // Process neighbor closed notification.
        public void OnNeighborClosed(IPeerNeighbor neighbor)
        { 
            // If the neighbor is closed abruptly by the remote node, OnNeighborClosing will
            // not be invoked. Remove neighbor's timer from the table. 
            RemoveTimer (neighbor); 
        }
 
        // Process neighbor closing notification.
        public void OnNeighborClosing (IPeerNeighbor neighbor, PeerCloseReason closeReason)
        {
            // Send Disconnect message to a Connected neighbor 
            if (neighbor.IsConnected)
                SendTerminatingMessage(neighbor, PeerStrings.DisconnectAction, closeReason); 
        } 

        // Process neighbor authenticated notification 
        public void OnNeighborAuthenticated(IPeerNeighbor neighbor)
        {
            if (!(this.state != State.Created))
            { 
                DiagnosticUtility.DebugAssert("Connector not expected to be in Created state");
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); 
            } 

            if (!(PeerNeighborStateHelper.IsAuthenticatedOrClosed(neighbor.State))) 
            {
                DiagnosticUtility.DebugAssert(string.Format(CultureInfo.InvariantCulture, "Neighbor state expected to be Authenticated or Closed, actual state: {0}", neighbor.State));
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false);
            } 

            // setting the state fails if neighbor is already closed or closing 
            // If so, we have nothing to do. 
            if (!neighbor.TrySetState(PeerNeighborState.Connecting))
            { 
                if (!(neighbor.State >= PeerNeighborState.Faulted))
                {
                    DiagnosticUtility.DebugAssert(string.Format(CultureInfo.InvariantCulture, "Neighbor state expected to be Faulted or Closed, actual state: {0}", neighbor.State));
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); 
                }
                return; 
            } 

            // Add a timer to timer table to transition the neighbor to connected state 
            // within finite duration. The neighbor is closed if the timer fires and the
            // neighbor has not reached connected state.
            // The timer is not added if neighbor or connector are closed
            if (AddTimer(neighbor)) 
            {
                // Need to send connect message if the neighbor is the initiator 
                if (neighbor.IsInitiator) 
                {
                    if (this.neighborManager.ConnectedNeighborCount < this.config.MaxNeighbors) 
                        SendConnect(neighbor);
                    else
                    {
                        // We have max connected neighbors already. So close this one. 
                        this.neighborManager.CloseNeighbor(neighbor, PeerCloseReason.NodeBusy,
                            PeerCloseInitiator.LocalNode); 
                    } 
                }
            } 
        }

        public void Open()
        { 
            lock (ThisLock)
            { 
                if (!(this.state == State.Created)) 
                {
                    DiagnosticUtility.DebugAssert("Connector expected to be in Created state"); 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false);
                }
                this.state = State.Opened;
            } 
        }
 
        // 
        // Process Connect from the neighbor
        public void Connect(IPeerNeighbor neighbor, ConnectInfo connectInfo) 
        {
            // Don't bother processing the message if Connector has closed
            if (this.state != State.Opened)
                return; 

            PeerCloseReason closeReason = PeerCloseReason.None; 
 
            // A connect message should only be received by a responder neighbor that is
            // in Connecting state. If not, we close the neighbor without bothering 
            // to send a Refuse message
            // A malicious neighbor can format a message with a null connectInfo as an argument
            if (neighbor.IsInitiator || !connectInfo.HasBody() || (neighbor.State != PeerNeighborState.Connecting &&
                neighbor.State != PeerNeighborState.Closed) ) 
            {
                closeReason = PeerCloseReason.InvalidNeighbor; 
            } 

            // Remove the timer from the timer table for this neighbor. If the timer is not 
            // present, the neighbor is already being closed and the Connect message should
            // be ignored.
            else if (RemoveTimer(neighbor))
            { 
                // Determine if Welcome or Refuse should be sent
 
                // Refuse if node has maximum allowed connected neighbors? 
                if (this.neighborManager.ConnectedNeighborCount >= this.config.MaxNeighbors)
                    closeReason = PeerCloseReason.NodeBusy; 
                else
                {
                    // Deserialization failed or connect info is invalid?
                    if (!PeerValidateHelper.ValidNodeAddress(connectInfo.Address)) 
                    {
                        closeReason = PeerCloseReason.InvalidNeighbor; 
                    } 
                    else
                    { 
                        // Determine if neighbor should be accepted.
                        PeerCloseReason closeReason2;
                        IPeerNeighbor neighborToClose;
                        string action = PeerStrings.RefuseAction; 
                        ValidateNeighbor(neighbor, connectInfo.NodeId, out neighborToClose, out closeReason2, out action);
 
                        if (neighbor != neighborToClose)    // new neighbor should be accepted 
                        {
                            SendWelcome(neighbor); 
                            try
                            {
                                neighbor.ListenAddress = connectInfo.Address;
                            } 
                            catch (ObjectDisposedException e)
                            { 
                                DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); 
                            }
 
                            if (! neighbor.TrySetState(PeerNeighborState.Connected))
                                if (!(neighbor.State >= PeerNeighborState.Disconnecting))
                                {
                                    DiagnosticUtility.DebugAssert("Neighbor state expected to be >= Disconnecting; it is " + neighbor.State.ToString()); 
                                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false);
                                } 
 
                            if (neighborToClose != null)
                            { 
                                // The other neighbor should be closed
                                SendTerminatingMessage(neighborToClose, action, closeReason2);
                                this.neighborManager.CloseNeighbor(neighborToClose, closeReason2, PeerCloseInitiator.LocalNode);
                            } 
                        }
                        else 
                            closeReason = closeReason2; 
                    }
                } 
            }

            if (closeReason != PeerCloseReason.None)
            { 
                SendTerminatingMessage(neighbor, PeerStrings.RefuseAction, closeReason);
                this.neighborManager.CloseNeighbor (neighbor, closeReason, PeerCloseInitiator.LocalNode); 
            } 
        }
 
        // Process Disconnect message from the neighbor
        public void Disconnect(IPeerNeighbor neighbor, DisconnectInfo disconnectInfo)
        {
            // Don't bother processing the message if Connector has closed 
            if (this.state != State.Opened)
                return; 
 
            PeerCloseReason closeReason = PeerCloseReason.InvalidNeighbor;
            IList referrals = null; 

            if (disconnectInfo.HasBody())
            {
                // We should only receive Disconnect message after the neighbor has transitioned 
                // to connected state.
                if (neighbor.State >= PeerNeighborState.Connected) 
                { 
                    if (PeerConnectorHelper.IsDefined(disconnectInfo.Reason))
                    { 
                        closeReason = (PeerCloseReason)disconnectInfo.Reason;
                        referrals = disconnectInfo.Referrals;
                    }
                } 
            }
 
            // Complete processing of disconnect message 
            CompleteTerminateMessageProcessing (neighbor, closeReason, referrals);
        } 


        // Process Refuse message from the neighbor
        public void Refuse(IPeerNeighbor neighbor, RefuseInfo refuseInfo) 
        {
            // Don't bother processing the message if Connector has closed 
            if (this.state != State.Opened) 
                return;
 
            PeerCloseReason closeReason = PeerCloseReason.InvalidNeighbor;
            IList referrals = null;

            if (refuseInfo.HasBody()) 
            {
                // Refuse message should only be received when neighbor is the initiator 
                // and is in connecting state --we accept in closed state to account for 
                // timeouts.
                if (neighbor.IsInitiator && (neighbor.State == PeerNeighborState.Connecting || 
                    neighbor.State == PeerNeighborState.Closed))
                {
                    // Remove the entry from timer table for this neighbor
                    RemoveTimer(neighbor); 

                    if (PeerConnectorHelper.IsDefined(refuseInfo.Reason)) 
                    { 
                        closeReason = (PeerCloseReason)refuseInfo.Reason;
                        referrals = refuseInfo.Referrals; 
                    }
                }
            }
            // Complete processing of refuse message 
            CompleteTerminateMessageProcessing(neighbor, closeReason, referrals);
        } 
 
        // Process Welcome message from the neighbor
        public void Welcome(IPeerNeighbor neighbor, WelcomeInfo welcomeInfo) 
        {
            // Don't bother processing the message if Connector has closed
            if (this.state != State.Opened)
                return; 

            PeerCloseReason closeReason = PeerCloseReason.None; 
 
            // Welcome message should only be received when neighbor is the initiator
            // and is in connecting state --we accept in closed state to account for 
            // timeouts.
            if (!neighbor.IsInitiator || !welcomeInfo.HasBody() || (neighbor.State != PeerNeighborState.Connecting &&
                neighbor.State != PeerNeighborState.Closed))
            { 
                closeReason = PeerCloseReason.InvalidNeighbor;
            } 
            // Remove the entry from timer table for this neighbor. If entry is still present, 
            // RemoveTimer returns true. Otherwise, neighbor is already being closed and
            // welcome message will be ignored. 
            else if (RemoveTimer(neighbor))
            {
                // It is allowed for a node to have more than MaxNeighbours when processing a welcome message
                // Determine if neighbor should be accepted. 
                PeerCloseReason closeReason2;
                IPeerNeighbor neighborToClose; 
                string action = PeerStrings.RefuseAction; 
                ValidateNeighbor(neighbor, welcomeInfo.NodeId, out neighborToClose, out closeReason2, out action);
 
                if (neighbor != neighborToClose)
                {
                    // Neighbor should be accepted AddReferrals validates the referrals,
                    // if they are valid then the neighbor is accepted. 
                    if (this.maintainer.AddReferrals(welcomeInfo.Referrals, neighbor))
                    { 
                        if (!neighbor.TrySetState(PeerNeighborState.Connected)) 
                        {
                            if (!(neighbor.State >= PeerNeighborState.Faulted)) 
                            {
                                DiagnosticUtility.DebugAssert("Neighbor state expected to be >= Faulted; it is " + neighbor.State.ToString());
                                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false);
                            } 
                        }
 
                        if (neighborToClose != null) 
                        {
                            // The other neighbor should be closed 
                            SendTerminatingMessage(neighborToClose, action, closeReason2);
                            this.neighborManager.CloseNeighbor(neighborToClose, closeReason2, PeerCloseInitiator.LocalNode);
                        }
                    } 
                    else
                    { 
                        // Referrals were invalid this node is suspicous 
                        closeReason = PeerCloseReason.InvalidNeighbor;
                    } 
                }
                else
                {
                    closeReason = closeReason2; 
                }
            } 
 
            if (closeReason != PeerCloseReason.None)
            { 
                SendTerminatingMessage(neighbor, PeerStrings.DisconnectAction, closeReason);
                this.neighborManager.CloseNeighbor(neighbor, closeReason, PeerCloseInitiator.LocalNode);
            }
        } 

        bool RemoveTimer (IPeerNeighbor neighbor) 
        { 
            IOThreadTimer timer = null;
            bool removed = false; 

            // Remove the timer from the table and cancel it. Do this if Connector is
            // still open. Otherwise, Close method will have already cancelled the timers.
            lock (ThisLock) 
            {
                if (this.state == State.Opened && 
                    this.timerTable.TryGetValue(neighbor, out timer)) 
                {
                    removed = this.timerTable.Remove(neighbor); 
                }
            }
            if (timer != null)
            { 
                timer.Cancel();
                if (!(removed)) 
                { 
                    DiagnosticUtility.DebugAssert("Neighbor key should have beeen removed from the table");
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); 
                }
            }

            return removed; 
        }
 
        void SendConnect (IPeerNeighbor neighbor) 
        {
            // We do not attempt to send the message if PeerConnector is not open 
            if (neighbor.State == PeerNeighborState.Connecting && this.state == State.Opened)
            {
                // Retrieve the local address. The retrieved address may be null if the node
                // is shutdown. In that case, don't bother to send connect message since the 
                // node is closing...
                PeerNodeAddress listenAddress = this.config.GetListenAddress(true); 
                if (listenAddress != null) 
                {
                    ConnectInfo connectInfo = new ConnectInfo(this.config.NodeId, listenAddress); 
                    Message message = ConnectInfoMessageConverter.ToMessage(connectInfo, MessageVersion.Soap12WSAddressing10);
                    SendMessageToNeighbor(neighbor, message, OnConnectFailure);
                }
            } 
        }
 
        // Send Disconnect or Refuse message 
        void SendTerminatingMessage(IPeerNeighbor neighbor, string action, PeerCloseReason closeReason)
        { 
            // We do not attempt to send the message if Connector is not open
            // or if the close reason is InvalidNeighbor.
            if (this.state != State.Opened || closeReason == PeerCloseReason.InvalidNeighbor)
                return; 

            // Set the neighbor state to disconnecting. TrySetState can fail if the 
            // neighbor is already being closed. Disconnect/Refuse msg not sent in that case. 
            if (neighbor.TrySetState(PeerNeighborState.Disconnecting))
            { 
                // Get referrals from the maintainer
                Referral[] referrals = maintainer.GetReferrals();

                // Build and send the message 
                Message message;
                if (action == PeerStrings.DisconnectAction) 
                { 
                    DisconnectInfo disconnectInfo = new DisconnectInfo((DisconnectReason)closeReason, referrals);
                    message = DisconnectInfoMessageConverter.ToMessage(disconnectInfo, MessageVersion.Soap12WSAddressing10); 
                }
                else
                {
                    RefuseInfo refuseInfo = new RefuseInfo((RefuseReason)closeReason, referrals); 
                    message = RefuseInfoMessageConverter.ToMessage(refuseInfo, MessageVersion.Soap12WSAddressing10);
                } 
                SendMessageToNeighbor(neighbor, message, null); 
            }
            else 
                if (!(neighbor.State >= PeerNeighborState.Disconnecting))
                {
                    DiagnosticUtility.DebugAssert("Neighbor state expected to be >= Disconnecting; it is " + neighbor.State.ToString());
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); 
                }
        } 
 
        void SendWelcome (IPeerNeighbor neighbor)
        { 
            // We do not attempt to send the message if PeerConnector is not open
            if (state == State.Opened)
            {
                // Get referrals from the maintainer 
                Referral[] referrals = maintainer.GetReferrals();
 
                WelcomeInfo welcomeInfo = new WelcomeInfo(this.config.NodeId, referrals); 
                Message message = WelcomeInfoMessageConverter.ToMessage(welcomeInfo, MessageVersion.Soap12WSAddressing10);
                SendMessageToNeighbor(neighbor, message, OnConnectFailure); 
            }
        }

        // Validates the new neighbor based on its node ID. If it detects duplicate neighbor condition, 
        // it will return reference to the neighbor that should be closed.
        void ValidateNeighbor(IPeerNeighbor neighbor, ulong neighborNodeId, 
            out IPeerNeighbor neighborToClose, out PeerCloseReason closeReason, out string action) 
        {
            neighborToClose = null; 
            closeReason = PeerCloseReason.None;
            action = null;

            // Invalid neighbor node Id? 
            if (neighborNodeId == PeerTransportConstants.InvalidNodeId)
            { 
                neighborToClose = neighbor; 
                closeReason = PeerCloseReason.InvalidNeighbor;
            } 
            // Neighbor's node ID matches local node Id?
            else if (neighborNodeId == this.config.NodeId)
            {
                neighborToClose = neighbor; 
                closeReason = PeerCloseReason.DuplicateNodeId;
            } 
            else 
            {
                // Check for duplicate neighbors (i.e., if another neighbor has the 
                // same node Id as the new neighbor).
                // Set neighbor's node Id prior to calling FindDuplicateNeighbor.
                try
                { 
                    neighbor.NodeId = neighborNodeId;
                } 
                catch (ObjectDisposedException e) 
                {
                    DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); 
                    return;
                }

                IPeerNeighbor duplicateNeighbor = 
                    this.neighborManager.FindDuplicateNeighbor(neighborNodeId, neighbor);
                if(duplicateNeighbor != null && this.neighborManager.PingNeighbor(duplicateNeighbor)) 
                { 
                    // We have a duplicate neighbor. Determine which one should be closed
                    closeReason = PeerCloseReason.DuplicateNeighbor; 

                    // In the corner case where both neighbors are initiated by the same node,
                    // close the new neighbor -- Maintainer is expected to check if there is
                    // already a connection to a node prior to initiating a new connection. 
                    if (neighbor.IsInitiator == duplicateNeighbor.IsInitiator)
                        neighborToClose = neighbor; 
 
                    // Otherwise, close the neighbor that was initiated by the node with the
                    // larger node ID -- this ensures that both nodes tear down the same link. 
                    else if (this.config.NodeId > neighborNodeId)
                        neighborToClose = (neighbor.IsInitiator ? neighbor : duplicateNeighbor);
                    else
                        neighborToClose = (neighbor.IsInitiator ? duplicateNeighbor : neighbor); 
                }
            } 
 
            if (neighborToClose != null)
            { 
                // If we decided to close the other neighbor, go ahead and do it.
                if (neighborToClose != neighbor)
                {
                    // Send Disconnect or Refuse message depending on its state 
                    if (neighborToClose.State == PeerNeighborState.Connected)
                    { 
                        action = PeerStrings.DisconnectAction; 
                    }
                    else if (!neighborToClose.IsInitiator && 
                        neighborToClose.State == PeerNeighborState.Connecting)
                    {
                        action = PeerStrings.RefuseAction;
                    } 
                }
            } 
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK