Пример #1
0
        public static void UpdateParameterCaches(RpcMethodInfo rpcMethodInfo, HashSet <Type> alreadyCheckedTypes)
        {
            MethodInfo methodInfo = rpcMethodInfo.MethodInfo;
            var        paramsInfo = methodInfo.GetParameters();

            for (int i = 0, n = paramsInfo.Length; i < n; ++i)
            {
                ParameterInfo paramInfo = paramsInfo[i];

                // Store if this parameter is Nullable
                if (paramInfo.HasAttribute <Nullable>())
                {
                    NullableParamCache.Add(paramInfo);
                }

                Type type = paramInfo.ParameterType;
                UpdateType(type, alreadyCheckedTypes);
            }

            if (rpcMethodInfo.HasReturnType)
            {
                if (rpcMethodInfo.ReturnType.IsGenericType)
                {
                    foreach (Type genericArg in rpcMethodInfo.ReturnType.GetGenericArguments())
                    {
                        UpdateType(genericArg, alreadyCheckedTypes);
                    }
                }
                else
                {
                    UpdateType(rpcMethodInfo.ReturnType, alreadyCheckedTypes);
                }
            }
        }
Пример #2
0
        public MessageInfo AnalyzeMessage(byte[] data, int offset, int length)
        {
            var  reader = new BinaryReader(new MemoryStream(data, offset, length));
            byte header = reader.ReadByte();

            if ((header & ResponseTypeFlag) == 0)
            {
                byte          ifaceOrdinal  = header;
                byte          methodOrdinal = reader.ReadByte();
                HandlerData   handlerData   = _handlersData[ifaceOrdinal];
                RpcMethodInfo rpcMethodInfo = handlerData.InterfaceMethods[methodOrdinal];

                return(new MessageInfo
                {
                    Type = MessageType.HandlerCall,
                    InterfaceType = RpcInterface.GetRpcInterface(ifaceOrdinal),
                    InterfaceMethodInfo = rpcMethodInfo.MethodInfo,
                    Handler = handlerData.Handler,
                });
            }

            return(new MessageInfo
            {
                Type = MessageType.CallResult,
            });
        }
Пример #3
0
        private static RpcMethodInfo GetRpcMethodInfo(MethodInfo methodInfo)
        {
            var rpcMethodInfo = new RpcMethodInfo
            {
                MethodInfo     = methodInfo,
                ParameterTypes = methodInfo.GetParameters(),
            };

            Type returnType = methodInfo.ReturnType;

            if (returnType == typeof(void))
            {
                return(rpcMethodInfo);
            }

            if (returnType.IsGenericType)
            {
                Type genericTypeDef   = returnType.GetGenericTypeDefinition();
                var  genericArguments = returnType.GetGenericArguments();
                Type concreteGenericTypeDef;

                if (genericTypeDef == typeof(IFuture <>))
                {
                    concreteGenericTypeDef = typeof(Future <>);
                }
                else if (genericTypeDef == typeof(IFutureErr <>))
                {
                    concreteGenericTypeDef = typeof(FutureErr <>);
                }
                else
                {
                    throw new InvalidOperationException("Invalid return type of method " +
                                                        methodInfo.DeclaringType.Name + "." + methodInfo.Name +
                                                        ". Allowed types are IFuture and IFutureErr type found is " +
                                                        returnType.Name);
                }

                rpcMethodInfo.ReturnType = concreteGenericTypeDef.MakeGenericType(genericArguments);
            }
            else
            {
                if (returnType == typeof(IFuture))
                {
                    rpcMethodInfo.ReturnType = typeof(Future);
                }
                else if (returnType == typeof(IFutureErr))
                {
                    rpcMethodInfo.ReturnType = typeof(FutureErr);
                }
                else
                {
                    throw new InvalidOperationException("Invalid return type of method " +
                                                        methodInfo.DeclaringType.Name + "." + methodInfo.Name +
                                                        ". Allowed types are IFuture and IFutureErr type found is " +
                                                        returnType.Name);
                }
            }

            return(rpcMethodInfo);
        }
