Exemple #1
0
        void IFlooderForThrottle.OnThrottleReached()
        {
            if (DiagnosticUtility.ShouldTraceInformation)
            {
                string message = SR.GetString(SR.PeerThrottleWaiting, this.config.MeshId);
                PeerThrottleTraceRecord record = new PeerThrottleTraceRecord(this.config.MeshId, message);
                TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.PeerFlooderReceiveMessageQuotaExceeded,
                                        SR.GetString(SR.TraceCodePeerFlooderReceiveMessageQuotaExceeded), record, this, null);
            }

            IPeerNeighbor peer = this.neighborManager.SlowestNeighbor();

            if (peer == null)
            {
                return;
            }
            UtilityExtension extension = peer.Utility;

            if (peer.IsConnected && extension != null)
            {
                if (extension.PendingMessages > PeerTransportConstants.MessageThreshold)
                {
                    extension.BeginCheckPoint(new UtilityExtension.PruneNeighborCallback(PruneNeighborCallback));
                }
                else
                {
                    Fx.Assert(false, "Neighbor is marked slow with messages " + extension.PendingMessages);
                }
                FireReachedEvent();
            }
        }
        // Notify whoever is interested in NeighborClosed, and start the Maintenance algorithms at threshold
        public virtual void OnNeighborClosed(IPeerNeighbor neighbor)
        {
            if (isOpen)
            {
                lock (ThisLock)
                {
                    if (neighbor != null && neighbor.ListenAddress != null)
                    {
                        EndpointAddress key = neighbor.ListenAddress.EndpointAddress;
                    }

                    if (isOpen && !isRunningMaintenance && neighborManager.ConnectedNeighborCount < config.MinNeighbors)
                    {
                        maintainerTimer.Set(0);
                    }
                }
            }

            NeighborClosedHandler handler = NeighborClosed;

            if (handler != null)
            {
                handler(neighbor);
            }
        }
 public void AddResult(IAsyncResult result, IPeerNeighbor neighbor)
 {
     lock (this.ThisLock)
     {
         this.results.Add(result, neighbor);
     }
 }
Exemple #4
0
 public override void ProcessLinkUtility(IPeerNeighbor neighbor, UtilityInfo utilityInfo)
 {
     if (!PeerNeighborStateHelper.IsConnected(neighbor.State))
     {
         neighbor.Abort(PeerCloseReason.InvalidNeighbor, PeerCloseInitiator.LocalNode);
     }
     else
     {
         try
         {
             UtilityExtension.ProcessLinkUtility(neighbor, utilityInfo);
         }
         catch (Exception exception)
         {
             if (Fx.IsFatal(exception))
             {
                 throw;
             }
             if (PeerFlooderBase <Message, UtilityInfo> .CloseNeighborIfKnownException(base.neighborManager, exception, neighbor) != null)
             {
                 throw;
             }
             DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Information);
         }
     }
 }
        private void OnReferralsAdded(IList <Referral> referrals, IPeerNeighbor neighbor)
        {
            bool flag = false;

            foreach (Referral referral in referrals)
            {
                if (!this.disposed)
                {
                    lock (this.ThisLock)
                    {
                        if (!this.disposed)
                        {
                            if (!this.maintainer.IsOpen)
                            {
                                return;
                            }
                            Uri endpointUri = GetEndpointUri(referral.Address);
                            if (((endpointUri != GetEndpointUri(this.maintainer.GetListenAddress())) && !this.nodeAddresses.ContainsKey(endpointUri)) && (!this.pendingConnectedNeighbor.ContainsKey(endpointUri) && (this.maintainer.FindDuplicateNeighbor(referral.Address) == null)))
                            {
                                this.nodeAddresses[endpointUri] = referral.Address;
                                flag = true;
                            }
                        }
                    }
                }
            }
            if (flag && (this.maintainer.ConnectedNeighborCount < this.wantedConnectionCount))
            {
                this.addNeighbor.Set();
            }
        }
 private void SendTerminatingMessage(IPeerNeighbor neighbor, string action, PeerCloseReason closeReason)
 {
     if ((this.state == State.Opened) && (closeReason != PeerCloseReason.InvalidNeighbor))
     {
         if (neighbor.TrySetState(PeerNeighborState.Disconnecting))
         {
             Message    message;
             Referral[] referrals = this.maintainer.GetReferrals();
             if (action == "http://schemas.microsoft.com/net/2006/05/peer/Disconnect")
             {
                 DisconnectInfo typedMessage = new DisconnectInfo((DisconnectReason)closeReason, referrals);
                 message = this.DisconnectInfoMessageConverter.ToMessage(typedMessage, MessageVersion.Soap12WSAddressing10);
             }
             else
             {
                 RefuseInfo info2 = new RefuseInfo((RefuseReason)closeReason, referrals);
                 message = this.RefuseInfoMessageConverter.ToMessage(info2, MessageVersion.Soap12WSAddressing10);
             }
             this.SendMessageToNeighbor(neighbor, message, null);
         }
         else if (neighbor.State < PeerNeighborState.Disconnecting)
         {
             throw Fx.AssertAndThrow("Neighbor state expected to be >= Disconnecting; it is " + neighbor.State.ToString());
         }
     }
 }
