Code:
/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / clr / src / BCL / System / Runtime / Remoting / TerminatorSinks.cs / 1 / TerminatorSinks.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== // // Remoting terminator sinks for sink chains along a remoting call. // There is only one static instance of each of these exposed through // the MessageSink property. // namespace System.Runtime.Remoting.Messaging { using System; using System.Threading; using System.Runtime.InteropServices; using System.Runtime.Remoting.Activation; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Contexts; using System.Collections; using System.Globalization; // Methods shared by all terminator sinks. // [Serializable] internal class InternalSink { /* * Checks the replySink param for NULL and type. * If the param is good, it returns NULL. * Else it returns a Message with the relevant exception. */ internal static IMessage ValidateMessage(IMessage reqMsg) { IMessage retMsg = null; if (reqMsg == null) { retMsg = new ReturnMessage( new ArgumentNullException("reqMsg"), null); } return retMsg; } /* * This check is performed only for client & server context * terminator sinks and only on the Async path. * */ internal static IMessage DisallowAsyncActivation(IMessage reqMsg) { // < if (reqMsg is IConstructionCallMessage) { return new ReturnMessage(new RemotingException(Environment.GetResourceString("Remoting_Activation_AsyncUnsupported")), null /*reqMsg*/ ); } return null; } internal static Identity GetIdentity(IMessage reqMsg) { Identity id = null; if (reqMsg is IInternalMessage) { id = ((IInternalMessage) reqMsg).IdentityObject; } else if (reqMsg is InternalMessageWrapper) { id = (Identity)((InternalMessageWrapper)reqMsg).GetIdentityObject(); } // Try the slow path if the identity has not been obtained yet if(null == id) { String objURI = GetURI(reqMsg); id = IdentityHolder.ResolveIdentity(objURI); // An object could get disconnected on another thread while a call is in progress if(id == null) { throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_ServerObjectNotFound"), objURI)); } } return id; } internal static ServerIdentity GetServerIdentity(IMessage reqMsg) { ServerIdentity srvID = null; bool bOurMsg = false; String objURI = null; IInternalMessage iim = reqMsg as IInternalMessage; if (iim != null) { Message.DebugOut("GetServerIdentity.ServerIdentity from IInternalMessage\n"); srvID = ((IInternalMessage) reqMsg).ServerIdentityObject; bOurMsg = true; } else if (reqMsg is InternalMessageWrapper) { srvID = (ServerIdentity)((InternalMessageWrapper)reqMsg).GetServerIdentityObject(); } // Try the slow path if the identity has not been obtained yet if(null == srvID) { Message.DebugOut("GetServerIdentity.ServerIdentity from IMethodCallMessage\n"); objURI = GetURI(reqMsg); Identity id = IdentityHolder.ResolveIdentity(objURI); if(id is ServerIdentity) { srvID = (ServerIdentity)id; // Cache the serverIdentity in the message if (bOurMsg) { iim.ServerIdentityObject = srvID; } } } return srvID; } // Retrieve the URI either via a method call or through // a dictionary property. internal static String GetURI(IMessage msg) { String uri = null; IMethodMessage mm = msg as IMethodMessage; if (mm != null) { uri = mm.Uri; } else { IDictionary prop = msg.Properties; if(null != prop) { uri = (String)prop["__Uri"]; } } return uri; } } // // Terminator sink for server envoy message sink chain. This delegates // to the client context chain for the call. // /* package scope */ [Serializable] internal class EnvoyTerminatorSink : InternalSink, IMessageSink { private static EnvoyTerminatorSink messageSink; private static Object staticSyncObject = new Object(); internal static IMessageSink MessageSink { get { if (messageSink == null) { EnvoyTerminatorSink tmpSink = new EnvoyTerminatorSink(); lock(staticSyncObject) { if (messageSink == null) { messageSink = tmpSink; } } } return messageSink; } } public virtual IMessage SyncProcessMessage(IMessage reqMsg) { Message.DebugOut("---------------------------Envoy Chain Terminator: SyncProcessMessage"); IMessage errMsg = ValidateMessage(reqMsg); if (errMsg != null) { return errMsg; } // Validate returns null if the reqMsg is okay! return Thread.CurrentContext.GetClientContextChain().SyncProcessMessage(reqMsg); } public virtual IMessageCtrl AsyncProcessMessage(IMessage reqMsg, IMessageSink replySink) { Message.DebugOut("---------------------------Envoy Chain Terminator: AsyncProcessMessage"); IMessageCtrl msgCtrl = null; IMessage errMsg = ValidateMessage(reqMsg); if (errMsg != null) { // Notify replySink of error if we can // < if (replySink != null) { replySink.SyncProcessMessage(errMsg); } } else { msgCtrl = Thread.CurrentContext.GetClientContextChain().AsyncProcessMessage(reqMsg, replySink); } return msgCtrl; } public IMessageSink NextSink { get { // We are the terminal sink of this chain return null; } } } // // Terminator sink for client context message sink chain. This delegates // to the appropriate channel sink for the call. // // /* package scope */ internal class ClientContextTerminatorSink : InternalSink, IMessageSink { private static ClientContextTerminatorSink messageSink; private static Object staticSyncObject = new Object(); internal static IMessageSink MessageSink { get { if (messageSink == null) { ClientContextTerminatorSink tmpSink = new ClientContextTerminatorSink(); lock(staticSyncObject) { if (messageSink == null) { messageSink = tmpSink; } } } return messageSink; } } internal static Object SyncProcessMessageCallback(Object[] args) { IMessage reqMsg = (IMessage) args[0]; IMessageSink channelSink = (IMessageSink) args[1]; return channelSink.SyncProcessMessage(reqMsg); } public virtual IMessage SyncProcessMessage(IMessage reqMsg) { Message.DebugOut("+++++++++++++++++++++++++ CliCtxTerminator: SyncProcessMsg"); IMessage errMsg = ValidateMessage(reqMsg); if (errMsg != null) { return errMsg; } Context ctx = Thread.CurrentContext; bool bHasDynamicSinks = ctx.NotifyDynamicSinks(reqMsg, true, // bCliSide true, // bStart false, // bAsync true); // bNotifyGlobals IMessage replyMsg; if (reqMsg is IConstructionCallMessage) { errMsg = ctx.NotifyActivatorProperties( reqMsg, false /*bServerSide*/); if (errMsg != null) { return errMsg; } replyMsg = ((IConstructionCallMessage)reqMsg).Activator.Activate( (IConstructionCallMessage)reqMsg); BCLDebug.Assert(replyMsg is IConstructionReturnMessage,"bad ctorRetMsg"); errMsg = ctx.NotifyActivatorProperties( replyMsg, false /*bServerSide*/); if (errMsg != null) { return errMsg; } } else { replyMsg = null; ChannelServices.NotifyProfiler(reqMsg, RemotingProfilerEvent.ClientSend); Object[] args = new Object[] { null, null }; IMessageSink channelSink = GetChannelSink(reqMsg); // Forward call to the channel. args[0] = reqMsg; args[1] = channelSink; InternalCrossContextDelegate xctxDel = new InternalCrossContextDelegate(SyncProcessMessageCallback); // Move to default context unless we are going through // the cross-context channel if (channelSink != CrossContextChannel.MessageSink) { replyMsg = (IMessage) Thread.CurrentThread.InternalCrossContextCallback(Context.DefaultContext, xctxDel, args); } else { replyMsg = (IMessage) xctxDel(args); } ChannelServices.NotifyProfiler(replyMsg, RemotingProfilerEvent.ClientReceive); } if (bHasDynamicSinks) { ctx.NotifyDynamicSinks(reqMsg, true, // bCliSide false, // bStart false, // bAsync true); // bNotifyGlobals } return replyMsg; } internal static Object AsyncProcessMessageCallback(Object[] args) { IMessage reqMsg = (IMessage) args[0]; IMessageSink replySink = (IMessageSink) args[1]; IMessageSink channelSink = (IMessageSink) args[2]; return channelSink.AsyncProcessMessage(reqMsg, replySink); } public virtual IMessageCtrl AsyncProcessMessage(IMessage reqMsg, IMessageSink replySink) { Message.DebugOut("+++++++++++++++++++++++++ CliCtxTerminator: AsyncProcessMsg"); IMessage errMsg = ValidateMessage(reqMsg); IMessageCtrl msgCtrl=null; if (errMsg == null) { errMsg = DisallowAsyncActivation(reqMsg); } if (errMsg != null) { if (replySink != null) { replySink.SyncProcessMessage(errMsg); } } else { // If active, notify the profiler that an asynchronous remoting call is being made. if (RemotingServices.CORProfilerTrackRemotingAsync()) { Guid g; RemotingServices.CORProfilerRemotingClientSendingMessage(out g, true); if (RemotingServices.CORProfilerTrackRemotingCookie()) reqMsg.Properties["CORProfilerCookie"] = g; // Only wrap the replySink if the call wants a reply if (replySink != null) { // Now wrap the reply sink in our own so that we can notify the profiler of // when the reply is received. Upon invocation, it will notify the profiler // then pass control on to the replySink passed in above. IMessageSink profSink = new ClientAsyncReplyTerminatorSink(replySink); // Replace the reply sink with our own replySink = profSink; } } Context cliCtx = Thread.CurrentContext; // Notify dynamic sinks that an Async call started cliCtx.NotifyDynamicSinks( reqMsg, true, // bCliSide true, // bStart true, // bAsync true); // bNotifyGlobals // Intercept the async reply to force the thread back // into the client-context before it executes further // and to notify dynamic sinks if (replySink != null) { replySink = new AsyncReplySink(replySink, cliCtx); } Object[] args = new Object[] { null, null, null }; InternalCrossContextDelegate xctxDel = new InternalCrossContextDelegate(AsyncProcessMessageCallback); IMessageSink channelSink = GetChannelSink(reqMsg); // Forward call to the channel. args[0] = reqMsg; args[1] = replySink; args[2] = channelSink; // Move to default context unless we are going through // the cross-context channel if (channelSink != CrossContextChannel.MessageSink) { msgCtrl = (IMessageCtrl) Thread.CurrentThread.InternalCrossContextCallback(Context.DefaultContext, xctxDel, args); } else { msgCtrl = (IMessageCtrl) xctxDel(args); } } return msgCtrl; } public IMessageSink NextSink { get { // We are the terminal sink of this chain return null; } } // Find the next chain (or channel) sink to delegate to. private IMessageSink GetChannelSink(IMessage reqMsg) { Identity id = GetIdentity(reqMsg); return id.ChannelSink; } } internal class AsyncReplySink : IMessageSink { IMessageSink _replySink;// original reply sink that we are wrapping Context _cliCtx; // the context this call emerged from internal AsyncReplySink(IMessageSink replySink, Context cliCtx) { _replySink = replySink; _cliCtx = cliCtx; } internal static Object SyncProcessMessageCallback(Object[] args) { IMessage reqMsg = (IMessage) args[0]; IMessageSink replySink = (IMessageSink) args[1]; // Call the dynamic sinks to notify that the async call // has completed Thread.CurrentContext.NotifyDynamicSinks( reqMsg, // this is the async reply true, // bCliSide false, // bStart true, // bAsync true); // bNotifyGlobals // call the original reply sink now that we have moved // to the correct client context return replySink.SyncProcessMessage(reqMsg); } public virtual IMessage SyncProcessMessage(IMessage reqMsg) { // we just switch back to the old context before calling // the next replySink IMessage retMsg = null; if (_replySink != null) { Object[] args = new Object[] { reqMsg, _replySink }; InternalCrossContextDelegate xctxDel = new InternalCrossContextDelegate(SyncProcessMessageCallback); retMsg = (IMessage) Thread.CurrentThread.InternalCrossContextCallback(_cliCtx, xctxDel, args); } return retMsg; } public virtual IMessageCtrl AsyncProcessMessage( IMessage reqMsg, IMessageSink replySink) { throw new NotSupportedException(); } public IMessageSink NextSink { get { return _replySink; } } } // // Terminator sink for server context message sink chain. This delegates // to the appropriate object sink chain for the call. // // /* package scope */ [Serializable] internal class ServerContextTerminatorSink : InternalSink, IMessageSink { private static ServerContextTerminatorSink messageSink; private static Object staticSyncObject = new Object(); internal static IMessageSink MessageSink { get { if (messageSink == null) { ServerContextTerminatorSink tmpSink = new ServerContextTerminatorSink(); lock(staticSyncObject) { if (messageSink == null) { messageSink = tmpSink; } } } return messageSink; } } public virtual IMessage SyncProcessMessage(IMessage reqMsg) { Message.DebugOut("+++++++++++++++++++++++++ SrvCtxTerminator: SyncProcessMsg"); IMessage errMsg = ValidateMessage(reqMsg); if (errMsg != null) { return errMsg; } Context ctx = Thread.CurrentContext; IMessage replyMsg; if (reqMsg is IConstructionCallMessage) { errMsg = ctx.NotifyActivatorProperties( reqMsg, true /*bServerSide*/); if (errMsg != null) { return errMsg; } replyMsg = ((IConstructionCallMessage)reqMsg).Activator.Activate((IConstructionCallMessage)reqMsg); BCLDebug.Assert(replyMsg is IConstructionReturnMessage,"bad ctorRetMsg"); errMsg = ctx.NotifyActivatorProperties( replyMsg, true /*bServerSide*/); if (errMsg != null) { return errMsg; } } else { // Pass call on to the server object specific chain MarshalByRefObject obj = null; try{ replyMsg = GetObjectChain(reqMsg, out obj).SyncProcessMessage(reqMsg); } finally { IDisposable iDis = null; if (obj != null && ((iDis=(obj as IDisposable)) != null)) { iDis.Dispose(); } } } return replyMsg; } public virtual IMessageCtrl AsyncProcessMessage(IMessage reqMsg, IMessageSink replySink) { Message.DebugOut("+++++++++++++++++++++++++ SrvCtxTerminator: SyncProcessMsg"); IMessageCtrl msgCtrl=null; IMessage errMsg = ValidateMessage(reqMsg); if (errMsg == null) { errMsg = DisallowAsyncActivation(reqMsg); } if (errMsg != null) { if (replySink!=null) { replySink.SyncProcessMessage(errMsg); } } else { // < MarshalByRefObject obj; IMessageSink nextChain = GetObjectChain(reqMsg, out obj); IDisposable iDis; if (obj != null && ((iDis = (obj as IDisposable)) != null)) { DisposeSink dsink = new DisposeSink(iDis, replySink); replySink = dsink; } msgCtrl = nextChain.AsyncProcessMessage( reqMsg, replySink); } return msgCtrl; } public IMessageSink NextSink { get { // We are the terminal sink of this chain return null; } } internal virtual IMessageSink GetObjectChain(IMessage reqMsg,out MarshalByRefObject obj) { ServerIdentity srvID = GetServerIdentity(reqMsg); return srvID.GetServerObjectChain(out obj); } } internal class DisposeSink : IMessageSink { IDisposable _iDis; IMessageSink _replySink; internal DisposeSink(IDisposable iDis, IMessageSink replySink) { _iDis = iDis; _replySink = replySink; } public virtual IMessage SyncProcessMessage(IMessage reqMsg) { IMessage replyMsg = null; try{ if (_replySink != null) { replyMsg = _replySink.SyncProcessMessage(reqMsg); } } finally{ // call dispose on the object now! _iDis.Dispose(); } return replyMsg; } public virtual IMessageCtrl AsyncProcessMessage(IMessage reqMsg, IMessageSink replySink) { throw new NotSupportedException(); } public IMessageSink NextSink { get { return _replySink; } } } // // Terminator sink for the server object sink chain. This should // be just replaced by the dispatcher sink. // /* package scope */ [Serializable] internal class ServerObjectTerminatorSink : InternalSink, IMessageSink { internal StackBuilderSink _stackBuilderSink; internal ServerObjectTerminatorSink(MarshalByRefObject srvObj) { _stackBuilderSink = new StackBuilderSink(srvObj); } public virtual IMessage SyncProcessMessage(IMessage reqMsg) { Message.DebugOut("+++++++++++++++++++++++++ SrvObjTerminator: SyncProcessMsg\n"); IMessage errMsg = ValidateMessage(reqMsg); if (errMsg != null) { return errMsg; } ServerIdentity srvID = GetServerIdentity(reqMsg); BCLDebug.Assert(null != srvID,"null != srvID"); ArrayWithSize objectSinks = srvID.ServerSideDynamicSinks; if (objectSinks != null) { DynamicPropertyHolder.NotifyDynamicSinks( reqMsg, objectSinks, false, // bCliSide true, // bStart false); // bAsync } Message.DebugOut("ServerObjectTerminator.Invoking method on object\n"); // Pass call on to the server object specific chain BCLDebug.Assert(null != _stackBuilderSink,"null != _stackBuilderSink"); IMessage replyMsg; IMessageSink serverAsSink = _stackBuilderSink.ServerObject as IMessageSink; if (serverAsSink != null) replyMsg = serverAsSink.SyncProcessMessage(reqMsg); else replyMsg = _stackBuilderSink.SyncProcessMessage(reqMsg); if (objectSinks != null) { DynamicPropertyHolder.NotifyDynamicSinks( replyMsg, objectSinks, false, // bCliSide false, // bStart false); // bAsync } return replyMsg; } public virtual IMessageCtrl AsyncProcessMessage(IMessage reqMsg, IMessageSink replySink) { IMessageCtrl msgCtrl=null; IMessage errMsg = ValidateMessage(reqMsg); // < if (errMsg!=null) { if (replySink!=null) { replySink.SyncProcessMessage(errMsg); } } else { // Pass call on to the server object specific chain IMessageSink serverAsSink = _stackBuilderSink.ServerObject as IMessageSink; if (serverAsSink != null) msgCtrl = serverAsSink.AsyncProcessMessage(reqMsg, replySink); else msgCtrl = _stackBuilderSink.AsyncProcessMessage(reqMsg, replySink); } return msgCtrl; } public IMessageSink NextSink { get { // We are the terminal sink of this chain return null; } } } // // Terminator sink used for profiling so that we can intercept asynchronous // replies on the client side. // /* package scope */ internal class ClientAsyncReplyTerminatorSink : IMessageSink { internal IMessageSink _nextSink; internal ClientAsyncReplyTerminatorSink(IMessageSink nextSink) { BCLDebug.Assert(nextSink != null, "null IMessageSink passed to ClientAsyncReplyTerminatorSink ctor."); _nextSink = nextSink; } public virtual IMessage SyncProcessMessage(IMessage replyMsg) { // If this class has been brought into the picture, then the following must be true. BCLDebug.Assert(RemotingServices.CORProfilerTrackRemoting(), "CORProfilerTrackRemoting returned false, but we're in AsyncProcessMessage!"); BCLDebug.Assert(RemotingServices.CORProfilerTrackRemotingAsync(), "CORProfilerTrackRemoting returned false, but we're in AsyncProcessMessage!"); Guid g = Guid.Empty; // If GUID cookies are active, then we try to get it from the properties dictionary if (RemotingServices.CORProfilerTrackRemotingCookie()) { Object obj = replyMsg.Properties["CORProfilerCookie"]; if (obj != null) { g = (Guid) obj; } } // Notify the profiler that we are receiving an async reply from the server-side RemotingServices.CORProfilerRemotingClientReceivingReply(g, true); // Now that we've done the intercepting, pass the message on to the regular chain return _nextSink.SyncProcessMessage(replyMsg); } public virtual IMessageCtrl AsyncProcessMessage(IMessage replyMsg, IMessageSink replySink) { // Since this class is only used for intercepting async replies, this function should // never get called. (Async replies are synchronous, ironically) BCLDebug.Assert(false, "ClientAsyncReplyTerminatorSink.AsyncProcessMessage called!"); return null; } public IMessageSink NextSink { get { return _nextSink; } } // Do I need a finalize here? } }
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- UshortList2.cs
- WriteTimeStream.cs
- FixedSOMGroup.cs
- VisualStyleInformation.cs
- ArithmeticException.cs
- Screen.cs
- RunInstallerAttribute.cs
- UnsafeNativeMethods.cs
- BaseTemplateCodeDomTreeGenerator.cs
- Converter.cs
- ChtmlImageAdapter.cs
- StringToken.cs
- WebPartCancelEventArgs.cs
- LowerCaseStringConverter.cs
- InputReferenceExpression.cs
- AuthStoreRoleProvider.cs
- StylusPointProperties.cs
- ReversePositionQuery.cs
- FormsAuthenticationUser.cs
- CertificateManager.cs
- FixedTextPointer.cs
- DbMetaDataFactory.cs
- TypeForwardedToAttribute.cs
- PrivilegeNotHeldException.cs
- BookmarkNameHelper.cs
- safePerfProviderHandle.cs
- DataSourceControl.cs
- Rfc2898DeriveBytes.cs
- RequestStatusBarUpdateEventArgs.cs
- NameTable.cs
- X509PeerCertificateElement.cs
- DbConnectionStringBuilder.cs
- MatrixStack.cs
- Int32Storage.cs
- SBCSCodePageEncoding.cs
- CodeThrowExceptionStatement.cs
- UnsafeCollabNativeMethods.cs
- BackStopAuthenticationModule.cs
- ElementUtil.cs
- ProfileProvider.cs
- PrivateFontCollection.cs
- InvalidOleVariantTypeException.cs
- PersonalizablePropertyEntry.cs
- MsmqVerifier.cs
- XmlSchemaComplexType.cs
- QuaternionAnimationUsingKeyFrames.cs
- BuildManager.cs
- FormViewUpdatedEventArgs.cs
- SafeNativeMemoryHandle.cs
- MatrixStack.cs
- ApplicationCommands.cs
- FileUtil.cs
- HttpDateParse.cs
- HtmlTableCell.cs
- DataSvcMapFileSerializer.cs
- DefaultMemberAttribute.cs
- SystemColors.cs
- VirtualPath.cs
- BooleanToVisibilityConverter.cs
- Int16Storage.cs
- AlphabeticalEnumConverter.cs
- DBParameter.cs
- SecurityRuntime.cs
- TabOrder.cs
- ListChangedEventArgs.cs
- DataSourceHelper.cs
- LicenseException.cs
- KnownBoxes.cs
- _SingleItemRequestCache.cs
- AssemblyInfo.cs
- CorrelationExtension.cs
- XmlElementCollection.cs
- RijndaelManagedTransform.cs
- VersionPair.cs
- NativeRightsManagementAPIsStructures.cs
- DateTimeConverter2.cs
- HttpPostServerProtocol.cs
- RemoveStoryboard.cs
- SiteMapNode.cs
- InstancePersistenceEvent.cs
- LinkedList.cs
- Int32Rect.cs
- BuildProvider.cs
- ScalarType.cs
- FormatPage.cs
- ContractListAdapter.cs
- WebPartVerbCollection.cs
- ipaddressinformationcollection.cs
- MailMessageEventArgs.cs
- Point3DCollectionConverter.cs
- ReturnValue.cs
- OracleConnectionFactory.cs
- XmlDataSourceView.cs
- Operators.cs
- BitmapCacheBrush.cs
- TemplatePropertyEntry.cs
- SmiMetaData.cs
- CollectionEditVerbManager.cs
- DynamicILGenerator.cs
- XsltException.cs