Example #1
0
            private static async Task <bool> OnRelease(ArenaSession s)
            {
                var l = s.GetLock();

                try
                {
                    using (var t = EndSession(s))
                    {
                        if (await t)
                        {
                            lock (sessions)
                            {
                                if (s._locks == 0)
                                {
                                    s.Session = null;
                                    sessions.Remove(s.Email);
                                    s.Dispose();

                                    return(true);
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    Util.Logging.Log(e);
                }
                finally
                {
                    l.Dispose();
                }

                return(false);
            }
Example #2
0
        public async Task AddGame(GameResultModel gameModel)
        {
            using (var context = dbContext())
            {
                var game = new GameResult();
                game.InjectFrom(gameModel);

                if (gameModel.Hero != null)
                {
                    game.Hero = context.Heroes.Find(gameModel.Hero.Id);
                }

                if (gameModel.OpponentHero != null)
                {
                    game.OpponentHero = context.Heroes.Find(gameModel.OpponentHero.Id);
                }

                ArenaSessionModel arenaModel = null;
                ArenaSession      arena      = null;
                if (gameModel.ArenaSession != null)
                {
                    gameModel.Deck = null;
                    game.DeckKey   = null;
                    game.Deck      = null;

                    arenaModel = gameModel.ArenaSession;
                    arena      = context.ArenaSessions.Query().FirstOrDefault(x => x.Id == arenaModel.Id);
                    if (arena == null)
                    {
                        throw new InvalidOperationException("Add arena using gameManager first!");
                    }
                    // context.Entry(arena).CurrentValues.SetValues(arenaModel);

                    AddGameToArena(game, arena);
                    SetEndDateIfNeeded(arena);
                    arena.Modified = DateTime.Now;
                }

                if (gameModel.Deck != null)
                {
                    game.Deck = context.Decks.Find(gameModel.Deck.Id);
                }

                context.Games.Add(game);

                await context.SaveChangesAsync();

                gameModel.InjectFrom(game);
                events.PublishOnBackgroundThread(new GameResultAdded(this, gameModel));
                if (arenaModel != null)
                {
                    arenaModel.InjectFrom(arena);
                    gameModel.ArenaSession = arenaModel;
                    arenaModel.Games.Add(gameModel);
                    var latestId = context.ArenaSessions.OrderByDescending(x => x.StartDate).Select(x => x.Id).FirstOrDefault();
                    events.PublishOnBackgroundThread(new ArenaSessionUpdated(arenaModel.Id, latestId == arenaModel.Id));
                }
            }
        }
 public static void MapFrom(this ArenaSessionModel target, ArenaSession source)
 {
     target.InjectFrom(source);
     // target.Games.IsNotifying = false;
     target.Games.Clear();
     target.Games.AddRange(source.Games.Select(g => g.ToModel()));
     // target.Games.IsNotifying = true;
     // target.Games.Refresh();            
 }
 public static void MapFrom(this ArenaSessionModel target, ArenaSession source)
 {
     target.InjectFrom(source);
     // target.Games.IsNotifying = false;
     target.Games.Clear();
     target.Games.AddRange(source.Games.Select(g => g.ToModel()));
     // target.Games.IsNotifying = true;
     // target.Games.Refresh();
 }
Example #5
0
        private void SetEndDateIfNeeded(ArenaSession arena)
        {
            if (arena.IsEnded && arena.EndDate == null)
            {
                arena.EndDate = DateTime.Now;
            }

            if (!arena.IsEnded && arena.EndDate != null)
            {
                arena.EndDate = null;
            }
        }
        public static ArenaSessionModel ToModel(this ArenaSession arena, int arenaSessionRecurse = 0)
        {
            if (arena == null)
            {
                return(null);
            }
            ArenaSessionModel model = null;

            model = new ArenaSessionModel();
            model.InjectFrom(arena);
            model.Games.AddRange(arena.Games.Select(x => x.ToModel(arenaSessionRecurse, model)));
            return(model);
        }
Example #7
0
            private static void Release(ArenaSession s)
            {
                lock (sessions)
                {
                    var b = s._locks == 0;

                    if (!b && --s._locks == 0)
                    {
                        s._released = DateTime.UtcNow;
                        b           = true;
                    }

                    if (b)
                    {
                        if (!s.HasSession)
                        {
                            var l = s.TryGetLock();
                            if (l != null)
                            {
                                try
                                {
                                    sessions.Remove(s.Email);
                                    s.Dispose();
                                    return;
                                }
                                finally
                                {
                                    l.Dispose();
                                }
                            }
                        }
                    }
                    else
                    {
                        return;
                    }

                    if (releasing != null)
                    {
                        releasing.Enqueue(s);
                    }
                    else
                    {
                        releasing = new Queue <ArenaSession>();
                        releasing.Enqueue(s);
                        ReleaseAsync();
                    }
                }
            }
Example #8
0
            private static Session GetSession(string email)
            {
                ArenaSession s;

                lock (sessions)
                {
                    if (!sessions.TryGetValue(email, out s))
                    {
                        sessions[email] = s = new ArenaSession(email);
                    }
                    ++s._locks;
                }

                return(new Session(s));
            }
Example #9
0
        protected void AddGameToArena(GameResult game, ArenaSession arena)
        {
            game.ArenaSessionId = arena.Id;
            game.ArenaSession   = arena;
            arena.Games.Add(game);

            if (game.Victory)
            {
                arena.Wins++;
            }
            else
            {
                arena.Losses++;
            }
        }
Example #10
0
            private static async Task <bool> VerifySession(ArenaSession s, Settings.PasswordString password, bool ping)
            {
                var b = s.HasSession;

                if (b && ping)
                {
                    try
                    {
                        b = await s.Session.Ping();
                    }
                    catch
                    {
                        b = false;
                    }
                }

                if (!b)
                {
                    if (password == null || password.Data.IsEmpty)
                    {
                        return(false);
                    }

                    OnLoginRequest();

                    using (var t = Tools.ArenaAccount.LoginAccount(s.Email, password.ToSecureString()))
                    {
                        await t;

                        s.Session = t.Result;

                        if (s.Session != null)
                        {
                            s.Password = password;

                            return(true);
                        }
                        else
                        {
                            return(false);
                        }
                    }
                }

                return(true);
            }
Example #11
0
                    public void Dispose()
                    {
                        lock (this)
                        {
                            if (s != null)
                            {
                                Monitor.Enter(s);

                                s._lock = null;

                                Monitor.Pulse(s);
                                Monitor.Exit(s);

                                s = null;
                            }
                        }
                    }
Example #12
0
                public void Release()
                {
                    GC.SuppressFinalize(this);

                    ArenaSession s;

                    lock (this)
                    {
                        if (session != null)
                        {
                            s       = session;
                            session = null;
                        }
                        else
                        {
                            return;
                        }
                    }

                    s.Release();
                }
Example #13
0
        public async Task <ArenaSessionModel> AddArenaSession(ArenaSessionModel arenaModel)
        {
            using (var context = dbContext())
            {
                var arena = new ArenaSession();
                arena.InjectFrom(arenaModel);
                if (arenaModel.Hero != null)
                {
                    arena.Hero = context.Heroes.Find(arenaModel.Hero.Id);
                }
                if (arenaModel.Image1 != null)
                {
                    var img = context.ArenaDeckImages.Find(arenaModel.Image1.Id);
                    if (img == null)
                    {
                        img = arenaModel.Image1;
                        context.ArenaDeckImages.Add(img);
                    }
                    context.Entry(img).CurrentValues.SetValues(arenaModel.Image1);
                    arena.Image1 = img;
                }
                if (arenaModel.Image2 != null)
                {
                    var img = context.ArenaDeckImages.Find(arenaModel.Image2.Id);
                    if (img == null)
                    {
                        img = arenaModel.Image2;
                        context.ArenaDeckImages.Add(img);
                    }
                    context.Entry(img).CurrentValues.SetValues(arenaModel.Image2);
                    arena.Image2 = img;
                }
                context.ArenaSessions.Add(arena);
                await context.SaveChangesAsync();

                arenaModel.InjectFrom(arena);
            }
            events.PublishOnBackgroundThread(new ArenaSessionAdded(arenaModel));
            return(arenaModel);
        }
Example #14
0
        public async Task DeleteGame(Guid id)
        {
            using (var context = dbContext())
            {
                var g = context.Games.Query().FirstOrDefault(x => x.Id == id);
                if (g == null)
                {
                    events.PublishOnBackgroundThread(new GameResultDeleted(id));
                    return;
                    // throw new ArgumentException(string.Format("Game with id '{0}' not found", id), "id");
                }

                // work around old bug
                var deleted = context.DeletedGames.Find(id);
                if (deleted != null)
                {
                    context.DeletedGames.Remove(deleted);
                    context.SaveChanges();
                }

                // move to deleted table
                deleted = new DeletedGameResult();
                deleted.InjectFrom(g);
                deleted.DeletedDate = DateTime.Now;
                context.DeletedGames.Add(deleted);

                var arenaId = g.ArenaSessionId;
                var victory = g.Victory;
                context.Games.Remove(g);
                await context.SaveChangesAsync();

                ArenaSession arena = null;
                if (arenaId != null)
                {
                    arena = context.ArenaSessions.Query().FirstOrDefault(x => x.Id == arenaId);
                    if (arena != null)
                    {
                        //if (victory && arena.IncompleteWins)
                        //{
                        //    arena.Wins--;
                        //}
                        //else if (!victory && arena.IncompleteLosses)
                        //{
                        //    arena.Losses--;
                        //}
                        if (victory)
                        {
                            arena.Wins--;
                        }
                        else
                        {
                            arena.Losses--;
                        }

                        arena.EndDate  = null;
                        arena.Modified = DateTime.Now;
                    }
                }

                await context.SaveChangesAsync();

                events.PublishOnBackgroundThread(new GameResultDeleted(id, arenaId));
                if (arena != null)
                {
                    events.PublishOnBackgroundThread(new ArenaSessionUpdated(arena.Id));
                }
            }
        }
Example #15
0
 public Session(ArenaSession session)
 {
     this.session = session;
 }
Example #16
0
        public async Task UpdateGame(GameResultModel gameModel)
        {
            using (var context = dbContext())
            {
                var game = context.Games.FirstOrDefault(x => x.Id == gameModel.Id);
                if (game == null)
                {
                    throw new ArgumentException("game does not exist", "gameModel");
                }
                var oldVictory = game.Victory;
                if (gameModel.ArenaSession != null)
                {
                    gameModel.Deck = null;
                }

                context.Entry(game).CurrentValues.SetValues(gameModel);
                if (!Equals(gameModel.Hero, game.Hero) &&
                    gameModel.Hero != null)
                {
                    game.Hero = context.Heroes.Find(gameModel.Hero.Id);
                }
                if (!Equals(gameModel.OpponentHero, game.OpponentHero) &&
                    gameModel.OpponentHero != null)
                {
                    game.OpponentHero = context.Heroes.Find(gameModel.OpponentHero.Id);
                }
                if (!Equals(gameModel.Deck, game.Deck) &&
                    gameModel.Deck != null)
                {
                    game.Deck = context.Decks.Find(gameModel.Deck.Id);
                }

                game.Modified = DateTime.Now;
                await context.SaveChangesAsync();

                ArenaSession arena = null;
                if (gameModel.ArenaSession != null)
                {
                    arena = context.ArenaSessions.Query().First(x => x.Id == game.ArenaSessionId);

                    if (game.Victory &&
                        !oldVictory)
                    {
                        arena.Wins++;
                        arena.Losses--;
                    }
                    else if (!game.Victory && oldVictory)
                    {
                        arena.Wins--;
                        arena.Losses++;
                    }

                    SetEndDateIfNeeded(arena);

                    gameModel.ArenaSession.InjectFrom(arena);
                    arena.Modified = DateTime.Now;
                    await context.SaveChangesAsync();
                }

                gameModel.InjectFrom(game);
                events.PublishOnBackgroundThread(new GameResultUpdated(gameModel.Id, game.ArenaSessionId));
                if (gameModel.ArenaSession != null)
                {
                    events.PublishOnBackgroundThread(new ArenaSessionUpdated(gameModel.ArenaSession.Id));
                }
            }
        }
        protected void AddGameToArena(GameResult game, ArenaSession arena)
        {
            game.ArenaSessionId = arena.Id;
            game.ArenaSession = arena;
            arena.Games.Add(game);

            if (game.Victory)
            {
                arena.Wins++;
            }
            else
            {
                arena.Losses++;
            }
        }
        private void SetEndDateIfNeeded(ArenaSession arena)
        {
            if (arena.IsEnded && arena.EndDate == null)
            {
                arena.EndDate = DateTime.Now;
            }

            if (!arena.IsEnded && arena.EndDate != null)
            {
                arena.EndDate = null;
            }
        }
 public async Task<ArenaSessionModel> AddArenaSession(ArenaSessionModel arenaModel)
 {
     using (var context = this.dbContext())
     {
         var arena = new ArenaSession();
         arena.InjectFrom(arenaModel);
         if (arenaModel.Hero != null)
         {
             arena.Hero = context.Heroes.Find(arenaModel.Hero.Id);
         }
         if (arenaModel.Image1 != null)
         {
             var img = context.ArenaDeckImages.Find(arenaModel.Image1.Id);
             if (img == null)
             {
                 img = arenaModel.Image1;
                 context.ArenaDeckImages.Add(img);
             }
             context.Entry(img).CurrentValues.SetValues(arenaModel.Image1);
             arena.Image1 = img;
         }
         if (arenaModel.Image2 != null)
         {
             var img = context.ArenaDeckImages.Find(arenaModel.Image2.Id);
             if (img == null)
             {
                 img = arenaModel.Image2;
                 context.ArenaDeckImages.Add(img);
             }
             context.Entry(img).CurrentValues.SetValues(arenaModel.Image2);
             arena.Image2 = img;
         }
         context.ArenaSessions.Add(arena);
         await context.SaveChangesAsync();
         arenaModel.InjectFrom(arena);
     }
     this.events.PublishOnBackgroundThread(new ArenaSessionAdded(arenaModel));
     return arenaModel;
 }
Example #20
0
            private static async void ReleaseAsync()
            {
                var delay = true;
                var last  = DateTime.UtcNow;

                EventHandler onQueueComplete = delegate
                {
                    last = DateTime.UtcNow;
                };

                AllQueuedLaunchesComplete += onQueueComplete;

                while (true)
                {
                    if (delay)
                    {
                        await Task.Delay(20000);
                    }

                    ArenaSession s = null;

                    lock (sessions)
                    {
                        int count = releasing != null ? releasing.Count : 0;

                        if (count == 0)
                        {
                            releasing = null;
                            AllQueuedLaunchesComplete -= onQueueComplete;
                            return;
                        }

                        var now   = DateTime.UtcNow;
                        var empty = GetPendingLaunchCount() == 0 && now.Subtract(last).TotalSeconds > 10;

                        while (count-- > 0)
                        {
                            var _s = releasing.Dequeue();

                            if (_s._locks == 0)
                            {
                                if (!_s.HasSession)
                                {
                                    if (_s.IsDisposed)
                                    {
                                        continue;
                                    }

                                    //session was never used and can simply be dropped
                                    var l = _s.TryGetLock();
                                    if (l != null)
                                    {
                                        try
                                        {
                                            sessions.Remove(_s.Email);
                                            _s.Dispose();
                                        }
                                        finally
                                        {
                                            l.Dispose();
                                        }

                                        continue;
                                    }
                                }
                                else if (empty)
                                {
                                    //sessions will be dropped after 30s when no accounts are queued
                                    if (now.Subtract(_s._released).TotalSeconds > 30)
                                    {
                                        s = _s;
                                        break;
                                    }
                                }
                                else if (now.Subtract(_s._released).TotalMinutes > 5)
                                {
                                    //assuming it isn't needed
                                    s = _s;
                                    break;
                                }
                            }
                            else
                            {
                                continue;
                            }

                            releasing.Enqueue(_s);
                        }
                    }

                    if (s != null)
                    {
                        delay = false;
                        var removed = false;

                        try
                        {
                            removed = await OnRelease(s);
                        }
                        catch (Exception e)
                        {
                            Util.Logging.Log(e);
                        }

                        if (!removed)
                        {
                            lock (sessions)
                            {
                                if (s._locks == 0)
                                {
                                    releasing.Enqueue(s);
                                }
                            }
                        }
                    }
                    else
                    {
                        delay = true;
                    }
                }
            }
Example #21
0
            /// <summary>
            /// Ends the session
            /// </summary>
            /// <param name="force">Forces logout on sessions in use</param>
            /// <param name="login">Login if required, otherwise it'll be skipped</param>
            /// <param name="quick">Only logout</param>
            private static async Task <bool> EndSession(ArenaSession s, bool force = false, bool login = true, bool quick = false)
            {
                if (!s.HasSession)
                {
                    return(true);
                }

                var retry = true;

                do
                {
                    var v            = Settings.NetworkAuthorization.Value;
                    var removeAll    = v.HasFlag(Settings.NetworkAuthorizationFlags.RemoveAll);
                    var removeOthers = removeAll || v.HasFlag(Settings.NetworkAuthorizationFlags.RemovePreviouslyAuthorized);

                    var b = false;

                    try
                    {
                        if (removeOthers && !quick)
                        {
                            //warning: verifying could potentially take a minute
                            if (login && !await VerifySession(s, s.Password, false))
                            {
                                throw new Exception("Login failed");
                            }

                            if (!force)
                            {
                                lock (sessions)
                                {
                                    if (s._locks > 0)
                                    {
                                        return(false);
                                    }
                                }
                            }

                            b = !s.Session.RequiresAuthentication;
                        }
                    }
                    catch (Exception e)
                    {
                        Util.Logging.Log(e);

                        b = false;
                    }

                    try
                    {
                        if (b)
                        {
                            if (removeOthers)
                            {
                                var networks = await s.Session.GetAuthorizedNetworks();

                                var count = networks.Length;

                                if (!removeAll)
                                {
                                    --count;
                                }

                                for (var i = 0; i < count; i++)
                                {
                                    await s.Session.Remove(networks[i]);
                                }
                            }
                        }

                        retry = false;

                        if (s.HasSession)
                        {
                            await s.Session.Logout();
                        }
                    }
                    catch (Exception e)
                    {
                        Util.Logging.Log(e);

                        if (e is Tools.ArenaAccount.SessionExpiredException && retry && login)
                        {
                            retry = false;
                            continue;
                        }
                    }

                    break;
                }while (true);

                return(true);
            }
Example #22
0
            /// <summary>
            /// Logs into the account to check if authentication is required
            /// </summary>
            private static VerifyResult DoVerify(ArenaSession s, Settings.IAccount account)
            {
                using (var t = VerifySession(s, account.Password, true))
                {
                    t.Wait();
                    if (!t.Result)
                    {
                        throw new Exception("Login failed");
                    }
                }

                if (!s.Session.RequiresAuthentication)
                {
                    if (account.NetworkAuthorizationState != Settings.NetworkAuthorizationState.Disabled)
                    {
                        account.NetworkAuthorizationState = Settings.NetworkAuthorization.Value.HasFlag(Settings.NetworkAuthorizationFlags.RemoveAll) ? Settings.NetworkAuthorizationState.Unknown : Settings.NetworkAuthorizationState.OK;
                    }

                    return(VerifyResult.OK);
                }

                if (account.NetworkAuthorizationState == Settings.NetworkAuthorizationState.OK)
                {
                    //account was previously authorized, assuming IP was changed - flag all accounts
                    foreach (var _a in Util.Accounts.GetAccounts())
                    {
                        if (_a.NetworkAuthorizationState == Settings.NetworkAuthorizationState.OK)
                        {
                            _a.NetworkAuthorizationState = Settings.NetworkAuthorizationState.Unknown;
                        }
                    }
                }

                switch (s.Session.Authentication)
                {
                case Tools.ArenaAccount.AuthenticationType.Email:
                case Tools.ArenaAccount.AuthenticationType.SMS:
                    break;

                case Tools.ArenaAccount.AuthenticationType.TOTP:

                    if (account.TotpKey != null)
                    {
                        var  now   = DateTime.UtcNow.Ticks;
                        byte retry = 0;

                        do
                        {
                            try
                            {
                                if (retry > 0)
                                {
                                    OnLoginRequest();

                                    //authorizing can only be attempted once per session
                                    using (var t = s.Session.Login(s.Email, account.Password.ToSecureString()))
                                    {
                                        t.Wait();
                                        if (t.Result)
                                        {
                                            s.Password = account.Password;
                                            if (!s.Session.RequiresAuthentication || s.Session.Authentication != Tools.ArenaAccount.AuthenticationType.TOTP)
                                            {
                                                break;
                                            }
                                        }
                                        else
                                        {
                                            break;
                                        }
                                    }

                                    if (retry > 1)
                                    {
                                        break;
                                    }

                                    //retrying using the server's time
                                    now = s.Session.Date.Ticks;
                                    if (now <= 0)
                                    {
                                        now = DateTime.UtcNow.Ticks;
                                    }
                                }

                                var key = Tools.Totp.Generate(account.TotpKey, now);
                                using (var t = s.Session.Authenticate(new string(key)))
                                {
                                    t.Wait();
                                    if (t.Result)
                                    {
                                        break;
                                    }
                                }
                            }
                            catch (Exception e)
                            {
                                Util.Logging.Log(e);

                                if (e.InnerException != null)
                                {
                                    if (retry == 0 && (e.InnerException is Tools.ArenaAccount.AuthenticationException || e.InnerException is Tools.ArenaAccount.SessionExpiredException))
                                    {
                                        retry++;

                                        continue;
                                    }
                                }

                                retry += 2;
                            }

                            break;
                        }while (true);
                    }

                    break;

                default:
                    return(VerifyResult.None);
                }

                if (s.Session.RequiresAuthentication)
                {
                    return(VerifyResult.Required);
                }
                else
                {
                    if (account.NetworkAuthorizationState != Settings.NetworkAuthorizationState.Disabled)
                    {
                        account.NetworkAuthorizationState = Settings.NetworkAuthorization.Value.HasFlag(Settings.NetworkAuthorizationFlags.RemoveAll) ? Settings.NetworkAuthorizationState.Unknown : Settings.NetworkAuthorizationState.OK;
                    }

                    return(VerifyResult.Completed);
                }
            }
Example #23
0
 public Lock(ArenaSession s)
 {
     this.s = s;
 }