Пример #4
0
        public void BeginCall(int methodOrdinal, object context)
        {
            var clientData = (ClientData)context;

            _currentCallMethod = clientData.InterfaceMethods[methodOrdinal];
            _currentCallFuture = null;

            if (_currentCallMethod.HasReturnType)
            {
                _currentCallFuture = Activator.CreateInstance(_currentCallMethod.ReturnType);
                ++_nextCallId;

                if (_nextCallId >= ResponseTypeFlag)
                {
                    _nextCallId = 1;
                }

                if (_resultFutures.ContainsKey(_nextCallId))
                {
                    throw new InvalidOperationException("CallId overrun.");
                }

                _resultFutures[_nextCallId] = _currentCallFuture;
            }

            _currentCallStream = new MemoryStream(64);
            _currentCallWriter = new BinaryWriter(_currentCallStream);
            _currentCallWriter.Write((byte)clientData.InterfaceOrdinal);
            _currentCallWriter.Write((byte)methodOrdinal);

            if (_currentCallFuture != null)
            {
                _currentCallWriter.Write((byte)_nextCallId);
            }

            _currentCallArg = 0;
        }
Пример #5
0
        private void ProcessHandlerCall(BinaryReader reader, byte ifaceOrdinal, object context)
        {
            HandlerData handlerData;

            if (!_handlersData.TryGetValue(ifaceOrdinal, out handlerData))
            {
                Type ifaceType = RpcInterface.GetRpcInterface(ifaceOrdinal);

                if (ifaceType == null)
                {
                    throw new ProtocolViolationException("Unknown RPC interface ordinal received: " + ifaceOrdinal);
                }

                MethodInfo mi = RpcInterface.GetOrderedMethods(ifaceType)[reader.ReadByte()].MethodInfo;

                throw new ProtocolViolationException("RPC call received for " + ifaceType.FullName + "." + mi.Name +
                                                     " which does not have a handler registered.");
            }

            byte          methodOrdinal = reader.ReadByte();
            RpcMethodInfo rpcMethodInfo = handlerData.InterfaceMethods[methodOrdinal];
            MethodInfo    methodInfo    = rpcMethodInfo.MethodInfo;
            byte          callId        = 0;

            if (rpcMethodInfo.HasReturnType)
            {
                callId = reader.ReadByte();
            }

            var paramsInfo  = methodInfo.GetParameters();
            var paramValues = new object[paramsInfo.Length];

            for (int i = 0, n = paramValues.Length; i < n; ++i)
            {
                paramValues[i] = BinarySerializer.DeserializeParameter(reader, paramsInfo[i]);
            }

            var callContext = new HandlerCallContext
            {
                HandlerType = handlerData.RpcInterfaceType,
                Handler     = handlerData.Handler,
                Method      = methodInfo,
                CallId      = callId,
                Context     = context,
            };

            if (OnBeforeHandlerCall != null)
            {
                OnBeforeHandlerCall(callContext);
            }

            callContext.Result = methodInfo.Invoke(handlerData.Handler, paramValues);

            if (callContext.Result != null && OnDataOut != null)
            {
                Type resultFutureType = callContext.Result.GetType();
                var  stream           = new MemoryStream(64);
                var  writer           = new BinaryWriter(stream);
                var  header           = (byte)(ResponseTypeFlag | callId);
                writer.Write((byte)header);

                resultFutureType.GetMethod("Serialize", BindingFlags.NonPublic | BindingFlags.Instance)
                .Invoke(callContext.Result, new object[] { writer });

                OnDataOut(stream.ToArray(), 0, (int)stream.Length);
            }

            if (OnAfterHandlerCall != null)
            {
                OnAfterHandlerCall(callContext);
            }
        }
