#include "server.h"

// Ignore the following warnings in this header when doing Yocto builds.
#include <sys/stat.h>

#include <algorithm>
#include <chrono>  // NOLINT
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <filesystem>  // NOLINT
#include <fstream>
#include <functional>
#include <ios>
#include <iterator>
#include <map>
#include <memory>
#include <optional>
#include <queue>
#include <string>
#include <string_view>
#include <system_error>  // NOLINT
#include <thread>        // NOLINT
#include <unordered_set>
#include <utility>
#include <vector>

#include "tlbmc/credentials/credential_manager.h"
#include "tlbmc/hal/sysfs/led.h"

#pragma GCC diagnostic push
#pragma GCC diagnostic warning \
    "-Wdeprecated-declarations"  // There is not a good way to avoid this as we
                                 // need backward compatibility

#include "absl/base/thread_annotations.h"
#include "absl/container/flat_hash_map.h"
#include "absl/strings/match.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/clock.h"
#include "subscription.h"
#include "app.hpp"
#include "grpc/grpc.h"
#include "grpcpp/support/status.h"
#include <nlohmann/json_fwd.hpp>
#include "peer_identity.h"
#include "usb_fru_config.pb.h"
#include "tlbmc/hal/fru_scanner_gpio.h"
#include "tlbmc/hal/fru_scanner_usb.h"
#include "tlbmc/hal/shared_mem/static_client_impl.h"
#include "tlbmc/hal/shared_mem/static_server_impl.h"
#include "tlbmc/hft/core/hft_service.h"
#include "tlbmc/store/octeon10_evk_store.h"

#ifdef ENABLE_LOAS3_VALIDATION
#include "security/zatar/loas3_validation/validation/validation.h"
#endif

// `B200` is defined in a macro while also in an enum. Need to undefine it to
// avoid build errors.
// More context at https://yaqs.corp.google.com/eng/q/1495189578728865792
#undef B200

#include "gbmc-hal/api/app/inventory/smbios_inventory.h"
#include "gbmc-hal/api/system/codecs/smbios_codec.h"
#include "gbmc-hal/api/system/registries.h"
#include "gbmc-hal/api/system/registry_configs.h"
#include "bus_topology.pb.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "boost/asio/error.hpp"  // NOLINT
#include "boost/asio/io_context.hpp"  // NOLINT
#include "boost/asio/post.hpp"  // NOLINT
#include "boost/beast/http/verb.hpp"  // NOLINT
#include "boost/uuid/uuid.hpp"  // NOLINT
#include "boost/uuid/uuid_generators.hpp"  // NOLINT
#include "boost/uuid/uuid_io.hpp"  // NOLINT
#include "redfish_v1.grpc.pb.h"
#include "redfish_v1.pb.h"
#include "redfish_v1_grpc_include.h"
#include "zatar/struct_proto_conversion.h"
#include "http_request.hpp"
#include "http_response.hpp"
#include "async_resp.hpp"
#include <nlohmann/json.hpp>
#include "oauth_utils.h"
#include "tlbmc/service/fru_service.h"
#include "tlbmc/adapter/data_source.h"
#include "payload.pb.h"
#include "sensor_identifier.pb.h"
#include "sensor_payload.pb.h"
#include "tlbmc/central_config/config.h"
#include "tlbmc/collector/fake_fru_collector.h"
#include "tlbmc/collector/fake_gpio_collector.h"
#include "tlbmc/collector/gpio_collector.h"
#include "tlbmc/configs/proto_config_parser.h"
#include "tlbmc/configs/rate_limiter_config.h"
#include "tlbmc/deterministic_bmc/offline_config_parser/offline_config_parser.h"
#include "tlbmc/deterministic_bmc/offline_config_parser/proto_reader.h"
#include "tlbmc/hal/fake_fru_scanner_fram.h"
#include "tlbmc/hal/fru_scanner.h"
#include "tlbmc/hal/fru_scanner_adc.h"
#include "tlbmc/hal/fru_scanner_cable.h"
#include "tlbmc/hal/fru_scanner_fram.h"
#include "tlbmc/hal/fru_scanner_i2c.h"
#include "tlbmc/hal/nic_veeprom/interface.h"
#include "tlbmc/hal/shared_mem/server_interface.h"
#include "tlbmc/hal/sysfs/i2c.h"
#include "tlbmc/hal/sysfs/i3c.h"
#include "tlbmc/hal/sysfs/iio.h"
#include "tlbmc/hal/sysfs/peci.h"
#include "tlbmc/hft/core/manager.h"
#include "tlbmc/hft/core/manager_fake.h"
#include "tlbmc/hft/core/manager_impl.h"
#include "tlbmc/hft/task_scheduler_adapter.h"
#include "tlbmc/redfish/app.h"
#include "tlbmc/redfish/request.h"
#include "tlbmc/redfish/response.h"
#include "tlbmc/redfish/routes/all_routes.h"
#include "tlbmc/store/store.h"
#include "tlbmc/store/store_hft_adapter.h"
#include "tlbmc/store/store_impl.h"
#include "tlbmc/trace/tracer.h"
#include "g3/grpc_headers.h"
#include "bmcweb_authorizer_singleton.h"
#include "rate_limiter.h"
#include "zatar/bmcweb_cert_provider.h"
#include "zatar/bmcweb_cert_provider_impl.h"
#include "zatar/bmcweb_credentials.h"
#include "openssl/sha.h"  // NOLINT: just for sanity check. No crypto is done.

namespace milotic {

using ::milotic_tlbmc::RedfishRequest;
using ::milotic_tlbmc::RedfishResponse;
using ::milotic_tlbmc::StaticSharedMemoryClient;
using ::milotic_tlbmc::StaticSharedMemoryServer;

grpc::Status SubscriptionPreCheck(
    const grpc::AuthContext& auth_context,
    const std::multimap<grpc::string_ref, grpc::string_ref>& client_metadata,
    const ::redfish::v1::Request* request,
    ::milotic::redfish::BmcWebCertProvider::ServerStatus server_status) {
  ::milotic::authz::BmcWebAuthorizerSingleton& authorizer =
      ::milotic::authz::BmcWebAuthorizerSingleton::GetInstance();
  // Abort if it is not mutual authenticated
  if (server_status != ::milotic::redfish::BmcWebCertProvider::ServerStatus::
                           kWithRootCertsAndProdSignedCert) {
    return grpc::Status(grpc::StatusCode::PERMISSION_DENIED,
                        "The server is not in mutual authenticated mode thus "
                        "no subscription is "
                        "allowed. Please check Server's credential status.");
  }

  if (!auth_context.IsPeerAuthenticated()) {
    return grpc::Status(
        grpc::StatusCode::PERMISSION_DENIED,
        "The request is not authenticated thus no subscription is "
        "allowed. Please check Server's credential status.");
  }

  // Abort if target doesn't match
  if (grpc::Status status =
          authorizer.CheckTarget(auth_context, client_metadata, *request);
      !status.ok()) {
    return status;
  }

  return grpc::Status::OK;
}

namespace internal {

// The implementation of the ServiceWriteReactor.
// This implementation maintains a queue of events, which is supposed to be
// filled by the SubscriptionService.
class Reactor final : public grpc::ServerWriteReactor<::redfish::v1::Response> {
 public:
  // The status of the reactor (also the stream).
  enum class Status : char {
    kIdle,           // The stream is idle, no write is in the flight.
    kWriteInFlight,  // There is a write in flight.
    kFinishCalled,   // The stream will be terminated soon at any given time as
                     // `Finish` has been called. A stream can fall into this
                     // state because of "previous write failed" or "client
                     // cancelled the stream". The stream is waiting for OnDone
                     // to be called to declare the stream fully finished.
    kFinished,  // The stream has been terminated. The `reactor` pointer might
                // be still valid but will be released at any given time.
  };

  Reactor(ecclesia::SubscriptionService* subscription_service,
          std::function<void(Reactor*)>&& on_done,
          size_t maximum_event_queue_size)
      : subscription_service_(subscription_service),
        on_done_(std::move(on_done)),
        maximum_event_queue_size_(maximum_event_queue_size) {}

  // NOTE: set this once before any StartWrite is called.
  void SetPeerSpiffeIdentity(const ::milotic::authz::PeerSpiffeIdentity& peer) {
    peer_ = peer;
  }

  void SafeFinish(const grpc::Status& status) {
    absl::MutexLock lock(status_mutex_);
    if (status_ == Status::kFinishCalled || status_ == Status::kFinished) {
      return;
    }
    status_ = Status::kFinishCalled;
    Finish(status);
  }

  void OnWriteDone(bool ok) override {
    {
      absl::MutexLock status_lock(status_mutex_);
      if (status_ != Status::kWriteInFlight) {
        return;
      }
      if (!ok) {
        LOG(ERROR) << "Failed to write response";
        status_ = Status::kFinishCalled;
        Finish(grpc::Status(grpc::StatusCode::INTERNAL,
                            "Failed to write response"));
        return;
      }
      // Now pop the last event as it won't be referenced again
      {
        absl::MutexLock events_lock(events_mutex_);
        events_.pop();
      }
      status_ = Status::kIdle;
    }
    if (is_testing_events_) {
      GenerateSingleTestingEvent();
    }
    // The above code block will ensure no lock is held when the block goes out
    // of scope.
    WriteAnEventIfAny();
  }

