2 // System.Runtime.Remoting.Channels.ChannelServices.cs
4 // Author: Rodrigo Moya (rodrigo@ximian.com)
5 // Dietmar Maurer (dietmar@ximian.com)
6 // Lluis Sanchez Gual (lluis@ideary.com)
8 // 2002 (C) Copyright, Ximian, Inc.
11 using System.Collections;
12 using System.Reflection;
13 using System.Runtime.Remoting;
14 using System.Runtime.Remoting.Channels;
15 using System.Runtime.Remoting.Messaging;
16 using System.Runtime.Remoting.Contexts;
18 namespace System.Runtime.Remoting
21 internal class ChannelInfo : IChannelInfo
23 object [] channelData = null;
27 channelData = ChannelServices.GetCurrentChannelInfo ();
30 public ChannelInfo (object remoteChannelData)
32 channelData = new object[] { remoteChannelData };
35 public object[] ChannelData
48 namespace System.Runtime.Remoting.Channels
50 public sealed class ChannelServices
52 private static ArrayList registeredChannels = new ArrayList ();
53 private static ArrayList delayedClientChannels = new ArrayList ();
55 private static CrossContextChannel _crossContextSink = new CrossContextChannel();
57 internal static string CrossContextUrl = "__CrossContext";
59 private ChannelServices ()
63 internal static CrossContextChannel CrossContextChannel
65 get { return _crossContextSink; }
68 internal static IMessageSink CreateClientChannelSinkChain(string url, object remoteChannelData, out string objectUri)
70 // Locate a channel that can parse the url. This channel will be used to
71 // create the sink chain.
73 object[] channelDataArray = (object[])remoteChannelData;
75 lock (registeredChannels.SyncRoot)
77 // First of all, try registered channels
78 foreach (IChannel c in registeredChannels)
80 IChannelSender sender = c as IChannelSender;
81 if (sender == null) continue;
83 IMessageSink sink = CreateClientChannelSinkChain (sender, url, channelDataArray, out objectUri);
84 if (sink != null) return sink;
87 // Not found. Try now creation delayed channels
88 foreach (IChannelSender sender in delayedClientChannels)
90 IMessageSink sink = CreateClientChannelSinkChain (sender, url, channelDataArray, out objectUri);
92 delayedClientChannels.Remove (sender);
93 RegisterChannel (sender);
103 internal static IMessageSink CreateClientChannelSinkChain (IChannelSender sender, string url, object[] channelDataArray, out string objectUri)
106 if (channelDataArray == null) {
107 return sender.CreateMessageSink (url, null, out objectUri);
110 foreach (object data in channelDataArray) {
111 IMessageSink sink = sender.CreateMessageSink (url, data, out objectUri);
112 if (sink != null) return sink;
118 public static IChannel[] RegisteredChannels
121 lock (registeredChannels.SyncRoot)
123 IChannel[] channels = new IChannel[registeredChannels.Count];
125 for (int i = 0; i < registeredChannels.Count; i++)
126 channels[i] = (IChannel) registeredChannels[i];
134 public static IMessageCtrl AsyncDispatchMessage (IMessage msg,
135 IMessageSink replySink)
137 throw new NotImplementedException ();
140 public static IServerChannelSink CreateServerChannelSinkChain (
141 IServerChannelSinkProvider provider, IChannelReceiver channel)
143 IServerChannelSinkProvider tmp = provider;
144 while (tmp.Next != null) tmp = tmp.Next;
145 tmp.Next = new ServerDispatchSinkProvider ();
147 // Every provider has to call CreateSink() of its next provider
148 return provider.CreateSink (channel);
152 public static ServerProcessing DispatchMessage (
153 IServerChannelSinkStack sinkStack,
155 out IMessage replyMsg)
157 // TODO: Async processing
159 replyMsg = SyncDispatchMessage (msg);
161 if (RemotingServices.IsOneWay (((IMethodMessage) msg).MethodBase))
162 return ServerProcessing.OneWay;
164 return ServerProcessing.Complete;
167 public static IChannel GetChannel (string name)
169 lock (registeredChannels.SyncRoot)
171 foreach (IChannel chnl in registeredChannels) {
172 if (chnl.ChannelName == name && !(chnl is CrossAppDomainChannel)) return chnl;
179 public static IDictionary GetChannelSinkProperties (object obj)
181 throw new NotImplementedException ();
184 public static string[] GetUrlsForObject (MarshalByRefObject obj)
186 string uri = RemotingServices.GetObjectUri (obj);
187 if (uri == null) return new string [0];
189 ArrayList list = new ArrayList ();
191 lock (registeredChannels.SyncRoot)
193 foreach (object chnl_obj in registeredChannels) {
194 if (chnl_obj is CrossAppDomainChannel) continue;
196 IChannelReceiver chnl = chnl_obj as IChannelReceiver;
199 list.AddRange (chnl.GetUrlsForUri (uri));
203 return (string[]) list.ToArray (typeof(string));
206 public static void RegisterChannel (IChannel chnl)
208 // Put the channel in the correct place according to its priority.
209 // Since there are not many channels, a linear search is ok.
211 lock (registeredChannels.SyncRoot)
214 for (int n = 0; n < registeredChannels.Count; n++)
216 IChannel regc = (IChannel) registeredChannels[n];
218 if (regc.ChannelName == chnl.ChannelName)
219 throw new RemotingException ("Channel " + regc.ChannelName + " already registered");
221 if (regc.ChannelPriority < chnl.ChannelPriority && pos==-1)
225 if (pos != -1) registeredChannels.Insert (pos, chnl);
226 else registeredChannels.Add (chnl);
228 IChannelReceiver receiver = chnl as IChannelReceiver;
229 if (receiver != null) receiver.StartListening (null);
233 internal static void RegisterChannelConfig (ChannelData channel)
235 IServerChannelSinkProvider serverSinks = null;
236 IClientChannelSinkProvider clientSinks = null;
238 // Create server providers
239 for (int n=channel.ServerProviders.Count-1; n>=0; n--)
241 ProviderData prov = channel.ServerProviders[n] as ProviderData;
242 IServerChannelSinkProvider sinkp = (IServerChannelSinkProvider) CreateProvider (prov);
243 sinkp.Next = serverSinks;
247 // Create client providers
248 for (int n=channel.ClientProviders.Count-1; n>=0; n--)
250 ProviderData prov = channel.ClientProviders[n] as ProviderData;
251 IClientChannelSinkProvider sinkp = (IClientChannelSinkProvider) CreateProvider (prov);
252 sinkp.Next = clientSinks;
256 // Create the channel
258 Type type = Type.GetType (channel.Type);
259 if (type == null) throw new RemotingException ("Type '" + channel.Type + "' not found");
263 bool clienc = typeof (IChannelSender).IsAssignableFrom (type);
264 bool serverc = typeof (IChannelReceiver).IsAssignableFrom (type);
266 if (clienc && serverc) {
267 signature = new Type [] {typeof(IDictionary), typeof(IClientChannelSinkProvider), typeof(IServerChannelSinkProvider)};
268 parms = new Object[] {channel.CustomProperties, clientSinks, serverSinks};
271 signature = new Type [] {typeof(IDictionary), typeof(IClientChannelSinkProvider)};
272 parms = new Object[] {channel.CustomProperties, clientSinks};
275 signature = new Type [] {typeof(IDictionary), typeof(IServerChannelSinkProvider)};
276 parms = new Object[] {channel.CustomProperties, serverSinks};
279 throw new RemotingException (type + " is not a valid channel type");
281 ConstructorInfo ctor = type.GetConstructor (signature);
283 throw new RemotingException (type + " does not have a valid constructor");
288 ch = (IChannel) ctor.Invoke (parms);
290 catch (TargetInvocationException ex)
292 throw ex.InnerException;
295 lock (registeredChannels.SyncRoot)
297 if (channel.DelayLoadAsClientChannel == "true" && !(ch is IChannelReceiver))
298 delayedClientChannels.Add (ch);
300 RegisterChannel (ch);
304 static object CreateProvider (ProviderData prov)
306 Type pvtype = Type.GetType (prov.Type);
307 if (pvtype == null) throw new RemotingException ("Type '" + prov.Type + "' not found");
308 Object[] pvparms = new Object[] {prov.CustomProperties, prov.CustomData};
312 return Activator.CreateInstance (pvtype, pvparms);
316 if (ex is TargetInvocationException) ex = ((TargetInvocationException)ex).InnerException;
317 throw new RemotingException ("An instance of provider '" + pvtype + "' could not be created: " + ex.Message);
321 public static IMessage SyncDispatchMessage (IMessage msg)
323 IMethodMessage call = (IMethodMessage)msg;
324 ServerIdentity identity = RemotingServices.GetIdentityForUri(call.Uri) as ServerIdentity;
325 if (identity == null) return new ReturnMessage (new RemotingException ("No receiver for uri " + call.Uri), (IMethodCallMessage) msg);
327 RemotingServices.SetMessageTargetIdentity (msg, identity);
328 return _crossContextSink.SyncProcessMessage (msg);
331 public static void UnregisterChannel (IChannel chnl)
334 throw new ArgumentNullException ();
336 lock (registeredChannels.SyncRoot)
338 if (!registeredChannels.Contains ((object) chnl))
339 throw new RemotingException ();
341 registeredChannels.Remove ((object) chnl);
343 IChannelReceiver chnlReceiver = chnl as IChannelReceiver;
344 if(chnlReceiver != null)
345 chnlReceiver.StopListening(null);
349 internal static object [] GetCurrentChannelInfo ()
351 ArrayList list = new ArrayList ();
353 lock (registeredChannels.SyncRoot)
355 foreach (object chnl_obj in registeredChannels) {
356 IChannelReceiver chnl = chnl_obj as IChannelReceiver;
359 object chnl_data = chnl.ChannelData;
360 if (chnl_data != null)
361 list.Add (chnl_data);
366 return list.ToArray ();