Exemple #7
0
 void PruneNeighborCallback(IPeerNeighbor peer)
 {
     lock (ThisLock)
     {
         if (this.Neighbors.Count <= 1)
         {
             return;
         }
         if (DiagnosticUtility.ShouldTraceWarning)
         {
             string message = SR.GetString(SR.PeerThrottlePruning, this.config.MeshId);
             PeerThrottleTraceRecord record = new PeerThrottleTraceRecord(this.config.MeshId, message);
             TraceUtility.TraceEvent(TraceEventType.Warning, TraceCode.PeerFlooderReceiveMessageQuotaExceeded,
                                     SR.GetString(SR.TraceCodePeerFlooderReceiveMessageQuotaExceeded), record, this, null);
         }
     }
     try
     {
         peer.Abort(PeerCloseReason.NodeTooSlow, PeerCloseInitiator.LocalNode);
     }
     catch (Exception e)
     {
         if (Fx.IsFatal(e))
         {
             throw;
         }
         if (null != CloseNeighborIfKnownException(neighborManager, e, peer))
         {
             throw;
         }
         DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
     }
 }
Exemple #8
0
 public void AddResult(IAsyncResult result, IPeerNeighbor neighbor)
 {
     lock (ThisLock)
     {
         this.results.Add(result, neighbor);
     }
 }
 private void CleanupOnConnectFailure(IPeerNeighbor neighbor, PeerCloseReason reason, Exception exception)
 {
     if (this.RemoveTimer(neighbor))
     {
         this.neighborManager.CloseNeighbor(neighbor, reason, PeerCloseInitiator.LocalNode, exception);
     }
 }
 protected virtual IAsyncResult BeginFloodReceivedMessage(IPeerNeighbor sender, MessageBuffer messageBuffer, TimeSpan timeout, AsyncCallback callback, object state, int index, MessageHeader hopHeader)
 {
     this.quotaHelper.AcquireNoQueue();
     try
     {
         return(this.FloodMessageToNeighbors(messageBuffer, timeout, callback, state, index, hopHeader, sender, this.OnMessageSentHandler));
     }
     catch (Exception exception)
     {
         if (Fx.IsFatal(exception))
         {
             throw;
         }
         if (!(exception is QuotaExceededException) && (!(exception is CommunicationException) || !(exception.InnerException is QuotaExceededException)))
         {
             throw;
         }
         System.ServiceModel.DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Information);
         if (System.ServiceModel.DiagnosticUtility.ShouldTraceError)
         {
             PeerFlooderTraceRecord extendedData = new PeerFlooderTraceRecord(this.config.MeshId, sender.ListenAddress, exception);
             TraceUtility.TraceEvent(TraceEventType.Error, 0x4004f, System.ServiceModel.SR.GetString("TraceCodePeerFlooderReceiveMessageQuotaExceeded"), extendedData, this, null);
         }
         return(null);
     }
 }
 private void PruneNeighborCallback(IPeerNeighbor peer)
 {
     lock (this.ThisLock)
     {
         if (this.Neighbors.Count <= 1)
         {
             return;
         }
         if (System.ServiceModel.DiagnosticUtility.ShouldTraceWarning)
         {
             string message = System.ServiceModel.SR.GetString("PeerThrottlePruning", new object[] { this.config.MeshId });
             PeerThrottleTraceRecord extendedData = new PeerThrottleTraceRecord(this.config.MeshId, message);
             TraceUtility.TraceEvent(TraceEventType.Warning, 0x4004f, System.ServiceModel.SR.GetString("TraceCodePeerFlooderReceiveMessageQuotaExceeded"), extendedData, this, null);
         }
     }
     try
     {
         peer.Abort(PeerCloseReason.NodeTooSlow, PeerCloseInitiator.LocalNode);
     }
     catch (Exception exception)
     {
         if (Fx.IsFatal(exception))
         {
             throw;
         }
         if (PeerFlooderBase <TFloodContract, TLinkContract> .CloseNeighborIfKnownException(this.neighborManager, exception, peer) != null)
         {
             throw;
         }
         System.ServiceModel.DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Information);
     }
 }
 public void OnNeighborAuthenticated(IPeerNeighbor neighbor)
 {
     if (this.state == State.Created)
     {
         throw Fx.AssertAndThrow("Connector not expected to be in Created state");
     }
     if (!PeerNeighborStateHelper.IsAuthenticatedOrClosed(neighbor.State))
     {
         throw Fx.AssertAndThrow(string.Format(CultureInfo.InvariantCulture, "Neighbor state expected to be Authenticated or Closed, actual state: {0}", new object[] { neighbor.State }));
     }
     if (!neighbor.TrySetState(PeerNeighborState.Connecting))
     {
         if (neighbor.State < PeerNeighborState.Faulted)
         {
             throw Fx.AssertAndThrow(string.Format(CultureInfo.InvariantCulture, "Neighbor state expected to be Faulted or Closed, actual state: {0}", new object[] { neighbor.State }));
         }
     }
     else if (this.AddTimer(neighbor) && neighbor.IsInitiator)
     {
         if (this.neighborManager.ConnectedNeighborCount < this.config.MaxNeighbors)
         {
             this.SendConnect(neighbor);
         }
         else
         {
             this.neighborManager.CloseNeighbor(neighbor, PeerCloseReason.NodeBusy, PeerCloseInitiator.LocalNode);
         }
     }
 }