  void SetToTestMode() { is_testing_events_ = true; }

  void OnCancel() override {
    absl::MutexLock lock(status_mutex_);
    if (status_ == Status::kFinishCalled || status_ == Status::kFinished) {
      return;
    }
    status_ = Status::kFinishCalled;
    Finish(grpc::Status(grpc::StatusCode::CANCELLED,
                        "Client cancelled requests."));
  }

  void OnDone() override {
    {
      absl::MutexLock lock(status_mutex_);
      status_ = Status::kFinished;
    }
    if (peer_) {
      grpc::Status status =
          ::milotic::authz::BmcWebAuthorizerSingleton::GetInstance()
              .RecordNewUnsubscription(*peer_);
      if (!status.ok()) {
        // Conversion from grpc::Status to std::ostream is not supported in grpc
        // v1.56.2 which is what was used causing builds to break. See
        // b/323972900
        LOG(ERROR) << "RecordNewUnsubscription failed with code "
                   << status.error_code() << " and message "
                   << status.error_message();
      }
    }
    {
      absl::MutexLock lock(subscription_id_mutex_);
      if (subscription_id_ && subscription_service_ != nullptr) {
        subscription_service_->DeleteSubscription(*subscription_id_);
      }
    }
    if (on_done_) {
      on_done_(this);
    }
  }

  void SetSubscriptionId(const ecclesia::SubscriptionId& id) {
    absl::MutexLock lock(subscription_id_mutex_);
    subscription_id_ = id;
  }

  void AddAnEvent(const ::redfish::v1::Response& event) {
    // We only push an event to the queue if the stream is idle or has a write
    // in flight.
    absl::MutexLock status_lock(status_mutex_);
    if (status_ != Status::kIdle && status_ != Status::kWriteInFlight) {
      return;
    }
    // TODO: check subscription IDs match before enqueue.
    absl::MutexLock events_lock(events_mutex_);
    if (events_.size() >= maximum_event_queue_size_) {
      LOG(WARNING) << "Too many events to queue; new events have been ignored";
      return;
    }
    events_.push(event);
  }

  Status GetStatus() {
    absl::MutexLock lock(status_mutex_);
    return status_;
  }

  void WriteAnEventIfAny() {
    // We only start a new StartWrite if the stream is idle.
    absl::MutexLock status_lock(status_mutex_);
    if (status_ != Status::kIdle) {
      return;
    }
    absl::MutexLock lock(events_mutex_);
    if (events_.empty()) {
      return;
    }
    status_ = Status::kWriteInFlight;
    StartWrite(&events_.front());
  }

  void StartTestingEvents() {
    GenerateSingleTestingEvent();
    WriteAnEventIfAny();
  }

 protected:
  void GenerateSingleTestingEvent() {
    ::redfish::v1::Response event;
    nlohmann::json json_response;
    event.set_code(200);
    json_response["number"] = test_event_count_;
    event.set_json_str(json_response.dump());
    test_event_count_++;
    AddAnEvent(event);
  }

 private:
  // The data members below are guaranteed to be created before OnWrite starts,
  // afterwards they are read-only, so no need to be protected by a lock
  std::optional<::milotic::authz::PeerSpiffeIdentity> peer_;
  bool is_testing_events_ = false;
  ecclesia::SubscriptionService* subscription_service_ = nullptr;
  std::function<void(Reactor*)> on_done_;
  size_t maximum_event_queue_size_ = 0;

  // The data members below is guaranteed to be accessed only by one thread at a
  // time.
  int test_event_count_ = 0;

  // `events_` might be modified by different thread: gRPC Event Engine threads,
  // subscription service threads.
  absl::Mutex events_mutex_;
  std::queue<::redfish::v1::Response> events_ ABSL_GUARDED_BY(events_mutex_);

  // `subscription_id_` might be modified by different thread. For example, the
  // stream gets closed very early before any SetSubscriptionId is called.
  absl::Mutex subscription_id_mutex_;
  std::optional<ecclesia::SubscriptionId> subscription_id_
      ABSL_GUARDED_BY(subscription_id_mutex_);

  // `status_` might be modified by different thread.
  // `status_` is to avoid extra Write to be fired when the stream is
  // supposed to be finished.
  absl::Mutex status_mutex_;
  Status status_ ABSL_GUARDED_BY(status_mutex_) = Status::kIdle;
};

class RedfishV1Impl final : public ecclesia::GrpcRedfishV1::CallbackService {
 public:
  RedfishV1Impl(
      App* app, const milotic_tlbmc::RedfishApp* tlbmc_app,
      const std::shared_ptr<boost::asio::io_context>& io_context_main_thread,
      const std::shared_ptr<boost::asio::io_context>& io_context_worker_threads,
      ::milotic::redfish::BmcWebCertProvider& cert_provider,
      RedfishServiceConfig& config,
      ecclesia::SubscriptionService* subscription_service,
      crow::RateLimiter* rate_limiter)
      : hardware_concurrency_(std::thread::hardware_concurrency()),
        app_(app),
        tlbmc_app_(tlbmc_app),
        io_context_main_thread_(io_context_main_thread),
        io_context_worker_threads_(io_context_worker_threads),
        cert_provider_(cert_provider),
        config_(config),
        subscription_service_(subscription_service),
        rate_limiter_(rate_limiter) {}

  ~RedfishV1Impl() override = default;

  grpc::ServerUnaryReactor* Get(grpc::CallbackServerContext* context,
                                const ::redfish::v1::Request* request,
                                ::redfish::v1::Response* response) override {
    return RequestUri(context, boost::beast::http::verb::get, request,
                      response);
  }
  grpc::ServerUnaryReactor* Post(grpc::CallbackServerContext* context,
                                 const ::redfish::v1::Request* request,
                                 ::redfish::v1::Response* response) override {
    return RequestUri(context, boost::beast::http::verb::post, request,
                      response);
  }
  grpc::ServerUnaryReactor* Put(grpc::CallbackServerContext* context,
                                const ::redfish::v1::Request* request,
                                ::redfish::v1::Response* response) override {
    return RequestUri(context, boost::beast::http::verb::put, request,
                      response);
  }
  grpc::ServerUnaryReactor* Patch(grpc::CallbackServerContext* context,
                                  const ::redfish::v1::Request* request,
                                  ::redfish::v1::Response* response) override {
    return RequestUri(context, boost::beast::http::verb::patch, request,
                      response);
  }
  grpc::ServerUnaryReactor* Delete(grpc::CallbackServerContext* context,
                                   const ::redfish::v1::Request* request,
                                   ::redfish::v1::Response* response) override {
    return RequestUri(context, boost::beast::http::verb::delete_, request,
                      response);
  }

  grpc::ServerUnaryReactor* GetOverridePolicy(
      grpc::CallbackServerContext* context,
      const ::redfish::v1::GetOverridePolicyRequest* /*unused*/,
      ::redfish::v1::GetOverridePolicyResponse* response) override {
    grpc::ServerUnaryReactor* reactor = context->DefaultReactor();

    namespace fs = std::filesystem;
    fs::file_status status =
        fs::status(fs::path(config_.redfish_override_policy_path));
    if (!fs::is_regular_file(status)) {
      reactor->Finish(grpc::Status(
          grpc::StatusCode::NOT_FOUND,
          "Policy file not found: " + config_.redfish_override_policy_path));
      return reactor;
    }

    std::ifstream policy_file(config_.redfish_override_policy_path);

    if (!policy_file) {
      reactor->Finish(grpc::Status(
          grpc::StatusCode::INTERNAL,
          "Policy file read error: " + config_.redfish_override_policy_path));
      return reactor;
    }

    response->set_policy(
        std::string(std::istreambuf_iterator<char>{policy_file}, {}));
    reactor->Finish(grpc::Status::OK);
    return reactor;
  }