Пример #6
0
        // The generated code for the proxy type is like this:
        //
        //	public class IBlahServiceRpcProxy : IBlahService
        //	{
        //		public ICallInterceptor Interceptor;
        //		public object Context;
        //
        //		public int Blah(int param1, string param2)
        //		{
        //      object argsArray = Interceptor.GetArgsArray(2);
        //      argsArray[0] = param1;
        //      argsArray[1] = param2;
        //			return (int) Interceptor.MethodCall(0, Context, argsArray);
        //		}
        //	}

        private static Type CreateDynamicProxyType(ModuleBuilder moduleBuilder, Type type, HashSet <Type> checkedTypes)
        {
            TypeBuilder tb = moduleBuilder.DefineType(type.Name + "RpcProxy", TypeAttributes.Public);

            tb.AddInterfaceImplementation(type);
            FieldBuilder interceptorFi = tb.DefineField("Interceptor", typeof(ICallInterceptor), FieldAttributes.Public);
            FieldBuilder contextFi     = tb.DefineField("Context", typeof(object), FieldAttributes.Public);

            RpcMethodInfo[] methods               = GetOrderedMethods(type);
            MethodInfo      beginCall             = typeof(ICallInterceptor).GetMethod("BeginCall");
            MethodInfo      genericPushArg        = typeof(ICallInterceptor).GetMethod("PushArg");
            MethodInfo      completeCall          = typeof(ICallInterceptor).GetMethod("CompleteCall");
            var             genericPushArgMethods = new Dictionary <Type, MethodInfo>();

            for (int ord = 0; ord < methods.Length; ++ord)
            {
                RpcMethodInfo rpcMethodInfo = methods[ord];
                BinarySerializer.UpdateParameterCaches(rpcMethodInfo, checkedTypes);
                MethodInfo      methodInfo = rpcMethodInfo.MethodInfo;
                ParameterInfo[] paramInfo  = rpcMethodInfo.ParameterTypes;
                var             paramTypes = new Type[paramInfo.Length];

                for (int i = 0, n = paramInfo.Length; i < n; ++i)
                {
                    paramTypes[i] = paramInfo[i].ParameterType;

                    if (!genericPushArgMethods.ContainsKey(paramTypes[i]))
                    {
                        genericPushArgMethods[paramTypes[i]] = genericPushArg.MakeGenericMethod(paramTypes[i]);
                    }
                }

                MethodBuilder mtb = tb.DefineMethod(
                    methodInfo.Name,
                    MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final,
                    methodInfo.ReturnType,
                    paramTypes);

                ILGenerator gen = mtb.GetILGenerator();

                // Interceptor.BeginCall(3, Context);
                gen.Emit(OpCodes.Ldarg_0);
                gen.Emit(OpCodes.Ldfld, interceptorFi);
                gen.Emit(OpCodes.Ldc_I4, ord);
                gen.Emit(OpCodes.Ldarg_0);
                gen.Emit(OpCodes.Ldfld, contextFi);
                gen.Emit(OpCodes.Callvirt, beginCall);

                // Call PushArg for each argument
                for (int i = 0, n = paramInfo.Length; i < n; ++i)
                {
                    Type       paramType = paramInfo[i].ParameterType;
                    MethodInfo pushArgMi = genericPushArgMethods[paramType];

                    // Interceptor.PushArg(arg_i);
                    gen.Emit(OpCodes.Ldarg_0);
                    gen.Emit(OpCodes.Ldfld, interceptorFi);
                    gen.Emit(OpCodes.Ldarg, i + 1);
                    gen.Emit(OpCodes.Callvirt, pushArgMi);
                }

                // return Interceptor.CompleteCall();
                gen.Emit(OpCodes.Ldarg_0);
                gen.Emit(OpCodes.Ldfld, interceptorFi);
                gen.Emit(OpCodes.Callvirt, completeCall);

                if (mtb.ReturnType == typeof(void))
                {
                    gen.Emit(OpCodes.Pop);
                }
                else
                {
                    gen.Emit(OpCodes.Castclass, mtb.ReturnType);
                }

                gen.Emit(OpCodes.Ret);
            }

            return(tb.CreateType());
        }