예제 #1
0
        /// <summary>
        /// Handles clients "join session" request.
        /// </summary>
        /// <param name="transporter">The transporter.</param>
        /// <param name="request">The request.</param>
        /// <returns></returns>
        /// <exception cref="AuthenticationException">Please login first.</exception>
        /// <exception cref="System.Exception">
        /// Cannot create a loop-back session!
        /// or
        /// Client {request.ClientID} was not found.
        /// or
        /// Client {request.ClientID} is already in session with another client.
        /// </exception>
        private ResonanceActionResult <JoinSessionResponse> OnClientJoinSessionRequest(IResonanceTransporter transporter, JoinSessionRequest request)
        {
            ResonanceTcpClient client = transporter as ResonanceTcpClient;

            if (client.ClientID == null)
            {
                throw new AuthenticationException("Please login first.");
            }

            var existingClient = _clients.FirstOrDefault(x => x.ClientID == request.ClientID);

            if (client == existingClient)
            {
                throw new Exception($"Cannot create a loop-back session!");
            }

            if (existingClient == null)
            {
                throw new Exception($"Client {request.ClientID} was not found.");
            }

            if (existingClient.InSession)
            {
                throw new Exception($"Client {request.ClientID} is already in session with another client.");
            }

            existingClient.SendRequestAsync <JoinSessionRequest, JoinSessionResponse>(new JoinSessionRequest()
            {
                ClientID = client.ClientID
            }, new ResonanceRequestConfig()
            {
                Timeout = TimeSpan.FromSeconds(10)
            }).GetAwaiter().GetResult();

            Task.Delay(100).ContinueWith((x) => //Delay the IsSession true to avoid routing of the JoinSessionResponse..
            {
                client.RemoteClient         = existingClient;
                existingClient.RemoteClient = client;
                client.InSession            = true;
                existingClient.InSession    = true;

                Logger.LogInformation($"Clients {client.ClientID} and {existingClient.ClientID} are now in session.");
            });

            return(new JoinSessionResponse());
        }
예제 #2
0
        /// <summary>
        /// Handles clients login request.
        /// </summary>
        /// <param name="transporter">The transporter.</param>
        /// <param name="request">The request.</param>
        /// <returns></returns>
        /// <exception cref="System.Exception">Client {request.ClientID} is already taken.</exception>
        private ResonanceActionResult <LoginResponse> OnClientLoginRequest(IResonanceTransporter transporter, LoginRequest request)
        {
            ResonanceTcpClient client = transporter as ResonanceTcpClient;

            if (_clients.Exists(x => x.ClientID == request.ClientID))
            {
                throw new Exception($"Client {request.ClientID} is already taken.");
            }

            client.ClientID = request.ClientID;
            _clients.Add(client);

            Logger.LogInformation($"{client.ClientID} is now connected.");

            UpdateClientsList();

            return(new LoginResponse());
        }
예제 #3
0
        /// <summary>
        /// Handles clients "leave session" request.
        /// </summary>
        /// <param name="transporter">The transporter.</param>
        /// <param name="request">The request.</param>
        private async void OnClientLeaveSessionRequest(IResonanceTransporter transporter, ResonanceMessage <LeaveSessionRequest> request)
        {
            ResonanceTcpClient client = transporter as ResonanceTcpClient;

            if (client.InSession)
            {
                Logger.LogWarning($"Client {client.ClientID} has closed the session.");
                client.InSession = false;
                client.RemoteClient.InSession = false;

                await client.RemoteClient.SendAsync(new LeaveSessionRequest()
                {
                    Reason = $"{client.RemoteClient.ClientID} has left the session"
                });

                client.RemoteClient.RemoteClient = null;
                client.RemoteClient = null;

                UpdateClientsList();
            }
        }
예제 #4
0
        /// <summary>
        /// Handles a client's stage changed event.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="ResonanceComponentStateChangedEventArgs"/> instance containing the event data.</param>
        private async void OnClientStateChanged(object sender, ResonanceComponentStateChangedEventArgs e)
        {
            ResonanceTcpClient client = sender as ResonanceTcpClient;

            if (e.NewState == ResonanceComponentState.Failed)
            {
                Logger.LogWarning($"Client {client.ClientID} disconnected.");

                _clients.Remove(client);

                UpdateClientsList();

                if (client.InSession)
                {
                    client.RemoteClient.InSession = false;
                    await client.RemoteClient.SendAsync(new LeaveSessionRequest()
                    {
                        Reason = "The remote client has disconnected"
                    });
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Handles incoming connections.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="ResonanceListeningServerConnectionRequestEventArgs{Adapters.Tcp.TcpAdapter}"/> instance containing the event data.</param>
        private async void OnConnectionRequest(object sender, ResonanceListeningServerConnectionRequestEventArgs <Adapters.Tcp.TcpAdapter> e)
        {
            ResonanceTcpClient newClient = new ResonanceTcpClient();

            //Enable keep alive so we are aware of clients losing contact.
            newClient.KeepAliveConfiguration.Enabled = true;

            //Configure the transporter fail when the keep alive determines no connection.
            newClient.KeepAliveConfiguration.FailTransporterOnTimeout = true;

            newClient.CreateBuilder()
            .WithAdapter(e.Accept())
            .WithJsonTranscoding()
            .Build();

            newClient.StateChanged += OnClientStateChanged;
            newClient.RegisterRequestHandler <LoginRequest, LoginResponse>(OnClientLoginRequest);
            newClient.RegisterRequestHandler <JoinSessionRequest, JoinSessionResponse>(OnClientJoinSessionRequest);
            newClient.RegisterRequestHandler <LeaveSessionRequest>(OnClientLeaveSessionRequest);

            await newClient.ConnectAsync();
        }