예제 #1
0
        public void RegisterRpcHandler(object handler)
        {
            Type handlerType       = handler.GetType();
            bool handlerRegistered = false;

            foreach (var intType in handlerType.GetInterfaces())
            {
                if (intType.HasAttribute <RpcInterface>())
                {
                    var         iface = intType.GetAttribute <RpcInterface>();
                    HandlerData existingHandler;

                    if (_handlersData.TryGetValue(iface.Ordinal, out existingHandler))
                    {
                        RemoveRpcHandler(handler);
                        throw new ArgumentException("Handler with type " + handler.GetType() + " implements " + iface.GetType() +
                                                    " which is already handled by " + existingHandler.Handler.GetType());
                    }

                    _handlersData[iface.Ordinal] = new HandlerData
                    {
                        RpcInterfaceType = intType,
                        Handler          = handler,
                        InterfaceMethods = RpcInterface.GetOrderedMethods(intType),
                    };

                    handlerRegistered = true;
                }
            }

            if (!handlerRegistered)
            {
                throw new ArgumentException("Handler with type " + handler.GetType() + " does not implement any RPC interface.");
            }
        }
예제 #2
0
        public T GetRpcInterface <T>() where T : class
        {
            ClientData clientData;

            if (_clientsData.TryGetValue(typeof(T), out clientData))
            {
                return((T)clientData.Proxy);
            }

            var type = typeof(T);

            if (type.HasAttribute <RpcInterface>())
            {
                var newClientData = new ClientData()
                {
                    InterfaceOrdinal = type.GetAttribute <RpcInterface>().Ordinal,
                    InterfaceMethods = RpcInterface.GetOrderedMethods(type),
                };

                newClientData.Proxy     = RpcInterface.CreateDynamicProxy <T>(this, newClientData);
                _clientsData[typeof(T)] = newClientData;
                return((T)newClientData.Proxy);
            }

            throw new NotSupportedException(type.Name + " does not have the RPCInterface attribute");
        }
예제 #3
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,
            });
        }
예제 #4
0
        public static void Serialize <T>(BinaryWriter writer, Type type, bool nullable, T value)
        {
            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(System.Nullable <>))
            {
                Type underlyingType = type.GetGenericArguments()[0];
                Serialize(writer, underlyingType, true, value);
                return;
            }

            if (nullable)
            {
                if (value == null)
                {
                    writer.Write((byte)0);
                    return;
                }

                writer.Write((byte)1);
            }
            else if (value == null)
            {
                throw new SerializationException("Trying to serialize a non Nullable null value");
            }

            Action <BinaryWriter, object, bool> serializerFunc;

            if (WriteFunctions.TryGetValue(type, out serializerFunc))
            {
                serializerFunc(writer, value, nullable);
                return;
            }

            if (type.IsEnum)
            {
                Type underlyingType = Enum.GetUnderlyingType(type);

                if (WriteFunctions.TryGetValue(underlyingType, out serializerFunc))
                {
                    serializerFunc(writer, Convert.ChangeType(value, underlyingType), nullable);
                }
                else
                {
                    throw new SerializationException("Enum " + type.Name + " underlying type is not serializable.");
                }

                return;
            }

            SerializableTypeInfo serTypeInfo = SerializableTypeCache[type];

            if (serTypeInfo != null)
            {
                if (serTypeInfo.SerializeMethod.IsStatic)
                {
                    serTypeInfo.SerializeMethod.Invoke(null, new object[] { value, writer });
                }
                else
                {
                    serTypeInfo.SerializeMethod.Invoke(value, new object[] { writer });
                }

                return;
            }

            Type elementType = GetListElementType(type);

            if (elementType != null)
            {
                Action <BinaryWriter, object, bool> writeFunc = (wrtr, vlue, nlble) => {
                    wrtr.Write(checked ((ushort)((ICollection)vlue).Count));

                    foreach (var el in (IEnumerable)vlue)
                    {
                        Serialize(wrtr, elementType, nlble, el);
                    }
                };

                WriteFunctions[type] = writeFunc;
                writeFunc(writer, value, nullable);
                return;
            }

            foreach (var info in RpcInterface.GetOrederedFields(type))
            {
                if (!info.IsStatic)
                {
                    Serialize(writer, info.FieldType, NullableParamCache.Contains(info), info.GetValue(value));
                }
            }

            foreach (var info in RpcInterface.GetOrderedProperties(type))
            {
                if (info.CanRead && info.CanWrite)
                {
                    Serialize(writer, info.PropertyType, NullableParamCache.Contains(info), info.GetValue(value, null));
                }
            }
        }
예제 #5
0
        public static object Deserialize(BinaryReader reader, Type type, bool nullable)
        {
            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(System.Nullable <>))
            {
                Type underlyingType = type.GetGenericArguments()[0];
                return(Deserialize(reader, underlyingType, true));
            }

            if (nullable && reader.ReadByte() == 0)
            {
                return(null);
            }

            Func <BinaryReader, bool, object> deserializerFunc;

            if (ReadFunctions.TryGetValue(type, out deserializerFunc))
            {
                return(deserializerFunc(reader, nullable));
            }

            if (type.IsEnum)
            {
                Type underlyingType = Enum.GetUnderlyingType(type);

                if (ReadFunctions.TryGetValue(underlyingType, out deserializerFunc))
                {
                    object value = deserializerFunc(reader, nullable);
                    return(Enum.ToObject(type, value));
                }

                throw new SerializationException("Enum " + type.Name + " underlying type is not serializable.");
            }

            SerializableTypeInfo serTypeInfo = SerializableTypeCache[type];

            if (serTypeInfo != null)
            {
                if (serTypeInfo.DeserializeMethod != null)
                {
                    return(serTypeInfo.DeserializeMethod.Invoke(null, new object[] { reader }));
                }

                if (serTypeInfo.Constructor != null)
                {
                    return(Activator.CreateInstance(type, reader));
                }
            }

            Type elementType = GetListElementType(type);

            if (elementType != null)
            {
                Func <BinaryReader, bool, object> readFunc;

                if (type.IsArray)
                {
                    readFunc = (rdr, nlble) => {
                        int length = rdr.ReadUInt16();
                        var array  = (Array)Activator.CreateInstance(type, length);

                        for (int i = 0; i < length; ++i)
                        {
                            array.SetValue(Deserialize(rdr, elementType, nlble), i);
                        }

                        return(array);
                    };
                }
                else
                {
                    Type listType = typeof(List <>).MakeGenericType(elementType);

                    readFunc = (rdr, nlble) => {
                        int length = rdr.ReadUInt16();
                        var list   = (IList)Activator.CreateInstance(listType);

                        for (int i = 0; i < length; ++i)
                        {
                            list.Add(Deserialize(rdr, elementType, nlble));
                        }

                        return(list);
                    };
                }

                ReadFunctions[type] = readFunc;
                return(readFunc(reader, nullable));
            }

            var obj = Activator.CreateInstance(type);

            foreach (var info in RpcInterface.GetOrederedFields(type))
            {
                if (!info.IsStatic)
                {
                    var fieldValue = Deserialize(reader, info.FieldType, NullableParamCache.Contains(info));
                    info.SetValue(obj, fieldValue);
                }
            }

            foreach (var info in RpcInterface.GetOrderedProperties(type))
            {
                if (info.CanRead && info.CanWrite)
                {
                    var propValue = Deserialize(reader, info.PropertyType, NullableParamCache.Contains(info));
                    info.SetValue(obj, propValue, null);
                }
            }

            return(obj);
        }
예제 #6
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);
            }
        }