We need you! We're working hard on the next version of Developer Fusion - Let us know what you think we should be up to!

The Labs \ Source Viewer \ SSCLI \ System.Runtime.Remoting.Channels \ ChannelServices

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. //* File: Channel.cs
  16. //*
  17. //*
  18. //*
  19. //* Purpose: Defines the general purpose remoting proxy
  20. //*
  21. //* Date: May 27, 1999
  22. //*
  23. namespace System.Runtime.Remoting.Channels
  24. {
  25.     using System;
  26.     using System.Collections;
  27.     using System.IO;
  28.     using System.Reflection;
  29.     using System.Runtime.CompilerServices;
  30.     using System.Runtime.InteropServices;
  31.     using System.Runtime.Remoting;
  32.     using System.Runtime.Remoting.Activation;
  33.     using System.Runtime.Remoting.Messaging;
  34.     using System.Runtime.Remoting.Metadata;
  35.     using System.Runtime.Remoting.Proxies;
  36.     using System.Threading;
  37.     using System.Security.Permissions;
  38.     using System.Globalization;
  39.    
  40.     // ChannelServices
  41.    
  42.     [System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
  43.     internal struct Perf_Contexts
  44.     {
  45.         internal int cRemoteCalls;
  46.         internal int cChannels;
  47.     }
  48.    
  49.     [System.Runtime.InteropServices.ComVisible(true)]
  50.     public sealed class ChannelServices
  51.     {
  52.         // This gets refreshed when a channel is registered/unregistered.
  53.         private static object[] s_currentChannelData = null;
  54.        
  55.         static internal object[] CurrentChannelData {
  56.             get {
  57.                 if (s_currentChannelData == null)
  58.                     RefreshChannelData();
  59.                
  60.                 return s_currentChannelData;
  61.             }
  62.         }
  63.         // CurrentChannelData
  64.        
  65.         // hide the default constructor
  66.         private ChannelServices()
  67.         {
  68.         }
  69.        
  70.         // list of registered channels and a lock to take when adding or removing channels
  71.         private static object s_channelLock = new object();
  72.         private static RegisteredChannelList s_registeredChannels = new RegisteredChannelList();
  73.        
  74.        
  75.         // Private member variables
  76.         // These have all been converted to getters and setters to get the effect of
  77.         // per-AppDomain statics (note: statics are per-AppDomain now, so these members
  78.         // could just be declared as statics on ChannelServices).
  79.        
  80.         private static long remoteCalls {
  81.             get { return Thread.GetDomain().RemotingData.ChannelServicesData.remoteCalls; }
  82.             set { Thread.GetDomain().RemotingData.ChannelServicesData.remoteCalls = value; }
  83.         }
  84.        
  85.         private static IMessageSink xCtxChannel;
  86.        
  87.        
  88.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  89.         unsafe static extern Perf_Contexts* GetPrivateContextsPerfCounters();
  90.        
  91.         unsafe private static Perf_Contexts* perf_Contexts = GetPrivateContextsPerfCounters();
  92.        
  93.        
  94.         [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.RemotingConfiguration)]
  95.         public static void RegisterChannel(IChannel chnl, bool ensureSecurity)
  96.         {
  97.             RegisterChannelInternal(chnl, ensureSecurity);
  98.         }
  99.        
  100.         [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.RemotingConfiguration)]
  101.         [Obsolete("Use System.Runtime.Remoting.ChannelServices.RegisterChannel(IChannel chnl, bool ensureSecurity) instead.", false)]
  102.         public static void RegisterChannel(IChannel chnl)
  103.         {
  104.                 /*ensureSecurity*/            RegisterChannelInternal(chnl, false);
  105.         }
  106.        
  107.        
  108.         static bool unloadHandlerRegistered = false;
  109.         unsafe static internal void RegisterChannelInternal(IChannel chnl, bool ensureSecurity)
  110.         {
  111.             // Validate arguments
  112.             if (null == chnl) {
  113.                 throw new ArgumentNullException("chnl");
  114.             }
  115.            
  116.             bool fLocked = false;
  117.             RuntimeHelpers.PrepareConstrainedRegions();
  118.             try {
  119.                 Monitor.ReliableEnter(s_channelLock, ref fLocked);
  120.                 string chnlName = chnl.ChannelName;
  121.                
  122.                 RegisteredChannelList regChnlList = s_registeredChannels;
  123.                
  124.                 // Check to make sure that the channel has not been registered
  125.                 if ((chnlName == null) || (chnlName.Length == 0) || (-1 == regChnlList.FindChannelIndex(chnl.ChannelName))) {
  126.                     if (ensureSecurity) {
  127.                         ISecurableChannel securableChannel = chnl as ISecurableChannel;
  128.                         if (securableChannel != null)
  129.                             securableChannel.IsSecured = ensureSecurity;
  130.                         else
  131.                             throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Channel_CannotBeSecured"), chnl.ChannelName ?? chnl.ToString()));
  132.                        
  133.                     }
  134.                     RegisteredChannel[] oldList = regChnlList.RegisteredChannels;
  135.                     RegisteredChannel[] newList = null;
  136.                     if (oldList == null) {
  137.                         newList = new RegisteredChannel[1];
  138.                     }
  139.                     else
  140.                         newList = new RegisteredChannel[oldList.Length + 1];
  141.                    
  142.                     if (!unloadHandlerRegistered && !(chnl is CrossAppDomainChannel)) {
  143.                         // Register a unload handler only once and if the channel being registered
  144.                         // is not the x-domain channel. x-domain channel does nothing inside its
  145.                         // StopListening implementation
  146.                         AppDomain.CurrentDomain.DomainUnload += new EventHandler(UnloadHandler);
  147.                         unloadHandlerRegistered = true;
  148.                     }
  149.                    
  150.                     // Add the interface to the array in priority order
  151.                     int priority = chnl.ChannelPriority;
  152.                     int current = 0;
  153.                    
  154.                     // Find the place in the array to insert
  155.                     while (current < oldList.Length) {
  156.                         RegisteredChannel oldChannel = oldList[current];
  157.                         if (priority > oldChannel.Channel.ChannelPriority) {
  158.                             newList[current] = new RegisteredChannel(chnl);
  159.                             break;
  160.                         }
  161.                         else {
  162.                             newList[current] = oldChannel;
  163.                             current++;
  164.                         }
  165.                     }
  166.                    
  167.                     if (current == oldList.Length) {
  168.                         // chnl has lower priority than all old channels, so we insert
  169.                         // it at the end of the list.
  170.                         newList[oldList.Length] = new RegisteredChannel(chnl);
  171.                     }
  172.                     else {
  173.                         // finish copying rest of the old channels
  174.                         while (current < oldList.Length) {
  175.                             newList[current + 1] = oldList[current];
  176.                             current++;
  177.                         }
  178.                     }
  179.                    
  180.                     if (perf_Contexts != null) {
  181.                         perf_Contexts->cChannels++;
  182.                     }
  183.                    
  184.                     s_registeredChannels = new RegisteredChannelList(newList);
  185.                 }
  186.                 else {
  187.                     throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_ChannelNameAlreadyRegistered"), chnl.ChannelName));
  188.                 }
  189.                
  190.                 RefreshChannelData();
  191.             }
  192.             // lock (s_channelLock)
  193.             finally {
  194.                 if (fLocked) {
  195.                     Monitor.Exit(s_channelLock);
  196.                 }
  197.             }
  198.         }
  199.         // RegisterChannelInternal
  200.        
  201.         [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.RemotingConfiguration)]
  202.         unsafe public static void UnregisterChannel(IChannel chnl)
  203.         {
  204.             // we allow null to be passed in, so we can use this api to trigger the
  205.             // refresh of the channel data
  206.            
  207.             bool fLocked = false;
  208.             RuntimeHelpers.PrepareConstrainedRegions();
  209.             try {
  210.                 Monitor.ReliableEnter(s_channelLock, ref fLocked);
  211.                 if (chnl != null) {
  212.                     RegisteredChannelList regChnlList = s_registeredChannels;
  213.                    
  214.                     // Check to make sure that the channel has been registered
  215.                     int matchingIdx = regChnlList.FindChannelIndex(chnl);
  216.                     if (-1 == matchingIdx) {
  217.                         throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_ChannelNotRegistered"), chnl.ChannelName));
  218.                     }
  219.                    
  220.                     RegisteredChannel[] oldList = regChnlList.RegisteredChannels;
  221.                     RegisteredChannel[] newList = null;
  222.                     BCLDebug.Assert((oldList != null) && (oldList.Length != 0), "channel list should not be empty");
  223.                    
  224.                     newList = new RegisteredChannel[oldList.Length - 1];
  225.                    
  226.                     // Call stop listening on the channel if it is a receiver.
  227.                     IChannelReceiver srvChannel = chnl as IChannelReceiver;
  228.                     if (srvChannel != null)
  229.                         srvChannel.StopListening(null);
  230.                    
  231.                     int current = 0;
  232.                     int oldPos = 0;
  233.                     while (oldPos < oldList.Length) {
  234.                         if (oldPos == matchingIdx) {
  235.                             oldPos++;
  236.                         }
  237.                         else {
  238.                             newList[current] = oldList[oldPos];
  239.                             current++;
  240.                             oldPos++;
  241.                         }
  242.                     }
  243.                    
  244.                     if (perf_Contexts != null) {
  245.                         perf_Contexts->cChannels--;
  246.                     }
  247.                    
  248.                     s_registeredChannels = new RegisteredChannelList(newList);
  249.                 }
  250.                
  251.                 RefreshChannelData();
  252.             }
  253.             // lock (s_channelLock)
  254.             finally {
  255.                 if (fLocked) {
  256.                     Monitor.Exit(s_channelLock);
  257.                 }
  258.             }
  259.         }
  260.         // UnregisterChannel
  261.        
  262.         public static IChannel[] RegisteredChannels {
  263.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  264.             get {
  265.                 RegisteredChannelList regChnlList = s_registeredChannels;
  266.                 int count = regChnlList.Count;
  267.                
  268.                 if (0 == count) {
  269.                     return new IChannel[0];
  270.                 }
  271.                 else {
  272.                     // we hide the CrossAppDomainChannel, so the number of visible
  273.                     // channels is one less than the number of registered channels.
  274.                     int visibleChannels = count - 1;
  275.                    
  276.                     // Copy the array of visible channels into a new array
  277.                     // and return
  278.                     int co = 0;
  279.                     IChannel[] temp = new IChannel[visibleChannels];
  280.                     for (int i = 0; i < count; i++) {
  281.                         IChannel channel = regChnlList.GetChannel(i);
  282.                         // add the channel to the array if it is not the CrossAppDomainChannel
  283.                         if (!(channel is CrossAppDomainChannel))
  284.                             temp[co++] = channel;
  285.                     }
  286.                     return temp;
  287.                 }
  288.             }
  289.         }
  290.         // RegisteredChannels
  291.         static internal IMessageSink CreateMessageSink(string url, object data, out string objectURI)
  292.         {
  293.             BCLDebug.Trace("REMOTE", "ChannelServices::CreateMessageSink for url " + url + "\n");
  294.             IMessageSink msgSink = null;
  295.             objectURI = null;
  296.            
  297.             RegisteredChannelList regChnlList = s_registeredChannels;
  298.             int count = regChnlList.Count;
  299.            
  300.             for (int i = 0; i < count; i++) {
  301.                 if (regChnlList.IsSender(i)) {
  302.                     IChannelSender chnl = (IChannelSender)regChnlList.GetChannel(i);
  303.                     msgSink = chnl.CreateMessageSink(url, data, out objectURI);
  304.                    
  305.                     if (msgSink != null)
  306.                         break;
  307.                 }
  308.             }
  309.            
  310.             // If the object uri has not been set, set it to the url as
  311.             // default value
  312.             if (null == objectURI) {
  313.                 objectURI = url;
  314.             }
  315.            
  316.             return msgSink;
  317.         }
  318.         // CreateMessageSink
  319.         static internal IMessageSink CreateMessageSink(object data)
  320.         {
  321.             string objectUri;
  322.             return CreateMessageSink(null, data, out objectUri);
  323.         }
  324.         // CreateMessageSink
  325.        
  326.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  327.         public static IChannel GetChannel(string name)
  328.         {
  329.             RegisteredChannelList regChnlList = s_registeredChannels;
  330.            
  331.             int matchingIdx = regChnlList.FindChannelIndex(name);
  332.             if (0 <= matchingIdx) {
  333.                 IChannel channel = regChnlList.GetChannel(matchingIdx);
  334.                 if ((channel is CrossAppDomainChannel) || (channel is CrossContextChannel))
  335.                     return null;
  336.                 else
  337.                     return channel;
  338.             }
  339.             else {
  340.                 return null;
  341.             }
  342.         }
  343.         // GetChannel
  344.        
  345.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  346.         public static string[] GetUrlsForObject(MarshalByRefObject obj)
  347.         {
  348.             if (null == obj) {
  349.                 return null;
  350.             }
  351.            
  352.             RegisteredChannelList regChnlList = s_registeredChannels;
  353.             int count = regChnlList.Count;
  354.            
  355.             Hashtable table = new Hashtable();
  356.             bool fServer;
  357.             Identity id = MarshalByRefObject.GetIdentity(obj, out fServer);
  358.            
  359.             if (null != id) {
  360.                 string uri = id.ObjURI;
  361.                
  362.                 if (null != uri) {
  363.                     for (int i = 0; i < count; i++) {
  364.                         if (regChnlList.IsReceiver(i)) {
  365.                             try {
  366.                                 string[] urls = ((IChannelReceiver)regChnlList.GetChannel(i)).GetUrlsForUri(uri);
  367.                                 // Add the strings to the table
  368.                                 for (int j = 0; j < urls.Length; j++) {
  369.                                     table.Add(urls[j], urls[j]);
  370.                                 }
  371.                             }
  372.                             catch (NotSupportedException) {
  373.                                 // We do not count the channels that do not
  374.                                 // support this method
  375.                             }
  376.                         }
  377.                     }
  378.                 }
  379.             }
  380.            
  381.             // copy url's into string array
  382.             ICollection keys = table.Keys;
  383.             string[] urlList = new string[keys.Count];
  384.             int co = 0;
  385.             foreach (string key in keys) {
  386.                 urlList[co++] = key;
  387.             }
  388.             return urlList;
  389.         }
  390.        
  391.         // Find the channel message sink associated with a given proxy
  392.         static internal IMessageSink GetChannelSinkForProxy(object obj)
  393.         {
  394.             IMessageSink sink = null;
  395.             if (RemotingServices.IsTransparentProxy(obj)) {
  396.                 RealProxy rp = RemotingServices.GetRealProxy(obj);
  397.                 RemotingProxy remProxy = rp as RemotingProxy;
  398.                 if (null != remProxy) {
  399.                     Identity idObj = remProxy.IdentityObject;
  400.                     BCLDebug.Assert(null != idObj, "null != idObj");
  401.                     sink = idObj.ChannelSink;
  402.                 }
  403.             }
  404.            
  405.             return sink;
  406.         }
  407.         // GetChannelSinkForProxy
  408.        
  409.         // Get the message sink dictionary of properties for a given proxy
  410.        
  411.         [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.RemotingConfiguration)]
  412.         public static IDictionary GetChannelSinkProperties(object obj)
  413.         {
  414.             IMessageSink sink = GetChannelSinkForProxy(obj);
  415.             IClientChannelSink chnlSink = sink as IClientChannelSink;
  416.             if (null != chnlSink) {
  417.                 // collect dictionaries for all channel sinks and return
  418.                 // aggregate dictionary
  419.                 ArrayList dictionaries = new ArrayList();
  420.                
  421.                 do {
  422.                     IDictionary dict = chnlSink.Properties;
  423.                     if (dict != null)
  424.                         dictionaries.Add(dict);
  425.                    
  426.                     chnlSink = chnlSink.NextChannelSink;
  427.                 }
  428.                 while (chnlSink != null);
  429.                
  430.                 return new AggregateDictionary(dictionaries);
  431.             }
  432.             else {
  433.                 IDictionary dict = sink as IDictionary;
  434.                 if (null != dict) {
  435.                     return dict;
  436.                 }
  437.                 else {
  438.                     return null;
  439.                 }
  440.             }
  441.         }
  442.         // GetChannelSinkProperties
  443.        
  444.         static internal IMessageSink GetCrossContextChannelSink()
  445.         {
  446.             if (null == xCtxChannel) {
  447.                 xCtxChannel = CrossContextChannel.MessageSink;
  448.             }
  449.            
  450.             return xCtxChannel;
  451.         }
  452.         // GetCrossContextChannelSink
  453.        
  454.         #if DEBUG
  455.         // A few methods to count the number of calls made across appdomains,
  456.         // processes and machines
  457.         static internal long GetNumberOfRemoteCalls()
  458.         {
  459.             return remoteCalls;
  460.         }
  461.         // GetNumberOfRemoteCalls
  462.         #endif //DEBUG
  463.         unsafe static internal void IncrementRemoteCalls(long cCalls)
  464.         {
  465.             remoteCalls += cCalls;
  466.             if (perf_Contexts != null)
  467.                 perf_Contexts->cRemoteCalls += (int)cCalls;
  468.         }
  469.         // IncrementRemoteCalls
  470.         static internal void IncrementRemoteCalls()
  471.         {
  472.             IncrementRemoteCalls(1);
  473.         }
  474.         // IncrementRemoteCalls
  475.        
  476.         static internal void RefreshChannelData()
  477.         {
  478.             bool fLocked = false;
  479.             RuntimeHelpers.PrepareConstrainedRegions();
  480.             try {
  481.                 Monitor.ReliableEnter(s_channelLock, ref fLocked);
  482.                 s_currentChannelData = CollectChannelDataFromChannels();
  483.             }
  484.             finally {
  485.                 if (fLocked) {
  486.                     Monitor.Exit(s_channelLock);
  487.                 }
  488.             }
  489.         }
  490.         // RefreshChannelData
  491.         private static object[] CollectChannelDataFromChannels()
  492.         {
  493.             // Ensure that our native cross-context & cross-domain channels
  494.             // are registered
  495.             RemotingServices.RegisterWellKnownChannels();
  496.            
  497.             RegisteredChannelList regChnlList = s_registeredChannels;
  498.             int count = regChnlList.Count;
  499.            
  500.             // Compute the number of channels that implement IChannelReceiver
  501.             int numChnls = regChnlList.ReceiverCount;
  502.            
  503.             // Allocate array for channel data
  504.             object[] data = new object[numChnls];
  505.            
  506.             // we need to remove null entries
  507.             int nonNullDataCount = 0;
  508.            
  509.             // Set the channel data, names and mime types
  510.             for (int i = 0int j = 0; i < count; i++) {
  511.                
  512.                 IChannel chnl = regChnlList.GetChannel(i);
  513.                
  514.                 if (null == chnl) {
  515.                     throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_ChannelNotRegistered"), ""));
  516.                 }
  517.                
  518.                 if (regChnlList.IsReceiver(i)) {
  519.                     BCLDebug.Trace("REMOTE", "Setting info for receiver " + j + "\n");
  520.                     // Extract the data
  521.                     object channelData = ((IChannelReceiver)chnl).ChannelData;
  522.                     data[j] = channelData;
  523.                     if (channelData != null)
  524.                         nonNullDataCount++;
  525.                    
  526.                     // Increment the counter
  527.                     j++;
  528.                 }
  529.             }
  530.            
  531.             if (nonNullDataCount != numChnls) {
  532.                 // there were null entries, so remove them.
  533.                 object[] nonNullData = new object[nonNullDataCount];
  534.                 int nonNullCounter = 0;
  535.                 for (int co = 0; co < numChnls; co++) {
  536.                     object channelData = data[co];
  537.                     if (channelData != null)
  538.                         nonNullData[nonNullCounter++] = channelData;
  539.                 }
  540.                
  541.                 data = nonNullData;
  542.             }
  543.            
  544.             return data;
  545.         }
  546.         // CollectChannelDataFromChannels
  547.         // Checks to make sure the remote method being invoked is callable
  548.         static bool IsMethodReallyPublic(MethodInfo mi)
  549.         {
  550.             if (!mi.IsPublic || mi.IsStatic)
  551.                 return false;
  552.            
  553.             if (!mi.IsGenericMethod)
  554.                 return true;
  555.            
  556.             foreach (Type t in mi.GetGenericArguments())
  557.                 if (!t.IsVisible)
  558.                     return false;
  559.            
  560.             return true;
  561.         }
  562.        
  563.         //--------------------------------------------------------------------
  564.         //----------------------- Dispatch Support ------------------------
  565.         //--------------------------------------------------------------------
  566.        
  567.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  568.         public static ServerProcessing DispatchMessage(IServerChannelSinkStack sinkStack, IMessage msg, out IMessage replyMsg)
  569.         {
  570.             ServerProcessing processing = ServerProcessing.Complete;
  571.             replyMsg = null;
  572.            
  573.             try {
  574.                 if (null == msg) {
  575.                     throw new ArgumentNullException("msg");
  576.                 }
  577.                
  578.                 BCLDebug.Trace("REMOTE", "Dispatching for URI " + InternalSink.GetURI(msg));
  579.                
  580.                 // we must switch to the target context of the object and call the context chains etc...
  581.                 // Currenly XContextChannel does exactly so. So this method is just a wrapper..
  582.                
  583.                
  584.                 // Make sure that incoming calls are counted as a remote call. This way it
  585.                 // makes more sense on a server.
  586.                 IncrementRemoteCalls();
  587.                
  588.                 // Check if the object has been disconnected or if it is
  589.                 // a well known object then we have to create it lazily.
  590.                 ServerIdentity srvId = CheckDisconnectedOrCreateWellKnownObject(msg);
  591.                
  592.                 // Make sure that this isn't an AppDomain object since we don't allow
  593.                 // calls to the AppDomain from out of process (and x-process calls
  594.                 // are always dispatched through this method)
  595.                 if (srvId.ServerType == typeof(System.AppDomain)) {
  596.                     throw new RemotingException(Environment.GetResourceString("Remoting_AppDomainsCantBeCalledRemotely"));
  597.                 }
  598.                
  599.                
  600.                 IMethodCallMessage mcm = msg as IMethodCallMessage;
  601.                
  602.                 if (mcm == null) {
  603.                     // It's a plain IMessage, so just check to make sure that the
  604.                     // target object implements IMessageSink and dispatch synchronously.
  605.                    
  606.                     if (!typeof(IMessageSink).IsAssignableFrom(srvId.ServerType)) {
  607.                         throw new RemotingException(Environment.GetResourceString("Remoting_AppDomainsCantBeCalledRemotely"));
  608.                     }
  609.                    
  610.                     processing = ServerProcessing.Complete;
  611.                     replyMsg = ChannelServices.GetCrossContextChannelSink().SyncProcessMessage(msg);
  612.                 }
  613.                 else {
  614.                     // It's an IMethodCallMessage.
  615.                    
  616.                     // Check if the method is one way. Dispatch one way calls in
  617.                     // an asynchronous manner
  618.                     MethodInfo method = (MethodInfo)mcm.MethodBase;
  619.                    
  620.                     // X-process / X-machine calls should be to non-static
  621.                     // public methods only! Non-public or static methods can't
  622.                     // be called remotely.
  623.                     if (!IsMethodReallyPublic(method) && !RemotingServices.IsMethodAllowedRemotely(method)) {
  624.                         throw new RemotingException(Environment.GetResourceString("Remoting_NonPublicOrStaticCantBeCalledRemotely"));
  625.                     }
  626.                    
  627.                     RemotingMethodCachedData cache = (RemotingMethodCachedData)InternalRemotingServices.GetReflectionCachedData(method);
  628.                    
  629.                     /*
  630.                         FUTURE:
  631.                         Dispatching asynchronously was cut from v1. We should reactivate
  632.                         the following code in v1.x or v2.
  633.                    
  634.                     // look for async method version             
  635.                     MethodInfo begin;
  636.                     MethodInfo end;
  637.                     ServerChannelSinkStack serverSinkStack = sinkStack as ServerChannelSinkStack;
  638.                     if ((sinkStack != null) &&
  639.                         cache.GetAsyncMethodVersion(out begin, out end))
  640.                     {
  641.                         processing = ServerProcessing.Async;
  642.                         IMessage asyncMsg =
  643.                             new AsyncMethodCallMessageWrapper(
  644.                                 (IMethodCallMessage)msg,
  645.                                 begin,
  646.                                 new AsyncCallback(sinkStack.ServerCallback),
  647.                                 null);
  648.                         serverSinkStack.AsyncMessage = asyncMsg;           
  649.                         serverSinkStack.AsyncEnd = end;
  650.                         serverSinkStack.Message = (IMethodCallMessage)msg;
  651.                         asyncMsg.Properties["__SinkStack"] = sinkStack;
  652.    
  653.                         // We don't dispatch yet. That happens when the server transport sink
  654.                         //  eventually calls sinkStack.StoreAndDispatch(...).
  655.                     }
  656.                     else
  657.                     */                   
  658. if (RemotingServices.IsOneWay(method)) {
  659.                         processing = ServerProcessing.OneWay;
  660.                         ChannelServices.GetCrossContextChannelSink().AsyncProcessMessage(msg, null);
  661.                     }
  662.                     else {
  663.                         // regular processing
  664.                         processing = ServerProcessing.Complete;
  665.                         if (!srvId.ServerType.IsContextful) {
  666.                             object[] args = new object[] {msg, srvId.ServerContext};
  667.     &nbs