diff --git a/mobile/library/cc/BUILD b/mobile/library/cc/BUILD index fce829345778..e09ff75df02b 100644 --- a/mobile/library/cc/BUILD +++ b/mobile/library/cc/BUILD @@ -6,6 +6,12 @@ envoy_package() envoy_cc_library( name = "envoy_engine_cc_lib", + srcs = [ + "log_level.cc", + "request_method.cc", + "retry_policy.cc", + "upstream_http_protocol.h", + ], hdrs = [ "bridge_utility.h", "engine.h", diff --git a/mobile/library/cc/log_level.cc b/mobile/library/cc/log_level.cc new file mode 100644 index 000000000000..737b463183d2 --- /dev/null +++ b/mobile/library/cc/log_level.cc @@ -0,0 +1,35 @@ +#include "log_level.h" + +#include + +namespace Envoy { +namespace Platform { + +static const std::pair LOG_LEVEL_LOOKUP[]{ + {LogLevel::trace, "trace"}, {LogLevel::debug, "debug"}, {LogLevel::info, "info"}, + {LogLevel::warn, "warn"}, {LogLevel::error, "error"}, {LogLevel::critical, "critical"}, + {LogLevel::off, "off"}, +}; + +std::string log_level_to_string(LogLevel method) { + for (const auto& pair : LOG_LEVEL_LOOKUP) { + if (pair.first == method) { + return pair.second; + } + } + + throw std::out_of_range("unknown log level type"); +} + +LogLevel log_level_from_string(const std::string& str) { + for (const auto& pair : LOG_LEVEL_LOOKUP) { + if (pair.second == str) { + return pair.first; + } + } + + throw std::out_of_range("unknown log level type"); +} + +} // namespace Platform +} // namespace Envoy diff --git a/mobile/library/cc/request_method.cc b/mobile/library/cc/request_method.cc new file mode 100644 index 000000000000..108dc5f433be --- /dev/null +++ b/mobile/library/cc/request_method.cc @@ -0,0 +1,37 @@ +#include "request_method.h" + +#include +#include + +namespace Envoy { +namespace Platform { + +static const std::pair REQUEST_METHOD_LOOKUP[]{ + {RequestMethod::DELETE, "DELETE"}, {RequestMethod::GET, "GET"}, + {RequestMethod::HEAD, "HEAD"}, {RequestMethod::OPTIONS, "OPTIONS"}, + {RequestMethod::PATCH, "PATCH"}, {RequestMethod::POST, "POST"}, + {RequestMethod::PUT, "PUT"}, {RequestMethod::TRACE, "TRACE"}, +}; + +std::string request_method_to_string(RequestMethod method) { + for (const auto& pair : REQUEST_METHOD_LOOKUP) { + if (pair.first == method) { + return pair.second; + } + } + + throw std::out_of_range("unknown request method type"); +} + +RequestMethod request_method_from_string(const std::string& str) { + for (const auto& pair : REQUEST_METHOD_LOOKUP) { + if (pair.second == str) { + return pair.first; + } + } + + throw std::out_of_range("unknown request method type"); +} + +} // namespace Platform +} // namespace Envoy diff --git a/mobile/library/cc/retry_policy.cc b/mobile/library/cc/retry_policy.cc new file mode 100644 index 000000000000..17a9b96f98c9 --- /dev/null +++ b/mobile/library/cc/retry_policy.cc @@ -0,0 +1,105 @@ +#include "retry_policy.h" + +namespace Envoy { +namespace Platform { + +static const std::pair RETRY_RULE_LOOKUP[]{ + {RetryRule::Status5xx, "5xx"}, + {RetryRule::GatewayError, "gateway-error"}, + {RetryRule::ConnectFailure, "connect-failure"}, + {RetryRule::RefusedStream, "refused-stream"}, + {RetryRule::Retriable4xx, "retriable-4xx"}, + {RetryRule::RetriableHeaders, "retriable-headers"}, + {RetryRule::Reset, "reset"}, +}; + +std::string retry_rule_to_string(RetryRule retry_rule) { + for (const auto& pair : RETRY_RULE_LOOKUP) { + if (pair.first == retry_rule) { + return pair.second; + } + } + throw std::invalid_argument("invalid retry rule"); +} + +RetryRule retry_rule_from_string(const std::string& str) { + for (const auto& pair : RETRY_RULE_LOOKUP) { + if (pair.second == str) { + return pair.first; + } + } + throw std::invalid_argument("invalid retry rule"); +} + +RawHeaderMap RetryPolicy::as_raw_header_map() const { + RawHeaderMap outbound_headers{ + {"x-envoy-max-retries", {std::to_string(this->max_retry_count)}}, + {"x-envoy-upstream-rq-timeout-ms", + {std::to_string(this->total_upstream_timeout_ms.value_or(0))}}, + }; + + if (this->per_try_timeout_ms.has_value()) { + outbound_headers["x-envoy-upstream-rq-per-try-timeout-ms"] = + std::vector{std::to_string(this->per_try_timeout_ms.value())}; + } + + std::vector retry_on; + for (const auto& retry_rule : this->retry_on) { + retry_on.push_back(retry_rule_to_string(retry_rule)); + } + + if (this->retry_status_codes.size() > 0) { + retry_on.push_back("retriable-status-codes"); + std::vector retry_status_codes; + for (const auto& status_code : this->retry_status_codes) { + retry_status_codes.push_back(std::to_string(status_code)); + } + outbound_headers["x-envoy-retriable-status-codes"] = retry_status_codes; + } + + if (retry_on.size() > 0) { + outbound_headers["x-envoy-retry-on"] = retry_on; + } + + return outbound_headers; +} + +RetryPolicy RetryPolicy::from_raw_header_map(const RawHeaderMap& headers) { + RetryPolicy retry_policy; + + if (headers.contains("x-envoy-max-retries")) { + retry_policy.max_retry_count = std::stoi(headers.at("x-envoy-max-retries")[0]); + } + + if (headers.contains("x-envoy-upstream-rq-timeout-ms")) { + retry_policy.total_upstream_timeout_ms = + std::stoi(headers.at("x-envoy-upstream-rq-timeout-ms")[0]); + } + + if (headers.contains("x-envoy-upstream-rq-per-try-timeout-ms")) { + retry_policy.per_try_timeout_ms = + std::stoi(headers.at("x-envoy-upstream-rq-per-try-timeout-ms")[0]); + } + + bool has_retriable_status_codes = false; + if (headers.contains("x-envoy-retry-on")) { + for (const auto& retry_rule_str : headers.at("x-envoy-retry-on")) { + if (retry_rule_str == "retriable-status_codes") { + has_retriable_status_codes = true; + continue; + } + retry_policy.retry_on.push_back(retry_rule_from_string(retry_rule_str)); + } + } + + if (has_retriable_status_codes && headers.contains("x-envoy-retriable-status-codes")) { + for (const auto& status_code_str : headers.at("x-envoy-retriable-status-codes")) { + retry_policy.retry_status_codes.push_back(std::stoi(status_code_str)); + } + } + + return retry_policy; +} + +} // namespace Platform +} // namespace Envoy diff --git a/mobile/library/cc/upstream_http_protocol.cc b/mobile/library/cc/upstream_http_protocol.cc new file mode 100644 index 000000000000..8ca0af5a5061 --- /dev/null +++ b/mobile/library/cc/upstream_http_protocol.cc @@ -0,0 +1,32 @@ +#include "upstream_http_protocol.h" + +#include + +namespace Envoy { +namespace Platform { + +static const std::pair UPSTREAM_HTTP_PROTOCOL_LOOKUP[]{ + {UpstreamHttpProtocol::HTTP1, "http1"}, + {UpstreamHttpProtocol::HTTP2, "http2"}, +}; + +std::string upstream_http_protocol_to_string(UpstreamHttpProtocol protocol) { + for (const auto& pair : UPSTREAM_HTTP_PROTOCOL_LOOKUP) { + if (pair.first == protocol) { + return pair.second; + } + } + throw std::invalid_argument("invalid upstream http protocol"); +} + +UpstreamHttpProtocol upstream_http_protocol_from_string(const std::string& str) { + for (const auto& pair : UPSTREAM_HTTP_PROTOCOL_LOOKUP) { + if (pair.second == str) { + return pair.first; + } + } + throw std::invalid_argument("invalid upstream http protocol"); +} + +} // namespace Platform +} // namespace Envoy