Exemple #13
0
        // 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 <Referral> 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);
        }
 private void CleanupOnConnectFailure(IPeerNeighbor neighbor, PeerCloseReason reason, Exception exception)
 {
     if (this.RemoveTimer(neighbor))
     {
         this.neighborManager.CloseNeighbor(neighbor, reason, PeerCloseInitiator.LocalNode, exception);
     }
 }
        private void SendMessageToNeighbor(IPeerNeighbor neighbor, Message message, PeerMessageHelpers.CleanupCallback cleanupCallback)
        {
            bool flag = false;

            try
            {
                neighbor.Send(message);
            }
            catch (Exception exception)
            {
                if (Fx.IsFatal(exception))
                {
                    flag = true;
                    throw;
                }
                if ((!(exception is CommunicationException) && !(exception is QuotaExceededException)) && (!(exception is ObjectDisposedException) && !(exception is TimeoutException)))
                {
                    throw;
                }
                DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Information);
                if (cleanupCallback != null)
                {
                    cleanupCallback(neighbor, PeerCloseReason.InternalFailure, exception);
                }
            }
            finally
            {
                if (!flag)
                {
                    message.Close();
                }
            }
        }
 public void OnNeighborClosing(IPeerNeighbor neighbor, PeerCloseReason closeReason)
 {
     if (neighbor.IsConnected)
     {
         this.SendTerminatingMessage(neighbor, "http://schemas.microsoft.com/net/2006/05/peer/Disconnect", closeReason);
     }
 }
        private IPeerNeighbor GetNeighbor()
        {
            IPeerNeighbor neighbor = this.getNeighborCallback(OperationContext.Current.GetCallbackChannel <IPeerProxy>());

            if ((neighbor == null) || (neighbor.State == PeerNeighborState.Closed))
            {
                if (DiagnosticUtility.ShouldTraceWarning)
                {
                    TraceUtility.TraceEvent(TraceEventType.Warning, 0x40036, System.ServiceModel.SR.GetString("TraceCodePeerNeighborNotFound"), new PeerNodeTraceRecord(this.config.NodeId), OperationContext.Current.IncomingMessage);
                }
                return(null);
            }
            if (DiagnosticUtility.ShouldTraceVerbose)
            {
                PeerNeighborState state            = neighbor.State;
                PeerNodeAddress   listenAddress    = null;
                IPAddress         connectIPAddress = null;
                if ((state >= PeerNeighborState.Opened) && (state <= PeerNeighborState.Connected))
                {
                    listenAddress    = this.config.GetListenAddress(true);
                    connectIPAddress = this.config.ListenIPAddress;
                }
                PeerNeighborTraceRecord extendedData = new PeerNeighborTraceRecord(neighbor.NodeId, this.config.NodeId, listenAddress, connectIPAddress, neighbor.GetHashCode(), neighbor.IsInitiator, state.ToString(), null, null, OperationContext.Current.IncomingMessage.Headers.Action);
                TraceUtility.TraceEvent(TraceEventType.Verbose, 0x4003a, System.ServiceModel.SR.GetString("TraceCodePeerNeighborMessageReceived"), extendedData, this, null);
            }
            return(neighbor);
        }
