예제 #1
0
        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)
            {
                ContextTransitionFrame frame = new ContextTransitionFrame();
                Thread.CurrentThread.EnterContext(_cliCtx, ref frame);

                // 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
                retMsg = _replySink.SyncProcessMessage(reqMsg);

                // return the thread to its earlier context
                Thread.CurrentThread.ReturnToContext(ref frame);
            }
            return(retMsg);
        }
예제 #2
0
        /* package */
        internal virtual void FinishAsyncWork(Object stateIgnored)
        {
            // set to the server context
            ContextTransitionFrame frame = new ContextTransitionFrame();
            Context srvCtx = _srvID.ServerContext;

            Thread.CurrentThread.EnterContext(srvCtx, ref frame);

            LogicalCallContext threadPoolCallCtx =
                CallContext.SetLogicalCallContext(_callCtx);

            // Call the server context chain Async. We provide workItem as our
            // replySink ... this will cause the replySink.ProcessMessage
            // to switch back to the context of the original caller thread.

            // Call the dynamic sinks to notify that the async call
            // is starting
            srvCtx.NotifyDynamicSinks(
                _reqMsg,
                false,  // bCliSide
                true,   // bStart
                true,   // bAsync
                true);  // bNotifyGlobals

            IMessageCtrl ctrl =
                srvCtx.GetServerContextChain().AsyncProcessMessage(
                    _reqMsg,
                    (IMessageSink)this);

            // change back to the old context
            CallContext.SetLogicalCallContext(threadPoolCallCtx);
            Thread.CurrentThread.ReturnToContext(ref frame);
        }
예제 #3
0
        } // DoDispatch

        internal byte[] DoTransitionDispatch(
            byte[] reqStmBuff,
            SmuggledMethodCallMessage smuggledMcm,
            out SmuggledMethodReturnMessage smuggledMrm)
        {
            // Note: To be safe w.r.t. the app domain leak code, this frame
            // should have no non-agile references in it.

            ContextTransitionFrame frame = new ContextTransitionFrame();

            // change to server domain
            Thread.CurrentThread.EnterContextInternal(
                null,
                _srvContextID,
                _srvDomainID,
                ref frame);

            byte[] retBuff = null;
            smuggledMrm = null;
            try
            {
                Message.DebugOut("#### : changed to Server Domain :: " + (Thread.CurrentContext.InternalContextID).ToString("X"));

                retBuff = DoDispatch(reqStmBuff, smuggledMcm, out smuggledMrm);
            }
            catch (Exception e)
            {
                // This will catch exceptions thrown by the infrastructure,
                // Serialization/Deserialization etc
                // Those thrown by the server are already taken care of
                // and encoded in the retMsg .. so we don't come here for
                // that case.

                // We are in another appDomain, so we can't simply throw
                // the exception object across. The following marshals it
                // into a serialized return message.
                IMessage retMsg =
                    new ReturnMessage(e, new ErrorMessage());
                //*********************** SERIALIZE RET-MSG ******************
                retBuff = CrossAppDomainSerializer.SerializeMessage(retMsg).GetBuffer();
                retMsg  = null;
            }
            finally
            {
                RemotingServices.LogRemotingStage(RemotingServices.SERVER_RET_SEND);
                Thread.CurrentThread.ReturnToContext(ref frame);
                Message.DebugOut("#### : changed back to Client Domain " + (Thread.CurrentContext.InternalContextID).ToString("X"));
            }

            // System.Diagnostics.Debugger.Break();
            return(retBuff);
        } // DoTransitionDispatch
예제 #4
0
        internal void EnterContext(Context newContext, ref ContextTransitionFrame frame)
        {
            EnterContextInternal(newContext, newContext.InternalContextID, 0, ref frame);
            // The newContext parameter is passed in just to keep GC from
            // collecting a new context when we are trying to enter it.
            // By the time this returns, the m_Context field in the managed
            // thread is already set to the newContext ... so from there on
            // the newContext is rooted.

            // EnterContextInternal is directly called by the X-AppDomain
            // channel since it only has the target context-id and not the
            // context object itself (since the latter is in another domain)
            // It is also called directly when we are bootstrapping a new
            // AppDomain w.r.t. remoting (in CreateProxyForDomain). In both
            // these cases, the newContext is null.
        }
