1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree.
7  */
8 
9 #pragma once
10 
11 #include <folly/Memory.h>
12 #include <folly/io/async/DestructorCheck.h>
13 #include <proxygen/lib/http/session/HTTPTransaction.h>
14 
15 namespace proxygen {
16 
17 static const std::string kMessageFilterDefaultName_ = "Unknown";
18 
19 class HTTPMessageFilter
20     : public HTTPTransaction::Handler
21     , public folly::DestructorCheck {
22  public:
setNextTransactionHandler(HTTPTransaction::Handler * next)23   void setNextTransactionHandler(HTTPTransaction::Handler* next) {
24     nextTransactionHandler_ = CHECK_NOTNULL(next);
25   }
setPrevFilter(HTTPMessageFilter * prev)26   virtual void setPrevFilter(HTTPMessageFilter* prev) noexcept {
27     prev_ = CHECK_NOTNULL(prev);
28   }
setPrevTxn(HTTPTransaction * prev)29   virtual void setPrevTxn(HTTPTransaction* prev) noexcept {
30     prev_ = CHECK_NOTNULL(prev);
31   }
getNextTransactionHandler()32   HTTPTransaction::Handler* getNextTransactionHandler() {
33     return nextTransactionHandler_;
34   }
35 
36   virtual std::unique_ptr<HTTPMessageFilter> clone() noexcept = 0;
37 
38   // This function is used to validate whether a request could be DSRed.
39   // The function is called pre-delegation. For body mutating filters,
40   // allowDSR should return false. Other examples, beside body mutating,
41   // is a filter which rate limit the response delivery
42   // Note that allowDSR is a pure virtual to make the filter author
43   // aware of it
44   virtual bool allowDSR() const noexcept = 0;
45 
46   // These HTTPTransaction::Handler callbacks may be overwritten
47   // The default behavior is to pass the call through.
onHeadersComplete(std::unique_ptr<HTTPMessage> msg)48   void onHeadersComplete(std::unique_ptr<HTTPMessage> msg) noexcept override {
49     nextTransactionHandler_->onHeadersComplete(std::move(msg));
50   }
onBody(std::unique_ptr<folly::IOBuf> chain)51   void onBody(std::unique_ptr<folly::IOBuf> chain) noexcept override {
52     nextTransactionHandler_->onBody(std::move(chain));
53   }
onChunkHeader(size_t length)54   void onChunkHeader(size_t length) noexcept override {
55     nextTransactionHandler_->onChunkHeader(length);
56   }
onChunkComplete()57   void onChunkComplete() noexcept override {
58     nextTransactionHandler_->onChunkComplete();
59   }
onTrailers(std::unique_ptr<HTTPHeaders> trailers)60   void onTrailers(std::unique_ptr<HTTPHeaders> trailers) noexcept override {
61     nextTransactionHandler_->onTrailers(std::move(trailers));
62   }
onEOM()63   void onEOM() noexcept override {
64     nextTransactionHandler_->onEOM();
65   }
onUpgrade(UpgradeProtocol protocol)66   void onUpgrade(UpgradeProtocol protocol) noexcept override {
67     nextTransactionHandler_->onUpgrade(protocol);
68   }
onError(const HTTPException & error)69   void onError(const HTTPException& error) noexcept override {
70     nextTransactionHandler_->onError(error);
71   }
72 
73   // These HTTPTransaction::Handler callbacks cannot be overrwritten
setTransaction(HTTPTransaction * txn)74   void setTransaction(HTTPTransaction* txn) noexcept final {
75     nextTransactionHandler_->setTransaction(txn);
76   }
detachTransaction()77   void detachTransaction() noexcept final {
78     if (prev_.which() == 1) {
79       // After detachTransaction(), the HTTPTransaction will destruct itself.
80       // Set it to nullptr to avoid holding a stale pointer.
81       prev_ = static_cast<HTTPTransaction*>(nullptr);
82     }
83     if (nextTransactionHandler_) {
84       nextTransactionHandler_->detachTransaction();
85     }
86   }
onEgressPaused()87   void onEgressPaused() noexcept final {
88     nextTransactionHandler_->onEgressPaused();
89   }
onEgressResumed()90   void onEgressResumed() noexcept final {
91     nextTransactionHandler_->onEgressResumed();
92   }
onPushedTransaction(HTTPTransaction * txn)93   void onPushedTransaction(HTTPTransaction* txn) noexcept final {
94     nextTransactionHandler_->onPushedTransaction(txn);
95   }
onExTransaction(HTTPTransaction * txn)96   void onExTransaction(HTTPTransaction* txn) noexcept final {
97     nextTransactionHandler_->onExTransaction(txn);
98   }
99 
getFilterName()100   virtual const std::string& getFilterName() const noexcept {
101     return kMessageFilterDefaultName_;
102   }
103 
104   virtual void pause() noexcept;
105 
106   virtual void resume(uint64_t offset) noexcept;
107 
108   // This is called by the handler when it wants to detach from the transaction.
109   // After this call, the handler and the transaction can be destroyed without
110   // notifying each other. We pass the call through the filter chain to
111   // avoid holding a stale pointer to the transaction.
detachHandlerFromTransaction()112   void detachHandlerFromTransaction() noexcept {
113     if (prev_.which() == 0) {
114       auto prev = boost::get<HTTPMessageFilter*>(prev_);
115       if (prev) {
116         // prev points to another filter, popagate the call.
117         prev->detachHandlerFromTransaction();
118       }
119     } else {
120       auto prev = boost::get<HTTPTransaction*>(prev_);
121       if (prev) {
122         // prev points to the transaction, detach the handler from the
123         // transaction.
124         prev->setHandler(nullptr);
125         // Set the pointer to nullptr. It is not safe to use the pointer since
126         // after this the transaction can be destroyed without notifying the
127         // filter.
128         prev_ = static_cast<HTTPTransaction*>(nullptr);
129       }
130     }
131   }
132 
133  protected:
nextOnHeadersComplete(std::unique_ptr<HTTPMessage> msg)134   virtual void nextOnHeadersComplete(std::unique_ptr<HTTPMessage> msg) {
135     nextTransactionHandler_->onHeadersComplete(std::move(msg));
136   }
nextOnBody(std::unique_ptr<folly::IOBuf> chain)137   virtual void nextOnBody(std::unique_ptr<folly::IOBuf> chain) {
138     nextTransactionHandler_->onBody(std::move(chain));
139   }
nextOnChunkHeader(size_t length)140   virtual void nextOnChunkHeader(size_t length) {
141     nextTransactionHandler_->onChunkHeader(length);
142   }
nextOnChunkComplete()143   virtual void nextOnChunkComplete() {
144     nextTransactionHandler_->onChunkComplete();
145   }
nextOnTrailers(std::unique_ptr<HTTPHeaders> trailers)146   virtual void nextOnTrailers(std::unique_ptr<HTTPHeaders> trailers) {
147     nextTransactionHandler_->onTrailers(std::move(trailers));
148   }
nextOnEOM()149   virtual void nextOnEOM() {
150     nextTransactionHandler_->onEOM();
151   }
nextOnError(const HTTPException & ex)152   virtual void nextOnError(const HTTPException& ex) {
153     nextTransactionHandler_->onError(ex);
154   }
155   HTTPTransaction::Handler* nextTransactionHandler_{nullptr};
156 
157   boost::variant<HTTPMessageFilter*, HTTPTransaction*> prev_ =
158       static_cast<HTTPTransaction*>(nullptr);
159 
160   bool nextElementIsPaused_{false};
161 };
162 
163 } // namespace proxygen
164