示例#1
0
        /// <summary>
        /// Private method for simplifying the remote procedure call.  I don't want to write this in IL!!
        /// </summary>
        /// <param name="clientObject"></param>
        /// <param name="functionToCall"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public static object RemoteCallClient(IRPCProxy clientObject, string functionToCall, object[] args)
        {
            if (!clientObject.IsDisposed)
            {
                var connection = clientObject.ServerConnection;

                RemoteCallWrapper wrapper = new RemoteCallWrapper();
                wrapper.args       = (from arg in args select RPCArgumentBase.CreateDynamic(arg)).ToList();
                wrapper.name       = functionToCall;
                wrapper.instanceId = clientObject.ServerInstanceID;
                var guid = ShortGuid.NewGuid();

                string packetTypeRequest  = clientObject.ImplementedInterface.Name + "-RPC-CALL-" + wrapper.instanceId;
                string packetTypeResponse = packetTypeRequest + "-" + guid;

                SendReceiveOptions options = clientObject.SendReceiveOptions;
                clientObject.RPCTimeout = 500000;

                if (options != null)
                {
                    wrapper = connection.SendReceiveObject <RemoteCallWrapper, RemoteCallWrapper>(packetTypeRequest, packetTypeResponse, clientObject.RPCTimeout, wrapper, options, options);
                }
                else
                {
                    wrapper = connection.SendReceiveObject <RemoteCallWrapper, RemoteCallWrapper>(packetTypeRequest, packetTypeResponse, clientObject.RPCTimeout, wrapper);
                }

                if (wrapper.Exception != null)
                {
                    throw new RPCException(wrapper.Exception);
                }

                for (int i = 0; i < args.Length; i++)
                {
                    args[i] = wrapper.args[i].UntypedValue;
                }

                if (wrapper.result != null)
                {
                    return(wrapper.result.UntypedValue);
                }
                else
                {
                    return(null);
                }
            }
            else
            {
                throw new ObjectDisposedException("clientObject", "RPC object has already been disposed of and cannot be reused");
            }
        }
示例#2
0
            private static EventHandler <A> GenerateEvent <A>(Connection clientConnection, string instanceId, Type interfaceType, string eventName) where A : EventArgs
            {
                return(new EventHandler <A>((sender, args) =>
                {
                    var packetType = interfaceType.Name + "-RPC-LISTENER-" + instanceId;
                    RemoteCallWrapper callWrapper = new RemoteCallWrapper();
                    callWrapper.name = eventName;
                    callWrapper.instanceId = instanceId;
                    callWrapper.args = new List <RPCArgumentBase>()
                    {
                        RPCArgumentBase.CreateDynamic(sender), RPCArgumentBase.CreateDynamic(args)
                    };

                    clientConnection.SendObject(packetType, callWrapper);
                }));
            }
示例#3
0
        /// <summary>
        /// Causes the provided <see cref="IRPCProxy"/> instance to be disposed
        /// </summary>
        /// <param name="clientObject">The <see cref="IRPCProxy"/> to dispose</param>
        public static void DestroyRPCClient(IRPCProxy clientObject)
        {
            if (!clientObject.IsDisposed)
            {
                clientObject.GetType().GetField("isDisposed", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(clientObject, true);

                var connection = clientObject.ServerConnection;

                if (connection.ConnectionInfo.ConnectionState != ConnectionState.Shutdown)
                {
                    string packetTypeRequest = clientObject.ImplementedInterface.Name + "-REMOVE-REFERENCE-" + clientObject.ServerInstanceID;

                    RemoteCallWrapper wrapper = new RemoteCallWrapper();
                    wrapper.args       = new List <RPCArgumentBase>();
                    wrapper.name       = null;
                    wrapper.instanceId = clientObject.ServerInstanceID;

                    //Tell the server that we are no longer listenning
                    try { connection.SendObject <RemoteCallWrapper>(packetTypeRequest, wrapper); }
                    catch (Exception) { }

                    //Next remove the event packet handler
                    try { connection.RemoveIncomingPacketHandler(clientObject.ImplementedInterface.Name + "-RPC-LISTENER-" + clientObject.ServerInstanceID); }
                    catch (Exception) { }

                    //Next remove the server side dispose handler
                    try { connection.RemoveIncomingPacketHandler(clientObject.ImplementedInterface.Name + "-RPC-DISPOSE-" + clientObject.ServerInstanceID); }
                    catch (Exception) { }
                }

                //Finally remove the object from the cache. This guarentees that if we try to get the instance again at some time in the future
                //we won't end up with a disposed RPC object
                lock (cacheLocker)
                {
                    var cacheKey = new CachedRPCKey(clientObject.ServerInstanceID, clientObject.ServerConnection, clientObject.ImplementedInterface);

                    try { cachedInstances.Remove(cacheKey); }
                    catch (Exception) { }
                }
            }
        }
示例#4
0
        private static void RPCDisconnectHandler <T, I>(PacketHeader header, Connection connection, RemoteCallWrapper wrapper) where T : I
        {
            lock (locker)
            {
                if (!RPCObjectsById.ContainsKey(wrapper.instanceId))
                {
                    return;
                }

                var rpcObject = RPCObjectsById[wrapper.instanceId];
                rpcObject.RemoveClientSubscription(connection);
            }
        }
示例#5
0
        private static void RunRPCFunctionHandler <T, I>(PacketHeader header, Connection connection, RemoteCallWrapper wrapper) where T : I
        {
            I          instance = default(I);
            MethodInfo funcRef  = typeof(I).GetMethod(wrapper.name);

            try
            {
                lock (locker)
                {
                    instance = (I)(RPCObjectsById[wrapper.instanceId].RPCObject);
                }
            }
            catch (Exception)
            {
                wrapper.result    = null;
                wrapper.Exception = "SERVER SIDE EXCEPTION\n\n" + "Invalid instanceID" + "\n\nEND SERVER SIDE EXCEPTION\n\n";
                connection.SendObject(header.PacketType, wrapper);
                return;
            }

            object[] args = null;

            if (wrapper.args == null)
            {
                args = new object[0];
            }
            else
            {
                args = (from arg in wrapper.args select arg.UntypedValue).ToArray();
            }

            try
            {
                wrapper.result = RPCArgumentBase.CreateDynamic(funcRef.Invoke(instance, args));
                wrapper.args   = (from arg in args select RPCArgumentBase.CreateDynamic(arg)).ToList();
            }
            catch (Exception e)
            {
                wrapper.result = null;

                if (e.InnerException != null)
                {
                    e = e.InnerException;
                }

                wrapper.Exception = "SERVER SIDE EXCEPTION\n\n" + e.ToString() + "\n\nEND SERVER SIDE EXCEPTION\n\n";
            }

            string returnPacketType = header.GetOption(PacketHeaderStringItems.RequestedReturnPacketType);

            connection.SendObject(returnPacketType, wrapper);
        }