MessageSmuggler.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / clr / src / BCL / System / Runtime / Remoting / MessageSmuggler.cs / 1 / MessageSmuggler.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
//==========================================================================
//  File:       MessageSmuggler.cs 
// 
//  Summary:    Implements objects necessary to smuggle messages across
//              AppDomains and determine when it's possible. 
//
//=========================================================================

using System; 
using System.Collections;
using System.IO; 
using System.Runtime.Remoting; 
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Messaging; 
using System.Runtime.Remoting.Proxies;


namespace System.Runtime.Remoting.Messaging 
{
 
    internal class MessageSmuggler 
    {
        private static bool CanSmuggleObjectDirectly(Object obj) 
        {
            if ((obj is String) ||
                (obj.GetType() == typeof(void)) ||
                obj.GetType().IsPrimitive) 
            {
                return true; 
            } 

            return false; 
        } // CanSmuggleObjectDirectly


        protected static Object[] FixupArgs(Object[] args, ref ArrayList argsToSerialize) 
        {
            Object[] newArgs = new Object[args.Length]; 
 
            int total = args.Length;
            for (int co = 0; co < total; co++) 
            {
                newArgs[co] = FixupArg(args[co], ref argsToSerialize);
            }
 
            return newArgs;
        } // FixupArgs 
 

        protected static Object FixupArg(Object arg, ref ArrayList argsToSerialize) 
        {
            // This method examines an argument and sees if it can be smuggled in some form.
            //   If it can directly be smuggled (i.e. it is a primitive or string), we
            //   just return the same object. If it's a marshal by ref object, we 
            //   see if we can smuggle the obj ref. If it's a primitive or string array,
            //   we can smuggle a cloned copy of the array. In all other cases, 
            //   we add it to the list of args we want serialized, and return a 
            //   placeholder element (SerializedArg).
 
            if (arg == null)
                return null;

            int index; 

            // IMPORTANT!!! This should be done first because CanSmuggleObjectDirectly 
            //   calls GetType() and that would slow this down. 
            MarshalByRefObject mbo = arg as MarshalByRefObject;
            if (mbo != null) 
            {
                // We can only try to smuggle objref's for actual CLR objects
                //   or for RemotingProxy's.
                if (!RemotingServices.IsTransparentProxy(mbo) || 
                    RemotingServices.GetRealProxy(mbo) is RemotingProxy)
                { 
                    ObjRef objRef = RemotingServices.MarshalInternal(mbo, null, null); 
                    if (objRef.CanSmuggle())
                    { 
                        if (!RemotingServices.IsTransparentProxy(mbo))
                        {
                            ServerIdentity srvId = (ServerIdentity)MarshalByRefObject.GetIdentity(mbo);
                            srvId.SetHandle(); 
                            objRef.SetServerIdentity(srvId.GetHandle());
                            objRef.SetDomainID(AppDomain.CurrentDomain.GetId()); 
                        } 
                        ObjRef smugObjRef = objRef.CreateSmuggleableCopy();
                        smugObjRef.SetMarshaledObject(); 
                        return new SmuggledObjRef(smugObjRef);
                    }
                }
 
                // Add this arg to list of one's to serialize and return a placeholder
                //   since we couldn't smuggle the objref. 
                if (argsToSerialize == null) 
                    argsToSerialize = new ArrayList();
                index = argsToSerialize.Count; 
                argsToSerialize.Add(arg);
                return new SerializedArg(index);
            }
 
            if (CanSmuggleObjectDirectly(arg))
                return arg; 
 
            // if this is a primitive array, we can just make a copy.
            //   (IMPORTANT: We can directly use this copy from the 
            //    other app domain, there is no reason to make another
            //    copy once we are on the other side)
            Array array = arg as Array;
            if (array != null) 
            {
                Type elementType = array.GetType().GetElementType(); 
                if (elementType.IsPrimitive || (elementType == typeof(String))) 
                    return array.Clone();
            } 


            // Add this arg to list of one's to serialize and return a placeholder.
            if (argsToSerialize == null) 
                argsToSerialize = new ArrayList();
            index = argsToSerialize.Count; 
            argsToSerialize.Add(arg); 
            return new SerializedArg(index);
        } // FixupArg 


