2 // System.Runtime.Remoting.RemotingServices.cs
5 // Dietmar Maurer (dietmar@ximian.com)
6 // Lluis Sanchez Gual (lluis@ideary.com)
9 // (C) 2001 Ximian, Inc. http://www.ximian.com
10 // Copyright (C) 2004, 2006 Novell, Inc (http://www.novell.com)
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:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
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.
32 using System
.Diagnostics
;
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
;
47 using System
.Runtime
.Remoting
.Services
;
48 using System
.Security
.Permissions
;
49 using System
.Runtime
.ConstrainedExecution
;
50 using System
.Runtime
.Serialization
.Formatters
;
52 namespace System
.Runtime
.Remoting
54 [System
.Runtime
.InteropServices
.ComVisible (true)]
55 public sealed class RemotingServices
57 // Holds the identities of the objects, using uri as index
58 static Hashtable uri_hash
= new Hashtable ();
60 static BinaryFormatter _serializationFormatter
;
61 static BinaryFormatter _deserializationFormatter
;
64 static readonly object app_id_lock
= new object ();
66 static int next_id
= 1;
67 const BindingFlags methodBindings
= BindingFlags
.Instance
| BindingFlags
.Public
| BindingFlags
.NonPublic
;
68 static readonly MethodInfo FieldSetterMethod
;
69 static readonly MethodInfo FieldGetterMethod
;
71 // Holds information in xdomain calls. Names are short to minimize serialized size.
74 public object d
; /* call data */
75 public object c
; /* call context */
78 static RemotingServices ()
80 RemotingSurrogateSelector surrogateSelector
= new RemotingSurrogateSelector ();
81 StreamingContext context
= new StreamingContext (StreamingContextStates
.Remoting
, null);
82 _serializationFormatter
= new BinaryFormatter (surrogateSelector
, context
);
83 _deserializationFormatter
= new BinaryFormatter (null, context
);
84 _serializationFormatter
.AssemblyFormat
= FormatterAssemblyStyle
.Full
;
85 _deserializationFormatter
.AssemblyFormat
= FormatterAssemblyStyle
.Full
;
87 RegisterInternalChannels ();
88 CreateWellKnownServerIdentity (typeof(RemoteActivator
), "RemoteActivationService.rem", WellKnownObjectMode
.Singleton
);
90 FieldSetterMethod
= typeof(object).GetMethod ("FieldSetter", BindingFlags
.NonPublic
|BindingFlags
.Instance
);
91 FieldGetterMethod
= typeof(object).GetMethod ("FieldGetter", BindingFlags
.NonPublic
|BindingFlags
.Instance
);
94 private RemotingServices () {}
96 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
97 internal extern static object InternalExecute (MethodBase method
, Object obj
,
98 Object
[] parameters
, out object [] out_args
);
100 // Returns the actual implementation of @method in @type.
101 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
102 internal extern static MethodBase
GetVirtualMethod (Type type
, MethodBase method
);
104 [ReliabilityContractAttribute (Consistency
.WillNotCorruptState
, Cer
.Success
)]
105 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
106 public extern static bool IsTransparentProxy (object proxy
);
108 internal static IMethodReturnMessage
InternalExecuteMessage (
109 MarshalByRefObject target
, IMethodCallMessage reqMsg
)
111 ReturnMessage result
;
113 Type tt
= target
.GetType ();
115 if (reqMsg
.MethodBase
.DeclaringType
== tt
||
116 reqMsg
.MethodBase
== FieldSetterMethod
||
117 reqMsg
.MethodBase
== FieldGetterMethod
) {
118 method
= reqMsg
.MethodBase
;
120 method
= GetVirtualMethod (tt
, reqMsg
.MethodBase
);
123 throw new RemotingException (
124 String
.Format ("Cannot resolve method {0}:{1}", tt
, reqMsg
.MethodName
));
127 if (reqMsg
.MethodBase
.IsGenericMethod
) {
128 Type
[] genericArguments
= reqMsg
.MethodBase
.GetGenericArguments ();
129 MethodInfo gmd
= ((MethodInfo
)method
).GetGenericMethodDefinition ();
130 method
= gmd
.MakeGenericMethod (genericArguments
);
133 object oldContext
= CallContext
.SetCurrentCallContext (reqMsg
.LogicalCallContext
);
138 object rval
= InternalExecute (method
, target
, reqMsg
.Args
, out out_args
);
140 // Collect parameters with Out flag from the request message
141 // FIXME: This can be done in the unmanaged side and will be
144 ParameterInfo
[] parameters
= method
.GetParameters();
145 object[] returnArgs
= new object [parameters
.Length
];
149 foreach (ParameterInfo par
in parameters
)
151 if (par
.IsOut
&& !par
.ParameterType
.IsByRef
)
152 returnArgs
[n
++] = reqMsg
.GetArg (par
.Position
);
153 else if (par
.ParameterType
.IsByRef
)
154 returnArgs
[n
++] = out_args
[noa
++];
156 returnArgs
[n
++] = null;
159 result
= new ReturnMessage (rval
, returnArgs
, n
, CallContext
.CreateLogicalCallContext (true), reqMsg
);
163 result
= new ReturnMessage (e
, reqMsg
);
166 CallContext
.RestoreCallContext (oldContext
);
170 public static IMethodReturnMessage
ExecuteMessage (
171 MarshalByRefObject target
, IMethodCallMessage reqMsg
)
173 if (IsTransparentProxy(target
))
175 // Message must go through all chain of sinks
176 RealProxy rp
= GetRealProxy (target
);
177 return (IMethodReturnMessage
) rp
.Invoke (reqMsg
);
180 return InternalExecuteMessage (target
, reqMsg
);
183 [System
.Runtime
.InteropServices
.ComVisible (true)]
184 public static object Connect (Type classToProxy
, string url
)
186 ObjRef objRef
= new ObjRef (classToProxy
, url
, null);
187 return GetRemoteObject (objRef
, classToProxy
);
190 [System
.Runtime
.InteropServices
.ComVisible (true)]
191 public static object Connect (Type classToProxy
, string url
, object data
)
193 ObjRef objRef
= new ObjRef (classToProxy
, url
, data
);
194 return GetRemoteObject (objRef
, classToProxy
);
197 public static bool Disconnect (MarshalByRefObject obj
)
199 if (obj
== null) throw new ArgumentNullException ("obj");
201 ServerIdentity identity
;
203 if (IsTransparentProxy (obj
))
205 // CBOs are always accessed through a proxy, even in the server, so
206 // for server CBOs it is ok to disconnect a proxy
208 RealProxy proxy
= GetRealProxy(obj
);
209 if (proxy
.GetProxiedType().IsContextful
&& (proxy
.ObjectIdentity
is ServerIdentity
))
210 identity
= proxy
.ObjectIdentity
as ServerIdentity
;
212 throw new ArgumentException ("The obj parameter is a proxy.");
215 identity
= obj
.ObjectIdentity
;
216 obj
.ObjectIdentity
= null;
219 if (identity
== null || !identity
.IsConnected
)
223 LifetimeServices
.StopTrackingLifetime (identity
);
224 DisposeIdentity (identity
);
225 TrackingServices
.NotifyDisconnectedObject (obj
);
230 public static Type
GetServerTypeForUri (string URI
)
232 ServerIdentity ident
= GetIdentityForUri (URI
) as ServerIdentity
;
233 if (ident
== null) return null;
234 return ident
.ObjectType
;
237 public static string GetObjectUri (MarshalByRefObject obj
)
239 Identity ident
= GetObjectIdentity(obj
);
240 if (ident
is ClientIdentity
) return ((ClientIdentity
)ident
).TargetUri
;
241 else if (ident
!= null) return ident
.ObjectUri
;
245 public static object Unmarshal (ObjRef objectRef
)
247 return Unmarshal (objectRef
, true);
250 public static object Unmarshal (ObjRef objectRef
, bool fRefine
)
252 Type classToProxy
= fRefine
? objectRef
.ServerType
: typeof (MarshalByRefObject
);
253 if (classToProxy
== null) classToProxy
= typeof (MarshalByRefObject
);
255 if (objectRef
.IsReferenceToWellKnow
) {
256 object obj
= GetRemoteObject (objectRef
, classToProxy
);
257 TrackingServices
.NotifyUnmarshaledObject (obj
, objectRef
);
264 if (classToProxy
.IsContextful
) {
265 // Look for a ProxyAttribute
266 ProxyAttribute att
= (ProxyAttribute
) Attribute
.GetCustomAttribute (classToProxy
, typeof(ProxyAttribute
), true);
268 obj
= att
.CreateProxy (objectRef
, classToProxy
, null, null).GetTransparentProxy();
269 TrackingServices
.NotifyUnmarshaledObject (obj
, objectRef
);
273 obj
= GetProxyForRemoteObject (objectRef
, classToProxy
);
274 TrackingServices
.NotifyUnmarshaledObject (obj
, objectRef
);
279 public static ObjRef
Marshal (MarshalByRefObject Obj
)
281 return Marshal (Obj
, null, null);
284 public static ObjRef
Marshal (MarshalByRefObject Obj
, string URI
)
286 return Marshal (Obj
, URI
, null);
289 public static ObjRef
Marshal (MarshalByRefObject Obj
, string ObjURI
, Type RequestedType
)
291 if (IsTransparentProxy (Obj
))
293 RealProxy proxy
= RemotingServices
.GetRealProxy (Obj
);
294 Identity identity
= proxy
.ObjectIdentity
;
296 if (identity
!= null)
298 if (proxy
.GetProxiedType().IsContextful
&& !identity
.IsConnected
)
300 // Unregistered local contextbound object. Register now.
301 ClientActivatedIdentity cboundIdentity
= (ClientActivatedIdentity
)identity
;
302 if (ObjURI
== null) ObjURI
= NewUri();
303 cboundIdentity
.ObjectUri
= ObjURI
;
304 RegisterServerIdentity (cboundIdentity
);
305 cboundIdentity
.StartTrackingLifetime ((ILease
)Obj
.InitializeLifetimeService());
306 return cboundIdentity
.CreateObjRef (RequestedType
);
308 else if (ObjURI
!= null)
309 throw new RemotingException ("It is not possible marshal a proxy of a remote object.");
311 ObjRef or
= proxy
.ObjectIdentity
.CreateObjRef (RequestedType
);
312 TrackingServices
.NotifyMarshaledObject (Obj
, or
);
317 if (RequestedType
== null) RequestedType
= Obj
.GetType ();
321 if (Obj
.ObjectIdentity
== null)
324 CreateClientActivatedServerIdentity (Obj
, RequestedType
, ObjURI
);
329 ClientActivatedIdentity identity
= GetIdentityForUri ("/" + ObjURI
) as ClientActivatedIdentity
;
330 if (identity
== null || Obj
!= identity
.GetServerObject())
331 CreateClientActivatedServerIdentity (Obj
, RequestedType
, ObjURI
);
336 if (IsTransparentProxy (Obj
))
337 oref
= RemotingServices
.GetRealProxy (Obj
).ObjectIdentity
.CreateObjRef (RequestedType
);
339 oref
= Obj
.CreateObjRef (RequestedType
);
341 TrackingServices
.NotifyMarshaledObject (Obj
, oref
);
345 static string NewUri ()
347 if (app_id
== null) {
350 app_id
= Guid
.NewGuid().ToString().Replace('-', '_') + "/";
354 int n
= Interlocked
.Increment (ref next_id
);
355 return app_id
+ Environment
.TickCount
.ToString("x") + "_" + n
+ ".rem";
358 [ReliabilityContractAttribute (Consistency
.WillNotCorruptState
, Cer
.Success
)]
359 public static RealProxy
GetRealProxy (object proxy
)
361 if (!IsTransparentProxy(proxy
)) throw new RemotingException("Cannot get the real proxy from an object that is not a transparent proxy.");
362 return (RealProxy
)((TransparentProxy
)proxy
)._rp
;
365 public static MethodBase
GetMethodBaseFromMethodMessage(IMethodMessage msg
)
367 Type type
= Type
.GetType (msg
.TypeName
);
369 throw new RemotingException ("Type '" + msg
.TypeName
+ "' not found.");
371 return GetMethodBaseFromName (type
, msg
.MethodName
, (Type
[]) msg
.MethodSignature
);
374 internal static MethodBase
GetMethodBaseFromName (Type type
, string methodName
, Type
[] signature
)
376 if (type
.IsInterface
) {
377 return FindInterfaceMethod (type
, methodName
, signature
);
380 MethodBase method
= null;
381 if (signature
== null)
382 method
= type
.GetMethod (methodName
, methodBindings
);
384 method
= type
.GetMethod (methodName
, methodBindings
, null, (Type
[]) signature
, null);
389 if (methodName
== "FieldSetter")
390 return FieldSetterMethod
;
392 if (methodName
== "FieldGetter")
393 return FieldGetterMethod
;
395 if (signature
== null)
396 return type
.GetConstructor (methodBindings
, null, Type
.EmptyTypes
, null);
398 return type
.GetConstructor (methodBindings
, null, signature
, null);
402 static MethodBase
FindInterfaceMethod (Type type
, string methodName
, Type
[] signature
)
404 MethodBase method
= null;
406 if (signature
== null)
407 method
= type
.GetMethod (methodName
, methodBindings
);
409 method
= type
.GetMethod (methodName
, methodBindings
, null, signature
, null);
411 if (method
!= null) return method
;
413 foreach (Type t
in type
.GetInterfaces ()) {
414 method
= FindInterfaceMethod (t
, methodName
, signature
);
415 if (method
!= null) return method
;
421 public static void GetObjectData(object obj
, SerializationInfo info
, StreamingContext context
)
423 if (obj
== null) throw new ArgumentNullException ("obj");
425 ObjRef oref
= Marshal ((MarshalByRefObject
)obj
);
426 oref
.GetObjectData (info
, context
);
429 public static ObjRef
GetObjRefForProxy(MarshalByRefObject obj
)
431 Identity ident
= GetObjectIdentity(obj
);
432 if (ident
== null) return null;
433 else return ident
.CreateObjRef(null);
436 public static object GetLifetimeService (MarshalByRefObject obj
)
438 if (obj
== null) return null;
439 return obj
.GetLifetimeService ();
442 public static IMessageSink
GetEnvoyChainForProxy (MarshalByRefObject obj
)
444 if (IsTransparentProxy(obj
))
445 return ((ClientIdentity
)GetRealProxy (obj
).ObjectIdentity
).EnvoySink
;
447 throw new ArgumentException ("obj must be a proxy.","obj");
451 [Conditional ("REMOTING_PERF")]
452 [Obsolete ("It existed for only internal use in .NET and unimplemented in mono")]
453 public static void LogRemotingStage (int stage
)
455 throw new NotImplementedException ();
458 public static string GetSessionIdForMethodMessage(IMethodMessage msg
)
460 // It seems that this it what MS returns.
464 public static bool IsMethodOverloaded(IMethodMessage msg
)
466 const BindingFlags bfinst
= BindingFlags
.NonPublic
| BindingFlags
.Public
| BindingFlags
.Instance
;
467 MonoType type
= (MonoType
) msg
.MethodBase
.DeclaringType
;
468 return type
.GetMethodsByName (msg
.MethodName
, bfinst
, false, type
).Length
> 1;
471 public static bool IsObjectOutOfAppDomain(object tp
)
473 MarshalByRefObject mbr
= tp
as MarshalByRefObject
;
478 // TODO: use internal call for better performance
479 Identity ident
= GetObjectIdentity (mbr
);
480 return ident
is ClientIdentity
;
483 public static bool IsObjectOutOfContext(object tp
)
485 MarshalByRefObject mbr
= tp
as MarshalByRefObject
;
490 // TODO: use internal call for better performance
491 Identity ident
= GetObjectIdentity (mbr
);
492 if (ident
== null) return false;
494 ServerIdentity sident
= ident
as ServerIdentity
;
495 if (sident
!= null) return sident
.Context
!= System
.Threading
.Thread
.CurrentContext
;
499 public static bool IsOneWay(MethodBase method
)
501 return method
.IsDefined (typeof (OneWayAttribute
), false);
504 internal static bool IsAsyncMessage(IMessage msg
)
506 if (! (msg
is MonoMethodMessage
)) return false;
507 else if (((MonoMethodMessage
)msg
).IsAsync
) return true;
508 else if (IsOneWay (((MonoMethodMessage
)msg
).MethodBase
)) return true;
512 public static void SetObjectUriForMarshal(MarshalByRefObject obj
, string uri
)
514 if (IsTransparentProxy (obj
)) {
515 RealProxy proxy
= RemotingServices
.GetRealProxy(obj
);
516 Identity identity
= proxy
.ObjectIdentity
;
518 if (identity
!= null && !(identity
is ServerIdentity
) && !proxy
.GetProxiedType().IsContextful
)
519 throw new RemotingException ("SetObjectUriForMarshal method should only be called for MarshalByRefObjects that exist in the current AppDomain.");
525 #region Internal Methods
527 internal static object CreateClientProxy (ActivatedClientTypeEntry entry
, object[] activationAttributes
)
529 if (entry
.ContextAttributes
!= null || activationAttributes
!= null)
531 ArrayList props
= new ArrayList ();
532 if (entry
.ContextAttributes
!= null) props
.AddRange (entry
.ContextAttributes
);
533 if (activationAttributes
!= null) props
.AddRange (activationAttributes
);
534 return CreateClientProxy (entry
.ObjectType
, entry
.ApplicationUrl
, props
.ToArray ());
537 return CreateClientProxy (entry
.ObjectType
, entry
.ApplicationUrl
, null);
540 internal static object CreateClientProxy (Type objectType
, string url
, object[] activationAttributes
)
542 string activationUrl
= url
;
543 if (!activationUrl
.EndsWith ("/"))
544 activationUrl
+= "/";
545 activationUrl
+= "RemoteActivationService.rem";
548 GetClientChannelSinkChain (activationUrl
, null, out objectUri
);
550 RemotingProxy proxy
= new RemotingProxy (objectType
, activationUrl
, activationAttributes
);
551 return proxy
.GetTransparentProxy();
554 internal static object CreateClientProxy (WellKnownClientTypeEntry entry
)
556 return Connect (entry
.ObjectType
, entry
.ObjectUrl
, null);
559 internal static object CreateClientProxyForContextBound (Type type
, object[] activationAttributes
)
561 if (type
.IsContextful
)
563 // Look for a ProxyAttribute
564 ProxyAttribute att
= (ProxyAttribute
) Attribute
.GetCustomAttribute (type
, typeof(ProxyAttribute
), true);
566 return att
.CreateInstance (type
);
568 RemotingProxy proxy
= new RemotingProxy (type
, ChannelServices
.CrossContextUrl
, activationAttributes
);
569 return proxy
.GetTransparentProxy();
572 internal static object CreateClientProxyForComInterop (Type type
)
574 Mono
.Interop
.ComInteropProxy proxy
= Mono
.Interop
.ComInteropProxy
.CreateProxy (type
);
575 return proxy
.GetTransparentProxy ();
578 internal static Identity
GetIdentityForUri (string uri
)
580 string normUri
= GetNormalizedUri (uri
);
583 Identity i
= (Identity
) uri_hash
[normUri
];
586 normUri
= RemoveAppNameFromUri (uri
);
588 i
= (Identity
) uri_hash
[normUri
];
596 // If the specified uri starts with the application name,
597 // RemoveAppNameFromUri returns the uri w/out the leading
598 // application name, otherwise it returns null.
600 // Assumes that the uri is not normalized.
602 static string RemoveAppNameFromUri (string uri
)
604 string name
= RemotingConfiguration
.ApplicationName
;
605 if (name
== null) return null;
606 name
= "/" + name
+ "/";
607 if (uri
.StartsWith (name
))
608 return uri
.Substring (name
.Length
);
613 internal static Identity
GetObjectIdentity (MarshalByRefObject obj
)
615 if (IsTransparentProxy(obj
))
616 return GetRealProxy (obj
).ObjectIdentity
;
618 return obj
.ObjectIdentity
;
621 internal static ClientIdentity
GetOrCreateClientIdentity(ObjRef objRef
, Type proxyType
, out object clientProxy
)
623 // This method looks for an identity for the given url.
624 // If an identity is not found, it creates the identity and
625 // assigns it a proxy to the remote object.
627 // Creates the client sink chain for the given url or channelData.
628 // It will also get the object uri from the url.
630 object channelData
= objRef
.ChannelInfo
!= null ? objRef
.ChannelInfo
.ChannelData
: null;
633 IMessageSink sink
= GetClientChannelSinkChain (objRef
.URI
, channelData
, out objectUri
);
635 if (objectUri
== null) objectUri
= objRef
.URI
;
640 string uri
= GetNormalizedUri (objRef
.URI
);
642 ClientIdentity identity
= uri_hash
[uri
] as ClientIdentity
;
643 if (identity
!= null)
645 // Object already registered
646 clientProxy
= identity
.ClientProxy
;
647 if (clientProxy
!= null) return identity
;
649 // The proxy has just been GCed, so its identity cannot
650 // be reused. Just dispose it.
651 DisposeIdentity (identity
);
654 // Creates an identity and a proxy for the remote object
656 identity
= new ClientIdentity (objectUri
, objRef
);
657 identity
.ChannelSink
= sink
;
659 // Registers the identity
660 uri_hash
[uri
] = identity
;
662 if (proxyType
!= null)
664 RemotingProxy proxy
= new RemotingProxy (proxyType
, identity
);
665 CrossAppDomainSink cds
= sink
as CrossAppDomainSink
;
667 proxy
.SetTargetDomain (cds
.TargetDomainId
);
669 clientProxy
= proxy
.GetTransparentProxy();
670 identity
.ClientProxy
= (MarshalByRefObject
) clientProxy
;
677 static IMessageSink
GetClientChannelSinkChain(string url
, object channelData
, out string objectUri
)
679 IMessageSink sink
= ChannelServices
.CreateClientChannelSinkChain (url
, channelData
, out objectUri
);
684 string msg
= String
.Format ("Cannot create channel sink to connect to URL {0}. An appropriate channel has probably not been registered.", url
);
685 throw new RemotingException (msg
);
689 string msg
= String
.Format ("Cannot create channel sink to connect to the remote object. An appropriate channel has probably not been registered.", url
);
690 throw new RemotingException (msg
);
696 internal static ClientActivatedIdentity
CreateContextBoundObjectIdentity(Type objectType
)
698 ClientActivatedIdentity identity
= new ClientActivatedIdentity (null, objectType
);
699 identity
.ChannelSink
= ChannelServices
.CrossContextChannel
;
703 internal static ClientActivatedIdentity
CreateClientActivatedServerIdentity(MarshalByRefObject realObject
, Type objectType
, string objectUri
)
705 ClientActivatedIdentity identity
= new ClientActivatedIdentity (objectUri
, objectType
);
706 identity
.AttachServerObject (realObject
, Context
.DefaultContext
);
707 RegisterServerIdentity (identity
);
708 identity
.StartTrackingLifetime ((ILease
)realObject
.InitializeLifetimeService ());
712 internal static ServerIdentity
CreateWellKnownServerIdentity(Type objectType
, string objectUri
, WellKnownObjectMode mode
)
714 ServerIdentity identity
;
716 if (mode
== WellKnownObjectMode
.SingleCall
)
717 identity
= new SingleCallIdentity(objectUri
, Context
.DefaultContext
, objectType
);
719 identity
= new SingletonIdentity(objectUri
, Context
.DefaultContext
, objectType
);
721 RegisterServerIdentity (identity
);
725 private static void RegisterServerIdentity(ServerIdentity identity
)
729 if (uri_hash
.ContainsKey (identity
.ObjectUri
))
730 throw new RemotingException ("Uri already in use: " + identity
.ObjectUri
+ ".");
732 uri_hash
[identity
.ObjectUri
] = identity
;
736 internal static object GetProxyForRemoteObject (ObjRef objref
, Type classToProxy
)
738 ClientActivatedIdentity identity
= GetIdentityForUri (objref
.URI
) as ClientActivatedIdentity
;
739 if (identity
!= null) return identity
.GetServerObject ();
740 else return GetRemoteObject (objref
, classToProxy
);
743 internal static object GetRemoteObject(ObjRef objRef
, Type proxyType
)
746 GetOrCreateClientIdentity (objRef
, proxyType
, out proxy
);
750 // This method is called by the runtime
751 internal static object GetServerObject (string uri
)
753 ClientActivatedIdentity identity
= GetIdentityForUri (uri
) as ClientActivatedIdentity
;
754 if (identity
== null) throw new RemotingException ("Server for uri '" + uri
+ "' not found");
755 return identity
.GetServerObject ();
758 // This method is called by the runtime
759 [SecurityPermission (SecurityAction
.Assert
, SerializationFormatter
= true)] // FIXME: to be reviewed
760 internal static byte[] SerializeCallData (object obj
)
762 LogicalCallContext ctx
= CallContext
.CreateLogicalCallContext (false);
764 CACD cad
= new CACD ();
770 if (obj
== null) return null;
771 MemoryStream ms
= new MemoryStream ();
772 _serializationFormatter
.Serialize (ms
, obj
);
773 return ms
.ToArray ();
776 // This method is called by the runtime
777 [SecurityPermission (SecurityAction
.Assert
, SerializationFormatter
= true)] // FIXME: to be reviewed
778 internal static object DeserializeCallData (byte[] array
)
780 if (array
== null) return null;
782 MemoryStream ms
= new MemoryStream (array
);
783 object obj
= _deserializationFormatter
.Deserialize (ms
);
786 CACD cad
= (CACD
) obj
;
788 CallContext
.UpdateCurrentCallContext ((LogicalCallContext
) cad
.c
);
793 // This method is called by the runtime
794 [SecurityPermission (SecurityAction
.Assert
, SerializationFormatter
= true)] // FIXME: to be reviewed
795 internal static byte[] SerializeExceptionData (Exception ex
)
802 MemoryStream ms
= new MemoryStream ();
803 _serializationFormatter
.Serialize (ms
, ex
);
804 return ms
.ToArray ();
806 catch (Exception e
) {
807 if (e
is ThreadAbortException
) {
808 Thread
.ResetAbort ();
812 else if (retry
== 2) {
813 ex
= new Exception ();
814 ex
.SetMessage (e
.Message
);
815 ex
.SetStackTrace (e
.StackTrace
);
826 catch (Exception tex
)
828 byte[] data
= SerializeExceptionData (tex
);
829 Thread
.ResetAbort ();
834 internal static object GetDomainProxy(AppDomain domain
)
838 Context currentContext
= Thread
.CurrentContext
;
842 data
= (byte[])AppDomain
.InvokeInDomain (domain
, typeof (AppDomain
).GetMethod ("GetMarshalledDomainObjRef", BindingFlags
.Instance
|BindingFlags
.NonPublic
), domain
, null);
846 AppDomain
.InternalSetContext (currentContext
);
849 byte[] data_copy
= new byte [data
.Length
];
850 data
.CopyTo (data_copy
, 0);
851 MemoryStream stream
= new MemoryStream (data_copy
);
852 ObjRef appref
= (ObjRef
) CADSerializer
.DeserializeObject (stream
);
853 return (AppDomain
) RemotingServices
.Unmarshal(appref
);
856 private static void RegisterInternalChannels()
858 CrossAppDomainChannel
.RegisterCrossAppDomainChannel();
861 internal static void DisposeIdentity (Identity ident
)
865 if (!ident
.Disposed
) {
866 ClientIdentity clientId
= ident
as ClientIdentity
;
867 if (clientId
!= null)
868 uri_hash
.Remove (GetNormalizedUri (clientId
.TargetUri
));
870 uri_hash
.Remove (ident
.ObjectUri
);
872 ident
.Disposed
= true;
877 internal static Identity
GetMessageTargetIdentity (IMessage msg
)
879 // Returns the identity where the message is sent
881 if (msg
is IInternalMessage
)
882 return ((IInternalMessage
)msg
).TargetIdentity
;
886 string uri
= GetNormalizedUri (((IMethodMessage
)msg
).Uri
);
887 return uri_hash
[uri
] as ServerIdentity
;
891 internal static void SetMessageTargetIdentity (IMessage msg
, Identity ident
)
893 if (msg
is IInternalMessage
)
894 ((IInternalMessage
)msg
).TargetIdentity
= ident
;
897 internal static bool UpdateOutArgObject (ParameterInfo pi
, object local
, object remote
)
899 if (pi
.ParameterType
.IsArray
&& ((Array
)local
).Rank
== 1)
901 Array alocal
= (Array
) local
;
902 if (alocal
.Rank
== 1)
904 Array
.Copy ((Array
) remote
, alocal
, alocal
.Length
);
915 static string GetNormalizedUri (string uri
)
917 if (uri
.StartsWith ("/")) return uri
.Substring (1);