• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 2017 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #ifndef GRPCPP_IMPL_CODEGEN_BYTE_BUFFER_H
20 #define GRPCPP_IMPL_CODEGEN_BYTE_BUFFER_H
21 
22 #include <grpc/impl/codegen/byte_buffer.h>
23 
24 #include <grpcpp/impl/codegen/config.h>
25 #include <grpcpp/impl/codegen/core_codegen_interface.h>
26 #include <grpcpp/impl/codegen/serialization_traits.h>
27 #include <grpcpp/impl/codegen/slice.h>
28 #include <grpcpp/impl/codegen/status.h>
29 
30 #include <vector>
31 
32 namespace grpc {
33 
34 class ServerInterface;
35 class ByteBuffer;
36 class ServerInterface;
37 
38 namespace internal {
39 template <class RequestType, class ResponseType>
40 class CallbackUnaryHandler;
41 template <class RequestType, class ResponseType>
42 class CallbackServerStreamingHandler;
43 template <class RequestType>
44 void* UnaryDeserializeHelper(grpc_call*, grpc_byte_buffer*, ::grpc::Status*,
45                              RequestType*);
46 template <class ServiceType, class RequestType, class ResponseType>
47 class ServerStreamingHandler;
48 template <::grpc::StatusCode code>
49 class ErrorMethodHandler;
50 class CallOpSendMessage;
51 template <class R>
52 class CallOpRecvMessage;
53 class CallOpGenericRecvMessage;
54 class ExternalConnectionAcceptorImpl;
55 template <class R>
56 class DeserializeFuncType;
57 class GrpcByteBufferPeer;
58 
59 }  // namespace internal
60 /// A sequence of bytes.
61 class ByteBuffer final {
62  public:
63   /// Constuct an empty buffer.
ByteBuffer()64   ByteBuffer() : buffer_(nullptr) {}
65 
66   /// Construct buffer from \a slices, of which there are \a nslices.
ByteBuffer(const Slice * slices,size_t nslices)67   ByteBuffer(const Slice* slices, size_t nslices) {
68     // The following assertions check that the representation of a grpc::Slice
69     // is identical to that of a grpc_slice:  it has a grpc_slice field, and
70     // nothing else.
71     static_assert(std::is_same<decltype(slices[0].slice_), grpc_slice>::value,
72                   "Slice must have same representation as grpc_slice");
73     static_assert(sizeof(Slice) == sizeof(grpc_slice),
74                   "Slice must have same representation as grpc_slice");
75     // The following assertions check that the representation of a ByteBuffer is
76     // identical to grpc_byte_buffer*:  it has a grpc_byte_buffer* field,
77     // and nothing else.
78     static_assert(std::is_same<decltype(buffer_), grpc_byte_buffer*>::value,
79                   "ByteBuffer must have same representation as "
80                   "grpc_byte_buffer*");
81     static_assert(sizeof(ByteBuffer) == sizeof(grpc_byte_buffer*),
82                   "ByteBuffer must have same representation as "
83                   "grpc_byte_buffer*");
84     // The const_cast is legal if grpc_raw_byte_buffer_create() does no more
85     // than its advertised side effect of increasing the reference count of the
86     // slices it processes, and such an increase does not affect the semantics
87     // seen by the caller of this constructor.
88     buffer_ = g_core_codegen_interface->grpc_raw_byte_buffer_create(
89         reinterpret_cast<grpc_slice*>(const_cast<Slice*>(slices)), nslices);
90   }
91 
92   /// Constuct a byte buffer by referencing elements of existing buffer
93   /// \a buf. Wrapper of core function grpc_byte_buffer_copy . This is not
94   /// a deep copy; it is just a referencing. As a result, its performance is
95   /// size-independent.
ByteBuffer(const ByteBuffer & buf)96   ByteBuffer(const ByteBuffer& buf) : buffer_(nullptr) { operator=(buf); }
97 
~ByteBuffer()98   ~ByteBuffer() {
99     if (buffer_) {
100       g_core_codegen_interface->grpc_byte_buffer_destroy(buffer_);
101     }
102   }
103 
104   /// Wrapper of core function grpc_byte_buffer_copy . This is not
105   /// a deep copy; it is just a referencing. As a result, its performance is
106   /// size-independent.
107   ByteBuffer& operator=(const ByteBuffer& buf) {
108     if (this != &buf) {
109       Clear();  // first remove existing data
110     }
111     if (buf.buffer_) {
112       // then copy
113       buffer_ = g_core_codegen_interface->grpc_byte_buffer_copy(buf.buffer_);
114     }
115     return *this;
116   }
117 
118   /// Dump (read) the buffer contents into \a slices.
119   Status Dump(std::vector<Slice>* slices) const;
120 
121   /// Remove all data.
Clear()122   void Clear() {
123     if (buffer_) {
124       g_core_codegen_interface->grpc_byte_buffer_destroy(buffer_);
125       buffer_ = nullptr;
126     }
127   }
128 
129   /// Make a duplicate copy of the internals of this byte
130   /// buffer so that we have our own owned version of it.
131   /// bbuf.Duplicate(); is equivalent to bbuf=bbuf; but is actually readable.
132   /// This is not a deep copy; it is a referencing and its performance
133   /// is size-independent.
Duplicate()134   void Duplicate() {
135     buffer_ = g_core_codegen_interface->grpc_byte_buffer_copy(buffer_);
136   }
137 
138   /// Forget underlying byte buffer without destroying
139   /// Use this only for un-owned byte buffers
Release()140   void Release() { buffer_ = nullptr; }
141 
142   /// Buffer size in bytes.
Length()143   size_t Length() const {
144     return buffer_ == nullptr
145                ? 0
146                : g_core_codegen_interface->grpc_byte_buffer_length(buffer_);
147   }
148 
149   /// Swap the state of *this and *other.
Swap(ByteBuffer * other)150   void Swap(ByteBuffer* other) {
151     grpc_byte_buffer* tmp = other->buffer_;
152     other->buffer_ = buffer_;
153     buffer_ = tmp;
154   }
155 
156   /// Is this ByteBuffer valid?
Valid()157   bool Valid() const { return (buffer_ != nullptr); }
158 
159  private:
160   friend class SerializationTraits<ByteBuffer, void>;
161   friend class ServerInterface;
162   friend class internal::CallOpSendMessage;
163   template <class R>
164   friend class internal::CallOpRecvMessage;
165   friend class internal::CallOpGenericRecvMessage;
166   template <class RequestType>
167   friend void* internal::UnaryDeserializeHelper(grpc_call*, grpc_byte_buffer*,
168                                                 ::grpc::Status*, RequestType*);
169   template <class ServiceType, class RequestType, class ResponseType>
170   friend class internal::ServerStreamingHandler;
171   template <class RequestType, class ResponseType>
172   friend class internal::CallbackUnaryHandler;
173   template <class RequestType, class ResponseType>
174   friend class internal::CallbackServerStreamingHandler;
175   template <StatusCode code>
176   friend class internal::ErrorMethodHandler;
177   template <class R>
178   friend class internal::DeserializeFuncType;
179   friend class ProtoBufferReader;
180   friend class ProtoBufferWriter;
181   friend class internal::GrpcByteBufferPeer;
182   friend class internal::ExternalConnectionAcceptorImpl;
183 
184   grpc_byte_buffer* buffer_;
185 
186   // takes ownership
set_buffer(grpc_byte_buffer * buf)187   void set_buffer(grpc_byte_buffer* buf) {
188     if (buffer_) {
189       Clear();
190     }
191     buffer_ = buf;
192   }
193 
c_buffer()194   grpc_byte_buffer* c_buffer() { return buffer_; }
c_buffer_ptr()195   grpc_byte_buffer** c_buffer_ptr() { return &buffer_; }
196 
197   class ByteBufferPointer {
198    public:
199     /* NOLINTNEXTLINE(google-explicit-constructor) */
ByteBufferPointer(const ByteBuffer * b)200     ByteBufferPointer(const ByteBuffer* b)
201         : bbuf_(const_cast<ByteBuffer*>(b)) {}
202     /* NOLINTNEXTLINE(google-explicit-constructor) */
203     operator ByteBuffer*() { return bbuf_; }
204     /* NOLINTNEXTLINE(google-explicit-constructor) */
205     operator grpc_byte_buffer*() { return bbuf_->buffer_; }
206     /* NOLINTNEXTLINE(google-explicit-constructor) */
207     operator grpc_byte_buffer**() { return &bbuf_->buffer_; }
208 
209    private:
210     ByteBuffer* bbuf_;
211   };
bbuf_ptr()212   ByteBufferPointer bbuf_ptr() const { return ByteBufferPointer(this); }
213 };
214 
215 template <>
216 class SerializationTraits<ByteBuffer, void> {
217  public:
Deserialize(ByteBuffer * byte_buffer,ByteBuffer * dest)218   static Status Deserialize(ByteBuffer* byte_buffer, ByteBuffer* dest) {
219     dest->set_buffer(byte_buffer->buffer_);
220     return Status::OK;
221   }
Serialize(const ByteBuffer & source,ByteBuffer * buffer,bool * own_buffer)222   static Status Serialize(const ByteBuffer& source, ByteBuffer* buffer,
223                           bool* own_buffer) {
224     *buffer = source;
225     *own_buffer = true;
226     return g_core_codegen_interface->ok();
227   }
228 };
229 
230 }  // namespace grpc
231 
232 #endif  // GRPCPP_IMPL_CODEGEN_BYTE_BUFFER_H
233