Skip to content

Commit

Permalink
translation/Protocol: add packet RATE_LIMIT_SITE_REQUESTS
Browse files Browse the repository at this point in the history
  • Loading branch information
MaxKellermann committed Jul 12, 2024
1 parent e0fefc1 commit 67def8a
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 0 deletions.
28 changes: 28 additions & 0 deletions src/translation/Parser.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1131,6 +1131,22 @@ TranslateParser::HandleAllowRemoteNetwork(std::span<const std::byte> payload)
response.allow_remote_networks.Add(alloc, address, prefix_length);
}

inline void
TranslateParser::HandleTokenBucketParams(TranslateTokenBucketParams &params,
const char *packet_name,
std::span<const std::byte> payload)
{
if (params.IsDefined())
throw FmtRuntimeError("duplicate {} packet", packet_name);

if (payload.size() != sizeof(params))
throw FmtRuntimeError("malformed {} packet", packet_name);

memcpy(&params, payload.data(), sizeof(params));
if (!params.IsValid())
throw FmtRuntimeError("malformed {} packet", packet_name);
}

#endif // TRANSLATION_ENABLE_HTTP

static bool
Expand Down Expand Up @@ -4318,6 +4334,18 @@ TranslateParser::HandleRegularPacket(TranslationCommand command,
#else
break;
#endif

case TranslationCommand::RATE_LIMIT_SITE_REQUESTS:
#if TRANSLATION_ENABLE_HTTP
if (response.site == nullptr)
throw std::runtime_error{"misplaced RATE_LIMIT_SITE_REQUESTS packet"};

HandleTokenBucketParams(response.rate_limit_site_requests,
"RATE_LIMIT_SITE_REQUESTS", payload);
return;
#else
break;
#endif
}

throw FmtRuntimeError("unknown translation packet: {}", (unsigned)command);
Expand Down
4 changes: 4 additions & 0 deletions src/translation/Parser.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <string_view>

struct TranslateResponse;
struct TranslateTokenBucketParams;
struct FileAddress;
struct CgiAddress;
struct HttpAddress;
Expand Down Expand Up @@ -265,6 +266,9 @@ private:

#if TRANSLATION_ENABLE_HTTP
void HandleAllowRemoteNetwork(std::span<const std::byte> payload);
void HandleTokenBucketParams(TranslateTokenBucketParams &params,
const char *packet_name,
std::span<const std::byte> payload);
#endif

Result HandlePacket(TranslationCommand command,
Expand Down
6 changes: 6 additions & 0 deletions src/translation/Protocol.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -1287,6 +1287,12 @@ enum class TranslationCommand : uint16_t {
* This packet may be sent more than once.
*/
ALLOW_REMOTE_NETWORK = 263,

/**
* Configure a rate limit for all requests of this site.
* Payload is two 32-bit floats: rate and burst.
*/
RATE_LIMIT_SITE_REQUESTS = 264,
};

struct TranslationHeader {
Expand Down
8 changes: 8 additions & 0 deletions src/translation/Response.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,10 @@ TranslateResponse::Clear() noexcept

validate_mtime.mtime = 0;
validate_mtime.path = nullptr;

#if TRANSLATION_ENABLE_HTTP
rate_limit_site_requests.Clear();
#endif
}

static std::span<const char *const>
Expand Down Expand Up @@ -518,6 +522,10 @@ TranslateResponse::CopyFrom(AllocatorPtr alloc, const TranslateResponse &src) no

validate_mtime.mtime = src.validate_mtime.mtime;
validate_mtime.path = alloc.CheckDup(src.validate_mtime.path);

#if TRANSLATION_ENABLE_HTTP
rate_limit_site_requests = src.rate_limit_site_requests;
#endif
}

void
Expand Down
21 changes: 21 additions & 0 deletions src/translation/Response.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,23 @@ class AllocatorPtr;
class UniqueRegex;
class MatchData;

struct TranslateTokenBucketParams {
float rate, burst;

void Clear() noexcept {
rate = -1;
}

bool IsDefined() const noexcept {
return rate > 0;
}

bool IsValid() const noexcept {
// TODO check std::isfinite()?
return rate > 0 && burst > 0;
}
};

struct TranslateResponse {
/**
* The protocol version from the BEGIN packet.
Expand Down Expand Up @@ -322,6 +339,10 @@ struct TranslateResponse {
const char *path;
} validate_mtime;

#if TRANSLATION_ENABLE_HTTP
TranslateTokenBucketParams rate_limit_site_requests;
#endif

/**
* From #TranslationCommand::TIMEOUT. Zero if unset.
*/
Expand Down
6 changes: 6 additions & 0 deletions src/translation/server/Response.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,12 @@ public:
static_cast<std::span<const std::byte>>(address));
}

auto &RateLimitSiteRequests(const float &rate, const float &burst) noexcept {
return MultiPacket(TranslationCommand::RATE_LIMIT_SITE_REQUESTS,
std::span{&rate, 1},
std::span{&burst, 1});
}

struct RedirectContext {
Response &response;

Expand Down

0 comments on commit 67def8a

Please sign in to comment.