Exemple #18
0
        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)
                {
                    throw Fx.AssertAndThrow("Neighbor key should have beeen removed from the table");
                }
            }

            return(removed);
        }
Exemple #19
0
        // 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 <Referral> 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);
        }
Exemple #20
0
        public override void ProcessLinkUtility(IPeerNeighbor neighbor, UtilityInfo utilityInfo)
        {
            if (!PeerNeighborStateHelper.IsConnected(neighbor.State))
            {
                neighbor.Abort(PeerCloseReason.InvalidNeighbor, PeerCloseInitiator.LocalNode);
                return;
            }

            try
            {
                UtilityExtension.ProcessLinkUtility(neighbor, utilityInfo);
            }
            catch (Exception e)
            {
                if (Fx.IsFatal(e))
                {
                    throw;
                }
                if (null != CloseNeighborIfKnownException(neighborManager, e, neighbor))
                {
                    throw;
                }
                DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
            }
        }
Exemple #21
0
        public void OnNeighborOpened(object sender, EventArgs args)
        {
            IPeerNeighbor neighbor = sender as IPeerNeighbor;
            EventHandler  handler  = this.OnNeighborAuthenticated;

            if (handler == null)
            {
                neighbor.Abort(PeerCloseReason.LeavingMesh, PeerCloseInitiator.LocalNode);
                return;
            }
            if (this.authenticationMode == PeerAuthenticationMode.Password)
            {
                if (!(neighbor.Extensions.Find <PeerChannelAuthenticatorExtension>() == null))
                {
                    throw Fx.AssertAndThrow("extension already exists!");
                }
                PeerChannelAuthenticatorExtension extension = new PeerChannelAuthenticatorExtension(this, handler, args, this.MeshId);
                neighbor.Extensions.Add(extension);
                if (neighbor.IsInitiator)
                {
                    extension.InitiateHandShake();
                }
            }
            else
            {
                neighbor.TrySetState(PeerNeighborState.Authenticated);
                handler(sender, args);
            }
        }
 public void Connect(IPeerNeighbor neighbor, ConnectInfo connectInfo)
 {
     if (this.state == State.Opened)
     {
         PeerCloseReason none = PeerCloseReason.None;
         if ((neighbor.IsInitiator || !connectInfo.HasBody()) || ((neighbor.State != PeerNeighborState.Connecting) && (neighbor.State != PeerNeighborState.Closed)))
         {
             none = PeerCloseReason.InvalidNeighbor;
         }
         else if (this.RemoveTimer(neighbor))
         {
             if (this.neighborManager.ConnectedNeighborCount >= this.config.MaxNeighbors)
             {
                 none = PeerCloseReason.NodeBusy;
             }
             else if (!PeerValidateHelper.ValidNodeAddress(connectInfo.Address))
             {
                 none = PeerCloseReason.InvalidNeighbor;
             }
             else
             {
                 PeerCloseReason reason2;
                 IPeerNeighbor   neighbor2;
                 string          action = "http://schemas.microsoft.com/net/2006/05/peer/Refuse";
                 this.ValidateNeighbor(neighbor, connectInfo.NodeId, out neighbor2, out reason2, out action);
                 if (neighbor != neighbor2)
                 {
                     this.SendWelcome(neighbor);
                     try
                     {
                         neighbor.ListenAddress = connectInfo.Address;
                     }
                     catch (ObjectDisposedException exception)
                     {
                         DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Information);
                     }
                     if (!neighbor.TrySetState(PeerNeighborState.Connected) && (neighbor.State < PeerNeighborState.Disconnecting))
                     {
                         throw Fx.AssertAndThrow("Neighbor state expected to be >= Disconnecting; it is " + neighbor.State.ToString());
                     }
                     if (neighbor2 != null)
                     {
                         this.SendTerminatingMessage(neighbor2, action, reason2);
                         this.neighborManager.CloseNeighbor(neighbor2, reason2, PeerCloseInitiator.LocalNode);
                     }
                 }
                 else
                 {
                     none = reason2;
                 }
             }
         }
         if (none != PeerCloseReason.None)
         {
             this.SendTerminatingMessage(neighbor, "http://schemas.microsoft.com/net/2006/05/peer/Refuse", none);
             this.neighborManager.CloseNeighbor(neighbor, none, PeerCloseInitiator.LocalNode);
         }
     }
 }