        protected static Object[] UndoFixupArgs(Object[] args, ArrayList deserializedArgs)
        { 
            Object[] newArgs = new Object[args.Length];
            int total = args.Length; 
            for (int co = 0; co < total; co++) 
            {
                newArgs[co] = UndoFixupArg(args[co], deserializedArgs); 
            }

            return newArgs;
        } // UndoFixupArgs 

 
        protected static Object UndoFixupArg(Object arg, ArrayList deserializedArgs) 
        {
            SmuggledObjRef smuggledObjRef = arg as SmuggledObjRef; 
            if (smuggledObjRef != null)
            {
                // We call GetRealObject here ... that covers any
                // special unmarshaling we need to do for _ComObject 
                return smuggledObjRef.ObjRef.GetRealObjectHelper();
            } 
 
            SerializedArg serializedArg = arg as SerializedArg;
            if (serializedArg != null) 
            {
                return deserializedArgs[serializedArg.Index];
            }
 
            return arg;
        } // UndoFixupArg 
 

        // returns number of entries added to argsToSerialize 
        protected static int StoreUserPropertiesForMethodMessage(
            IMethodMessage msg,
            ref ArrayList argsToSerialize)
        { 
            IDictionary properties = msg.Properties;
            MessageDictionary dict = properties as MessageDictionary; 
            if (dict != null) 
            {
                if (dict.HasUserData()) 
                {
                    int co = 0;
                    foreach (DictionaryEntry entry in dict.InternalDictionary)
                    { 
                        if (argsToSerialize == null)
                            argsToSerialize = new ArrayList(); 
                        argsToSerialize.Add(entry); 
                        co++;
                    } 

                    return co;
                }
                else 
                {
                    return 0; 
                } 
            }
            else 
            {
                // <

                int co = 0; 
                foreach (DictionaryEntry entry in properties)
                { 
                    if (argsToSerialize == null) 
                        argsToSerialize = new ArrayList();
                    argsToSerialize.Add(entry); 
                    co++;
                }

                return co; 
            }
        } // StoreUserPropertiesForMethodMessage 
 

        // 
        // Helper classes used to smuggle transformed arguments
        //

        protected class SerializedArg 
        {
            private int _index; 
 
            public SerializedArg(int index)
            { 
                _index = index;
            }

            public int Index { get { return _index; } } 
        }
 
        // 
        // end of Helper classes used to smuggle transformed arguments
        // 

    } // class MessageSmuggler

 

    // stores an object reference 
    internal class SmuggledObjRef 
    {
        ObjRef _objRef; 

        public SmuggledObjRef(ObjRef objRef)
        {
            _objRef = objRef; 
        }
 
        public ObjRef ObjRef { get { return _objRef; } } 
    } // SmuggledObjRef
 



 
    internal class SmuggledMethodCallMessage : MessageSmuggler
    { 
        private String   _uri; 
        private String   _methodName;
        private String   _typeName; 
        private Object[] _args;

        private byte[] _serializedArgs = null;
#if false // This field isn't currently used 
        private Object[] _serializerSmuggledArgs = null;
#endif 
 
        // other things that might need to go through serializer
        private SerializedArg _methodSignature = null; 
        private SerializedArg _instantiation = null;
        private Object        _callContext = null; // either a call id string or a SerializedArg pointing to CallContext object

        private int _propertyCount = 0; //  = # of user properties in dictionary 
                                        //   note: first  entries in _deserializedArgs will be the property entries
 
 
        // always use this helper method to create
        internal static SmuggledMethodCallMessage SmuggleIfPossible(IMessage msg) 
        {
            IMethodCallMessage mcm = msg as IMethodCallMessage;
            if (mcm == null)
                return null; 

            return new SmuggledMethodCallMessage(mcm); 
        } 

        // hide default constructor 
        private SmuggledMethodCallMessage(){}

