1 // 2 // System.Runtime.Remoting.RemotingServices.cs 3 // 4 // Authors: 5 // Dietmar Maurer (dietmar@ximian.com) 6 // Lluis Sanchez Gual (lluis@ideary.com) 7 // Patrik Torstensson 8 // 9 // (C) 2001 Ximian, Inc. http://www.ximian.com 10 // Copyright (C) 2004, 2006 Novell, Inc (http://www.novell.com) 11 // 12 // Permission is hereby granted, free of charge, to any person obtaining 13 // a copy of this software and associated documentation files (the 14 // "Software"), to deal in the Software without restriction, including 15 // without limitation the rights to use, copy, modify, merge, publish, 16 // distribute, sublicense, and/or sell copies of the Software, and to 17 // permit persons to whom the Software is furnished to do so, subject to 18 // the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be 21 // included in all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 // 31 32 using System.Diagnostics; 33 using System.Text; 34 using System.Reflection; 35 using System.Threading; 36 using System.Collections; 37 using System.Runtime.Remoting.Messaging; 38 using System.Runtime.Remoting.Proxies; 39 using System.Runtime.Remoting.Channels; 40 using System.Runtime.Remoting.Contexts; 41 using System.Runtime.Remoting.Activation; 42 using System.Runtime.Remoting.Lifetime; 43 using System.Runtime.CompilerServices; 44 using System.Runtime.Serialization; 45 using System.Runtime.Serialization.Formatters.Binary; 46 using System.IO; 47 using System.Runtime.Remoting.Services; 48 using System.Security.Permissions; 49 using System.Runtime.ConstrainedExecution; 50 using System.Runtime.Serialization.Formatters; 51 52 namespace System.Runtime.Remoting 53 { 54 [System.Runtime.InteropServices.ComVisible (true)] 55 static 56 public class RemotingServices 57 { 58 // Holds the identities of the objects, using uri as index 59 static Hashtable uri_hash = new Hashtable (); 60 61 static BinaryFormatter _serializationFormatter; 62 static BinaryFormatter _deserializationFormatter; 63 64 static string app_id; 65 static readonly object app_id_lock = new object (); 66 67 static int next_id = 1; 68 const BindingFlags methodBindings = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; 69 static readonly MethodInfo FieldSetterMethod; 70 static readonly MethodInfo FieldGetterMethod; 71 72 // Holds information in xdomain calls. Names are short to minimize serialized size. 73 [Serializable] 74 class CACD { 75 public object d; /* call data */ 76 public object c; /* call context */ 77 } 78 RemotingServices()79 static RemotingServices () 80 { 81 RemotingSurrogateSelector surrogateSelector = new RemotingSurrogateSelector (); 82 StreamingContext context = new StreamingContext (StreamingContextStates.Remoting, null); 83 _serializationFormatter = new BinaryFormatter (surrogateSelector, context); 84 _deserializationFormatter = new BinaryFormatter (null, context); 85 _serializationFormatter.AssemblyFormat = FormatterAssemblyStyle.Full; 86 _deserializationFormatter.AssemblyFormat = FormatterAssemblyStyle.Full; 87 88 RegisterInternalChannels (); 89 CreateWellKnownServerIdentity (typeof(RemoteActivator), "RemoteActivationService.rem", WellKnownObjectMode.Singleton); 90 91 FieldSetterMethod = typeof(object).GetMethod ("FieldSetter", BindingFlags.NonPublic|BindingFlags.Instance); 92 FieldGetterMethod = typeof(object).GetMethod ("FieldGetter", BindingFlags.NonPublic|BindingFlags.Instance); 93 } 94 95 [MethodImplAttribute(MethodImplOptions.InternalCall)] InternalExecute(MethodBase method, Object obj, Object[] parameters, out object [] out_args)96 internal extern static object InternalExecute (MethodBase method, Object obj, 97 Object[] parameters, out object [] out_args); 98 99 // Returns the actual implementation of @method in @type. 100 [MethodImplAttribute(MethodImplOptions.InternalCall)] GetVirtualMethod(Type type, MethodBase method)101 internal extern static MethodBase GetVirtualMethod (Type type, MethodBase method); 102 103 #if DISABLE_REMOTING IsTransparentProxy(object proxy)104 public static bool IsTransparentProxy (object proxy) 105 { 106 throw new NotSupportedException (); 107 } 108 #else 109 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)] 110 [MethodImplAttribute(MethodImplOptions.InternalCall)] IsTransparentProxy(object proxy)111 public extern static bool IsTransparentProxy (object proxy); 112 ProxyCheckCast(RealProxy rp, RuntimeType castType)113 internal static bool ProxyCheckCast (RealProxy rp, RuntimeType castType) 114 { 115 // TODO: What should it do? 116 return true; 117 } 118 #endif 119 InternalExecuteMessage( MarshalByRefObject target, IMethodCallMessage reqMsg)120 internal static IMethodReturnMessage InternalExecuteMessage ( 121 MarshalByRefObject target, IMethodCallMessage reqMsg) 122 { 123 ReturnMessage result; 124 125 Type tt = target.GetType (); 126 MethodBase method; 127 if (reqMsg.MethodBase.DeclaringType == tt || 128 reqMsg.MethodBase == FieldSetterMethod || 129 reqMsg.MethodBase == FieldGetterMethod) { 130 method = reqMsg.MethodBase; 131 } else { 132 method = GetVirtualMethod (tt, reqMsg.MethodBase); 133 134 if (method == null) 135 throw new RemotingException ( 136 String.Format ("Cannot resolve method {0}:{1}", tt, reqMsg.MethodName)); 137 } 138 139 if (reqMsg.MethodBase.IsGenericMethod) { 140 Type[] genericArguments = reqMsg.MethodBase.GetGenericArguments (); 141 MethodInfo gmd = ((MethodInfo)method).GetGenericMethodDefinition (); 142 method = gmd.MakeGenericMethod (genericArguments); 143 } 144 145 var oldContext = CallContext.SetLogicalCallContext (reqMsg.LogicalCallContext); 146 147 try 148 { 149 object [] out_args; 150 object rval = InternalExecute (method, target, reqMsg.Args, out out_args); 151 152 // Collect parameters with Out flag from the request message 153 // FIXME: This can be done in the unmanaged side and will be 154 // more efficient 155 156 ParameterInfo[] parameters = method.GetParameters(); 157 object[] returnArgs = new object [parameters.Length]; 158 159 int n = 0; 160 int noa = 0; 161 foreach (ParameterInfo par in parameters) 162 { 163 if (par.IsOut && !par.ParameterType.IsByRef) 164 returnArgs [n++] = reqMsg.GetArg (par.Position); 165 else if (par.ParameterType.IsByRef) 166 returnArgs [n++] = out_args [noa++]; 167 else 168 returnArgs [n++] = null; 169 } 170 171 var latestCallContext = Thread.CurrentThread.GetMutableExecutionContext().LogicalCallContext; 172 result = new ReturnMessage (rval, returnArgs, n, latestCallContext, reqMsg); 173 } 174 catch (Exception e) 175 { 176 result = new ReturnMessage (e, reqMsg); 177 } 178 179 CallContext.SetLogicalCallContext (oldContext); 180 return result; 181 } 182 ExecuteMessage( MarshalByRefObject target, IMethodCallMessage reqMsg)183 public static IMethodReturnMessage ExecuteMessage ( 184 MarshalByRefObject target, IMethodCallMessage reqMsg) 185 { 186 if (IsTransparentProxy(target)) 187 { 188 // Message must go through all chain of sinks 189 RealProxy rp = GetRealProxy (target); 190 return (IMethodReturnMessage) rp.Invoke (reqMsg); 191 } 192 else // Direct call 193 return InternalExecuteMessage (target, reqMsg); 194 } 195 196 [System.Runtime.InteropServices.ComVisible (true)] Connect(Type classToProxy, string url)197 public static object Connect (Type classToProxy, string url) 198 { 199 ObjRef objRef = new ObjRef (classToProxy, url, null); 200 return GetRemoteObject (objRef, classToProxy); 201 } 202 203 [System.Runtime.InteropServices.ComVisible (true)] Connect(Type classToProxy, string url, object data)204 public static object Connect (Type classToProxy, string url, object data) 205 { 206 ObjRef objRef = new ObjRef (classToProxy, url, data); 207 return GetRemoteObject (objRef, classToProxy); 208 } 209 Disconnect(MarshalByRefObject obj)210 public static bool Disconnect (MarshalByRefObject obj) 211 { 212 if (obj == null) throw new ArgumentNullException ("obj"); 213 214 ServerIdentity identity; 215 216 if (IsTransparentProxy (obj)) 217 { 218 // CBOs are always accessed through a proxy, even in the server, so 219 // for server CBOs it is ok to disconnect a proxy 220 221 RealProxy proxy = GetRealProxy(obj); 222 if (proxy.GetProxiedType().IsContextful && (proxy.ObjectIdentity is ServerIdentity)) 223 identity = proxy.ObjectIdentity as ServerIdentity; 224 else 225 throw new ArgumentException ("The obj parameter is a proxy."); 226 } 227 else { 228 identity = obj.ObjectIdentity; 229 obj.ObjectIdentity = null; 230 } 231 232 if (identity == null || !identity.IsConnected) 233 return false; 234 else 235 { 236 LifetimeServices.StopTrackingLifetime (identity); 237 DisposeIdentity (identity); 238 TrackingServices.NotifyDisconnectedObject (obj); 239 return true; 240 } 241 } 242 GetServerTypeForUri(string URI)243 public static Type GetServerTypeForUri (string URI) 244 { 245 ServerIdentity ident = GetIdentityForUri (URI) as ServerIdentity; 246 if (ident == null) return null; 247 return ident.ObjectType; 248 } 249 GetObjectUri(MarshalByRefObject obj)250 public static string GetObjectUri (MarshalByRefObject obj) 251 { 252 Identity ident = GetObjectIdentity(obj); 253 if (ident is ClientIdentity) return ((ClientIdentity)ident).TargetUri; 254 else if (ident != null) return ident.ObjectUri; 255 else return null; 256 } 257 Unmarshal(ObjRef objectRef)258 public static object Unmarshal (ObjRef objectRef) 259 { 260 return Unmarshal (objectRef, true); 261 } 262 Unmarshal(ObjRef objectRef, bool fRefine)263 public static object Unmarshal (ObjRef objectRef, bool fRefine) 264 { 265 Type classToProxy = fRefine ? objectRef.ServerType : typeof (MarshalByRefObject); 266 if (classToProxy == null) classToProxy = typeof (MarshalByRefObject); 267 268 if (objectRef.IsReferenceToWellKnow) { 269 object obj = GetRemoteObject (objectRef, classToProxy); 270 TrackingServices.NotifyUnmarshaledObject (obj, objectRef); 271 return obj; 272 } 273 else 274 { 275 object obj; 276 277 if (classToProxy.IsContextful) { 278 // Look for a ProxyAttribute 279 ProxyAttribute att = (ProxyAttribute) Attribute.GetCustomAttribute (classToProxy, typeof(ProxyAttribute), true); 280 if (att != null) { 281 obj = att.CreateProxy (objectRef, classToProxy, null, null).GetTransparentProxy(); 282 TrackingServices.NotifyUnmarshaledObject (obj, objectRef); 283 return obj; 284 } 285 } 286 obj = GetProxyForRemoteObject (objectRef, classToProxy); 287 TrackingServices.NotifyUnmarshaledObject (obj, objectRef); 288 return obj; 289 } 290 } 291 Marshal(MarshalByRefObject Obj)292 public static ObjRef Marshal (MarshalByRefObject Obj) 293 { 294 return Marshal (Obj, null, null); 295 } 296 Marshal(MarshalByRefObject Obj, string URI)297 public static ObjRef Marshal (MarshalByRefObject Obj, string URI) 298 { 299 return Marshal (Obj, URI, null); 300 } 301 Marshal(MarshalByRefObject Obj, string ObjURI, Type RequestedType)302 public static ObjRef Marshal (MarshalByRefObject Obj, string ObjURI, Type RequestedType) 303 { 304 if (IsTransparentProxy (Obj)) 305 { 306 RealProxy proxy = RemotingServices.GetRealProxy (Obj); 307 Identity identity = proxy.ObjectIdentity; 308 309 if (identity != null) 310 { 311 if (proxy.GetProxiedType().IsContextful && !identity.IsConnected) 312 { 313 // Unregistered local contextbound object. Register now. 314 ClientActivatedIdentity cboundIdentity = (ClientActivatedIdentity)identity; 315 if (ObjURI == null) ObjURI = NewUri(); 316 cboundIdentity.ObjectUri = ObjURI; 317 RegisterServerIdentity (cboundIdentity); 318 cboundIdentity.StartTrackingLifetime ((ILease)Obj.InitializeLifetimeService()); 319 return cboundIdentity.CreateObjRef (RequestedType); 320 } 321 else if (ObjURI != null) 322 throw new RemotingException ("It is not possible marshal a proxy of a remote object."); 323 324 ObjRef or = proxy.ObjectIdentity.CreateObjRef (RequestedType); 325 TrackingServices.NotifyMarshaledObject (Obj, or); 326 return or; 327 } 328 } 329 330 if (RequestedType == null) RequestedType = Obj.GetType (); 331 332 if (ObjURI == null) 333 { 334 if (Obj.ObjectIdentity == null) 335 { 336 ObjURI = NewUri(); 337 CreateClientActivatedServerIdentity (Obj, RequestedType, ObjURI); 338 } 339 } 340 else 341 { 342 ClientActivatedIdentity identity = GetIdentityForUri ("/" + ObjURI) as ClientActivatedIdentity; 343 if (identity == null || Obj != identity.GetServerObject()) 344 CreateClientActivatedServerIdentity (Obj, RequestedType, ObjURI); 345 } 346 347 ObjRef oref; 348 349 if (IsTransparentProxy (Obj)) 350 oref = RemotingServices.GetRealProxy (Obj).ObjectIdentity.CreateObjRef (RequestedType); 351 else 352 oref = Obj.CreateObjRef (RequestedType); 353 354 TrackingServices.NotifyMarshaledObject (Obj, oref); 355 return oref; 356 } 357 NewUri()358 static string NewUri () 359 { 360 if (app_id == null) { 361 lock (app_id_lock) { 362 if (app_id == null) 363 app_id = Guid.NewGuid().ToString().Replace('-', '_') + "/"; 364 } 365 } 366 367 int n = Interlocked.Increment (ref next_id); 368 return app_id + Environment.TickCount.ToString("x") + "_" + n + ".rem"; 369 } 370 371 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)] GetRealProxy(object proxy)372 public static RealProxy GetRealProxy (object proxy) 373 { 374 if (!IsTransparentProxy(proxy)) throw new RemotingException("Cannot get the real proxy from an object that is not a transparent proxy."); 375 return (RealProxy)((TransparentProxy)proxy)._rp; 376 } 377 GetMethodBaseFromMethodMessage(IMethodMessage msg)378 public static MethodBase GetMethodBaseFromMethodMessage(IMethodMessage msg) 379 { 380 Type type = Type.GetType (msg.TypeName); 381 if (type == null) 382 throw new RemotingException ("Type '" + msg.TypeName + "' not found."); 383 384 return GetMethodBaseFromName (type, msg.MethodName, (Type[]) msg.MethodSignature); 385 } 386 GetMethodBaseFromName(Type type, string methodName, Type[] signature)387 internal static MethodBase GetMethodBaseFromName (Type type, string methodName, Type[] signature) 388 { 389 if (type.IsInterface) { 390 return FindInterfaceMethod (type, methodName, signature); 391 } 392 else { 393 MethodBase method = null; 394 if (signature == null) 395 method = type.GetMethod (methodName, methodBindings); 396 else 397 method = type.GetMethod (methodName, methodBindings, null, (Type[]) signature, null); 398 399 if (method != null) 400 return method; 401 402 if (methodName == "FieldSetter") 403 return FieldSetterMethod; 404 405 if (methodName == "FieldGetter") 406 return FieldGetterMethod; 407 408 if (signature == null) 409 return type.GetConstructor (methodBindings, null, Type.EmptyTypes, null); 410 else 411 return type.GetConstructor (methodBindings, null, signature, null); 412 } 413 } 414 FindInterfaceMethod(Type type, string methodName, Type[] signature)415 static MethodBase FindInterfaceMethod (Type type, string methodName, Type[] signature) 416 { 417 MethodBase method = null; 418 419 if (signature == null) 420 method = type.GetMethod (methodName, methodBindings); 421 else 422 method = type.GetMethod (methodName, methodBindings, null, signature, null); 423 424 if (method != null) return method; 425 426 foreach (Type t in type.GetInterfaces ()) { 427 method = FindInterfaceMethod (t, methodName, signature); 428 if (method != null) return method; 429 } 430 431 return null; 432 } 433 GetObjectData(object obj, SerializationInfo info, StreamingContext context)434 public static void GetObjectData(object obj, SerializationInfo info, StreamingContext context) 435 { 436 if (obj == null) throw new ArgumentNullException ("obj"); 437 438 ObjRef oref = Marshal ((MarshalByRefObject)obj); 439 oref.GetObjectData (info, context); 440 } 441 GetObjRefForProxy(MarshalByRefObject obj)442 public static ObjRef GetObjRefForProxy(MarshalByRefObject obj) 443 { 444 Identity ident = GetObjectIdentity(obj); 445 if (ident == null) return null; 446 else return ident.CreateObjRef(null); 447 } 448 GetLifetimeService(MarshalByRefObject obj)449 public static object GetLifetimeService (MarshalByRefObject obj) 450 { 451 if (obj == null) return null; 452 return obj.GetLifetimeService (); 453 } 454 GetEnvoyChainForProxy(MarshalByRefObject obj)455 public static IMessageSink GetEnvoyChainForProxy (MarshalByRefObject obj) 456 { 457 if (IsTransparentProxy(obj)) 458 return ((ClientIdentity)GetRealProxy (obj).ObjectIdentity).EnvoySink; 459 else 460 throw new ArgumentException ("obj must be a proxy.","obj"); 461 } 462 463 [MonoTODO] 464 [Conditional ("REMOTING_PERF")] 465 [Obsolete ("It existed for only internal use in .NET and unimplemented in mono")] LogRemotingStage(int stage)466 public static void LogRemotingStage (int stage) 467 { 468 throw new NotImplementedException (); 469 } 470 GetSessionIdForMethodMessage(IMethodMessage msg)471 public static string GetSessionIdForMethodMessage(IMethodMessage msg) 472 { 473 // It seems that this it what MS returns. 474 return msg.Uri; 475 } 476 IsMethodOverloaded(IMethodMessage msg)477 public static bool IsMethodOverloaded(IMethodMessage msg) 478 { 479 const BindingFlags bfinst = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance; 480 RuntimeType type = (RuntimeType) msg.MethodBase.DeclaringType; 481 return type.GetMethodsByName (msg.MethodName, bfinst, false, type).Length > 1; 482 } 483 IsObjectOutOfAppDomain(object tp)484 public static bool IsObjectOutOfAppDomain(object tp) 485 { 486 MarshalByRefObject mbr = tp as MarshalByRefObject; 487 488 if (mbr == null) 489 return false; 490 491 // TODO: use internal call for better performance 492 Identity ident = GetObjectIdentity (mbr); 493 return ident is ClientIdentity; 494 } 495 IsObjectOutOfContext(object tp)496 public static bool IsObjectOutOfContext(object tp) 497 { 498 MarshalByRefObject mbr = tp as MarshalByRefObject; 499 500 if (mbr == null) 501 return false; 502 503 // TODO: use internal call for better performance 504 Identity ident = GetObjectIdentity (mbr); 505 if (ident == null) return false; 506 507 ServerIdentity sident = ident as ServerIdentity; 508 if (sident != null) return sident.Context != System.Threading.Thread.CurrentContext; 509 else return true; 510 } 511 IsOneWay(MethodBase method)512 public static bool IsOneWay(MethodBase method) 513 { 514 return method.IsDefined (typeof (OneWayAttribute), false); 515 } 516 IsAsyncMessage(IMessage msg)517 internal static bool IsAsyncMessage(IMessage msg) 518 { 519 if (! (msg is MonoMethodMessage)) return false; 520 else if (((MonoMethodMessage)msg).IsAsync) return true; 521 else if (IsOneWay (((MonoMethodMessage)msg).MethodBase)) return true; 522 else return false; 523 } 524 SetObjectUriForMarshal(MarshalByRefObject obj, string uri)525 public static void SetObjectUriForMarshal(MarshalByRefObject obj, string uri) 526 { 527 if (IsTransparentProxy (obj)) { 528 RealProxy proxy = RemotingServices.GetRealProxy(obj); 529 Identity identity = proxy.ObjectIdentity; 530 531 if (identity != null && !(identity is ServerIdentity) && !proxy.GetProxiedType().IsContextful) 532 throw new RemotingException ("SetObjectUriForMarshal method should only be called for MarshalByRefObjects that exist in the current AppDomain."); 533 } 534 535 Marshal (obj, uri); 536 } 537 538 #region Internal Methods 539 CreateClientProxy(ActivatedClientTypeEntry entry, object[] activationAttributes)540 internal static object CreateClientProxy (ActivatedClientTypeEntry entry, object[] activationAttributes) 541 { 542 if (entry.ContextAttributes != null || activationAttributes != null) 543 { 544 ArrayList props = new ArrayList (); 545 if (entry.ContextAttributes != null) props.AddRange (entry.ContextAttributes); 546 if (activationAttributes != null) props.AddRange (activationAttributes); 547 return CreateClientProxy (entry.ObjectType, entry.ApplicationUrl, props.ToArray ()); 548 } 549 else 550 return CreateClientProxy (entry.ObjectType, entry.ApplicationUrl, null); 551 } 552 CreateClientProxy(Type objectType, string url, object[] activationAttributes)553 internal static object CreateClientProxy (Type objectType, string url, object[] activationAttributes) 554 { 555 string activationUrl = url; 556 if (!activationUrl.EndsWith ("/")) 557 activationUrl += "/"; 558 activationUrl += "RemoteActivationService.rem"; 559 560 string objectUri; 561 GetClientChannelSinkChain (activationUrl, null, out objectUri); 562 563 RemotingProxy proxy = new RemotingProxy (objectType, activationUrl, activationAttributes); 564 return proxy.GetTransparentProxy(); 565 } 566 CreateClientProxy(WellKnownClientTypeEntry entry)567 internal static object CreateClientProxy (WellKnownClientTypeEntry entry) 568 { 569 return Connect (entry.ObjectType, entry.ObjectUrl, null); 570 } 571 CreateClientProxyForContextBound(Type type, object[] activationAttributes)572 internal static object CreateClientProxyForContextBound (Type type, object[] activationAttributes) 573 { 574 if (type.IsContextful) 575 { 576 // Look for a ProxyAttribute 577 ProxyAttribute att = (ProxyAttribute) Attribute.GetCustomAttribute (type, typeof(ProxyAttribute), true); 578 if (att != null) 579 return att.CreateInstance (type); 580 } 581 RemotingProxy proxy = new RemotingProxy (type, ChannelServices.CrossContextUrl, activationAttributes); 582 return proxy.GetTransparentProxy(); 583 } 584 #if !MOBILE CreateClientProxyForComInterop(Type type)585 internal static object CreateClientProxyForComInterop (Type type) 586 { 587 Mono.Interop.ComInteropProxy proxy = Mono.Interop.ComInteropProxy.CreateProxy (type); 588 return proxy.GetTransparentProxy (); 589 } 590 #endif GetIdentityForUri(string uri)591 internal static Identity GetIdentityForUri (string uri) 592 { 593 string normUri = GetNormalizedUri (uri); 594 lock (uri_hash) 595 { 596 Identity i = (Identity) uri_hash [normUri]; 597 598 if (i == null) { 599 normUri = RemoveAppNameFromUri (uri); 600 if (normUri != null) 601 i = (Identity) uri_hash [normUri]; 602 } 603 604 return i; 605 } 606 } 607 608 // 609 // If the specified uri starts with the application name, 610 // RemoveAppNameFromUri returns the uri w/out the leading 611 // application name, otherwise it returns null. 612 // 613 // Assumes that the uri is not normalized. 614 // RemoveAppNameFromUri(string uri)615 static string RemoveAppNameFromUri (string uri) 616 { 617 string name = RemotingConfiguration.ApplicationName; 618 if (name == null) return null; 619 name = "/" + name + "/"; 620 if (uri.StartsWith (name)) 621 return uri.Substring (name.Length); 622 else 623 return null; 624 } 625 GetObjectIdentity(MarshalByRefObject obj)626 internal static Identity GetObjectIdentity (MarshalByRefObject obj) 627 { 628 if (IsTransparentProxy(obj)) 629 return GetRealProxy (obj).ObjectIdentity; 630 else 631 return obj.ObjectIdentity; 632 } 633 GetOrCreateClientIdentity(ObjRef objRef, Type proxyType, out object clientProxy)634 internal static ClientIdentity GetOrCreateClientIdentity(ObjRef objRef, Type proxyType, out object clientProxy) 635 { 636 // This method looks for an identity for the given url. 637 // If an identity is not found, it creates the identity and 638 // assigns it a proxy to the remote object. 639 640 // Creates the client sink chain for the given url or channelData. 641 // It will also get the object uri from the url. 642 643 object channelData = objRef.ChannelInfo != null ? objRef.ChannelInfo.ChannelData : null; 644 645 string objectUri; 646 IMessageSink sink = GetClientChannelSinkChain (objRef.URI, channelData, out objectUri); 647 648 if (objectUri == null) objectUri = objRef.URI; 649 650 lock (uri_hash) 651 { 652 clientProxy = null; 653 string uri = GetNormalizedUri (objRef.URI); 654 655 ClientIdentity identity = uri_hash [uri] as ClientIdentity; 656 if (identity != null) 657 { 658 // Object already registered 659 clientProxy = identity.ClientProxy; 660 if (clientProxy != null) return identity; 661 662 // The proxy has just been GCed, so its identity cannot 663 // be reused. Just dispose it. 664 DisposeIdentity (identity); 665 } 666 667 // Creates an identity and a proxy for the remote object 668 669 identity = new ClientIdentity (objectUri, objRef); 670 identity.ChannelSink = sink; 671 672 // Registers the identity 673 uri_hash [uri] = identity; 674 if (proxyType != null) 675 { 676 RemotingProxy proxy = new RemotingProxy (proxyType, identity); 677 CrossAppDomainSink cds = sink as CrossAppDomainSink; 678 if (cds != null) 679 proxy.SetTargetDomain (cds.TargetDomainId); 680 681 clientProxy = proxy.GetTransparentProxy(); 682 identity.ClientProxy = (MarshalByRefObject) clientProxy; 683 } 684 return identity; 685 } 686 } 687 GetClientChannelSinkChain(string url, object channelData, out string objectUri)688 static IMessageSink GetClientChannelSinkChain(string url, object channelData, out string objectUri) 689 { 690 IMessageSink sink = ChannelServices.CreateClientChannelSinkChain (url, channelData, out objectUri); 691 if (sink == null) 692 { 693 if (url != null) 694 { 695 string msg = String.Format ("Cannot create channel sink to connect to URL {0}. An appropriate channel has probably not been registered.", url); 696 throw new RemotingException (msg); 697 } 698 else 699 { 700 string msg = String.Format ("Cannot create channel sink to connect to the remote object. An appropriate channel has probably not been registered.", url); 701 throw new RemotingException (msg); 702 } 703 } 704 return sink; 705 } 706 CreateContextBoundObjectIdentity(Type objectType)707 internal static ClientActivatedIdentity CreateContextBoundObjectIdentity(Type objectType) 708 { 709 ClientActivatedIdentity identity = new ClientActivatedIdentity (null, objectType); 710 identity.ChannelSink = ChannelServices.CrossContextChannel; 711 return identity; 712 } 713 CreateClientActivatedServerIdentity(MarshalByRefObject realObject, Type objectType, string objectUri)714 internal static ClientActivatedIdentity CreateClientActivatedServerIdentity(MarshalByRefObject realObject, Type objectType, string objectUri) 715 { 716 ClientActivatedIdentity identity = new ClientActivatedIdentity (objectUri, objectType); 717 identity.AttachServerObject (realObject, Context.DefaultContext); 718 RegisterServerIdentity (identity); 719 identity.StartTrackingLifetime ((ILease)realObject.InitializeLifetimeService ()); 720 return identity; 721 } 722 CreateWellKnownServerIdentity(Type objectType, string objectUri, WellKnownObjectMode mode)723 internal static ServerIdentity CreateWellKnownServerIdentity(Type objectType, string objectUri, WellKnownObjectMode mode) 724 { 725 ServerIdentity identity; 726 727 if (mode == WellKnownObjectMode.SingleCall) 728 identity = new SingleCallIdentity(objectUri, Context.DefaultContext, objectType); 729 else 730 identity = new SingletonIdentity(objectUri, Context.DefaultContext, objectType); 731 732 RegisterServerIdentity (identity); 733 return identity; 734 } 735 RegisterServerIdentity(ServerIdentity identity)736 private static void RegisterServerIdentity(ServerIdentity identity) 737 { 738 lock (uri_hash) 739 { 740 if (uri_hash.ContainsKey (identity.ObjectUri)) 741 throw new RemotingException ("Uri already in use: " + identity.ObjectUri + "."); 742 743 uri_hash[identity.ObjectUri] = identity; 744 } 745 } 746 GetProxyForRemoteObject(ObjRef objref, Type classToProxy)747 internal static object GetProxyForRemoteObject (ObjRef objref, Type classToProxy) 748 { 749 ClientActivatedIdentity identity = GetIdentityForUri (objref.URI) as ClientActivatedIdentity; 750 if (identity != null) return identity.GetServerObject (); 751 else return GetRemoteObject (objref, classToProxy); 752 } 753 GetRemoteObject(ObjRef objRef, Type proxyType)754 internal static object GetRemoteObject(ObjRef objRef, Type proxyType) 755 { 756 object proxy; 757 GetOrCreateClientIdentity (objRef, proxyType, out proxy); 758 return proxy; 759 } 760 761 // This method is called by the runtime GetServerObject(string uri)762 internal static object GetServerObject (string uri) 763 { 764 ClientActivatedIdentity identity = GetIdentityForUri (uri) as ClientActivatedIdentity; 765 if (identity == null) throw new RemotingException ("Server for uri '" + uri + "' not found"); 766 return identity.GetServerObject (); 767 } 768 769 // This method is called by the runtime 770 [SecurityPermission (SecurityAction.Assert, SerializationFormatter = true)] // FIXME: to be reviewed SerializeCallData(object obj)771 internal static byte[] SerializeCallData (object obj) 772 { 773 var ctx = Thread.CurrentThread.GetExecutionContextReader().LogicalCallContext; 774 if (!ctx.IsNull) { 775 CACD cad = new CACD (); 776 cad.d = obj; 777 cad.c = ctx.Clone (); 778 obj = cad; 779 } 780 781 if (obj == null) return null; 782 MemoryStream ms = new MemoryStream (); 783 _serializationFormatter.Serialize (ms, obj); 784 return ms.ToArray (); 785 } 786 787 // This method is called by the runtime 788 [SecurityPermission (SecurityAction.Assert, SerializationFormatter = true)] // FIXME: to be reviewed DeserializeCallData(byte[] array)789 internal static object DeserializeCallData (byte[] array) 790 { 791 if (array == null) return null; 792 793 MemoryStream ms = new MemoryStream (array); 794 object obj = _deserializationFormatter.Deserialize (ms); 795 796 if (obj is CACD) { 797 CACD cad = (CACD) obj; 798 obj = cad.d; 799 800 var lcc = (LogicalCallContext) cad.c; 801 if (lcc.HasInfo) 802 Thread.CurrentThread.GetMutableExecutionContext().LogicalCallContext.Merge (lcc); 803 } 804 return obj; 805 } 806 807 // This method is called by the runtime 808 [SecurityPermission (SecurityAction.Assert, SerializationFormatter = true)] // FIXME: to be reviewed SerializeExceptionData(Exception ex)809 internal static byte[] SerializeExceptionData (Exception ex) 810 { 811 byte[] result = null; 812 try { 813 /* empty - we're only interested in the protected block */ 814 } finally { 815 MemoryStream ms = new MemoryStream (); 816 _serializationFormatter.Serialize (ms, ex); 817 result = ms.ToArray (); 818 } 819 return result; 820 } 821 GetDomainProxy(AppDomain domain)822 internal static object GetDomainProxy(AppDomain domain) 823 { 824 byte[] data = null; 825 826 Context currentContext = Thread.CurrentContext; 827 828 try 829 { 830 data = (byte[])AppDomain.InvokeInDomain (domain, typeof (AppDomain).GetMethod ("GetMarshalledDomainObjRef", BindingFlags.Instance|BindingFlags.NonPublic), domain, null); 831 } 832 finally 833 { 834 AppDomain.InternalSetContext (currentContext); 835 } 836 837 byte[] data_copy = new byte [data.Length]; 838 data.CopyTo (data_copy, 0); 839 MemoryStream stream = new MemoryStream (data_copy); 840 ObjRef appref = (ObjRef) CADSerializer.DeserializeObject (stream); 841 return (AppDomain) RemotingServices.Unmarshal(appref); 842 } 843 RegisterInternalChannels()844 private static void RegisterInternalChannels() 845 { 846 CrossAppDomainChannel.RegisterCrossAppDomainChannel(); 847 } 848 DisposeIdentity(Identity ident)849 internal static void DisposeIdentity (Identity ident) 850 { 851 lock (uri_hash) 852 { 853 if (!ident.Disposed) { 854 ClientIdentity clientId = ident as ClientIdentity; 855 if (clientId != null) 856 uri_hash.Remove (GetNormalizedUri (clientId.TargetUri)); 857 else 858 uri_hash.Remove (ident.ObjectUri); 859 860 ident.Disposed = true; 861 } 862 } 863 } 864 GetMessageTargetIdentity(IMessage msg)865 internal static Identity GetMessageTargetIdentity (IMessage msg) 866 { 867 // Returns the identity where the message is sent 868 869 if (msg is IInternalMessage) 870 return ((IInternalMessage)msg).TargetIdentity; 871 872 lock (uri_hash) 873 { 874 string uri = GetNormalizedUri (((IMethodMessage)msg).Uri); 875 return uri_hash [uri] as ServerIdentity; 876 } 877 } 878 SetMessageTargetIdentity(IMessage msg, Identity ident)879 internal static void SetMessageTargetIdentity (IMessage msg, Identity ident) 880 { 881 if (msg is IInternalMessage) 882 ((IInternalMessage)msg).TargetIdentity = ident; 883 } 884 UpdateOutArgObject(ParameterInfo pi, object local, object remote)885 internal static bool UpdateOutArgObject (ParameterInfo pi, object local, object remote) 886 { 887 if (pi.ParameterType.IsArray && ((Array)local).Rank == 1) 888 { 889 Array alocal = (Array) local; 890 if (alocal.Rank == 1) 891 { 892 Array.Copy ((Array) remote, alocal, alocal.Length); 893 return true; 894 } 895 else 896 { 897 // TODO 898 } 899 } 900 return false; 901 } 902 GetNormalizedUri(string uri)903 static string GetNormalizedUri (string uri) 904 { 905 if (uri.StartsWith ("/")) return uri.Substring (1); 906 else return uri; 907 } 908 909 #endregion 910 } 911 } 912