예제 #5
0
        public virtual IMessage     SyncProcessMessage(IMessage msg)
        {
            // This gets called when the called object finishes the AsyncWork...

            // This is called irrespective of whether we delegated the initial
            // work to a thread pool thread or not. Quite likely it will be
            // called on a user thread (i.e. a thread different from the
            // forward call thread)

            // we just switch back to the old context before calling
            // the next replySink
            IMessage retMsg = null;

            if (_replySink != null)
            {
                // This assert covers the common case (ThreadPool)
                // and checks that the reply thread for the async call
                // indeed emerges from the server context.
                BCLDebug.Assert(
                    (_srvID == null) ||
                    (_srvID.ServerContext == Thread.CurrentContext),
                    "Thread expected to be in the server context!");

                // Call the dynamic sinks to notify that the async call
                // has completed
                Thread.CurrentContext.NotifyDynamicSinks(
                    msg,    // this is the async reply
                    false,  // bCliSide
                    false,  // bStart
                    true,   // bAsync
                    true);  // bNotifyGlobals

                ContextTransitionFrame frame = new ContextTransitionFrame();
                Thread.CurrentThread.EnterContext(_oldCtx, ref frame);
                retMsg = _replySink.SyncProcessMessage(msg);
                Thread.CurrentThread.ReturnToContext(ref frame);
            }
            return(retMsg);
        }
예제 #6
0
 internal extern bool EnterContextInternal(Context ctx, Int32 id, Int32 appDomainID, ref ContextTransitionFrame frame);
예제 #7
0
 internal extern bool ReturnToContext(ref ContextTransitionFrame frame);
예제 #8
0
        } // AsyncProcessMessage

        internal static IMessageCtrl DoAsyncDispatch(IMessage reqMsg, IMessageSink replySink)
        {
            ServerIdentity srvID    = GetServerIdentity(reqMsg);
            AsyncWorkItem  workItem = null;

            // If active, notify the profiler that an asynchronous remoting message was received.
            if (RemotingServices.CORProfilerTrackRemotingAsync())
            {
                Guid g = Guid.Empty;

                if (RemotingServices.CORProfilerTrackRemotingCookie())
                {
                    Object obj = reqMsg.Properties["CORProfilerCookie"];
                    if (obj != null)
                    {
                        g = (Guid)obj;
                    }
                }

                RemotingServices.CORProfilerRemotingServerReceivingMessage(g, true);

                // 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 sent.  Upon invocation, it will notify the profiler
                    // then pass control on to the replySink passed in above.
                    IMessageSink profSink =
                        new ServerAsyncReplyTerminatorSink(replySink);

                    // Replace the reply sink with our own
                    replySink = profSink;
                }
            }

            Context srvCtx = srvID.ServerContext;

            //if (srvCtx.IsThreadPoolAware)
            //{
            // this is the case when we do not queue the work item since the
            // server context claims to be doing its own threading.

            Context oldCtx = Thread.CurrentContext;
            // change to server object context
            ContextTransitionFrame frame = new ContextTransitionFrame();

            Thread.CurrentThread.EnterContext(srvID.ServerContext, ref frame);

            // we use the work item just as our replySink in this case
            if (replySink != null)
            {
                workItem = new AsyncWorkItem(replySink, oldCtx);
            }
            Message.DebugOut("::::::::::::::::::::::::: CrossContext Channel: passing to ServerContextChain");
            // call the server context chain
            IMessageCtrl msgCtrl =
                srvID.ServerContext.GetServerContextChain().AsyncProcessMessage(reqMsg, (IMessageSink)workItem);

            Message.DebugOut("::::::::::::::::::::::::: CrossContext Channel: back from ServerContextChain");
            // chain back to the dispatch thread context
            Thread.CurrentThread.ReturnToContext(ref frame);

            //}

            return(msgCtrl);
        } // DoDispatch
