RemotingServices.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. //
  2. // System.Runtime.Remoting.RemotingServices.cs
  3. //
  4. // Authors:
  5. // Dietmar Maurer ([email protected])
  6. // Lluis Sanchez Gual ([email protected])
  7. // Patrik Torstensson
  8. //
  9. // (C) 2001 Ximian, Inc. http://www.ximian.com
  10. //
  11. using System;
  12. using System.Reflection;
  13. using System.Threading;
  14. using System.Collections;
  15. using System.Runtime.Remoting.Messaging;
  16. using System.Runtime.Remoting.Proxies;
  17. using System.Runtime.Remoting.Channels;
  18. using System.Runtime.Remoting.Contexts;
  19. using System.Runtime.Remoting.Activation;
  20. using System.Runtime.Remoting.Lifetime;
  21. using System.Runtime.CompilerServices;
  22. using System.Runtime.Serialization;
  23. using System.IO;
  24. namespace System.Runtime.Remoting
  25. {
  26. public sealed class RemotingServices
  27. {
  28. // Holds the identities of the objects, using uri as index
  29. static Hashtable uri_hash = new Hashtable ();
  30. internal static string app_id;
  31. static int next_id = 1;
  32. static RemotingServices ()
  33. {
  34. RegisterInternalChannels ();
  35. app_id = "/" + Guid.NewGuid().ToString().Replace('-', '_') + "/";
  36. CreateWellKnownServerIdentity (typeof(RemoteActivator), "RemoteActivationService.rem", WellKnownObjectMode.Singleton);
  37. }
  38. private RemotingServices () {}
  39. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  40. internal extern static object InternalExecute (MonoMethod method, Object obj,
  41. Object[] parameters, out object [] out_args);
  42. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  43. public extern static bool IsTransparentProxy (object proxy);
  44. internal static IMethodReturnMessage InternalExecuteMessage (
  45. MarshalByRefObject target, IMethodCallMessage reqMsg)
  46. {
  47. ReturnMessage result;
  48. MonoMethod method = (MonoMethod) target.GetType().GetMethod(reqMsg.MethodName, BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance, null, (Type[]) reqMsg.MethodSignature, null);
  49. try {
  50. object [] out_args;
  51. object rval = InternalExecute (method, target, reqMsg.Args, out out_args);
  52. result = new ReturnMessage (rval, out_args, out_args.Length,
  53. reqMsg.LogicalCallContext, reqMsg);
  54. } catch (Exception e) {
  55. result = new ReturnMessage (e, reqMsg);
  56. }
  57. return result;
  58. }
  59. public static IMethodReturnMessage ExecuteMessage (
  60. MarshalByRefObject target, IMethodCallMessage reqMsg)
  61. {
  62. if (IsTransparentProxy(target))
  63. {
  64. // Message must go through all chain of sinks
  65. RealProxy rp = GetRealProxy (target);
  66. return (IMethodReturnMessage) rp.Invoke (reqMsg);
  67. }
  68. else // Direct call
  69. return InternalExecuteMessage (target, reqMsg);
  70. }
  71. public static object Connect (Type classToProxy, string url)
  72. {
  73. ObjRef objRef = new ObjRef (classToProxy, url, null);
  74. return GetRemoteObject (objRef, classToProxy);
  75. }
  76. public static object Connect (Type classToProxy, string url, object data)
  77. {
  78. ObjRef objRef = new ObjRef (classToProxy, url, data);
  79. return GetRemoteObject (objRef, classToProxy);
  80. }
  81. public static bool Disconnect (MarshalByRefObject obj)
  82. {
  83. if (obj == null) throw new ArgumentNullException ("obj");
  84. if (IsTransparentProxy (obj)) throw new ArgumentException ("The obj parameter is a proxy");
  85. ServerIdentity identity = obj.ObjectIdentity;
  86. if (identity == null || !identity.IsConnected)
  87. return false;
  88. else
  89. {
  90. LifetimeServices.StopTrackingLifetime (identity);
  91. DisposeIdentity (identity);
  92. return true;
  93. }
  94. }
  95. public static Type GetServerTypeForUri (string uri)
  96. {
  97. Identity ident = GetIdentityForUri (uri);
  98. if (ident == null) return null;
  99. return ident.ObjectType;
  100. }
  101. public static string GetObjectUri (MarshalByRefObject obj)
  102. {
  103. Identity ident = GetObjectIdentity(obj);
  104. if (ident != null) return ident.ObjectUri;
  105. else return null;
  106. }
  107. public static object Unmarshal (ObjRef objref)
  108. {
  109. return Unmarshal(objref, true);
  110. }
  111. public static object Unmarshal (ObjRef objref, bool fRefine)
  112. {
  113. // FIXME: use type name when fRefine==true
  114. Type classToProxy = fRefine ? objref.ServerType : typeof (MarshalByRefObject);
  115. if (objref.IsReferenceToWellKnow)
  116. return GetRemoteObject(objref, classToProxy);
  117. else
  118. {
  119. if (classToProxy.IsContextful)
  120. {
  121. // Look for a ProxyAttribute
  122. ProxyAttribute att = (ProxyAttribute) Attribute.GetCustomAttribute (classToProxy, typeof(ProxyAttribute),true);
  123. if (att != null)
  124. return att.CreateProxy (objref, classToProxy, null, null).GetTransparentProxy();
  125. }
  126. return GetProxyForRemoteObject (objref, classToProxy);
  127. }
  128. }
  129. public static ObjRef Marshal (MarshalByRefObject obj)
  130. {
  131. return Marshal (obj, null, null);
  132. }
  133. public static ObjRef Marshal (MarshalByRefObject obj, string uri)
  134. {
  135. return Marshal (obj, uri, null);
  136. }
  137. public static ObjRef Marshal (MarshalByRefObject obj, string uri, Type requested_type)
  138. {
  139. if (IsTransparentProxy (obj))
  140. {
  141. RealProxy proxy = RemotingServices.GetRealProxy(obj);
  142. Identity identity = proxy.ObjectIdentity;
  143. if (identity != null)
  144. {
  145. if (identity.ObjectType.IsContextful && !identity.IsConnected)
  146. {
  147. // Unregistered local contextbound object. Register now.
  148. ClientActivatedIdentity cboundIdentity = (ClientActivatedIdentity)identity;
  149. if (uri == null) uri = NewUri();
  150. cboundIdentity.ObjectUri = uri;
  151. RegisterServerIdentity (cboundIdentity);
  152. cboundIdentity.StartTrackingLifetime ((ILease)obj.InitializeLifetimeService());
  153. return cboundIdentity.CreateObjRef(requested_type);
  154. }
  155. else if (uri != null)
  156. throw new RemotingException ("It is not possible marshal a proxy of a remote object");
  157. return proxy.ObjectIdentity.CreateObjRef(requested_type);
  158. }
  159. }
  160. if (requested_type == null) requested_type = obj.GetType();
  161. if (uri == null)
  162. {
  163. uri = NewUri();
  164. CreateClientActivatedServerIdentity (obj, requested_type, uri);
  165. }
  166. else
  167. {
  168. ClientActivatedIdentity identity = uri_hash [uri] as ClientActivatedIdentity;
  169. if (identity == null || obj != identity.GetServerObject())
  170. CreateClientActivatedServerIdentity (obj, requested_type, uri);
  171. }
  172. return obj.CreateObjRef(requested_type);
  173. }
  174. static string NewUri ()
  175. {
  176. return app_id + Environment.TickCount + "_" + next_id++;
  177. }
  178. public static RealProxy GetRealProxy (object proxy)
  179. {
  180. if (!IsTransparentProxy(proxy)) throw new RemotingException("Cannot get the real proxy from an object that is not a transparent proxy");
  181. return (RealProxy)((TransparentProxy)proxy)._rp;
  182. }
  183. public static MethodBase GetMethodBaseFromMethodMessage(IMethodMessage msg)
  184. {
  185. Type type = Type.GetType (msg.TypeName);
  186. if (type == null)
  187. throw new RemotingException ("Type '" + msg.TypeName + "' not found!");
  188. BindingFlags bflags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
  189. if (msg.MethodSignature == null)
  190. return type.GetMethod (msg.MethodName, bflags);
  191. else
  192. return type.GetMethod (msg.MethodName, bflags, null, (Type[]) msg.MethodSignature, null);
  193. }
  194. public static void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
  195. {
  196. if (obj == null) throw new ArgumentNullException ("obj");
  197. ObjRef oref = Marshal ((MarshalByRefObject)obj);
  198. oref.GetObjectData (info, context);
  199. }
  200. public static ObjRef GetObjRefForProxy(MarshalByRefObject obj)
  201. {
  202. Identity ident = GetObjectIdentity(obj);
  203. if (ident == null) return null;
  204. else return ident.CreateObjRef(null);
  205. }
  206. [MonoTODO]
  207. public static string GetSessionIdForMethodMessage(IMethodMessage msg)
  208. {
  209. throw new NotImplementedException ();
  210. }
  211. public static bool IsMethodOverloaded(IMethodMessage msg)
  212. {
  213. Type type = msg.MethodBase.DeclaringType;
  214. MemberInfo[] members = type.GetMember (msg.MethodName, MemberTypes.Method, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
  215. return members.Length > 1;
  216. }
  217. public static bool IsObjectOutOfAppDomain(object tp)
  218. {
  219. Identity ident = GetObjectIdentity((MarshalByRefObject)tp);
  220. if (ident != null) return !ident.IsFromThisAppDomain;
  221. else return false;
  222. }
  223. public static bool IsObjectOutOfContext(object tp)
  224. {
  225. ServerIdentity ident = GetObjectIdentity((MarshalByRefObject)tp) as ServerIdentity;
  226. if (ident != null) return ident.Context != System.Threading.Thread.CurrentContext;
  227. else return false;
  228. }
  229. public static bool IsOneWay(MethodBase method)
  230. {
  231. object[] atts = method.GetCustomAttributes (typeof (OneWayAttribute), false);
  232. return atts.Length > 0;
  233. }
  234. public static void SetObjectUriForMarshal(MarshalByRefObject obj, string uri)
  235. {
  236. if (IsTransparentProxy (obj)) throw new RemotingException ("SetObjectUriForMarshal method should only be called for MarshalByRefObjects that exist in the current AppDomain.");
  237. Marshal (obj, uri);
  238. }
  239. #region Internal Methods
  240. internal static object CreateClientProxy (ActivatedClientTypeEntry entry, object[] activationAttributes)
  241. {
  242. if (entry.ContextAttributes != null || activationAttributes != null)
  243. {
  244. ArrayList props = new ArrayList ();
  245. if (entry.ContextAttributes != null) props.AddRange (entry.ContextAttributes);
  246. if (activationAttributes != null) props.AddRange (activationAttributes);
  247. return CreateClientProxy (entry.ObjectType, entry.ApplicationUrl, props.ToArray ());
  248. }
  249. else
  250. return CreateClientProxy (entry.ObjectType, entry.ApplicationUrl, null);
  251. }
  252. internal static object CreateClientProxy (Type objectType, string url, object[] activationAttributes)
  253. {
  254. string activationUrl = url + "/RemoteActivationService.rem";
  255. string objectUri;
  256. IMessageSink sink = GetClientChannelSinkChain (activationUrl, null, out objectUri);
  257. RemotingProxy proxy = new RemotingProxy (objectType, activationUrl, activationAttributes);
  258. return proxy.GetTransparentProxy();
  259. }
  260. internal static object CreateClientProxy (WellKnownClientTypeEntry entry)
  261. {
  262. return Connect (entry.ObjectType, entry.ObjectUrl, null);
  263. }
  264. internal static object CreateClientProxyForContextBound (Type type, object[] activationAttributes)
  265. {
  266. if (type.IsContextful)
  267. {
  268. // Look for a ProxyAttribute
  269. ProxyAttribute att = (ProxyAttribute) Attribute.GetCustomAttribute (type, typeof(ProxyAttribute), true);
  270. if (att != null)
  271. return att.CreateInstance (type);
  272. }
  273. RemotingProxy proxy = new RemotingProxy (type, ChannelServices.CrossContextUrl, activationAttributes);
  274. return proxy.GetTransparentProxy();
  275. }
  276. internal static Identity GetIdentityForUri (string uri)
  277. {
  278. lock (uri_hash)
  279. {
  280. return (Identity)uri_hash [uri];
  281. }
  282. }
  283. internal static Identity GetObjectIdentity (MarshalByRefObject obj)
  284. {
  285. if (IsTransparentProxy(obj))
  286. return GetRealProxy (obj).ObjectIdentity;
  287. else
  288. return obj.ObjectIdentity;
  289. }
  290. internal static ClientIdentity GetOrCreateClientIdentity(ObjRef objRef, Type proxyType)
  291. {
  292. // This method looks for an identity for the given url.
  293. // If an identity is not found, it creates the identity and
  294. // assigns it a proxy to the remote object.
  295. // Creates the client sink chain for the given url or channelData.
  296. // It will also get the object uri from the url.
  297. object channelData = objRef.ChannelInfo != null ? objRef.ChannelInfo.ChannelData : null;
  298. string url = (channelData == null) ? objRef.URI : null;
  299. string objectUri;
  300. IMessageSink sink = GetClientChannelSinkChain (url, channelData, out objectUri);
  301. if (objectUri == null) objectUri = objRef.URI;
  302. lock (uri_hash)
  303. {
  304. ClientIdentity identity = uri_hash [objRef.URI] as ClientIdentity;
  305. if (identity != null)
  306. return identity; // Object already registered
  307. // Creates an identity and a proxy for the remote object
  308. identity = new ClientIdentity (objectUri, objRef);
  309. identity.ChannelSink = sink;
  310. if (proxyType != null)
  311. {
  312. RemotingProxy proxy = new RemotingProxy (proxyType, identity);
  313. identity.ClientProxy = (MarshalByRefObject) proxy.GetTransparentProxy();
  314. }
  315. // Registers the identity
  316. uri_hash [objRef.URI] = identity;
  317. return identity;
  318. }
  319. }
  320. static IMessageSink GetClientChannelSinkChain(string url, object channelData, out string objectUri)
  321. {
  322. IMessageSink sink = ChannelServices.CreateClientChannelSinkChain (url, channelData, out objectUri);
  323. if (sink == null)
  324. {
  325. if (url != null)
  326. {
  327. string msg = String.Format ("Cannot create channel sink to connect to URL {0}. An appropriate channel has probably not been registered.", url);
  328. throw new RemotingException (msg);
  329. }
  330. else
  331. {
  332. string msg = String.Format ("Cannot create channel sink to connect to the remote object. An appropriate channel has probably not been registered.", url);
  333. throw new RemotingException (msg);
  334. }
  335. }
  336. return sink;
  337. }
  338. internal static ClientActivatedIdentity CreateContextBoundObjectIdentity(Type objectType)
  339. {
  340. ClientActivatedIdentity identity = new ClientActivatedIdentity (null, objectType);
  341. identity.ChannelSink = ChannelServices.CrossContextChannel;
  342. return identity;
  343. }
  344. internal static ClientActivatedIdentity CreateClientActivatedServerIdentity(MarshalByRefObject realObject, Type objectType, string objectUri)
  345. {
  346. ClientActivatedIdentity identity = new ClientActivatedIdentity (objectUri, objectType);
  347. identity.AttachServerObject (realObject, Context.DefaultContext);
  348. RegisterServerIdentity (identity);
  349. identity.StartTrackingLifetime ((ILease)realObject.InitializeLifetimeService ());
  350. return identity;
  351. }
  352. internal static ServerIdentity CreateWellKnownServerIdentity(Type objectType, string objectUri, WellKnownObjectMode mode)
  353. {
  354. ServerIdentity identity;
  355. if (mode == WellKnownObjectMode.SingleCall)
  356. identity = new SingleCallIdentity(objectUri, Context.DefaultContext, objectType);
  357. else
  358. identity = new SingletonIdentity(objectUri, Context.DefaultContext, objectType);
  359. RegisterServerIdentity (identity);
  360. return identity;
  361. }
  362. private static void RegisterServerIdentity(ServerIdentity identity)
  363. {
  364. lock (uri_hash)
  365. {
  366. if (uri_hash.ContainsKey (identity.ObjectUri))
  367. throw new RemotingException ("Uri already in use: " + identity.ObjectUri);
  368. uri_hash[identity.ObjectUri] = identity;
  369. }
  370. }
  371. internal static object GetProxyForRemoteObject (ObjRef objref, Type classToProxy)
  372. {
  373. ClientActivatedIdentity identity = uri_hash [objref.URI] as ClientActivatedIdentity;
  374. if (identity != null) return identity.GetServerObject ();
  375. else return GetRemoteObject (objref, classToProxy);
  376. }
  377. internal static object GetRemoteObject(ObjRef objRef, Type proxyType)
  378. {
  379. ClientIdentity id = GetOrCreateClientIdentity (objRef, proxyType);
  380. return id.ClientProxy;
  381. }
  382. internal static object GetDomainProxy(AppDomain domain)
  383. {
  384. byte[] data = null;
  385. Context currentContext = Thread.CurrentContext;
  386. AppDomain currentDomain = AppDomain.InternalSetDomain (domain);
  387. try
  388. {
  389. data = domain.GetMarshalledDomainObjRef ();
  390. }
  391. finally
  392. {
  393. AppDomain.InternalSetDomain (currentDomain);
  394. AppDomain.InternalSetContext (currentContext);
  395. }
  396. MemoryStream stream = new MemoryStream (data);
  397. ObjRef appref = (ObjRef) CADSerializer.DeserializeObject (stream);
  398. return (AppDomain) RemotingServices.Unmarshal(appref);
  399. }
  400. private static void RegisterInternalChannels()
  401. {
  402. CrossAppDomainChannel.RegisterCrossAppDomainChannel();
  403. }
  404. internal static void DisposeIdentity (ServerIdentity ident)
  405. {
  406. uri_hash.Remove (ident.ObjectUri);
  407. }
  408. internal static Identity GetMessageTargetIdentity (IMessage msg)
  409. {
  410. // Returns the identity where the message is sent
  411. if (msg is IInternalMessage)
  412. return ((IInternalMessage)msg).TargetIdentity;
  413. lock (uri_hash)
  414. {
  415. return uri_hash [((IMethodMessage)msg).Uri] as ServerIdentity;
  416. }
  417. }
  418. internal static void SetMessageTargetIdentity (IMessage msg, Identity ident)
  419. {
  420. if (msg is IInternalMessage)
  421. ((IInternalMessage)msg).TargetIdentity = ident;
  422. }
  423. #endregion
  424. }
  425. }