  grpc::ServerWriteReactor<::redfish::v1::Response>* Subscribe(
      grpc::CallbackServerContext* context,
      const ::redfish::v1::Request* request) override {
    // A reactor will only released when all references are cleared. References
    // include gRPC core layer, and the subscription service.
    auto reactor = std::make_shared<Reactor>(
        subscription_service_,
        [this](Reactor* reactor) { RemoveReactor(reactor); },
        config_.maximum_event_queue_size);
    StoreReactor(reactor);

    if (!config_.generate_testing_events &&
        (config_.disable_eventing || subscription_service_ == nullptr)) {
      reactor->SafeFinish(
          grpc::Status(grpc::StatusCode::UNIMPLEMENTED,
                       "Eventing is disabled or not implemented."));
      return reactor.get();
    }

    if (config_.generate_testing_events) {
      reactor->SetToTestMode();
    }

    // Sanity check: the server has to be in mutual TLS mode and the requester
    // has been authenticated
    if (grpc::Status status = SubscriptionPreCheck(
            *context->auth_context(), context->client_metadata(), request,
            cert_provider_.GetServerStatus());
        !status.ok()) {
      reactor->SafeFinish(status);
      LOG(WARNING) << "AuthorizeSubscription failed: "
                   << status.error_message();
      return reactor.get();
    }

    // Rate limit
    ::milotic::authz::PeerSpiffeIdentity peer;
    if (grpc::Status status = ::milotic::authz::BmcWebAuthorizerSingleton::
            GetPeerIdentityFromAuthContext(*context->auth_context(), peer);
        !status.ok()) {
      reactor->SafeFinish(status);
      LOG(WARNING) << "GetPeerIdentityFromAuthContext failed"
                   << status.error_message();
      return reactor.get();
    }
    if (grpc::Status status =
            ::milotic::authz::BmcWebAuthorizerSingleton::GetInstance()
                .RecordNewSubscription(peer);
        !status.ok()) {
      reactor->SafeFinish(status);
      LOG(WARNING) << "RecordNewSubscription failed" << status.error_message();
      return reactor.get();
    }
    reactor->SetPeerSpiffeIdentity(peer);

    nlohmann::json event_config =
        nlohmann::json::parse(request->json_str(), nullptr, false);

    // Create subscription asynchronously.
    if (subscription_service_ != nullptr) {
      std::unordered_set<std::string> peer_privileges;
      if (grpc::Status status =
              ::milotic::authz::BmcWebAuthorizerSingleton::GetInstance()
                  .GetPrivilegesViaMTls(*context->auth_context(),
                                        peer_privileges);
          !status.ok()) {
        reactor->SafeFinish(status);
        LOG(WARNING) << "GetPrivilegesViaMTls failed" << status.error_message();
        return reactor.get();
      }
      subscription_service_->CreateSubscription(
          event_config, peer_privileges,
          [this, reactor](
              const absl::StatusOr<ecclesia::SubscriptionId>& subscription_id) {
            if (!subscription_id.ok()) {
              reactor->SafeFinish(
                  grpc::Status(grpc::StatusCode::INTERNAL,
                               subscription_id.status().ToString()));
              return;
            }
            reactor->SetSubscriptionId(*subscription_id);

            // Note: any StartWrite must be after any Finish calls above
            if (config_.generate_testing_events) {
              reactor->StartTestingEvents();
            }
          },
          [reactor](const nlohmann::json& event_json) mutable {
            if (reactor == nullptr) return;
            // If reactor ever reports that it is finished, we should never
            // access it again.
            if (reactor->GetStatus() == Reactor::Status::kFinished) {
              reactor = nullptr;
              return;
            }
            // If reactor is about to finish, we should return and wait until
            // it is actually finished. We must not start a new StartWrite().
            if (reactor->GetStatus() == Reactor::Status::kFinishCalled) {
              return;
            }
            ::redfish::v1::Response event;
            event.set_json_str(event_json.dump());
            event.set_code(200);
            reactor->AddAnEvent(event);
            reactor->WriteAnEventIfAny();
          });
      return reactor.get();
    }

    if (config_.generate_testing_events) {
      reactor->StartTestingEvents();
    }
    return reactor.get();
  }

 private:
  struct ProfilingTimeStamps {
    std::chrono::time_point<std::chrono::high_resolution_clock>
        request_uri_start;
    std::chrono::time_point<std::chrono::high_resolution_clock>
        entering_io_context;
    std::chrono::time_point<std::chrono::high_resolution_clock> handler_start;
    std::chrono::time_point<std::chrono::high_resolution_clock> handler_end;
    std::chrono::time_point<std::chrono::high_resolution_clock> response_end;
    absl::Time request_start;
  };

  std::optional<crow::Request> GetInternalRequestFromProto(
      boost::beast::http::request<boost::beast::http::string_body>&&
          boost_request,
      grpc::ServerUnaryReactor* reactor,
      grpc::CallbackServerContext* context) const {
    std::error_code error;
    crow::Request crow_request(std::move(boost_request), error);

    if (error) {
      LOG(ERROR) << "Request failed to construct " << error;
      reactor->Finish(grpc::Status(grpc::StatusCode::INTERNAL,
                                   "Request failed to construct"));
      return std::nullopt;
    }

    // If enable_insecure_server is true, set fromGrpc to false; otherwise
    // fromGrpc should be false.
    crow_request.fromGrpc = !config_.enable_insecure_server;

    crow_request.with_trust_bundle =
        cert_provider_.GetServerStatus() ==
            ::milotic::redfish::BmcWebCertProvider::ServerStatus::
                kWithRootCertsAndProdSignedCert ||
        cert_provider_.GetServerStatus() ==
            ::milotic::redfish::BmcWebCertProvider::ServerStatus::
                kWithRootCertsAndSelfSignedCert;

    crow_request.peer_authenticated =
        context->auth_context()->IsPeerAuthenticated();
    return crow_request;
  }

  grpc::Status SetPeerPrivileges(
      const grpc::AuthContext& auth_context,
      const ::redfish::v1::Request* request,
      std::unordered_set<std::string>& peer_privileges,
      bool with_trust_bundle) const {
    std::optional<std::string> oauth_token =
        ::milotic::authz::GetOAuthTokenFromRequest(*request);

    grpc::Status privileges_status;
    if (config_.enable_insecure_server) {
      peer_privileges.clear();
      privileges_status = grpc::Status::OK;
    } else if (oauth_token != std::nullopt) {
      privileges_status =
          ::milotic::authz::BmcWebAuthorizerSingleton::GetInstance()
              .GetPrivilegesViaOAuth(auth_context, *oauth_token,
                                     peer_privileges);
    } else {
      privileges_status =
          ::milotic::authz::BmcWebAuthorizerSingleton::GetInstance()
              .GetPrivilegesViaMTls(auth_context, peer_privileges);
      // Allow recovery RPCs when there is no trust bundle.
      if (!privileges_status.ok() && !with_trust_bundle) {
        LOG(WARNING) << "Server doesn't have trust bundle; only recovery RPCs "
                        "are allowed";
        peer_privileges.clear();
        privileges_status = grpc::Status::OK;
      }
    }

    return privileges_status;
  }

  static std::chrono::time_point<std::chrono::high_resolution_clock>
  GetCurrentTime(bool do_profiling) {
    if (!do_profiling)
      return std::chrono::high_resolution_clock::time_point::min();
    return std::chrono::high_resolution_clock::now();
  }

  static void LogProfileTimeInResp(
      std::chrono::time_point<std::chrono::high_resolution_clock> start,
      std::chrono::time_point<std::chrono::high_resolution_clock> end,
      const std::string& profile_label, bool do_profiling,
      crow::Response& res) {
    if (!do_profiling) return;
    auto time_delta =
        std::chrono::duration_cast<std::chrono::nanoseconds>(end - start);
    res.jsonValue[profile_label] = time_delta.count();
  }

  static void UpdateResponseMetrics(int code, std::string_view resource_url,
                                    bool tlbmc_enabled,
                                    absl::Time request_start) {
    if (tlbmc_enabled) {
      absl::Duration response_time = absl::Now() - request_start;
      milotic_tlbmc::StaticSharedMemoryServer::GetInstance()
          .UpdateMetricsResponse(response_time, code, resource_url);
    }
  }

  static void AsyncResponseHandler(::redfish::v1::Response* response,
                                   grpc::ServerUnaryReactor* reactor,
                                   crow::Response& res,
                                   ProfilingTimeStamps profiling_time_stamps,
                                   bool do_profiling, bool tlbmc_enabled,
                                   std::string_view resource_url) {
    if (!res.stringResponse) {
      LOG(ERROR) << "HTTP response is empty!";
      reactor->Finish(grpc::Status(grpc::StatusCode::INTERNAL,
                                   "HTTP response from BMCWeb is empty."));
      UpdateResponseMetrics(static_cast<int>(res.result()), resource_url,
                            tlbmc_enabled, profiling_time_stamps.request_start);
      return;
    }

    auto* headers = response->mutable_headers();
    for (const auto& element : res.stringResponse->base()) {
      // Repeated headers are combined into a ',' separated list. See
      // https://www.rfc-editor.org/rfc/rfc9110.html#section-5.3-3.
      auto found = headers->find(element.name_string());
      if (found == headers->end()) {
        (*headers)[element.name_string()] = element.value();
      } else {
        found->second += ',';
        found->second += element.value();
      }
    }

    profiling_time_stamps.response_end = GetCurrentTime(do_profiling);

    LogProfileTimeInResp(profiling_time_stamps.request_uri_start,
                         profiling_time_stamps.response_end,
                         "time-total-response", do_profiling, res);

    if ((*res.stringResponse)["Content-Type"] == "application/octet-stream" ||
        (*res.stringResponse)["OData-Version"] != "4.0") {
      *response->mutable_octet_stream() = res.body();
    } else {
      *response->mutable_json_str() = res.jsonValue.dump(
          2, ' ', true, nlohmann::json::error_handler_t::replace);
    }
    response->set_code(static_cast<unsigned int>(res.result()));
    reactor->Finish(grpc::Status::OK);
    UpdateResponseMetrics(static_cast<int>(res.result()), resource_url,
                          tlbmc_enabled, profiling_time_stamps.request_start);
  }

