2 // System.Runtime.Remoting.Channels.CrossDomainChannel.cs
4 // Author: Patrik Torstensson (totte_mono@yahoo.com)
6 // 2003 (C) Copyright, Ximian, Inc.
9 using System.Collections;
11 using System.Threading;
\r
12 using System.Runtime.Remoting;
\r
13 using System.Runtime.Remoting.Messaging;
\r
14 using System.Runtime.Remoting.Channels;
\r
15 using System.Runtime.Remoting.Contexts;
\r
16 using System.Runtime.Serialization;
\r
17 using System.Runtime.Serialization.Formatters.Binary;
\r
19 namespace System.Runtime.Remoting.Channels
\r
22 // Holds the cross appdomain channel data (used to get/create the correct sink)
24 internal class CrossAppDomainChannelData
\r
26 // TODO: Add context support
27 private int _domainId;
\r
29 internal CrossAppDomainChannelData(int domainId)
\r
31 _domainId = domainId;
\r
34 internal int DomainID
\r
36 get { return _domainId; }
\r
40 // Responsible for marshalling objects between appdomains
42 internal class CrossAppDomainChannel : IChannel, IChannelSender, IChannelReceiver
\r
44 private const String _strName = "MONOCAD";
45 private const String _strBaseURI = "MONOCADURI";
47 private static Object s_lock = new Object();
49 internal static void RegisterCrossAppDomainChannel()
\r
53 // todo: make singleton
\r
54 CrossAppDomainChannel monocad = new CrossAppDomainChannel();
\r
55 ChannelServices.RegisterChannel ((IChannel) monocad);
\r
59 // IChannel implementation
\r
60 public virtual String ChannelName
\r
62 get { return _strName; }
\r
65 public virtual int ChannelPriority
\r
70 public String Parse(String url, out String objectURI)
\r
77 public virtual Object ChannelData
\r
79 get { return new CrossAppDomainChannelData(Thread.GetDomainID()); }
\r
82 public virtual String[] GetUrlsForUri(String objectURI)
\r
84 throw new NotSupportedException("CrossAppdomain channel dont support UrlsForUri");
\r
88 public virtual void StartListening(Object data) {}
\r
89 public virtual void StopListening(Object data) {}
\r
92 public virtual IMessageSink CreateMessageSink(String url, Object data, out String uri)
\r
95 IMessageSink sink = null;
\r
97 if (url == null && data != null)
\r
99 // Get the data and then get the sink
\r
100 CrossAppDomainChannelData cadData = data as CrossAppDomainChannelData;
\r
101 if (cadData != null)
\r
102 // GetSink creates a new sink if we don't have any (use contexts here later)
\r
103 sink = CrossAppDomainSink.GetSink(cadData.DomainID);
\r
107 if (url != null && data == null)
\r
109 if (url.StartsWith(_strName))
\r
111 throw new NotSupportedException("Can't create a named channel via crossappdomain");
\r
121 [MonoTODO("Handle domain unloading?")]
\r
122 internal class CrossAppDomainSink : IMessageSink
\r
124 private static Hashtable s_sinks = new Hashtable();
\r
126 private int _domainID;
\r
128 internal CrossAppDomainSink(int domainID)
\r
130 _domainID = domainID;
\r
133 internal static CrossAppDomainSink GetSink(int domainID)
\r
135 // Check if we have a sink for the current domainID
\r
136 // note, locking is not to bad here, very few class to GetSink
\r
137 lock (s_sinks.SyncRoot)
\r
139 if (s_sinks.ContainsKey(domainID))
\r
140 return (CrossAppDomainSink) s_sinks[domainID];
\r
143 CrossAppDomainSink sink = new CrossAppDomainSink(domainID);
\r
144 s_sinks[domainID] = sink;
\r
151 public virtual IMessage SyncProcessMessage(IMessage msgRequest)
\r
153 IMessage retMessage = null;
\r
157 // Time to transit into the "our" domain
\r
158 byte [] arrResponse = null;
\r
159 byte [] arrRequest = null;
\r
161 CADMethodReturnMessage cadMrm = null;
\r
162 CADMethodCallMessage cadMsg;
\r
164 cadMsg = CADMethodCallMessage.Create (msgRequest);
\r
165 if (null == cadMsg) {
\r
166 // Serialize the request message
\r
167 MemoryStream reqMsgStream = CADSerializer.SerializeMessage(msgRequest);
\r
168 arrRequest = reqMsgStream.GetBuffer();
\r
171 Context currentContext = Thread.CurrentContext;
172 AppDomain currentDomain = AppDomain.InternalSetDomainByID ( _domainID );
176 AppDomain.CurrentDomain.ProcessMessageInDomain (arrRequest, cadMsg, out arrResponse, out cadMrm);
180 IMessage errorMsg = new MethodResponse (e, new ErrorMessage());
181 arrResponse = CADSerializer.SerializeMessage (errorMsg).GetBuffer();
\r
185 AppDomain.InternalSetDomain (currentDomain);
186 AppDomain.InternalSetContext (currentContext);
189 if (null != arrResponse) {
\r
190 // Time to deserialize the message
\r
191 MemoryStream respMsgStream = new MemoryStream(arrResponse);
\r
193 // Deserialize the response message
\r
194 retMessage = CADSerializer.DeserializeMessage(respMsgStream, msgRequest as IMethodCallMessage);
\r
196 retMessage = new MethodResponse (msgRequest as IMethodCallMessage, cadMrm);
\r
198 catch (Exception e)
\r
202 Console.WriteLine("Exception in base domain");
203 retMessage = new ReturnMessage (e, msgRequest as IMethodCallMessage);
207 // this is just to be sure
\r
214 public virtual IMessageCtrl AsyncProcessMessage(IMessage reqMsg, IMessageSink replySink)
\r
216 throw new NotSupportedException();
\r
219 public IMessageSink NextSink { get { return null; } }
\r
222 internal class CADSerializer
224 internal static IMessage DeserializeMessage(MemoryStream mem, IMethodCallMessage msg)
\r
226 BinaryFormatter serializer = new BinaryFormatter();
\r
228 serializer.SurrogateSelector = null;
\r
232 return (IMessage) serializer.Deserialize(mem, null);
\r
234 return (IMessage) serializer.DeserializeMethodResponse(mem, null, msg);
\r
237 internal static MemoryStream SerializeMessage(IMessage msg)
\r
239 MemoryStream mem = new MemoryStream ();
\r
240 BinaryFormatter serializer = new BinaryFormatter ();
\r
242 serializer.SurrogateSelector = new RemotingSurrogateSelector ();
\r
243 serializer.Serialize (mem, msg);
\r
250 internal static MemoryStream SerializeObject(object obj)
\r
252 MemoryStream mem = new MemoryStream ();
\r
253 BinaryFormatter serializer = new BinaryFormatter ();
\r
255 serializer.SurrogateSelector = new RemotingSurrogateSelector ();
\r
256 serializer.Serialize (mem, obj);
\r
263 internal static object DeserializeObject(MemoryStream mem)
\r
265 BinaryFormatter serializer = new BinaryFormatter();
\r
267 serializer.SurrogateSelector = null;
\r
270 return serializer.Deserialize (mem);
\r