-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
grpc: utilities for inter-converting grpc::ByteBuffer and Buffer::Ins…
…tance. (#6732) Add utilities for converting between grpc::ByteBuffer and Buffer::Instance and for adding gRPC frame headers to Buffer::Instances. This is in support for proving raw (Buffer::Instance) gRPC support which is in support of #4272. This PR also renames Grpc::Common::serializeBody to Grpc::Common::serializeToGrpcFrame which is a better description of the actual behavior as per comments on #6525, Risk Level: low Testing: Complete unit tests provided. Signed-off-by: John Plevyak <jplevyak@gmail.com>
- Loading branch information
Showing
17 changed files
with
334 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
#include "common/grpc/google_grpc_utils.h" | ||
|
||
#include <atomic> | ||
#include <cstdint> | ||
#include <cstring> | ||
#include <string> | ||
|
||
#include "common/buffer/buffer_impl.h" | ||
#include "common/common/assert.h" | ||
#include "common/common/empty_string.h" | ||
#include "common/common/enum_to_int.h" | ||
#include "common/common/fmt.h" | ||
#include "common/common/macros.h" | ||
#include "common/common/stack_array.h" | ||
#include "common/common/utility.h" | ||
|
||
#include "absl/strings/match.h" | ||
|
||
namespace Envoy { | ||
namespace Grpc { | ||
|
||
struct BufferInstanceContainer { | ||
BufferInstanceContainer(int ref_count, Buffer::InstancePtr&& buffer) | ||
: ref_count_(ref_count), buffer_(std::move(buffer)) {} | ||
std::atomic<uint32_t> ref_count_; // In case gPRC dereferences in a different threads. | ||
Buffer::InstancePtr buffer_; | ||
|
||
static void derefBufferInstanceContainer(void* container_ptr) { | ||
auto container = static_cast<BufferInstanceContainer*>(container_ptr); | ||
container->ref_count_--; | ||
// This is safe because the ref_count_ is never incremented. | ||
if (container->ref_count_ <= 0) { | ||
delete container; | ||
} | ||
} | ||
}; | ||
|
||
grpc::ByteBuffer GoogleGrpcUtils::makeByteBuffer(Buffer::InstancePtr&& buffer_instance) { | ||
if (!buffer_instance) { | ||
return {}; | ||
} | ||
Buffer::RawSlice on_raw_slice; | ||
// NB: we need to pass in >= 1 in order to get the real "n" (see Buffer::Instance for details). | ||
const int n_slices = buffer_instance->getRawSlices(&on_raw_slice, 1); | ||
if (n_slices <= 0) { | ||
return {}; | ||
} | ||
auto* container = new BufferInstanceContainer{n_slices, std::move(buffer_instance)}; | ||
if (n_slices == 1) { | ||
grpc::Slice one_slice(on_raw_slice.mem_, on_raw_slice.len_, | ||
&BufferInstanceContainer::derefBufferInstanceContainer, container); | ||
return {&one_slice, 1}; | ||
} | ||
STACK_ARRAY(many_raw_slices, Buffer::RawSlice, n_slices); | ||
container->buffer_->getRawSlices(many_raw_slices.begin(), n_slices); | ||
std::vector<grpc::Slice> slices; | ||
slices.reserve(n_slices); | ||
for (int i = 0; i < n_slices; i++) { | ||
slices.emplace_back(many_raw_slices[i].mem_, many_raw_slices[i].len_, | ||
&BufferInstanceContainer::derefBufferInstanceContainer, container); | ||
} | ||
return {&slices[0], slices.size()}; | ||
} | ||
|
||
struct ByteBufferContainer { | ||
ByteBufferContainer(int ref_count) : ref_count_(ref_count) {} | ||
~ByteBufferContainer() { ::free(fragments_); } | ||
uint32_t ref_count_; | ||
Buffer::BufferFragmentImpl* fragments_ = nullptr; | ||
std::vector<grpc::Slice> slices_; | ||
}; | ||
|
||
Buffer::InstancePtr GoogleGrpcUtils::makeBufferInstance(const grpc::ByteBuffer& byte_buffer) { | ||
auto buffer = std::make_unique<Buffer::OwnedImpl>(); | ||
if (byte_buffer.Length() == 0) { | ||
return buffer; | ||
} | ||
// NB: ByteBuffer::Dump moves the data out of the ByteBuffer so we need to ensure that the | ||
// lifetime of the Slice(s) exceeds our Buffer::Instance. | ||
std::vector<grpc::Slice> slices; | ||
byte_buffer.Dump(&slices); | ||
auto* container = new ByteBufferContainer(static_cast<int>(slices.size())); | ||
std::function<void(const void*, size_t, const Buffer::BufferFragmentImpl*)> releaser = | ||
[container](const void*, size_t, const Buffer::BufferFragmentImpl*) { | ||
container->ref_count_--; | ||
if (container->ref_count_ <= 0) { | ||
delete container; | ||
} | ||
}; | ||
// NB: addBufferFragment takes a pointer alias to the BufferFragmentImpl which is passed in so we | ||
// need to ensure that the lifetime of those objects exceeds that of the Buffer::Instance. | ||
RELEASE_ASSERT(!::posix_memalign(reinterpret_cast<void**>(&container->fragments_), | ||
alignof(Buffer::BufferFragmentImpl), | ||
sizeof(Buffer::BufferFragmentImpl) * slices.size()), | ||
"posix_memalign failure"); | ||
for (size_t i = 0; i < slices.size(); i++) { | ||
new (&container->fragments_[i]) | ||
Buffer::BufferFragmentImpl(slices[i].begin(), slices[i].size(), releaser); | ||
} | ||
for (size_t i = 0; i < slices.size(); i++) { | ||
buffer->addBufferFragment(container->fragments_[i]); | ||
} | ||
container->slices_ = std::move(slices); | ||
return buffer; | ||
} | ||
|
||
} // namespace Grpc | ||
} // namespace Envoy |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
#pragma once | ||
|
||
#include <cstdint> | ||
#include <string> | ||
|
||
#include "envoy/buffer/buffer.h" | ||
|
||
#include "grpcpp/grpcpp.h" | ||
|
||
namespace Envoy { | ||
namespace Grpc { | ||
|
||
class GoogleGrpcUtils { | ||
public: | ||
/** | ||
* Build grpc::ByteBuffer which aliases the data in a Buffer::InstancePtr. | ||
* @param buffer source data container. | ||
* @return byteBuffer target container aliased to the data in Buffer::Instance and owning the | ||
* Buffer::Instance. | ||
*/ | ||
static grpc::ByteBuffer makeByteBuffer(Buffer::InstancePtr&& buffer); | ||
|
||
/** | ||
* Build Buffer::Instance which aliases the data in a grpc::ByteBuffer. | ||
* @param buffer source data container. | ||
* @return a Buffer::InstancePtr aliased to the data in the provided grpc::ByteBuffer and | ||
* owning the corresponding grpc::Slice(s). | ||
*/ | ||
static Buffer::InstancePtr makeBufferInstance(const grpc::ByteBuffer& buffer); | ||
}; | ||
|
||
} // namespace Grpc | ||
} // namespace Envoy |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.