1 using System.Diagnostics.Contracts;
4 // Copyright (c) Microsoft Corporation. All rights reserved.
9 //* <EMAIL>Author: Tarun Anand (Microsoft)</EMAIL>
11 //* Purpose: Defines the general purpose remoting proxy
13 //* Date: May 27, 1999
15 namespace System.Runtime.Remoting.Channels {
17 using System.Collections;
19 using System.Reflection;
20 using System.Runtime.CompilerServices;
21 using System.Runtime.InteropServices;
22 using System.Runtime.Remoting;
23 using System.Runtime.Remoting.Activation;
24 using System.Runtime.Remoting.Messaging;
25 using System.Runtime.Remoting.Metadata;
26 using System.Runtime.Remoting.Proxies;
27 using System.Runtime.Versioning;
28 using System.Threading;
29 using System.Security;
30 using System.Security.Permissions;
31 using System.Globalization;
35 [System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
36 internal struct Perf_Contexts {
37 internal volatile int cRemoteCalls;
38 internal volatile int cChannels;
41 [System.Runtime.InteropServices.ComVisible(true)]
42 public sealed class ChannelServices
44 // This gets refreshed when a channel is registered/unregistered.
45 private static volatile Object[] s_currentChannelData = null;
47 [System.Security.SecuritySafeCritical] // static constructors should be safe to call
48 static ChannelServices()
52 internal static Object[] CurrentChannelData
54 [System.Security.SecurityCritical] // auto-generated
57 if (s_currentChannelData == null)
60 return s_currentChannelData;
62 } // CurrentChannelData
65 // hide the default constructor
66 private ChannelServices()
70 // list of registered channels and a lock to take when adding or removing channels
71 // Note that the channel list is read outside of the lock, which is why it's marked volatile.
72 private static Object s_channelLock = new Object();
73 private static volatile RegisteredChannelList s_registeredChannels = new RegisteredChannelList();
76 // Private member variables
77 // These have all been converted to getters and setters to get the effect of
78 // per-AppDomain statics (note: statics are per-AppDomain now, so these members
79 // could just be declared as statics on ChannelServices).
81 private static long remoteCalls
83 get { return Thread.GetDomain().RemotingData.ChannelServicesData.remoteCalls; }
84 set { Thread.GetDomain().RemotingData.ChannelServicesData.remoteCalls = value; }
87 private static volatile IMessageSink xCtxChannel;
90 [System.Security.SecurityCritical] // auto-generated
91 [MethodImplAttribute(MethodImplOptions.InternalCall)]
92 [ResourceExposure(ResourceScope.None)]
93 static unsafe extern Perf_Contexts* GetPrivateContextsPerfCounters();
96 unsafe private static volatile Perf_Contexts *perf_Contexts = GetPrivateContextsPerfCounters();
99 [System.Security.SecuritySafeCritical] // auto-generated
100 [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration)]
101 public static void RegisterChannel(IChannel chnl, bool ensureSecurity)
103 RegisterChannelInternal(chnl, ensureSecurity);
106 [System.Security.SecuritySafeCritical] // auto-generated
107 [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration)]
108 [Obsolete("Use System.Runtime.Remoting.ChannelServices.RegisterChannel(IChannel chnl, bool ensureSecurity) instead.", false)]
109 public static void RegisterChannel(IChannel chnl)
111 RegisterChannelInternal(chnl, false/*ensureSecurity*/);
115 static bool unloadHandlerRegistered = false;
116 [System.Security.SecurityCritical] // auto-generated
117 unsafe internal static void RegisterChannelInternal(IChannel chnl, bool ensureSecurity)
119 // Validate arguments
122 throw new ArgumentNullException("chnl");
124 Contract.EndContractBlock();
126 bool fLocked = false;
127 RuntimeHelpers.PrepareConstrainedRegions();
130 Monitor.Enter(s_channelLock, ref fLocked);
131 String chnlName = chnl.ChannelName;
133 RegisteredChannelList regChnlList = s_registeredChannels;
135 // Check to make sure that the channel has not been registered
136 if((chnlName == null) ||
137 (chnlName.Length == 0) ||
138 (-1 == regChnlList.FindChannelIndex(chnl.ChannelName)))
142 ISecurableChannel securableChannel = chnl as ISecurableChannel;
143 if (securableChannel != null)
144 securableChannel.IsSecured = ensureSecurity;
146 throw new RemotingException(Environment.GetResourceString("Remoting_Channel_CannotBeSecured", chnl.ChannelName??chnl.ToString()));
149 RegisteredChannel[] oldList = regChnlList.RegisteredChannels;
150 RegisteredChannel[] newList = null;
153 newList = new RegisteredChannel[1];
156 newList = new RegisteredChannel[oldList.Length + 1];
158 if (!unloadHandlerRegistered && !(chnl is CrossAppDomainChannel))
160 // Register a unload handler only once and if the channel being registered
161 // is not the x-domain channel. x-domain channel does nothing inside its
162 // StopListening implementation
163 AppDomain.CurrentDomain.DomainUnload += new EventHandler(UnloadHandler);
164 unloadHandlerRegistered = true;
167 // Add the interface to the array in priority order
168 int priority = chnl.ChannelPriority;
171 // Find the place in the array to insert
172 while (current < oldList.Length)
174 RegisteredChannel oldChannel = oldList[current];
175 if (priority > oldChannel.Channel.ChannelPriority)
177 newList[current] = new RegisteredChannel(chnl);
182 newList[current] = oldChannel;
187 if (current == oldList.Length)
189 // chnl has lower priority than all old channels, so we insert
190 // it at the end of the list.
191 newList[oldList.Length] = new RegisteredChannel(chnl);
195 // finish copying rest of the old channels
196 while (current < oldList.Length)
198 newList[current + 1] = oldList[current];
203 if (perf_Contexts != null) {
204 perf_Contexts->cChannels++;
207 s_registeredChannels = new RegisteredChannelList(newList);
211 throw new RemotingException(Environment.GetResourceString("Remoting_ChannelNameAlreadyRegistered", chnl.ChannelName));
214 RefreshChannelData();
215 } // lock (s_channelLock)
220 Monitor.Exit(s_channelLock);
223 } // RegisterChannelInternal
226 [System.Security.SecuritySafeCritical] // auto-generated
227 [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration)]
228 unsafe public static void UnregisterChannel(IChannel chnl)
230 // we allow null to be passed in, so we can use this api to trigger the
231 // refresh of the channel data <
234 bool fLocked = false;
235 RuntimeHelpers.PrepareConstrainedRegions();
238 Monitor.Enter(s_channelLock, ref fLocked);
241 RegisteredChannelList regChnlList = s_registeredChannels;
243 // Check to make sure that the channel has been registered
244 int matchingIdx = regChnlList.FindChannelIndex(chnl);
245 if(-1 == matchingIdx)
247 throw new RemotingException(Environment.GetResourceString("Remoting_ChannelNotRegistered", chnl.ChannelName));
250 RegisteredChannel[] oldList = regChnlList.RegisteredChannels;
251 RegisteredChannel[] newList = null;
252 Contract.Assert((oldList != null) && (oldList.Length != 0), "channel list should not be empty");
254 newList = new RegisteredChannel[oldList.Length - 1];
256 // Call stop listening on the channel if it is a receiver.
257 IChannelReceiver srvChannel = chnl as IChannelReceiver;
258 if (srvChannel != null)
259 srvChannel.StopListening(null);
263 while (oldPos < oldList.Length)
265 if (oldPos == matchingIdx)
271 newList[current] = oldList[oldPos];
277 if (perf_Contexts != null) {
278 perf_Contexts->cChannels--;
281 s_registeredChannels = new RegisteredChannelList(newList);
284 RefreshChannelData();
285 } // lock (s_channelLock)
290 Monitor.Exit(s_channelLock);
293 } // UnregisterChannel
296 public static IChannel[] RegisteredChannels
298 [System.Security.SecurityCritical] // auto-generated_required
301 RegisteredChannelList regChnlList = s_registeredChannels;
302 int count = regChnlList.Count;
306 return new IChannel[0];
310 // we hide the CrossAppDomainChannel, so the number of visible
311 // channels is one less than the number of registered channels.
312 int visibleChannels = count - 1;
314 // Copy the array of visible channels into a new array
317 IChannel[] temp = new IChannel[visibleChannels];
318 for (int i = 0; i < count; i++)
320 IChannel channel = regChnlList.GetChannel(i);
321 // add the channel to the array if it is not the CrossAppDomainChannel
322 if (!(channel is CrossAppDomainChannel))
323 temp[co++] = channel;
328 } // RegisteredChannels
330 [System.Security.SecurityCritical] // auto-generated
331 internal static IMessageSink CreateMessageSink(String url, Object data, out String objectURI)
333 BCLDebug.Trace("REMOTE", "ChannelServices::CreateMessageSink for url " + url + "\n");
334 IMessageSink msgSink = null;
337 RegisteredChannelList regChnlList = s_registeredChannels;
338 int count = regChnlList.Count;
340 for(int i = 0; i < count; i++)
342 if(regChnlList.IsSender(i))
344 IChannelSender chnl = (IChannelSender)regChnlList.GetChannel(i);
345 msgSink = chnl.CreateMessageSink(url, data, out objectURI);
352 // If the object uri has not been set, set it to the url as
354 if(null == objectURI)
360 } // CreateMessageSink
362 [System.Security.SecurityCritical] // auto-generated
363 internal static IMessageSink CreateMessageSink(Object data)
366 return CreateMessageSink(null, data, out objectUri);
367 } // CreateMessageSink
370 [System.Security.SecurityCritical] // auto-generated_required
371 public static IChannel GetChannel(String name)
373 RegisteredChannelList regChnlList = s_registeredChannels;
375 int matchingIdx = regChnlList.FindChannelIndex(name);
378 IChannel channel = regChnlList.GetChannel(matchingIdx);
379 if ((channel is CrossAppDomainChannel) || (channel is CrossContextChannel))
391 [System.Security.SecurityCritical] // auto-generated_required
392 public static String[] GetUrlsForObject(MarshalByRefObject obj)
399 RegisteredChannelList regChnlList = s_registeredChannels;
400 int count = regChnlList.Count;
402 Hashtable table = new Hashtable();
404 Identity id = MarshalByRefObject.GetIdentity(obj, out fServer);
408 String uri = id.ObjURI;
412 for(int i = 0; i < count; i++)
414 if(regChnlList.IsReceiver(i))
418 String[] urls = ((IChannelReceiver)regChnlList.GetChannel(i)).GetUrlsForUri(uri);
419 // Add the strings to the table
420 for(int j = 0; j < urls.Length; j++)
422 table.Add(urls[j], urls[j]);
425 catch(NotSupportedException )
427 // We do not count the channels that do not
428 // support this method
435 // copy url's into string array
436 ICollection keys = table.Keys;
437 String[] urlList = new String[keys.Count];
439 foreach (String key in keys)
446 // Find the channel message sink associated with a given proxy
448 [System.Security.SecurityCritical] // auto-generated
449 internal static IMessageSink GetChannelSinkForProxy(Object obj)
451 IMessageSink sink = null;
452 if (RemotingServices.IsTransparentProxy(obj))
454 RealProxy rp = RemotingServices.GetRealProxy(obj);
455 RemotingProxy remProxy = rp as RemotingProxy;
456 if (null != remProxy)
458 Identity idObj = remProxy.IdentityObject;
459 Contract.Assert(null != idObj,"null != idObj");
460 sink = idObj.ChannelSink;
465 } // GetChannelSinkForProxy
468 // Get the message sink dictionary of properties for a given proxy
470 [System.Security.SecuritySafeCritical] // auto-generated
471 [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration)]
472 public static IDictionary GetChannelSinkProperties(Object obj)
474 IMessageSink sink = GetChannelSinkForProxy(obj);
475 IClientChannelSink chnlSink = sink as IClientChannelSink;
476 if (null != chnlSink)
478 // collect dictionaries for all channel sinks and return
479 // aggregate dictionary
480 ArrayList dictionaries = new ArrayList();
484 IDictionary dict = chnlSink.Properties;
486 dictionaries.Add(dict);
488 chnlSink = chnlSink.NextChannelSink;
489 } while (chnlSink != null);
491 return new AggregateDictionary(dictionaries);
495 IDictionary dict = sink as IDictionary;
505 } // GetChannelSinkProperties
508 internal static IMessageSink GetCrossContextChannelSink()
510 if(null == xCtxChannel)
512 xCtxChannel = CrossContextChannel.MessageSink;
516 } // GetCrossContextChannelSink
520 // A few methods to count the number of calls made across appdomains,
521 // processes and machines
522 internal static long GetNumberOfRemoteCalls()
525 } // GetNumberOfRemoteCalls
528 [System.Security.SecurityCritical] // auto-generated
529 unsafe internal static void IncrementRemoteCalls(long cCalls)
531 remoteCalls += cCalls;
532 if (perf_Contexts != null)
533 perf_Contexts->cRemoteCalls += (int)cCalls;
534 } // IncrementRemoteCalls
536 [System.Security.SecurityCritical] // auto-generated
537 internal static void IncrementRemoteCalls()
539 IncrementRemoteCalls( 1 );
540 } // IncrementRemoteCalls
543 [System.Security.SecurityCritical] // auto-generated
544 internal static void RefreshChannelData()
546 bool fLocked = false;
547 RuntimeHelpers.PrepareConstrainedRegions();
550 Monitor.Enter(s_channelLock, ref fLocked);
551 s_currentChannelData = CollectChannelDataFromChannels();
557 Monitor.Exit(s_channelLock);
560 } // RefreshChannelData
562 [System.Security.SecurityCritical] // auto-generated
563 private static Object[] CollectChannelDataFromChannels()
565 // Ensure that our native cross-context & cross-domain channels
567 RemotingServices.RegisterWellKnownChannels();
569 RegisteredChannelList regChnlList = s_registeredChannels;
570 int count = regChnlList.Count;
572 // Compute the number of channels that implement IChannelReceiver
573 int numChnls = regChnlList.ReceiverCount;
575 // Allocate array for channel data
576 Object[] data = new Object[numChnls];
578 // we need to remove null entries
579 int nonNullDataCount = 0;
581 // Set the channel data, names and mime types
582 for (int i = 0, j = 0; i < count; i++)
585 IChannel chnl = regChnlList.GetChannel(i);
589 throw new RemotingException(Environment.GetResourceString("Remoting_ChannelNotRegistered", ""));
592 if (regChnlList.IsReceiver(i))
594 BCLDebug.Trace("REMOTE", "Setting info for receiver " + j.ToString(CultureInfo.InvariantCulture) + "\n");
596 Object channelData = ((IChannelReceiver)chnl).ChannelData;
597 data[j] = channelData;
598 if (channelData != null)
601 // Increment the counter
606 if (nonNullDataCount != numChnls)
608 // there were null entries, so remove them.
609 Object[] nonNullData = new Object[nonNullDataCount];
610 int nonNullCounter = 0;
611 for (int co = 0; co < numChnls; co++)
613 Object channelData = data[co];
614 if (channelData != null)
615 nonNullData[nonNullCounter++] = channelData;
622 } // CollectChannelDataFromChannels
624 // Checks to make sure the remote method being invoked is callable
625 static bool IsMethodReallyPublic(MethodInfo mi)
627 if (!mi.IsPublic || mi.IsStatic)
630 if (!mi.IsGenericMethod)
633 foreach (Type t in mi.GetGenericArguments())
640 //--------------------------------------------------------------------
641 //----------------------- Dispatch Support ------------------------
642 //--------------------------------------------------------------------
644 [System.Security.SecurityCritical] // auto-generated_required
645 public static ServerProcessing DispatchMessage(
646 IServerChannelSinkStack sinkStack,
648 out IMessage replyMsg)
650 ServerProcessing processing = ServerProcessing.Complete;
657 throw new ArgumentNullException("msg");
660 BCLDebug.Trace("REMOTE", "Dispatching for URI " + InternalSink.GetURI(msg));
662 // we must switch to the target context of the object and call the context chains etc...
663 // Currenly XContextChannel does exactly so. So this method is just a wrapper..
668 // Make sure that incoming calls are counted as a remote call. This way it
669 // makes more sense on a server.
670 IncrementRemoteCalls();
672 // Check if the object has been disconnected or if it is
673 // a well known object then we have to create it lazily.
674 ServerIdentity srvId = CheckDisconnectedOrCreateWellKnownObject(msg);
676 // Make sure that this isn't an AppDomain object since we don't allow
677 // calls to the AppDomain from out of process (and x-process calls
678 // are always dispatched through this method)
679 if (srvId.ServerType == typeof(System.AppDomain))
681 throw new RemotingException(
682 Environment.GetResourceString(
683 "Remoting_AppDomainsCantBeCalledRemotely"));
687 IMethodCallMessage mcm = msg as IMethodCallMessage;
691 // It's a plain IMessage, so just check to make sure that the
692 // target object implements IMessageSink and dispatch synchronously.
694 if (!typeof(IMessageSink).IsAssignableFrom(srvId.ServerType))
696 throw new RemotingException(
697 Environment.GetResourceString(
698 "Remoting_AppDomainsCantBeCalledRemotely"));
701 processing = ServerProcessing.Complete;
702 replyMsg = ChannelServices.GetCrossContextChannelSink().SyncProcessMessage(msg);
706 // It's an IMethodCallMessage.
708 // Check if the method is one way. Dispatch one way calls in
709 // an asynchronous manner
710 MethodInfo method = (MethodInfo)mcm.MethodBase;
712 // X-process / X-machine calls should be to non-static
713 // public methods only! Non-public or static methods can't
714 // be called remotely.
715 if (!IsMethodReallyPublic(method) &&
716 !RemotingServices.IsMethodAllowedRemotely(method))
718 throw new RemotingException(
719 Environment.GetResourceString(
720 "Remoting_NonPublicOrStaticCantBeCalledRemotely"));
723 RemotingMethodCachedData cache = (RemotingMethodCachedData)
724 InternalRemotingServices.GetReflectionCachedData(method);
755 if(RemotingServices.IsOneWay(method))
757 processing = ServerProcessing.OneWay;
758 ChannelServices.GetCrossContextChannelSink().AsyncProcessMessage(msg, null);
762 // regular processing
763 processing = ServerProcessing.Complete;
764 if (!srvId.ServerType.IsContextful)
766 Object[] args = new Object[]{msg, srvId.ServerContext};
767 replyMsg = (IMessage) CrossContextChannel.SyncProcessMessageCallback(args);
770 replyMsg = ChannelServices.GetCrossContextChannelSink().SyncProcessMessage(msg);
772 } // end of case for IMethodCallMessage
776 if(processing != ServerProcessing.OneWay)
780 IMethodCallMessage mcm =
781 (IMethodCallMessage) ((msg!=null)?msg:new ErrorMessage());
782 replyMsg = (IMessage)new ReturnMessage(e, mcm);
785 ((ReturnMessage)replyMsg).SetLogicalCallContext(
787 msg.Properties[Message.CallContextKey]);
792 // Fatal exception .. ignore
800 // This method is used by the channel to dispatch the incoming messages
801 // to the server side chain(s) based on the URI embedded in the message.
802 // The URI uniquely identifies the receiving object.
804 [System.Security.SecurityCritical] // auto-generated_required
805 public static IMessage SyncDispatchMessage(IMessage msg)
807 IMessage msgRet = null;
808 bool fIsOneWay = false;
814 throw new ArgumentNullException("msg");
819 // For ContextBoundObject's,
820 // we must switch to the target context of the object and call the context chains etc...
821 // Currenly XContextChannel does exactly so. So this method is just a wrapper..
824 // Make sure that incoming calls are counted as a remote call. This way it
825 // makes more sense on a server.
826 IncrementRemoteCalls();
829 if (!(msg is TransitionCall))
831 // Check if the object has been disconnected or if it is
832 // a well known object then we have to create it lazily.
833 CheckDisconnectedOrCreateWellKnownObject(msg);
835 MethodBase method = ((IMethodMessage)msg).MethodBase;
837 // Check if the method is one way. Dispatch one way calls in
838 // an asynchronous manner
839 fIsOneWay = RemotingServices.IsOneWay(method);
843 IMessageSink nextSink = ChannelServices.GetCrossContextChannelSink();
847 msgRet = nextSink.SyncProcessMessage(msg);
851 nextSink.AsyncProcessMessage(msg, null);
860 IMethodCallMessage mcm =
861 (IMethodCallMessage) ((msg!=null)?msg:new ErrorMessage());
862 msgRet = (IMessage)new ReturnMessage(e, mcm);
865 ((ReturnMessage)msgRet).SetLogicalCallContext(
866 mcm.LogicalCallContext);
871 // Fatal exception .. ignore
879 // This method is used by the channel to dispatch the incoming messages
880 // to the server side chain(s) based on the URI embedded in the message.
881 // The URI uniquely identifies the receiving object.
883 [System.Security.SecurityCritical] // auto-generated_required
884 public static IMessageCtrl AsyncDispatchMessage(IMessage msg, IMessageSink replySink)
886 IMessageCtrl ctrl = null;
892 throw new ArgumentNullException("msg");
895 // we must switch to the target context of the object and call the context chains etc...
896 // Currenly XContextChannel does exactly so. So this method is just a wrapper..
898 // Make sure that incoming calls are counted as a remote call. This way it
899 // makes more sense on a server.
900 IncrementRemoteCalls();
902 if (!(msg is TransitionCall))
904 // Check if the object has been disconnected or if it is
905 // a well known object then we have to create it lazily.
906 CheckDisconnectedOrCreateWellKnownObject(msg);
911 ctrl = ChannelServices.GetCrossContextChannelSink().AsyncProcessMessage(msg, replySink);
915 if(null != replySink)
919 IMethodCallMessage mcm = (IMethodCallMessage)msg;
920 ReturnMessage retMsg = new ReturnMessage(e, (IMethodCallMessage)msg);
923 retMsg.SetLogicalCallContext(mcm.LogicalCallContext);
925 replySink.SyncProcessMessage(retMsg);
929 // Fatal exception... ignore
935 } // AsyncDispatchMessage
938 // Creates a channel sink chain (adds special dispatch sink to the end of the chain)
939 [System.Security.SecurityCritical] // auto-generated_required
940 public static IServerChannelSink CreateServerChannelSinkChain(
941 IServerChannelSinkProvider provider, IChannelReceiver channel)
943 if (provider == null)
944 return new DispatchChannelSink();
946 // add dispatch provider to end (first find last provider)
947 IServerChannelSinkProvider lastProvider = provider;
948 while (lastProvider.Next != null)
949 lastProvider = lastProvider.Next;
950 lastProvider.Next = new DispatchChannelSinkProvider();
952 IServerChannelSink sinkChain = provider.CreateSink(channel);
954 // remove dispatch provider from end
955 lastProvider.Next = null;
958 } // CreateServerChannelSinkChain
962 // Check if the object has been disconnected or if it is
963 // a well known object then we have to create it lazily.
964 [System.Security.SecurityCritical] // auto-generated
965 internal static ServerIdentity CheckDisconnectedOrCreateWellKnownObject(IMessage msg)
967 ServerIdentity ident = InternalSink.GetServerIdentity(msg);
969 BCLDebug.Trace("REMOTE", "Identity found = " + (ident == null ? "null" : "ServerIdentity"));
971 // If the identity is null, then we should check whether the
972 // request if for a well known object. If yes, then we should
973 // create the well known object lazily and marshal it.
974 if ((ident == null) || ident.IsRemoteDisconnected())
976 String uri = InternalSink.GetURI(msg);
977 BCLDebug.Trace("REMOTE", "URI " + uri);
980 ServerIdentity newIdent = RemotingConfigHandler.CreateWellKnownObject(uri);
981 if (newIdent != null)
983 // The uri was a registered wellknown object.
985 BCLDebug.Trace("REMOTE", "Identity created = " + (ident == null ? "null" : "ServerIdentity"));
992 if ((ident == null) || (ident.IsRemoteDisconnected()))
994 String uri = InternalSink.GetURI(msg);
995 throw new RemotingException(Environment.GetResourceString("Remoting_Disconnected",uri));
1000 // Channel Services AppDomain Unload Event Handler
1001 [System.Security.SecurityCritical] // auto-generated
1002 internal static void UnloadHandler(Object sender, EventArgs e)
1004 StopListeningOnAllChannels();
1007 [System.Security.SecurityCritical] // auto-generated
1008 private static void StopListeningOnAllChannels()
1012 RegisteredChannelList regChnlList = s_registeredChannels;
1013 int count = regChnlList.Count;
1015 for(int i = 0; i < count; i++)
1017 if(regChnlList.IsReceiver(i))
1019 IChannelReceiver chnl = (IChannelReceiver)regChnlList.GetChannel(i);
1020 chnl.StopListening(null);
1026 // Ignore ... appdomain is shutting down..
1034 // INTERNAL PROFILER NOTIFICATION SERVICES
1037 [System.Security.SecurityCritical] // auto-generated
1038 internal static void NotifyProfiler(IMessage msg, RemotingProfilerEvent profilerEvent)
1040 switch (profilerEvent)
1043 case RemotingProfilerEvent.ClientSend:
1045 if (RemotingServices.CORProfilerTrackRemoting())
1049 RemotingServices.CORProfilerRemotingClientSendingMessage(out g, false);
1051 if (RemotingServices.CORProfilerTrackRemotingCookie())
1052 msg.Properties["CORProfilerCookie"] = g;
1055 } // case RemotingProfilerEvent.ClientSend
1057 case RemotingProfilerEvent.ClientReceive:
1059 if (RemotingServices.CORProfilerTrackRemoting())
1061 Guid g = Guid.Empty;
1063 if (RemotingServices.CORProfilerTrackRemotingCookie())
1065 Object obj = msg.Properties["CORProfilerCookie"];
1073 RemotingServices.CORProfilerRemotingClientReceivingReply(g, false);
1076 } // case RemotingProfilerEvent.ClientReceive
1083 // This is a helper used by UrlObjRef's.
1084 // Finds an http channel and returns first url for this object.
1085 [System.Security.SecurityCritical] // auto-generated
1086 internal static String FindFirstHttpUrlForObject(String objectUri)
1088 if (objectUri == null)
1091 RegisteredChannelList regChnlList = s_registeredChannels;
1092 int count = regChnlList.Count;
1094 for (int i = 0; i < count; i++)
1096 if(regChnlList.IsReceiver(i))
1098 IChannelReceiver chnl = (IChannelReceiver)regChnlList.GetChannel(i);
1099 String chnlType = chnl.GetType().FullName;
1100 if ((String.CompareOrdinal(chnlType, "System.Runtime.Remoting.Channels.Http.HttpChannel") == 0) ||
1101 (String.CompareOrdinal(chnlType, "System.Runtime.Remoting.Channels.Http.HttpServerChannel") == 0))
1103 String[] urls = chnl.GetUrlsForUri(objectUri);
1104 if ((urls != null) && (urls.Length > 0))
1111 } // FindFirstHttpUrlForObject
1116 // Note: These methods should be included even in retail builds so that
1117 // they can be called from the debugger.
1120 internal static void DumpRegisteredChannels()
1122 // To use from cordbg:
1123 // f System.Runtime.Remoting.Channels.ChannelServices::DumpRegisteredChannels
1125 RegisteredChannelList regChnlList = s_registeredChannels;
1126 int count = regChnlList.Count;
1128 Console.Error.WriteLine("Registered Channels:");
1130 for (int i = 0; i < count; i++)
1132 IChannel chnl = regChnlList.GetChannel(i);
1133 Console.Error.WriteLine(chnl);
1135 } // DumpRegisteredChannels
1139 } // class ChannelServices
1142 // used by ChannelServices.NotifyProfiler
1144 internal enum RemotingProfilerEvent
1148 } // RemotingProfilerEvent
1153 internal class RegisteredChannel
1155 // private member variables
1156 private IChannel channel;
1158 private const byte SENDER = 0x1;
1159 private const byte RECEIVER = 0x2;
1161 internal RegisteredChannel(IChannel chnl)
1165 if(chnl is IChannelSender)
1169 if(chnl is IChannelReceiver)
1175 internal virtual IChannel Channel
1177 get { return channel; }
1180 internal virtual bool IsSender()
1182 return ((flags & SENDER) != 0);
1185 internal virtual bool IsReceiver()
1187 return ((flags & RECEIVER) != 0);
1189 }// class RegisteredChannel
1193 // This list should be considered immutable once created.
1197 internal class RegisteredChannelList
1199 private RegisteredChannel[] _channels;
1201 internal RegisteredChannelList()
1203 _channels = new RegisteredChannel[0];
1204 } // RegisteredChannelList
1206 internal RegisteredChannelList(RegisteredChannel[] channels)
1208 _channels = channels;
1209 } // RegisteredChannelList
1211 internal RegisteredChannel[] RegisteredChannels
1213 get { return _channels; }
1214 } // RegisteredChannels
1220 if (_channels == null)
1223 return _channels.Length;
1227 internal IChannel GetChannel(int index)
1229 return _channels[index].Channel;
1232 internal bool IsSender(int index)
1234 return _channels[index].IsSender();
1237 internal bool IsReceiver(int index)
1239 return _channels[index].IsReceiver();
1242 internal int ReceiverCount
1246 if (_channels == null)
1250 for (int i = 0; i < _channels.Length; i++)
1260 internal int FindChannelIndex(IChannel channel)
1262 Object chnlAsObject = (Object)channel;
1264 for (int i = 0; i < _channels.Length; i++)
1266 if (chnlAsObject == (Object)GetChannel(i))
1271 } // FindChannelIndex
1273 [System.Security.SecurityCritical] // auto-generated
1274 internal int FindChannelIndex(String name)
1276 for (int i = 0; i < _channels.Length; i++)
1278 if(String.Compare(name, GetChannel(i).ChannelName, StringComparison.OrdinalIgnoreCase) == 0)
1283 } // FindChannelIndex
1286 } // class RegisteredChannelList
1291 internal class ChannelServicesData
1293 internal long remoteCalls = 0;
1294 internal CrossContextChannel xctxmessageSink = null;
1295 internal CrossAppDomainChannel xadmessageSink = null;
1296 internal bool fRegisterWellKnownChannels = false;
1300 // Terminator sink used for profiling so that we can intercept asynchronous
1301 // replies on the server side.
1305 internal class ServerAsyncReplyTerminatorSink : IMessageSink
1307 internal IMessageSink _nextSink;
1309 internal ServerAsyncReplyTerminatorSink(IMessageSink nextSink)
1311 Contract.Assert(nextSink != null,
1312 "null IMessageSink passed to ServerAsyncReplyTerminatorSink ctor.");
1313 _nextSink = nextSink;
1316 [System.Security.SecurityCritical] // auto-generated
1317 public virtual IMessage SyncProcessMessage(IMessage replyMsg)
1319 // If this class has been brought into the picture, then the following must be true.
1320 Contract.Assert(RemotingServices.CORProfilerTrackRemoting(),
1321 "CORProfilerTrackRemoting returned false, but we're in AsyncProcessMessage!");
1322 Contract.Assert(RemotingServices.CORProfilerTrackRemotingAsync(),
1323 "CORProfilerTrackRemoting returned false, but we're in AsyncProcessMessage!");
1327 // Notify the profiler that we are receiving an async reply from the server-side
1328 RemotingServices.CORProfilerRemotingServerSendingReply(out g, true);
1330 // If GUID cookies are active, then we save it for the other end of the channel
1331 if (RemotingServices.CORProfilerTrackRemotingCookie())
1332 replyMsg.Properties["CORProfilerCookie"] = g;
1334 // Now that we've done the intercepting, pass the message on to the regular chain
1335 return _nextSink.SyncProcessMessage(replyMsg);
1338 [System.Security.SecurityCritical] // auto-generated
1339 public virtual IMessageCtrl AsyncProcessMessage(IMessage replyMsg, IMessageSink replySink)
1341 // Since this class is only used for intercepting async replies, this function should
1342 // never get called. (Async replies are synchronous, ironically)
1343 Contract.Assert(false, "ServerAsyncReplyTerminatorSink.AsyncProcessMessage called!");
1348 public IMessageSink NextSink
1350 [System.Security.SecurityCritical] // auto-generated
1357 // Do I need a finalize here?