mirror of https://github.com/grpc/grpc.git
commit
933c955aaf
113 changed files with 1647 additions and 527 deletions
@ -0,0 +1,15 @@ |
||||
There are times when we make changes that include a temporary shim for |
||||
backward-compatibility (e.g., a macro or some other function to preserve |
||||
the original API) to avoid having to bump the major version number in |
||||
the next release. However, when we do eventually want to release a |
||||
feature that does change the API in a non-backward-compatible way, we |
||||
will wind up bumping the major version number anyway, at which point we |
||||
can take the opportunity to clean up any pending backward-compatibility |
||||
shims. |
||||
|
||||
This file lists all pending backward-compatibility changes that should |
||||
be cleaned up the next time we are going to bump the major version |
||||
number: |
||||
|
||||
- remove `GRPC_ARG_MAX_MESSAGE_LENGTH` channel arg from |
||||
`include/grpc/impl/codegen/grpc_types.h` (commit `af00d8b`) |
@ -0,0 +1,86 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, 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. |
||||
* |
||||
*/ |
||||
|
||||
#include "src/core/ext/census/trace_context.h" |
||||
|
||||
#include <grpc/census.h> |
||||
#include <grpc/support/log.h> |
||||
#include <stdbool.h> |
||||
|
||||
#include "third_party/nanopb/pb_decode.h" |
||||
#include "third_party/nanopb/pb_encode.h" |
||||
|
||||
// This function assumes the TraceContext is valid.
|
||||
size_t encode_trace_context(google_trace_TraceContext *ctxt, uint8_t *buffer, |
||||
const size_t buf_size) { |
||||
// Create a stream that will write to our buffer.
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer, buf_size); |
||||
|
||||
// encode message
|
||||
bool status = pb_encode(&stream, google_trace_TraceContext_fields, ctxt); |
||||
|
||||
if (!status) { |
||||
gpr_log(GPR_DEBUG, "TraceContext encoding failed: %s", |
||||
PB_GET_ERROR(&stream)); |
||||
return 0; |
||||
} |
||||
|
||||
return stream.bytes_written; |
||||
} |
||||
|
||||
bool decode_trace_context(google_trace_TraceContext *ctxt, uint8_t *buffer, |
||||
const size_t nbytes) { |
||||
// Create a stream that reads nbytes from the buffer.
|
||||
pb_istream_t stream = pb_istream_from_buffer(buffer, nbytes); |
||||
|
||||
// decode message
|
||||
bool status = pb_decode(&stream, google_trace_TraceContext_fields, ctxt); |
||||
|
||||
if (!status) { |
||||
gpr_log(GPR_DEBUG, "TraceContext decoding failed: %s", |
||||
PB_GET_ERROR(&stream)); |
||||
return false; |
||||
} |
||||
|
||||
// check fields
|
||||
if (!ctxt->has_trace_id) { |
||||
gpr_log(GPR_DEBUG, "Invalid TraceContext: missing trace_id"); |
||||
return false; |
||||
} |
||||
if (!ctxt->has_span_id) { |
||||
gpr_log(GPR_DEBUG, "Invalid TraceContext: missing span_id"); |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
@ -0,0 +1,68 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, 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. |
||||
* |
||||
*/ |
||||
|
||||
/* Functions for manipulating trace contexts as defined in
|
||||
src/proto/census/trace.proto */ |
||||
#ifndef GRPC_CORE_EXT_CENSUS_TRACE_CONTEXT_H |
||||
#define GRPC_CORE_EXT_CENSUS_TRACE_CONTEXT_H |
||||
|
||||
#include "src/core/ext/census/gen/trace_context.pb.h" |
||||
|
||||
/* Maximum number of bytes required to encode a TraceContext (31)
|
||||
1 byte for trace_id field |
||||
1 byte for trace_id length |
||||
1 byte for trace_id.hi field |
||||
8 bytes for trace_id.hi (uint64_t) |
||||
1 byte for trace_id.lo field |
||||
8 bytes for trace_id.lo (uint64_t) |
||||
1 byte for span_id field |
||||
8 bytes for span_id (uint64_t) |
||||
1 byte for is_sampled field |
||||
1 byte for is_sampled (bool) */ |
||||
#define TRACE_MAX_CONTEXT_SIZE 31 |
||||
|
||||
/* Encode a trace context (ctxt) into proto format to the buffer provided. The
|
||||
size of buffer must be at least TRACE_MAX_CONTEXT_SIZE. On success, returns the |
||||
number of bytes successfully encoded into buffer. On failure, returns 0. */ |
||||
size_t encode_trace_context(google_trace_TraceContext *ctxt, uint8_t *buffer, |
||||
const size_t buf_size); |
||||
|
||||
/* Decode a proto-encoded TraceContext from the provided buffer into the
|
||||
TraceContext structure (ctxt). The function expects to be supplied the number |
||||
of bytes to be read from buffer (nbytes). This function will also validate that |
||||
the TraceContext has a span_id and a trace_id, and will return false if either |
||||
of these do not exist. On success, returns true and false otherwise. */ |
||||
bool decode_trace_context(google_trace_TraceContext *ctxt, uint8_t *buffer, |
||||
const size_t nbytes); |
||||
|
||||
#endif |
@ -0,0 +1,165 @@ |
||||
//
|
||||
// Copyright 2016, 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.
|
||||
//
|
||||
|
||||
#include "src/core/lib/channel/message_size_filter.h" |
||||
|
||||
#include <limits.h> |
||||
#include <string.h> |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/log.h> |
||||
#include <grpc/support/string_util.h> |
||||
|
||||
#include "src/core/lib/channel/channel_args.h" |
||||
|
||||
// The protobuf library will (by default) start warning at 100 megs.
|
||||
#define DEFAULT_MAX_MESSAGE_LENGTH (4 * 1024 * 1024) |
||||
|
||||
typedef struct call_data { |
||||
// Receive closures are chained: we inject this closure as the
|
||||
// recv_message_ready up-call on transport_stream_op, and remember to
|
||||
// call our next_recv_message_ready member after handling it.
|
||||
grpc_closure recv_message_ready; |
||||
// Used by recv_message_ready.
|
||||
grpc_byte_stream** recv_message; |
||||
// Original recv_message_ready callback, invoked after our own.
|
||||
grpc_closure* next_recv_message_ready; |
||||
} call_data; |
||||
|
||||
typedef struct channel_data { |
||||
size_t max_send_size; |
||||
size_t max_recv_size; |
||||
} channel_data; |
||||
|
||||
// Callback invoked when we receive a message. Here we check the max
|
||||
// receive message size.
|
||||
static void recv_message_ready(grpc_exec_ctx* exec_ctx, void* user_data, |
||||
grpc_error* error) { |
||||
grpc_call_element* elem = user_data; |
||||
call_data* calld = elem->call_data; |
||||
channel_data* chand = elem->channel_data; |
||||
if (*calld->recv_message != NULL && |
||||
(*calld->recv_message)->length > chand->max_recv_size) { |
||||
char* message_string; |
||||
gpr_asprintf( |
||||
&message_string, "Received message larger than max (%u vs. %lu)", |
||||
(*calld->recv_message)->length, (unsigned long)chand->max_recv_size); |
||||
gpr_slice message = gpr_slice_from_copied_string(message_string); |
||||
gpr_free(message_string); |
||||
grpc_call_element_send_cancel_with_message( |
||||
exec_ctx, elem, GRPC_STATUS_INVALID_ARGUMENT, &message); |
||||
} |
||||
// Invoke the next callback.
|
||||
grpc_exec_ctx_sched(exec_ctx, calld->next_recv_message_ready, error, NULL); |
||||
} |
||||
|
||||
// Start transport op.
|
||||
static void start_transport_stream_op(grpc_exec_ctx* exec_ctx, |
||||
grpc_call_element* elem, |
||||
grpc_transport_stream_op* op) { |
||||
call_data* calld = elem->call_data; |
||||
channel_data* chand = elem->channel_data; |
||||
// Check max send message size.
|
||||
if (op->send_message != NULL && |
||||
op->send_message->length > chand->max_send_size) { |
||||
char* message_string; |
||||
gpr_asprintf(&message_string, "Sent message larger than max (%u vs. %lu)", |
||||
op->send_message->length, (unsigned long)chand->max_send_size); |
||||
gpr_slice message = gpr_slice_from_copied_string(message_string); |
||||
gpr_free(message_string); |
||||
grpc_call_element_send_cancel_with_message( |
||||
exec_ctx, elem, GRPC_STATUS_INVALID_ARGUMENT, &message); |
||||
} |
||||
// Inject callback for receiving a message.
|
||||
if (op->recv_message_ready != NULL) { |
||||
calld->next_recv_message_ready = op->recv_message_ready; |
||||
calld->recv_message = op->recv_message; |
||||
op->recv_message_ready = &calld->recv_message_ready; |
||||
} |
||||
// Chain to the next filter.
|
||||
grpc_call_next_op(exec_ctx, elem, op); |
||||
} |
||||
|
||||
// Constructor for call_data.
|
||||
static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx, |
||||
grpc_call_element* elem, |
||||
grpc_call_element_args* args) { |
||||
call_data* calld = elem->call_data; |
||||
calld->next_recv_message_ready = NULL; |
||||
grpc_closure_init(&calld->recv_message_ready, recv_message_ready, elem); |
||||
return GRPC_ERROR_NONE; |
||||
} |
||||
|
||||
// Destructor for call_data.
|
||||
static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, |
||||
const grpc_call_final_info* final_info, |
||||
void* ignored) {} |
||||
|
||||
// Constructor for channel_data.
|
||||
static void init_channel_elem(grpc_exec_ctx* exec_ctx, |
||||
grpc_channel_element* elem, |
||||
grpc_channel_element_args* args) { |
||||
GPR_ASSERT(!args->is_last); |
||||
channel_data* chand = elem->channel_data; |
||||
memset(chand, 0, sizeof(*chand)); |
||||
chand->max_send_size = DEFAULT_MAX_MESSAGE_LENGTH; |
||||
chand->max_recv_size = DEFAULT_MAX_MESSAGE_LENGTH; |
||||
const grpc_integer_options options = {DEFAULT_MAX_MESSAGE_LENGTH, 0, INT_MAX}; |
||||
for (size_t i = 0; i < args->channel_args->num_args; ++i) { |
||||
if (strcmp(args->channel_args->args[i].key, |
||||
GRPC_ARG_MAX_SEND_MESSAGE_LENGTH) == 0) { |
||||
chand->max_send_size = (size_t)grpc_channel_arg_get_integer( |
||||
&args->channel_args->args[i], options); |
||||
} |
||||
if (strcmp(args->channel_args->args[i].key, |
||||
GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH) == 0) { |
||||
chand->max_recv_size = (size_t)grpc_channel_arg_get_integer( |
||||
&args->channel_args->args[i], options); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Destructor for channel_data.
|
||||
static void destroy_channel_elem(grpc_exec_ctx* exec_ctx, |
||||
grpc_channel_element* elem) {} |
||||
|
||||
const grpc_channel_filter grpc_message_size_filter = { |
||||
start_transport_stream_op, |
||||
grpc_channel_next_op, |
||||
sizeof(call_data), |
||||
init_call_elem, |
||||
grpc_call_stack_ignore_set_pollset_or_pollset_set, |
||||
destroy_call_elem, |
||||
sizeof(channel_data), |
||||
init_channel_elem, |
||||
destroy_channel_elem, |
||||
grpc_call_next_get_peer, |
||||
"message_size"}; |
@ -0,0 +1,39 @@ |
||||
//
|
||||
// Copyright 2016, 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 GRPC_CORE_LIB_CHANNEL_MESSAGE_SIZE_FILTER_H |
||||
#define GRPC_CORE_LIB_CHANNEL_MESSAGE_SIZE_FILTER_H |
||||
|
||||
#include "src/core/lib/channel/channel_stack.h" |
||||
|
||||
extern const grpc_channel_filter grpc_message_size_filter; |
||||
|
||||
#endif /* GRPC_CORE_LIB_CHANNEL_MESSAGE_SIZE_FILTER_H */ |
@ -0,0 +1,53 @@ |
||||
# Copyright 2016, 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. |
||||
|
||||
"""Tests of Channel Args on client/server side.""" |
||||
|
||||
import unittest |
||||
|
||||
import grpc |
||||
|
||||
TEST_CHANNEL_ARGS = ( |
||||
('arg1', b'bytes_val'), |
||||
('arg2', 'str_val'), |
||||
('arg3', 1), |
||||
(b'arg4', 'str_val'), |
||||
) |
||||
|
||||
|
||||
class ChannelArgsTest(unittest.TestCase): |
||||
|
||||
def test_client(self): |
||||
grpc.insecure_channel('localhost:8080', options=TEST_CHANNEL_ARGS) |
||||
|
||||
def test_server(self): |
||||
grpc.server(None, options=TEST_CHANNEL_ARGS) |
||||
|
||||
if __name__ == '__main__': |
||||
unittest.main(verbosity=2) |
Binary file not shown.
@ -0,0 +1,3 @@ |
||||
trace_id { hi : 5; lo : 1 } |
||||
span_id : 7 |
||||
is_sampled : true |
Binary file not shown.
@ -0,0 +1,2 @@ |
||||
trace_id { hi : 5; lo : 1 } |
||||
span_id : 7 |
Binary file not shown.
@ -0,0 +1,2 @@ |
||||
span_id : 7 |
||||
is_sampled : true |
Binary file not shown.
@ -0,0 +1,2 @@ |
||||
trace_id { hi : 5; lo : 1 } |
||||
is_sampled : true |
@ -0,0 +1,231 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, 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. |
||||
* |
||||
*/ |
||||
|
||||
#include <grpc/census.h> |
||||
#include <grpc/support/log.h> |
||||
#include <grpc/support/port_platform.h> |
||||
#include <grpc/support/useful.h> |
||||
#include <stdbool.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include "src/core/ext/census/base_resources.h" |
||||
#include "src/core/ext/census/resource.h" |
||||
#include "test/core/util/test_config.h" |
||||
|
||||
#include "src/core/ext/census/gen/trace_context.pb.h" |
||||
#include "src/core/ext/census/trace_context.h" |
||||
#include "third_party/nanopb/pb_decode.h" |
||||
#include "third_party/nanopb/pb_encode.h" |
||||
|
||||
#define BUF_SIZE 256 |
||||
|
||||
/* Encodes a TraceContext structure (ctxt1) to a buffer, and then decodes it
|
||||
to a second TraceContext (ctxt2). Validates that the resulting TraceContext |
||||
has a span_id, trace_id, and that the values are equal to those in initial |
||||
TraceContext. On success, returns true. If encode_trace_context returns 0, |
||||
decode_trace_context fails, or the resulting TraceContext is missing a trace_id |
||||
or span_id, it will return false. */ |
||||
bool validate_encode_decode_context(google_trace_TraceContext *ctxt1, |
||||
uint8_t *buffer, size_t buf_size) { |
||||
google_trace_TraceContext ctxt2 = google_trace_TraceContext_init_zero; |
||||
size_t msg_length; |
||||
GPR_ASSERT(ctxt1->has_trace_id && ctxt1->has_span_id); |
||||
|
||||
msg_length = encode_trace_context(ctxt1, buffer, buf_size); |
||||
if (msg_length == 0) { |
||||
return false; |
||||
} |
||||
|
||||
if (!decode_trace_context(&ctxt2, buffer, msg_length)) { |
||||
return false; |
||||
} |
||||
|
||||
if (!ctxt2.has_trace_id || !ctxt2.has_span_id) { |
||||
return false; |
||||
} |
||||
|
||||
GPR_ASSERT( |
||||
ctxt1->trace_id.hi == ctxt2.trace_id.hi && |
||||
ctxt1->trace_id.lo == ctxt2.trace_id.lo && |
||||
ctxt1->span_id == ctxt2.span_id && |
||||
ctxt1->has_is_sampled == ctxt2.has_is_sampled && |
||||
(ctxt1->has_is_sampled ? ctxt1->is_sampled == ctxt2.is_sampled : true)); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/* Decodes a proto-encoded TraceContext from a buffer. If decode_trace_context
|
||||
fails or the resulting TraceContext is missing a trace_id or span_id it will |
||||
return false, otherwise returns true. */ |
||||
bool validate_decode_context(google_trace_TraceContext *ctxt, uint8_t *buffer, |
||||
size_t msg_length) { |
||||
// Validate the decoding of a context written to buffer.
|
||||
if (!decode_trace_context(ctxt, buffer, msg_length)) { |
||||
return false; |
||||
} |
||||
|
||||
if (!ctxt->has_trace_id || !ctxt->has_span_id) { |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/* Read an encoded trace context from a file. Validates that the decoding
|
||||
gives the expected result (succeed). */ |
||||
static void read_and_validate_context_from_file(google_trace_TraceContext *ctxt, |
||||
const char *file, |
||||
const bool succeed) { |
||||
uint8_t buffer[BUF_SIZE]; |
||||
FILE *input = fopen(file, "rb"); |
||||
GPR_ASSERT(input != NULL); |
||||
size_t nbytes = fread(buffer, 1, BUF_SIZE, input); |
||||
GPR_ASSERT(nbytes <= BUF_SIZE && feof(input) && !ferror(input)); |
||||
bool res = validate_decode_context(ctxt, buffer, nbytes); |
||||
GPR_ASSERT(res == succeed); |
||||
GPR_ASSERT(fclose(input) == 0); |
||||
} |
||||
|
||||
// Test full proto-buffer.
|
||||
static void test_full() { |
||||
google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero; |
||||
read_and_validate_context_from_file( |
||||
&ctxt, "test/core/census/data/context_full.pb", true); |
||||
} |
||||
|
||||
// Test empty proto-buffer.
|
||||
static void test_empty() { |
||||
google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero; |
||||
read_and_validate_context_from_file( |
||||
&ctxt, "test/core/census/data/context_empty.pb", false); |
||||
} |
||||
|
||||
// Test proto-buffer with only trace_id.
|
||||
static void test_trace_only() { |
||||
google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero; |
||||
read_and_validate_context_from_file( |
||||
&ctxt, "test/core/census/data/context_trace_only.pb", false); |
||||
} |
||||
|
||||
// Test proto-buffer with only span_id.
|
||||
static void test_span_only() { |
||||
google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero; |
||||
read_and_validate_context_from_file( |
||||
&ctxt, "test/core/census/data/context_span_only.pb", false); |
||||
} |
||||
|
||||
// Test proto-buffer without is_sampled value.
|
||||
static void test_no_sample() { |
||||
google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero; |
||||
read_and_validate_context_from_file( |
||||
&ctxt, "test/core/census/data/context_no_sample.pb", true); |
||||
GPR_ASSERT(ctxt.has_is_sampled == false && ctxt.is_sampled == false); |
||||
} |
||||
|
||||
static void test_encode_decode() { |
||||
uint8_t buffer[BUF_SIZE] = {0}; |
||||
|
||||
google_trace_TraceContext ctxt1 = google_trace_TraceContext_init_zero; |
||||
ctxt1.has_trace_id = true; |
||||
ctxt1.trace_id.has_hi = true; |
||||
ctxt1.trace_id.has_lo = true; |
||||
ctxt1.trace_id.lo = 1; |
||||
ctxt1.trace_id.hi = 2; |
||||
ctxt1.has_span_id = true; |
||||
ctxt1.span_id = 3; |
||||
validate_encode_decode_context(&ctxt1, buffer, sizeof(buffer)); |
||||
|
||||
google_trace_TraceContext ctxt2 = google_trace_TraceContext_init_zero; |
||||
ctxt2.has_trace_id = true; |
||||
ctxt2.trace_id.has_hi = false; |
||||
ctxt2.trace_id.has_lo = false; |
||||
ctxt2.has_span_id = true; |
||||
validate_encode_decode_context(&ctxt2, buffer, sizeof(buffer)); |
||||
} |
||||
|
||||
// Test a corrupted proto-buffer.
|
||||
static void test_corrupt() { |
||||
uint8_t buffer[BUF_SIZE] = {0}; |
||||
google_trace_TraceContext ctxt1 = google_trace_TraceContext_init_zero; |
||||
size_t msg_length; |
||||
|
||||
ctxt1.has_trace_id = true; |
||||
ctxt1.trace_id.has_hi = true; |
||||
ctxt1.trace_id.has_lo = true; |
||||
ctxt1.trace_id.lo = 1; |
||||
ctxt1.trace_id.hi = 2; |
||||
ctxt1.has_span_id = true; |
||||
ctxt1.span_id = 3; |
||||
ctxt1.is_sampled = true; |
||||
msg_length = encode_trace_context(&ctxt1, buffer, sizeof(buffer)); |
||||
|
||||
/* Corrupt some bytes. 255 (0xFF) should be illegal for the first byte of the
|
||||
proto encoded object. */ |
||||
buffer[0] = 255; |
||||
|
||||
bool res = validate_decode_context(&ctxt1, buffer, msg_length); |
||||
GPR_ASSERT(res == false); |
||||
} |
||||
|
||||
static void test_buffer_size() { |
||||
// This buffer is too small, so the encode should fail.
|
||||
uint8_t buffer[16] = {0}; |
||||
google_trace_TraceContext ctxt1 = google_trace_TraceContext_init_zero; |
||||
size_t msg_length; |
||||
|
||||
ctxt1.has_trace_id = true; |
||||
ctxt1.trace_id.has_hi = true; |
||||
ctxt1.trace_id.has_lo = true; |
||||
ctxt1.trace_id.lo = 1; |
||||
ctxt1.trace_id.hi = 2; |
||||
ctxt1.has_span_id = true; |
||||
ctxt1.span_id = 3; |
||||
ctxt1.is_sampled = true; |
||||
msg_length = encode_trace_context(&ctxt1, buffer, sizeof(buffer)); |
||||
|
||||
GPR_ASSERT(msg_length == 0); |
||||
} |
||||
|
||||
int main(int argc, char **argv) { |
||||
grpc_test_init(argc, argv); |
||||
test_full(); |
||||
test_empty(); |
||||
test_trace_only(); |
||||
test_span_only(); |
||||
test_encode_decode(); |
||||
test_corrupt(); |
||||
test_no_sample(); |
||||
test_buffer_size(); |
||||
|
||||
return 0; |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue