/// <summary> /// Broadcasts message to all registered receivers. /// </summary> /// <param name="msg">The message to be broadcasted.</param> /// <returns></returns> public override IMessage Invoke(IMessage msg) { ResultCollector resultCollector = null; // broadcasting using (ReaderAutoLocker reader = new ReaderAutoLocker(this._dispatcher._readerWriterLock)) { resultCollector = new ResultCollector(this._dispatcher, this._dispatcher._receivers.Count + 3, msg); } resultCollector.PerformBroadcasting(msg); return new ReturnMessage(resultCollector, null, 0, (LogicalCallContext) msg.Properties["__CallContext"], (IMethodCallMessage) msg); }
/// <summary> /// Returns the receiver associated with the specified uri. /// </summary> /// <param name="mbrUri">The uri associated with the receiver.</param> /// <returns>The receiver associated with the specified uri.</returns> public ReceiverInfo GetReceiverInfo(string mbrUri) { using (ReaderAutoLocker reader = new ReaderAutoLocker(this._readerWriterLock)) { return this._receivers[mbrUri] as ReceiverInfo; } }
/// <summary> /// Returns the filtered array of the ReceiverInfo instances. /// </summary> /// <param name="arrayOfReceiverInfo">The list of receivers being filtered out.</param> /// <param name="iMessage">The invocation.</param> /// <param name="resultCollector">The Result Collector obtaining the list of receivers. Is used for debugging purposes only.</param> public void GetListOfReceivers(out object[] arrayOfReceiverInfo, IMessage iMessage, ResultCollector resultCollector) { arrayOfReceiverInfo = null; try { using (ReaderAutoLocker reader = new ReaderAutoLocker(this._readerWriterLock)) { // check whether they were cached if (this._cachedReceiversInfoArray == null) { this._cachedReceiversInfoArray = new object[this._receivers.Values.Count]; this._receivers.Values.CopyTo(this._cachedReceiversInfoArray, 0); } // get the cached array arrayOfReceiverInfo = this._cachedReceiversInfoArray; // and drive it thru the filter IMulticastFilter iMulticastFilter = Dispatcher.GetCurrentFilter(); if (iMulticastFilter == null) iMulticastFilter = this.IMulticastFilter; if (iMulticastFilter != null) { // LOG: BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter; if ( binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0 ) { binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "Dispatcher.GetListOfReceivers", LogMessageType.BroadcastFilterCalled, null, null, null, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, false, this, resultCollector, false, null, iMulticastFilter.GetType().ToString(), null, "The broadcast filter is called. The type of the filter: {0}.", iMulticastFilter.GetType().ToString()); } arrayOfReceiverInfo = iMulticastFilter.GetReceivers(arrayOfReceiverInfo, iMessage); } } } catch(Exception ex) { // LOG: BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter; if ( binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0 ) { binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "Dispatcher.GetListOfReceivers", LogMessageType.BroadcastFilterCalled, ex, null, null, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, false, this, resultCollector, false, null, null, null, "The exception occurred while calling the broadcast filter."); } } }
/// <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> /// 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; }