        private SmuggledMethodCallMessage(IMethodCallMessage mcm)
        { 
            _uri = mcm.Uri;
            _methodName = mcm.MethodName; 
            _typeName = mcm.TypeName; 

            ArrayList argsToSerialize = null; 

            IInternalMessage iim = mcm as IInternalMessage;

            // user properties (everything but special entries) 
            if ((iim == null) || iim.HasProperties())
                _propertyCount = StoreUserPropertiesForMethodMessage(mcm, ref argsToSerialize); 
 
            // generic instantiation information
            if (mcm.MethodBase.IsGenericMethod) 
            {
                Type[] inst = mcm.MethodBase.GetGenericArguments();
                if (inst != null && inst.Length > 0)
                { 
                    if (argsToSerialize == null)
                        argsToSerialize = new ArrayList(); 
                    _instantiation = new SerializedArg(argsToSerialize.Count); 
                    argsToSerialize.Add(inst);
                } 
            }

            // handle method signature
            if (RemotingServices.IsMethodOverloaded(mcm)) 
            {
                if (argsToSerialize == null) 
                    argsToSerialize = new ArrayList(); 
                _methodSignature = new SerializedArg(argsToSerialize.Count);
                argsToSerialize.Add(mcm.MethodSignature); 
            }

            // handle call context
            LogicalCallContext lcc = mcm.LogicalCallContext; 
            if (lcc == null)
            { 
                _callContext = null; 
            }
            else 
            if (lcc.HasInfo)
            {
                if (argsToSerialize == null)
                    argsToSerialize = new ArrayList(); 
                _callContext = new SerializedArg(argsToSerialize.Count);
                argsToSerialize.Add(lcc); 
            } 
            else
            { 
                // just smuggle the call id string
                _callContext = lcc.RemotingData.LogicalCallID;
            }
 
            _args = FixupArgs(mcm.Args, ref argsToSerialize);
 
            if (argsToSerialize != null) 
            {
                //MemoryStream argStm = CrossAppDomainSerializer.SerializeMessageParts(argsToSerialize, out _serializerSmuggledArgs); 
                MemoryStream argStm = CrossAppDomainSerializer.SerializeMessageParts(argsToSerialize);
                _serializedArgs = argStm.GetBuffer();
            }
 
        } // SmuggledMethodCallMessage
 
 
        // returns a list of the deserialized arguments
        internal ArrayList FixupForNewAppDomain() 
        {
            ArrayList deserializedArgs = null;

            if (_serializedArgs != null) 
            {
                deserializedArgs = 
                    CrossAppDomainSerializer.DeserializeMessageParts( 
                        new MemoryStream(_serializedArgs));
                //deserializedArgs = 
                //    CrossAppDomainSerializer.DeserializeMessageParts(
                //        new MemoryStream(_serializedArgs), _serializerSmuggledArgs);
                _serializedArgs = null;
            } 

            return deserializedArgs; 
        } // FixupForNewAppDomain 

 
        internal String Uri { get { return _uri; } }
        internal String MethodName { get { return _methodName; } }
        internal String TypeName { get { return _typeName; } }
 
        internal Type[] GetInstantiation(ArrayList deserializedArgs)
        { 
            if (_instantiation != null) 
                return (Type[])deserializedArgs[_instantiation.Index];
            else 
               return null;
        }

        internal Object[] GetMethodSignature(ArrayList deserializedArgs) 
        {
            if (_methodSignature != null) 
                return (Object[])deserializedArgs[_methodSignature.Index]; 
            else
               return null; 
        }

        internal Object[] GetArgs(ArrayList deserializedArgs)
        { 
            return UndoFixupArgs(_args, deserializedArgs);
        } // GetArgs 
 
        internal LogicalCallContext GetCallContext(ArrayList deserializedArgs)
        { 
            if (_callContext == null)
            {
                return null;
            } 
            if (_callContext is String)
            { 
                LogicalCallContext callContext = new LogicalCallContext(); 
                callContext.RemotingData.LogicalCallID = (String)_callContext;
                return callContext; 
            }
            else
                return (LogicalCallContext)deserializedArgs[((SerializedArg)_callContext).Index];
        } 

        internal int MessagePropertyCount 
        { 
            get { return _propertyCount; }
        } 

        internal void PopulateMessageProperties(IDictionary dict, ArrayList deserializedArgs)
        {
            for (int co = 0; co < _propertyCount; co++) 
            {
                DictionaryEntry de = (DictionaryEntry)deserializedArgs[co]; 
                dict[de.Key] = de.Value; 
            }
        } 

    } // class SmuggledMethodCallMessage

 

    internal class SmuggledMethodReturnMessage : MessageSmuggler 
    { 
        private Object[]  _args;
        private Object    _returnValue; 

        private byte[] _serializedArgs = null;
#if false // This field isn't currently used
        private Object[] _serializerSmuggledArgs = null; 
#endif
 
        // other things that might need to go through serializer 
        private SerializedArg _exception = null;
        private Object        _callContext = null; // either a call id string or a SerializedArg pointing to CallContext object 

        private int _propertyCount; //  = # of user properties in dictionary
                                    //   note: first  entries in _deserializedArgs will be the property entries
 

