public PeerNeighborManager(PeerIPHelper ipHelper, PeerNodeConfig config, IPeerNodeMessageHandling messageHandler) { Fx.Assert(ipHelper != null, "Non-null ipHelper is expected"); Fx.Assert(config != null, "Non-null Config is expected"); this.neighborList = new List<PeerNeighbor>(); this.connectedNeighborList = new List<IPeerNeighbor>(); this.ipHelper = ipHelper; this.messageHandler = messageHandler; this.config = config; this.thisLock = new object(); this.traceRecord = new PeerNodeTraceRecord(config.NodeId); this.state = State.Created; }
// Queued callback to actually process the address change // The design is such that any address change notifications are queued just like Open/Close operations. // So, we need not worry about address changes racing with other address changes or Open/Close operations. // Abort can happen at any time. However, Abort skips unregistering addresses, so this method doesn't have // to worry about undoing its work if Abort happens. void OnIPAddressChange() { string lclMeshId = null; PeerNodeAddress nodeAddress = null; object lclResolverRegistrationId = null; bool lclRegistered = false; PeerIPHelper lclIPHelper = ipHelper; PeerNodeConfig lclconfig = config; bool processChange = false; TimeoutHelper timeoutHelper = new TimeoutHelper(ServiceDefaults.SendTimeout); // Determine if IP addresses have really changed before notifying the resolver // since it is possible that another change notification ahead of this one in the queue // may have already completed notifying the resolver of the most current change. if (lclIPHelper != null && config != null) { nodeAddress = lclconfig.GetListenAddress(false); processChange = lclIPHelper.AddressesChanged(nodeAddress.IPAddresses); if (processChange) { // Build the nodeAddress with the updated IP addresses nodeAddress = new PeerNodeAddress( nodeAddress.EndpointAddress, lclIPHelper.GetLocalAddresses()); } } lock (ThisLock) { // Skip processing if the node isn't open anymore or if addresses haven't changed if (processChange && isOpen) { lclMeshId = meshId; lclResolverRegistrationId = resolverRegistrationId; lclRegistered = registered; config.SetListenAddress(nodeAddress); completeTraceRecord = new PeerNodeTraceRecord(config.NodeId, meshId, nodeAddress); } else { return; } } //#57954 - log and ---- non-critical exceptions during network change event notifications try { // Do we have any addresses? If so, update or re-register. Otherwise, unregister. if (nodeAddress.IPAddresses.Count > 0) { if (lclRegistered) { resolver.Update(lclResolverRegistrationId, nodeAddress, timeoutHelper.RemainingTime()); } else { RegisterAddress(lclMeshId, nodeAddress, timeoutHelper.RemainingTime()); } } else { UnregisterAddress(timeoutHelper.RemainingTime()); } } catch (Exception e) { if (Fx.IsFatal(e)) throw; DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning); } PingConnections(); if (DiagnosticUtility.ShouldTraceInformation) { TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.PeerNodeAddressChanged, SR.GetString(SR.TraceCodePeerNodeAddressChanged), this.completeTraceRecord, this, null); } }
// the core functionality of open (all but waiting for a connection) void OpenCore(TimeSpan timeout) { TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); PeerMaintainer lclMaintainer; PeerNodeConfig lclConfig; string lclMeshId; lock (ThisLock) { if (ListenUri == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ListenUriNotSet, this.GetType()))); } // extract mesh id from listen uri meshId = ListenUri.Host; // generate the node id byte[] bytes = new byte[sizeof(ulong)]; ulong nodeId = 0; do { System.ServiceModel.Security.CryptoHelper.FillRandomBytes(bytes); for (int i = 0; i < sizeof(ulong); i++) nodeId |= ((ulong)bytes[i]) << i * 8; } while (nodeId == PeerTransportConstants.InvalidNodeId); // now that the node id has been generated, create the trace record that describes this traceRecord = new PeerNodeTraceRecord(nodeId, meshId); if (DiagnosticUtility.ShouldTraceInformation) { TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.PeerNodeOpening, SR.GetString(SR.TraceCodePeerNodeOpening), this.traceRecord, this, null); } // create the node configuration config = new PeerNodeConfig(meshId, nodeId, resolver, messagePropagationFilter, encoder, ListenUri, listenIPAddress, port, maxReceivedMessageSize, minNeighbors, idealNeighbors, maxNeighbors, maxReferrals, connectTimeout, maintainerInterval, securityManager, this.readerQuotas, this.maxBufferPoolSize, this.MaxSendQueue, this.MaxReceiveQueue); // create components if (listenIPAddress != null) ipHelper = new PeerIPHelper(listenIPAddress); else ipHelper = new PeerIPHelper(); bufferManager = BufferManager.CreateBufferManager(64 * config.MaxReceivedMessageSize, (int)config.MaxReceivedMessageSize); neighborManager = new PeerNeighborManager(ipHelper, config, this); flooder = PeerFlooder.CreateFlooder(config, neighborManager, this); maintainer = new PeerMaintainer(config, neighborManager, flooder); connector = new PeerConnector(config, neighborManager, maintainer); Dictionary<Type, object> services = serviceHandlers; if (services == null) { services = new Dictionary<Type, object>(); services.Add(typeof(IPeerConnectorContract), connector); services.Add(typeof(IPeerFlooderContract<Message, UtilityInfo>), flooder); } service = new PeerService(this.config, neighborManager.ProcessIncomingChannel, neighborManager.GetNeighborFromProxy, services, this); this.securityManager.MeshId = this.meshId; service.Open(timeoutHelper.RemainingTime()); // register for events neighborManager.NeighborClosed += new EventHandler<PeerNeighborCloseEventArgs>(OnNeighborClosed); neighborManager.NeighborClosing += new EventHandler<PeerNeighborCloseEventArgs>(OnNeighborClosing); neighborManager.NeighborConnected += new EventHandler(OnNeighborConnected); neighborManager.NeighborOpened += new EventHandler(this.SecurityManager.OnNeighborOpened); this.securityManager.OnNeighborAuthenticated += new EventHandler(this.OnNeighborAuthenticated); neighborManager.Online += new EventHandler(FireOnline); neighborManager.Offline += new EventHandler(FireOffline); ipHelper.AddressChanged += new EventHandler(stateManager.OnIPAddressesChanged); // open components ipHelper.Open(); // Set the listen address before opening any more components PeerNodeAddress nodeAddress = new PeerNodeAddress(service.GetListenAddress(), ipHelper.GetLocalAddresses()); config.SetListenAddress(nodeAddress); neighborManager.Open(service.Binding, service); connector.Open(); maintainer.Open(); flooder.Open(); isOpen = true; completeTraceRecord = new PeerNodeTraceRecord(nodeId, meshId, nodeAddress); // Set these locals inside the lock (Abort may occur whilst Opening) lclMaintainer = maintainer; lclMeshId = meshId; lclConfig = config; openException = null; } // retrieve listen addresses and register with the resolver if (isOpen) { // attempt to connect to the mesh lclMaintainer.ScheduleConnect(new PeerMaintainer.ConnectCallback(OnConnectionAttemptCompleted)); } }
private void OpenCore(TimeSpan timeout) { PeerMaintainer maintainer; TimeoutHelper helper = new TimeoutHelper(timeout); lock (this.ThisLock) { if (this.ListenUri == null) { throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(System.ServiceModel.SR.GetString("ListenUriNotSet", new object[] { base.GetType() }))); } this.meshId = this.ListenUri.Host; byte[] buffer = new byte[8]; ulong id = 0L; do { CryptoHelper.FillRandomBytes(buffer); for (int i = 0; i < 8; i++) { id |= buffer[i] << (i * 8); } } while (id == 0L); this.traceRecord = new PeerNodeTraceRecord(id, this.meshId); if (System.ServiceModel.DiagnosticUtility.ShouldTraceInformation) { TraceUtility.TraceEvent(TraceEventType.Information, 0x40040, System.ServiceModel.SR.GetString("TraceCodePeerNodeOpening"), this.traceRecord, this, null); } this.config = new PeerNodeConfig(this.meshId, id, this.resolver, this.messagePropagationFilter, this.encoder, this.ListenUri, this.listenIPAddress, this.port, this.maxReceivedMessageSize, this.minNeighbors, this.idealNeighbors, this.maxNeighbors, this.maxReferrals, this.connectTimeout, this.maintainerInterval, this.securityManager, this.readerQuotas, this.maxBufferPoolSize, this.MaxSendQueue, this.MaxReceiveQueue); if (this.listenIPAddress != null) { this.ipHelper = new PeerIPHelper(this.listenIPAddress); } else { this.ipHelper = new PeerIPHelper(); } this.bufferManager = BufferManager.CreateBufferManager(0x40L * this.config.MaxReceivedMessageSize, (int) this.config.MaxReceivedMessageSize); this.neighborManager = new PeerNeighborManager(this.ipHelper, this.config, this); this.flooder = PeerFlooder.CreateFlooder(this.config, this.neighborManager, this); this.maintainer = new PeerMaintainer(this.config, this.neighborManager, this.flooder); this.connector = new PeerConnector(this.config, this.neighborManager, this.maintainer); Dictionary<System.Type, object> serviceHandlers = this.serviceHandlers; if (serviceHandlers == null) { serviceHandlers = new Dictionary<System.Type, object>(); serviceHandlers.Add(typeof(IPeerConnectorContract), this.connector); serviceHandlers.Add(typeof(IPeerFlooderContract<Message, UtilityInfo>), this.flooder); } this.service = new PeerService(this.config, new PeerService.ChannelCallback(this.neighborManager.ProcessIncomingChannel), new PeerService.GetNeighborCallback(this.neighborManager.GetNeighborFromProxy), serviceHandlers, this); this.securityManager.MeshId = this.meshId; this.service.Open(helper.RemainingTime()); this.neighborManager.NeighborClosed += new EventHandler<PeerNeighborCloseEventArgs>(this.OnNeighborClosed); this.neighborManager.NeighborClosing += new EventHandler<PeerNeighborCloseEventArgs>(this.OnNeighborClosing); this.neighborManager.NeighborConnected += new EventHandler(this.OnNeighborConnected); this.neighborManager.NeighborOpened += new EventHandler(this.SecurityManager.OnNeighborOpened); this.securityManager.OnNeighborAuthenticated = (EventHandler) Delegate.Combine(this.securityManager.OnNeighborAuthenticated, new EventHandler(this.OnNeighborAuthenticated)); this.neighborManager.Online += new EventHandler(this.FireOnline); this.neighborManager.Offline += new EventHandler(this.FireOffline); this.ipHelper.AddressChanged += new EventHandler(this.stateManager.OnIPAddressesChanged); this.ipHelper.Open(); PeerNodeAddress address = new PeerNodeAddress(this.service.GetListenAddress(), this.ipHelper.GetLocalAddresses()); this.config.SetListenAddress(address); this.neighborManager.Open(this.service.Binding, this.service); this.connector.Open(); this.maintainer.Open(); this.flooder.Open(); this.isOpen = true; this.completeTraceRecord = new PeerNodeTraceRecord(id, this.meshId, address); maintainer = this.maintainer; this.openException = null; } if (this.isOpen) { maintainer.ScheduleConnect(new PeerMaintainerBase<ConnectAlgorithms>.ConnectCallback(this.OnConnectionAttemptCompleted)); } }
private void OnIPAddressChange() { string lclMeshId = null; PeerNodeAddress listenAddress = null; object registrationId = null; bool registered = false; PeerIPHelper ipHelper = this.ipHelper; PeerNodeConfig config = this.config; bool flag2 = false; TimeoutHelper helper2 = new TimeoutHelper(ServiceDefaults.SendTimeout); if ((ipHelper != null) && (this.config != null)) { listenAddress = config.GetListenAddress(false); flag2 = ipHelper.AddressesChanged(listenAddress.IPAddresses); if (flag2) { listenAddress = new PeerNodeAddress(listenAddress.EndpointAddress, ipHelper.GetLocalAddresses()); } } lock (this.ThisLock) { if (flag2 && this.isOpen) { lclMeshId = this.meshId; registrationId = this.resolverRegistrationId; registered = this.registered; this.config.SetListenAddress(listenAddress); this.completeTraceRecord = new PeerNodeTraceRecord(this.config.NodeId, this.meshId, listenAddress); } else { return; } } try { if (listenAddress.IPAddresses.Count > 0) { if (registered) { this.resolver.Update(registrationId, listenAddress, helper2.RemainingTime()); } else { this.RegisterAddress(lclMeshId, listenAddress, helper2.RemainingTime()); } } else { this.UnregisterAddress(helper2.RemainingTime()); } } catch (Exception exception) { if (Fx.IsFatal(exception)) { throw; } System.ServiceModel.DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Warning); } this.PingConnections(); if (System.ServiceModel.DiagnosticUtility.ShouldTraceInformation) { TraceUtility.TraceEvent(TraceEventType.Information, 0x4003f, System.ServiceModel.SR.GetString("TraceCodePeerNodeAddressChanged"), this.completeTraceRecord, this, null); } }