public static PeerFlooder CreateFlooder(PeerNodeConfig config, PeerNeighborManager neighborManager, IPeerNodeMessageHandling messageHandler) { PeerFlooder flooder = new PeerFlooder(config, neighborManager); flooder.messageHandler = messageHandler; return(flooder); }
public PeerMaintainerBase(PeerNodeConfig config, PeerNeighborManager neighborManager, PeerFlooder flooder) { this.neighborManager = neighborManager; this.flooder = flooder; this.config = config; this.thisLock = new object(); this.referralCache = new Dictionary <EndpointAddress, Referral>(); this.maintainerTimer = new IOThreadTimer(new Action <object>(this.OnMaintainerTimer), this, false); }
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); } }
// 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)); } }
public PeerMaintainer(PeerNodeConfig config, PeerNeighborManager neighborManager, PeerFlooder flooder) : base(config, neighborManager, flooder) { }
//this is the callback routine for async completion on channel BeginSend() operations. //if we are done, simply return. This can happen if user called sync EndX. //if the flooder is still processing BeginSend(), then we probably cant complete. In this case, add the result to pending and return //main thread will flush the pending completions in MarkEnd(). //otherwise, call EndX on the result and remove it from results. //if this is the last invoke, signal user using base.Complete AND isCompleted=true internal void OnSendComplete(IAsyncResult result) { bool callComplete = false; IPeerNeighbor neighbor = null; bool fatal = false; if (isCompleted) { return; } Message message = (Message)result.AsyncState; //wait until flooder had a chance to call all outgoing channels and give us Async results. lock (ThisLock) { if (isCompleted) { return; } if (!this.results.TryGetValue(result, out neighbor)) { if (!doneAdding) { this.pending.Add(result); } else { throw Fx.AssertAndThrow("IAsyncResult is un-accounted for."); } return; } this.results.Remove(result); try { //try doing this only if the async result is marked !CompletedSynchronously. if (!result.CompletedSynchronously) { neighbor.EndSend(result); offNode = true; UtilityExtension.OnEndSend(neighbor, this); } } catch (Exception e) { if (Fx.IsFatal(e)) { fatal = true; throw; } Exception temp = PeerFlooder.CloseNeighborIfKnownException(pnm, e, neighbor); //we want to return the very first exception to the user. if (temp != null && this.doneAdding && !this.shouldCallComplete) { throw; } if (this.exception == null) { this.exception = temp; } DiagnosticUtility.TraceHandledException(e, TraceEventType.Information); } finally { if (message != null && !result.CompletedSynchronously && !fatal) { message.Close(); } } //dont want to call Complete from the lock. //we just decide if this thread should call complete and call outside the lock. if (this.results.Count == 0 && this.doneAdding && this.shouldCallComplete) { this.isCompleted = true; callComplete = true; } } //if we are done with callbacks and beginx calls, if (callComplete && this.shouldCallComplete) { CompleteOp(false); } }
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); } }
public IAsyncResult BeginSend(object registrant, Message message, Uri via, ITransportFactorySettings settings, TimeSpan timeout, AsyncCallback callback, object state, SecurityProtocol securityProtocol) { TimeoutHelper helper = new TimeoutHelper(timeout); MessageBuffer encodedMessage = null; Message message2 = null; ulong maxValue = ulong.MaxValue; PeerMessagePropagation localAndRemote = PeerMessagePropagation.LocalAndRemote; int messageSize = -1; SendAsyncResult result = new SendAsyncResult(callback, state); AsyncCallback callback2 = Fx.ThunkCallback(new AsyncCallback(result.OnFloodComplete)); try { PeerFlooder flooder; byte[] primarySignatureValue; lock (this.ThisLock) { this.ThrowIfNotOpen(); flooder = this.flooder; } int maxBufferSize = (int) Math.Min(this.maxReceivedMessageSize, settings.MaxReceivedMessageSize); Guid guid = this.ProcessOutgoingMessage(message, via); this.SecureOutgoingMessage(ref message, via, timeout, securityProtocol); if (message is SecurityAppliedMessage) { ArraySegment<byte> buffer = this.encoder.WriteMessage(message, 0x7fffffff, this.bufferManager); message2 = this.encoder.ReadMessage(buffer, this.bufferManager); primarySignatureValue = (message as SecurityAppliedMessage).PrimarySignatureValue; messageSize = buffer.Count; } else { message2 = message; primarySignatureValue = guid.ToByteArray(); } encodedMessage = message2.CreateBufferedCopy(maxBufferSize); string contentType = settings.MessageEncoderFactory.Encoder.ContentType; if (this.messagePropagationFilter != null) { using (Message message3 = encodedMessage.CreateMessage()) { localAndRemote = ((IPeerNodeMessageHandling) this).DetermineMessagePropagation(message3, PeerMessageOrigination.Local); } } if (((localAndRemote & PeerMessagePropagation.Remote) != PeerMessagePropagation.None) && (maxValue == 0L)) { localAndRemote &= ~PeerMessagePropagation.Remote; } IAsyncResult result2 = null; if ((localAndRemote & PeerMessagePropagation.Remote) != PeerMessagePropagation.None) { result2 = flooder.BeginFloodEncodedMessage(primarySignatureValue, encodedMessage, helper.RemainingTime(), callback2, null); if (System.ServiceModel.DiagnosticUtility.ShouldTraceVerbose) { TraceUtility.TraceEvent(TraceEventType.Verbose, 0x4003e, System.ServiceModel.SR.GetString("TraceCodePeerChannelMessageSent"), this, message); } } else { result2 = new CompletedAsyncResult(callback2, null); } if ((localAndRemote & PeerMessagePropagation.Local) != PeerMessagePropagation.None) { using (Message message4 = encodedMessage.CreateMessage()) { int i = message4.Headers.FindHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"); if (i >= 0) { message4.Headers.AddUnderstood(i); } using (MessageBuffer buffer3 = message4.CreateBufferedCopy(maxBufferSize)) { this.DeliverMessageToClientChannels(registrant, buffer3, via, message.Headers.To, contentType, messageSize, -1, null); } } } result.OnLocalDispatchComplete(result); } finally { message.Close(); if (message2 != null) { message2.Close(); } if (encodedMessage != null) { encodedMessage.Close(); } } return result; }