blob: 2b666138aed521723b5798f9dcc58f281f677580 [file] [log] [blame]
#ifndef THIRD_PARTY_MILOTIC_INTERNAL_CC_BMCWEB_SMART_ROUTER_H_
#define THIRD_PARTY_MILOTIC_INTERNAL_CC_BMCWEB_SMART_ROUTER_H_
#include <array>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
#include "absl/base/thread_annotations.h"
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "boost/asio/io_context.hpp" // NOLINT
#include "boost/beast/http/message.hpp" //NOLINT
#include "boost/beast/http/string_body.hpp" //NOLINT
#include "boost/beast/http/verb.hpp" // NOLINT
#include "boost/system/error_code.hpp" // NOLINT
#include "boost/url/parse.hpp" // NOLINT
#include "boost/url/url.hpp" // NOLINT
#include "http_request.hpp"
#include "async_resp.hpp"
#include "utility.hpp"
#include "app_interface.h"
#include "router_interface.h"
#include "routing.hpp"
// DO NOT MODIFY THIS FILE IN GERRIT. THIS FILE SHOULD ONLY BE MODIFIED IN G3
namespace crow {
namespace internal {
struct Node {
absl::flat_hash_map<std::string, Node> children;
bool is_leaf = false;
};
// The class is thread compatible.
class SimpleTrie {
public:
explicit SimpleTrie(const absl::flat_hash_set<std::string>& subtrees);
~SimpleTrie() = default;
// This SimpleTrie is not going to validate the URL is actually a valid URL.
// As the input of this function in our use case comes from a valid Redfish
// request, the url is guaranteed to be a valid URL.
bool IsUrlInSubtrees(std::string_view url) const;
void DebugPrint() const;
protected:
void AddSubtree(std::string_view subtree);
private:
Node root_;
const absl::flat_hash_set<std::string> subtrees_;
};
} // namespace internal
// This router will automatically route the requests to the appropriate
// router based on the request path.
class SmartRouter : public RouterInterface {
public:
// Clang thinks that the following constructor is deleted, but on gcc, it is
// not.
SmartRouter() : tlbmc_owned_subtrees_({}) {}; // NOLINT
~SmartRouter() override = default;
SmartRouter(const SmartRouter&) = delete;
SmartRouter& operator=(const SmartRouter&) = delete;
SmartRouter(SmartRouter&&) = delete;
SmartRouter& operator=(SmartRouter&&) = delete;
SmartRouter(bool allow_session_empty, AppInterface* tlbmc_app);
void Validate();
void Handle(crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& async_resp) override;
// This is a wrapper around the gbmcweb router's handleUpgrade function.
template <typename Adaptor>
void HandleUpgrade(Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Adaptor&& adaptor) {
gbmcweb_router_.handleUpgrade(req, asyncResp,
std::forward<Adaptor>(adaptor));
}
DynamicRule& NewRuleDynamic(std::string&& rule);
std::vector<const std::string*> GetRoutes(const std::string& parent);
void DebugPrint();
template <uint64_t N>
typename black_magic::Arguments<
N>::type::template rebind<TaggedRule>&
NewRuleTagged(std::string_view rule) {
return gbmcweb_router_.newRuleTagged<N>(rule);
}
// Plugin Routes
template <uint64_t Tag, typename Func, size_t N>
void AddHandler(absl::string_view url, boost::beast::http::verb verb,
const std::array<redfish::Privileges, N>& p, Func&& func) {
gbmcweb_router_.newRuleTagged<Tag>(url).methods(verb).privileges(p)(func);
// TODO(b/396518102): Add support for plugins in tlbmc.
// tlbmc_app_->AddRoute<Tag>(url).methods(verb)(func);
}
template <uint64_t Tag, typename Func>
void ReplaceHandler(std::string_view url, boost::beast::http::verb verb,
Func&& func) {
gbmcweb_router_.replaceHandler<Tag>(url, verb, func);
// TODO(b/396518102): Add support for plugins in tlbmc.
// tlbmc_app_->ReplaceHandler<Tag>(url, verb, func);
}
template <uint64_t Tag>
void RemoveHandler(std::string_view url, boost::beast::http::verb verb) {
gbmcweb_router_.removeRuleTagged<Tag>(url, verb);
// TODO(b/396518102): Add support for plugins in tlbmc.
// tlbmc_app_->RemoveHandler<Tag>(url, verb);
}
template <uint64_t Tag, typename Func>
void AppendHandler(std::string_view url, boost::beast::http::verb verb,
Func&& func) {
gbmcweb_router_.appendHandler<Tag>(url, verb, func);
// TODO(b/396518102): Add support for plugins in tlbmc.
// tlbmc_app_->AppendHandler<Tag>(url, verb, func);
}
bool IsTlbmcOwnedUrl(std::string_view url, boost::beast::http::verb verb);
Router& GetGbmcwebRouter() { return gbmcweb_router_; }
void UpdateTlbmcOwnedUrls() override;
protected:
// Store both the gbmcweb and tlbmc routers.
Router gbmcweb_router_ = Router(true);
AppInterface* const tlbmc_app_ = nullptr;
absl::Mutex tlbmc_owned_urls_mutex_;
absl::flat_hash_map<std::string, size_t> tlbmc_owned_urls_
ABSL_GUARDED_BY(tlbmc_owned_urls_mutex_);
private:
absl::flat_hash_map<std::string, size_t> GetTlbmcOwnedUrls();
absl::flat_hash_set<std::string> GetTlbmcOwnedSubtrees();
const internal::SimpleTrie tlbmc_owned_subtrees_;
};
} // namespace crow
#endif // THIRD_PARTY_MILOTIC_INTERNAL_CC_BMCWEB_SMART_ROUTER_H_