mirror of https://github.com/grpc/grpc.git
commit
7a2c4d8927
31 changed files with 1350 additions and 18 deletions
@ -0,0 +1,112 @@ |
|||||||
|
/*
|
||||||
|
* |
||||||
|
* 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 <string.h> |
||||||
|
|
||||||
|
#include "src/core/lib/channel/channel_stack.h" |
||||||
|
#include "src/cpp/common/channel_filter.h" |
||||||
|
|
||||||
|
namespace grpc { |
||||||
|
|
||||||
|
// MetadataBatch
|
||||||
|
|
||||||
|
grpc_linked_mdelem *MetadataBatch::AddMetadata(const string &key, |
||||||
|
const string &value) { |
||||||
|
grpc_linked_mdelem *storage = new grpc_linked_mdelem; |
||||||
|
memset(storage, 0, sizeof(grpc_linked_mdelem)); |
||||||
|
storage->md = grpc_mdelem_from_strings(key.c_str(), value.c_str()); |
||||||
|
grpc_metadata_batch_link_head(batch_, storage); |
||||||
|
return storage; |
||||||
|
} |
||||||
|
|
||||||
|
// ChannelData
|
||||||
|
|
||||||
|
void ChannelData::StartTransportOp(grpc_exec_ctx *exec_ctx, |
||||||
|
grpc_channel_element *elem, |
||||||
|
TransportOp *op) { |
||||||
|
grpc_channel_next_op(exec_ctx, elem, op->op()); |
||||||
|
} |
||||||
|
|
||||||
|
// CallData
|
||||||
|
|
||||||
|
void CallData::StartTransportStreamOp(grpc_exec_ctx *exec_ctx, |
||||||
|
grpc_call_element *elem, |
||||||
|
TransportStreamOp *op) { |
||||||
|
grpc_call_next_op(exec_ctx, elem, op->op()); |
||||||
|
} |
||||||
|
|
||||||
|
void CallData::SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx, |
||||||
|
grpc_call_element *elem, |
||||||
|
grpc_polling_entity *pollent) { |
||||||
|
grpc_call_stack_ignore_set_pollset_or_pollset_set(exec_ctx, elem, pollent); |
||||||
|
} |
||||||
|
|
||||||
|
char *CallData::GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { |
||||||
|
return grpc_call_next_get_peer(exec_ctx, elem); |
||||||
|
} |
||||||
|
|
||||||
|
// internal code used by RegisterChannelFilter()
|
||||||
|
|
||||||
|
namespace internal { |
||||||
|
|
||||||
|
// Note: Implicitly initialized to nullptr due to static lifetime.
|
||||||
|
std::vector<FilterRecord> *channel_filters; |
||||||
|
|
||||||
|
namespace { |
||||||
|
|
||||||
|
bool MaybeAddFilter(grpc_channel_stack_builder *builder, void *arg) { |
||||||
|
const FilterRecord &filter = *(FilterRecord *)arg; |
||||||
|
if (filter.include_filter) { |
||||||
|
const grpc_channel_args *args = |
||||||
|
grpc_channel_stack_builder_get_channel_arguments(builder); |
||||||
|
if (!filter.include_filter(*args)) return true; |
||||||
|
} |
||||||
|
return grpc_channel_stack_builder_prepend_filter(builder, &filter.filter, |
||||||
|
nullptr, nullptr); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void ChannelFilterPluginInit() { |
||||||
|
for (size_t i = 0; i < channel_filters->size(); ++i) { |
||||||
|
FilterRecord &filter = (*channel_filters)[i]; |
||||||
|
grpc_channel_init_register_stage(filter.stack_type, filter.priority, |
||||||
|
MaybeAddFilter, (void *)&filter); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void ChannelFilterPluginShutdown() {} |
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
} // namespace grpc
|
@ -0,0 +1,386 @@ |
|||||||
|
/*
|
||||||
|
* |
||||||
|
* 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 GRPCXX_CHANNEL_FILTER_H |
||||||
|
#define GRPCXX_CHANNEL_FILTER_H |
||||||
|
|
||||||
|
#include <grpc++/impl/codegen/config.h> |
||||||
|
#include <grpc/census.h> |
||||||
|
#include <grpc/grpc.h> |
||||||
|
#include <grpc/impl/codegen/alloc.h> |
||||||
|
|
||||||
|
#include <functional> |
||||||
|
#include <vector> |
||||||
|
|
||||||
|
#include "src/core/lib/channel/channel_stack.h" |
||||||
|
#include "src/core/lib/security/context/security_context.h" |
||||||
|
#include "src/core/lib/surface/channel_init.h" |
||||||
|
#include "src/core/lib/transport/metadata_batch.h" |
||||||
|
|
||||||
|
/// An interface to define filters.
|
||||||
|
///
|
||||||
|
/// To define a filter, implement a subclass of each of \c CallData and
|
||||||
|
/// \c ChannelData. Then register the filter using something like this:
|
||||||
|
/// \code{.cpp}
|
||||||
|
/// RegisterChannelFilter<MyChannelDataSubclass, MyCallDataSubclass>(
|
||||||
|
/// "name-of-filter", GRPC_SERVER_CHANNEL, INT_MAX, nullptr);
|
||||||
|
/// \endcode
|
||||||
|
|
||||||
|
namespace grpc { |
||||||
|
|
||||||
|
/// A C++ wrapper for the \c grpc_metadata_batch struct.
|
||||||
|
class MetadataBatch { |
||||||
|
public: |
||||||
|
/// Borrows a pointer to \a batch, but does NOT take ownership.
|
||||||
|
/// The caller must ensure that \a batch continues to exist for as
|
||||||
|
/// long as the MetadataBatch object does.
|
||||||
|
explicit MetadataBatch(grpc_metadata_batch *batch) : batch_(batch) {} |
||||||
|
|
||||||
|
grpc_metadata_batch *batch() const { return batch_; } |
||||||
|
|
||||||
|
/// Adds metadata and returns the newly allocated storage.
|
||||||
|
/// The caller takes ownership of the result, which must exist for the
|
||||||
|
/// lifetime of the gRPC call.
|
||||||
|
grpc_linked_mdelem *AddMetadata(const string &key, const string &value); |
||||||
|
|
||||||
|
class const_iterator : public std::iterator<std::bidirectional_iterator_tag, |
||||||
|
const grpc_mdelem> { |
||||||
|
public: |
||||||
|
const grpc_mdelem &operator*() const { return *elem_->md; } |
||||||
|
const grpc_mdelem *operator->() const { return elem_->md; } |
||||||
|
|
||||||
|
const_iterator &operator++() { |
||||||
|
elem_ = elem_->next; |
||||||
|
return *this; |
||||||
|
} |
||||||
|
const_iterator operator++(int) { |
||||||
|
const_iterator tmp(*this); |
||||||
|
operator++(); |
||||||
|
return tmp; |
||||||
|
} |
||||||
|
const_iterator &operator--() { |
||||||
|
elem_ = elem_->prev; |
||||||
|
return *this; |
||||||
|
} |
||||||
|
const_iterator operator--(int) { |
||||||
|
const_iterator tmp(*this); |
||||||
|
operator--(); |
||||||
|
return tmp; |
||||||
|
} |
||||||
|
|
||||||
|
bool operator==(const const_iterator &other) const { |
||||||
|
return elem_ == other.elem_; |
||||||
|
} |
||||||
|
bool operator!=(const const_iterator &other) const { |
||||||
|
return elem_ != other.elem_; |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
friend class MetadataBatch; |
||||||
|
explicit const_iterator(grpc_linked_mdelem *elem) : elem_(elem) {} |
||||||
|
|
||||||
|
grpc_linked_mdelem *elem_; |
||||||
|
}; |
||||||
|
|
||||||
|
const_iterator begin() const { return const_iterator(batch_->list.head); } |
||||||
|
const_iterator end() const { return const_iterator(nullptr); } |
||||||
|
|
||||||
|
private: |
||||||
|
grpc_metadata_batch *batch_; // Not owned.
|
||||||
|
}; |
||||||
|
|
||||||
|
/// A C++ wrapper for the \c grpc_transport_op struct.
|
||||||
|
class TransportOp { |
||||||
|
public: |
||||||
|
/// Borrows a pointer to \a op, but does NOT take ownership.
|
||||||
|
/// The caller must ensure that \a op continues to exist for as
|
||||||
|
/// long as the TransportOp object does.
|
||||||
|
explicit TransportOp(grpc_transport_op *op) : op_(op) {} |
||||||
|
|
||||||
|
grpc_transport_op *op() const { return op_; } |
||||||
|
|
||||||
|
// TODO(roth): Add a C++ wrapper for grpc_error?
|
||||||
|
grpc_error *disconnect_with_error() const { |
||||||
|
return op_->disconnect_with_error; |
||||||
|
} |
||||||
|
bool send_goaway() const { return op_->send_goaway; } |
||||||
|
|
||||||
|
// TODO(roth): Add methods for additional fields as needed.
|
||||||
|
|
||||||
|
private: |
||||||
|
grpc_transport_op *op_; // Not owned.
|
||||||
|
}; |
||||||
|
|
||||||
|
/// A C++ wrapper for the \c grpc_transport_stream_op struct.
|
||||||
|
class TransportStreamOp { |
||||||
|
public: |
||||||
|
/// Borrows a pointer to \a op, but does NOT take ownership.
|
||||||
|
/// The caller must ensure that \a op continues to exist for as
|
||||||
|
/// long as the TransportStreamOp object does.
|
||||||
|
explicit TransportStreamOp(grpc_transport_stream_op *op) |
||||||
|
: op_(op), |
||||||
|
send_initial_metadata_(op->send_initial_metadata), |
||||||
|
send_trailing_metadata_(op->send_trailing_metadata), |
||||||
|
recv_initial_metadata_(op->recv_initial_metadata), |
||||||
|
recv_trailing_metadata_(op->recv_trailing_metadata) {} |
||||||
|
|
||||||
|
grpc_transport_stream_op *op() const { return op_; } |
||||||
|
|
||||||
|
grpc_closure *on_complete() const { return op_->on_complete; } |
||||||
|
void set_on_complete(grpc_closure *closure) { op_->on_complete = closure; } |
||||||
|
|
||||||
|
MetadataBatch *send_initial_metadata() { |
||||||
|
return op_->send_initial_metadata == nullptr ? nullptr |
||||||
|
: &send_initial_metadata_; |
||||||
|
} |
||||||
|
MetadataBatch *send_trailing_metadata() { |
||||||
|
return op_->send_trailing_metadata == nullptr ? nullptr |
||||||
|
: &send_trailing_metadata_; |
||||||
|
} |
||||||
|
MetadataBatch *recv_initial_metadata() { |
||||||
|
return op_->recv_initial_metadata == nullptr ? nullptr |
||||||
|
: &recv_initial_metadata_; |
||||||
|
} |
||||||
|
MetadataBatch *recv_trailing_metadata() { |
||||||
|
return op_->recv_trailing_metadata == nullptr ? nullptr |
||||||
|
: &recv_trailing_metadata_; |
||||||
|
} |
||||||
|
|
||||||
|
uint32_t *send_initial_metadata_flags() const { |
||||||
|
return &op_->send_initial_metadata_flags; |
||||||
|
} |
||||||
|
|
||||||
|
grpc_closure *recv_initial_metadata_ready() const { |
||||||
|
return op_->recv_initial_metadata_ready; |
||||||
|
} |
||||||
|
void set_recv_initial_metadata_ready(grpc_closure *closure) { |
||||||
|
op_->recv_initial_metadata_ready = closure; |
||||||
|
} |
||||||
|
|
||||||
|
grpc_byte_stream *send_message() const { return op_->send_message; } |
||||||
|
void set_send_message(grpc_byte_stream *send_message) { |
||||||
|
op_->send_message = send_message; |
||||||
|
} |
||||||
|
|
||||||
|
/// To be called only on clients and servers, respectively.
|
||||||
|
grpc_client_security_context *client_security_context() const { |
||||||
|
return (grpc_client_security_context *)op_->context[GRPC_CONTEXT_SECURITY] |
||||||
|
.value; |
||||||
|
} |
||||||
|
grpc_server_security_context *server_security_context() const { |
||||||
|
return (grpc_server_security_context *)op_->context[GRPC_CONTEXT_SECURITY] |
||||||
|
.value; |
||||||
|
} |
||||||
|
|
||||||
|
census_context *get_census_context() const { |
||||||
|
return (census_context *)op_->context[GRPC_CONTEXT_TRACING].value; |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
grpc_transport_stream_op *op_; // Not owned.
|
||||||
|
MetadataBatch send_initial_metadata_; |
||||||
|
MetadataBatch send_trailing_metadata_; |
||||||
|
MetadataBatch recv_initial_metadata_; |
||||||
|
MetadataBatch recv_trailing_metadata_; |
||||||
|
}; |
||||||
|
|
||||||
|
/// Represents channel data.
|
||||||
|
class ChannelData { |
||||||
|
public: |
||||||
|
virtual ~ChannelData() { |
||||||
|
if (peer_) gpr_free((void *)peer_); |
||||||
|
} |
||||||
|
|
||||||
|
/// Caller does NOT take ownership of result.
|
||||||
|
const char *peer() const { return peer_; } |
||||||
|
|
||||||
|
// TODO(roth): Find a way to avoid passing elem into these methods.
|
||||||
|
virtual void StartTransportOp(grpc_exec_ctx *exec_ctx, |
||||||
|
grpc_channel_element *elem, TransportOp *op); |
||||||
|
|
||||||
|
protected: |
||||||
|
/// Takes ownership of \a peer.
|
||||||
|
ChannelData(const grpc_channel_args &args, const char *peer) : peer_(peer) {} |
||||||
|
|
||||||
|
private: |
||||||
|
const char *peer_; |
||||||
|
}; |
||||||
|
|
||||||
|
/// Represents call data.
|
||||||
|
class CallData { |
||||||
|
public: |
||||||
|
virtual ~CallData() {} |
||||||
|
|
||||||
|
/// Initializes the call data.
|
||||||
|
virtual grpc_error *Init() { return GRPC_ERROR_NONE; } |
||||||
|
|
||||||
|
// TODO(roth): Find a way to avoid passing elem into these methods.
|
||||||
|
|
||||||
|
/// Starts a new stream operation.
|
||||||
|
virtual void StartTransportStreamOp(grpc_exec_ctx *exec_ctx, |
||||||
|
grpc_call_element *elem, |
||||||
|
TransportStreamOp *op); |
||||||
|
|
||||||
|
/// Sets a pollset or pollset set.
|
||||||
|
virtual void SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx, |
||||||
|
grpc_call_element *elem, |
||||||
|
grpc_polling_entity *pollent); |
||||||
|
|
||||||
|
/// Gets the peer name.
|
||||||
|
virtual char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem); |
||||||
|
|
||||||
|
protected: |
||||||
|
explicit CallData(const ChannelData &) {} |
||||||
|
}; |
||||||
|
|
||||||
|
namespace internal { |
||||||
|
|
||||||
|
// Defines static members for passing to C core.
|
||||||
|
// Members of this class correspond to the members of the C
|
||||||
|
// grpc_channel_filter struct.
|
||||||
|
template <typename ChannelDataType, typename CallDataType> |
||||||
|
class ChannelFilter GRPC_FINAL { |
||||||
|
public: |
||||||
|
static const size_t channel_data_size = sizeof(ChannelDataType); |
||||||
|
|
||||||
|
static void InitChannelElement(grpc_exec_ctx *exec_ctx, |
||||||
|
grpc_channel_element *elem, |
||||||
|
grpc_channel_element_args *args) { |
||||||
|
const char *peer = |
||||||
|
args->optional_transport |
||||||
|
? grpc_transport_get_peer(exec_ctx, args->optional_transport) |
||||||
|
: nullptr; |
||||||
|
// Construct the object in the already-allocated memory.
|
||||||
|
new (elem->channel_data) ChannelDataType(*args->channel_args, peer); |
||||||
|
} |
||||||
|
|
||||||
|
static void DestroyChannelElement(grpc_exec_ctx *exec_ctx, |
||||||
|
grpc_channel_element *elem) { |
||||||
|
reinterpret_cast<ChannelDataType *>(elem->channel_data)->~ChannelDataType(); |
||||||
|
} |
||||||
|
|
||||||
|
static void StartTransportOp(grpc_exec_ctx *exec_ctx, |
||||||
|
grpc_channel_element *elem, |
||||||
|
grpc_transport_op *op) { |
||||||
|
ChannelDataType *channel_data = (ChannelDataType *)elem->channel_data; |
||||||
|
TransportOp op_wrapper(op); |
||||||
|
channel_data->StartTransportOp(exec_ctx, elem, &op_wrapper); |
||||||
|
} |
||||||
|
|
||||||
|
static const size_t call_data_size = sizeof(CallDataType); |
||||||
|
|
||||||
|
static grpc_error *InitCallElement(grpc_exec_ctx *exec_ctx, |
||||||
|
grpc_call_element *elem, |
||||||
|
grpc_call_element_args *args) { |
||||||
|
const ChannelDataType &channel_data = |
||||||
|
*(ChannelDataType *)elem->channel_data; |
||||||
|
// Construct the object in the already-allocated memory.
|
||||||
|
CallDataType *call_data = new (elem->call_data) CallDataType(channel_data); |
||||||
|
return call_data->Init(); |
||||||
|
} |
||||||
|
|
||||||
|
static void DestroyCallElement(grpc_exec_ctx *exec_ctx, |
||||||
|
grpc_call_element *elem, |
||||||
|
const grpc_call_final_info *final_info, |
||||||
|
void *and_free_memory) { |
||||||
|
reinterpret_cast<CallDataType *>(elem->call_data)->~CallDataType(); |
||||||
|
} |
||||||
|
|
||||||
|
static void StartTransportStreamOp(grpc_exec_ctx *exec_ctx, |
||||||
|
grpc_call_element *elem, |
||||||
|
grpc_transport_stream_op *op) { |
||||||
|
CallDataType *call_data = (CallDataType *)elem->call_data; |
||||||
|
TransportStreamOp op_wrapper(op); |
||||||
|
call_data->StartTransportStreamOp(exec_ctx, elem, &op_wrapper); |
||||||
|
} |
||||||
|
|
||||||
|
static void SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx, |
||||||
|
grpc_call_element *elem, |
||||||
|
grpc_polling_entity *pollent) { |
||||||
|
CallDataType *call_data = (CallDataType *)elem->call_data; |
||||||
|
call_data->SetPollsetOrPollsetSet(exec_ctx, elem, pollent); |
||||||
|
} |
||||||
|
|
||||||
|
static char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { |
||||||
|
CallDataType *call_data = (CallDataType *)elem->call_data; |
||||||
|
return call_data->GetPeer(exec_ctx, elem); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
struct FilterRecord { |
||||||
|
grpc_channel_stack_type stack_type; |
||||||
|
int priority; |
||||||
|
std::function<bool(const grpc_channel_args &)> include_filter; |
||||||
|
grpc_channel_filter filter; |
||||||
|
}; |
||||||
|
extern std::vector<FilterRecord> *channel_filters; |
||||||
|
|
||||||
|
void ChannelFilterPluginInit(); |
||||||
|
void ChannelFilterPluginShutdown(); |
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
/// Registers a new filter.
|
||||||
|
/// Must be called by only one thread at a time.
|
||||||
|
/// The \a include_filter argument specifies a function that will be called
|
||||||
|
/// to determine at run-time whether or not to add the filter. If the
|
||||||
|
/// value is nullptr, the filter will be added unconditionally.
|
||||||
|
template <typename ChannelDataType, typename CallDataType> |
||||||
|
void RegisterChannelFilter( |
||||||
|
const char *name, grpc_channel_stack_type stack_type, int priority, |
||||||
|
std::function<bool(const grpc_channel_args &)> include_filter) { |
||||||
|
// If we haven't been called before, initialize channel_filters and
|
||||||
|
// call grpc_register_plugin().
|
||||||
|
if (internal::channel_filters == nullptr) { |
||||||
|
grpc_register_plugin(internal::ChannelFilterPluginInit, |
||||||
|
internal::ChannelFilterPluginShutdown); |
||||||
|
internal::channel_filters = new std::vector<internal::FilterRecord>(); |
||||||
|
} |
||||||
|
// Add an entry to channel_filters. The filter will be added when the
|
||||||
|
// C-core initialization code calls ChannelFilterPluginInit().
|
||||||
|
typedef internal::ChannelFilter<ChannelDataType, CallDataType> FilterType; |
||||||
|
internal::FilterRecord filter_record = { |
||||||
|
stack_type, |
||||||
|
priority, |
||||||
|
include_filter, |
||||||
|
{FilterType::StartTransportStreamOp, FilterType::StartTransportOp, |
||||||
|
FilterType::call_data_size, FilterType::InitCallElement, |
||||||
|
FilterType::SetPollsetOrPollsetSet, FilterType::DestroyCallElement, |
||||||
|
FilterType::channel_data_size, FilterType::InitChannelElement, |
||||||
|
FilterType::DestroyChannelElement, FilterType::GetPeer, name}}; |
||||||
|
internal::channel_filters->push_back(filter_record); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace grpc
|
||||||
|
|
||||||
|
#endif // GRPCXX_CHANNEL_FILTER_H
|
@ -0,0 +1,48 @@ |
|||||||
|
# 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. |
||||||
|
|
||||||
|
import threading |
||||||
|
from concurrent import futures |
||||||
|
|
||||||
|
|
||||||
|
class RecordingThreadPool(futures.Executor): |
||||||
|
"""A thread pool that records if used.""" |
||||||
|
def __init__(self, max_workers): |
||||||
|
self._tp_executor = futures.ThreadPoolExecutor(max_workers=max_workers) |
||||||
|
self._lock = threading.Lock() |
||||||
|
self._was_used = False |
||||||
|
|
||||||
|
def submit(self, fn, *args, **kwargs): |
||||||
|
with self._lock: |
||||||
|
self._was_used = True |
||||||
|
self._tp_executor.submit(fn, *args, **kwargs) |
||||||
|
|
||||||
|
def was_used(self): |
||||||
|
with self._lock: |
||||||
|
return self._was_used |
@ -0,0 +1,353 @@ |
|||||||
|
/*
|
||||||
|
* |
||||||
|
* 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 <memory> |
||||||
|
#include <mutex> |
||||||
|
|
||||||
|
#include <grpc++/channel.h> |
||||||
|
#include <grpc++/client_context.h> |
||||||
|
#include <grpc++/create_channel.h> |
||||||
|
#include <grpc++/generic/async_generic_service.h> |
||||||
|
#include <grpc++/generic/generic_stub.h> |
||||||
|
#include <grpc++/impl/codegen/proto_utils.h> |
||||||
|
#include <grpc++/server.h> |
||||||
|
#include <grpc++/server_builder.h> |
||||||
|
#include <grpc++/server_context.h> |
||||||
|
#include <grpc++/support/config.h> |
||||||
|
#include <grpc++/support/slice.h> |
||||||
|
#include <grpc/grpc.h> |
||||||
|
#include <grpc/support/thd.h> |
||||||
|
#include <grpc/support/time.h> |
||||||
|
#include <gtest/gtest.h> |
||||||
|
|
||||||
|
#include "src/cpp/common/channel_filter.h" |
||||||
|
#include "src/proto/grpc/testing/echo.grpc.pb.h" |
||||||
|
#include "test/core/util/port.h" |
||||||
|
#include "test/core/util/test_config.h" |
||||||
|
#include "test/cpp/util/byte_buffer_proto_helper.h" |
||||||
|
|
||||||
|
using grpc::testing::EchoRequest; |
||||||
|
using grpc::testing::EchoResponse; |
||||||
|
using std::chrono::system_clock; |
||||||
|
|
||||||
|
namespace grpc { |
||||||
|
namespace testing { |
||||||
|
namespace { |
||||||
|
|
||||||
|
void* tag(int i) { return (void*)(intptr_t)i; } |
||||||
|
|
||||||
|
void verify_ok(CompletionQueue* cq, int i, bool expect_ok) { |
||||||
|
bool ok; |
||||||
|
void* got_tag; |
||||||
|
EXPECT_TRUE(cq->Next(&got_tag, &ok)); |
||||||
|
EXPECT_EQ(expect_ok, ok); |
||||||
|
EXPECT_EQ(tag(i), got_tag); |
||||||
|
} |
||||||
|
|
||||||
|
namespace { |
||||||
|
|
||||||
|
int global_num_connections = 0; |
||||||
|
int global_num_calls = 0; |
||||||
|
mutex global_mu; |
||||||
|
|
||||||
|
void IncrementConnectionCounter() { |
||||||
|
unique_lock<mutex> lock(global_mu); |
||||||
|
++global_num_connections; |
||||||
|
} |
||||||
|
|
||||||
|
void ResetConnectionCounter() { |
||||||
|
unique_lock<mutex> lock(global_mu); |
||||||
|
global_num_connections = 0; |
||||||
|
} |
||||||
|
|
||||||
|
int GetConnectionCounterValue() { |
||||||
|
unique_lock<mutex> lock(global_mu); |
||||||
|
return global_num_connections; |
||||||
|
} |
||||||
|
|
||||||
|
void IncrementCallCounter() { |
||||||
|
unique_lock<mutex> lock(global_mu); |
||||||
|
++global_num_calls; |
||||||
|
} |
||||||
|
|
||||||
|
void ResetCallCounter() { |
||||||
|
unique_lock<mutex> lock(global_mu); |
||||||
|
global_num_calls = 0; |
||||||
|
} |
||||||
|
|
||||||
|
int GetCallCounterValue() { |
||||||
|
unique_lock<mutex> lock(global_mu); |
||||||
|
return global_num_calls; |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
class ChannelDataImpl : public ChannelData { |
||||||
|
public: |
||||||
|
ChannelDataImpl(const grpc_channel_args& args, const char* peer) |
||||||
|
: ChannelData(args, peer) { |
||||||
|
IncrementConnectionCounter(); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
class CallDataImpl : public CallData { |
||||||
|
public: |
||||||
|
explicit CallDataImpl(const ChannelDataImpl& channel_data) |
||||||
|
: CallData(channel_data) {} |
||||||
|
|
||||||
|
void StartTransportStreamOp(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, |
||||||
|
TransportStreamOp* op) GRPC_OVERRIDE { |
||||||
|
// Incrementing the counter could be done from the ctor, but we want
|
||||||
|
// to test that the individual methods are actually called correctly.
|
||||||
|
if (op->recv_initial_metadata() != nullptr) IncrementCallCounter(); |
||||||
|
grpc_call_next_op(exec_ctx, elem, op->op()); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
class FilterEnd2endTest : public ::testing::Test { |
||||||
|
protected: |
||||||
|
FilterEnd2endTest() : server_host_("localhost") {} |
||||||
|
|
||||||
|
void SetUp() GRPC_OVERRIDE { |
||||||
|
int port = grpc_pick_unused_port_or_die(); |
||||||
|
server_address_ << server_host_ << ":" << port; |
||||||
|
// Setup server
|
||||||
|
ServerBuilder builder; |
||||||
|
builder.AddListeningPort(server_address_.str(), |
||||||
|
InsecureServerCredentials()); |
||||||
|
builder.RegisterAsyncGenericService(&generic_service_); |
||||||
|
srv_cq_ = builder.AddCompletionQueue(); |
||||||
|
server_ = builder.BuildAndStart(); |
||||||
|
} |
||||||
|
|
||||||
|
void TearDown() GRPC_OVERRIDE { |
||||||
|
server_->Shutdown(); |
||||||
|
void* ignored_tag; |
||||||
|
bool ignored_ok; |
||||||
|
cli_cq_.Shutdown(); |
||||||
|
srv_cq_->Shutdown(); |
||||||
|
while (cli_cq_.Next(&ignored_tag, &ignored_ok)) |
||||||
|
; |
||||||
|
while (srv_cq_->Next(&ignored_tag, &ignored_ok)) |
||||||
|
; |
||||||
|
} |
||||||
|
|
||||||
|
void ResetStub() { |
||||||
|
std::shared_ptr<Channel> channel = |
||||||
|
CreateChannel(server_address_.str(), InsecureChannelCredentials()); |
||||||
|
generic_stub_.reset(new GenericStub(channel)); |
||||||
|
ResetConnectionCounter(); |
||||||
|
ResetCallCounter(); |
||||||
|
} |
||||||
|
|
||||||
|
void server_ok(int i) { verify_ok(srv_cq_.get(), i, true); } |
||||||
|
void client_ok(int i) { verify_ok(&cli_cq_, i, true); } |
||||||
|
void server_fail(int i) { verify_ok(srv_cq_.get(), i, false); } |
||||||
|
void client_fail(int i) { verify_ok(&cli_cq_, i, false); } |
||||||
|
|
||||||
|
void SendRpc(int num_rpcs) { |
||||||
|
const grpc::string kMethodName("/grpc.cpp.test.util.EchoTestService/Echo"); |
||||||
|
for (int i = 0; i < num_rpcs; i++) { |
||||||
|
EchoRequest send_request; |
||||||
|
EchoRequest recv_request; |
||||||
|
EchoResponse send_response; |
||||||
|
EchoResponse recv_response; |
||||||
|
Status recv_status; |
||||||
|
|
||||||
|
ClientContext cli_ctx; |
||||||
|
GenericServerContext srv_ctx; |
||||||
|
GenericServerAsyncReaderWriter stream(&srv_ctx); |
||||||
|
|
||||||
|
// The string needs to be long enough to test heap-based slice.
|
||||||
|
send_request.set_message("Hello world. Hello world. Hello world."); |
||||||
|
std::unique_ptr<GenericClientAsyncReaderWriter> call = |
||||||
|
generic_stub_->Call(&cli_ctx, kMethodName, &cli_cq_, tag(1)); |
||||||
|
client_ok(1); |
||||||
|
std::unique_ptr<ByteBuffer> send_buffer = |
||||||
|
SerializeToByteBuffer(&send_request); |
||||||
|
call->Write(*send_buffer, tag(2)); |
||||||
|
// Send ByteBuffer can be destroyed after calling Write.
|
||||||
|
send_buffer.reset(); |
||||||
|
client_ok(2); |
||||||
|
call->WritesDone(tag(3)); |
||||||
|
client_ok(3); |
||||||
|
|
||||||
|
generic_service_.RequestCall(&srv_ctx, &stream, srv_cq_.get(), |
||||||
|
srv_cq_.get(), tag(4)); |
||||||
|
|
||||||
|
verify_ok(srv_cq_.get(), 4, true); |
||||||
|
EXPECT_EQ(server_host_, srv_ctx.host().substr(0, server_host_.length())); |
||||||
|
EXPECT_EQ(kMethodName, srv_ctx.method()); |
||||||
|
ByteBuffer recv_buffer; |
||||||
|
stream.Read(&recv_buffer, tag(5)); |
||||||
|
server_ok(5); |
||||||
|
EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_request)); |
||||||
|
EXPECT_EQ(send_request.message(), recv_request.message()); |
||||||
|
|
||||||
|
send_response.set_message(recv_request.message()); |
||||||
|
send_buffer = SerializeToByteBuffer(&send_response); |
||||||
|
stream.Write(*send_buffer, tag(6)); |
||||||
|
send_buffer.reset(); |
||||||
|
server_ok(6); |
||||||
|
|
||||||
|
stream.Finish(Status::OK, tag(7)); |
||||||
|
server_ok(7); |
||||||
|
|
||||||
|
recv_buffer.Clear(); |
||||||
|
call->Read(&recv_buffer, tag(8)); |
||||||
|
client_ok(8); |
||||||
|
EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_response)); |
||||||
|
|
||||||
|
call->Finish(&recv_status, tag(9)); |
||||||
|
client_ok(9); |
||||||
|
|
||||||
|
EXPECT_EQ(send_response.message(), recv_response.message()); |
||||||
|
EXPECT_TRUE(recv_status.ok()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
CompletionQueue cli_cq_; |
||||||
|
std::unique_ptr<ServerCompletionQueue> srv_cq_; |
||||||
|
std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; |
||||||
|
std::unique_ptr<grpc::GenericStub> generic_stub_; |
||||||
|
std::unique_ptr<Server> server_; |
||||||
|
AsyncGenericService generic_service_; |
||||||
|
const grpc::string server_host_; |
||||||
|
std::ostringstream server_address_; |
||||||
|
}; |
||||||
|
|
||||||
|
TEST_F(FilterEnd2endTest, SimpleRpc) { |
||||||
|
ResetStub(); |
||||||
|
EXPECT_EQ(0, GetConnectionCounterValue()); |
||||||
|
EXPECT_EQ(0, GetCallCounterValue()); |
||||||
|
SendRpc(1); |
||||||
|
EXPECT_EQ(1, GetConnectionCounterValue()); |
||||||
|
EXPECT_EQ(1, GetCallCounterValue()); |
||||||
|
} |
||||||
|
|
||||||
|
TEST_F(FilterEnd2endTest, SequentialRpcs) { |
||||||
|
ResetStub(); |
||||||
|
EXPECT_EQ(0, GetConnectionCounterValue()); |
||||||
|
EXPECT_EQ(0, GetCallCounterValue()); |
||||||
|
SendRpc(10); |
||||||
|
EXPECT_EQ(1, GetConnectionCounterValue()); |
||||||
|
EXPECT_EQ(10, GetCallCounterValue()); |
||||||
|
} |
||||||
|
|
||||||
|
// One ping, one pong.
|
||||||
|
TEST_F(FilterEnd2endTest, SimpleBidiStreaming) { |
||||||
|
ResetStub(); |
||||||
|
EXPECT_EQ(0, GetConnectionCounterValue()); |
||||||
|
EXPECT_EQ(0, GetCallCounterValue()); |
||||||
|
|
||||||
|
const grpc::string kMethodName( |
||||||
|
"/grpc.cpp.test.util.EchoTestService/BidiStream"); |
||||||
|
EchoRequest send_request; |
||||||
|
EchoRequest recv_request; |
||||||
|
EchoResponse send_response; |
||||||
|
EchoResponse recv_response; |
||||||
|
Status recv_status; |
||||||
|
ClientContext cli_ctx; |
||||||
|
GenericServerContext srv_ctx; |
||||||
|
GenericServerAsyncReaderWriter srv_stream(&srv_ctx); |
||||||
|
|
||||||
|
cli_ctx.set_compression_algorithm(GRPC_COMPRESS_GZIP); |
||||||
|
send_request.set_message("Hello"); |
||||||
|
std::unique_ptr<GenericClientAsyncReaderWriter> cli_stream = |
||||||
|
generic_stub_->Call(&cli_ctx, kMethodName, &cli_cq_, tag(1)); |
||||||
|
client_ok(1); |
||||||
|
|
||||||
|
generic_service_.RequestCall(&srv_ctx, &srv_stream, srv_cq_.get(), |
||||||
|
srv_cq_.get(), tag(2)); |
||||||
|
|
||||||
|
verify_ok(srv_cq_.get(), 2, true); |
||||||
|
EXPECT_EQ(server_host_, srv_ctx.host().substr(0, server_host_.length())); |
||||||
|
EXPECT_EQ(kMethodName, srv_ctx.method()); |
||||||
|
|
||||||
|
std::unique_ptr<ByteBuffer> send_buffer = |
||||||
|
SerializeToByteBuffer(&send_request); |
||||||
|
cli_stream->Write(*send_buffer, tag(3)); |
||||||
|
send_buffer.reset(); |
||||||
|
client_ok(3); |
||||||
|
|
||||||
|
ByteBuffer recv_buffer; |
||||||
|
srv_stream.Read(&recv_buffer, tag(4)); |
||||||
|
server_ok(4); |
||||||
|
EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_request)); |
||||||
|
EXPECT_EQ(send_request.message(), recv_request.message()); |
||||||
|
|
||||||
|
send_response.set_message(recv_request.message()); |
||||||
|
send_buffer = SerializeToByteBuffer(&send_response); |
||||||
|
srv_stream.Write(*send_buffer, tag(5)); |
||||||
|
send_buffer.reset(); |
||||||
|
server_ok(5); |
||||||
|
|
||||||
|
cli_stream->Read(&recv_buffer, tag(6)); |
||||||
|
client_ok(6); |
||||||
|
EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_response)); |
||||||
|
EXPECT_EQ(send_response.message(), recv_response.message()); |
||||||
|
|
||||||
|
cli_stream->WritesDone(tag(7)); |
||||||
|
client_ok(7); |
||||||
|
|
||||||
|
srv_stream.Read(&recv_buffer, tag(8)); |
||||||
|
server_fail(8); |
||||||
|
|
||||||
|
srv_stream.Finish(Status::OK, tag(9)); |
||||||
|
server_ok(9); |
||||||
|
|
||||||
|
cli_stream->Finish(&recv_status, tag(10)); |
||||||
|
client_ok(10); |
||||||
|
|
||||||
|
EXPECT_EQ(send_response.message(), recv_response.message()); |
||||||
|
EXPECT_TRUE(recv_status.ok()); |
||||||
|
|
||||||
|
EXPECT_EQ(1, GetCallCounterValue()); |
||||||
|
EXPECT_EQ(1, GetConnectionCounterValue()); |
||||||
|
} |
||||||
|
|
||||||
|
void RegisterFilter() { |
||||||
|
grpc::RegisterChannelFilter<ChannelDataImpl, CallDataImpl>( |
||||||
|
"test-filter", GRPC_SERVER_CHANNEL, INT_MAX, nullptr); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace testing
|
||||||
|
} // namespace grpc
|
||||||
|
|
||||||
|
int main(int argc, char** argv) { |
||||||
|
grpc_test_init(argc, argv); |
||||||
|
::testing::InitGoogleTest(&argc, argv); |
||||||
|
grpc::testing::RegisterFilter(); |
||||||
|
return RUN_ALL_TESTS(); |
||||||
|
} |
@ -0,0 +1,207 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||||
|
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" /> |
||||||
|
<ItemGroup Label="ProjectConfigurations"> |
||||||
|
<ProjectConfiguration Include="Debug|Win32"> |
||||||
|
<Configuration>Debug</Configuration> |
||||||
|
<Platform>Win32</Platform> |
||||||
|
</ProjectConfiguration> |
||||||
|
<ProjectConfiguration Include="Debug|x64"> |
||||||
|
<Configuration>Debug</Configuration> |
||||||
|
<Platform>x64</Platform> |
||||||
|
</ProjectConfiguration> |
||||||
|
<ProjectConfiguration Include="Release|Win32"> |
||||||
|
<Configuration>Release</Configuration> |
||||||
|
<Platform>Win32</Platform> |
||||||
|
</ProjectConfiguration> |
||||||
|
<ProjectConfiguration Include="Release|x64"> |
||||||
|
<Configuration>Release</Configuration> |
||||||
|
<Platform>x64</Platform> |
||||||
|
</ProjectConfiguration> |
||||||
|
</ItemGroup> |
||||||
|
<PropertyGroup Label="Globals"> |
||||||
|
<ProjectGuid>{1D42975A-18A5-09D0-30B1-2AE6A97FB9DE}</ProjectGuid> |
||||||
|
<IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected> |
||||||
|
<IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir> |
||||||
|
</PropertyGroup> |
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> |
||||||
|
<PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration"> |
||||||
|
<PlatformToolset>v100</PlatformToolset> |
||||||
|
</PropertyGroup> |
||||||
|
<PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration"> |
||||||
|
<PlatformToolset>v110</PlatformToolset> |
||||||
|
</PropertyGroup> |
||||||
|
<PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration"> |
||||||
|
<PlatformToolset>v120</PlatformToolset> |
||||||
|
</PropertyGroup> |
||||||
|
<PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration"> |
||||||
|
<PlatformToolset>v140</PlatformToolset> |
||||||
|
</PropertyGroup> |
||||||
|
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration"> |
||||||
|
<ConfigurationType>Application</ConfigurationType> |
||||||
|
<UseDebugLibraries>true</UseDebugLibraries> |
||||||
|
<CharacterSet>Unicode</CharacterSet> |
||||||
|
</PropertyGroup> |
||||||
|
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration"> |
||||||
|
<ConfigurationType>Application</ConfigurationType> |
||||||
|
<UseDebugLibraries>false</UseDebugLibraries> |
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization> |
||||||
|
<CharacterSet>Unicode</CharacterSet> |
||||||
|
</PropertyGroup> |
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> |
||||||
|
<ImportGroup Label="ExtensionSettings"> |
||||||
|
</ImportGroup> |
||||||
|
<ImportGroup Label="PropertySheets"> |
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> |
||||||
|
<Import Project="$(SolutionDir)\..\vsprojects\cpptest.props" /> |
||||||
|
<Import Project="$(SolutionDir)\..\vsprojects\global.props" /> |
||||||
|
<Import Project="$(SolutionDir)\..\vsprojects\openssl.props" /> |
||||||
|
<Import Project="$(SolutionDir)\..\vsprojects\protobuf.props" /> |
||||||
|
<Import Project="$(SolutionDir)\..\vsprojects\winsock.props" /> |
||||||
|
<Import Project="$(SolutionDir)\..\vsprojects\zlib.props" /> |
||||||
|
</ImportGroup> |
||||||
|
<PropertyGroup Label="UserMacros" /> |
||||||
|
<PropertyGroup Condition="'$(Configuration)'=='Debug'"> |
||||||
|
<TargetName>filter_end2end_test</TargetName> |
||||||
|
<Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib> |
||||||
|
<Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib> |
||||||
|
<Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl> |
||||||
|
<Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl> |
||||||
|
</PropertyGroup> |
||||||
|
<PropertyGroup Condition="'$(Configuration)'=='Release'"> |
||||||
|
<TargetName>filter_end2end_test</TargetName> |
||||||
|
<Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib> |
||||||
|
<Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib> |
||||||
|
<Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl> |
||||||
|
<Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl> |
||||||
|
</PropertyGroup> |
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> |
||||||
|
<ClCompile> |
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader> |
||||||
|
<WarningLevel>Level3</WarningLevel> |
||||||
|
<Optimization>Disabled</Optimization> |
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
||||||
|
<SDLCheck>true</SDLCheck> |
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> |
||||||
|
<TreatWarningAsError>true</TreatWarningAsError> |
||||||
|
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat> |
||||||
|
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild> |
||||||
|
</ClCompile> |
||||||
|
<Link> |
||||||
|
<SubSystem>Console</SubSystem> |
||||||
|
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation> |
||||||
|
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation> |
||||||
|
</Link> |
||||||
|
</ItemDefinitionGroup> |
||||||
|
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> |
||||||
|
<ClCompile> |
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader> |
||||||
|
<WarningLevel>Level3</WarningLevel> |
||||||
|
<Optimization>Disabled</Optimization> |
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
||||||
|
<SDLCheck>true</SDLCheck> |
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> |
||||||
|
<TreatWarningAsError>true</TreatWarningAsError> |
||||||
|
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat> |
||||||
|
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild> |
||||||
|
</ClCompile> |
||||||
|
<Link> |
||||||
|
<SubSystem>Console</SubSystem> |
||||||
|
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation> |
||||||
|
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation> |
||||||
|
</Link> |
||||||
|
</ItemDefinitionGroup> |
||||||
|
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> |
||||||
|
<ClCompile> |
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader> |
||||||
|
<WarningLevel>Level3</WarningLevel> |
||||||
|
<Optimization>MaxSpeed</Optimization> |
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking> |
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions> |
||||||
|
<SDLCheck>true</SDLCheck> |
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> |
||||||
|
<TreatWarningAsError>true</TreatWarningAsError> |
||||||
|
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat> |
||||||
|
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild> |
||||||
|
</ClCompile> |
||||||
|
<Link> |
||||||
|
<SubSystem>Console</SubSystem> |
||||||
|
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation> |
||||||
|
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation> |
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding> |
||||||
|
<OptimizeReferences>true</OptimizeReferences> |
||||||
|
</Link> |
||||||
|
</ItemDefinitionGroup> |
||||||
|
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> |
||||||
|
<ClCompile> |
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader> |
||||||
|
<WarningLevel>Level3</WarningLevel> |
||||||
|
<Optimization>MaxSpeed</Optimization> |
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking> |
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions> |
||||||
|
<SDLCheck>true</SDLCheck> |
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> |
||||||
|
<TreatWarningAsError>true</TreatWarningAsError> |
||||||
|
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat> |
||||||
|
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild> |
||||||
|
</ClCompile> |
||||||
|
<Link> |
||||||
|
<SubSystem>Console</SubSystem> |
||||||
|
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation> |
||||||
|
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation> |
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding> |
||||||
|
<OptimizeReferences>true</OptimizeReferences> |
||||||
|
</Link> |
||||||
|
</ItemDefinitionGroup> |
||||||
|
|
||||||
|
<ItemGroup> |
||||||
|
<ClCompile Include="$(SolutionDir)\..\test\cpp\end2end\filter_end2end_test.cc"> |
||||||
|
</ClCompile> |
||||||
|
</ItemGroup> |
||||||
|
<ItemGroup> |
||||||
|
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util\grpc++_test_util.vcxproj"> |
||||||
|
<Project>{0BE77741-552A-929B-A497-4EF7ECE17A64}</Project> |
||||||
|
</ProjectReference> |
||||||
|
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj"> |
||||||
|
<Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project> |
||||||
|
</ProjectReference> |
||||||
|
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj"> |
||||||
|
<Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project> |
||||||
|
</ProjectReference> |
||||||
|
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj"> |
||||||
|
<Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project> |
||||||
|
</ProjectReference> |
||||||
|
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj"> |
||||||
|
<Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project> |
||||||
|
</ProjectReference> |
||||||
|
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj"> |
||||||
|
<Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project> |
||||||
|
</ProjectReference> |
||||||
|
</ItemGroup> |
||||||
|
<ItemGroup> |
||||||
|
<None Include="packages.config" /> |
||||||
|
</ItemGroup> |
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> |
||||||
|
<ImportGroup Label="ExtensionTargets"> |
||||||
|
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" /> |
||||||
|
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" /> |
||||||
|
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" /> |
||||||
|
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" /> |
||||||
|
</ImportGroup> |
||||||
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> |
||||||
|
<PropertyGroup> |
||||||
|
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> |
||||||
|
</PropertyGroup> |
||||||
|
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" /> |
||||||
|
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" /> |
||||||
|
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" /> |
||||||
|
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" /> |
||||||
|
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" /> |
||||||
|
</Target> |
||||||
|
</Project> |
||||||
|
|
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||||
|
<ItemGroup> |
||||||
|
<ClCompile Include="$(SolutionDir)\..\test\cpp\end2end\filter_end2end_test.cc"> |
||||||
|
<Filter>test\cpp\end2end</Filter> |
||||||
|
</ClCompile> |
||||||
|
</ItemGroup> |
||||||
|
|
||||||
|
<ItemGroup> |
||||||
|
<Filter Include="test"> |
||||||
|
<UniqueIdentifier>{f7581160-220d-1118-f29e-6b37e45671c9}</UniqueIdentifier> |
||||||
|
</Filter> |
||||||
|
<Filter Include="test\cpp"> |
||||||
|
<UniqueIdentifier>{63784d35-03cc-1a7e-0c95-a9451bc1daf4}</UniqueIdentifier> |
||||||
|
</Filter> |
||||||
|
<Filter Include="test\cpp\end2end"> |
||||||
|
<UniqueIdentifier>{d2a01682-970e-d23d-1eb8-ef020e3a1ca3}</UniqueIdentifier> |
||||||
|
</Filter> |
||||||
|
</ItemGroup> |
||||||
|
</Project> |
||||||
|
|
Loading…
Reference in new issue