LCOV - code coverage report
Current view: top level - source/common/grpc - google_grpc_utils.cc (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 49 83 59.0 %
Date: 2024-01-05 06:35:25 Functions: 6 11 54.5 %

          Line data    Source code
       1             : #include "source/common/grpc/google_grpc_utils.h"
       2             : 
       3             : #include <atomic>
       4             : #include <cstdint>
       5             : #include <cstring>
       6             : #include <string>
       7             : 
       8             : #include "envoy/grpc/google_grpc_creds.h"
       9             : #include "envoy/registry/registry.h"
      10             : 
      11             : #include "source/common/buffer/buffer_impl.h"
      12             : #include "source/common/common/assert.h"
      13             : #include "source/common/common/empty_string.h"
      14             : #include "source/common/common/enum_to_int.h"
      15             : #include "source/common/common/fmt.h"
      16             : #include "source/common/common/macros.h"
      17             : #include "source/common/common/utility.h"
      18             : 
      19             : #include "absl/container/fixed_array.h"
      20             : #include "absl/strings/match.h"
      21             : 
      22             : namespace Envoy {
      23             : namespace Grpc {
      24             : 
      25             : namespace {
      26             : 
      27             : std::shared_ptr<grpc::ChannelCredentials>
      28             : getGoogleGrpcChannelCredentials(const envoy::config::core::v3::GrpcService& grpc_service,
      29           2 :                                 Api::Api& api) {
      30           2 :   GoogleGrpcCredentialsFactory* credentials_factory = nullptr;
      31           2 :   const std::string& google_grpc_credentials_factory_name =
      32           2 :       grpc_service.google_grpc().credentials_factory_name();
      33           2 :   if (google_grpc_credentials_factory_name.empty()) {
      34           2 :     credentials_factory = Registry::FactoryRegistry<GoogleGrpcCredentialsFactory>::getFactory(
      35           2 :         "envoy.grpc_credentials.default");
      36           2 :   } else {
      37           0 :     credentials_factory = Registry::FactoryRegistry<GoogleGrpcCredentialsFactory>::getFactory(
      38           0 :         google_grpc_credentials_factory_name);
      39           0 :   }
      40           2 :   if (credentials_factory == nullptr) {
      41           0 :     throw EnvoyException(absl::StrCat("Unknown google grpc credentials factory: ",
      42           0 :                                       google_grpc_credentials_factory_name));
      43           0 :   }
      44           2 :   return credentials_factory->getChannelCredentials(grpc_service, api);
      45           2 : }
      46             : 
      47             : } // namespace
      48             : 
      49             : struct BufferInstanceContainer {
      50             :   BufferInstanceContainer(int ref_count, Buffer::InstancePtr&& buffer)
      51           1 :       : ref_count_(ref_count), buffer_(std::move(buffer)) {}
      52             :   std::atomic<uint32_t> ref_count_; // In case gPRC dereferences in a different threads.
      53             :   Buffer::InstancePtr buffer_;
      54             : 
      55           1 :   static void derefBufferInstanceContainer(void* container_ptr) {
      56           1 :     auto container = static_cast<BufferInstanceContainer*>(container_ptr);
      57           1 :     container->ref_count_--;
      58             :     // This is safe because the ref_count_ is never incremented.
      59           1 :     if (container->ref_count_ <= 0) {
      60           1 :       delete container;
      61           1 :     }
      62           1 :   }
      63             : };
      64             : 
      65           1 : grpc::ByteBuffer GoogleGrpcUtils::makeByteBuffer(Buffer::InstancePtr&& buffer_instance) {
      66           1 :   if (!buffer_instance) {
      67           0 :     return {};
      68           0 :   }
      69           1 :   Buffer::RawSliceVector raw_slices = buffer_instance->getRawSlices();
      70           1 :   if (raw_slices.empty()) {
      71           0 :     return {};
      72           0 :   }
      73             : 
      74           1 :   auto* container =
      75           1 :       new BufferInstanceContainer{static_cast<int>(raw_slices.size()), std::move(buffer_instance)};
      76           1 :   std::vector<grpc::Slice> slices;
      77           1 :   slices.reserve(raw_slices.size());
      78           1 :   for (Buffer::RawSlice& raw_slice : raw_slices) {
      79           1 :     slices.emplace_back(raw_slice.mem_, raw_slice.len_,
      80           1 :                         &BufferInstanceContainer::derefBufferInstanceContainer, container);
      81           1 :   }
      82           1 :   return {&slices[0], slices.size()}; // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
      83           1 : }
      84             : 
      85             : class GrpcSliceBufferFragmentImpl : public Buffer::BufferFragment {
      86             : public:
      87           0 :   explicit GrpcSliceBufferFragmentImpl(grpc::Slice&& slice) : slice_(std::move(slice)) {}
      88             : 
      89             :   // Buffer::BufferFragment
      90           0 :   const void* data() const override { return slice_.begin(); }
      91           0 :   size_t size() const override { return slice_.size(); }
      92           0 :   void done() override { delete this; }
      93             : 
      94             : private:
      95             :   const grpc::Slice slice_;
      96             : };
      97             : 
      98           0 : Buffer::InstancePtr GoogleGrpcUtils::makeBufferInstance(const grpc::ByteBuffer& byte_buffer) {
      99           0 :   auto buffer = std::make_unique<Buffer::OwnedImpl>();
     100           0 :   if (byte_buffer.Length() == 0) {
     101           0 :     return buffer;
     102           0 :   }
     103             :   // NB: ByteBuffer::Dump moves the data out of the ByteBuffer so we need to ensure that the
     104             :   // lifetime of the Slice(s) exceeds our Buffer::Instance.
     105           0 :   std::vector<grpc::Slice> slices;
     106           0 :   if (!byte_buffer.Dump(&slices).ok()) {
     107           0 :     return nullptr;
     108           0 :   }
     109             : 
     110           0 :   for (auto& slice : slices) {
     111           0 :     buffer->addBufferFragment(*new GrpcSliceBufferFragmentImpl(std::move(slice)));
     112           0 :   }
     113           0 :   return buffer;
     114           0 : }
     115             : 
     116             : grpc::ChannelArguments
     117           2 : GoogleGrpcUtils::channelArgsFromConfig(const envoy::config::core::v3::GrpcService& config) {
     118           2 :   grpc::ChannelArguments args;
     119           2 :   for (const auto& channel_arg : config.google_grpc().channel_args().args()) {
     120           1 :     switch (channel_arg.second.value_specifier_case()) {
     121           1 :     case envoy::config::core::v3::GrpcService::GoogleGrpc::ChannelArgs::Value::kStringValue:
     122           1 :       args.SetString(channel_arg.first, channel_arg.second.string_value());
     123           1 :       break;
     124           0 :     case envoy::config::core::v3::GrpcService::GoogleGrpc::ChannelArgs::Value::kIntValue:
     125           0 :       args.SetInt(channel_arg.first, channel_arg.second.int_value());
     126           0 :       break;
     127           0 :     case envoy::config::core::v3::GrpcService::GoogleGrpc::ChannelArgs::Value::
     128           0 :         VALUE_SPECIFIER_NOT_SET:
     129           0 :       PANIC_DUE_TO_PROTO_UNSET;
     130           1 :     }
     131           1 :   }
     132           2 :   return args;
     133           2 : }
     134             : 
     135             : std::shared_ptr<grpc::Channel>
     136           2 : GoogleGrpcUtils::createChannel(const envoy::config::core::v3::GrpcService& config, Api::Api& api) {
     137           2 :   std::shared_ptr<grpc::ChannelCredentials> creds = getGoogleGrpcChannelCredentials(config, api);
     138           2 :   const grpc::ChannelArguments args = channelArgsFromConfig(config);
     139           2 :   return CreateCustomChannel(config.google_grpc().target_uri(), creds, args);
     140           2 : }
     141             : 
     142             : } // namespace Grpc
     143             : } // namespace Envoy

Generated by: LCOV version 1.15