예제 #9
0
        public virtual IMessageCtrl AsyncProcessMessage(IMessage reqMsg, IMessageSink replySink)
        {
            Message.DebugOut("::::::::::::::::::::::::::: CrossContext Channel: Async call starting!!\n");
            // One way Async notifications may potentially pass a null reply sink.
            IMessage     errMsg  = ValidateMessage(reqMsg);
            IMessageCtrl msgCtrl = null;

            if (errMsg != null)
            {
                if (replySink != null)
                {
                    replySink.SyncProcessMessage(errMsg);
                }
            }
            else
            {
                ServerIdentity srvID    = GetServerIdentity(reqMsg);
                AsyncWorkItem  workItem = null;

                // If active, notify the profiler that an asynchronous remoting message was received.
                if (RemotingServices.CORProfilerTrackRemotingAsync())
                {
                    Guid g = Guid.Empty;

                    if (RemotingServices.CORProfilerTrackRemotingCookie())
                    {
                        Object obj = reqMsg.Properties["CORProfilerCookie"];

                        if (obj != null)
                        {
                            g = (Guid)obj;
                        }
                    }

                    RemotingServices.CORProfilerRemotingServerReceivingMessage(g, true);

                    // 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 sent.  Upon invocation, it will notify the profiler
                        // then pass control on to the replySink passed in above.
                        IMessageSink profSink = new ServerAsyncReplyTerminatorSink(replySink);

                        // Replace the reply sink with our own
                        replySink = profSink;
                    }
                }

                Context srvCtx = srvID.ServerContext;
                if (srvCtx.IsThreadPoolAware)
                {
                    // this is the case when we do not queue the work item since the
                    // server context claims to be doing its own threading.

                    Context oldCtx = Thread.CurrentContext;
                    // change to server object context
                    ContextTransitionFrame frame = new ContextTransitionFrame();
                    srvCtx = srvID.ServerContext;
                    Thread.CurrentThread.EnterContext(srvCtx, ref frame);

                    // we use the work item just as our replySink in this case
                    if (replySink != null)
                    {
                        workItem = new AsyncWorkItem(replySink, oldCtx);
                    }

                    Message.DebugOut("::::::::::::::::::::::::: CrossContext Channel: passing to ServerContextChain");

                    srvCtx.NotifyDynamicSinks(
                        reqMsg,
                        false,          // bCliSide
                        true,           // bStart
                        true,           // bAsync
                        true);          // bNotifyGlobals

                    // call the server context chain
                    msgCtrl =
                        srvCtx.GetServerContextChain().AsyncProcessMessage(
                            reqMsg,
                            (IMessageSink)workItem);

                    // Note: for async calls, we will do the return notification
                    // for dynamic properties only when the async call
                    // completes (i.e. when the replySink gets called)

                    Message.DebugOut("::::::::::::::::::::::::: CrossContext Channel: back from ServerContextChain");

                    // chain back to the dispatch thread context
                    Thread.CurrentThread.ReturnToContext(ref frame);
                }
                else
                {
                    // This is the case where we take care of returning the calling
                    // thread asap by using the ThreadPool for completing the call.

                    // we use a more elaborate WorkItem and delegate the work to the thread pool
                    workItem = new AsyncWorkItem(reqMsg,
                                                 replySink,
                                                 Thread.CurrentContext,
                                                 srvID);

                    WaitCallback threadFunc = new WaitCallback(workItem.FinishAsyncWork);
                    // Note: Dynamic sinks are notified in the threadFunc
                    ThreadPool.QueueUserWorkItem(threadFunc);

                    msgCtrl = null;
                }
            }

            Message.DebugOut("::::::::::::::::::::::::::: CrossContext Channel: Async call returning!!\n");
            return(msgCtrl);
        } // AsyncProcessMessage