  void HandleTlbmcRequest(
      grpc::CallbackServerContext* context,
      const ::redfish::v1::Request* grpc_request,
      boost::beast::http::request<boost::beast::http::string_body>&&
          boost_request,
      ::redfish::v1::Response* grpc_response, grpc::ServerUnaryReactor* reactor,
      bool with_trust_bundle, bool enable_insecure_server) const {
    milotic_tlbmc::Tracer::GetInstance().AddRepeatedDatapoint(
        "Tlbmc-Parse-Request-Begin", absl::Now());
    absl::StatusOr<milotic_tlbmc::RedfishRequest> request =
        milotic_tlbmc::RedfishRequest::Create(std::move(boost_request));
    if (!request.ok()) {
      reactor->Finish(grpc::Status(grpc::StatusCode::INTERNAL,
                                   request.status().ToString()));
      return;
    }
    request->SetWithTrustBundle(with_trust_bundle);
    // If enable_insecure_server is true, set `FromGrpc` to false; otherwise
    // `FromGrpc` should be true.
    request->SetFromGrpc(!enable_insecure_server);
    request->SetPeerAuthenticated(
        context->auth_context()->IsPeerAuthenticated());

    LOG(INFO) << "Received TLBMC request; |url|=" << request->Target()
              << "; |method|=" << static_cast<int>(request->Method());

    std::unordered_set<std::string> peer_privileges;
    if (grpc::Status privileges_status =
            SetPeerPrivileges(*context->auth_context(), grpc_request,
                              peer_privileges, with_trust_bundle);
        !privileges_status.ok() && !enable_insecure_server) {
      reactor->Finish(privileges_status);
      return;
    }

    request->SetPeerPrivileges(peer_privileges);
    milotic_tlbmc::Tracer::GetInstance().AddRepeatedDatapoint(
        "Tlbmc-Parse-Request-End", absl::Now());

    RedfishResponse response(reactor, *grpc_response);
    milotic_tlbmc::Tracer::GetInstance().AddRepeatedDatapoint(
        "Tlbmc-Redfish-Routing-Begin", absl::Now());
    tlbmc_app_->Handle(std::move(*request), std::move(response));
  }

  void HandleNonTlbmcRequest(
      grpc::CallbackServerContext* context,
      const ::redfish::v1::Request* request,
      boost::beast::http::request<boost::beast::http::string_body>&&
          boost_request,
      ::redfish::v1::Response* response, grpc::ServerUnaryReactor* reactor,
      ProfilingTimeStamps profiling_time_stamps) const {
    std::optional<crow::Request> crow_request =
        GetInternalRequestFromProto(std::move(boost_request), reactor, context);
    if (!crow_request) {
      return;
    }

    LOG(INFO) << "Received non-TLBMC request; |url|=" << crow_request->target()
              << "; |method|=" << crow_request->methodString();

    if (grpc::Status privileges_status = SetPeerPrivileges(
            *context->auth_context(), request, crow_request->peer_privileges,
            crow_request->with_trust_bundle);
        !privileges_status.ok()) {
      reactor->Finish(privileges_status);
      return;
    }

    auto async_resp = std::make_shared<bmcweb::AsyncResp>(nullptr);
    if (auto it = request->headers().find(bmcweb::BMCWEB_HINT_MAX_AGE_SEC);
        it != request->headers().end()) {
      int64_t max_age_sec{};
      bool success = absl::SimpleAtoi(it->second, &max_age_sec);
      if (!success || max_age_sec <= 0) {
        reactor->Finish(grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
                                     "Invalid BMCWEB_HINT_MAX_AGE_SEC,"
                                     "must be a positive integer"));
        return;
      }
      async_resp->hintMaxAgeSec = max_age_sec;
      async_resp->hintCacheMaxAgeSec = max_age_sec;
    }

    profiling_time_stamps.request_start = absl::Now();
    std::string resource_url = std::string(crow_request->target());
    async_resp->res.setCompleteRequestHandler(
        [response, reactor, profiling_time_stamps,
         do_profiling{config_.do_profiling},
         tlbmc_enabled{config_.enable_tlbmc && tlbmc_app_ != nullptr},
         resource_url(std::move(resource_url))](crow::Response& res) {
          AsyncResponseHandler(response, reactor, res, profiling_time_stamps,
                               do_profiling, tlbmc_enabled, resource_url);
        });

    profiling_time_stamps.entering_io_context =
        GetCurrentTime(config_.do_profiling);

    if (crow_request->method() == boost::beast::http::verb::get &&
        config_.multi_thread_get) {
      auto strand = std::make_shared<boost::asio::io_context::strand>(
          *io_context_worker_threads_);
      async_resp->strand_ = strand;
      boost::asio::post(*strand, [this, crow_request{std::move(crow_request)},
                                  async_resp{std::move(async_resp)}]() mutable {
        app_->handle(*crow_request, async_resp);
      });
    } else {
      boost::asio::post(
          *io_context_main_thread_, [crow_request{std::move(crow_request)},
                                     /*async_resp has to be moved to prevent
                                       the handler being called in the grpc
                                       thread due to expand queries.*/
                                     async_resp{std::move(async_resp)},
                                     profiling_time_stamps, this]() mutable {
            profiling_time_stamps.handler_start =
                GetCurrentTime(config_.do_profiling);

            app_->handle(*crow_request, async_resp);

            profiling_time_stamps.handler_end =
                GetCurrentTime(config_.do_profiling);

            LogProfileTimeInResp(profiling_time_stamps.request_uri_start,
                                 profiling_time_stamps.entering_io_context,
                                 "time-before-io-context", config_.do_profiling,
                                 async_resp->res);
            LogProfileTimeInResp(profiling_time_stamps.entering_io_context,
                                 profiling_time_stamps.handler_start,
                                 "time-io-context-queue-wait",
                                 config_.do_profiling, async_resp->res);
            LogProfileTimeInResp(profiling_time_stamps.handler_start,
                                 profiling_time_stamps.handler_end,
                                 "time-handler", config_.do_profiling,
                                 async_resp->res);
          });
    }
  }

  static bool IsTlbmcRequest(const ::redfish::v1::Request* request) {
    return absl::StartsWith(request->url(), milotic_tlbmc::kTlbmcPrefix);
  }

  static bool IsEmmcMounted() {
    struct stat st_mount;
    struct stat st_parent;
    if (stat("/mnt/luks-mmcblk0_fs", &st_mount) != 0) {
      return false;
    }
    if (stat("/mnt", &st_parent) != 0) {
      return false;
    }
    return st_mount.st_dev != st_parent.st_dev;
  }

