aboutsummaryrefslogtreecommitdiffhomepage
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/grpc++/impl/codegen/call.h141
-rw-r--r--include/grpc++/impl/codegen/client_context.h10
-rw-r--r--include/grpc++/impl/codegen/client_unary_call.h9
-rw-r--r--include/grpc++/impl/codegen/core_codegen.h8
-rw-r--r--include/grpc++/impl/codegen/core_codegen_interface.h17
-rw-r--r--include/grpc++/impl/codegen/metadata_map.h71
-rw-r--r--include/grpc++/impl/codegen/method_handler_impl.h8
-rw-r--r--include/grpc++/impl/codegen/proto_utils.h8
-rw-r--r--include/grpc++/impl/codegen/rpc_service_method.h9
-rw-r--r--include/grpc++/impl/codegen/server_context.h5
-rw-r--r--include/grpc++/impl/codegen/server_interface.h5
-rw-r--r--include/grpc++/impl/codegen/slice.h65
-rw-r--r--include/grpc++/impl/codegen/sync_stream.h8
-rw-r--r--include/grpc++/support/byte_buffer.h3
-rw-r--r--include/grpc/census.h14
-rw-r--r--include/grpc/compression.h8
-rw-r--r--include/grpc/grpc.h10
-rw-r--r--include/grpc/impl/codegen/grpc_types.h51
-rw-r--r--include/grpc/impl/codegen/slice.h21
-rw-r--r--include/grpc/slice.h38
20 files changed, 321 insertions, 188 deletions
diff --git a/include/grpc++/impl/codegen/call.h b/include/grpc++/impl/codegen/call.h
index 475f8d11bc..a17cdf9236 100644
--- a/include/grpc++/impl/codegen/call.h
+++ b/include/grpc++/impl/codegen/call.h
@@ -45,6 +45,7 @@
#include <grpc++/impl/codegen/config.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/serialization_traits.h>
+#include <grpc++/impl/codegen/slice.h>
#include <grpc++/impl/codegen/status.h>
#include <grpc++/impl/codegen/status_helper.h>
#include <grpc++/impl/codegen/string_ref.h>
@@ -62,19 +63,6 @@ class CallHook;
class CompletionQueue;
extern CoreCodegenInterface* g_core_codegen_interface;
-inline void FillMetadataMap(
- grpc_metadata_array* arr,
- std::multimap<grpc::string_ref, grpc::string_ref>* metadata) {
- for (size_t i = 0; i < arr->count; i++) {
- // TODO(yangg) handle duplicates?
- metadata->insert(std::pair<grpc::string_ref, grpc::string_ref>(
- arr->metadata[i].key, grpc::string_ref(arr->metadata[i].value,
- arr->metadata[i].value_length)));
- }
- g_core_codegen_interface->grpc_metadata_array_destroy(arr);
- g_core_codegen_interface->grpc_metadata_array_init(arr);
-}
-
// TODO(yangg) if the map is changed before we send, the pointers will be a
// mess. Make sure it does not happen.
inline grpc_metadata* FillMetadataArray(
@@ -87,9 +75,8 @@ inline grpc_metadata* FillMetadataArray(
metadata.size() * sizeof(grpc_metadata)));
size_t i = 0;
for (auto iter = metadata.cbegin(); iter != metadata.cend(); ++iter, ++i) {
- metadata_array[i].key = iter->first.c_str();
- metadata_array[i].value = iter->second.c_str();
- metadata_array[i].value_length = iter->second.size();
+ metadata_array[i].key = SliceReferencingString(iter->first);
+ metadata_array[i].value = SliceReferencingString(iter->second);
}
return metadata_array;
}
@@ -175,7 +162,7 @@ template <int I>
class CallNoOp {
protected:
void AddOp(grpc_op* ops, size_t* nops) {}
- void FinishOp(bool* status, int max_receive_message_size) {}
+ void FinishOp(bool* status) {}
};
class CallOpSendInitialMetadata {
@@ -213,7 +200,7 @@ class CallOpSendInitialMetadata {
op->data.send_initial_metadata.maybe_compression_level.level =
maybe_compression_level_.level;
}
- void FinishOp(bool* status, int max_receive_message_size) {
+ void FinishOp(bool* status) {
if (!send_) return;
g_core_codegen_interface->gpr_free(initial_metadata_);
send_ = false;
@@ -253,7 +240,7 @@ class CallOpSendMessage {
// Flags are per-message: clear them after use.
write_options_.Clear();
}
- void FinishOp(bool* status, int max_receive_message_size) {
+ void FinishOp(bool* status) {
if (own_buf_) g_core_codegen_interface->grpc_byte_buffer_destroy(send_buf_);
send_buf_ = nullptr;
}
@@ -301,14 +288,12 @@ class CallOpRecvMessage {
op->data.recv_message.recv_message = &recv_buf_;
}
- void FinishOp(bool* status, int max_receive_message_size) {
+ void FinishOp(bool* status) {
if (message_ == nullptr) return;
if (recv_buf_) {
if (*status) {
got_message = *status =
- SerializationTraits<R>::Deserialize(recv_buf_, message_,
- max_receive_message_size)
- .ok();
+ SerializationTraits<R>::Deserialize(recv_buf_, message_).ok();
} else {
got_message = false;
g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_);
@@ -331,8 +316,7 @@ class CallOpRecvMessage {
namespace CallOpGenericRecvMessageHelper {
class DeserializeFunc {
public:
- virtual Status Deserialize(grpc_byte_buffer* buf,
- int max_receive_message_size) = 0;
+ virtual Status Deserialize(grpc_byte_buffer* buf) = 0;
virtual ~DeserializeFunc() {}
};
@@ -340,10 +324,8 @@ template <class R>
class DeserializeFuncType final : public DeserializeFunc {
public:
DeserializeFuncType(R* message) : message_(message) {}
- Status Deserialize(grpc_byte_buffer* buf,
- int max_receive_message_size) override {
- return SerializationTraits<R>::Deserialize(buf, message_,
- max_receive_message_size);
+ Status Deserialize(grpc_byte_buffer* buf) override {
+ return SerializationTraits<R>::Deserialize(buf, message_);
}
~DeserializeFuncType() override {}
@@ -382,13 +364,12 @@ class CallOpGenericRecvMessage {
op->data.recv_message.recv_message = &recv_buf_;
}
- void FinishOp(bool* status, int max_receive_message_size) {
+ void FinishOp(bool* status) {
if (!deserialize_) return;
if (recv_buf_) {
if (*status) {
got_message = true;
- *status =
- deserialize_->Deserialize(recv_buf_, max_receive_message_size).ok();
+ *status = deserialize_->Deserialize(recv_buf_).ok();
} else {
got_message = false;
g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_);
@@ -422,7 +403,7 @@ class CallOpClientSendClose {
op->flags = 0;
op->reserved = NULL;
}
- void FinishOp(bool* status, int max_receive_message_size) { send_ = false; }
+ void FinishOp(bool* status) { send_ = false; }
private:
bool send_;
@@ -451,13 +432,14 @@ class CallOpServerSendStatus {
trailing_metadata_count_;
op->data.send_status_from_server.trailing_metadata = trailing_metadata_;
op->data.send_status_from_server.status = send_status_code_;
+ status_details_slice_ = SliceReferencingString(send_status_details_);
op->data.send_status_from_server.status_details =
- send_status_details_.empty() ? nullptr : send_status_details_.c_str();
+ send_status_details_.empty() ? nullptr : &status_details_slice_;
op->flags = 0;
op->reserved = NULL;
}
- void FinishOp(bool* status, int max_receive_message_size) {
+ void FinishOp(bool* status) {
if (!send_status_available_) return;
g_core_codegen_interface->gpr_free(trailing_metadata_);
send_status_available_ = false;
@@ -469,37 +451,36 @@ class CallOpServerSendStatus {
grpc::string send_status_details_;
size_t trailing_metadata_count_;
grpc_metadata* trailing_metadata_;
+ grpc_slice status_details_slice_;
};
class CallOpRecvInitialMetadata {
public:
- CallOpRecvInitialMetadata() : recv_initial_metadata_(nullptr) {}
+ CallOpRecvInitialMetadata() : metadata_map_(nullptr) {}
void RecvInitialMetadata(ClientContext* context) {
context->initial_metadata_received_ = true;
- recv_initial_metadata_ = &context->recv_initial_metadata_;
+ metadata_map_ = &context->recv_initial_metadata_;
}
protected:
void AddOp(grpc_op* ops, size_t* nops) {
- if (!recv_initial_metadata_) return;
- memset(&recv_initial_metadata_arr_, 0, sizeof(recv_initial_metadata_arr_));
+ if (metadata_map_ == nullptr) return;
grpc_op* op = &ops[(*nops)++];
op->op = GRPC_OP_RECV_INITIAL_METADATA;
- op->data.recv_initial_metadata.recv_initial_metadata =
- &recv_initial_metadata_arr_;
+ op->data.recv_initial_metadata.recv_initial_metadata = metadata_map_->arr();
op->flags = 0;
op->reserved = NULL;
}
- void FinishOp(bool* status, int max_receive_message_size) {
- if (recv_initial_metadata_ == nullptr) return;
- FillMetadataMap(&recv_initial_metadata_arr_, recv_initial_metadata_);
- recv_initial_metadata_ = nullptr;
+
+ void FinishOp(bool* status) {
+ if (metadata_map_ == nullptr) return;
+ metadata_map_->FillMap();
+ metadata_map_ = nullptr;
}
private:
- std::multimap<grpc::string_ref, grpc::string_ref>* recv_initial_metadata_;
- grpc_metadata_array recv_initial_metadata_arr_;
+ MetadataMap* metadata_map_;
};
class CallOpClientRecvStatus {
@@ -507,46 +488,37 @@ class CallOpClientRecvStatus {
CallOpClientRecvStatus() : recv_status_(nullptr) {}
void ClientRecvStatus(ClientContext* context, Status* status) {
- recv_trailing_metadata_ = &context->trailing_metadata_;
+ metadata_map_ = &context->trailing_metadata_;
recv_status_ = status;
}
protected:
void AddOp(grpc_op* ops, size_t* nops) {
if (recv_status_ == nullptr) return;
- memset(&recv_trailing_metadata_arr_, 0,
- sizeof(recv_trailing_metadata_arr_));
- status_details_ = nullptr;
- status_details_capacity_ = 0;
grpc_op* op = &ops[(*nops)++];
op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
- op->data.recv_status_on_client.trailing_metadata =
- &recv_trailing_metadata_arr_;
+ op->data.recv_status_on_client.trailing_metadata = metadata_map_->arr();
op->data.recv_status_on_client.status = &status_code_;
op->data.recv_status_on_client.status_details = &status_details_;
- op->data.recv_status_on_client.status_details_capacity =
- &status_details_capacity_;
op->flags = 0;
op->reserved = NULL;
}
- void FinishOp(bool* status, int max_receive_message_size) {
+ void FinishOp(bool* status) {
if (recv_status_ == nullptr) return;
- FillMetadataMap(&recv_trailing_metadata_arr_, recv_trailing_metadata_);
- *recv_status_ = Status(
- static_cast<StatusCode>(status_code_),
- status_details_ ? grpc::string(status_details_) : grpc::string());
- g_core_codegen_interface->gpr_free(status_details_);
+ metadata_map_->FillMap();
+ *recv_status_ = Status(static_cast<StatusCode>(status_code_),
+ grpc::string(GRPC_SLICE_START_PTR(status_details_),
+ GRPC_SLICE_END_PTR(status_details_)));
+ g_core_codegen_interface->grpc_slice_unref(status_details_);
recv_status_ = nullptr;
}
private:
- std::multimap<grpc::string_ref, grpc::string_ref>* recv_trailing_metadata_;
+ MetadataMap* metadata_map_;
Status* recv_status_;
- grpc_metadata_array recv_trailing_metadata_arr_;
grpc_status_code status_code_;
- char* status_details_;
- size_t status_details_capacity_;
+ grpc_slice status_details_;
};
/// An abstract collection of CallOpSet's, to be used whenever
@@ -567,22 +539,17 @@ class CallOpSetCollectionInterface
/// API.
class CallOpSetInterface : public CompletionQueueTag {
public:
- CallOpSetInterface() : max_receive_message_size_(0) {}
+ CallOpSetInterface() {}
/// Fills in grpc_op, starting from ops[*nops] and moving
/// upwards.
virtual void FillOps(grpc_op* ops, size_t* nops) = 0;
- void set_max_receive_message_size(int max_receive_message_size) {
- max_receive_message_size_ = max_receive_message_size;
- }
-
/// Mark this as belonging to a collection if needed
void SetCollection(std::shared_ptr<CallOpSetCollectionInterface> collection) {
collection_ = collection;
}
protected:
- int max_receive_message_size_;
std::shared_ptr<CallOpSetCollectionInterface> collection_;
};
@@ -614,12 +581,12 @@ class CallOpSet : public CallOpSetInterface,
}
bool FinalizeResult(void** tag, bool* status) override {
- this->Op1::FinishOp(status, max_receive_message_size_);
- this->Op2::FinishOp(status, max_receive_message_size_);
- this->Op3::FinishOp(status, max_receive_message_size_);
- this->Op4::FinishOp(status, max_receive_message_size_);
- this->Op5::FinishOp(status, max_receive_message_size_);
- this->Op6::FinishOp(status, max_receive_message_size_);
+ this->Op1::FinishOp(status);
+ this->Op2::FinishOp(status);
+ this->Op3::FinishOp(status);
+ this->Op4::FinishOp(status);
+ this->Op5::FinishOp(status);
+ this->Op6::FinishOp(status);
*tag = return_tag_;
collection_.reset(); // drop the ref at this point
return true;
@@ -651,35 +618,19 @@ class Call final {
public:
/* call is owned by the caller */
Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq)
- : call_hook_(call_hook),
- cq_(cq),
- call_(call),
- max_receive_message_size_(-1) {}
-
- Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq,
- int max_receive_message_size)
- : call_hook_(call_hook),
- cq_(cq),
- call_(call),
- max_receive_message_size_(max_receive_message_size) {}
+ : call_hook_(call_hook), cq_(cq), call_(call) {}
void PerformOps(CallOpSetInterface* ops) {
- if (max_receive_message_size_ > 0) {
- ops->set_max_receive_message_size(max_receive_message_size_);
- }
call_hook_->PerformOpsOnCall(ops, this);
}
grpc_call* call() const { return call_; }
CompletionQueue* cq() const { return cq_; }
- int max_receive_message_size() { return max_receive_message_size_; }
-
private:
CallHook* call_hook_;
CompletionQueue* cq_;
grpc_call* call_;
- int max_receive_message_size_;
};
} // namespace grpc
diff --git a/include/grpc++/impl/codegen/client_context.h b/include/grpc++/impl/codegen/client_context.h
index 777b2f8847..b91c7f65d4 100644
--- a/include/grpc++/impl/codegen/client_context.h
+++ b/include/grpc++/impl/codegen/client_context.h
@@ -57,7 +57,9 @@
#include <grpc++/impl/codegen/config.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/create_auth_context.h>
+#include <grpc++/impl/codegen/metadata_map.h>
#include <grpc++/impl/codegen/security/auth_context.h>
+#include <grpc++/impl/codegen/slice.h>
#include <grpc++/impl/codegen/status.h>
#include <grpc++/impl/codegen/string_ref.h>
#include <grpc++/impl/codegen/time.h>
@@ -193,7 +195,7 @@ class ClientContext {
const std::multimap<grpc::string_ref, grpc::string_ref>&
GetServerInitialMetadata() const {
GPR_CODEGEN_ASSERT(initial_metadata_received_);
- return recv_initial_metadata_;
+ return *recv_initial_metadata_.map();
}
/// Return a collection of trailing metadata key-value pairs. Note that keys
@@ -205,7 +207,7 @@ class ClientContext {
const std::multimap<grpc::string_ref, grpc::string_ref>&
GetServerTrailingMetadata() const {
// TODO(yangg) check finished
- return trailing_metadata_;
+ return *trailing_metadata_.map();
}
/// Set the deadline for the client call.
@@ -375,8 +377,8 @@ class ClientContext {
mutable std::shared_ptr<const AuthContext> auth_context_;
struct census_context* census_context_;
std::multimap<grpc::string, grpc::string> send_initial_metadata_;
- std::multimap<grpc::string_ref, grpc::string_ref> recv_initial_metadata_;
- std::multimap<grpc::string_ref, grpc::string_ref> trailing_metadata_;
+ MetadataMap recv_initial_metadata_;
+ MetadataMap trailing_metadata_;
grpc_call* propagate_from_call_;
PropagationOptions propagation_options_;
diff --git a/include/grpc++/impl/codegen/client_unary_call.h b/include/grpc++/impl/codegen/client_unary_call.h
index 70d65549c8..201e52ae07 100644
--- a/include/grpc++/impl/codegen/client_unary_call.h
+++ b/include/grpc++/impl/codegen/client_unary_call.h
@@ -69,7 +69,14 @@ Status BlockingUnaryCall(ChannelInterface* channel, const RpcMethod& method,
ops.ClientSendClose();
ops.ClientRecvStatus(context, &status);
call.PerformOps(&ops);
- GPR_CODEGEN_ASSERT((cq.Pluck(&ops) && ops.got_message) || !status.ok());
+ if (cq.Pluck(&ops)) {
+ if (!ops.got_message && status.ok()) {
+ return Status(StatusCode::UNIMPLEMENTED,
+ "No message returned for unary request");
+ }
+ } else {
+ GPR_CODEGEN_ASSERT(!status.ok());
+ }
return status;
}
diff --git a/include/grpc++/impl/codegen/core_codegen.h b/include/grpc++/impl/codegen/core_codegen.h
index 6b5e637e4e..754bf14b25 100644
--- a/include/grpc++/impl/codegen/core_codegen.h
+++ b/include/grpc++/impl/codegen/core_codegen.h
@@ -81,7 +81,10 @@ class CoreCodegen : public CoreCodegenInterface {
grpc_slice grpc_slice_split_tail(grpc_slice* s, size_t split) override;
void grpc_slice_buffer_add(grpc_slice_buffer* sb, grpc_slice slice) override;
void grpc_slice_buffer_pop(grpc_slice_buffer* sb) override;
-
+ grpc_slice grpc_slice_from_static_buffer(const void* buffer,
+ size_t length) override;
+ grpc_slice grpc_slice_from_copied_buffer(const void* buffer,
+ size_t length) override;
void grpc_metadata_array_init(grpc_metadata_array* array) override;
void grpc_metadata_array_destroy(grpc_metadata_array* array) override;
@@ -91,7 +94,8 @@ class CoreCodegen : public CoreCodegenInterface {
virtual const Status& ok() override;
virtual const Status& cancelled() override;
- void assert_fail(const char* failed_assertion) override;
+ void assert_fail(const char* failed_assertion, const char* file,
+ int line) override;
};
} // namespace grpc
diff --git a/include/grpc++/impl/codegen/core_codegen_interface.h b/include/grpc++/impl/codegen/core_codegen_interface.h
index 4783a43454..45ea040303 100644
--- a/include/grpc++/impl/codegen/core_codegen_interface.h
+++ b/include/grpc++/impl/codegen/core_codegen_interface.h
@@ -56,7 +56,8 @@ namespace grpc {
class CoreCodegenInterface {
public:
/// Upon a failed assertion, log the error.
- virtual void assert_fail(const char* failed_assertion) = 0;
+ virtual void assert_fail(const char* failed_assertion, const char* file,
+ int line) = 0;
virtual grpc_completion_queue* grpc_completion_queue_create(
void* reserved) = 0;
@@ -99,6 +100,10 @@ class CoreCodegenInterface {
virtual void grpc_slice_buffer_add(grpc_slice_buffer* sb,
grpc_slice slice) = 0;
virtual void grpc_slice_buffer_pop(grpc_slice_buffer* sb) = 0;
+ virtual grpc_slice grpc_slice_from_static_buffer(const void* buffer,
+ size_t length) = 0;
+ virtual grpc_slice grpc_slice_from_copied_buffer(const void* buffer,
+ size_t length) = 0;
virtual void grpc_metadata_array_init(grpc_metadata_array* array) = 0;
virtual void grpc_metadata_array_destroy(grpc_metadata_array* array) = 0;
@@ -113,11 +118,11 @@ class CoreCodegenInterface {
extern CoreCodegenInterface* g_core_codegen_interface;
/// Codegen specific version of \a GPR_ASSERT.
-#define GPR_CODEGEN_ASSERT(x) \
- do { \
- if (!(x)) { \
- grpc::g_core_codegen_interface->assert_fail(#x); \
- } \
+#define GPR_CODEGEN_ASSERT(x) \
+ do { \
+ if (!(x)) { \
+ grpc::g_core_codegen_interface->assert_fail(#x, __FILE__, __LINE__); \
+ } \
} while (0)
} // namespace grpc
diff --git a/include/grpc++/impl/codegen/metadata_map.h b/include/grpc++/impl/codegen/metadata_map.h
new file mode 100644
index 0000000000..53b9d62f9f
--- /dev/null
+++ b/include/grpc++/impl/codegen/metadata_map.h
@@ -0,0 +1,71 @@
+/*
+*
+* Copyright 2015, Google Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following disclaimer
+* in the documentation and/or other materials provided with the
+* distribution.
+* * Neither the name of Google Inc. nor the names of its
+* contributors may be used to endorse or promote products derived from
+* this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+#ifndef GRPCXX_IMPL_CODEGEN_METADATA_MAP_H
+#define GRPCXX_IMPL_CODEGEN_METADATA_MAP_H
+
+#include <grpc++/impl/codegen/slice.h>
+
+namespace grpc {
+
+class MetadataMap {
+ public:
+ MetadataMap() { memset(&arr_, 0, sizeof(arr_)); }
+
+ ~MetadataMap() {
+ g_core_codegen_interface->grpc_metadata_array_destroy(&arr_);
+ }
+
+ void FillMap() {
+ for (size_t i = 0; i < arr_.count; i++) {
+ // TODO(yangg) handle duplicates?
+ map_.insert(std::pair<grpc::string_ref, grpc::string_ref>(
+ StringRefFromSlice(&arr_.metadata[i].key),
+ StringRefFromSlice(&arr_.metadata[i].value)));
+ }
+ }
+
+ std::multimap<grpc::string_ref, grpc::string_ref> *map() { return &map_; }
+ const std::multimap<grpc::string_ref, grpc::string_ref> *map() const {
+ return &map_;
+ }
+ grpc_metadata_array *arr() { return &arr_; }
+
+ private:
+ grpc_metadata_array arr_;
+ std::multimap<grpc::string_ref, grpc::string_ref> map_;
+};
+
+} // namespace grpc
+
+#endif // GRPCXX_IMPL_CODEGEN_METADATA_MAP_H
diff --git a/include/grpc++/impl/codegen/method_handler_impl.h b/include/grpc++/impl/codegen/method_handler_impl.h
index d5d27e15cd..83b569ce74 100644
--- a/include/grpc++/impl/codegen/method_handler_impl.h
+++ b/include/grpc++/impl/codegen/method_handler_impl.h
@@ -52,8 +52,8 @@ class RpcMethodHandler : public MethodHandler {
void RunHandler(const HandlerParameter& param) final {
RequestType req;
- Status status = SerializationTraits<RequestType>::Deserialize(
- param.request, &req, param.max_receive_message_size);
+ Status status =
+ SerializationTraits<RequestType>::Deserialize(param.request, &req);
ResponseType rsp;
if (status.ok()) {
status = func_(service_, param.server_context, &req, &rsp);
@@ -138,8 +138,8 @@ class ServerStreamingHandler : public MethodHandler {
void RunHandler(const HandlerParameter& param) final {
RequestType req;
- Status status = SerializationTraits<RequestType>::Deserialize(
- param.request, &req, param.max_receive_message_size);
+ Status status =
+ SerializationTraits<RequestType>::Deserialize(param.request, &req);
if (status.ok()) {
ServerWriter<ResponseType> writer(param.call, param.server_context);
diff --git a/include/grpc++/impl/codegen/proto_utils.h b/include/grpc++/impl/codegen/proto_utils.h
index 2f15487591..2123b62ed9 100644
--- a/include/grpc++/impl/codegen/proto_utils.h
+++ b/include/grpc++/impl/codegen/proto_utils.h
@@ -203,8 +203,7 @@ class SerializationTraits<T, typename std::enable_if<std::is_base_of<
}
static Status Deserialize(grpc_byte_buffer* buffer,
- grpc::protobuf::Message* msg,
- int max_receive_message_size) {
+ grpc::protobuf::Message* msg) {
if (buffer == nullptr) {
return Status(StatusCode::INTERNAL, "No payload");
}
@@ -215,10 +214,7 @@ class SerializationTraits<T, typename std::enable_if<std::is_base_of<
return reader.status();
}
::grpc::protobuf::io::CodedInputStream decoder(&reader);
- if (max_receive_message_size > 0) {
- decoder.SetTotalBytesLimit(max_receive_message_size,
- max_receive_message_size);
- }
+ decoder.SetTotalBytesLimit(INT_MAX, INT_MAX);
if (!msg->ParseFromCodedStream(&decoder)) {
result = Status(StatusCode::INTERNAL, msg->InitializationErrorString());
}
diff --git a/include/grpc++/impl/codegen/rpc_service_method.h b/include/grpc++/impl/codegen/rpc_service_method.h
index 78c54e3771..eb8f9a1096 100644
--- a/include/grpc++/impl/codegen/rpc_service_method.h
+++ b/include/grpc++/impl/codegen/rpc_service_method.h
@@ -57,17 +57,12 @@ class MethodHandler {
public:
virtual ~MethodHandler() {}
struct HandlerParameter {
- HandlerParameter(Call* c, ServerContext* context, grpc_byte_buffer* req,
- int max_size)
- : call(c),
- server_context(context),
- request(req),
- max_receive_message_size(max_size) {}
+ HandlerParameter(Call* c, ServerContext* context, grpc_byte_buffer* req)
+ : call(c), server_context(context), request(req) {}
Call* call;
ServerContext* server_context;
// Handler required to grpc_byte_buffer_destroy this
grpc_byte_buffer* request;
- int max_receive_message_size;
};
virtual void RunHandler(const HandlerParameter& param) = 0;
};
diff --git a/include/grpc++/impl/codegen/server_context.h b/include/grpc++/impl/codegen/server_context.h
index dd30576379..8c7fe0809e 100644
--- a/include/grpc++/impl/codegen/server_context.h
+++ b/include/grpc++/impl/codegen/server_context.h
@@ -39,6 +39,7 @@
#include <grpc++/impl/codegen/config.h>
#include <grpc++/impl/codegen/create_auth_context.h>
+#include <grpc++/impl/codegen/metadata_map.h>
#include <grpc++/impl/codegen/security/auth_context.h>
#include <grpc++/impl/codegen/string_ref.h>
#include <grpc++/impl/codegen/time.h>
@@ -123,7 +124,7 @@ class ServerContext {
const std::multimap<grpc::string_ref, grpc::string_ref>& client_metadata()
const {
- return client_metadata_;
+ return *client_metadata_.map();
}
grpc_compression_level compression_level() const {
@@ -223,7 +224,7 @@ class ServerContext {
CompletionQueue* cq_;
bool sent_initial_metadata_;
mutable std::shared_ptr<const AuthContext> auth_context_;
- std::multimap<grpc::string_ref, grpc::string_ref> client_metadata_;
+ MetadataMap client_metadata_;
std::multimap<grpc::string, grpc::string> initial_metadata_;
std::multimap<grpc::string, grpc::string> trailing_metadata_;
diff --git a/include/grpc++/impl/codegen/server_interface.h b/include/grpc++/impl/codegen/server_interface.h
index 666b9ff66e..bd1b36e883 100644
--- a/include/grpc++/impl/codegen/server_interface.h
+++ b/include/grpc++/impl/codegen/server_interface.h
@@ -152,7 +152,6 @@ class ServerInterface : public CallHook {
void* const tag_;
const bool delete_on_finalize_;
grpc_call* call_;
- grpc_metadata_array initial_metadata_array_;
};
class RegisteredAsyncRequest : public BaseAsyncRequest {
@@ -199,9 +198,7 @@ class ServerInterface : public CallHook {
bool FinalizeResult(void** tag, bool* status) override {
bool serialization_status =
*status && payload_ &&
- SerializationTraits<Message>::Deserialize(
- payload_, request_, server_->max_receive_message_size())
- .ok();
+ SerializationTraits<Message>::Deserialize(payload_, request_).ok();
bool ret = RegisteredAsyncRequest::FinalizeResult(tag, status);
*status = serialization_status && *status;
return ret;
diff --git a/include/grpc++/impl/codegen/slice.h b/include/grpc++/impl/codegen/slice.h
new file mode 100644
index 0000000000..04b2f9af01
--- /dev/null
+++ b/include/grpc++/impl/codegen/slice.h
@@ -0,0 +1,65 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPCXX_IMPL_CODEGEN_SLICE_H
+#define GRPCXX_IMPL_CODEGEN_SLICE_H
+
+#include <grpc++/impl/codegen/core_codegen_interface.h>
+#include <grpc++/impl/codegen/string_ref.h>
+
+namespace grpc {
+
+inline grpc::string_ref StringRefFromSlice(const grpc_slice* slice) {
+ return grpc::string_ref(
+ reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(*slice)),
+ GRPC_SLICE_LENGTH(*slice));
+}
+
+inline grpc::string StringFromCopiedSlice(grpc_slice slice) {
+ return grpc::string(reinterpret_cast<char*>(GRPC_SLICE_START_PTR(slice)),
+ GRPC_SLICE_LENGTH(slice));
+}
+
+inline grpc_slice SliceReferencingString(const grpc::string& str) {
+ return g_core_codegen_interface->grpc_slice_from_static_buffer(str.data(),
+ str.length());
+}
+
+inline grpc_slice SliceFromCopiedString(const grpc::string& str) {
+ return g_core_codegen_interface->grpc_slice_from_copied_buffer(str.data(),
+ str.length());
+}
+
+} // namespace grpc
+
+#endif // GRPCXX_IMPL_CODEGEN_SLICE_H
diff --git a/include/grpc++/impl/codegen/sync_stream.h b/include/grpc++/impl/codegen/sync_stream.h
index 4d9b074e95..1f7708bab9 100644
--- a/include/grpc++/impl/codegen/sync_stream.h
+++ b/include/grpc++/impl/codegen/sync_stream.h
@@ -160,7 +160,7 @@ class ClientReader final : public ClientReaderInterface<R> {
}
bool NextMessageSize(uint32_t* sz) override {
- *sz = call_.max_receive_message_size();
+ *sz = INT_MAX;
return true;
}
@@ -310,7 +310,7 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
}
bool NextMessageSize(uint32_t* sz) override {
- *sz = call_.max_receive_message_size();
+ *sz = INT_MAX;
return true;
}
@@ -382,7 +382,7 @@ class ServerReader final : public ServerReaderInterface<R> {
}
bool NextMessageSize(uint32_t* sz) override {
- *sz = call_->max_receive_message_size();
+ *sz = INT_MAX;
return true;
}
@@ -474,7 +474,7 @@ class ServerReaderWriterBody final {
}
bool NextMessageSize(uint32_t* sz) {
- *sz = call_->max_receive_message_size();
+ *sz = INT_MAX;
return true;
}
diff --git a/include/grpc++/support/byte_buffer.h b/include/grpc++/support/byte_buffer.h
index 1f317df663..064a03b977 100644
--- a/include/grpc++/support/byte_buffer.h
+++ b/include/grpc++/support/byte_buffer.h
@@ -95,8 +95,7 @@ class ByteBuffer final {
template <>
class SerializationTraits<ByteBuffer, void> {
public:
- static Status Deserialize(grpc_byte_buffer* byte_buffer, ByteBuffer* dest,
- int max_receive_message_size) {
+ static Status Deserialize(grpc_byte_buffer* byte_buffer, ByteBuffer* dest) {
dest->set_buffer(byte_buffer);
return Status::OK;
}
diff --git a/include/grpc/census.h b/include/grpc/census.h
index 62ff45d894..822c42c0a4 100644
--- a/include/grpc/census.h
+++ b/include/grpc/census.h
@@ -156,7 +156,7 @@ CENSUSAPI void census_context_destroy(census_context *context);
CENSUSAPI const census_context_status *census_context_get_status(
const census_context *context);
-/* Structure used for iterating over the tegs in a context. API clients should
+/* Structure used for iterating over the tags in a context. API clients should
not use or reference internal fields - neither their contents or
presence/absence are guaranteed. */
typedef struct {
@@ -180,7 +180,7 @@ CENSUSAPI int census_context_next_tag(census_context_iterator *iterator,
CENSUSAPI int census_context_get_tag(const census_context *context,
const char *key, census_tag *tag);
-/* Tag set encode/decode functionality. These functionas are intended
+/* Tag set encode/decode functionality. These functions are intended
for use by RPC systems only, for purposes of transmitting/receiving contexts.
*/
@@ -205,14 +205,14 @@ enum census_trace_mask_values {
};
/** Get the current trace mask associated with this context. The value returned
- will be the logical or of census_trace_mask_values values. */
+ will be the logical OR of census_trace_mask_values values. */
CENSUSAPI int census_trace_mask(const census_context *context);
/** Set the trace mask associated with a context. */
CENSUSAPI void census_set_trace_mask(int trace_mask);
/* The concept of "operation" is a fundamental concept for Census. In an RPC
- system, and operation typcially represents a single RPC, or a significant
+ system, an operation typically represents a single RPC, or a significant
sub-part thereof (e.g. a single logical "read" RPC to a distributed storage
system might do several other actions in parallel, from looking up metadata
indices to making requests of other services - each of these could be a
@@ -362,7 +362,7 @@ CENSUSAPI census_context *census_start_server_rpc_op(
@param context The base context. Can be NULL.
@param family Family name to associate with the trace
- @param name Name within family to associated with traces/stats
+ @param name Name within family to associate with traces/stats
@param trace_mask An OR of census_trace_mask_values values. Only used if
context is NULL.
@@ -454,7 +454,7 @@ CENSUSAPI void census_trace_scan_end();
protobuf, `resource_pb_size` being the size of the buffer. Returns a -ve
value on error, or a positive (>= 0) resource id (for use in
census_delete_resource() and census_record_values()). In order to be valid, a
- resource must have a name, and at least one numerator in it's unit type. The
+ resource must have a name, and at least one numerator in its unit type. The
resource name must be unique, and an error will be returned if it is not. */
CENSUSAPI int32_t census_define_resource(const uint8_t *resource_pb,
size_t resource_pb_size);
@@ -462,7 +462,7 @@ CENSUSAPI int32_t census_define_resource(const uint8_t *resource_pb,
/* Delete a resource created by census_define_resource(). */
CENSUSAPI void census_delete_resource(int32_t resource_id);
-/* Determine the id of a resource, given it's name. returns -1 if the resource
+/* Determine the id of a resource, given its name. returns -1 if the resource
does not exist. */
CENSUSAPI int32_t census_resource_id(const char *name);
diff --git a/include/grpc/compression.h b/include/grpc/compression.h
index 5f285cdcdf..659d6fe758 100644
--- a/include/grpc/compression.h
+++ b/include/grpc/compression.h
@@ -34,11 +34,12 @@
#ifndef GRPC_COMPRESSION_H
#define GRPC_COMPRESSION_H
-#include <stdlib.h>
-
#include <grpc/impl/codegen/port_platform.h>
+#include <stdlib.h>
+
#include <grpc/impl/codegen/compression_types.h>
+#include <grpc/slice.h>
#ifdef __cplusplus
extern "C" {
@@ -48,8 +49,7 @@ extern "C" {
* grpc_compression_algorithm instance, updating \a algorithm. Returns 1 upon
* success, 0 otherwise. */
GRPCAPI int grpc_compression_algorithm_parse(
- const char *name, size_t name_length,
- grpc_compression_algorithm *algorithm);
+ grpc_slice value, grpc_compression_algorithm *algorithm);
/** Updates \a name with the encoding name corresponding to a valid \a
* algorithm. Note that \a name is statically allocated and must *not* be freed.
diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h
index 898f4d533b..37b823ae1e 100644
--- a/include/grpc/grpc.h
+++ b/include/grpc/grpc.h
@@ -178,8 +178,8 @@ GRPCAPI void grpc_channel_watch_connectivity_state(
possible values). */
GRPCAPI grpc_call *grpc_channel_create_call(
grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask,
- grpc_completion_queue *completion_queue, const char *method,
- const char *host, gpr_timespec deadline, void *reserved);
+ grpc_completion_queue *completion_queue, grpc_slice method,
+ const grpc_slice *host, gpr_timespec deadline, void *reserved);
/** Ping the channels peer (load balanced channels will select one sub-channel
to ping); if the channel is not connected, posts a failed. */
@@ -402,14 +402,14 @@ GRPCAPI void grpc_server_destroy(grpc_server *server);
GRPCAPI int grpc_tracer_set_enabled(const char *name, int enabled);
/** Check whether a metadata key is legal (will be accepted by core) */
-GRPCAPI int grpc_header_key_is_legal(const char *key, size_t length);
+GRPCAPI int grpc_header_key_is_legal(grpc_slice slice);
/** Check whether a non-binary metadata value is legal (will be accepted by
core) */
-GRPCAPI int grpc_header_nonbin_value_is_legal(const char *value, size_t length);
+GRPCAPI int grpc_header_nonbin_value_is_legal(grpc_slice slice);
/** Check whether a metadata key corresponds to a binary value */
-GRPCAPI int grpc_is_binary_header(const char *key, size_t length);
+GRPCAPI int grpc_is_binary_header(grpc_slice slice);
/** Convert grpc_call_error values to a string */
GRPCAPI const char *grpc_call_error_to_string(grpc_call_error error);
diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h
index 8d20f705ee..7fbaf56e75 100644
--- a/include/grpc/impl/codegen/grpc_types.h
+++ b/include/grpc/impl/codegen/grpc_types.h
@@ -179,6 +179,15 @@ typedef struct {
Larger values give lower CPU usage for large messages, but more head of line
blocking for small messages. */
#define GRPC_ARG_HTTP2_MAX_FRAME_SIZE "grpc.http2.max_frame_size"
+/** Minimum time (in milliseconds) between successive ping frames being sent */
+#define GRPC_ARG_HTTP2_MIN_TIME_BETWEEN_PINGS_MS \
+ "grpc.http2.min_time_between_pings_ms"
+/** How many pings can we send before needing to send a data frame or header
+ frame?
+ (0 indicates that an infinite number of pings can be sent without sending
+ a data frame or header frame) */
+#define GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA \
+ "grpc.http2.max_pings_without_data"
/** How much data are we willing to queue up per stream if
GRPC_WRITE_BUFFER_HINT is set? This is an upper bound */
#define GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE "grpc.http2.write_buffer_size"
@@ -294,9 +303,11 @@ typedef enum grpc_call_error {
/** A single metadata element */
typedef struct grpc_metadata {
- const char *key;
- const char *value;
- size_t value_length;
+ /* the key, value values are expected to line up with grpc_mdelem: if changing
+ them, update metadata.h at the same time. */
+ grpc_slice key;
+ grpc_slice value;
+
uint32_t flags;
/** The following fields are reserved for grpc internal use.
@@ -338,10 +349,8 @@ typedef struct {
} grpc_metadata_array;
typedef struct {
- char *method;
- size_t method_capacity;
- char *host;
- size_t host_capacity;
+ grpc_slice method;
+ grpc_slice host;
gpr_timespec deadline;
uint32_t flags;
void *reserved;
@@ -425,7 +434,10 @@ typedef struct grpc_op {
size_t trailing_metadata_count;
grpc_metadata *trailing_metadata;
grpc_status_code status;
- const char *status_details;
+ /* optional: set to NULL if no details need sending, non-NULL if they do
+ * pointer will not be retained past the start_batch call
+ */
+ grpc_slice *status_details;
} send_status_from_server;
/** ownership of the array is with the caller, but ownership of the elements
stays with the call object (ie key, value members are owned by the call
@@ -450,28 +462,7 @@ typedef struct grpc_op {
value, or reuse it in a future op. */
grpc_metadata_array *trailing_metadata;
grpc_status_code *status;
- /** status_details is a buffer owned by the application before the op
- completes and after the op has completed. During the operation
- status_details may be reallocated to a size larger than
- *status_details_capacity, in which case *status_details_capacity will
- be updated with the new array capacity.
-
- Pre-allocating space:
- size_t my_capacity = 8;
- char *my_details = gpr_malloc(my_capacity);
- x.status_details = &my_details;
- x.status_details_capacity = &my_capacity;
-
- Not pre-allocating space:
- size_t my_capacity = 0;
- char *my_details = NULL;
- x.status_details = &my_details;
- x.status_details_capacity = &my_capacity;
-
- After the call:
- gpr_free(my_details); */
- char **status_details;
- size_t *status_details_capacity;
+ grpc_slice *status_details;
} recv_status_on_client;
struct {
/** out argument, set to 1 if the call failed in any way (seen as a
diff --git a/include/grpc/impl/codegen/slice.h b/include/grpc/impl/codegen/slice.h
index 035260445e..0b09a0bfd8 100644
--- a/include/grpc/impl/codegen/slice.h
+++ b/include/grpc/impl/codegen/slice.h
@@ -40,6 +40,8 @@
#include <grpc/impl/codegen/exec_ctx_fwd.h>
#include <grpc/impl/codegen/gpr_slice.h>
+typedef struct grpc_slice grpc_slice;
+
/* Slice API
A slice represents a contiguous reference counted array of bytes.
@@ -53,14 +55,25 @@
reference ownership semantics (who should call unref?) and mutability
constraints (is the callee allowed to modify the slice?) */
+typedef struct grpc_slice_refcount_vtable {
+ void (*ref)(void *);
+ void (*unref)(grpc_exec_ctx *exec_ctx, void *);
+ int (*eq)(grpc_slice a, grpc_slice b);
+ uint32_t (*hash)(grpc_slice slice);
+} grpc_slice_refcount_vtable;
+
/* Reference count container for grpc_slice. Contains function pointers to
increment and decrement reference counts. Implementations should cleanup
when the reference count drops to zero.
Typically client code should not touch this, and use grpc_slice_malloc,
grpc_slice_new, or grpc_slice_new_with_len instead. */
typedef struct grpc_slice_refcount {
- void (*ref)(void *);
- void (*unref)(grpc_exec_ctx *exec_ctx, void *);
+ const grpc_slice_refcount_vtable *vtable;
+ /* If a subset of this slice is taken, use this pointer for the refcount.
+ Typically points back to the refcount itself, however iterning
+ implementations can use this to avoid a verification step on each hash
+ or equality check */
+ struct grpc_slice_refcount *sub_refcount;
} grpc_slice_refcount;
#define GRPC_SLICE_INLINED_SIZE (sizeof(size_t) + sizeof(uint8_t *) - 1)
@@ -74,7 +87,7 @@ typedef struct grpc_slice_refcount {
If the slice does not have a refcount, it represents an inlined small piece
of data that is copied by value. */
-typedef struct grpc_slice {
+struct grpc_slice {
struct grpc_slice_refcount *refcount;
union {
struct {
@@ -86,7 +99,7 @@ typedef struct grpc_slice {
uint8_t bytes[GRPC_SLICE_INLINED_SIZE];
} inlined;
} data;
-} grpc_slice;
+};
#define GRPC_SLICE_BUFFER_INLINE_ELEMENTS 8
diff --git a/include/grpc/slice.h b/include/grpc/slice.h
index 1f181aae16..ea66e094e9 100644
--- a/include/grpc/slice.h
+++ b/include/grpc/slice.h
@@ -76,6 +76,12 @@ GPRAPI grpc_slice grpc_slice_new_with_len(void *p, size_t len,
Aborts if malloc() fails. */
GPRAPI grpc_slice grpc_slice_malloc(size_t length);
+/* Intern a slice:
+
+ The return value for two invocations of this function with the same sequence
+ of bytes is a slice which points to the same memory. */
+GPRAPI grpc_slice grpc_slice_intern(grpc_slice slice);
+
/* Create a slice by copying a string.
Does not preserve null terminators.
Equivalent to:
@@ -93,6 +99,9 @@ GPRAPI grpc_slice grpc_slice_from_copied_buffer(const char *source, size_t len);
/* Create a slice pointing to constant memory */
GPRAPI grpc_slice grpc_slice_from_static_string(const char *source);
+/* Create a slice pointing to constant memory */
+GPRAPI grpc_slice grpc_slice_from_static_buffer(const void *source, size_t len);
+
/* Return a result slice derived from s, which shares a ref count with s, where
result.data==s.data+begin, and result.length==end-begin.
The ref count of s is increased by one.
@@ -113,18 +122,45 @@ GPRAPI grpc_slice grpc_slice_split_tail(grpc_slice *s, size_t split);
Requires s intialized, split <= s.length */
GPRAPI grpc_slice grpc_slice_split_head(grpc_slice *s, size_t split);
-GPRAPI grpc_slice gpr_empty_slice(void);
+GPRAPI grpc_slice grpc_empty_slice(void);
+
+GPRAPI uint32_t grpc_slice_default_hash_impl(grpc_slice s);
+GPRAPI int grpc_slice_default_eq_impl(grpc_slice a, grpc_slice b);
+
+GPRAPI int grpc_slice_eq(grpc_slice a, grpc_slice b);
/* Returns <0 if a < b, ==0 if a == b, >0 if a > b
The order is arbitrary, and is not guaranteed to be stable across different
versions of the API. */
GPRAPI int grpc_slice_cmp(grpc_slice a, grpc_slice b);
GPRAPI int grpc_slice_str_cmp(grpc_slice a, const char *b);
+GPRAPI int grpc_slice_buf_cmp(grpc_slice a, const void *b, size_t blen);
+
+/* return non-zero if the first blen bytes of a are equal to b */
+GPRAPI int grpc_slice_buf_start_eq(grpc_slice a, const void *b, size_t blen);
+
+/* return the index of the last instance of \a c in \a s, or -1 if not found */
+GPRAPI int grpc_slice_rchr(grpc_slice s, char c);
+GPRAPI int grpc_slice_chr(grpc_slice s, char c);
+
+/* return the index of the first occurance of \a needle in \a haystack, or -1 if
+ * it's not found */
+GPRAPI int grpc_slice_slice(grpc_slice haystack, grpc_slice needle);
+
+GPRAPI uint32_t grpc_slice_hash(grpc_slice s);
/* Do two slices point at the same memory, with the same length
If a or b is inlined, actually compares data */
GPRAPI int grpc_slice_is_equivalent(grpc_slice a, grpc_slice b);
+/* Return a slice pointing to newly allocated memory that has the same contents
+ * as \a s */
+GPRAPI grpc_slice grpc_slice_dup(grpc_slice a);
+
+/* Return a copy of slice as a C string. Offers no protection against embedded
+ NULL's. Returned string must be freed with gpr_free. */
+GPRAPI char *grpc_slice_to_c_string(grpc_slice s);
+
#ifdef __cplusplus
}
#endif