void CloseCore(TimeSpan timeout, bool graceful) { PeerService lclService; PeerMaintainer lclMaintainer; PeerNeighborManager lclNeighborManager; PeerConnector lclConnector; PeerIPHelper lclIPHelper; PeerNodeConfig lclConfig; PeerFlooder lclFlooder; Exception exception = null; TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); if (DiagnosticUtility.ShouldTraceInformation) { TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.PeerNodeClosing, SR.GetString(SR.TraceCodePeerNodeClosing), this.traceRecord, this, null); } lock (ThisLock) { isOpen = false; lclMaintainer = maintainer; lclNeighborManager = neighborManager; lclConnector = connector; lclIPHelper = ipHelper; lclService = service; lclConfig = config; lclFlooder = flooder; } // only unregister if we are doing a g----ful shutdown try { if (graceful) { UnregisterAddress(timeout); } else { if (lclConfig != null) { ActionItem.Schedule(new Action<object>(UnregisterAddress), lclConfig.UnregisterTimeout); } } } catch (Exception e) { if (Fx.IsFatal(e)) throw; DiagnosticUtility.TraceHandledException(e, TraceEventType.Information); if (exception == null) exception = e; } try { if (lclConnector != null) lclConnector.Closing(); if (lclService != null) { try { lclService.Abort(); } catch (Exception e) { if (Fx.IsFatal(e)) throw; DiagnosticUtility.TraceHandledException(e, TraceEventType.Information); if (exception == null) exception = e; } } if (lclMaintainer != null) { try { lclMaintainer.Close(); } catch (Exception e) { if (Fx.IsFatal(e)) throw; DiagnosticUtility.TraceHandledException(e, TraceEventType.Information); if (exception == null) exception = e; } } if (lclIPHelper != null) { try { lclIPHelper.Close(); lclIPHelper.AddressChanged -= new EventHandler(stateManager.OnIPAddressesChanged); } catch (Exception e) { if (Fx.IsFatal(e)) throw; DiagnosticUtility.TraceHandledException(e, TraceEventType.Information); if (exception == null) exception = e; } } if (lclNeighborManager != null) { lclNeighborManager.NeighborConnected -= new EventHandler(OnNeighborConnected); lclNeighborManager.NeighborOpened -= new EventHandler(this.securityManager.OnNeighborOpened); this.securityManager.OnNeighborAuthenticated -= new EventHandler(this.OnNeighborAuthenticated); lclNeighborManager.Online -= new EventHandler(FireOnline); lclNeighborManager.Offline -= new EventHandler(FireOffline); try { lclNeighborManager.Shutdown(graceful, timeoutHelper.RemainingTime()); } catch (Exception e) { if (Fx.IsFatal(e)) throw; DiagnosticUtility.TraceHandledException(e, TraceEventType.Information); if (exception == null) exception = e; } // unregister for neighbor close events once shutdown has completed lclNeighborManager.NeighborClosed -= new EventHandler<PeerNeighborCloseEventArgs>(OnNeighborClosed); lclNeighborManager.NeighborClosing -= new EventHandler<PeerNeighborCloseEventArgs>(OnNeighborClosing); lclNeighborManager.Close(); } if (lclConnector != null) { try { lclConnector.Close(); } catch (Exception e) { if (Fx.IsFatal(e)) throw; DiagnosticUtility.TraceHandledException(e, TraceEventType.Information); if (exception == null) exception = e; } } if (lclFlooder != null) { try { lclFlooder.Close(); } catch (Exception e) { if (Fx.IsFatal(e)) throw; DiagnosticUtility.TraceHandledException(e, TraceEventType.Information); if (exception == null) exception = e; } } } catch (Exception e) { if (Fx.IsFatal(e)) throw; if (exception == null) exception = e; } // reset object for next call to open EventHandler abortedHandler = null; lock (ThisLock) { // clear out old components (so they can be garbage collected) neighborManager = null; connector = null; maintainer = null; flooder = null; ipHelper = null; service = null; // reset generated config config = null; meshId = null; abortedHandler = Aborted; } // Notify anyone who is interested that abort has occured if (!graceful && abortedHandler != null) { try { abortedHandler(this, EventArgs.Empty); } catch (Exception e) { if (Fx.IsFatal(e)) throw; DiagnosticUtility.TraceHandledException(e, TraceEventType.Information); if (exception == null) exception = e; } } if (DiagnosticUtility.ShouldTraceInformation) { TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.PeerNodeClosed, SR.GetString(SR.TraceCodePeerNodeClosed), this.traceRecord, this, null); } if (exception != null && graceful == true) // Swallows all non fatal exceptions during Abort { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exception); } }
// Opens the neighbor manager. When this method returns the neighbor manager is ready // to accept incoming neighbor requests and to establish outgoing neighbors. public void Open(Binding serviceBinding, PeerService service) { Fx.Assert(serviceBinding != null, "serviceBinding must not be null"); Fx.Assert(service != null, "service must not be null"); lock (ThisLock) { this.service = service; this.serviceBinding = serviceBinding; if (!(this.state == State.Created)) { throw Fx.AssertAndThrow("Neighbor Manager is expected to be in Created state"); } this.state = State.Opened; } }
// 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)); } }
// ClosedCallback is a delegate to determine if caller has closed. If so, we bail out of open operation public NeighborOpenAsyncResult(PeerNeighbor neighbor, PeerNodeAddress remoteAddress, Binding binding, PeerService service, ClosedCallback closedCallback, TimeSpan timeout, AsyncCallback callback, object state) : base(callback, state) { this.neighbor = neighbor; IAsyncResult result = null; try { result = neighbor.BeginOpen(remoteAddress, binding, service, closedCallback, timeout, Fx.ThunkCallback(new AsyncCallback(OnOpen)), null); if (result.CompletedSynchronously) { neighbor.EndOpen(result); } } catch (Exception e) { if (Fx.IsFatal(e)) throw; neighbor.TraceEventHelper(TraceEventType.Warning, TraceCode.PeerNeighborOpenFailed, SR.GetString(SR.TraceCodePeerNeighborOpenFailed)); throw; } // Indicate [....] completion to the caller if (result.CompletedSynchronously) base.Complete(true); }
public OpenAsyncResult(PeerNeighbor neighbor, PeerNodeAddress remoteAddress, Binding binding, PeerService service, ClosedCallback closedCallback, TimeSpan timeout, AsyncCallback callback, object state) : base(callback, state) { Fx.Assert(remoteAddress != null && remoteAddress.IPAddresses.Count > 0, "Non-empty IPAddress collection expected"); this.timeoutHelper = new TimeoutHelper(timeout); this.neighbor = neighbor; this.currentIndex = 0; this.completedSynchronously = true; // initially this.remoteAddress = remoteAddress; this.service = service; this.binding = binding; this.onOpen = Fx.ThunkCallback(new AsyncCallback(OnOpen)); this.closed = closedCallback; BeginOpen(); }
// Begin opening of a neighbor channel to 'to'. instanceContext is where the remote // endpoint should send messages to (it will be a reference to PeerNeighborManager). public IAsyncResult BeginOpen(PeerNodeAddress remoteAddress, Binding binding, PeerService service, ClosedCallback closedCallback, TimeSpan timeout, AsyncCallback callback, object asyncState) { this.initiator = true; this.listenAddress = remoteAddress; OpenAsyncResult result = new OpenAsyncResult(this, remoteAddress, binding, service, closedCallback, timeout, callback, state); return result; }
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 CloseCore(TimeSpan timeout, bool graceful) { PeerService service; PeerMaintainer maintainer; PeerNeighborManager neighborManager; PeerConnector connector; PeerIPHelper ipHelper; PeerNodeConfig config; PeerFlooder flooder; Exception exception = null; TimeoutHelper helper2 = new TimeoutHelper(timeout); if (System.ServiceModel.DiagnosticUtility.ShouldTraceInformation) { TraceUtility.TraceEvent(TraceEventType.Information, 0x40043, System.ServiceModel.SR.GetString("TraceCodePeerNodeClosing"), this.traceRecord, this, null); } lock (this.ThisLock) { this.isOpen = false; maintainer = this.maintainer; neighborManager = this.neighborManager; connector = this.connector; ipHelper = this.ipHelper; service = this.service; config = this.config; flooder = this.flooder; } try { if (graceful) { this.UnregisterAddress(timeout); } else if (config != null) { ActionItem.Schedule(new Action<object>(this.UnregisterAddress), config.UnregisterTimeout); } } catch (Exception exception2) { if (Fx.IsFatal(exception2)) { throw; } System.ServiceModel.DiagnosticUtility.ExceptionUtility.TraceHandledException(exception2, TraceEventType.Information); if (exception == null) { exception = exception2; } } try { if (connector != null) { connector.Closing(); } if (service != null) { try { service.Abort(); } catch (Exception exception3) { if (Fx.IsFatal(exception3)) { throw; } System.ServiceModel.DiagnosticUtility.ExceptionUtility.TraceHandledException(exception3, TraceEventType.Information); if (exception == null) { exception = exception3; } } } if (maintainer != null) { try { maintainer.Close(); } catch (Exception exception4) { if (Fx.IsFatal(exception4)) { throw; } System.ServiceModel.DiagnosticUtility.ExceptionUtility.TraceHandledException(exception4, TraceEventType.Information); if (exception == null) { exception = exception4; } } } if (ipHelper != null) { try { ipHelper.Close(); ipHelper.AddressChanged -= new EventHandler(this.stateManager.OnIPAddressesChanged); } catch (Exception exception5) { if (Fx.IsFatal(exception5)) { throw; } System.ServiceModel.DiagnosticUtility.ExceptionUtility.TraceHandledException(exception5, TraceEventType.Information); if (exception == null) { exception = exception5; } } } if (neighborManager != null) { neighborManager.NeighborConnected -= new EventHandler(this.OnNeighborConnected); neighborManager.NeighborOpened -= new EventHandler(this.securityManager.OnNeighborOpened); this.securityManager.OnNeighborAuthenticated = (EventHandler) Delegate.Remove(this.securityManager.OnNeighborAuthenticated, new EventHandler(this.OnNeighborAuthenticated)); neighborManager.Online -= new EventHandler(this.FireOnline); neighborManager.Offline -= new EventHandler(this.FireOffline); try { neighborManager.Shutdown(graceful, helper2.RemainingTime()); } catch (Exception exception6) { if (Fx.IsFatal(exception6)) { throw; } System.ServiceModel.DiagnosticUtility.ExceptionUtility.TraceHandledException(exception6, TraceEventType.Information); if (exception == null) { exception = exception6; } } neighborManager.NeighborClosed -= new EventHandler<PeerNeighborCloseEventArgs>(this.OnNeighborClosed); neighborManager.NeighborClosing -= new EventHandler<PeerNeighborCloseEventArgs>(this.OnNeighborClosing); neighborManager.Close(); } if (connector != null) { try { connector.Close(); } catch (Exception exception7) { if (Fx.IsFatal(exception7)) { throw; } System.ServiceModel.DiagnosticUtility.ExceptionUtility.TraceHandledException(exception7, TraceEventType.Information); if (exception == null) { exception = exception7; } } } if (flooder != null) { try { flooder.Close(); } catch (Exception exception8) { if (Fx.IsFatal(exception8)) { throw; } System.ServiceModel.DiagnosticUtility.ExceptionUtility.TraceHandledException(exception8, TraceEventType.Information); if (exception == null) { exception = exception8; } } } } catch (Exception exception9) { if (Fx.IsFatal(exception9)) { throw; } if (exception == null) { exception = exception9; } } EventHandler aborted = null; lock (this.ThisLock) { this.neighborManager = null; this.connector = null; this.maintainer = null; this.flooder = null; this.ipHelper = null; this.service = null; this.config = null; this.meshId = null; aborted = this.Aborted; } if (!graceful && (aborted != null)) { try { aborted(this, EventArgs.Empty); } catch (Exception exception10) { if (Fx.IsFatal(exception10)) { throw; } System.ServiceModel.DiagnosticUtility.ExceptionUtility.TraceHandledException(exception10, TraceEventType.Information); if (exception == null) { exception = exception10; } } } if (System.ServiceModel.DiagnosticUtility.ShouldTraceInformation) { TraceUtility.TraceEvent(TraceEventType.Information, 0x40044, System.ServiceModel.SR.GetString("TraceCodePeerNodeClosed"), this.traceRecord, this, null); } if ((exception != null) && graceful) { throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperError(exception); } }