Skip to content

Commit

Permalink
Create a ResetsRateLimitFilter
Browse files Browse the repository at this point in the history
Summary: We want to limit resets separately from other control messages.

Reviewed By: afrind

Differential Revision: D50750901

fbshipit-source-id: 576257de0cb9648a0403d1605d30f6d3c10de335
  • Loading branch information
Aman Sharma authored and facebook-github-bot committed Nov 5, 2023
1 parent b231b0d commit 3698603
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 1 deletion.
3 changes: 2 additions & 1 deletion proxygen/lib/http/codec/RateLimitFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <proxygen/lib/http/codec/DirectErrorsRateLimitFilter.h>
#include <proxygen/lib/http/codec/HeadersRateLimitFilter.h>
#include <proxygen/lib/http/codec/RateLimitFilter.h>
#include <proxygen/lib/http/codec/ResetsRateLimitFilter.h>

namespace proxygen {

Expand Down Expand Up @@ -37,7 +38,7 @@ std::unique_ptr<RateLimitFilter> RateLimitFilter::createRateLimitFilter(
return std::make_unique<ControlMessageRateLimitFilter>(timer,
httpSessionStats);
case Type::RSTS:
return nullptr;
return std::make_unique<ResetsRateLimitFilter>(timer, httpSessionStats);
case Type::DIRECT_ERROR_HANDLING:
return std::make_unique<DirectErrorsRateLimitFilter>(timer,
httpSessionStats);
Expand Down
64 changes: 64 additions & 0 deletions proxygen/lib/http/codec/ResetsRateLimitFilter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/

#pragma once

#include <proxygen/lib/http/codec/HTTP2Framer.h>
#include <proxygen/lib/http/codec/RateLimitFilter.h>

namespace proxygen {

class ResetsRateLimitFilter : public RateLimitFilter {
public:
static const uint32_t kDefaultMaxEventsPerInterval = 200;
static const uint32_t kMaxEventsPerIntervalLowerBound = 100;
static constexpr std::chrono::milliseconds kDefaultTimeoutDuration{1000};

explicit ResetsRateLimitFilter(folly::HHWheelTimer* timer,
HTTPSessionStats* httpSessionStats)
: RateLimitFilter(timer, httpSessionStats) {
maxEventsInInterval_ = kDefaultMaxEventsPerInterval;
timeoutDuration_ = kDefaultTimeoutDuration;
}

void onAbort(HTTPCodec::StreamID streamID, ErrorCode code) override {
if (!incrementNumEventsInCurrentInterval()) {
callback_->onAbort(streamID, code);
} else {
sendErrorCallback(http2::FrameType::RST_STREAM);
}
}

void recordNumEventsInCurrentInterval(uint32_t numEvents) override {
// TODO: Add stats for number of resets in the current interval
}

void recordRateLimitBreached() override {
// TODO: Add stats for number of resets in the current interval
}

uint32_t getMaxEventsPerInvervalLowerBound() const override {
return kMaxEventsPerIntervalLowerBound;
}

private:
void sendErrorCallback(http2::FrameType frameType) {
HTTPException ex(
HTTPException::Direction::INGRESS_AND_EGRESS,
folly::to<std::string>(
"dropping connection due to too many control messages, num "
"control messages = ",
numEventsInCurrentInterval_,
", most recent frame type = ",
getFrameTypeString(http2::FrameType::RST_STREAM)));
ex.setProxygenError(kErrorDropped);
callback_->onError(0, ex, true);
}
};

} // namespace proxygen

0 comments on commit 3698603

Please sign in to comment.