Created
December 11, 2012 19:06
-
-
Save webcoyote/4261121 to your computer and use it in GitHub Desktop.
Transaction rate-limiting
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
unsigned PlatformTimeMs () { | |
#if defined(_WINDOWS_) | |
return GetTickCount(); | |
#else | |
#error Your implementation here | |
// something like clock_gettime(CLOCK_MONOTONIC, ...) for Unix/Linux | |
#endif | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CRateLimiter::CRateLimiter () | |
: m_timeMs(PlatformTimeMs()) | |
{} | |
bool CRateLimiter::AddTime (unsigned costMs, unsigned maxCostMs) { | |
ASSERT(costMs < maxCostMs); | |
// Reset rate-limiter time value if it has expired | |
// - handles integer overflow safely | |
unsigned currTimeMs = PlatformTimeMs(); | |
if ((int) (currTimeMs - m_timeMs) > 0) | |
m_timeMs = currTimeMs; | |
// Has the user accrued too much time-cost? | |
// - handles integer overflow safely | |
unsigned newTimeMs = m_timeMs + costMs; | |
if ((int) (newTimeMs - currTimeMs) >= (int) maxCostMs) | |
return false; | |
m_timeMs = newTimeMs; | |
return true; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class CRateLimiter { | |
public: | |
CRateLimiter (); | |
bool AddTime (unsigned costMs, unsigned maxCostMs); | |
private: | |
unsigned m_timeMs; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Using these values a player can attempt to login once | |
// every 30 seconds, but with as many as ten login attempts | |
// in a burst. While this sounds like a lot many players | |
// forget their passwords and need a number of attempts to | |
// remember it, which I discovered by analyzing log files. | |
// They should try LastPass, which is an awesome solution | |
// to this problem. | |
const unsigned LOGIN_COST_MS = 30 * 1000; | |
const unsigned MAX_LOGIN_COST_MS = 10 * LOGIN_COST_MS; | |
ErrorCode CPlayer::PlayerLogin () { | |
if (!m_rateLimiter.AddTime(LOGIN_COST_MS, MAX_LOGIN_COST_MS)) | |
return ERROR_LOGIN_RATE_LIMIT; | |
... login code here | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment