Exemple #1
0
        /// <summary>
        /// Wait on connection and received messages
        /// </summary>
        protected virtual void ReceiveAction()
        {
            try
            {
                using (NamedPipeServerStream serverStream =
                           new NamedPipeServerStream(
                               PipeName,
                               PipeDirection.InOut,
                               NumberOfThreads,
                               PipeTransmissionMode.Byte,
                               PipeOptions.Asynchronous))
                {
                    Task t = serverStream.WaitForConnectionAsync(CancellationToken.Token);
                    t.GetAwaiter().GetResult();


                    Guid      id     = Guid.NewGuid();
                    IpcStream stream = new IpcStream(serverStream, KnownTypes);

                    while (ProcessMessage(stream, id))
                    {
                    }
                    StatefulProxy.NotifyDisconnect(id);
                }

                // Todo: make sure there's a new listener, even when this isn't reached
                serverTask.Add(Task.Factory.StartNew(ReceiveAction));
            }
            catch (OperationCanceledException) { }
        }
Exemple #2
0
        /// <summary>
        /// Establish the TCP connection asynchonously
        /// </summary>
        /// <param name="keepalive">Wether the connection should be kept alive after a first message</param>
        /// <returns>True for success, False otherwise</returns>
        public async Task <bool> ConnectAsync(bool keepalive = true)
        {
            try
            {
                // connect socket
                connection                = new System.Net.Sockets.TcpClient();
                connection.NoDelay        = true;
                connection.ReceiveTimeout = 2000;
                await connection.ConnectAsync(EndPoint.Address, EndPoint.Port).ConfigureAwait(false);

                System.IO.Stream connectionStream = connection.GetStream();

                Stream = new IpcStream(connectionStream, KnownTypes, Encryptor);
            }
            catch (SocketException e)
            {
                System.Diagnostics.Debug.WriteLine(e);
                return(false);
            }

            if (keepalive)
            {
                StartPing();
            }

            return(true);
        }
Exemple #3
0
        /// <summary>
        /// Main connection loop, waits for and handles connections
        /// </summary>
        protected override void ReceiveAction()
        {
            try
            {
                var t = listener.AcceptTcpClientAsync(CancellationToken.Token);

                // wait for connection
                using (System.Net.Sockets.TcpClient client = t.GetAwaiter().GetResult())
                {
                    // Start new connection waiter before anything can go wrong here,
                    // leaving us without a server
                    serverTask.Add(Task.Factory.StartNew(ReceiveAction));

                    using (NetworkStream networkStream = client.GetStream())
                    {
                        networkStream.ReadTimeout = Server.ReadTimeOut;
                        Stream serverStream = networkStream;

                        Guid      id     = Guid.NewGuid();
                        IpcStream stream = new IpcStream(serverStream, KnownTypes, Encryptor);

                        // process incoming messages until disconnect
                        while (ProcessMessage(stream, id))
                        {
                        }
                        StatefulProxy.NotifyDisconnect(id);

                        serverStream.Close();
                    }
                }
            }
            catch (OperationCanceledException) { }
        }
Exemple #4
0
        /// <summary>
        /// Scans the service interface and registers custom proxy class
        /// </summary>
        /// <typeparam name="T">Service interface, must equal server-side</typeparam>
        /// <returns>Proxy class for remote calls</returns>
        public void RegisterServiceProxy <T>(Proxy <T> customProxy)
        {
            // check if service implements interface
            if (customProxy.GetType().GetInterface(typeof(T).Name) == null)
            {
                throw new InvalidOperationException("Custom Proxy class does not implement service interface");
            }

            IpcStream.ScanInterfaceForTypes(typeof(T), KnownTypes);
        }
Exemple #5
0
        /// <summary>
        /// Register a service interface on the server
        /// This is a one instance for all clients service
        /// </summary>
        /// <typeparam name="T">The interface of the service</typeparam>
        /// <param name="instance">Instance of a class implementing the service</param>
        public void RegisterService <T>(T instance)
        {
            if (!typeof(T).IsInterface)
            {
                throw new InvalidOperationException("Service Type is not an interface");
            }

            if (!(instance is T))
            {
                throw new InvalidOperationException("Instance must implement service interface");
            }

            services[typeof(T).Name] = instance;
            types[typeof(T).Name]    = typeof(T);

            IpcStream.ScanInterfaceForTypes(typeof(T), KnownTypes);
        }
Exemple #6
0
        /// <summary>
        /// Establish the TCP connection
        /// </summary>
        /// <param name="keepalive">Wether the connection should be kept alive after a first message</param>
        /// <returns>True for success, False otherwise</returns>
        public override bool Connect(bool keepalive = true)
        {
            try
            {
                // connect socket
                connection = new System.Net.Sockets.TcpClient();
                connection.ReceiveTimeout = 2000;
                connection.Connect(EndPoint);
                System.IO.Stream connectionStream = connection.GetStream();

                Stream = new IpcStream(connectionStream, KnownTypes, Encryptor);
            } catch (SocketException e)
            {
                System.Diagnostics.Debug.WriteLine(e);
                return(false);
            }

            if (keepalive)
            {
                StartPing();
            }

            return(true);
        }
