/// <summary> /// Registers the broadcast sender that sends a message to several receivers. /// Returns Guid (it's like URI for an MBR object) assigned for this sender that can be used /// to delete this broadcast sender later. /// </summary> /// <param name="generalBroadcastSender">The broadcast sender which sends a message via "true" multicast channel.</param> public string Add(GeneralBroadcastSender generalBroadcastSender) { // just add it as it would be the usual receiver ReceiverInfo receiverInfo = new ReceiverInfo(); receiverInfo.GeneralBroadcastSender = generalBroadcastSender; receiverInfo.Local = false; string uri = Guid.NewGuid().ToString("N") + "/" + generalBroadcastSender.Court; receiverInfo.MbrUri = uri; // register it using (WriterAutoLocker writer = new WriterAutoLocker(this._readerWriterLock)) { this._cachedReceiversInfoArray = null; this._receivers[uri] = receiverInfo; } // LOG: BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter; if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0) { binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "Dispatcher.Add", LogMessageType.BroadcastRecipientAdded, null, null, null, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, false, this, null, true, receiverInfo, generalBroadcastSender.Court, generalBroadcastSender.ITransportContext.HostIdentifier, "The \"true\" multicast sender is added."); } return(uri); }
/// <summary> /// Fires the BroadcastReceiverHasBeenExcluded event and detach the sponsor from the specified receiver. /// </summary> /// <param name="state">The receiver being excluded.</param> public void DeleteSponsorFromTheObjectAndFireEvent(object state) { ReceiverInfo receiverInfo = (ReceiverInfo)state; MarshalByRefObject marshalByRefObject = (MarshalByRefObject)receiverInfo.MbrObject; // fire the event try { if (this.BroadcastReceiverHasBeenExcluded != null) { this.BroadcastReceiverHasBeenExcluded(marshalByRefObject, receiverInfo); } } catch { // ignore all exceptions } // detach sponsor try { ILease lease = (ILease)RemotingServices.GetLifetimeService(marshalByRefObject); if (lease != null) { lease.Unregister(this.GlobalSponsor); } } catch { // ignore all exceptions } }
/// <summary> /// Returns the receiver associated with the specified uri. /// </summary> /// <param name="uri">The uri associated with the receiver.</param> /// <returns>The receiver associated with the specified uri.</returns> public MarshalByRefObject FindObjectByUri(string uri) { using (ReaderAutoLocker reader = new ReaderAutoLocker(this._readerWriterLock)) { ReceiverInfo receiverInfo = this._receivers[uri] as ReceiverInfo; if (receiverInfo == null) { return(null); } return(receiverInfo.MbrObject); } }
/// <summary> /// Processes the received response. /// </summary> /// <param name="message">The response.</param> public void ProcessRespose(Message message) { // it's a response via the usual channel that the remote host successfully received a message via broadcast channel // message.Sender - remote MBR uri string objectUri = message.DestinationMarshalByRef as string; if (objectUri == null) { return; } lock (this._dispatcher) { ReceiverInfo receiverInfo = this._dispatcher.GetReceiverInfo(objectUri); if (receiverInfo == null) { return; } receiverInfo.NeedsBroadcastSimulation = false; receiverInfo.NumberOfMulticastFails = 0; } // if time-out has expired if (this.AllMessagesReceived.WaitOne(0, false)) { return; } try { BinaryFormatter binaryFormatter = new BinaryFormatter(); object reply = binaryFormatter.Deserialize(message.Stream); this.ParseResult(objectUri, reply as IMethodReturnMessage, reply as Exception); } catch (Exception ex) { this.ParseResult(objectUri, null, ex); } }
/// <summary> /// Removes the receiver or the broadcast sender associated with the specified uri. /// Returns false if there is no such receiver found in the list of receivers. /// </summary> /// <param name="uri">The uri of the receiver.</param> public bool Remove(string uri) { if (uri == null || uri.Length <= 0) { return(false); } using (WriterAutoLocker writer = new WriterAutoLocker(this._readerWriterLock)) { // check if it is in the list if (!this._receivers.ContainsKey(uri)) { return(false); } this._cachedReceiversInfoArray = null; ReceiverInfo receiverInfo = (ReceiverInfo)this._receivers[uri]; this._receivers.Remove(uri); // LOG: BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter; if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0) { binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "Dispatcher.Remove", LogMessageType.BroadcastRecipientRemoved, null, null, receiverInfo.DbgRemoteHost, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, false, this, null, true, receiverInfo, uri, null, "The broadcast recipient or \"true\" broadcast sender is removed from the list of recipients."); } // Sponsor is being deleted in another thread; otherwise client disconnection // will cause dispatcher to be freezed for lengthy time out GenuineThreadPool.QueueUserWorkItem(new WaitCallback(this.DeleteSponsorFromTheObjectAndFireEvent), receiverInfo, false); } return(true); }
/// <summary> /// Looks for a failed broadcast receivers and invoke them again. /// </summary> public void SendMessageToFailedReceiversDirectly() { if (this._secondStagePerformed) { return; } this._secondStagePerformed = true; BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter; // the second stage of the broadcasting using (ReaderAutoLocker reader = new ReaderAutoLocker(this._dispatcher._readerWriterLock)) { // to prevent firing resultCollector.AllMessagesReceived event this.UnrepliedReceivers[_uniqueReceiverName] = null; lock (this) { foreach (DictionaryEntry entry in this.Failed) { OperationException operationException = entry.Value as OperationException; if (operationException != null && operationException.OperationErrorMessage != null && operationException.OperationErrorMessage.ErrorIdentifier == "GenuineChannels.Exception.Broadcast.RemoteEndPointDidNotReplyForTimeOut") { string uri = (string)entry.Key; ReceiverInfo receiverInfo = this._dispatcher.GetReceiverInfo(uri); // whether this receiver is expected to receive message via broadcast channel if (receiverInfo == null || receiverInfo.NeedsBroadcastSimulation) { continue; } // switch it back to simulation mode if the limit is exceeded lock (receiverInfo) { receiverInfo.NumberOfMulticastFails++; if (this._dispatcher.MaximumNumberOfConsecutiveFailsToEnableSimulationMode != 0 && receiverInfo.NumberOfMulticastFails >= this._dispatcher.MaximumNumberOfConsecutiveFailsToEnableSimulationMode) { // force simulation receiverInfo.NeedsBroadcastSimulation = true; receiverInfo.NumberOfMulticastFails = 0; } } // each time a new stream is created because sinks change stream position concurrently Stream messageToBeSent = (Stream)this._messageStream.Clone(); TransportHeaders transportHeaders = new TransportHeaders(); // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0) { string methodName = BinaryLogWriter.ParseInvocationMethod(this._iMessage.Properties["__MethodName"] as string, this._iMessage.Properties["__TypeName"] as string); string invocationTarget = receiverInfo.MbrUri; binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "ResultCollector.SendMessageToFailedReceiversDirectly", LogMessageType.BroadcastRecipientInvokedAfterTimeout, null, null, receiverInfo.DbgRemoteHost, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, false, this._dispatcher, this, false, receiverInfo, invocationTarget, methodName, "The broadcast invocation is being directed to the recipient, which did not respond during the first stage."); } // set destination MBR this._iMessage.Properties["__Uri"] = receiverInfo.MbrUri; transportHeaders[Message.TransportHeadersBroadcastObjRefOrCourt] = receiverInfo.SerializedObjRef; ClientChannelSinkStack clientChannelSinkStack = new ClientChannelSinkStack(this); clientChannelSinkStack.Push(this, null); receiverInfo.IClientChannelSink.AsyncProcessRequest(clientChannelSinkStack, this._iMessage, transportHeaders, messageToBeSent); } } } this.UnrepliedReceivers.Remove(_uniqueReceiverName); if (this.UnrepliedReceivers.Count <= 0) { this.AllMessagesReceived.Set(); } } }
/// <summary> /// Sends the invocation to all registered receivers. /// </summary> /// <param name="msg">The message to be sent.</param> public void PerformBroadcasting(IMessage msg) { BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter; string methodName = null; string invocationTarget = null; // the first stage of the broadcasting try { ArrayList listOfExcludedReceivers = new ArrayList(); this._iMessage = msg; methodName = BinaryLogWriter.ParseInvocationMethod(msg.Properties["__MethodName"] as string, msg.Properties["__TypeName"] as string); BinaryFormatter formatterForLocalRecipients = null; // serialize the message BinaryFormatter binaryFormatter = new BinaryFormatter(new RemotingSurrogateSelector(), new StreamingContext(StreamingContextStates.Other)); this._messageStream = new GenuineChunkedStream(false); binaryFormatter.Serialize(this._messageStream, msg); // to trace the message if it could reach the server via several channels string callGuidSubstring = null; if (this._dispatcher.IgnoreRecurrentCalls) { callGuidSubstring = Guid.NewGuid().ToString("N"); } // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0) { binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "ResultCollector.PerformBroadcasting", LogMessageType.BroadcastInvocationInitiated, null, null, null, binaryLogWriter[LogCategory.BroadcastEngine] > 1 ? (Stream)this._messageStream.Clone() : null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, true, this._dispatcher, this, false, null, methodName, null, "The broadcast invocation is initiated."); } // to prevent firing resultCollector.AllMessagesReceived event this.UnrepliedReceivers[_uniqueReceiverName] = null; object[] listOfReceiverInfo; this._dispatcher.GetListOfReceivers(out listOfReceiverInfo, msg, this); // through all recipients for (int i = 0; i < listOfReceiverInfo.Length; i++) { ReceiverInfo receiverInfo = listOfReceiverInfo[i] as ReceiverInfo; if (receiverInfo == null) { continue; } string mbrUri = (string)receiverInfo.MbrUri; invocationTarget = mbrUri; try { lock (receiverInfo) { if (this._dispatcher.MaximumNumberOfConsecutiveFailsToExcludeReceiverAutomatically != 0 && receiverInfo.NumberOfFails >= this._dispatcher.MaximumNumberOfConsecutiveFailsToExcludeReceiverAutomatically) { // put it to the list containing receivers being excluded listOfExcludedReceivers.Add(mbrUri); continue; } } // think that it'll fail if (!receiverInfo.Local && receiverInfo.GeneralBroadcastSender == null) { lock (this) { this.Failed[mbrUri] = GenuineExceptions.Get_Broadcast_RemoteEndPointDidNotReplyForTimeOut(); } } if (receiverInfo.Local) { // call to local appdomain // ignore recurrent calls if (this._dispatcher.IgnoreRecurrentCalls && UniqueCallTracer.Instance.WasGuidRegistered(mbrUri + callGuidSubstring)) { continue; } // we'll wait for the answer from this receiver this.UnrepliedReceivers[mbrUri] = null; // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0) { binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "ResultCollector.PerformBroadcasting", LogMessageType.BroadcastRecipientInvoked, null, null, null, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, false, this._dispatcher, this, false, receiverInfo, null, null, "The local receiver is invoked via LocalPerformer."); } if (formatterForLocalRecipients == null) { formatterForLocalRecipients = new BinaryFormatter(); } // fixed in 2.5.9.6 IMessage iLocalMessage = (IMessage)formatterForLocalRecipients.Deserialize((Stream)this._messageStream.Clone()); // queue task to run the call locally //IMessage iLocalMessage = (IMessage) binaryFormatter.Deserialize( (Stream) this._messageStream.Clone() ); LocalPerformer localPerformer = new LocalPerformer(iLocalMessage, this, receiverInfo.MbrObject); GenuineThreadPool.QueueUserWorkItem(new WaitCallback(localPerformer.Call), null, false); } else if (receiverInfo.GeneralBroadcastSender != null) { // call via true multicast channel Stream messageToBeSent = (Stream)this._messageStream.Clone(); // send via real broadcast sender to the specific court msg.Properties["__Uri"] = string.Empty; Message message = Message.CreateOutcomingMessage(receiverInfo.GeneralBroadcastSender.ITransportContext, msg, new TransportHeaders(), messageToBeSent, false); message.DestinationMarshalByRef = receiverInfo.SerializedObjRef; message.GenuineMessageType = GenuineMessageType.TrueBroadcast; // to ignore recurrent calls on the remote side if (this._dispatcher.IgnoreRecurrentCalls) { message.ITransportHeaders[Message.TransportHeadersBroadcastSendGuid] = callGuidSubstring; } // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0) { message.ITransportHeaders[Message.TransportHeadersInvocationTarget] = invocationTarget; message.ITransportHeaders[Message.TransportHeadersMethodName] = methodName; binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "ResultCollector.PerformBroadcasting", LogMessageType.BroadcastRecipientInvoked, null, null, null, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, false, this._dispatcher, this, false, receiverInfo, null, null, "Mulsticast sender is being invoked."); } // register to catch all the answers receiverInfo.GeneralBroadcastSender.ITransportContext.IIncomingStreamHandler.RegisterResponseProcessor(message.MessageId, this); // and send it receiverInfo.GeneralBroadcastSender.SendMessage(message, this); } else { // send the invocation through the usual channel // we'll wait for the reply this.UnrepliedReceivers[mbrUri] = null; // send only if this receiver is not expected to receive message via broadcast channel if (receiverInfo.NeedsBroadcastSimulation) { // each time a new stream is created because sinks change stream position concurrently Stream messageToBeSent = (Stream)this._messageStream.Clone(); TransportHeaders transportHeaders = new TransportHeaders(); // to ignore recurrent calls on the remote side if (this._dispatcher.IgnoreRecurrentCalls) { transportHeaders[Message.TransportHeadersBroadcastSendGuid] = callGuidSubstring; } // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0) { binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "ResultCollector.PerformBroadcasting", LogMessageType.BroadcastRecipientInvoked, null, null, receiverInfo.DbgRemoteHost, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, false, this._dispatcher, this, false, receiverInfo, null, null, "The broadcast recipient is being invoked directly."); } // invoke the destination MBR msg.Properties["__Uri"] = receiverInfo.MbrUri; transportHeaders[Message.TransportHeadersBroadcastObjRefOrCourt] = receiverInfo.SerializedObjRef; transportHeaders[Message.TransportHeadersMbrUriName] = receiverInfo.MbrUri; transportHeaders[Message.TransportHeadersGenuineMessageType] = GenuineMessageType.BroadcastEngine; transportHeaders[Message.TransportHeadersInvocationTarget] = invocationTarget; transportHeaders[Message.TransportHeadersMethodName] = methodName; ClientChannelSinkStack clientChannelSinkStack = new ClientChannelSinkStack(this); clientChannelSinkStack.Push(this, null); receiverInfo.IClientChannelSink.AsyncProcessRequest(clientChannelSinkStack, this._iMessage, transportHeaders, messageToBeSent); } } } catch (Exception ex) { this.ParseResult(mbrUri, null, ex); } } // remove set uri from the hash to check wither the invocation finished this.UnrepliedReceivers.Remove(_uniqueReceiverName); if (this.UnrepliedReceivers.Count <= 0) { this.AllMessagesReceived.Set(); } this.StartReceiving(); if (listOfExcludedReceivers.Count > 0) { foreach (string uri in listOfExcludedReceivers) { this._dispatcher.Remove(uri); } } } catch (Exception ex) { // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0) { binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "ResultCollector.PerformBroadcasting", LogMessageType.BroadcastInvocationInitiated, ex, null, null, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, false, this._dispatcher, this, false, null, invocationTarget, methodName, "A critical failure occurred during broadcast."); } throw; } }
/// <summary> /// Calls the callback when either all receivers reply or wait time elapses. /// </summary> /// <param name="state">Ignored.</param> /// <param name="timeOut">Ignored.</param> private void WaitUntilReceiversReplyOrTimeOut(object state, bool timeOut) { // check whether we have any unreplied true multicast-enabled receivers bool unrepliedReceivers = false; lock (this) { if (this.Failed.Count > 0 && !this._secondStagePerformed) { foreach (DictionaryEntry entry in this.Failed) { // fixed in 2.2 version string uri = (string)entry.Key; ReceiverInfo receiverInfo = this._dispatcher.GetReceiverInfo(uri); int numberOfFails = 0; if (receiverInfo != null) { lock (receiverInfo) { numberOfFails = ++receiverInfo.NumberOfFails; } } if (this._dispatcher.MaximumNumberOfConsecutiveFailsToExcludeReceiverAutomatically != 0 && numberOfFails >= this._dispatcher.MaximumNumberOfConsecutiveFailsToExcludeReceiverAutomatically) { this._dispatcher.Remove(uri); } // set time-out exception OperationException operationException = entry.Value as OperationException; if (operationException != null && operationException.OperationErrorMessage != null && operationException.OperationErrorMessage.ErrorIdentifier == "GenuineChannels.Exception.Broadcast.RemoteEndPointDidNotReplyForTimeOut") { unrepliedReceivers = true; break; } } } } if (unrepliedReceivers) { this.SendMessageToFailedReceiversDirectly(); this.StartReceiving(); return; } // LOG: BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter; if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0) { binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "ResultCollector.WaitUntilReceiversReplyOrTimeOut", LogMessageType.BroadcastInvocationCompleted, null, null, null, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, false, this._dispatcher, this, false, null, null, null, "The broadcast invocation is completed."); } // to stop receiving info this.AllMessagesReceived.Set(); if (this._broadcastCallFinishedHandler != null) { this._broadcastCallFinishedHandler(this._dispatcher, this._iMessage, this); } }
/// <summary> /// Writes down response came from the remote host. /// </summary> /// <param name="mbrUri">The uri of the remote MBR.</param> /// <param name="returnMessage">The received message or a null reference.</param> /// <param name="ex">The exception occurred during sending or receiving.</param> public void ParseResult(string mbrUri, IMethodReturnMessage returnMessage, Exception ex) { // if time-out has expired if (this.AllMessagesReceived.WaitOne(0, false)) { return; } // to increase or zero the number of consecutive fails ReceiverInfo receiverInfo = this._dispatcher.GetReceiverInfo(mbrUri); BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter; // if an exception is received Exception exception = null; if (ex != null || (returnMessage != null && returnMessage.Exception != null)) { exception = ex != null ? ex : returnMessage.Exception; HostInformation dbgRemoteHost = (receiverInfo == null ? null : receiverInfo.DbgRemoteHost); string numberOfFails = (receiverInfo == null ? string.Empty : receiverInfo.NumberOfFails.ToString()); // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0) { binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "ResultCollector.ParseResult", LogMessageType.BroadcastResponseParsed, exception, null, dbgRemoteHost, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, false, this._dispatcher, this, false, receiverInfo, numberOfFails, "false", "The exception is received in response to the broadcast. NumberOfFails: {0}.", numberOfFails); } } // if it's a message that the invocation was repeated, ignore it if (exception is OperationException) { OperationException operationException = (OperationException)exception; if (operationException.OperationErrorMessage.ErrorIdentifier == "GenuineChannels.Exception.Broadcast.CallHasAlreadyBeenMade") { return; } } lock (this) { // if successful response from this object has already been received this.UnrepliedReceivers.Remove(mbrUri); if (this.Successful.ContainsKey(mbrUri)) { return; } } lock (this) { // if an exception is received if (exception != null) { this.Failed[mbrUri] = exception; if (receiverInfo != null) { lock (receiverInfo) { if (receiverInfo.GeneralBroadcastSender == null && this._dispatcher.MaximumNumberOfConsecutiveFailsToExcludeReceiverAutomatically != 0 && receiverInfo.NumberOfFails >= this._dispatcher.MaximumNumberOfConsecutiveFailsToExcludeReceiverAutomatically) { // exclude it this._dispatcher.Remove(receiverInfo.MbrObject); } } } } else { // successful response this.Successful[mbrUri] = returnMessage; this.Failed.Remove(mbrUri); // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0) { HostInformation dbgRemoteHost = (receiverInfo == null ? null : receiverInfo.DbgRemoteHost); binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "ResultCollector.ParseResult", LogMessageType.BroadcastResponseParsed, null, null, dbgRemoteHost, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, false, this._dispatcher, this, false, receiverInfo, null, "true", "The successful response is received."); } if (receiverInfo != null) { lock (receiverInfo) { receiverInfo.NumberOfFails = 0; } } } if (this.UnrepliedReceivers.Count == 0) { this.AllMessagesReceived.Set(); } } }
/// <summary> /// Registers the receiver and associate the provided object with it. /// Returns false if the receiver has already been registered. /// WARNING: does not check whether the receiver supports the required interface (via Reflection) /// because this check requires client's dll. /// </summary> /// <param name="obj">The receiver being registered.</param> /// <param name="tag">The object associated with the receiver. This object is accessible when receiver is being unregistered or during filtering.</param> /// <param name="remoteGenuineUri">The uri of the remote host provided by any of Genuine Channels.</param> /// <param name="transportContext">The transport context of the remote host.</param> /// <returns>False if the receiver has been already registered.</returns> public bool Add(MarshalByRefObject obj, object tag, string remoteGenuineUri, ITransportContext transportContext) { if (obj == null) { throw new ArgumentNullException("obj"); } BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter; // check if it is in the list string uri = RemotingServices.GetObjectUri(obj); if (uri == null && !RemotingServices.IsObjectOutOfAppDomain(obj)) { // it was not marshalled RemotingServices.Marshal(obj); uri = RemotingServices.GetObjectUri(obj); } using (ReaderAutoLocker reader = new ReaderAutoLocker(this._readerWriterLock)) { if (this._receivers.ContainsKey(uri)) { return(false); } } // this check can not be performed because client's dll is required // // check on the interface // bool supportInterface = false; // foreach(Type interfaceType in obj.GetType().GetInterfaces()) // if (interfaceType == this._interfaceToSupport) // { // supportInterface = true; // break; // } // if (! supportInterface) // throw GenuineExceptions.Get_Broadcast_ObjectDoesNotSupportDestinationInterface(); // adds the object to the receiver list ReceiverInfo receiverInfo = new ReceiverInfo(); receiverInfo.MbrObject = obj; receiverInfo.MbrUri = uri; receiverInfo.Tag = tag; if (binaryLogWriter != null) { try { if (receiverInfo.MbrObject != null) { receiverInfo.DbgRemoteHost = GenuineUtility.FetchHostInformationFromMbr(receiverInfo.MbrObject); } } catch (Exception ex) { binaryLogWriter.WriteImplementationWarningEvent("Dispatcher.Add", LogMessageType.Error, ex, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, "Can't get HostInformation from MbrObject."); } } ObjRef objRef = receiverInfo.MbrObject.CreateObjRef(typeof(MarshalByRefObject)); receiverInfo.Local = objRef.IsFromThisAppDomain(); // cache object's info to speed up sending thru Genuine Channels if (!receiverInfo.Local) { if (remoteGenuineUri != null) { receiverInfo.IClientChannelSink = new GenuineTcpClientTransportSink(remoteGenuineUri, transportContext); } else { // check whether the client sink has registered itself on this MBR receiverInfo.IClientChannelSink = ChannelServices.GetChannelSinkProperties(obj)["GC_TS"] as IClientChannelSink; if (receiverInfo.IClientChannelSink == null) { throw GenuineExceptions.Get_Broadcast_ClientSinkIsUnknown(); } } // object uri receiverInfo.SerializedObjRef = objRef; // // and shell's uri // string shellUri; // ITransportContext iTransportContext; // GenuineUtility.FetchChannelUriFromMbr(obj, out shellUri, out iTransportContext); // if (shellUri == null) // throw GenuineExceptions.Get_Send_NoSender(objRef.URI); // // receiverInfo.ReceiverUri = shellUri; } // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0) { binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "Dispatcher.Add", LogMessageType.BroadcastRecipientAdded, null, null, receiverInfo.DbgRemoteHost, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, false, this, null, true, receiverInfo, null, null, "The broadcast recipient is added."); } // register the sponsor to prevent unexpected reclaiming ILease lease = (ILease)RemotingServices.GetLifetimeService(obj); if (lease != null) { lease.Register(this.GlobalSponsor); } // and register it using (WriterAutoLocker writer = new WriterAutoLocker(this._readerWriterLock)) { this._cachedReceiversInfoArray = null; this._receivers[uri] = receiverInfo; } return(true); }
/// <summary> /// Registers the broadcast sender that sends a message to several receivers. /// Returns Guid (it's like URI for an MBR object) assigned for this sender that can be used /// to delete this broadcast sender later. /// </summary> /// <param name="generalBroadcastSender">The broadcast sender which sends a message via "true" multicast channel.</param> public string Add(GeneralBroadcastSender generalBroadcastSender) { // just add it as it would be the usual receiver ReceiverInfo receiverInfo = new ReceiverInfo(); receiverInfo.GeneralBroadcastSender = generalBroadcastSender; receiverInfo.Local = false; string uri = Guid.NewGuid().ToString("N") + "/" + generalBroadcastSender.Court; receiverInfo.MbrUri = uri; // register it using (WriterAutoLocker writer = new WriterAutoLocker(this._readerWriterLock)) { this._cachedReceiversInfoArray = null; this._receivers[uri] = receiverInfo; } // LOG: BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter; if ( binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0 ) { binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "Dispatcher.Add", LogMessageType.BroadcastRecipientAdded, null, null, null, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, false, this, null, true, receiverInfo, generalBroadcastSender.Court, generalBroadcastSender.ITransportContext.HostIdentifier, "The \"true\" multicast sender is added."); } return uri; }
/// <summary> /// Registers the receiver and associate the provided object with it. /// Returns false if the receiver has already been registered. /// WARNING: does not check whether the receiver supports the required interface (via Reflection) /// because this check requires client's dll. /// </summary> /// <param name="obj">The receiver being registered.</param> /// <param name="tag">The object associated with the receiver. This object is accessible when receiver is being unregistered or during filtering.</param> /// <param name="remoteGenuineUri">The uri of the remote host provided by any of Genuine Channels.</param> /// <param name="transportContext">The transport context of the remote host.</param> /// <returns>False if the receiver has been already registered.</returns> public bool Add(MarshalByRefObject obj, object tag, string remoteGenuineUri, ITransportContext transportContext) { if (obj == null) throw new ArgumentNullException("obj"); BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter; // check if it is in the list string uri = RemotingServices.GetObjectUri(obj); if (uri == null && ! RemotingServices.IsObjectOutOfAppDomain(obj)) { // it was not marshalled RemotingServices.Marshal(obj); uri = RemotingServices.GetObjectUri(obj); } using (ReaderAutoLocker reader = new ReaderAutoLocker(this._readerWriterLock)) { if (this._receivers.ContainsKey(uri)) return false; } // this check can not be performed because client's dll is required // // check on the interface // bool supportInterface = false; // foreach(Type interfaceType in obj.GetType().GetInterfaces()) // if (interfaceType == this._interfaceToSupport) // { // supportInterface = true; // break; // } // if (! supportInterface) // throw GenuineExceptions.Get_Broadcast_ObjectDoesNotSupportDestinationInterface(); // adds the object to the receiver list ReceiverInfo receiverInfo = new ReceiverInfo(); receiverInfo.MbrObject = obj; receiverInfo.MbrUri = uri; receiverInfo.Tag = tag; if (binaryLogWriter != null) { try { if (receiverInfo.MbrObject != null) receiverInfo.DbgRemoteHost = GenuineUtility.FetchHostInformationFromMbr(receiverInfo.MbrObject); } catch(Exception ex) { binaryLogWriter.WriteImplementationWarningEvent("Dispatcher.Add", LogMessageType.Error, ex, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, "Can't get HostInformation from MbrObject."); } } ObjRef objRef = receiverInfo.MbrObject.CreateObjRef(typeof(MarshalByRefObject)); receiverInfo.Local = objRef.IsFromThisAppDomain(); // cache object's info to speed up sending thru Genuine Channels if (! receiverInfo.Local) { if (remoteGenuineUri != null) { receiverInfo.IClientChannelSink = new GenuineTcpClientTransportSink(remoteGenuineUri, transportContext); } else { // check whether the client sink has registered itself on this MBR receiverInfo.IClientChannelSink = ChannelServices.GetChannelSinkProperties(obj)["GC_TS"] as IClientChannelSink; if (receiverInfo.IClientChannelSink == null) throw GenuineExceptions.Get_Broadcast_ClientSinkIsUnknown(); } // object uri receiverInfo.SerializedObjRef = objRef; // // and shell's uri // string shellUri; // ITransportContext iTransportContext; // GenuineUtility.FetchChannelUriFromMbr(obj, out shellUri, out iTransportContext); // if (shellUri == null) // throw GenuineExceptions.Get_Send_NoSender(objRef.URI); // // receiverInfo.ReceiverUri = shellUri; } // LOG: if ( binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0 ) { binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "Dispatcher.Add", LogMessageType.BroadcastRecipientAdded, null, null, receiverInfo.DbgRemoteHost, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, false, this, null, true, receiverInfo, null, null, "The broadcast recipient is added."); } // register the sponsor to prevent unexpected reclaiming ILease lease = (ILease) RemotingServices.GetLifetimeService(obj); if (lease != null) lease.Register(this.GlobalSponsor); // and register it using (WriterAutoLocker writer = new WriterAutoLocker(this._readerWriterLock)) { this._cachedReceiversInfoArray = null; this._receivers[uri] = receiverInfo; } return true; }
/// <summary> /// Puts down a record containing information about the specified broadcast recipient. /// </summary> /// <param name="writeFullInformation">True if it is necessary to write all settings of the ReceiverInfo.</param> /// <param name="receiverInfo">The ReceiverInfo.</param> public void WriteReceiverInfo(bool writeFullInformation, ReceiverInfo receiverInfo) { this.BinaryWriter.Write( receiverInfo != null ); if (receiverInfo == null) return ; this.BinaryWriter.Write( (int) receiverInfo.DbgRecipientId ); this.BinaryWriter.Write( (bool) writeFullInformation ); if (! writeFullInformation) return ; this.WriteString( receiverInfo.MbrUri); this.BinaryWriter.Write((bool) receiverInfo.Local); if (receiverInfo.GeneralBroadcastSender != null) this.WriteString( receiverInfo.GeneralBroadcastSender.Court); else this.BinaryWriter.Write(string.Empty); }
/// <summary> /// Puts down a record describing a general Genuine Channels event. /// </summary> /// <param name="logCategory">The category of the event.</param> /// <param name="author">The author.</param> /// <param name="type">The type of the event(Subcategory).</param> /// <param name="exception">The exception associated with the event.</param> /// <param name="message">The message associated with the event.</param> /// <param name="remote">The remote host participating in the event.</param> /// <param name="content">The content associated with the record.</param> /// <param name="sourceThreadId">The id of the thread where the invocation was made.</param> /// <param name="sourceThreadName">The name of the thread.</param> /// <param name="securitySession">The Security Session.</param> /// <param name="securitySessionName">The name of the Security Session</param> /// <param name="writeDispatcherSettings">A value indicating whether it is necessary to put down broadcast dispatcher's settings.</param> /// <param name="dispatcher">The broadcast dispatcher.</param> /// <param name="resultCollector">The broadcast result collector.</param> /// <param name="writeReceiverInfoSettings">A value indicating whether it is necessary to put down information about the specified broadcast recipient.</param> /// <param name="receiverInfo">The broadcast recipient.</param> /// <param name="string1">The first string that elaborates the current event.</param> /// <param name="string2">The second string that elaborates the current event.</param> /// <param name="description">The description of the event.</param> /// <param name="parameters">Parameters to the description.</param> public void WriteBroadcastEngineEvent(LogCategory logCategory, string author, LogMessageType type, Exception exception, Message message, HostInformation remote, Stream content, int sourceThreadId, string sourceThreadName, SecuritySession securitySession, string securitySessionName, bool writeDispatcherSettings, Dispatcher dispatcher, ResultCollector resultCollector, bool writeReceiverInfoSettings, ReceiverInfo receiverInfo, string string1, string string2, string description, params object[] parameters) { if (dispatcher == null) { this.WriteImplementationWarningEvent("BinaryLogWriter.WriteBroadcastEngineEvent", LogMessageType.Error, null, sourceThreadId, sourceThreadName, "The reference is null. Stack trace: " + Environment.StackTrace); return ; } lock (this._streamLock) { this.WriteRecordHeader(BinaryRecordVersion.TransportBroadcastEngineRecord, logCategory, type, author); this.WriteException( exception ); this.WriteMessageSeqNo( message ); this.WriteHostInformationId( remote ); this.WriteBinaryContent( content ); this.BinaryWriter.Write( (int) sourceThreadId); this.WriteString( sourceThreadName ); this.WriteSecuritySessionId( securitySession ); this.WriteString( securitySessionName ); this.WriteResultCollectorId(resultCollector); this.WriteDispatcherSettings(writeDispatcherSettings, dispatcher); this.WriteReceiverInfo(writeReceiverInfoSettings, receiverInfo); this.WriteString( string1 ); this.WriteString( string2 ); this.WriteStringWithParameters( description, parameters); this.BinaryWriter.Flush(); } }
private void _dispatcher_BroadcastReceiverHasBeenExcluded(MarshalByRefObject marshalByRefObject, ReceiverInfo receiverInfo) { if(receiverInfo!=null) { lock(FailedReciverURIList) { FailedReciverURIList.Add(receiverInfo.MbrUri+" receiver fails "+receiverInfo.NumberOfFails.ToString()); } showFailReciverList("private void _dispatcher_BroadcastReceiverHasBeenExcluded(MarshalByRefObject marshalByRefObject, ReceiverInfo receiverInfo)"); } }