  static absl::StatusOr<
      boost::beast::http::request<boost::beast::http::string_body>>
  CreateBoostRequest(const ::redfish::v1::Request* request,
                     boost::beast::http::verb method) {
    boost::beast::http::request<boost::beast::http::string_body> boost_request;

    boost::system::result<boost::urls::url> url =
        boost::urls::parse_relative_ref(request->url());
    if (!url) {
      return absl::InvalidArgumentError(
          absl::StrFormat("URL %s is invalid", request->url()));
    }

    // https://www.dmtf.org/sites/default/files/standards/documents/DSP0266_1.8.0.pdf
    // Redfish spec states that # is URL must be a fragment. (6.1)
    // Fragments will be ignored by the server. (Also 6.1)
    boost_request.target(url->remove_fragment());
    boost_request.method(method);

    // Check if json_str here first since that's preferred.
    if (!request->json_str().empty()) {
      boost_request.body() = request->json_str();
    } else if (request->has_json()) {
      nlohmann::json json_req = ecclesia::StructToJson(request->json());
      if (!json_req.is_null()) {
        boost_request.body() = json_req.dump();
      }
    } else if (request->has_octet_stream()) {
      std::string stripped_url = url->path();
      if (stripped_url.starts_with(milotic_tlbmc::kTlbmcPrefix)) {
        stripped_url =
            stripped_url.substr(milotic_tlbmc::kTlbmcPrefix.size() - 1);
      }
      if (!stripped_url.empty() && stripped_url.back() == '/') {
        stripped_url.pop_back();
      }
      if (stripped_url != "/redfish/v1/UpdateService/MultipartUpdate" ||
          method != boost::beast::http::verb::post) {
        boost_request.body() = request->octet_stream();
      } else {
        // MultipartUpdate is a special case that we want to avoid copying the
        // entire content to the body. We will write the content to a
        // temporary file and then pass the file path to the handler.
        // Breaking the API boundary is not perfect but I didn't find other good
        // way to avoid copying the request body.
        std::string_view file_content = request->octet_stream();
#ifdef UNIT_TEST_BUILD
        std::string bundle_file_tmp_path = std::tmpnam(nullptr);
#else
        // TODO(nanzhou): handle concurrent multipart update requests better
        std::string bundle_file_tmp_path =
            "/mnt/luks-mmcblk0_fs/firmware_bundle.tar.gz.tmp";

        // If eMMC is not mounted, we should not write to the file system.
        // Instead, we will write to the tmpfs.
        bool is_emmc_mounted = IsEmmcMounted();
        if (!is_emmc_mounted) {
          return absl::InternalError(
              "eMMC is not mounted. Can't process multipart update.");
        }
#endif

        std::ofstream file(bundle_file_tmp_path, std::ios::binary);
        bool hash_check_good = true;
        SHA256_CTX sha256_ctx;
        if (SHA256_Init(&sha256_ctx) != 1) {
          hash_check_good = false;
        }
        constexpr std::size_t kBufferSize1MB = 1024 * 1024;
        std::size_t offset = 0;
        while (offset < file_content.size()) {
          std::size_t remaining_size = file_content.size() - offset;
          std::size_t current_chunk_size =
              std::min(kBufferSize1MB, remaining_size);
          std::string_view chunk =
              file_content.substr(offset, current_chunk_size);
          file.write(chunk.data(), static_cast<std::streamsize>(chunk.size()));
          offset += current_chunk_size;
          if (hash_check_good &&
              SHA256_Update(&sha256_ctx, chunk.data(), chunk.size()) != 1) {
            hash_check_good = false;
          }
        }
        file.flush();
        if (file.good()) {
          boost_request.body() = bundle_file_tmp_path;
        }
        unsigned char hash[SHA256_DIGEST_LENGTH];
        if (SHA256_Final(hash, &sha256_ctx) != 1) {
          hash_check_good = false;
        }
        if (hash_check_good) {
          std::string server_hash(reinterpret_cast<char*>(hash),
                                  SHA256_DIGEST_LENGTH);
          boost_request.base().insert("Multipart-SHA256-ServerSide",
                                      server_hash);
        }
      }
    }

    for (const auto& [key, value] : request->headers()) {
      boost_request.base().insert(key, value);
    };

    return boost_request;
  }
  grpc::ServerUnaryReactor* RequestUri(grpc::CallbackServerContext* context,
                                       boost::beast::http::verb method,
                                       const ::redfish::v1::Request* request,
                                       ::redfish::v1::Response* response) {
    ProfilingTimeStamps profiling_time_stamps;
    profiling_time_stamps.request_uri_start =
        GetCurrentTime(config_.do_profiling);

    using ::milotic::authz::BmcWebAuthorizerSingleton;

    grpc::ServerUnaryReactor* reactor = context->DefaultReactor();

    milotic_tlbmc::Tracer::GetInstance().AddRepeatedDatapoint(
        "Authz-CheckTarget-Begin", absl::Now());
    // Check target only when there is trust bundle and server is in secure
    // mode.
    bool with_trust_bundle =
        (cert_provider_.GetServerStatus() ==
             ::milotic::redfish::BmcWebCertProvider::ServerStatus::
                 kWithRootCertsAndProdSignedCert ||
         cert_provider_.GetServerStatus() ==
             ::milotic::redfish::BmcWebCertProvider::ServerStatus::
                 kWithRootCertsAndSelfSignedCert);
    if (!milotic_tlbmc::GetTlbmcConfig()
             .trust_bundle_install_module()
             .enabled() &&
        !config_.enable_insecure_server && with_trust_bundle) {
      grpc::Status status =
          BmcWebAuthorizerSingleton::GetInstance().CheckTarget(
              *context->auth_context(), context->client_metadata(), *request);
      if (!status.ok()) {
        LOG(WARNING) << "Check target failed: " << status.error_message();
        reactor->Finish(status);
        return reactor;
      }
    }

    absl::StatusOr<boost::beast::http::request<boost::beast::http::string_body>>
        boost_request = CreateBoostRequest(request, method);
    if (!boost_request.ok()) {
      reactor->Finish(
          grpc::Status(grpc::StatusCode::INTERNAL,
                       std::string(boost_request.status().message())));
      return reactor;
    }

    if (rate_limiter_ != nullptr) {
      if (std::optional<crow::RateLimiterDropInfo> drop_info =
              rate_limiter_->AdmitRequest(request->url());
          drop_info.has_value()) {
        reactor->Finish(grpc::Status(
            grpc::StatusCode::RESOURCE_EXHAUSTED,
            absl::StrFormat(
                "Request rate limited: bucket level %.2f, capacity %.2f, leak "
                "rate %.2f reqs/sec.",
                drop_info->bucket_level, drop_info->bucket_capacity,
                drop_info->leak_rate_per_sec)));
        return reactor;
      }
    }

    milotic_tlbmc::Tracer::GetInstance().AddRepeatedDatapoint(
        "Authz-CheckTarget-End", absl::Now());

    if (config_.enable_tlbmc && IsTlbmcRequest(request)) {
      HandleTlbmcRequest(context, request, std::move(boost_request.value()),
                         response, reactor, with_trust_bundle,
                         config_.enable_insecure_server);
    } else {
      HandleNonTlbmcRequest(context, request, std::move(boost_request.value()),
                            response, reactor, profiling_time_stamps);
    }

    return reactor;
  }

  void StoreReactor(const std::shared_ptr<Reactor>& reactor) {
    absl::MutexLock lock(mutex_);
    reactors_store_.insert({reactor.get(), reactor});
  }

  void RemoveReactor(Reactor* reactor) {
    absl::MutexLock lock(mutex_);
    reactors_store_.erase(reactor);
  }

  const unsigned int hardware_concurrency_;
  App* app_;
  const milotic_tlbmc::RedfishApp* tlbmc_app_;
  std::shared_ptr<boost::asio::io_context> io_context_main_thread_;
  std::shared_ptr<boost::asio::io_context> io_context_worker_threads_;
  ::milotic::redfish::BmcWebCertProvider& cert_provider_;
  RedfishServiceConfig& config_;
  ::redfish::v1::Response first_test_response_;
  ecclesia::SubscriptionService* subscription_service_ = nullptr;
  crow::RateLimiter* rate_limiter_ = nullptr;

  absl::Mutex mutex_;
  absl::flat_hash_map<Reactor*, std::shared_ptr<Reactor>> reactors_store_
      ABSL_GUARDED_BY(mutex_);
};

}  // namespace internal

void GrpcRedfishService::Shutdown() {
  LOG(INFO) << "Dumping trace: \n"
            << milotic_tlbmc::Tracer::GetInstance().Dump();
  LOG(WARNING) << "Shutdown gRPC server...";
  server_->Shutdown(std::chrono::system_clock::now() + std::chrono::seconds(1));
  server_->Wait();
  LOG(WARNING) << "gRPC server stopped!";
}

void GrpcRedfishService::RegisterTlbmcRoutesAndValidate(
    milotic_tlbmc::RedfishApp* app, const std::string& system_root_path) {
  if (app != nullptr) {
    milotic_tlbmc::RegisterAllRoutes(*app, system_root_path);
    app->Validate();
    if (app->GetSmartRouter() != nullptr) {
      app->GetSmartRouter()->UpdateTlbmcOwnedUrls();
    }
  }
}