Exemple #7
0
        /// <summary>
        /// Register a service interface on the server that keeps its state for a connection
        /// This a one instance for one client/connection service
        /// </summary>
        /// <typeparam name="T">The interface of the service</typeparam>
        /// <param name="t">Type of the class implementing the service, should have a default constructor
        /// which will be called on connection of a new client</param>
        public void RegisterStatefulService <T>(Type t)
        {
            if (!typeof(T).IsInterface)
            {
                throw new InvalidOperationException("Service Type is not an interface");
            }

            // check if service implements interface
            if (t.GetInterface(typeof(T).Name) == null)
            {
                throw new InvalidOperationException("Instance must implement service interface");
            }

            // check for default constructor
            if (t.GetConstructor(Type.EmptyTypes) == null || t.IsAbstract)
            {
                throw new InvalidOperationException("Stateful service requires default constructor");
            }

            services[typeof(T).Name] = new StatefulProxy(t);
            types[typeof(T).Name]    = typeof(T);

            IpcStream.ScanInterfaceForTypes(typeof(T), KnownTypes);
        }
Exemple #8
0
        /// <summary>
        /// Connect to server. This opens a persistent connection allowing multiple remote calls
        /// until <see cref="Disconnect(bool)"/> is called.
        /// </summary>
        /// <param name="keepalive">Whether to send pings over the connection to keep it alive</param>
        /// <returns>True if succeeded, false if not</returns>
        public virtual bool Connect(bool keepalive = true)
        {
            NamedPipeClientStream source = new NamedPipeClientStream(
                ".",
                PipeName,
                PipeDirection.InOut,
                PipeOptions.Asynchronous);

            try
            {
                source.Connect(500);
            } catch (TimeoutException)
            {
                return(false);
            }

            Stream = new IpcStream(source, KnownTypes);

            if (keepalive)
            {
                StartPing();
            }
            return(true);
        }
Exemple #9
0
        /// <summary>
        /// Process a received message by calling the corresponding method on the service instance and
        /// returning the return value over the network.
        /// </summary>
        /// <param name="stream">The message stream</param>
        /// <param name="streamId">A GUID identifying this connection</param>
        public bool ProcessMessage(IpcStream stream, Guid streamId)
        {
            IpcMessage msg = stream.ReadMessage();

            // this was a close-connection notification
            if (msg.StatusMsg == StatusMessage.CloseConnection)
            {
                return(false);
            }
            // or this is just a keepalive ping
            else if (msg.StatusMsg == StatusMessage.Ping)
            {
                return(true);
            }

            bool       processedOk = false;
            string     error       = "";
            object     rv          = null;
            IpcMessage returnMsg   = new IpcMessage();

            // find the service
            if (services.TryGetValue(msg.Service, out object instance) && instance != null)
            {
                // double check method existence against type-list for security
                // typelist will contain interfaces instead of instances
                if (types[msg.Service].GetMethod(msg.Method) != null)
                {
                    // separate handling for stateful service
                    if (instance is StatefulProxy)
                    {
                        try
                        {
                            // invoke method
                            System.Reflection.MethodInfo method =
                                (instance as StatefulProxy).Type.GetMethod(msg.Method);
                            if (method == null)
                            {
                                throw new InvalidOperationException("Method not found in stateful proxy");
                            }

                            rv          = (instance as StatefulProxy).Invoke(streamId, method, msg.Parameters);
                            processedOk = true;

                            // check if encryption is required
                            if (Attribute.IsDefined(method, typeof(EncryptIfTrueAttribute)) &&
                                (bool)rv == true)
                            {
                                returnMsg.StatusMsg = StatusMessage.Encrypt;
                            }
                        }
                        catch (Exception e) { error = e.ToString(); }
                    }
                    else
                    {
                        // get the method
                        System.Reflection.MethodInfo method = instance.GetType().GetMethod(msg.Method);
                        if (method != null)
                        {
                            try
                            {
                                // invoke method
                                rv          = method.Invoke(instance, msg.Parameters);
                                processedOk = true;

                                // check if encryption is required
                                if (Attribute.IsDefined(method, typeof(EncryptIfTrueAttribute)) &&
                                    (bool)rv == true)
                                {
                                    returnMsg.StatusMsg = StatusMessage.Encrypt;
                                }
                            }
                            catch (Exception e) { error = e.ToString(); }
                        }
                        else
                        {
                            error = "Could not find method";
                        }
                    }
                }
                else
                {
                    error = "Could not find method in type";
                }
            }
            else
            {
                error = "Could not find service";
            }

            // return either return value or error message
            if (processedOk)
            {
                returnMsg.Return = rv;
            }
            else
            {
                returnMsg.Error     = error;
                returnMsg.StatusMsg = StatusMessage.None;
            }

            stream.WriteMessage(returnMsg);

            // if there's more to come, keep reading a next message
            if (msg.StatusMsg == StatusMessage.KeepAlive)
            {
                return(true);
            }
            else // otherwise close the connection
            {
                return(false);
            }
        }
Exemple #10
0
        /// <summary>
        /// Scans the service interface and builds proxy class
        /// </summary>
        /// <typeparam name="T">Service interface, must equal server-side</typeparam>
        /// <returns>Proxy class for remote calls</returns>
        public T GetServiceProxy <T>()
        {
            IpcStream.ScanInterfaceForTypes(typeof(T), KnownTypes);

            return((T) new ProxyGenerator().CreateInterfaceProxyWithoutTarget(typeof(T), new Proxy <T>(this)));
        }