Exemple #23
0
 // 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);
     }
 }
        void IPeerServiceContract.Refuse(RefuseInfo refuseInfo)
        {
            IPeerNeighbor neighbor = this.GetNeighbor();

            if (neighbor != null)
            {
                this.connector.Refuse(neighbor, refuseInfo);
            }
        }
        void IPeerServiceContract.Connect(ConnectInfo connectInfo)
        {
            IPeerNeighbor neighbor = this.GetNeighbor();

            if (neighbor != null)
            {
                this.connector.Connect(neighbor, connectInfo);
            }
        }
        void IPeerServiceContract.LinkUtility(UtilityInfo utilityInfo)
        {
            IPeerNeighbor neighbor = this.GetNeighbor();

            if (neighbor != null)
            {
                this.flooder.ProcessLinkUtility(neighbor, utilityInfo);
            }
        }
        void IPeerServiceContract.Disconnect(DisconnectInfo disconnectInfo)
        {
            IPeerNeighbor neighbor = this.GetNeighbor();

            if (neighbor != null)
            {
                this.connector.Disconnect(neighbor, disconnectInfo);
            }
        }
        void IPeerServiceContract.Welcome(WelcomeInfo welcomeInfo)
        {
            IPeerNeighbor neighbor = this.GetNeighbor();

            if (neighbor != null)
            {
                this.connector.Welcome(neighbor, welcomeInfo);
            }
        }
        // Maintainer is expected to validate and accept the contents of referrals
        // and to determine how many referrals it will accept from the array.
        // Neighbor reference is passed in case the Maintainer decided to reject a referral
        // based on invalid content and close the neighbor.
        public bool AddReferrals(IList <Referral> referrals, IPeerNeighbor neighbor)
        {
            Fx.Assert(null != config.Resolver, "");

            bool valid             = true;
            bool canShareReferrals = false;

            try
            {
                canShareReferrals = config.Resolver.CanShareReferrals;
            }
            catch (Exception e)
            {
                if (Fx.IsFatal(e))
                {
                    throw;
                }
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(SR.GetString(SR.ResolverException), e);
            }
            if (referrals != null && canShareReferrals)
            {
                foreach (Referral referral in referrals)
                {
                    // If any referral is invalid then the connection is bad so don't accept any referals from this neighbor.
                    if (referral == null ||
                        referral.NodeId == PeerTransportConstants.InvalidNodeId ||
                        !PeerValidateHelper.ValidNodeAddress(referral.Address) ||
                        !PeerValidateHelper.ValidReferralNodeAddress(referral.Address))
                    {
                        valid = false;
                        break;
                    }
                }
                if (valid)
                {
                    lock (ThisLock)
                    {
                        foreach (Referral referral in referrals)
                        {
                            EndpointAddress key = referral.Address.EndpointAddress;
                            if (referralCache.Count <= this.config.MaxReferralCacheSize && !referralCache.ContainsKey(key))
                            {
                                referralCache.Add(key, referral);
                            }
                        }
                    }

                    // Invoke any handler that is interested in Referrals being added.
                    ReferralsAddedHandler handler = ReferralsAdded;
                    if (handler != null)
                    {
                        ReferralsAdded(referrals, neighbor);
                    }
                }
            }
            return(valid);
        }
