* ChannelServices.cs: Call context management moved to RemotingServices.
[mono.git] / mcs / class / corlib / System.Runtime.Remoting.Channels / ChannelServices.cs
1 //
2 // System.Runtime.Remoting.Channels.ChannelServices.cs
3 //
4 // Author: Rodrigo Moya (rodrigo@ximian.com)
5 //         Dietmar Maurer (dietmar@ximian.com)
6 //         Lluis Sanchez Gual (lluis@ideary.com)
7 //
8 // 2002 (C) Copyright, Ximian, Inc.
9 //
10
11 using System.Collections;
12 using System.Runtime.Remoting;
13 using System.Runtime.Remoting.Channels;
14 using System.Runtime.Remoting.Messaging;
15 using System.Runtime.Remoting.Contexts;
16
17 namespace System.Runtime.Remoting
18 {
19         [Serializable]
20         internal class ChannelInfo : IChannelInfo
21         {
22                 object [] channelData = null;
23
24                 public ChannelInfo ()
25                 {
26                         channelData = ChannelServices.GetCurrentChannelInfo ();
27                 }
28
29                 public ChannelInfo (object remoteChannelData)
30                 {
31                         channelData = new object[] { remoteChannelData };
32                 }
33                 
34                 public object[] ChannelData 
35                 {
36                         get {
37                                 return channelData;
38                         }
39                         
40                         set {
41                                 channelData = value;
42                         }
43                 }
44         }
45 }
46
47 namespace System.Runtime.Remoting.Channels
48 {
49         public sealed class ChannelServices
50         {
51                 private static ArrayList registeredChannels = new ArrayList ();
52                 private static CrossContextChannel _crossContextSink = new CrossContextChannel();
53                 
54                 internal static string CrossContextUrl = "__CrossContext";
55
56                 private ChannelServices ()
57                 {
58                 }
59
60                 internal static CrossContextChannel CrossContextChannel
61                 {
62                         get { return _crossContextSink; }
63                 }
64
65                 internal static IMessageSink CreateClientChannelSinkChain(string url, object remoteChannelData, out string objectUri)
66                 {
67                         // Locate a channel that can parse the url. This channel will be used to
68                         // create the sink chain.
69
70                         object[] channelDataArray = (object[])remoteChannelData;
71
72                         foreach (IChannel c in registeredChannels) 
73                         {
74                                 IChannelSender sender = c as IChannelSender;
75                                 if (c == null) continue;
76
77                                 if (channelDataArray == null) {
78                                         IMessageSink sink = sender.CreateMessageSink (url, null, out objectUri);
79                                         if (sink != null) return sink;          // URL is ok, this is the channel and the sink
80                                 }
81                                 else {
82                                         foreach (object data in channelDataArray) {
83                                                 IMessageSink sink = sender.CreateMessageSink (url, data, out objectUri);
84                                                 if (sink != null) return sink;          
85                                         }
86                                 }
87                         }
88                         objectUri = null;
89                         return null;
90                 }
91                 
92                 public static IChannel[] RegisteredChannels
93                 {
94                         get {
95                                 IChannel[] channels = new IChannel[registeredChannels.Count];
96
97                                 for (int i = 0; i < registeredChannels.Count; i++)
98                                         channels[i] = (IChannel) registeredChannels[i];
99
100                                 return channels;
101                         }
102                 }
103
104                 [MonoTODO]
105                 public static IMessageCtrl AsyncDispatchMessage (IMessage msg,
106                                                                  IMessageSink replySink)
107                 {
108                         throw new NotImplementedException ();
109                 }
110
111                 public static IServerChannelSink CreateServerChannelSinkChain (
112                         IServerChannelSinkProvider provider, IChannelReceiver channel)
113             {
114                         IServerChannelSinkProvider tmp = provider;
115                         while (tmp.Next != null) tmp = tmp.Next;
116                         tmp.Next = new ServerDispatchSinkProvider ();
117
118                         // Every provider has to call CreateSink() of its next provider
119                         return  provider.CreateSink (channel);
120                 }
121
122                 [MonoTODO]
123                 public static ServerProcessing DispatchMessage (
124                         IServerChannelSinkStack sinkStack,
125                         IMessage msg,
126                         out IMessage replyMsg)
127                 {
128                         // TODO: Async processing
129
130                         replyMsg = SyncDispatchMessage (msg);
131
132                         if (RemotingServices.IsOneWay (((IMethodMessage) msg).MethodBase))
133                                 return ServerProcessing.OneWay;
134                         else
135                                 return ServerProcessing.Complete;
136                 }
137
138                 public static IChannel GetChannel (string name)
139                 {
140                         foreach (IChannel chnl in registeredChannels) {
141                                 if (chnl.ChannelName == name && !(chnl is CrossAppDomainChannel)) return chnl;
142                         }
143                         return null;
144                 }
145
146                 [MonoTODO]
147                 public static IDictionary GetChannelSinkProperties (object obj)
148                 {
149                         throw new NotImplementedException ();
150                 }
151
152                 public static string[] GetUrlsForObject (MarshalByRefObject obj)
153                 {
154                         string uri = RemotingServices.GetObjectUri (obj);
155                         if (uri == null) return new string [0];
156
157                         ArrayList list = new ArrayList ();
158
159                         foreach (object chnl_obj in registeredChannels) {
160                                 if (chnl_obj is CrossAppDomainChannel) continue;
161                                 
162                                 IChannelReceiver chnl = chnl_obj as IChannelReceiver;
163
164                                 if (chnl != null)
165                                         list.AddRange (chnl.GetUrlsForUri (uri));
166                         }
167
168                         return  (string[]) list.ToArray (typeof(string));
169                 }
170
171                 public static void RegisterChannel (IChannel chnl)
172                 {
173                         // Put the channel in the correct place according to its priority.
174                         // Since there are not many channels, a linear search is ok.
175
176                         for (int n = 0; n < registeredChannels.Count; n++) {
177                                 if ( ((IChannel)registeredChannels[n]).ChannelPriority < chnl.ChannelPriority)
178                                 {
179                                         registeredChannels.Insert (n, chnl);
180                                         return;
181                                 }
182                         }
183                         registeredChannels.Add (chnl);
184                 }
185
186                 public static IMessage SyncDispatchMessage (IMessage msg)
187                 {
188                         IMethodMessage call = (IMethodMessage)msg;
189                         ServerIdentity identity = RemotingServices.GetIdentityForUri(call.Uri) as ServerIdentity;
190                         if (identity == null) return new ReturnMessage (new RemotingException ("No receiver for uri " + call.Uri), (IMethodCallMessage) msg);
191
192                         RemotingServices.SetMessageTargetIdentity (msg, identity);
193                         return _crossContextSink.SyncProcessMessage (msg);
194                 }
195
196                 public static void UnregisterChannel (IChannel chnl)
197                 {
198                         if (chnl == null)
199                                 throw new ArgumentNullException ();
200                         if (!registeredChannels.Contains ((object) chnl))
201                                 throw new RemotingException ();
202
203                         registeredChannels.Remove ((object) chnl);
204
205                         IChannelReceiver chnlReceiver = chnl as IChannelReceiver;
206                         if(chnlReceiver != null)
207                                 chnlReceiver.StopListening(null);
208 }
209
210                 internal static object [] GetCurrentChannelInfo ()
211                 {
212                         ArrayList list = new ArrayList ();
213                         
214                         foreach (object chnl_obj in registeredChannels) {
215                                 IChannelReceiver chnl = chnl_obj as IChannelReceiver;
216                         
217                                 if (chnl != null) {
218                                         object chnl_data = chnl.ChannelData;
219                                         if (chnl_data != null)
220                                                 list.Add (chnl_data);
221                                 }
222                         }
223
224                         return  list.ToArray ();
225                 }
226         }
227 }