| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807 |
- //------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------
- namespace System.ServiceModel.Channels
- {
- using System.Collections;
- using System.Collections.Specialized;
- using System.Globalization;
- using System.Reflection;
- using System.Runtime;
- using System.Runtime.Diagnostics;
- using System.Runtime.Remoting;
- using System.Runtime.Remoting.Messaging;
- using System.Runtime.Remoting.Proxies;
- using System.Security;
- using System.ServiceModel.Description;
- using System.ServiceModel.Diagnostics;
- using System.ServiceModel.Dispatcher;
- using System.Threading.Tasks;
- [Fx.Tag.SecurityNote(Critical = "Accesses a variety of LinkDemanded classes/methods (especially RealProxy)." +
- "Caller should protect access to the ServiceChannelProxy instance after construction.")]
- #pragma warning disable 618 // have not moved to the v4 security model yet
- [SecurityCritical(SecurityCriticalScope.Everything)]
- #pragma warning restore 618
- sealed class ServiceChannelProxy : RealProxy, IRemotingTypeInfo
- {
- const String activityIdSlotName = "E2ETrace.ActivityID";
- Type proxiedType;
- Type interfaceType;
- ServiceChannel serviceChannel;
- MbrObject objectWrapper;
- ImmutableClientRuntime proxyRuntime;
- MethodDataCache methodDataCache;
- internal ServiceChannelProxy(Type interfaceType, Type proxiedType, MessageDirection direction, ServiceChannel serviceChannel)
- : base(proxiedType)
- {
- if (!MessageDirectionHelper.IsDefined(direction))
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("direction"));
- this.interfaceType = interfaceType;
- this.proxiedType = proxiedType;
- this.serviceChannel = serviceChannel;
- this.proxyRuntime = serviceChannel.ClientRuntime.GetRuntime();
- this.methodDataCache = new MethodDataCache();
- this.objectWrapper = new MbrObject(this, proxiedType);
- }
- //Workaround is to set the activityid in remoting call's LogicalCallContext
- static LogicalCallContext SetActivityIdInLogicalCallContext(LogicalCallContext logicalCallContext)
- {
- if (TraceUtility.ActivityTracing)
- {
- logicalCallContext.SetData(activityIdSlotName, DiagnosticTraceBase.ActivityId);
- }
- return logicalCallContext;
- }
- IMethodReturnMessage CreateReturnMessage(object ret, object[] returnArgs, IMethodCallMessage methodCall)
- {
- if (returnArgs != null)
- {
- return CreateReturnMessage(ret, returnArgs, returnArgs.Length, SetActivityIdInLogicalCallContext(methodCall.LogicalCallContext), methodCall);
- }
- else
- {
- return new SingleReturnMessage(ret, methodCall);
- }
- }
- IMethodReturnMessage CreateReturnMessage(object ret, object[] outArgs, int outArgsCount, LogicalCallContext callCtx, IMethodCallMessage mcm)
- {
- return new ReturnMessage(ret, outArgs, outArgsCount, callCtx, mcm);
- }
- IMethodReturnMessage CreateReturnMessage(Exception e, IMethodCallMessage mcm)
- {
- return new ReturnMessage(e, mcm);
- }
- MethodData GetMethodData(IMethodCallMessage methodCall)
- {
- MethodBase method = methodCall.MethodBase;
- MethodData methodData;
- if (methodDataCache.TryGetMethodData(method, out methodData))
- {
- return methodData;
- }
- bool canCacheMessageData;
- Type declaringType = method.DeclaringType;
- if (declaringType == typeof(object))
- {
- MethodType methodType;
- if (methodCall.MethodBase == typeof(object).GetMethod("GetType"))
- {
- methodType = MethodType.GetType;
- }
- else
- {
- methodType = MethodType.Object;
- }
- canCacheMessageData = true;
- methodData = new MethodData(method, methodType);
- }
- else if (declaringType.IsInstanceOfType(this.serviceChannel))
- {
- canCacheMessageData = true;
- methodData = new MethodData(method, MethodType.Channel);
- }
- else
- {
- ProxyOperationRuntime operation = this.proxyRuntime.GetOperation(method, methodCall.Args, out canCacheMessageData);
- if (operation == null)
- {
- if (this.serviceChannel.Factory != null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SFxMethodNotSupported1, method.Name)));
- else
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SFxMethodNotSupportedOnCallback1, method.Name)));
- }
- MethodType methodType;
- if (operation.IsTaskCall(methodCall))
- {
- methodType = MethodType.TaskService;
- }
- else if (operation.IsSyncCall(methodCall))
- {
- methodType = MethodType.Service;
- }
- else if (operation.IsBeginCall(methodCall))
- {
- methodType = MethodType.BeginService;
- }
- else
- {
- methodType = MethodType.EndService;
- }
- methodData = new MethodData(method, methodType, operation);
- }
- if (canCacheMessageData)
- {
- methodDataCache.SetMethodData(methodData);
- }
- return methodData;
- }
- internal ServiceChannel GetServiceChannel()
- {
- return this.serviceChannel;
- }
- public override IMessage Invoke(IMessage message)
- {
- try
- {
- IMethodCallMessage methodCall = message as IMethodCallMessage;
- if (methodCall == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.SFxExpectedIMethodCallMessage)));
- MethodData methodData = GetMethodData(methodCall);
- switch (methodData.MethodType)
- {
- case MethodType.Service:
- return InvokeService(methodCall, methodData.Operation);
- case MethodType.BeginService:
- return InvokeBeginService(methodCall, methodData.Operation);
- case MethodType.EndService:
- return InvokeEndService(methodCall, methodData.Operation);
- case MethodType.TaskService:
- return InvokeTaskService(methodCall, methodData.Operation);
- case MethodType.Channel:
- return InvokeChannel(methodCall);
- case MethodType.GetType:
- return InvokeGetType(methodCall);
- case MethodType.Object:
- return InvokeObject(methodCall);
- default:
- Fx.Assert("Invalid proxy method type");
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Invalid proxy method type")));
- }
- }
- #pragma warning suppress 56500 // covered by FxCOP
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- return CreateReturnMessage(e, message as IMethodCallMessage);
- }
- }
- static class TaskCreator
- {
- static readonly Func<ServiceChannel, ProxyOperationRuntime, object[], AsyncCallback, object, IAsyncResult> beginCallDelegate = ServiceChannel.BeginCall;
- static readonly Hashtable createGenericTaskDelegateCache = new Hashtable(); // using Hashtable because it allows for lock-free reads
- static readonly MethodInfo createGenericTaskMI = typeof(TaskCreator).GetMethod("CreateGenericTask", new Type[] { typeof(ServiceChannel), typeof(ProxyOperationRuntime), typeof(object[]) });
- static Func<ServiceChannel, ProxyOperationRuntime, object[], Task> GetOrCreateTaskDelegate(Type taskResultType)
- {
- Func<ServiceChannel, ProxyOperationRuntime, object[], Task> createTaskDelegate = createGenericTaskDelegateCache[taskResultType] as Func<ServiceChannel, ProxyOperationRuntime, object[], Task>;
- if (createTaskDelegate != null)
- {
- return createTaskDelegate;
- }
- lock (createGenericTaskDelegateCache)
- {
- createTaskDelegate = createGenericTaskDelegateCache[taskResultType] as Func<ServiceChannel, ProxyOperationRuntime, object[], Task>;
- if (createTaskDelegate != null)
- {
- return createTaskDelegate;
- }
-
- MethodInfo methodInfo = createGenericTaskMI.MakeGenericMethod(taskResultType);
- createTaskDelegate = Delegate.CreateDelegate(typeof(Func<ServiceChannel, ProxyOperationRuntime, object[], Task>), methodInfo) as Func<ServiceChannel, ProxyOperationRuntime, object[], Task>;
- createGenericTaskDelegateCache[taskResultType] = createTaskDelegate;
- }
- return createTaskDelegate;
- }
- public static Task CreateTask(ServiceChannel channel, IMethodCallMessage methodCall, ProxyOperationRuntime operation)
- {
- if (operation.TaskTResult == ServiceReflector.VoidType)
- {
- return TaskCreator.CreateTask(channel, operation, methodCall.InArgs);
- }
- return TaskCreator.CreateGenericTask(channel, operation, methodCall.InArgs);
- }
- static Task CreateGenericTask(ServiceChannel channel, ProxyOperationRuntime operation, object[] inputParameters)
- {
- Func<ServiceChannel, ProxyOperationRuntime, object[], Task> createTaskDelegate = GetOrCreateTaskDelegate(operation.TaskTResult);
- return createTaskDelegate(channel, operation, inputParameters);
- }
- static Task CreateTask(ServiceChannel channel, ProxyOperationRuntime operation, object[] inputParameters)
- {
- Action<IAsyncResult> endCallDelegate = (asyncResult) =>
- {
- Fx.Assert(asyncResult != null, "'asyncResult' MUST NOT be NULL.");
- OperationContext originalOperationContext = OperationContext.Current;
- OperationContext.Current = asyncResult.AsyncState as OperationContext;
- try
- {
- channel.EndCall(operation.Action, ProxyOperationRuntime.EmptyArray, asyncResult);
- }
- finally
- {
- OperationContext.Current = originalOperationContext;
- }
- };
- return Task.Factory.FromAsync(beginCallDelegate, endCallDelegate, channel, operation, inputParameters, OperationContext.Current);
- }
- public static Task<T> CreateGenericTask<T>(ServiceChannel channel, ProxyOperationRuntime operation, object[] inputParameters)
- {
- Func<IAsyncResult, T> endCallDelegate = (asyncResult) =>
- {
- OperationContext originalOperationContext = OperationContext.Current;
- OperationContext.Current = asyncResult.AsyncState as OperationContext;
- try
- {
- return (T)channel.EndCall(operation.Action, ProxyOperationRuntime.EmptyArray, asyncResult);
- }
- finally
- {
- OperationContext.Current = originalOperationContext;
- }
- };
- return Task<T>.Factory.FromAsync<ServiceChannel, ProxyOperationRuntime, object[]>(beginCallDelegate, endCallDelegate, channel, operation, inputParameters, OperationContext.Current);
- }
- }
- IMessage InvokeTaskService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
- {
- Task task = TaskCreator.CreateTask(this.serviceChannel, methodCall, operation);
- return CreateReturnMessage(task, null, methodCall);
- }
- IMethodReturnMessage InvokeChannel(IMethodCallMessage methodCall)
- {
- string activityName = null;
- ActivityType activityType = ActivityType.Unknown;
- if (DiagnosticUtility.ShouldUseActivity)
- {
- if (ServiceModelActivity.Current == null ||
- ServiceModelActivity.Current.ActivityType != ActivityType.Close)
- {
- MethodData methodData = this.GetMethodData(methodCall);
- if (methodData.MethodBase.DeclaringType == typeof(System.ServiceModel.ICommunicationObject)
- && methodData.MethodBase.Name.Equals("Close", StringComparison.Ordinal))
- {
- activityName = SR.GetString(SR.ActivityClose, this.serviceChannel.GetType().FullName);
- activityType = ActivityType.Close;
- }
- }
- }
- using (ServiceModelActivity activity = string.IsNullOrEmpty(activityName) ? null : ServiceModelActivity.CreateBoundedActivity())
- {
- if (DiagnosticUtility.ShouldUseActivity)
- {
- ServiceModelActivity.Start(activity, activityName, activityType);
- }
- return ExecuteMessage(this.serviceChannel, methodCall);
- }
- }
- IMethodReturnMessage InvokeGetType(IMethodCallMessage methodCall)
- {
- return CreateReturnMessage(proxiedType, null, 0, SetActivityIdInLogicalCallContext(methodCall.LogicalCallContext), methodCall);
- }
- IMethodReturnMessage InvokeObject(IMethodCallMessage methodCall)
- {
- return RemotingServices.ExecuteMessage(this.objectWrapper, methodCall);
- }
- IMethodReturnMessage InvokeBeginService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
- {
- AsyncCallback callback;
- object asyncState;
- object[] ins = operation.MapAsyncBeginInputs(methodCall, out callback, out asyncState);
- object ret = this.serviceChannel.BeginCall(operation.Action, operation.IsOneWay, operation, ins, callback, asyncState);
- return CreateReturnMessage(ret, null, methodCall);
- }
- IMethodReturnMessage InvokeEndService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
- {
- IAsyncResult result;
- object[] outs;
- operation.MapAsyncEndInputs(methodCall, out result, out outs);
- object ret = this.serviceChannel.EndCall(operation.Action, outs, result);
- object[] returnArgs = operation.MapAsyncOutputs(methodCall, outs, ref ret);
- return CreateReturnMessage(ret, returnArgs, methodCall);
- }
- IMethodReturnMessage InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
- {
- object[] outs;
- object[] ins = operation.MapSyncInputs(methodCall, out outs);
- object ret = this.serviceChannel.Call(operation.Action, operation.IsOneWay, operation, ins, outs);
- object[] returnArgs = operation.MapSyncOutputs(methodCall, outs, ref ret);
- return CreateReturnMessage(ret, returnArgs, methodCall);
- }
- IMethodReturnMessage ExecuteMessage(object target, IMethodCallMessage methodCall)
- {
- MethodBase targetMethod = methodCall.MethodBase;
- object[] args = methodCall.Args;
- object returnValue = null;
- try
- {
- returnValue = targetMethod.Invoke(target, args);
- }
- catch (TargetInvocationException e)
- {
- return CreateReturnMessage(e.InnerException, methodCall);
- }
- return CreateReturnMessage(returnValue,
- args,
- args.Length,
- null,
- methodCall);
- }
- bool IRemotingTypeInfo.CanCastTo(Type toType, object o)
- {
- return toType.IsAssignableFrom(proxiedType) || serviceChannel.CanCastTo(toType);
- }
- string IRemotingTypeInfo.TypeName
- {
- get { return proxiedType.FullName; }
- set { }
- }
- class MethodDataCache
- {
- MethodData[] methodDatas;
- public MethodDataCache()
- {
- this.methodDatas = new MethodData[4];
- }
- object ThisLock
- {
- get { return this; }
- }
- public bool TryGetMethodData(MethodBase method, out MethodData methodData)
- {
- lock (ThisLock)
- {
- MethodData[] methodDatas = this.methodDatas;
- int index = FindMethod(methodDatas, method);
- if (index >= 0)
- {
- methodData = methodDatas[index];
- return true;
- }
- else
- {
- methodData = new MethodData();
- return false;
- }
- }
- }
- static int FindMethod(MethodData[] methodDatas, MethodBase methodToFind)
- {
- for (int i = 0; i < methodDatas.Length; i++)
- {
- MethodBase method = methodDatas[i].MethodBase;
- if (method == null)
- {
- break;
- }
- if (method == methodToFind)
- {
- return i;
- }
- }
- return -1;
- }
- public void SetMethodData(MethodData methodData)
- {
- lock (ThisLock)
- {
- int index = FindMethod(this.methodDatas, methodData.MethodBase);
- if (index < 0)
- {
- for (int i = 0; i < this.methodDatas.Length; i++)
- {
- if (methodDatas[i].MethodBase == null)
- {
- methodDatas[i] = methodData;
- return;
- }
- }
- MethodData[] newMethodDatas = new MethodData[methodDatas.Length * 2];
- Array.Copy(methodDatas, newMethodDatas, methodDatas.Length);
- newMethodDatas[methodDatas.Length] = methodData;
- this.methodDatas = newMethodDatas;
- }
- }
- }
- }
- enum MethodType
- {
- Service,
- BeginService,
- EndService,
- Channel,
- Object,
- GetType,
- TaskService
- }
- struct MethodData
- {
- MethodBase methodBase;
- MethodType methodType;
- ProxyOperationRuntime operation;
- public MethodData(MethodBase methodBase, MethodType methodType)
- : this(methodBase, methodType, null)
- {
- }
- public MethodData(MethodBase methodBase, MethodType methodType, ProxyOperationRuntime operation)
- {
- this.methodBase = methodBase;
- this.methodType = methodType;
- this.operation = operation;
- }
- public MethodBase MethodBase
- {
- get { return methodBase; }
- }
- public MethodType MethodType
- {
- get { return methodType; }
- }
- public ProxyOperationRuntime Operation
- {
- get { return operation; }
- }
- }
- class MbrObject : MarshalByRefObject
- {
- RealProxy proxy;
- Type targetType;
- internal MbrObject(RealProxy proxy, Type targetType)
- {
- this.proxy = proxy;
- this.targetType = targetType;
- }
- public override bool Equals(object obj)
- {
- return Object.ReferenceEquals(obj, this.proxy.GetTransparentProxy());
- }
- public override string ToString()
- {
- return this.targetType.ToString();
- }
- public override int GetHashCode()
- {
- return this.proxy.GetHashCode();
- }
- }
- class SingleReturnMessage : IMethodReturnMessage
- {
- IMethodCallMessage methodCall;
- object ret;
- PropertyDictionary properties;
- public SingleReturnMessage(object ret, IMethodCallMessage methodCall)
- {
- this.ret = ret;
- this.methodCall = methodCall;
- this.properties = new PropertyDictionary();
- }
- public int ArgCount
- {
- get { return 0; }
- }
- public object[] Args
- {
- get { return EmptyArray.Instance; }
- }
- public Exception Exception
- {
- get { return null; }
- }
- public bool HasVarArgs
- {
- get { return methodCall.HasVarArgs; }
- }
- public LogicalCallContext LogicalCallContext
- {
- get { return SetActivityIdInLogicalCallContext(methodCall.LogicalCallContext); }
- }
- public MethodBase MethodBase
- {
- get { return methodCall.MethodBase; }
- }
- public string MethodName
- {
- get { return methodCall.MethodName; }
- }
- public object MethodSignature
- {
- get { return methodCall.MethodSignature; }
- }
- public object[] OutArgs
- {
- get { return EmptyArray.Instance; }
- }
- public int OutArgCount
- {
- get { return 0; }
- }
- public IDictionary Properties
- {
- get { return properties; }
- }
- public object ReturnValue
- {
- get { return ret; }
- }
- public string TypeName
- {
- get { return methodCall.TypeName; }
- }
- public string Uri
- {
- get { return null; }
- }
- public object GetArg(int index)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("index"));
- }
- public string GetArgName(int index)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("index"));
- }
- public object GetOutArg(int index)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("index"));
- }
- public string GetOutArgName(int index)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("index"));
- }
- class PropertyDictionary : IDictionary
- {
- ListDictionary properties;
- public object this[object key]
- {
- get { return Properties[key]; }
- set { Properties[key] = value; }
- }
- public int Count
- {
- get { return Properties.Count; }
- }
- public bool IsFixedSize
- {
- get { return false; }
- }
- public bool IsReadOnly
- {
- get { return false; }
- }
- public bool IsSynchronized
- {
- get { return false; }
- }
- public ICollection Keys
- {
- get { return Properties.Keys; }
- }
- ListDictionary Properties
- {
- get
- {
- if (properties == null)
- {
- properties = new ListDictionary();
- }
- return properties;
- }
- }
- public ICollection Values
- {
- get { return Properties.Values; }
- }
- public object SyncRoot
- {
- get { return null; }
- }
- public void Add(object key, object value)
- {
- Properties.Add(key, value);
- }
- public void Clear()
- {
- Properties.Clear();
- }
- public bool Contains(object key)
- {
- return Properties.Contains(key);
- }
- public void CopyTo(Array array, int index)
- {
- Properties.CopyTo(array, index);
- }
- public IDictionaryEnumerator GetEnumerator()
- {
- if (properties == null)
- {
- return EmptyEnumerator.Instance;
- }
- else
- {
- return properties.GetEnumerator();
- }
- }
- IEnumerator IEnumerable.GetEnumerator()
- {
- return ((IEnumerable)Properties).GetEnumerator();
- }
- public void Remove(object key)
- {
- Properties.Remove(key);
- }
- class EmptyEnumerator : IDictionaryEnumerator
- {
- static EmptyEnumerator instance = new EmptyEnumerator();
- EmptyEnumerator()
- {
- }
- public static EmptyEnumerator Instance
- {
- get { return instance; }
- }
- public bool MoveNext()
- {
- return false;
- }
- public Object Current
- {
- get
- {
- #pragma warning suppress 56503 // [....], IEnumerator guidelines, Current throws exception before calling MoveNext
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxDictionaryIsEmpty)));
- }
- }
- public void Reset()
- {
- }
- public Object Key
- {
- get
- {
- #pragma warning suppress 56503 // [....], IEnumerator guidelines, Current throws exception before calling MoveNext
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxDictionaryIsEmpty)));
- }
- }
- public Object Value
- {
- get
- {
- #pragma warning suppress 56503 // [....], IEnumerator guidelines, Current throws exception before calling MoveNext
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxDictionaryIsEmpty)));
- }
- }
- public DictionaryEntry Entry
- {
- get
- {
- #pragma warning suppress 56503 // [....], IEnumerator guidelines, Current throws exception before calling MoveNext
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxDictionaryIsEmpty)));
- }
- }
- }
- }
- }
- }
- }
|