public virtual T GetProxyObject <T>(IRpcChannel channel, int remoteInstanceId)
 {
     return((T)GetProxyObject(
                channel,
                new[] { typeof(T) }.Concat(typeof(T).GetInterfaces()).ToArray(),
                remoteInstanceId));
 }
        public override object GetProxyObject(IRpcChannel channel, Type[] interfaceTypes, int remoteInstanceId)
        {
            lock (_rpcObjects)
            {
                Purge();
                if (_rpcObjects.TryGetValue(RpcHandle.ComparisonHandle(remoteInstanceId), out var obj))
                {
                    if (((RpcObjectHandle)obj).Object.TryGetTarget(out var inst))
                    {
                        return(inst);
                    }
                }

                bool isDelegate = interfaceTypes.Length == 1 && interfaceTypes[0].IsSubclassOf(typeof(Delegate));

                var result = new RpcObjectHandle(null, pinned: /*isDelegate && !_clientRepository,*/ false, instanceId: remoteInstanceId);
                _rpcObjects.Add(result);

                var instance = isDelegate
                    ? ImplementDelegate(interfaceTypes[0], channel, remoteInstanceId, result.InstanceId)
                    : ImplementInterfaces(interfaceTypes, channel, remoteInstanceId, result.InstanceId);



                result.Object = new WeakReference <object>(instance);
                return(instance);
            }
        }