        // always use this helper method to create 
        internal static SmuggledMethodReturnMessage SmuggleIfPossible(IMessage msg) 
        {
            IMethodReturnMessage mrm = msg as IMethodReturnMessage; 
            if (mrm == null)
                return null;

            return new SmuggledMethodReturnMessage(mrm); 
        }
 
        // hide default constructor 
        private SmuggledMethodReturnMessage(){}
 
        private SmuggledMethodReturnMessage(IMethodReturnMessage mrm)
        {
            ArrayList argsToSerialize = null;
 
            ReturnMessage retMsg = mrm as ReturnMessage;
 
            // user properties (everything but special entries) 
            if ((retMsg == null) || retMsg.HasProperties())
                _propertyCount = StoreUserPropertiesForMethodMessage(mrm, ref argsToSerialize); 

            // handle exception
            Exception excep = mrm.Exception;
            if (excep != null) 
            {
                if (argsToSerialize == null) 
                    argsToSerialize = new ArrayList(); 
                _exception = new SerializedArg(argsToSerialize.Count);
                argsToSerialize.Add(excep); 
            }

            // handle call context
            LogicalCallContext lcc = mrm.LogicalCallContext; 
            if (lcc == null)
            { 
                _callContext = null; 
            }
            else 
            if (lcc.HasInfo)
            {
                if (lcc.Principal != null)
                    lcc.Principal = null; 

                if (argsToSerialize == null) 
                    argsToSerialize = new ArrayList(); 
                _callContext = new SerializedArg(argsToSerialize.Count);
                argsToSerialize.Add(lcc); 
            }
            else
            {
                // just smuggle the call id string 
                _callContext = lcc.RemotingData.LogicalCallID;
            } 
 
            _returnValue = FixupArg(mrm.ReturnValue, ref argsToSerialize);
            _args = FixupArgs(mrm.Args, ref argsToSerialize); 

            if (argsToSerialize != null)
            {
                MemoryStream argStm = CrossAppDomainSerializer.SerializeMessageParts(argsToSerialize); 
                //MemoryStream argStm = CrossAppDomainSerializer.SerializeMessageParts(argsToSerialize, out _serializerSmuggledArgs);
                _serializedArgs = argStm.GetBuffer(); 
            } 

        } // SmuggledMethodReturnMessage 


        internal ArrayList FixupForNewAppDomain()
        { 
            ArrayList deserializedArgs = null;
 
            if (_serializedArgs != null) 
            {
                deserializedArgs = 
                    CrossAppDomainSerializer.DeserializeMessageParts(
                        new MemoryStream(_serializedArgs));
                //deserializedArgs =
                //    CrossAppDomainSerializer.DeserializeMessageParts( 
                //        new MemoryStream(_serializedArgs), _serializerSmuggledArgs);
                _serializedArgs = null; 
            } 

            return deserializedArgs; 
        } // FixupForNewAppDomain

        internal Object GetReturnValue(ArrayList deserializedArgs)
        { 
            return UndoFixupArg(_returnValue, deserializedArgs);
        } // GetReturnValue 
 
        internal Object[] GetArgs(ArrayList deserializedArgs)
        { 
            Object[] obj = UndoFixupArgs(_args, deserializedArgs);
            return obj;
        } // GetArgs
 
        internal Exception GetException(ArrayList deserializedArgs)
        { 
            if (_exception != null) 
                return (Exception)deserializedArgs[_exception.Index];
            else 
                return null;
        } // Exception

        internal LogicalCallContext GetCallContext(ArrayList deserializedArgs) 
        {
            if (_callContext == null) 
            { 
                return null;
            } 
            if (_callContext is String)
            {
                LogicalCallContext callContext = new LogicalCallContext();
                callContext.RemotingData.LogicalCallID = (String)_callContext; 
                return callContext;
            } 
            else 
                return (LogicalCallContext)deserializedArgs[((SerializedArg)_callContext).Index];
        } 

        internal int MessagePropertyCount
        {
            get { return _propertyCount; } 
        }
 
        internal void PopulateMessageProperties(IDictionary dict, ArrayList deserializedArgs) 
        {
            for (int co = 0; co < _propertyCount; co++) 
            {
                DictionaryEntry de = (DictionaryEntry)deserializedArgs[co];
                dict[de.Key] = de.Value;
            } 
        }
 
    } // class SmuggledMethodReturnMessage 

 
} // namespace System.Runtime.Remoting.Messaging
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK