From 70a83893b093baa9fb8959f2f14cc0c97540b4cd Mon Sep 17 00:00:00 2001 From: Savinda Senevirathne Date: Fri, 5 Mar 2021 16:58:41 +0530 Subject: [PATCH] Fixing connection not closing when threshold exceeded from a single attempt. (#261) * Fixing connection not closing when threshold exceeded from a sigle message. * Updated hpws binary. --- src/bill/corebill.cpp | 36 +++++++++++++++++------------------- src/comm/comm_session.cpp | 30 ++++++++++++++---------------- src/comm/hpws.hpp | 2 +- test/bin/hpws | Bin 70080 -> 43656 bytes 4 files changed, 32 insertions(+), 36 deletions(-) diff --git a/src/bill/corebill.cpp b/src/bill/corebill.cpp index 1d508752..53a77f36 100644 --- a/src/bill/corebill.cpp +++ b/src/bill/corebill.cpp @@ -47,26 +47,24 @@ namespace corebill // Reset counter timestamp. stat.timestamp = time_now; } - else - { - // Check whether we have exceeded the threshold within the monitering interval. - const uint64_t elapsed_time = time_now - stat.timestamp; - if (elapsed_time <= VIOLATION_REFRESH_INTERVAL && stat.counter > VIOLATION_THRESHOLD) - { - // IP exceeded violation threshold. - stat.timestamp = 0; - stat.counter = 0; - std::scoped_lock gray_list_lock(graylist_mutex); - graylist.emplace(host, VIOLATION_REFRESH_INTERVAL); - LOG_WARNING << host << " placed on graylist."; - } - else if (elapsed_time > VIOLATION_REFRESH_INTERVAL) - { - // Start the counter fresh. - stat.timestamp = time_now; - stat.counter = 1; - } + // Check whether we have exceeded the threshold within the monitering interval. + const uint64_t elapsed_time = time_now - stat.timestamp; + if (elapsed_time <= VIOLATION_REFRESH_INTERVAL && stat.counter > VIOLATION_THRESHOLD) + { + // IP exceeded violation threshold. + + stat.timestamp = 0; + stat.counter = 0; + std::scoped_lock gray_list_lock(graylist_mutex); + graylist.emplace(host, VIOLATION_REFRESH_INTERVAL); + LOG_WARNING << host << " placed on graylist."; + } + else if (elapsed_time > VIOLATION_REFRESH_INTERVAL) + { + // Start the counter fresh. + stat.timestamp = time_now; + stat.counter = 1; } } diff --git a/src/comm/comm_session.cpp b/src/comm/comm_session.cpp index 25431242..d3b21890 100644 --- a/src/comm/comm_session.cpp +++ b/src/comm/comm_session.cpp @@ -275,25 +275,23 @@ namespace comm // Reset counter timestamp. t.timestamp = time_now; } - else + + // Check whether we have exceeded the threshold within the monitering interval. + const uint64_t elapsed_time = time_now - t.timestamp; + if (elapsed_time <= t.intervalms && t.counter_value > t.threshold_limit) { - // Check whether we have exceeded the threshold within the monitering interval. - const uint64_t elapsed_time = time_now - t.timestamp; - if (elapsed_time <= t.intervalms && t.counter_value > t.threshold_limit) - { - mark_for_closure(); + mark_for_closure(); - t.timestamp = 0; - t.counter_value = 0; + t.timestamp = 0; + t.counter_value = 0; - LOG_INFO << "Session " << display_name() << " threshold exceeded. (type:" << threshold_type << " limit:" << t.threshold_limit << ")"; - corebill::report_violation(host_address); - } - else if (elapsed_time > t.intervalms) - { - t.timestamp = time_now; - t.counter_value = amount; - } + LOG_INFO << "Session " << display_name() << " threshold exceeded. (type:" << threshold_type << " limit:" << t.threshold_limit << ")"; + corebill::report_violation(host_address); + } + else if (elapsed_time > t.intervalms) + { + t.timestamp = time_now; + t.counter_value = amount; } } diff --git a/src/comm/hpws.hpp b/src/comm/hpws.hpp index f5ec6deb..b6b63e4b 100644 --- a/src/comm/hpws.hpp +++ b/src/comm/hpws.hpp @@ -47,7 +47,7 @@ namespace hpws // used when waiting for messages that should already be on the pipe #define HPWS_SMALL_TIMEOUT 10 // used when waiting for server process to spawn -#define HPWS_LONG_TIMEOUT 50 +#define HPWS_LONG_TIMEOUT 1500 // This timeout has to account the possible delays in communication via internet. typedef union { diff --git a/test/bin/hpws b/test/bin/hpws index 6f508cec2d558a7afa82e8d4b6fd3028b272bef5..f1d550b5dd77d6483ce25d52732634a99aec9b3a 100755 GIT binary patch delta 299 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