std::unique_ptr<milotic_tlbmc::RedfishApp> GrpcRedfishService::CreateTlbmcApp(
    const RedfishServiceConfig& config) {
  if (!config.enable_tlbmc) {
    return nullptr;
  }
  if (config.enable_tlbmc_octeon10_evk) {
    return std::make_unique<milotic_tlbmc::RedfishApp>(
        std::make_unique<milotic_tlbmc::Octeon10EvkStore>());
  }
  using ::milotic_tlbmc::AdHocScannerType;
  using ::milotic_tlbmc::FakeGpioCollector;
  using ::milotic_tlbmc::FruScanner;
  using ::milotic_tlbmc::FruScannerAdc;
  using ::milotic_tlbmc::FruScannerCable;
  using ::milotic_tlbmc::FruScannerFram;
  using ::milotic_tlbmc::FruScannerGpio;
  using ::milotic_tlbmc::FruScannerI2c;
  using ::milotic_tlbmc::FruScannerUsb;
  using ::milotic_tlbmc::GpioCollector;
  using ::milotic_tlbmc::I2cSysfs;
  using ::milotic_tlbmc::I3cSysfs;
  using ::milotic_tlbmc::IioSysfs;
  using ::milotic_tlbmc::InitializeTlbmcConfig;
  using ::milotic_tlbmc::LedSysfs;
  using ::milotic_tlbmc::PeciSysfs;
  using ::milotic_tlbmc::RateLimiterConfig;
  using ::milotic_tlbmc::RedfishApp;
  using ::milotic_tlbmc::StoreImpl;
  using ::milotic_tlbmc::Tracer;
  InitializeTlbmcConfig(config.tlbmc_config_bundle_path,
                        config.tlbmc_release_file_path);
  RateLimiterConfig::Init(std::filesystem::path(config.tlbmc_config_bundle_path)
                              .parent_path()
                              .string());
  // Initialize tlbmc
  if (config.enable_tlbmc_trace) {
    Tracer::Initialize(true);
  }

  // Initialize deterministic bmc.
  bool enable_deterministic_bmc = milotic_tlbmc::GetTlbmcConfig()
                                      .fru_collector_module()
                                      .enable_deterministic_bmc();
  uhmm::I2cRoot i2c_root;
  uhmm::BmcMonitoredComponentsResponse bmc_monitored_components_response;

  milotic_tlbmc::StoreImpl::Options options;

  if (enable_deterministic_bmc) {
    deterministic_bmc::OfflineConfigParser::ConfigParserOptions
        config_parser_options;

    config_parser_options.uhmm_offline_data_proto_format =
        config.uhmm_offline_data_format;

    if (config.uhmm_offline_data_format ==
        deterministic_bmc::ProtoFormat::kTextProto) {
      config_parser_options.uhmm_offline_data_path_txtpb =
          config.uhmm_offline_data_path;
    } else if (config.uhmm_offline_data_format ==
               deterministic_bmc::ProtoFormat::kBinaryProto) {
      config_parser_options.uhmm_offline_data_path_pb =
          config.uhmm_offline_data_path;
    } else {
      LOG(ERROR) << "Invalid uhmm_offline_data_format: "
                 << config.uhmm_offline_data_format;
      enable_deterministic_bmc = false;
    }

    absl::StatusOr<std::unique_ptr<deterministic_bmc::OfflineConfigParser>>
        offline_config_parser = deterministic_bmc::OfflineConfigParser::Create(
            config_parser_options);
    std::unique_ptr<deterministic_bmc::OfflineConfigParser>
        offline_config_parser_ptr;
    if (!offline_config_parser.ok()) {
      LOG(ERROR) << "Uhmm is not ready for deterministic bmc, "
                    "OfflineConfigParser::Create failed with status: "
                 << offline_config_parser.status();
      enable_deterministic_bmc = false;
    } else {
      offline_config_parser_ptr = std::move(*offline_config_parser);
      if (!offline_config_parser_ptr->isUhmmConfigValid()) {
        LOG(ERROR) << "Uhmm config is not valid.";
        enable_deterministic_bmc = false;
      } else {
        // Deterministic bmc is enabled, get configs from the parser.
        absl::StatusOr<uhmm::BmcMonitoredComponentsResponse>
            bmc_monitored_components_response_status_or =
                offline_config_parser_ptr->GetBmcMonitoredComponentsResponse();
        if (!bmc_monitored_components_response_status_or.ok()) {
          // For absl::StatusOr access practice, this shall never happen as
          // we already checked isUhmmConfigValid() above.
          LOG(ERROR) << "Uhmm is not valid, getBmcMonitoredComponentsResponse "
                        "failed with status: "
                     << bmc_monitored_components_response_status_or.status();
          enable_deterministic_bmc = false;
        } else {
          bmc_monitored_components_response =
              *bmc_monitored_components_response_status_or;
        }
        // Get the I2cRoot config from the parser.
        absl::StatusOr<uhmm::I2cRoot> i2c_root_status_or =
            offline_config_parser_ptr->GetI2cRoot();
        if (!i2c_root_status_or.ok()) {
          // For absl::StatusOr access practice, this shall never happen as
          // we already checked isUhmmConfigValid() above.
          LOG(ERROR) << "Uhmm is not valid, getI2cRoot failed with status: "
                     << i2c_root_status_or.status();
          enable_deterministic_bmc = false;
        } else {
          i2c_root = *i2c_root_status_or;
        }
      }
    }
  }

  absl::flat_hash_map<
      uhmm::BmcMonitoredComponentsResponse::MonitoredComponent::ProbePath,
      std::unique_ptr<FruScanner>>
      deterministic_fru_scanners;
  if (enable_deterministic_bmc) {
    absl::flat_hash_map<
        uhmm::BmcMonitoredComponentsResponse::MonitoredComponent::ProbePath,
        std::vector<uhmm::BmcMonitoredComponentsResponse::MonitoredComponent>>
        probe_path_to_components;

    DLOG(INFO) << "Deterministic BMC: bmc_monitored_components_response: "
               << bmc_monitored_components_response;
    // Group components by probe path.
    for (const auto& component :
         bmc_monitored_components_response.monitored_components()) {
      if (component.has_probe_path()) {
        probe_path_to_components[component.probe_path()].push_back(component);
      }
    }

    // Create deterministic fru scanners for each probe path.
    for (const auto& [probe_path, components] : probe_path_to_components) {
      switch (probe_path) {
        case uhmm::BmcMonitoredComponentsResponse::MonitoredComponent::
            PROBE_PATH_I2C: {
          // TODO(haoooamazing): create the deterministic FruScannerI2c
          // here. We now still use the existing FruScannerI2c for all I2C
          // devices.
          break;
        }
        case uhmm::BmcMonitoredComponentsResponse::MonitoredComponent::
            PROBE_PATH_NCSI: {
          // Create FruScannerCable for NCSI.
          DLOG(INFO)
              << "Deterministic BMC: Creating FruScannerCable for NCSI with:"
              << components.size()
              << " components and root_dir: " << config.tlbmc_root_dir;
          milotic_tlbmc::FruScannerCable::Options fru_scanner_cable_options = {
              .root_dir = config.tlbmc_root_dir,
              .components = components,
          };
          std::unique_ptr<FruScannerCable> fru_scanner_cable =
              FruScannerCable::Create(fru_scanner_cable_options);
          deterministic_fru_scanners[probe_path] = std::move(fru_scanner_cable);
          break;
        }
        case uhmm::BmcMonitoredComponentsResponse::MonitoredComponent::
            PROBE_PATH_ADC: {
          // Create FruScannerAdc for ADC.
          DLOG(INFO)
              << "Deterministic BMC: Creating FruScannerAdc for ADC with:"
              << components.size() << " components.";
          milotic_tlbmc::FruScannerAdc::Options fru_scanner_adc_options = {
              .components = components,
          };
          std::unique_ptr<FruScannerAdc> fru_scanner_adc =
              FruScannerAdc::Create(fru_scanner_adc_options);
          deterministic_fru_scanners[probe_path] = std::move(fru_scanner_adc);
          break;
        }
        case uhmm::BmcMonitoredComponentsResponse::MonitoredComponent::
            PROBE_PATH_SMBIOS: {
          options.expected_smbios_components = components;
          break;
        }
        default:
          LOG(ERROR) << "Unsupported probe path: "
                     << uhmm::BmcMonitoredComponentsResponse::
                            MonitoredComponent::ProbePath_Name(probe_path);
      }
    }
  }

  LOG(WARNING) << "enable_deterministic_bmc: " << enable_deterministic_bmc;

  // Enable deterministic periodic fru scanning only if both deterministic bmc
  // and deterministic periodic fru scanning are enabled in the config.
  bool enable_deterministic_periodic_fru_scanning =
      enable_deterministic_bmc &&
      config.enable_deterministic_periodic_fru_scanning;

  LOG(WARNING) << "enable_deterministic_periodic_fru_scanning: "
               << enable_deterministic_periodic_fru_scanning;

  // Create FruScannerI2c instance.
  FruScannerI2c::Options fru_scanner_options;
  fru_scanner_options.root_dir = config.tlbmc_root_dir;
  fru_scanner_options.deterministic_scan = enable_deterministic_bmc;
  fru_scanner_options.i2c_root = i2c_root;
  fru_scanner_options.i2c_devices_sysfs_dir = config.tlbmc_i2c_sysfs_path;
  DLOG(INFO) << "i2c_devices_sysfs_dir: "
             << fru_scanner_options.i2c_devices_sysfs_dir;
  std::unique_ptr<FruScannerI2c> fru_scanner_i2c =
      FruScannerI2c::Create(fru_scanner_options);

  // Create FruScannerFram instance.
  FruScannerFram::Options fru_scanner_fram_options;
  std::unique_ptr<FruScannerFram> fru_scanner_fram;
  if (config.tlbmc_in_unit_test &&
      config.tlbmc_unit_test_enable_fake_fram_scanner) {
    DLOG(INFO) << "Using FakeFruScannerFram for unit test.";
    fru_scanner_fram = std::make_unique<milotic_tlbmc::FakeFruScannerFram>();
  } else {
    fru_scanner_fram = FruScannerFram::Create(fru_scanner_fram_options);
  }

  options.proto_parser = milotic_tlbmc::ProtoConfigParser::Create(
      config.tlbmc_proto_config_location);
  options.proto_parser->LoadProtoConfigs();

  std::unique_ptr<GpioCollector> gpio_collector;
  if (milotic_tlbmc::GetTlbmcConfig().gpio_collector_module().enabled()) {
    absl::StatusOr<std::unique_ptr<GpioCollector>> gpio_collector_status_or;
    if (config.tlbmc_in_unit_test &&
        config.tlbmc_unit_test_enable_fake_gpio_collector) {
      gpio_collector_status_or = FakeGpioCollector::Create();
    } else {
      gpio_collector_status_or = options.collector_factory->CreateGpioCollector(
          {.gpio_configs = options.proto_parser->GetGpioConfigs()});
    }
    if (!gpio_collector_status_or.ok()) {
      LOG(ERROR) << "Failed to create GPIO collector: "
                 << gpio_collector_status_or.status();
      return nullptr;
    }
    gpio_collector = std::move(*gpio_collector_status_or);
  }

  // TODO: b/509637698 - Migrate after the new model is ready.
  // Create FruScannerGpio instance.
  std::unique_ptr<FruScannerGpio> fru_scanner_gpio = nullptr;
  if (gpio_collector != nullptr) {
    FruScannerGpio::Options fru_scanner_gpio_options;
    auto gpio_fru_component_configs =
        options.proto_parser->GetGpioFruComponentConfigs();
    fru_scanner_gpio_options.components =
        std::vector<milotic_tlbmc::GpioFruComponent>(
            gpio_fru_component_configs.gpio_fru_components().begin(),
            gpio_fru_component_configs.gpio_fru_components().end());
    fru_scanner_gpio_options.gpio_collector = gpio_collector.get();
    absl::StatusOr<std::unique_ptr<FruScannerGpio>> fru_scanner_gpio_status_or =
        FruScannerGpio::Create(fru_scanner_gpio_options);
    if (!fru_scanner_gpio_status_or.ok()) {
      LOG(ERROR) << "Failed to create FruScannerGpio: "
                 << fru_scanner_gpio_status_or.status();
      return nullptr;
    }
    fru_scanner_gpio = std::move(*fru_scanner_gpio_status_or);
  }

  // TODO: b/526494991 - Migrate after the new model is ready.
  // Create FruScannerUsb instance if config is not empty.
  const milotic_tlbmc::UsbFruComponentConfigs usb_fru_component_configs =
      options.proto_parser->GetUsbFruComponentConfigs();
  std::unique_ptr<FruScannerUsb> fru_scanner_usb = nullptr;
  if (!usb_fru_component_configs.usb_fru_components().empty()) {
    FruScannerUsb::Options fru_scanner_usb_options = {
        .soc_path = usb_fru_component_configs.soc_path(),
        .components = std::vector<milotic_tlbmc::UsbFruComponent>(
            usb_fru_component_configs.usb_fru_components().begin(),
            usb_fru_component_configs.usb_fru_components().end()),
    };

    fru_scanner_usb = FruScannerUsb::Create(fru_scanner_usb_options);
  }

  absl::flat_hash_map<milotic_tlbmc::AdHocScannerType,
                      std::unique_ptr<FruScanner>>
      fru_scanners;
  fru_scanners[milotic_tlbmc::AdHocScannerType::SCANNER_TYPE_DEFAULT_IPMI_I2C] =
      std::move(fru_scanner_i2c);
  fru_scanners[milotic_tlbmc::AdHocScannerType::SCANNER_TYPE_CAVIUM_HSM_FRAM] =
      std::move(fru_scanner_fram);
  // Don't pass null fru scanner to the fru collector.
  if (fru_scanner_gpio != nullptr) {
    fru_scanners[milotic_tlbmc::AdHocScannerType::SCANNER_TYPE_GPIO] =
        std::move(fru_scanner_gpio);
  }
  if (fru_scanner_usb != nullptr) {
    fru_scanners[milotic_tlbmc::AdHocScannerType::SCANNER_TYPE_USB] =
        std::move(fru_scanner_usb);
  }

  std::string disable_tlbmc_file_path = config.tlbmc_disable_file;
  if (std::filesystem::exists(disable_tlbmc_file_path)) {
    LOG(WARNING) << "Forcefully disable tlbmc";
    return nullptr;
  }

  options.gpio_collector = std::move(gpio_collector);
  options.fru_scanners = std::move(fru_scanners);
  options.deterministic_fru_scanners = std::move(deterministic_fru_scanners);
  options.iio_sysfs = std::make_unique<IioSysfs>(milotic_tlbmc::IioSysfsConfig{
      .iio_sysfs_path = config.tlbmc_iio_sysfs_path});
  options.i2c_sysfs = std::make_unique<I2cSysfs>(milotic_tlbmc::I2cSysfsConfig{
      .i2c_sysfs_path = config.tlbmc_i2c_sysfs_path});
  options.i3c_sysfs = std::make_unique<I3cSysfs>(milotic_tlbmc::I3cSysfsConfig{
      .i3c_sysfs_path = config.tlbmc_i3c_sysfs_path});
  options.led_sysfs = std::make_unique<LedSysfs>(milotic_tlbmc::LedSysfsConfig{
      .led_sysfs_path = config.tlbmc_led_sysfs_path});
  options.peci_sysfs =
      std::make_unique<PeciSysfs>(milotic_tlbmc::PeciSysfsConfig{
          .peci_sysfs_path = config.tlbmc_peci_sysfs_path});
  options.config_location = config.tlbmc_entity_config_location;
  options.root_path = config.tlbmc_root_dir;
  options.tlbmc_unit_test_enable_fake_gpio_collector =
      config.tlbmc_unit_test_enable_fake_gpio_collector;
  options.smbios_single_host_file_path = config.smbios_single_host_file_path;
  options.smbios_multihost_host_file_path_prefix =
      config.smbios_multihost_host_file_path_prefix;
  options.smbios_single_host_status_file_path =
      config.smbios_single_host_status_file_path;
  options.smbios_multihost_host_status_file_path_prefix =
      config.smbios_multihost_host_status_file_path_prefix;

  // Create SmbiosCodec
  platforms::gbmc::hal::SmbiosCodecConfig codec_config;
  absl::StatusOr<std::shared_ptr<platforms::gbmc::hal::SmbiosCodec>>
      smbios_codec = platforms::gbmc::hal::SmbiosCodecRegistry::Create(
          "SmbiosCodec", codec_config);
  if (!smbios_codec.ok()) {
    LOG(ERROR) << "Failed to create SmbiosCodec: " << smbios_codec.status();
  } else {
    // Create SmbiosInventory
    platforms::gbmc::hal::SmbiosInventoryConfig inventory_config;
    inventory_config.codec = smbios_codec->get();
    inventory_config.search_paths = config.smbios_search_paths;

    absl::StatusOr<std::shared_ptr<platforms::gbmc::hal::SmbiosInventory>>
        smbios_inventory =
            platforms::gbmc::hal::SmbiosInventoryRegistry::Create(
                "SmbiosInventory", inventory_config);
    if (!smbios_inventory.ok()) {
      LOG(ERROR) << "Failed to create SmbiosInventory: "
                 << smbios_inventory.status();
    } else {
      options.smbios_inventory = *std::move(smbios_inventory);
      options.smbios_codec = *std::move(smbios_codec);
    }
  }

  options.private_key_path = config.private_key_path;
  options.cert_path = config.own_cert_path;
  options.trust_bundle_path = config.trust_bundle_path;
  options.trust_bundle_signature_path = config.trust_bundle_signature_path;
  options.owner_verification_cert_path = config.owner_verification_cert_path;
  options.owner_verification_config_path =
      config.owner_verification_config_path;
  options.bmc_ssh_trusted_user_ca_keys_path =
      config.bmc_ssh_trusted_user_ca_keys_path;
  options.os_verification_cert_path = config.os_verification_cert_path;
  options.os_verification_key_path = config.os_verification_key_path;
  options.serial_console_trusted_user_ca_keys_path =
      config.serial_console_trusted_user_ca_keys_path;
  options.serial_console_detatched_signature_path =
      config.serial_console_detatched_signature_path;
  options.syslog_client_conf_override_path =
      config.syslog_client_conf_override_path;
  options.syslog_root_cert_path = config.syslog_root_cert_path;
  options.offline_node_entities_path = config.offline_node_entity_path;
  options.enable_deterministic_bmc = enable_deterministic_bmc;
  options.enable_deterministic_periodic_fru_scanning =
      enable_deterministic_periodic_fru_scanning;
  options.periodic_deterministic_fru_scan_interval_ms =
      config.periodic_deterministic_fru_scan_interval_ms;
  options.system_registry = config.system_registry;
  options.enable_hft_test_sensor = config.enable_hft_test_sensor;
  options.credential_manager = config.credential_manager;

  if (config.nic_accessor_factory != nullptr) {
    options.nic_accessor_factory =
        [factory = config.nic_accessor_factory](
            ::milotic_tlbmc::nic_veeprom::NicTelemetryVersion version, int bus,
            int address)
        -> std::unique_ptr<::milotic_tlbmc::nic_veeprom::Accessor> {
      return (*factory)(version, bus, address);
    };
  }

  if (config.tlbmc_in_unit_test && config.executor_command_map.has_value()) {
    options.executor_command_map = *config.executor_command_map;
  }

  absl::StatusOr<std::unique_ptr<milotic_tlbmc::StoreImpl>> tlbmc_store =
      milotic_tlbmc::StoreImpl::Create(std::move(options));
  if (tlbmc_store.ok()) {
    std::vector<std::string> all_shm_sensor_keys =
        (*tlbmc_store)->GetAllSharedMemorySensorKeys();
    absl::Status shm_init_status =
        !config.tlbmc_in_unit_test
            ? StaticSharedMemoryServer::InitializeSharedMemory(
                  all_shm_sensor_keys)
            : StaticSharedMemoryServer::InitializeSharedMemoryForUnitTest(
                  all_shm_sensor_keys);

    if (!shm_init_status.ok()) {
      // Shared memory initialization can fail due to various reasons, such
      // as insufficient permissions, resource limits (e.g., running out of
      // memory or exceeding the maximum number of segments), or conflicts
      // with existing segments. This is not treated as a fatal error for
      // bmcweb, but sensor collection via shared memory will not work.
      LOG(WARNING) << "Failed to initialize shared memory segment: "
                   << shm_init_status;
    }

    if (config.tlbmc_in_unit_test) {
      StaticSharedMemoryServer::SetupInstanceForUnitTest();
      StaticSharedMemoryClient::SetupInstanceForUnitTest();
    }
    // Start the sensor & thermal collection after the shared memory server is
    // initialized.
    (*tlbmc_store)->StartSensorCollection();
    (*tlbmc_store)->StartThermalCollection();

    // Schedule periodic deterministic FRU scanning.
    (*tlbmc_store)->GetFruCollector()->SetUpPeriodicDeterministicFruScanning();
    LOG(WARNING) << "tlbmc enabled with real store";
    auto tlbmc_app =
        std::make_unique<milotic_tlbmc::RedfishApp>(std::move(*tlbmc_store));
    if (!config.tlbmc_defer_router_registration_and_validation) {
      RegisterTlbmcRoutesAndValidate(tlbmc_app.get(), config.tlbmc_root_dir);
    }
    return tlbmc_app;
  }
  LOG(ERROR) << "Cannot create tlBMC store!! Error: " << tlbmc_store.status()
             << " - Enabling tlBMC with dummy store.";
  auto store = std::make_unique<milotic_tlbmc::EmptyStore>();
  auto tlbmc_app =
      std::make_unique<milotic_tlbmc::RedfishApp>(std::move(store));
  if (!config.tlbmc_defer_router_registration_and_validation) {
    RegisterTlbmcRoutesAndValidate(tlbmc_app.get(), config.tlbmc_root_dir);
  }
  return tlbmc_app;
}

