//
using System;
+using System.Text;
using System.Reflection;
using System.Threading;
using System.Collections;
ReturnMessage result;
MonoMethod method = (MonoMethod) target.GetType().GetMethod(reqMsg.MethodName, BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance, null, (Type[]) reqMsg.MethodSignature, null);
-
- try {
+ object oldContext = CallContext.SetCurrentCallContext (reqMsg.LogicalCallContext);
+
+ try
+ {
object [] out_args;
object rval = InternalExecute (method, target, reqMsg.Args, out out_args);
- result = new ReturnMessage (rval, out_args, out_args.Length,
- reqMsg.LogicalCallContext, reqMsg);
- } catch (Exception e) {
+ // Collect parameters with Out flag from the request message
+
+ ParameterInfo[] parameters = method.GetParameters();
+ object[] returnArgs = new object [parameters.Length];
+
+ int n = 0;
+ int noa = 0;
+ foreach (ParameterInfo par in parameters)
+ {
+ if (par.IsOut && !par.ParameterType.IsByRef)
+ returnArgs [n++] = reqMsg.GetArg (par.Position);
+ else if (par.ParameterType.IsByRef)
+ returnArgs [n++] = out_args [noa++];
+ }
+
+ result = new ReturnMessage (rval, returnArgs, n, CallContext.CreateLogicalCallContext(), reqMsg);
+ }
+ catch (Exception e)
+ {
result = new ReturnMessage (e, reqMsg);
}
-
+
+ CallContext.RestoreCallContext (oldContext);
return result;
}
public static bool Disconnect (MarshalByRefObject obj)
{
if (obj == null) throw new ArgumentNullException ("obj");
- if (IsTransparentProxy (obj)) throw new ArgumentException ("The obj parameter is a proxy");
- ServerIdentity identity = obj.ObjectIdentity;
+ ServerIdentity identity;
+
+ if (IsTransparentProxy (obj))
+ {
+ // CBOs are always accessed through a proxy, even in the server, so
+ // for server CBOs it is ok to disconnect a proxy
+
+ RealProxy proxy = GetRealProxy(obj);
+ if (proxy.GetProxiedType().IsContextful && (proxy.ObjectIdentity is ServerIdentity))
+ identity = proxy.ObjectIdentity as ServerIdentity;
+ else
+ throw new ArgumentException ("The obj parameter is a proxy");
+ }
+ else
+ identity = obj.ObjectIdentity;
+
if (identity == null || !identity.IsConnected)
return false;
else
public static string GetObjectUri (MarshalByRefObject obj)
{
Identity ident = GetObjectIdentity(obj);
- if (ident != null) return ident.ObjectUri;
+ if (ident is ClientIdentity) return ((ClientIdentity)ident).TargetUri;
+ else if (ident != null) return ident.ObjectUri;
else return null;
}
// FIXME: use type name when fRefine==true
Type classToProxy = fRefine ? objref.ServerType : typeof (MarshalByRefObject);
+ if (classToProxy == null) classToProxy = typeof (MarshalByRefObject);
if (objref.IsReferenceToWellKnow)
return GetRemoteObject(objref, classToProxy);
}
else
{
- ClientActivatedIdentity identity = uri_hash [uri] as ClientActivatedIdentity;
+ ClientActivatedIdentity identity = GetIdentityForUri (uri) as ClientActivatedIdentity;
if (identity == null || obj != identity.GetServerObject())
CreateClientActivatedServerIdentity (obj, requested_type, uri);
}
else return ident.CreateObjRef(null);
}
+ public static object GetLifetimeService (MarshalByRefObject obj)
+ {
+ if (obj == null) return null;
+ return obj.GetLifetimeService ();
+ }
+
+ public static IMessageSink GetEnvoyChainForProxy (MarshalByRefObject obj)
+ {
+ if (IsTransparentProxy(obj))
+ return ((ClientIdentity)GetRealProxy (obj).ObjectIdentity).EnvoySink;
+ else
+ throw new ArgumentException ("obj must be a proxy","obj");
+ }
+
+ public static void LogRemotingStage (int stage)
+ {
+ throw new NotImplementedException ();
+ }
+
[MonoTODO]
public static string GetSessionIdForMethodMessage(IMethodMessage msg)
{
public static bool IsOneWay(MethodBase method)
{
+ // TODO: use internal call for better performance
object[] atts = method.GetCustomAttributes (typeof (OneWayAttribute), false);
return atts.Length > 0;
}
+ public static bool IsAsyncMessage(IMessage msg)
+ {
+ if (! (msg is MonoMethodMessage)) return false;
+ else if (((MonoMethodMessage)msg).IsAsync) return true;
+ else if (IsOneWay (((MonoMethodMessage)msg).MethodBase)) return true;
+ else return false;
+ }
+
public static void SetObjectUriForMarshal(MarshalByRefObject obj, string uri)
{
if (IsTransparentProxy (obj)) throw new RemotingException ("SetObjectUriForMarshal method should only be called for MarshalByRefObjects that exist in the current AppDomain.");
IMessageSink sink = ChannelServices.CreateClientChannelSinkChain (url, channelData, out objectUri);
if (sink == null)
{
- if (url != null) \r
+ if (url != null)
{
string msg = String.Format ("Cannot create channel sink to connect to URL {0}. An appropriate channel has probably not been registered.", url);
throw new RemotingException (msg);
}
- else \r
+ else
{
string msg = String.Format ("Cannot create channel sink to connect to the remote object. An appropriate channel has probably not been registered.", url);
throw new RemotingException (msg);
internal static object GetProxyForRemoteObject (ObjRef objref, Type classToProxy)
{
- ClientActivatedIdentity identity = uri_hash [objref.URI] as ClientActivatedIdentity;
+ ClientActivatedIdentity identity = GetIdentityForUri (objref.URI) as ClientActivatedIdentity;
if (identity != null) return identity.GetServerObject ();
else return GetRemoteObject (objref, classToProxy);
}
internal static void DisposeIdentity (ServerIdentity ident)
{
- uri_hash.Remove (ident.ObjectUri);
+ lock (uri_hash)
+ {
+ uri_hash.Remove (ident.ObjectUri);
+ }
}
internal static Identity GetMessageTargetIdentity (IMessage msg)
if (msg is IInternalMessage)
((IInternalMessage)msg).TargetIdentity = ident;
}
+
+ internal static bool UpdateOutArgObject (ParameterInfo pi, object local, object remote)
+ {
+ if (local is StringBuilder)
+ {
+ StringBuilder sb = local as StringBuilder;
+ sb.Remove (0, sb.Length);
+ sb.Append (remote.ToString());
+ return true;
+ }
+ else if (pi.ParameterType.IsArray && ((Array)local).Rank == 1)
+ {
+ Array alocal = (Array) local;
+ if (alocal.Rank == 1)
+ {
+ Array.Copy ((Array) remote, alocal, alocal.Length);
+ return true;
+ }
+ else
+ {
+ // TODO
+ }
+ }
+ return false;
+ }
#endregion
}