private void HandleVoicePacket(Command command, RemoteUser remoteUser)
        {
            if (remoteUser.IsInCallWith == null)
                return;

            remoteUser.IsInCallWith.Peer.SendCommand(command);
        }
        private void HandleEndCall(Command command, RemoteUser remoteUser)
        {
            if (remoteUser.IsInCallWith == null)
                return;

            var cmd = _commandBuilder.Create(CommandName.EndCall, string.Empty);
            remoteUser.IsInCallWith.Peer.SendCommand(cmd);
        }
        private async void HandleDial(Command command, RemoteUser remoteUser)
        {
            var callerNumber = _commandBuilder.GetUnderlyingObject<string>(command);
            var opponent = _connectionsManager.FindRemoteUserByNumber(callerNumber);

            var dialResult = new DialResult();

            if (opponent == null)
            {
                var opponentUser = _usersRepository.GetByNumber(callerNumber);
                if (opponentUser != null)
                {
                    _pushSender.SendVoipPush(opponentUser.PushUri, remoteUser.User.Number, remoteUser.User.Number);
                    var resultCommand = await _connectionsManager.PostWaiter(opponentUser.UserId, CommandName.IncomingCall);
                    var answerType = _commandBuilder.GetUnderlyingObject<AnswerResultType>(resultCommand);
                    if (answerType == AnswerResultType.Answered)
                    {
                        dialResult.Result = DialResultType.Answered;
                        opponent.IsInCallWith = remoteUser;
                        remoteUser.IsInCallWith = opponent;
                    }
                    else
                    {
                        dialResult.Result = DialResultType.Declined;
                    }
                }
                else
                {
                    dialResult.Result = DialResultType.NotFound;
                }
            }
            else
            {
                var incomingCallCommand = _commandBuilder.Create(CommandName.IncomingCall, callerNumber);
                var resultCommand = await opponent.Peer.SendCommandAndWaitAnswer(incomingCallCommand);
                var answerType = _commandBuilder.GetUnderlyingObject<AnswerResultType>(resultCommand);
                if (answerType == AnswerResultType.Answered)
                {
                    dialResult.Result = DialResultType.Answered;
                    opponent.IsInCallWith = remoteUser;
                    remoteUser.IsInCallWith = opponent;
                }
                else
                {
                    dialResult.Result = DialResultType.Declined;
                }
            }
            _commandBuilder.ChangeUnderlyingObject(command, dialResult);
            remoteUser.Peer.SendCommand(command);
        }
        private async void HandleAuthentication(RemoteUser remoteUser, Command command)
        {
            var request = _commandBuilder.GetUnderlyingObject<AuthenticationRequest>(command);
            var result = new AuthenticationResult();

            var user = _usersRepository.GetById(request.UserId);
            if (user != null)
            {
                result.Result = AuthenticationResultType.Success;
                user.OsName = request.OsName;
                user.PushUri = request.PushUri;
                user.DeviceName = request.DeviceName;
            }
            else
            {
                result.Result = AuthenticationResultType.NotRegistered;
            }
            _commandBuilder.ChangeUnderlyingObject(command, result);
            await remoteUser.Peer.SendCommand(command);
        }
        private async void HandleRegistration(RemoteUser remoteUser, Command command)
        {
            var request = _commandBuilder.GetUnderlyingObject<RegistrationRequest>(command);
            var result = new RegistrationResult();

            if (string.IsNullOrEmpty(request.Number) ||
                request.Number.Length < 4 ||
                request.Number.Trim(' ', '+').ToCharArray().Any(i => !char.IsDigit(i)))
            {
                result.Result = RegistrationResultType.NotRegistered;
            }
            else
            {
                remoteUser.User.Number = request.Number;
                remoteUser.User.UserId = Guid.NewGuid().ToString();
                _usersRepository.Add(remoteUser.User);
                result.Result = RegistrationResultType.Success;
                result.UserId = remoteUser.User.UserId;
            }
            _commandBuilder.ChangeUnderlyingObject(command, result);
            await remoteUser.Peer.SendCommand(command);
        }
        private void _resource_OnReceived(object sender, PeerCommandEventArgs e)
        {
            try
            {
                lock (_activeConnections)
                {
                    var command = _serializer.Deserialize(e.Data);
                    if (!string.IsNullOrEmpty(command.UserId))
                    {
                        lock (_responceWaiters)
                        {
                            TaskCompletionSource<Command> taskSource;
                            if (_responceWaiters.TryGetValue(new Tuple<string, CommandName>(command.UserId, command.Name),
                                out taskSource))
                            {
                                taskSource.TrySetResult(command);
                            }
                        }
                    }

                    var user = _userRepository.GetById(command.UserId);
                    RemoteUser remoteUser;
                    if (user != null)
                    {
                        var existedConnection = _activeConnections.FirstOrDefault(i => i.User.Equals(user));
                        if (existedConnection != null)
                        {
                            existedConnection.Peer = e.Peer;
                            existedConnection.Peer.UpdateLastActivity();
                            remoteUser = existedConnection;
                        }
                        else
                        {
                            remoteUser = new RemoteUser(user, e.Peer);
                        }
                        _activeConnections.Add(remoteUser);
                    }
                    else
                    {
                        remoteUser = new RemoteUser(new User(), e.Peer);
                        _activeConnections.Add(remoteUser);
                    }
                    CommandRecieved(this, new RemoteUserCommandEventArgs { Command = command, RemoteUser = remoteUser });
                }
            }
            catch (Exception exc)
            {
                Logger.Exception(exc, "_resource_OnReceived");
            }
        }