GrpcRedfishService::GrpcRedfishService(
    App* app, const milotic_tlbmc::RedfishApp* tlbmc_app,
    const std::shared_ptr<boost::asio::io_context>& io_context_main_thread,
    const std::shared_ptr<boost::asio::io_context>& io_context_worker_threads,
    const RedfishServiceConfig& config,
    ecclesia::SubscriptionService* subscription_service)
    : cert_provider_(
          std::make_unique<::milotic::redfish::BmcWebCertProviderImpl>(
              config.trust_bundle_path, config.private_key_path,
              config.own_cert_path, config.self_signed_key_cert_path,
              boost::uuids::to_string(boost::uuids::random_generator()()),
              config.authority_policy_file_binary,
              /*enable_insecure_server=*/config.enable_insecure_server,
              /*check_loas3_policy=*/config.check_loas3_policy)),
      config_(config),
      subscription_service_(subscription_service) {
  using ::milotic::authz::BmcWebAuthorizerSingleton;
  using ::milotic::redfish::BmcWebCertProvider;
  using ::milotic::redfish::BmcWebCertProviderImpl;
  using ::milotic::redfish::GetCredentialsWithoutAuthz;
  using ::milotic_fast_sanity::FruServiceImpl;
  using ::milotic_hft::HftServiceImpl;
  using ::milotic_hft::HighFrequencySensorReading;
  using ::milotic_hft::HighFrequencySensorsReadings;
  using ::milotic_hft::Payload;
  using ::milotic_hft::SubscriptionManager;
  using ::milotic_hft::SubscriptionManagerFake;
  using ::milotic_hft::SubscriptionManagerImpl;
  using ::milotic_tlbmc::StoreHftAdapter;

  LOG(WARNING) << "Start gRPC server...";
  LOG(WARNING) << "Initialize authorization layer...";
#ifdef ENABLE_LOAS3_VALIDATION
  security::SetCertificateAuthorityPolicyFilePath(
      config_.authority_policy_file_binary);
#endif
  BmcWebAuthorizerSingleton::Initialize(
      {
          .configuration_path = config_.authz_config_path,
          .platform_configuration_path = config_.authz_platform_config_path,
          .base_privileges_folder = config_.persistent_base_privileges_folder,
          .pattern_entity_overrides_path =
              config.pattern_to_entity_overrides_path,
          .offline_node_entities_path = config.offline_node_entity_path,
          .google_machine_identity_path = config_.gmi_file_path,
          .tlbmc_trust_bundle_install_module_is_enabled =
              milotic_tlbmc::GetTlbmcConfig()
                  .trust_bundle_install_module()
                  .enabled(),
      },
      /*oauth_key_path=*/config.oauth_key_path);
  if (!BmcWebAuthorizerSingleton::GetInstance()
           .IsBasePrivilegeRegistryFound()) {
    LOG(WARNING)
        << "Could not find Privilege Registry at /var/google/authz_policies";
    BmcWebAuthorizerSingleton::GetInstance().SetBasePrivilegesFolder(
        config_.rofs_base_privileges_folder);
  }

  if (milotic_tlbmc::GetTlbmcConfig().redfish_rate_limiter_module().enabled() &&
      tlbmc_app != nullptr) {
    rate_limiter_ = std::make_unique<crow::RateLimiter>(
        milotic_tlbmc::RateLimiterConfig::GetConfig(), config.clock);
    const_cast<milotic_tlbmc::RedfishApp*>(tlbmc_app)
        ->SetRateLimiterUpdateCallback(
            [this](const milotic_tlbmc::RedfishRateLimiterModule& config) {
              if (rate_limiter_) {
                rate_limiter_->UpdateConfig(config);
              }
            });
  }

  LOG(WARNING) << "Authorization layer initialized!";
  grpc::reflection::InitProtoReflectionServerBuilderPlugin();
  grpc::ServerBuilder builder;

  if (config_.enable_insecure_server) {
    builder.AddListeningPort("[::]:" + std::to_string(config_.port),
                             grpc::InsecureServerCredentials());
  } else {
    builder.AddListeningPort(
        "[::]:" + std::to_string(config_.port),
        GetCredentialsWithoutAuthz(*cert_provider_, config_.crl_directory));
  }

  service_ = std::make_unique<internal::RedfishV1Impl>(
      app, tlbmc_app, io_context_main_thread, io_context_worker_threads,
      *cert_provider_, config_, subscription_service_, rate_limiter_.get());

  std::unique_ptr<SubscriptionManager> subscription_manager;
  if (config_.enable_hft_fake_manager) {
    auto fake_manager = std::make_unique<SubscriptionManagerFake>();
    Payload payload;
    HighFrequencySensorsReadings* readings =
        payload.mutable_high_frequency_sensors_readings_batch()
            ->add_high_frequency_sensors();
    readings->mutable_sensor_identifier()->set_name("test_sensor");
    HighFrequencySensorReading* timestamped_reading =
        readings->add_timestamped_readings();
    timestamped_reading->set_timestamp_ns(1234567890);
    timestamped_reading->set_float_reading(1.23456789f);
    fake_manager->SetFakeData(std::move(payload));
    subscription_manager = std::move(fake_manager);
  } else if (tlbmc_app != nullptr) {
    absl::StatusOr<std::unique_ptr<milotic_hft::DataSource>> data_source =
        milotic_tlbmc::StoreHftAdapter::Create(tlbmc_app->GetStore());
    if (data_source.ok()) {
      subscription_manager = milotic_hft::SubscriptionManagerImpl::Create(
          std::move(*data_source),
          std::make_unique<milotic_tlbmc::HftTaskSchedulerAdapter>());
    } else {
      LOG(ERROR) << "Failed to create hft source adapter: "
                 << data_source.status();
    }
  }

  if (subscription_manager != nullptr && config_.enable_hft) {
    milotic_hft::HftServiceOptions hft_options;
    hft_options.is_serving_allowed = [cert_provider = cert_provider_.get()]() {
      return cert_provider != nullptr &&
             cert_provider->GetServerStatus() ==
                 ::milotic::redfish::BmcWebCertProvider::ServerStatus::
                     kWithRootCertsAndProdSignedCert;
    };
    hft_service_ = std::make_unique<milotic_hft::HftServiceImpl>(
        std::move(hft_options), std::move(subscription_manager),
        &::milotic::authz::BmcWebAuthorizerSingleton::GetInstance()
             .GetRedfishAuthorizer());
    builder.RegisterService(hft_service_.get());
    // TODO(nanzhou): better abstraction so tlbmc_app becomes a real frontend
    // and owns the hft service.
    // The const_cast is safe because we access the pointer before any URLs
    // start to be handled.
    if (tlbmc_app != nullptr) {
      const_cast<milotic_tlbmc::RedfishApp*>(tlbmc_app)->SetHftService(
          hft_service_.get());
    }
  }

  if (config_.enable_fast_sanity) {
    milotic_fast_sanity::FruServiceOptions fru_service_options{
        .cert_provider = cert_provider_.get(),
    };
    if (tlbmc_app != nullptr &&
        tlbmc_app->GetStore()->IsDeterministicBmcEnabled()) {
      fru_service_options.enable_deterministic_bmc = true;
      fru_service_options.fru_collector =
          tlbmc_app->GetStore()->GetFruCollector();
    } else if (config_
                   .tlbmc_unit_test_enable_fake_fru_collector_for_fast_sanity) {
      fru_service_options.enable_deterministic_bmc = true;
      static auto* fake_fru_collector =
          new milotic_tlbmc::FakeFruCollectorForTest();
      fru_service_options.fru_collector = fake_fru_collector;
    }

#ifdef UNIT_TEST_BUILD
    fru_service_options_ = fru_service_options;
#endif

    fru_service_ = std::make_unique<milotic_fast_sanity::FruServiceImpl>(
        app, fru_service_options);
    builder.RegisterService(fru_service_.get());
    LOG(WARNING) << "Fast-Sanity is enabled.";
  }

  builder.RegisterService(service_.get());
  // Set max message size to 500MB, this is to allow large request like Firmware
  // Update.
  constexpr int k500MB = 500 * 1024 * 1024;
  builder.AddChannelArgument(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH, k500MB);
  builder.AddChannelArgument(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, k500MB);

  // Set keepalive to kill zombie connections as buildup of connections can lead
  // to fd exhaustion. Keepalive will be sent every 2 hours by default.
  builder.AddChannelArgument(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS, 1);
  server_ = builder.BuildAndStart();
}

}  // namespace milotic

#pragma GCC diagnostic pop