Exemple #3
0
        /// <summary>
        /// Gets a proxy to the service instance specified by <paramref name="objectId"/>.
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <param name="objectId"></param>
        /// <param name="useSyncContext">Indicates that the current synchronization context should be used for the service intance.</param>
        /// <returns>The service proxy.</returns>
        /// <exception cref="RpcDefinitionException">Thrown if the RPC definition of <typeparamref name="TService"/> is not correct.</exception>
        public static TService GetServiceInstance <TService>(this IRpcChannel connection, RpcObjectId objectId, bool useSyncContext = true) where TService : class
        {
            if (connection is null)
            {
                throw new ArgumentNullException(nameof(connection));
            }

            return(connection.GetServiceInstance <TService>(objectId, default, useSyncContext ? SynchronizationContext.Current : null));
 public ClientDispatchProxy(IServiceProvider serviceProvider)
 {
     ServiceProvider = serviceProvider;
     m_RpcChannel    = serviceProvider.GetRequiredService <IRpcChannel>();
     m_RpcChannel.NewPackageReceived += NewPackageReceived;
     m_RpcCodec         = serviceProvider.GetRequiredService <IRpcCodec>();
     m_InvokeRepository = serviceProvider.GetRequiredService <IInvokeRepository>();
 }
Exemple #5
0
 public object DecodeRpcCallResultMessage(IRpcChannel channel, IRpcObjectRepository localRepository,
                                          IRpcObjectRepository remoteRepository, IRpcSerializer serializer, RpcCallResultMessage message, Type resultType)
 {
     if (message.Type == RpcMessageType.Exception)
     {
         throw new TargetInvocationException((Exception)message.Result.Value);
     }
     return(DecodeRpcArgument(channel, localRepository, remoteRepository, serializer, message.Result, resultType));
 }
Exemple #6
0
 public RpcProxyArgs(
     IRpcChannel connection, RpcObjectId objectId, IRpcSerializer serializer,
     IReadOnlyCollection <string>?implementedServices,
     SynchronizationContext?syncContext)
 {
     this.Channel             = connection ?? throw new ArgumentNullException(nameof(connection));
     this.ObjectId            = objectId;
     this.Serializer          = serializer;
     this.ImplementedServices = implementedServices;
     this.SyncContext         = syncContext;
 }
Exemple #7
0
 internal GrpcProxyArgs(IRpcChannel connection,
                        GrpcCore.CallInvoker callInvoker,
                        RpcObjectId objectId,
                        GrpcMethodsCache methodsCache,
                        IRpcSerializer serializer,
                        IReadOnlyCollection <string>?implementedServices,
                        SynchronizationContext?syncContext)
     : base(connection, objectId, serializer, implementedServices, syncContext)
 {
     this.CallInvoker  = callInvoker;
     this.MethodsCache = methodsCache;
 }
        public static TService Create <TService>(IRpcChannel rpcChannel)
            where TService : class, IRpcService
        {
            var serviceType = typeof(TService);

            if (!_proxyClientCache.ContainsKey(serviceType) || !_proxyClientCache.TryGetValue(serviceType, out var serviceInstanceTypeInfo))
            {
                serviceInstanceTypeInfo = _builder.Create <TService>();
                _proxyClientCache.TryAdd(serviceType, serviceInstanceTypeInfo);
            }

            var instance = Activator.CreateInstance(serviceInstanceTypeInfo, rpcChannel);

            return((TService)instance);
        }
Exemple #9
0
        public object DecodeRpcArgument(IRpcChannel channel, IRpcObjectRepository localRepository,
                                        IRpcObjectRepository remoteRepository, IRpcSerializer serializer, RpcArgument argument, Type argumentType)
        {
            switch (argument.Type)
            {
            case RpcType.Builtin:
                if (argument.Value == null || argumentType == typeof(void))
                {
                    return(null);
                }
                if (argumentType.IsAssignableFrom(argument.Value.GetType()))
                {
                    return(argument.Value);
                }

                return(serializer.ChangeType(argument.Value, argumentType));

            case RpcType.Proxy:
                var instanceId = (int)serializer.ChangeType(argument.Value, typeof(int));
                var instance   = localRepository.GetInstance(instanceId);
                if (instance == null)
                {
                    var intfTypes = localRepository.ResolveTypes(argument.TypeId, argumentType);
                    instance = remoteRepository.GetProxyObject(channel, intfTypes, instanceId);
                }
                return(instance);

            case RpcType.Serialized:
                var type = localRepository.ResolveTypes(argument.TypeId, argumentType)[0];
                return(serializer.ChangeType(argument.Value, type));

            case RpcType.ObjectArray:
                var arrayType   = localRepository.ResolveTypes(argument.TypeId, argumentType)[0];
                var elementType = arrayType?.GetElementType() ?? throw new InvalidOperationException();
                var array       = Array.CreateInstance(elementType, (int)argument.Value);

                for (int i = 0; i < array.Length; i++)
                {
                    array.SetValue(DecodeRpcArgument(channel, localRepository, remoteRepository, serializer, argument.ArrayElements[i],
                                                     elementType), i);
                }

                return(array);

            default:
                throw new InvalidDataException();
            }
        }
Exemple #10
0
        public override object GetProxyObject(IRpcChannel channel, Type[] interfaceTypes, int remoteInstanceId)
        {
            lock (_rpcObjects)
            {
                Purge();
                if (_rpcObjects.TryGetValue(RpcHandle.ComparisonHandle(remoteInstanceId), out var obj))
                {
                    if (((RpcObjectHandle)obj).Object.TryGetTarget(out var inst))
                    {
                        return(inst);
                    }
                }

                bool isDelegate = interfaceTypes.Length == 1 && interfaceTypes[0].IsSubclassOf(typeof(Delegate));

                var result = new RpcObjectHandle(null, pinned: /*isDelegate && !_clientRepository,*/ false, instanceId: remoteInstanceId);
                _rpcObjects.Add(result);

                object instance;
                if (isDelegate)
                {
                    throw new NotSupportedException("We do not support delegates for now.");
                }
                else
                {
                    var typesHash = CreateTypesHash(interfaceTypes);
                    if (!_typeImplementations.TryGetValue(typesHash, out var implementationType))
                    {
                        throw new InvalidOperationException($"Implementation type for interfaces {string.Join(", ", interfaceTypes.Select(t => t.ToString()))} not found.");
                    }
                    var constructor = implementationType.GetConstructor(
                        BindingFlags.NonPublic | BindingFlags.Instance,
                        null,
                        new Type[] { typeof(IRpcChannel), typeof(int), typeof(int) },
                        null);
                    instance = constructor.Invoke(new object[] { channel, result.InstanceId, remoteInstanceId });
                }


                result.Object = new WeakReference <object>(instance);
                return(instance);
            }
        }
        public bool RemoveKnownChannel(IRpcChannel channel)
        {
            var connectionInfo = channel?.ConnectionInfo;

            if (connectionInfo == null)
            {
                return(false);
            }

            bool removed = false;

            lock (this.syncRoot)
            {
                if (connectionInfo.ServerId != RpcServerId.Empty)
                {
                    if (this.idToKnownConnection.TryGetValue(connectionInfo.ServerId, out var currConnection))
                    {
                        if (channel == currConnection)
                        {
                            this.idToKnownConnection.Remove(connectionInfo.ServerId);
                            removed = true;
                        }
                    }
                }

                if (connectionInfo.HostUrl != null)
                {
                    if (this.urlToKnownConnection.TryGetValue(connectionInfo.HostUrl, out var currConnection))
                    {
                        if (channel == currConnection)
                        {
                            this.urlToKnownConnection.Remove(connectionInfo.HostUrl);
                            removed = true;
                        }
                    }
                }
            }

            return(removed);
        }
        private object ImplementDelegate(Type delegateType, IRpcChannel channel, int remoteInstanceId, int localInstanceId)
        {
            RpcTypeDefinition type;

            lock (_proxyImplementations)
            {
                var hash = CreateTypesHash(delegateType);
                if (!_proxyImplementations.TryGetValue(hash, out type))
                {
                    var tb           = _moduleBuilder.DefineType($"{delegateType.Name}Shadow{Guid.NewGuid():n}");
                    var invokerField = CreateConstructor(tb);
                    var(localField, remoteField) = ImplementIRpcObjectProxy(tb);

                    CreateDestructor(tb, invokerField, localField, remoteField);

                    ImplementMethod(tb, delegateType.GetMethod("Invoke"), invokerField, remoteField, false);

                    type = new RpcTypeDefinition
                    {
                        Type = tb.CreateTypeInfo().AsType()
                    };
                    type.LocalIdField  = type.Type.GetField(localField.Name, BindingFlags.NonPublic | BindingFlags.Instance);
                    type.RemoteIdField = type.Type.GetField(remoteField.Name, BindingFlags.NonPublic | BindingFlags.Instance);

                    _proxyImplementations.Add(hash, type);
                }
            }



            var delObj = Activator.CreateInstance(type.Type, channel);

            Debug.Assert(type.LocalIdField != null, "type.LocalIdField != null");
            Debug.Assert(type.RemoteIdField != null, "type.RemoteIdField != null");
            type.LocalIdField.SetValue(delObj, localInstanceId);
            type.RemoteIdField.SetValue(delObj, remoteInstanceId);

            return(Delegate.CreateDelegate(delegateType, delObj, "Invoke"));
        }
        public void GeneratedStubFooCall()
        {
            FooRequest           fooRequest     = FooRequest.CreateBuilder().Build();
            MockRepository       mocks          = new MockRepository();
            IRpcChannel          mockChannel    = mocks.StrictMock <IRpcChannel>();
            IRpcController       mockController = mocks.StrictMock <IRpcController>();
            TestService          service        = TestService.CreateStub(mockChannel);
            Action <FooResponse> doneHandler    = mocks.StrictMock <Action <FooResponse> >();

            using (mocks.Record()) {
                // Nasty way of mocking out "the channel calls the done handler".
                Expect.Call(() => mockChannel.CallMethod(null, null, null, null, null))
                .IgnoreArguments()
                .Constraints(Is.Same(FooDescriptor), Is.Same(mockController), Is.Same(fooRequest),
                             Is.Same(FooResponse.DefaultInstance), Is.Anything())
                .Do((CallFooDelegate)((p1, p2, p3, response, done) => done(response)));
                doneHandler.Invoke(FooResponse.DefaultInstance);
            }

            service.Foo(mockController, fooRequest, doneHandler);

            mocks.VerifyAll();
        }
        public void AddKnownChannel(IRpcChannel channel)
        {
            if (channel == null || channel.ConnectionInfo == null)
            {
                throw new ArgumentNullException(nameof(channel));
            }

            var connectionInfo = channel.ConnectionInfo;
            Uri?hostUrl        = connectionInfo?.HostUrl;

            if (connectionInfo == null ||
                (connectionInfo.ServerId == RpcServerId.Empty && hostUrl == null))
            {
                throw new ArgumentException("Known connection must include a ServerId or HostUrl.");
            }

            lock (this.syncRoot)
            {
                if (this.idToKnownConnection.ContainsKey(channel.ConnectionInfo.ServerId) ||
                    (hostUrl != null && this.urlToKnownConnection.ContainsKey(hostUrl)) ||
                    this.idToServerConnection.ContainsKey(channel.ConnectionInfo.ServerId) ||
                    (hostUrl != null && this.urlToServerConnection.ContainsKey(hostUrl)))
                {
                    throw new InvalidOperationException($"Known connection '{channel}' already added.");
                }

                if (connectionInfo.ServerId != RpcServerId.Empty)
                {
                    this.idToKnownConnection.Add(connectionInfo.ServerId, channel);
                }

                if (connectionInfo.HostUrl != null)
                {
                    this.urlToKnownConnection.Add(connectionInfo.HostUrl, channel);
                }
            }
        }
Exemple #15
0
 protected GrpcClientBase(IRpcChannel rpcChannel)
 {
     this._rpcChannel = rpcChannel ?? throw new ArgumentNullException(nameof(rpcChannel));
 }
        private object ImplementInterfaces(Type[] interfaceTypes, IRpcChannel channel, int remoteInstanceId, int localInstanceId)
        {
            if (!AllowNonPublicInterfaceAccess)
            {
                if (interfaceTypes.All(interfaceType =>
                                       interfaceType.IsInterface && !interfaceType.IsPublic && !interfaceType.IsNestedPublic))
                {
                    throw new RpcFailedException("Cannot get non public interface.");
                }
            }

            RpcTypeDefinition type;

            lock (_proxyImplementations)
            {
                var hash = CreateTypesHash(interfaceTypes);

                if (!_proxyImplementations.TryGetValue(hash, out type))
                {
                    /*
                     #if !NETSTANDARD && DEBUG
                     * ab = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("RpcDynamicTypes"),
                     *  AssemblyBuilderAccess.RunAndSave);
                     #endif*/

                    //add a destructor so we can inform other side about us not needing the object anymore


                    var tb = _moduleBuilder.DefineType($"I{Guid.NewGuid():N}Shadow");

                    var invokerField = CreateConstructor(tb);

                    var(localField, remoteField) = ImplementIRpcObjectProxy(tb);

                    CreateDestructor(tb, invokerField, localField, remoteField);

                    var allInterfaceTypes = AllowNonPublicInterfaceAccess
                       ? interfaceTypes
                       : interfaceTypes.Where(i => i.IsPublic || i.IsNestedPublic);

                    foreach (var intf in allInterfaceTypes)
                    {
                        tb.AddInterfaceImplementation(intf);
                        foreach (var method in intf.GetMethods().Where(m => !m.IsSpecialName))
                        {
                            ImplementMethod(tb, method, invokerField, remoteField, true);
                        }

                        foreach (var property in intf.GetProperties())
                        {
                            var prop = tb.DefineProperty(property.Name, property.Attributes, property.PropertyType,
                                                         null);
                            if (property.GetMethod != null)
                            {
                                prop.SetGetMethod(ImplementMethod(tb, property.GetMethod, invokerField,
                                                                  remoteField,
                                                                  true));
                            }

                            if (property.SetMethod != null)
                            {
                                prop.SetSetMethod(ImplementMethod(tb, property.SetMethod, invokerField,
                                                                  remoteField,
                                                                  true));
                            }
                        }

                        foreach (var evnt in intf.GetEvents())
                        {
                            if (evnt.AddMethod != null)
                            {
                                ImplementMethod(tb, evnt.AddMethod, invokerField, remoteField, true);
                            }

                            if (evnt.RemoveMethod != null)
                            {
                                ImplementMethod(tb, evnt.RemoveMethod, invokerField, remoteField, true, true);
                            }
                        }
                    }


                    type = new RpcTypeDefinition
                    {
                        Type = tb.CreateTypeInfo().AsType()
                    };
                    type.LocalIdField  = type.Type.GetField(localField.Name, BindingFlags.NonPublic | BindingFlags.Instance);
                    type.RemoteIdField = type.Type.GetField(remoteField.Name, BindingFlags.NonPublic | BindingFlags.Instance);

                    _proxyImplementations.Add(hash, type);
                }
            }

            /*
             #if !NETSTANDARD && DEBUG
             * ab.Save(@"RpcDynamicTypes.dll");
             #endif*/


            var result = Activator.CreateInstance(type.Type, channel);

            Debug.Assert(type.LocalIdField != null, "type.LocalIdField != null");
            Debug.Assert(type.RemoteIdField != null, "type.RemoteIdField != null");
            type.LocalIdField.SetValue(result, localInstanceId);
            type.RemoteIdField.SetValue(result, remoteInstanceId);

            return(result);
        }
 public abstract object GetProxyObject(IRpcChannel channel, Type[] interfaceTypes, int remoteInstanceId);