Exemple #30
0
        public virtual void OnNeighborConnected(IPeerNeighbor neighbor)
        {
            NeighborConnectedHandler neighborConnected = this.NeighborConnected;

            if (neighborConnected != null)
            {
                neighborConnected(neighbor);
            }
        }
        public virtual void OnNeighborConnected(IPeerNeighbor neighbor)
        {
            NeighborConnectedHandler handler = NeighborConnected;

            if (handler != null)
            {
                handler(neighbor);
            }
        }
        private void KillSlowNeighbor()
        {
            IPeerNeighbor neighbor = this.neighborManager.SlowestNeighbor();

            if (neighbor != null)
            {
                neighbor.Abort(PeerCloseReason.NodeTooSlow, PeerCloseInitiator.LocalNode);
            }
        }
 private void CompleteTerminateMessageProcessing(IPeerNeighbor neighbor, PeerCloseReason closeReason, IList<Referral> referrals)
 {
     if (neighbor.TrySetState(PeerNeighborState.Disconnected))
     {
         this.neighborManager.CloseNeighbor(neighbor, closeReason, PeerCloseInitiator.RemoteNode);
     }
     else if (neighbor.State < PeerNeighborState.Disconnected)
     {
         throw Fx.AssertAndThrow("Unexpected neighbor state");
     }
     this.maintainer.AddReferrals(referrals, neighbor);
 }
 private bool AddTimer(IPeerNeighbor neighbor)
 {
     bool flag = false;
     lock (this.ThisLock)
     {
         if ((this.state == State.Opened) && (neighbor.State == PeerNeighborState.Connecting))
         {
             IOThreadTimer timer = new IOThreadTimer(new Action<object>(this.OnConnectTimeout), neighbor, true);
             timer.Set(this.config.ConnectTimeout);
             this.timerTable.Add(neighbor, timer);
             flag = true;
         }
     }
     return flag;
 }
        public bool PingNeighbor(IPeerNeighbor peer)
        {
            bool result = true;
            Message message = Message.CreateMessage(MessageVersion.Soap12WSAddressing10, PeerStrings.PingAction);
            try
            {
                peer.Ping(message);
            }
            catch (Exception e)
            {
                if (Fx.IsFatal(e)) throw;
                DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
                peer.Abort(PeerCloseReason.InternalFailure, PeerCloseInitiator.LocalNode);
                result = false;
            }
            return result;

        }
        public void CloseNeighbor(IPeerNeighbor neighbor, PeerCloseReason closeReason,
            PeerCloseInitiator closeInitiator, Exception closeException)
        {
            PeerNeighbor nbr = (PeerNeighbor)neighbor;

            lock (ThisLock)
            {
                if (!(this.state != State.Created))
                {
                    throw Fx.AssertAndThrow("Neighbor Manager is not expected to be in Created state");
                }

                // Check that the neighbor is known to neighbor manager
                if (!this.neighborList.Contains(nbr))
                    return;
            }

            // initiate closing of the neighbor
            if (closeReason != PeerCloseReason.InvalidNeighbor)
            {
                if (!nbr.IsClosing)
                    InvokeAsyncNeighborClose(nbr, closeReason, closeInitiator, closeException, null);
            }
            else    // Call abort even if neighbor is already closing
            {
                nbr.Abort(closeReason, closeInitiator);
            }
        }
 private void ValidateNeighbor(IPeerNeighbor neighbor, ulong neighborNodeId, out IPeerNeighbor neighborToClose, out PeerCloseReason closeReason, out string action)
 {
     neighborToClose = null;
     closeReason = PeerCloseReason.None;
     action = null;
     if (neighborNodeId == 0L)
     {
         neighborToClose = neighbor;
         closeReason = PeerCloseReason.InvalidNeighbor;
     }
     else if (neighborNodeId == this.config.NodeId)
     {
         neighborToClose = neighbor;
         closeReason = PeerCloseReason.DuplicateNodeId;
     }
     else
     {
         try
         {
             neighbor.NodeId = neighborNodeId;
         }
         catch (ObjectDisposedException exception)
         {
             DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Information);
             return;
         }
         IPeerNeighbor peer = this.neighborManager.FindDuplicateNeighbor(neighborNodeId, neighbor);
         if ((peer != null) && this.neighborManager.PingNeighbor(peer))
         {
             closeReason = PeerCloseReason.DuplicateNeighbor;
             if (neighbor.IsInitiator == peer.IsInitiator)
             {
                 neighborToClose = neighbor;
             }
             else if (this.config.NodeId > neighborNodeId)
             {
                 neighborToClose = neighbor.IsInitiator ? neighbor : peer;
             }
             else
             {
                 neighborToClose = neighbor.IsInitiator ? peer : neighbor;
             }
         }
     }
     if ((neighborToClose != null) && (neighborToClose != neighbor))
     {
         if (neighborToClose.State == PeerNeighborState.Connected)
         {
             action = "http://schemas.microsoft.com/net/2006/05/peer/Disconnect";
         }
         else if (!neighborToClose.IsInitiator && (neighborToClose.State == PeerNeighborState.Connecting))
         {
             action = "http://schemas.microsoft.com/net/2006/05/peer/Refuse";
         }
     }
 }
        // 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.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;
                    }
                }
            }
        }
        // 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))
                {
                    throw Fx.AssertAndThrow("Neighbor state expected to be >= Disconnecting; it is " + neighbor.State.ToString());
                }
        }
        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)
                {
                    throw Fx.AssertAndThrow("Neighbor key should have beeen removed from the table");
                }
            }

            return removed;
        }
 // 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);
     }
 }
 //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 (Fx.IsFatal(e))
         {
             fatal = true;
             throw;
         }
         if (e is CommunicationException ||
             e is QuotaExceededException ||
             e is ObjectDisposedException ||
             e is TimeoutException)
         {
             DiagnosticUtility.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();
     }
 }
        // 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 Action<object>(OnConnectTimeout), neighbor, true);
                    timer.Set(this.config.ConnectTimeout);
                    this.timerTable.Add(neighbor, timer);
                    added = true;
                }
            }

            return added;
        }
 public void Welcome(IPeerNeighbor neighbor, WelcomeInfo welcomeInfo)
 {
     if (this.state == State.Opened)
     {
         PeerCloseReason none = PeerCloseReason.None;
         if ((!neighbor.IsInitiator || !welcomeInfo.HasBody()) || ((neighbor.State != PeerNeighborState.Connecting) && (neighbor.State != PeerNeighborState.Closed)))
         {
             none = PeerCloseReason.InvalidNeighbor;
         }
         else if (this.RemoveTimer(neighbor))
         {
             PeerCloseReason reason2;
             IPeerNeighbor neighbor2;
             string action = "http://schemas.microsoft.com/net/2006/05/peer/Refuse";
             this.ValidateNeighbor(neighbor, welcomeInfo.NodeId, out neighbor2, out reason2, out action);
             if (neighbor != neighbor2)
             {
                 if (this.maintainer.AddReferrals(welcomeInfo.Referrals, neighbor))
                 {
                     if (!neighbor.TrySetState(PeerNeighborState.Connected) && (neighbor.State < PeerNeighborState.Faulted))
                     {
                         throw Fx.AssertAndThrow("Neighbor state expected to be >= Faulted; it is " + neighbor.State.ToString());
                     }
                     if (neighbor2 != null)
                     {
                         this.SendTerminatingMessage(neighbor2, action, reason2);
                         this.neighborManager.CloseNeighbor(neighbor2, reason2, PeerCloseInitiator.LocalNode);
                     }
                 }
                 else
                 {
                     none = PeerCloseReason.InvalidNeighbor;
                 }
             }
             else
             {
                 none = reason2;
             }
         }
         if (none != PeerCloseReason.None)
         {
             this.SendTerminatingMessage(neighbor, "http://schemas.microsoft.com/net/2006/05/peer/Disconnect", none);
             this.neighborManager.CloseNeighbor(neighbor, none, PeerCloseInitiator.LocalNode);
         }
     }
 }
        // 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))
                            {
                                throw Fx.AssertAndThrow("Neighbor state expected to be >= Faulted; it is " + neighbor.State.ToString());
                            }
                        }

                        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);
            }
        }
        // Complete processing of Disconnect or Refuse message from the neighbor
        void CompleteTerminateMessageProcessing(IPeerNeighbor neighbor,
            PeerCloseReason closeReason, IList<Referral> 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))
                {
                    throw Fx.AssertAndThrow("Unexpected neighbor state");
                }

            // Hand over the referrals to maintainer
            this.maintainer.AddReferrals(referrals, neighbor);
        }
 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);
         }
     }
 }
 void OnConnectFailure(IPeerNeighbor neighbor, PeerCloseReason reason,
     Exception exception)
 {
     CleanupOnConnectFailure(neighbor, reason, exception);
 }
        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);
            }
        }
 // 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))
            {
                throw Fx.AssertAndThrow("Connector not expected to be in Created state");
            }

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

            // 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))
                {
                    throw Fx.AssertAndThrow(string.Format(CultureInfo.InvariantCulture, "Neighbor state expected to be Faulted or Closed, actual state: {0}", neighbor.State));
                }
                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);
                    }
                }
            }
        }
 private void SendWelcome(IPeerNeighbor neighbor)
 {
     if (this.state == State.Opened)
     {
         Referral[] referrals = this.maintainer.GetReferrals();
         WelcomeInfo typedMessage = new WelcomeInfo(this.config.NodeId, referrals);
         Message message = this.WelcomeInfoMessageConverter.ToMessage(typedMessage, MessageVersion.Soap12WSAddressing10);
         this.SendMessageToNeighbor(neighbor, message, new PeerMessageHelpers.CleanupCallback(this.OnConnectFailure));
     }
 }
        //<Implementation of PeerConnector.IPeerConnectorContract>
        // 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.TraceHandledException(e, TraceEventType.Information);
                            }

                            if (!neighbor.TrySetState(PeerNeighborState.Connected))
                                if (!(neighbor.State >= PeerNeighborState.Disconnecting))
                                {
                                    throw Fx.AssertAndThrow("Neighbor state expected to be >= Disconnecting; it is " + neighbor.State.ToString());
                                }

                            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);
            }
        }
 //
 // Close the specified neighbor. Ok to call multiple times, but NeighborClosing 
 // and NeighborClosed events are fired just once.
 // If the closeReason specified is InvalidNeighbor, it will be closed ungracefully
 //
 public void CloseNeighbor(IPeerNeighbor neighbor, PeerCloseReason closeReason,
     PeerCloseInitiator closeInitiator)
 {
     CloseNeighbor(neighbor, closeReason, closeInitiator, null);
 }
        // 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<Referral> 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);
        }
        // Find a duplicate neighbor (excluding skipNeighbor) matching the nodeID.
        public IPeerNeighbor FindDuplicateNeighbor(ulong nodeId, IPeerNeighbor skipNeighbor)
        {
            PeerNeighbor duplicateNeighbor = null;

            if (nodeId != PeerTransportConstants.InvalidNodeId)
            {
                lock (ThisLock)
                {
                    foreach (PeerNeighbor neighbor in this.neighborList)
                    {
                        // We restrict search to neighbors that are not yet closing.
                        if (neighbor != (PeerNeighbor)skipNeighbor && neighbor.NodeId == nodeId &&
                            !neighbor.IsClosing &&
                            neighbor.State < PeerNeighborState.Disconnecting)
                        {
                            duplicateNeighbor = neighbor;
                            break;
                        }
                    }
                }
            }
            return duplicateNeighbor;
        }
        // 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<Referral> 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);
        }
        // Find a duplicate neighbor (excluding skipNeighbor) matching the address.
        public IPeerNeighbor FindDuplicateNeighbor(PeerNodeAddress address, IPeerNeighbor skipNeighbor)
        {
            PeerNeighbor duplicateNeighbor = null;

            lock (ThisLock)
            {
                foreach (PeerNeighbor neighbor in this.neighborList)
                {
                    // We restrict search to neighbors that are not yet closing.
                    if (neighbor != (PeerNeighbor)skipNeighbor &&
                        neighbor.ListenAddress != null &&
                        neighbor.ListenAddress.ServicePath == address.ServicePath &&
                        !neighbor.IsClosing &&
                        neighbor.State < PeerNeighborState.Disconnecting)
                    {
                        duplicateNeighbor = neighbor;
                        break;
                    }
                }
            }
            return duplicateNeighbor;
        }
 public void Connect(IPeerNeighbor neighbor, ConnectInfo connectInfo)
 {
     if (this.state == State.Opened)
     {
         PeerCloseReason none = PeerCloseReason.None;
         if ((neighbor.IsInitiator || !connectInfo.HasBody()) || ((neighbor.State != PeerNeighborState.Connecting) && (neighbor.State != PeerNeighborState.Closed)))
         {
             none = PeerCloseReason.InvalidNeighbor;
         }
         else if (this.RemoveTimer(neighbor))
         {
             if (this.neighborManager.ConnectedNeighborCount >= this.config.MaxNeighbors)
             {
                 none = PeerCloseReason.NodeBusy;
             }
             else if (!PeerValidateHelper.ValidNodeAddress(connectInfo.Address))
             {
                 none = PeerCloseReason.InvalidNeighbor;
             }
             else
             {
                 PeerCloseReason reason2;
                 IPeerNeighbor neighbor2;
                 string action = "http://schemas.microsoft.com/net/2006/05/peer/Refuse";
                 this.ValidateNeighbor(neighbor, connectInfo.NodeId, out neighbor2, out reason2, out action);
                 if (neighbor != neighbor2)
                 {
                     this.SendWelcome(neighbor);
                     try
                     {
                         neighbor.ListenAddress = connectInfo.Address;
                     }
                     catch (ObjectDisposedException exception)
                     {
                         DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Information);
                     }
                     if (!neighbor.TrySetState(PeerNeighborState.Connected) && (neighbor.State < PeerNeighborState.Disconnecting))
                     {
                         throw Fx.AssertAndThrow("Neighbor state expected to be >= Disconnecting; it is " + neighbor.State.ToString());
                     }
                     if (neighbor2 != null)
                     {
                         this.SendTerminatingMessage(neighbor2, action, reason2);
                         this.neighborManager.CloseNeighbor(neighbor2, reason2, PeerCloseInitiator.LocalNode);
                     }
                 }
                 else
                 {
                     none = reason2;
                 }
             }
         }
         if (none != PeerCloseReason.None)
         {
             this.SendTerminatingMessage(neighbor, "http://schemas.microsoft.com/net/2006/05/peer/Refuse", none);
             this.neighborManager.CloseNeighbor(neighbor, none, PeerCloseInitiator.LocalNode);
         }
     }
 }