From b1b91a8f77ffaea47bcf53d05194ca02aee9f198 Mon Sep 17 00:00:00 2001 From: Greg Edwards Date: Sat, 21 Mar 2015 19:03:16 -0400 Subject: [PATCH 1/4] Track the player's last search time. --- gts/pokemondpds.ashx.cs | 2 ++ gts/syachi2ds.ashx.cs | 2 ++ library/Data/DataMysql.cs | 22 ++++++++++++++++++++++ library/Data/Database.cs | 2 ++ 4 files changed, 28 insertions(+) diff --git a/gts/pokemondpds.ashx.cs b/gts/pokemondpds.ashx.cs index 05c9a543..625d324e 100644 --- a/gts/pokemondpds.ashx.cs +++ b/gts/pokemondpds.ashx.cs @@ -334,6 +334,8 @@ namespace PkmnFoundations.GTS response.Write(record.Save(), 0, 292); } + Database.Instance.GtsSetLastSearch4(pid); + } break; // the exchange request uploads a record of the exchangee pokemon diff --git a/gts/syachi2ds.ashx.cs b/gts/syachi2ds.ashx.cs index 4e8ca31e..ac1d3448 100644 --- a/gts/syachi2ds.ashx.cs +++ b/gts/syachi2ds.ashx.cs @@ -335,6 +335,8 @@ namespace PkmnFoundations.GTS response.Write(record.Save(), 0, 296); } + Database.Instance.GtsSetLastSearch5(pid); + } break; // the exchange request uploads a record of the exchangee pokemon diff --git a/library/Data/DataMysql.cs b/library/Data/DataMysql.cs index 71f502cb..7cf91d98 100644 --- a/library/Data/DataMysql.cs +++ b/library/Data/DataMysql.cs @@ -500,6 +500,17 @@ namespace PkmnFoundations.Data WithTransaction(tran => GtsLogTrade4(tran, record, timeWithdrawn, partner_pid)); } + public void GtsSetLastSearch4(MySqlTransaction tran, int pid) + { + tran.ExecuteNonQuery("UPDATE GtsProfiles4 SET TimeLastSearch = " + + "GETUTCDATE() WHERE pid = @pid", new MySqlParameter("@pid", pid)); + } + + public override void GtsSetLastSearch4(int pid) + { + WithTransaction(tran => GtsSetLastSearch4(tran, pid)); + } + #endregion #region Battle Tower 4 @@ -1423,6 +1434,17 @@ namespace PkmnFoundations.Data _params2); } + public void GtsSetLastSearch5(MySqlTransaction tran, int pid) + { + tran.ExecuteNonQuery("UPDATE GtsProfiles5 SET TimeLastSearch = " + + "GETUTCDATE() WHERE pid = @pid", new MySqlParameter("@pid", pid)); + } + + public override void GtsSetLastSearch5(int pid) + { + WithTransaction(tran => GtsSetLastSearch5(tran, pid)); + } + #endregion #region Battle Subway 5 diff --git a/library/Data/Database.cs b/library/Data/Database.cs index 337941a7..4698f4a1 100644 --- a/library/Data/Database.cs +++ b/library/Data/Database.cs @@ -77,6 +77,7 @@ namespace PkmnFoundations.Data public abstract int GtsAvailablePokemon4(); public abstract void GtsLogTrade4(GtsRecord4 record, DateTime ? timeWithdrawn, int ? partner_pid); + public abstract void GtsSetLastSearch4(int pid); #endregion #region Battle Tower 4 @@ -113,6 +114,7 @@ namespace PkmnFoundations.Data public abstract int GtsAvailablePokemon5(); public abstract void GtsLogTrade5(GtsRecord5 record, DateTime ? timeWithdrawn, int ? partner_pid); + public abstract void GtsSetLastSearch5(int pid); #endregion #region Other Gamestats 5 From 6d9a809b5dc855d249a4aefa5839143874299723 Mon Sep 17 00:00:00 2001 From: Greg Edwards Date: Sat, 21 Mar 2015 19:20:31 -0400 Subject: [PATCH 2/4] Use web server time, not database time. (solves a race condition.) --- library/Data/DataMysql.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/library/Data/DataMysql.cs b/library/Data/DataMysql.cs index 7cf91d98..14e37019 100644 --- a/library/Data/DataMysql.cs +++ b/library/Data/DataMysql.cs @@ -503,7 +503,8 @@ namespace PkmnFoundations.Data public void GtsSetLastSearch4(MySqlTransaction tran, int pid) { tran.ExecuteNonQuery("UPDATE GtsProfiles4 SET TimeLastSearch = " + - "GETUTCDATE() WHERE pid = @pid", new MySqlParameter("@pid", pid)); + "@now WHERE pid = @pid", new MySqlParameter("@now", DateTime.UtcNow), + new MySqlParameter("@pid", pid)); } public override void GtsSetLastSearch4(int pid) @@ -1437,7 +1438,8 @@ namespace PkmnFoundations.Data public void GtsSetLastSearch5(MySqlTransaction tran, int pid) { tran.ExecuteNonQuery("UPDATE GtsProfiles5 SET TimeLastSearch = " + - "GETUTCDATE() WHERE pid = @pid", new MySqlParameter("@pid", pid)); + "@now WHERE pid = @pid", new MySqlParameter("@now", DateTime.UtcNow), + new MySqlParameter("@pid", pid)); } public override void GtsSetLastSearch5(int pid) From ee92cde7bb546fe21daf31bf1ae88150dc7eb06b Mon Sep 17 00:00:00 2001 From: Greg Edwards Date: Sat, 21 Mar 2015 19:36:44 -0400 Subject: [PATCH 3/4] Added function to retrieve a player's last search time. --- library/Data/DataMysql.cs | 26 ++++++++++++++++++++++++++ library/Data/Database.cs | 2 ++ 2 files changed, 28 insertions(+) diff --git a/library/Data/DataMysql.cs b/library/Data/DataMysql.cs index 14e37019..daf8e7ef 100644 --- a/library/Data/DataMysql.cs +++ b/library/Data/DataMysql.cs @@ -512,6 +512,19 @@ namespace PkmnFoundations.Data WithTransaction(tran => GtsSetLastSearch4(tran, pid)); } + public DateTime ? GtsGetLastSearch4(MySqlTransaction tran, int pid) + { + object result = tran.ExecuteScalar("SELECT TimeLastSearch " + + "FROM GtsProfiles4 WHERE pid = @pid", new MySqlParameter("@pid", pid)); + if (result == null || result is DBNull) return null; + return (DateTime)result; + } + + public override DateTime ? GtsGetLastSearch4(int pid) + { + return WithTransaction(tran => GtsGetLastSearch4(tran, pid)); + } + #endregion #region Battle Tower 4 @@ -1447,6 +1460,19 @@ namespace PkmnFoundations.Data WithTransaction(tran => GtsSetLastSearch5(tran, pid)); } + public DateTime? GtsGetLastSearch5(MySqlTransaction tran, int pid) + { + object result = tran.ExecuteScalar("SELECT TimeLastSearch " + + "FROM GtsProfiles5 WHERE pid = @pid", new MySqlParameter("@pid", pid)); + if (result == null || result is DBNull) return null; + return (DateTime)result; + } + + public override DateTime? GtsGetLastSearch5(int pid) + { + return WithTransaction(tran => GtsGetLastSearch5(tran, pid)); + } + #endregion #region Battle Subway 5 diff --git a/library/Data/Database.cs b/library/Data/Database.cs index 4698f4a1..cebaa841 100644 --- a/library/Data/Database.cs +++ b/library/Data/Database.cs @@ -78,6 +78,7 @@ namespace PkmnFoundations.Data public abstract void GtsLogTrade4(GtsRecord4 record, DateTime ? timeWithdrawn, int ? partner_pid); public abstract void GtsSetLastSearch4(int pid); + public abstract DateTime ? GtsGetLastSearch4(int pid); #endregion #region Battle Tower 4 @@ -115,6 +116,7 @@ namespace PkmnFoundations.Data public abstract void GtsLogTrade5(GtsRecord5 record, DateTime ? timeWithdrawn, int ? partner_pid); public abstract void GtsSetLastSearch5(int pid); + public abstract DateTime ? GtsGetLastSearch5(int pid); #endregion #region Other Gamestats 5 From 02113a157912b166867e34c08427681a6af9db9a Mon Sep 17 00:00:00 2001 From: Greg Edwards Date: Sat, 21 Mar 2015 19:39:56 -0400 Subject: [PATCH 4/4] Fixed possible cloning issue when trying to trade with an old search result, and that player has since uploaded a new pokemon. --- gts/pokemondpds.ashx.cs | 5 ++++- gts/syachi2ds.ashx.cs | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/gts/pokemondpds.ashx.cs b/gts/pokemondpds.ashx.cs index 625d324e..638553d5 100644 --- a/gts/pokemondpds.ashx.cs +++ b/gts/pokemondpds.ashx.cs @@ -355,8 +355,11 @@ namespace PkmnFoundations.GTS upload.IsExchanged = 0; int targetPid = BitConverter.ToInt32(data, 292); GtsRecord4 result = Database.Instance.GtsDataForUser4(targetPid); + DateTime ? searchTime = Database.Instance.GtsGetLastSearch4(pid); - if (result == null || result.IsExchanged != 0) + if (result == null || searchTime == null || + result.TimeDeposited > (DateTime)searchTime || // If this condition is met, it means the pokemon in the system is DIFFERENT from the one the user is trying to trade for, ie. it was deposited AFTER the user did their search. The one the user wants was either taken back or traded. + result.IsExchanged != 0) { // Pokémon is traded (or was never here to begin with) // todo: I only checked this on GenV. Check that this diff --git a/gts/syachi2ds.ashx.cs b/gts/syachi2ds.ashx.cs index ac1d3448..7870eee0 100644 --- a/gts/syachi2ds.ashx.cs +++ b/gts/syachi2ds.ashx.cs @@ -356,8 +356,11 @@ namespace PkmnFoundations.GTS upload.IsExchanged = 0; int targetPid = BitConverter.ToInt32(request, 296); GtsRecord5 result = Database.Instance.GtsDataForUser5(targetPid); + DateTime ? searchTime = Database.Instance.GtsGetLastSearch5(pid); - if (result == null || result.IsExchanged != 0) + if (result == null || searchTime == null || + result.TimeDeposited > (DateTime)searchTime || // If this condition is met, it means the pokemon in the system is DIFFERENT from the one the user is trying to trade for, ie. it was deposited AFTER the user did their search. The one the user wants was either taken back or traded. + result.IsExchanged != 0) { // Pokémon is traded (or was never here to begin with) SessionManager.Remove(session);