예제 #10
0
        public virtual IMessage     SyncProcessMessage(IMessage reqMsg)
        {
            IMessage replyMsg = null;

            try
            {
                Message.DebugOut("\n::::::::::::::::::::::::: CrossContext Channel: Sync call starting");
                IMessage errMsg = ValidateMessage(reqMsg);
                if (errMsg != null)
                {
                    return(errMsg);
                }

                ServerIdentity srvID = GetServerIdentity(reqMsg);
                Message.DebugOut("Got Server identity \n");
                BCLDebug.Assert(null != srvID, "null != srvID");


                BCLDebug.Assert(null != srvID.ServerContext, "null != srvID.ServerContext");

                bool fEnteredContext         = false;
                ContextTransitionFrame frame = new ContextTransitionFrame();
                try
                {
                    Context srvCtx = srvID.ServerContext;
                    Thread.CurrentThread.EnterContext(srvCtx, ref frame);
                    fEnteredContext = true;
                    // If profiling of remoting is active, must tell the profiler that we have received
                    // a message.
                    if (RemotingServices.CORProfilerTrackRemoting())
                    {
                        Guid g = Guid.Empty;

                        if (RemotingServices.CORProfilerTrackRemotingCookie())
                        {
                            Object obj = reqMsg.Properties["CORProfilerCookie"];

                            if (obj != null)
                            {
                                g = (Guid)obj;
                            }
                        }

                        RemotingServices.CORProfilerRemotingServerReceivingMessage(g, false);
                    }

                    Message.DebugOut("::::::::::::::::::::::::: CrossContext Channel: passing to ServerContextChain");

                    // Server side notifications for dynamic sinks are done
                    // in the x-context channel ... this is to maintain
                    // symmetry of the point of notification between
                    // the client and server context
                    srvCtx.NotifyDynamicSinks(
                        reqMsg,
                        false,          // bCliSide
                        true,           // bStart
                        false,          // bAsync
                        true);          // bNotifyGlobals

                    replyMsg = srvCtx.GetServerContextChain().SyncProcessMessage(reqMsg);
                    srvCtx.NotifyDynamicSinks(
                        replyMsg,
                        false,          // bCliSide
                        false,          // bStart
                        false,          // bAsync
                        true);          // bNotifyGlobals

                    Message.DebugOut("::::::::::::::::::::::::: CrossContext Channel: back from ServerContextChain");

                    // If profiling of remoting is active, must tell the profiler that we are sending a
                    // reply message.
                    if (RemotingServices.CORProfilerTrackRemoting())
                    {
                        Guid g;

                        RemotingServices.CORProfilerRemotingServerSendingReply(out g, false);

                        if (RemotingServices.CORProfilerTrackRemotingCookie())
                        {
                            replyMsg.Properties["CORProfilerCookie"] = g;
                        }
                    }
                }
                finally
                {
                    if (fEnteredContext)
                    {
                        Thread.CurrentThread.ReturnToContext(ref frame);
                    }
                }
            }
            catch (Exception e)
            {
                Message.DebugOut("Arrgh.. XCTXSink::throwing exception " + e + "\n");
                replyMsg = new ReturnMessage(e, (IMethodCallMessage)reqMsg);
                if (reqMsg != null)
                {
                    ((ReturnMessage)replyMsg).SetLogicalCallContext(
                        (LogicalCallContext)
                        reqMsg.Properties[Message.CallContextKey]);
                }
            }

            Message.DebugOut("::::::::::::::::::::::::::: CrossContext Channel: Sync call returning!!\n");
            return(replyMsg);
        }
예제 #11
0
        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);
                }

                // Forward call to the channel.
                IMessageSink channelSink = GetChannelSink(reqMsg);
                // Move to default context unless we are going through
                // the cross-context channel
                ContextTransitionFrame frame = new ContextTransitionFrame();
                if (channelSink != CrossContextChannel.MessageSink)
                {
                    Thread.CurrentThread.EnterContext(
                        Context.DefaultContext,
                        ref frame);
                }
                msgCtrl = channelSink.AsyncProcessMessage(reqMsg, replySink);

                if (channelSink != CrossContextChannel.MessageSink)
                {
                    Thread.CurrentThread.ReturnToContext(ref frame);
                }
            }
            return(msgCtrl);
        }
예제 #12
0
        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
            {
                ChannelServices.NotifyProfiler(reqMsg, RemotingProfilerEvent.ClientSend);

                // Forward call to the channel.
                IMessageSink channelSink = GetChannelSink(reqMsg);
                // Move to default context unless we are going through
                // the cross-context channel
                ContextTransitionFrame frame = new ContextTransitionFrame();
                if (channelSink != CrossContextChannel.MessageSink)
                {
                    Thread.CurrentThread.EnterContext(
                        Context.DefaultContext,
                        ref frame);
                }
                replyMsg = channelSink.SyncProcessMessage(reqMsg);

                if (channelSink != CrossContextChannel.MessageSink)
                {
                    Thread.CurrentThread.ReturnToContext(ref frame);
                }

                ChannelServices.NotifyProfiler(replyMsg, RemotingProfilerEvent.ClientReceive);
            }


            if (bHasDynamicSinks)
            {
                ctx.NotifyDynamicSinks(reqMsg,
                                       true,  // bCliSide
                                       false, // bStart
                                       false, // bAsync
                                       true); // bNotifyGlobals
            }

            return(replyMsg);
        }