mirror of https://github.com/grpc/grpc.git
Conflicts: tools/buildgen/generate_projects.pypull/2396/head
commit
5876ad1757
760 changed files with 30255 additions and 8382 deletions
@ -0,0 +1,77 @@ |
||||
Connection Backoff Interop Test Descriptions |
||||
=============================================== |
||||
|
||||
This test is to verify the client is reconnecting the server with correct |
||||
backoffs as specified in |
||||
[the spec](http://github.com/grpc/grpc/blob/master/doc/connection-backoff.md). |
||||
The test server has a port (control_port) running a rpc service for controlling |
||||
the server and another port (retry_port) to close any incoming tcp connections. |
||||
The test has the following flow: |
||||
|
||||
1. The server starts listening on control_port. |
||||
2. The client calls Start rpc on server control_port. |
||||
3. The server starts listening on retry_port. |
||||
4. The client connects to server retry_port and retries with backoff for 540s, |
||||
which translates to about 13 retries. |
||||
5. The client calls Stop rpc on server control port. |
||||
6. The client checks the response to see whether the server thinks the backoffs |
||||
are conforming the spec or do its own check on the backoffs in the response. |
||||
|
||||
Client and server use |
||||
[test.proto](https://github.com/grpc/grpc/blob/master/test/proto/test.proto). |
||||
Each language should implement its own client. The C++ server is shared among |
||||
languages. |
||||
|
||||
Client |
||||
------ |
||||
|
||||
Clients should accept these arguments: |
||||
* --server_control_port=PORT |
||||
* The server port to connect to for rpc. For example, "8080" |
||||
* --server_retry_port=PORT |
||||
* The server port to connect to for testing backoffs. For example, "8081" |
||||
|
||||
The client must connect to the control port without TLS. The client should |
||||
either assert on the server returned backoff status or check the returned |
||||
backoffs on its own. |
||||
|
||||
Procedure of client: |
||||
|
||||
1. Calls Start on server control port with a large deadline or no deadline, |
||||
waits for its finish and checks it succeeded. |
||||
2. Initiates a channel connection to server retry port, which should perform |
||||
reconnections with proper backoffs. A convienent way to achieve this is to |
||||
call Start with a deadline of 540s. The rpc should fail with deadline exceeded. |
||||
3. Calls Stop on server control port and checks it succeeded. |
||||
4. Checks the response to see whether the server thinks the backoffs passed the |
||||
test. |
||||
5. Optionally, the client can do its own check on the returned backoffs. |
||||
|
||||
|
||||
Server |
||||
------ |
||||
|
||||
A C++ server can be used for the test. Other languages do NOT need to implement |
||||
a server. To minimize the network delay, the server binary should run on the |
||||
same machine or on a nearby machine (in terms of network distance) with the |
||||
client binary. |
||||
|
||||
A server implements the ReconnectService to its state. It also opens a |
||||
tcp server on the retry_port, which just shuts down all incoming tcp |
||||
connections to simulate connection failures. The server will keep a record of |
||||
all the reconnection timestamps and return the connection backoffs in the |
||||
response in milliseconds. The server also checks the backoffs to see whether |
||||
they conform the spec and returns whether the client passes the test. |
||||
|
||||
If the server receives a Start call when another client is being tested, it |
||||
finishes the call when the other client is done. If some other host connects |
||||
to the server retry_port when a client is being tested, the server will log an |
||||
error but likely would think the client fails the test. |
||||
|
||||
The server accepts these arguments: |
||||
|
||||
* --control_port=PORT |
||||
* The port to listen on for control rpcs. For example, "8080" |
||||
* --retry_port=PORT |
||||
* The tcp server port. For example, "8081" |
||||
|
@ -0,0 +1,77 @@ |
||||
/*
|
||||
* |
||||
* 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_AUTH_PROPERTY_ITERATOR_H |
||||
#define GRPCXX_AUTH_PROPERTY_ITERATOR_H |
||||
|
||||
#include <iterator> |
||||
#include <vector> |
||||
|
||||
#include <grpc++/config.h> |
||||
|
||||
struct grpc_auth_context; |
||||
struct grpc_auth_property; |
||||
struct grpc_auth_property_iterator; |
||||
|
||||
namespace grpc { |
||||
class SecureAuthContext; |
||||
|
||||
typedef std::pair<grpc::string, grpc::string> AuthProperty; |
||||
|
||||
class AuthPropertyIterator |
||||
: public std::iterator<std::input_iterator_tag, const AuthProperty> { |
||||
public: |
||||
~AuthPropertyIterator(); |
||||
AuthPropertyIterator& operator++(); |
||||
AuthPropertyIterator operator++(int); |
||||
bool operator==(const AuthPropertyIterator& rhs) const; |
||||
bool operator!=(const AuthPropertyIterator& rhs) const; |
||||
const AuthProperty operator*(); |
||||
|
||||
protected: |
||||
AuthPropertyIterator(); |
||||
AuthPropertyIterator(const grpc_auth_property* property, |
||||
const grpc_auth_property_iterator* iter); |
||||
private: |
||||
friend class SecureAuthContext; |
||||
const grpc_auth_property* property_; |
||||
// The following items form a grpc_auth_property_iterator.
|
||||
const grpc_auth_context* ctx_; |
||||
size_t index_; |
||||
const char* name_; |
||||
}; |
||||
|
||||
} // namespace grpc
|
||||
|
||||
#endif // GRPCXX_AUTH_PROPERTY_ITERATOR_H
|
||||
|
@ -0,0 +1,82 @@ |
||||
/*
|
||||
* |
||||
* 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_DYNAMIC_THREAD_POOL_H |
||||
#define GRPCXX_DYNAMIC_THREAD_POOL_H |
||||
|
||||
#include <grpc++/config.h> |
||||
|
||||
#include <grpc++/impl/sync.h> |
||||
#include <grpc++/impl/thd.h> |
||||
#include <grpc++/thread_pool_interface.h> |
||||
|
||||
#include <list> |
||||
#include <memory> |
||||
#include <queue> |
||||
|
||||
namespace grpc { |
||||
|
||||
class DynamicThreadPool GRPC_FINAL : public ThreadPoolInterface { |
||||
public: |
||||
explicit DynamicThreadPool(int reserve_threads); |
||||
~DynamicThreadPool(); |
||||
|
||||
void Add(const std::function<void()>& callback) GRPC_OVERRIDE; |
||||
|
||||
private: |
||||
class DynamicThread { |
||||
public: |
||||
DynamicThread(DynamicThreadPool *pool); |
||||
~DynamicThread(); |
||||
private: |
||||
DynamicThreadPool *pool_; |
||||
std::unique_ptr<grpc::thread> thd_; |
||||
void ThreadFunc(); |
||||
}; |
||||
grpc::mutex mu_; |
||||
grpc::condition_variable cv_; |
||||
grpc::condition_variable shutdown_cv_; |
||||
bool shutdown_; |
||||
std::queue<std::function<void()>> callbacks_; |
||||
int reserve_threads_; |
||||
int nthreads_; |
||||
int threads_waiting_; |
||||
std::list<DynamicThread*> dead_threads_; |
||||
|
||||
void ThreadFunc(); |
||||
static void ReapThreads(std::list<DynamicThread*>* tlist); |
||||
}; |
||||
|
||||
} // namespace grpc
|
||||
|
||||
#endif // GRPCXX_DYNAMIC_THREAD_POOL_H
|
@ -0,0 +1,46 @@ |
||||
/*
|
||||
* |
||||
* 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 CENSUS_RPC_STAT_ID_H |
||||
#define CENSUS_RPC_STAT_ID_H |
||||
|
||||
/* Stats ID's used for RPC measurements. */ |
||||
#define CENSUS_INVALID_STAT_ID 0 /* ID 0 is always invalid */ |
||||
#define CENSUS_RPC_CLIENT_REQUESTS 1 /* Count of client requests sent. */ |
||||
#define CENSUS_RPC_SERVER_REQUESTS 2 /* Count of server requests sent. */ |
||||
#define CENSUS_RPC_CLIENT_ERRORS 3 /* Client error counts. */ |
||||
#define CENSUS_RPC_SERVER_ERRORS 4 /* Server error counts. */ |
||||
#define CENSUS_RPC_CLIENT_LATENCY 5 /* Client side request latency. */ |
||||
#define CENSUS_RPC_SERVER_LATENCY 6 /* Server side request latency. */ |
||||
|
||||
#endif /* CENSUS_RPC_STAT_ID_H */ |
@ -0,0 +1,328 @@ |
||||
/*
|
||||
* |
||||
* 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. |
||||
* |
||||
*/ |
||||
|
||||
#include <assert.h> |
||||
#include <string.h> |
||||
|
||||
#include <grpc/compression.h> |
||||
#include <grpc/support/log.h> |
||||
#include <grpc/support/slice_buffer.h> |
||||
|
||||
#include "src/core/channel/compress_filter.h" |
||||
#include "src/core/channel/channel_args.h" |
||||
#include "src/core/compression/message_compress.h" |
||||
|
||||
typedef struct call_data { |
||||
gpr_slice_buffer slices; /**< Buffers up input slices to be compressed */ |
||||
grpc_linked_mdelem compression_algorithm_storage; |
||||
int remaining_slice_bytes; /**< Input data to be read, as per BEGIN_MESSAGE */ |
||||
int written_initial_metadata; /**< Already processed initial md? */ |
||||
/** Compression algorithm we'll try to use. It may be given by incoming
|
||||
* metadata, or by the channel's default compression settings. */ |
||||
grpc_compression_algorithm compression_algorithm; |
||||
/** If true, contents of \a compression_algorithm are authoritative */ |
||||
int has_compression_algorithm; |
||||
} call_data; |
||||
|
||||
typedef struct channel_data { |
||||
/** Metadata key for the incoming (requested) compression algorithm */ |
||||
grpc_mdstr *mdstr_request_compression_algorithm_key; |
||||
/** Metadata key for the outgoing (used) compression algorithm */ |
||||
grpc_mdstr *mdstr_outgoing_compression_algorithm_key; |
||||
/** Precomputed metadata elements for all available compression algorithms */ |
||||
grpc_mdelem *mdelem_compression_algorithms[GRPC_COMPRESS_ALGORITHMS_COUNT]; |
||||
/** The default, channel-level, compression algorithm */ |
||||
grpc_compression_algorithm default_compression_algorithm; |
||||
} channel_data; |
||||
|
||||
/** Compress \a slices in place using \a algorithm. Returns 1 if compression did
|
||||
* actually happen, 0 otherwise (for example if the compressed output size was |
||||
* larger than the raw input). |
||||
* |
||||
* Returns 1 if the data was actually compress and 0 otherwise. */ |
||||
static int compress_send_sb(grpc_compression_algorithm algorithm, |
||||
gpr_slice_buffer *slices) { |
||||
int did_compress; |
||||
gpr_slice_buffer tmp; |
||||
gpr_slice_buffer_init(&tmp); |
||||
did_compress = grpc_msg_compress(algorithm, slices, &tmp); |
||||
if (did_compress) { |
||||
gpr_slice_buffer_swap(slices, &tmp); |
||||
} |
||||
gpr_slice_buffer_destroy(&tmp); |
||||
return did_compress; |
||||
} |
||||
|
||||
/** For each \a md element from the incoming metadata, filter out the entry for
|
||||
* "grpc-encoding", using its value to populate the call data's |
||||
* compression_algorithm field. */ |
||||
static grpc_mdelem* compression_md_filter(void *user_data, grpc_mdelem *md) { |
||||
grpc_call_element *elem = user_data; |
||||
call_data *calld = elem->call_data; |
||||
channel_data *channeld = elem->channel_data; |
||||
|
||||
if (md->key == channeld->mdstr_request_compression_algorithm_key) { |
||||
const char *md_c_str = grpc_mdstr_as_c_string(md->value); |
||||
if (!grpc_compression_algorithm_parse(md_c_str, |
||||
&calld->compression_algorithm)) { |
||||
gpr_log(GPR_ERROR, "Invalid compression algorithm: '%s'. Ignoring.", |
||||
md_c_str); |
||||
calld->compression_algorithm = GRPC_COMPRESS_NONE; |
||||
} |
||||
calld->has_compression_algorithm = 1; |
||||
return NULL; |
||||
} |
||||
|
||||
return md; |
||||
} |
||||
|
||||
static int skip_compression(channel_data *channeld, call_data *calld) { |
||||
if (calld->has_compression_algorithm) { |
||||
if (calld->compression_algorithm == GRPC_COMPRESS_NONE) { |
||||
return 1; |
||||
} |
||||
return 0; /* we have an actual call-specific algorithm */ |
||||
} |
||||
/* no per-call compression override */ |
||||
return channeld->default_compression_algorithm == GRPC_COMPRESS_NONE; |
||||
} |
||||
|
||||
/** Assembles a new grpc_stream_op_buffer with the compressed slices, modifying
|
||||
* the associated GRPC_OP_BEGIN_MESSAGE accordingly (new compressed length, |
||||
* flags indicating compression is in effect) and replaces \a send_ops with it. |
||||
* */ |
||||
static void finish_compressed_sopb(grpc_stream_op_buffer *send_ops, |
||||
grpc_call_element *elem) { |
||||
size_t i; |
||||
call_data *calld = elem->call_data; |
||||
int new_slices_added = 0; /* GPR_FALSE */ |
||||
grpc_metadata_batch metadata; |
||||
grpc_stream_op_buffer new_send_ops; |
||||
grpc_sopb_init(&new_send_ops); |
||||
|
||||
for (i = 0; i < send_ops->nops; i++) { |
||||
grpc_stream_op *sop = &send_ops->ops[i]; |
||||
switch (sop->type) { |
||||
case GRPC_OP_BEGIN_MESSAGE: |
||||
grpc_sopb_add_begin_message( |
||||
&new_send_ops, calld->slices.length, |
||||
sop->data.begin_message.flags | GRPC_WRITE_INTERNAL_COMPRESS); |
||||
break; |
||||
case GRPC_OP_SLICE: |
||||
/* Once we reach the slices section of the original buffer, simply add
|
||||
* all the new (compressed) slices. We obviously want to do this only |
||||
* once, hence the "new_slices_added" guard. */ |
||||
if (!new_slices_added) { |
||||
size_t j; |
||||
for (j = 0; j < calld->slices.count; ++j) { |
||||
grpc_sopb_add_slice(&new_send_ops, |
||||
gpr_slice_ref(calld->slices.slices[j])); |
||||
} |
||||
new_slices_added = 1; /* GPR_TRUE */ |
||||
} |
||||
break; |
||||
case GRPC_OP_METADATA: |
||||
/* move the metadata to the new buffer. */ |
||||
grpc_metadata_batch_move(&metadata, &sop->data.metadata); |
||||
grpc_sopb_add_metadata(&new_send_ops, metadata); |
||||
break; |
||||
case GRPC_NO_OP: |
||||
break; |
||||
} |
||||
} |
||||
grpc_sopb_swap(send_ops, &new_send_ops); |
||||
grpc_sopb_destroy(&new_send_ops); |
||||
} |
||||
|
||||
/** Filter's "main" function, called for any incoming grpc_transport_stream_op
|
||||
* instance that holds a non-zero number of send operations, accesible to this |
||||
* function in \a send_ops. */ |
||||
static void process_send_ops(grpc_call_element *elem, |
||||
grpc_stream_op_buffer *send_ops) { |
||||
call_data *calld = elem->call_data; |
||||
channel_data *channeld = elem->channel_data; |
||||
size_t i; |
||||
int did_compress = 0; |
||||
|
||||
/* In streaming calls, we need to reset the previously accumulated slices */ |
||||
gpr_slice_buffer_reset_and_unref(&calld->slices); |
||||
for (i = 0; i < send_ops->nops; ++i) { |
||||
grpc_stream_op *sop = &send_ops->ops[i]; |
||||
switch (sop->type) { |
||||
case GRPC_OP_BEGIN_MESSAGE: |
||||
/* buffer up slices until we've processed all the expected ones (as
|
||||
* given by GRPC_OP_BEGIN_MESSAGE) */ |
||||
calld->remaining_slice_bytes = sop->data.begin_message.length; |
||||
if (sop->data.begin_message.flags & GRPC_WRITE_NO_COMPRESS) { |
||||
calld->has_compression_algorithm = 1; /* GPR_TRUE */ |
||||
calld->compression_algorithm = GRPC_COMPRESS_NONE; |
||||
} |
||||
break; |
||||
case GRPC_OP_METADATA: |
||||
if (!calld->written_initial_metadata) { |
||||
/* Parse incoming request for compression. If any, it'll be available
|
||||
* at calld->compression_algorithm */ |
||||
grpc_metadata_batch_filter(&(sop->data.metadata), |
||||
compression_md_filter, elem); |
||||
if (!calld->has_compression_algorithm) { |
||||
/* If no algorithm was found in the metadata and we aren't
|
||||
* exceptionally skipping compression, fall back to the channel |
||||
* default */ |
||||
calld->compression_algorithm = |
||||
channeld->default_compression_algorithm; |
||||
calld->has_compression_algorithm = 1; /* GPR_TRUE */ |
||||
} |
||||
grpc_metadata_batch_add_tail( |
||||
&(sop->data.metadata), &calld->compression_algorithm_storage, |
||||
grpc_mdelem_ref(channeld->mdelem_compression_algorithms |
||||
[calld->compression_algorithm])); |
||||
calld->written_initial_metadata = 1; /* GPR_TRUE */ |
||||
} |
||||
break; |
||||
case GRPC_OP_SLICE: |
||||
if (skip_compression(channeld, calld)) continue; |
||||
GPR_ASSERT(calld->remaining_slice_bytes > 0); |
||||
/* Increase input ref count, gpr_slice_buffer_add takes ownership. */ |
||||
gpr_slice_buffer_add(&calld->slices, gpr_slice_ref(sop->data.slice)); |
||||
calld->remaining_slice_bytes -= GPR_SLICE_LENGTH(sop->data.slice); |
||||
if (calld->remaining_slice_bytes == 0) { |
||||
did_compress = |
||||
compress_send_sb(calld->compression_algorithm, &calld->slices); |
||||
} |
||||
break; |
||||
case GRPC_NO_OP: |
||||
break; |
||||
} |
||||
} |
||||
|
||||
/* Modify the send_ops stream_op_buffer depending on whether compression was
|
||||
* carried out */ |
||||
if (did_compress) { |
||||
finish_compressed_sopb(send_ops, elem); |
||||
} |
||||
} |
||||
|
||||
/* Called either:
|
||||
- in response to an API call (or similar) from above, to send something |
||||
- a network event (or similar) from below, to receive something |
||||
op contains type and call direction information, in addition to the data |
||||
that is being sent or received. */ |
||||
static void compress_start_transport_stream_op(grpc_call_element *elem, |
||||
grpc_transport_stream_op *op) { |
||||
if (op->send_ops && op->send_ops->nops > 0) { |
||||
process_send_ops(elem, op->send_ops); |
||||
} |
||||
|
||||
/* pass control down the stack */ |
||||
grpc_call_next_op(elem, op); |
||||
} |
||||
|
||||
/* Constructor for call_data */ |
||||
static void init_call_elem(grpc_call_element *elem, |
||||
const void *server_transport_data, |
||||
grpc_transport_stream_op *initial_op) { |
||||
/* grab pointers to our data from the call element */ |
||||
call_data *calld = elem->call_data; |
||||
|
||||
/* initialize members */ |
||||
gpr_slice_buffer_init(&calld->slices); |
||||
calld->has_compression_algorithm = 0; |
||||
calld->written_initial_metadata = 0; /* GPR_FALSE */ |
||||
|
||||
if (initial_op) { |
||||
if (initial_op->send_ops && initial_op->send_ops->nops > 0) { |
||||
process_send_ops(elem, initial_op->send_ops); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/* Destructor for call_data */ |
||||
static void destroy_call_elem(grpc_call_element *elem) { |
||||
/* grab pointers to our data from the call element */ |
||||
call_data *calld = elem->call_data; |
||||
gpr_slice_buffer_destroy(&calld->slices); |
||||
} |
||||
|
||||
/* Constructor for channel_data */ |
||||
static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master, |
||||
const grpc_channel_args *args, grpc_mdctx *mdctx, |
||||
int is_first, int is_last) { |
||||
channel_data *channeld = elem->channel_data; |
||||
grpc_compression_algorithm algo_idx; |
||||
|
||||
channeld->default_compression_algorithm = |
||||
grpc_channel_args_get_compression_algorithm(args); |
||||
|
||||
channeld->mdstr_request_compression_algorithm_key = |
||||
grpc_mdstr_from_string(mdctx, GRPC_COMPRESS_REQUEST_ALGORITHM_KEY, 0); |
||||
|
||||
channeld->mdstr_outgoing_compression_algorithm_key = |
||||
grpc_mdstr_from_string(mdctx, "grpc-encoding", 0); |
||||
|
||||
for (algo_idx = 0; algo_idx < GRPC_COMPRESS_ALGORITHMS_COUNT; ++algo_idx) { |
||||
char *algorithm_name; |
||||
GPR_ASSERT(grpc_compression_algorithm_name(algo_idx, &algorithm_name) != 0); |
||||
channeld->mdelem_compression_algorithms[algo_idx] = |
||||
grpc_mdelem_from_metadata_strings( |
||||
mdctx, |
||||
grpc_mdstr_ref(channeld->mdstr_outgoing_compression_algorithm_key), |
||||
grpc_mdstr_from_string(mdctx, algorithm_name, 0)); |
||||
} |
||||
|
||||
GPR_ASSERT(!is_last); |
||||
} |
||||
|
||||
/* Destructor for channel data */ |
||||
static void destroy_channel_elem(grpc_channel_element *elem) { |
||||
channel_data *channeld = elem->channel_data; |
||||
grpc_compression_algorithm algo_idx; |
||||
|
||||
grpc_mdstr_unref(channeld->mdstr_request_compression_algorithm_key); |
||||
grpc_mdstr_unref(channeld->mdstr_outgoing_compression_algorithm_key); |
||||
for (algo_idx = 0; algo_idx < GRPC_COMPRESS_ALGORITHMS_COUNT; |
||||
++algo_idx) { |
||||
grpc_mdelem_unref(channeld->mdelem_compression_algorithms[algo_idx]); |
||||
} |
||||
} |
||||
|
||||
const grpc_channel_filter grpc_compress_filter = { |
||||
compress_start_transport_stream_op, |
||||
grpc_channel_next_op, |
||||
sizeof(call_data), |
||||
init_call_elem, |
||||
destroy_call_elem, |
||||
sizeof(channel_data), |
||||
init_channel_elem, |
||||
destroy_channel_elem, |
||||
grpc_call_next_get_peer, |
||||
"compress"}; |
@ -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 GRPC_INTERNAL_CORE_CHANNEL_COMPRESS_FILTER_H |
||||
#define GRPC_INTERNAL_CORE_CHANNEL_COMPRESS_FILTER_H |
||||
|
||||
#include "src/core/channel/channel_stack.h" |
||||
|
||||
#define GRPC_COMPRESS_REQUEST_ALGORITHM_KEY "internal:grpc-encoding-request" |
||||
|
||||
/** Compression filter for outgoing data.
|
||||
* |
||||
* See <grpc/compression.h> for the available compression settings. |
||||
* |
||||
* Compression settings may come from: |
||||
* - Channel configuration, as established at channel creation time. |
||||
* - The metadata accompanying the outgoing data to be compressed. This is |
||||
* taken as a request only. We may choose not to honor it. The metadata key |
||||
* is given by \a GRPC_COMPRESS_REQUEST_ALGORITHM_KEY. |
||||
* |
||||
* Compression can be disabled for concrete messages (for instance in order to |
||||
* prevent CRIME/BEAST type attacks) by having the GRPC_WRITE_NO_COMPRESS set in |
||||
* the BEGIN_MESSAGE flags. |
||||
* |
||||
* The attempted compression mechanism is added to the resulting initial |
||||
* metadata under the'grpc-encoding' key. |
||||
* |
||||
* If compression is actually performed, BEGIN_MESSAGE's flag is modified to |
||||
* incorporate GRPC_WRITE_INTERNAL_COMPRESS. Otherwise, and regardless of the |
||||
* aforementioned 'grpc-encoding' metadata value, data will pass through |
||||
* uncompressed. */ |
||||
|
||||
extern const grpc_channel_filter grpc_compress_filter; |
||||
|
||||
#endif /* GRPC_INTERNAL_CORE_CHANNEL_COMPRESS_FILTER_H */ |
@ -0,0 +1,299 @@ |
||||
/*
|
||||
* |
||||
* 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. |
||||
* |
||||
*/ |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "src/core/client_config/resolvers/sockaddr_resolver.h" |
||||
|
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
#ifdef GPR_POSIX_SOCKET |
||||
#include <sys/un.h> |
||||
#endif |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/host_port.h> |
||||
#include <grpc/support/string_util.h> |
||||
|
||||
#include "src/core/client_config/lb_policies/pick_first.h" |
||||
#include "src/core/iomgr/resolve_address.h" |
||||
#include "src/core/support/string.h" |
||||
|
||||
typedef struct { |
||||
/** base class: must be first */ |
||||
grpc_resolver base; |
||||
/** refcount */ |
||||
gpr_refcount refs; |
||||
/** subchannel factory */ |
||||
grpc_subchannel_factory *subchannel_factory; |
||||
/** load balancing policy factory */ |
||||
grpc_lb_policy *(*lb_policy_factory)(grpc_subchannel **subchannels, |
||||
size_t num_subchannels); |
||||
|
||||
/** the address that we've 'resolved' */ |
||||
struct sockaddr_storage addr; |
||||
int addr_len; |
||||
|
||||
/** mutex guarding the rest of the state */ |
||||
gpr_mu mu; |
||||
/** have we published? */ |
||||
int published; |
||||
/** pending next completion, or NULL */ |
||||
grpc_iomgr_closure *next_completion; |
||||
/** target config address for next completion */ |
||||
grpc_client_config **target_config; |
||||
} sockaddr_resolver; |
||||
|
||||
static void sockaddr_destroy(grpc_resolver *r); |
||||
|
||||
static void sockaddr_maybe_finish_next_locked(sockaddr_resolver *r); |
||||
|
||||
static void sockaddr_shutdown(grpc_resolver *r); |
||||
static void sockaddr_channel_saw_error(grpc_resolver *r, |
||||
struct sockaddr *failing_address, |
||||
int failing_address_len); |
||||
static void sockaddr_next(grpc_resolver *r, grpc_client_config **target_config, |
||||
grpc_iomgr_closure *on_complete); |
||||
|
||||
static const grpc_resolver_vtable sockaddr_resolver_vtable = { |
||||
sockaddr_destroy, sockaddr_shutdown, sockaddr_channel_saw_error, |
||||
sockaddr_next}; |
||||
|
||||
static void sockaddr_shutdown(grpc_resolver *resolver) { |
||||
sockaddr_resolver *r = (sockaddr_resolver *)resolver; |
||||
gpr_mu_lock(&r->mu); |
||||
if (r->next_completion != NULL) { |
||||
*r->target_config = NULL; |
||||
/* TODO(ctiller): add delayed callback */ |
||||
grpc_iomgr_add_callback(r->next_completion); |
||||
r->next_completion = NULL; |
||||
} |
||||
gpr_mu_unlock(&r->mu); |
||||
} |
||||
|
||||
static void sockaddr_channel_saw_error(grpc_resolver *resolver, |
||||
struct sockaddr *sa, int len) {} |
||||
|
||||
static void sockaddr_next(grpc_resolver *resolver, |
||||
grpc_client_config **target_config, |
||||
grpc_iomgr_closure *on_complete) { |
||||
sockaddr_resolver *r = (sockaddr_resolver *)resolver; |
||||
gpr_mu_lock(&r->mu); |
||||
GPR_ASSERT(!r->next_completion); |
||||
r->next_completion = on_complete; |
||||
r->target_config = target_config; |
||||
sockaddr_maybe_finish_next_locked(r); |
||||
gpr_mu_unlock(&r->mu); |
||||
} |
||||
|
||||
static void sockaddr_maybe_finish_next_locked(sockaddr_resolver *r) { |
||||
grpc_client_config *cfg; |
||||
grpc_lb_policy *lb_policy; |
||||
grpc_subchannel *subchannel; |
||||
grpc_subchannel_args args; |
||||
|
||||
if (r->next_completion != NULL && !r->published) { |
||||
cfg = grpc_client_config_create(); |
||||
memset(&args, 0, sizeof(args)); |
||||
args.addr = (struct sockaddr *)&r->addr; |
||||
args.addr_len = r->addr_len; |
||||
subchannel = |
||||
grpc_subchannel_factory_create_subchannel(r->subchannel_factory, &args); |
||||
lb_policy = r->lb_policy_factory(&subchannel, 1); |
||||
grpc_client_config_set_lb_policy(cfg, lb_policy); |
||||
GRPC_LB_POLICY_UNREF(lb_policy, "unix"); |
||||
r->published = 1; |
||||
*r->target_config = cfg; |
||||
grpc_iomgr_add_callback(r->next_completion); |
||||
r->next_completion = NULL; |
||||
} |
||||
} |
||||
|
||||
static void sockaddr_destroy(grpc_resolver *gr) { |
||||
sockaddr_resolver *r = (sockaddr_resolver *)gr; |
||||
gpr_mu_destroy(&r->mu); |
||||
grpc_subchannel_factory_unref(r->subchannel_factory); |
||||
gpr_free(r); |
||||
} |
||||
|
||||
#ifdef GPR_POSIX_SOCKET |
||||
static int parse_unix(grpc_uri *uri, struct sockaddr_storage *addr, int *len) { |
||||
struct sockaddr_un *un = (struct sockaddr_un *)addr; |
||||
|
||||
un->sun_family = AF_UNIX; |
||||
strcpy(un->sun_path, uri->path); |
||||
*len = strlen(un->sun_path) + sizeof(un->sun_family) + 1; |
||||
|
||||
return 1; |
||||
} |
||||
#endif |
||||
|
||||
static int parse_ipv4(grpc_uri *uri, struct sockaddr_storage *addr, int *len) { |
||||
const char *host_port = uri->path; |
||||
char *host; |
||||
char *port; |
||||
int port_num; |
||||
int result = 0; |
||||
struct sockaddr_in *in = (struct sockaddr_in *)addr; |
||||
|
||||
if (*host_port == '/') ++host_port; |
||||
if (!gpr_split_host_port(host_port, &host, &port)) { |
||||
return 0; |
||||
} |
||||
|
||||
memset(in, 0, sizeof(*in)); |
||||
*len = sizeof(*in); |
||||
in->sin_family = AF_INET; |
||||
if (inet_pton(AF_INET, host, &in->sin_addr) == 0) { |
||||
gpr_log(GPR_ERROR, "invalid ipv4 address: '%s'", host); |
||||
goto done; |
||||
} |
||||
|
||||
if (port != NULL) { |
||||
if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 || |
||||
port_num > 65535) { |
||||
gpr_log(GPR_ERROR, "invalid ipv4 port: '%s'", port); |
||||
goto done; |
||||
} |
||||
in->sin_port = htons(port_num); |
||||
} else { |
||||
gpr_log(GPR_ERROR, "no port given for ipv4 scheme"); |
||||
goto done; |
||||
} |
||||
|
||||
result = 1; |
||||
done: |
||||
gpr_free(host); |
||||
gpr_free(port); |
||||
return result; |
||||
} |
||||
|
||||
static int parse_ipv6(grpc_uri *uri, struct sockaddr_storage *addr, int *len) { |
||||
const char *host_port = uri->path; |
||||
char *host; |
||||
char *port; |
||||
int port_num; |
||||
int result = 0; |
||||
struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)addr; |
||||
|
||||
if (*host_port == '/') ++host_port; |
||||
if (!gpr_split_host_port(host_port, &host, &port)) { |
||||
return 0; |
||||
} |
||||
|
||||
memset(in6, 0, sizeof(*in6)); |
||||
*len = sizeof(*in6); |
||||
in6->sin6_family = AF_INET6; |
||||
if (inet_pton(AF_INET6, host, &in6->sin6_addr) == 0) { |
||||
gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host); |
||||
goto done; |
||||
} |
||||
|
||||
if (port != NULL) { |
||||
if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 || |
||||
port_num > 65535) { |
||||
gpr_log(GPR_ERROR, "invalid ipv6 port: '%s'", port); |
||||
goto done; |
||||
} |
||||
in6->sin6_port = htons(port_num); |
||||
} else { |
||||
gpr_log(GPR_ERROR, "no port given for ipv6 scheme"); |
||||
goto done; |
||||
} |
||||
|
||||
result = 1; |
||||
done: |
||||
gpr_free(host); |
||||
gpr_free(port); |
||||
return result; |
||||
} |
||||
|
||||
static grpc_resolver *sockaddr_create( |
||||
grpc_uri *uri, |
||||
grpc_lb_policy *(*lb_policy_factory)(grpc_subchannel **subchannels, |
||||
size_t num_subchannels), |
||||
grpc_subchannel_factory *subchannel_factory, |
||||
int parse(grpc_uri *uri, struct sockaddr_storage *dst, int *len)) { |
||||
sockaddr_resolver *r; |
||||
|
||||
if (0 != strcmp(uri->authority, "")) { |
||||
gpr_log(GPR_ERROR, "authority based uri's not supported"); |
||||
return NULL; |
||||
} |
||||
|
||||
r = gpr_malloc(sizeof(sockaddr_resolver)); |
||||
memset(r, 0, sizeof(*r)); |
||||
if (!parse(uri, &r->addr, &r->addr_len)) { |
||||
gpr_free(r); |
||||
return NULL; |
||||
} |
||||
|
||||
gpr_ref_init(&r->refs, 1); |
||||
gpr_mu_init(&r->mu); |
||||
grpc_resolver_init(&r->base, &sockaddr_resolver_vtable); |
||||
r->subchannel_factory = subchannel_factory; |
||||
r->lb_policy_factory = lb_policy_factory; |
||||
|
||||
grpc_subchannel_factory_ref(subchannel_factory); |
||||
return &r->base; |
||||
} |
||||
|
||||
/*
|
||||
* FACTORY |
||||
*/ |
||||
|
||||
static void sockaddr_factory_ref(grpc_resolver_factory *factory) {} |
||||
|
||||
static void sockaddr_factory_unref(grpc_resolver_factory *factory) {} |
||||
|
||||
#define DECL_FACTORY(name) \ |
||||
static grpc_resolver *name##_factory_create_resolver( \
|
||||
grpc_resolver_factory *factory, grpc_uri *uri, \
|
||||
grpc_subchannel_factory *subchannel_factory) { \
|
||||
return sockaddr_create(uri, grpc_create_pick_first_lb_policy, \
|
||||
subchannel_factory, parse_##name); \
|
||||
} \
|
||||
static const grpc_resolver_factory_vtable name##_factory_vtable = { \
|
||||
sockaddr_factory_ref, sockaddr_factory_unref, \
|
||||
name##_factory_create_resolver}; \
|
||||
static grpc_resolver_factory name##_resolver_factory = { \
|
||||
&name##_factory_vtable}; \
|
||||
grpc_resolver_factory *grpc_##name##_resolver_factory_create() { \
|
||||
return &name##_resolver_factory; \
|
||||
} |
||||
|
||||
#ifdef GPR_POSIX_SOCKET |
||||
DECL_FACTORY(unix) |
||||
#endif |
||||
DECL_FACTORY(ipv4) |
||||
DECL_FACTORY(ipv6) |
@ -1,195 +0,0 @@ |
||||
/*
|
||||
* |
||||
* 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. |
||||
* |
||||
*/ |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
#ifdef GPR_POSIX_SOCKET |
||||
|
||||
#include "src/core/client_config/resolvers/unix_resolver_posix.h" |
||||
|
||||
#include <string.h> |
||||
#include <sys/un.h> |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/string_util.h> |
||||
|
||||
#include "src/core/client_config/lb_policies/pick_first.h" |
||||
#include "src/core/iomgr/resolve_address.h" |
||||
#include "src/core/support/string.h" |
||||
|
||||
typedef struct { |
||||
/** base class: must be first */ |
||||
grpc_resolver base; |
||||
/** refcount */ |
||||
gpr_refcount refs; |
||||
/** subchannel factory */ |
||||
grpc_subchannel_factory *subchannel_factory; |
||||
/** load balancing policy factory */ |
||||
grpc_lb_policy *(*lb_policy_factory)(grpc_subchannel **subchannels, |
||||
size_t num_subchannels); |
||||
|
||||
/** the address that we've 'resolved' */ |
||||
struct sockaddr_un addr; |
||||
int addr_len; |
||||
|
||||
/** mutex guarding the rest of the state */ |
||||
gpr_mu mu; |
||||
/** have we published? */ |
||||
int published; |
||||
/** pending next completion, or NULL */ |
||||
grpc_iomgr_closure *next_completion; |
||||
/** target config address for next completion */ |
||||
grpc_client_config **target_config; |
||||
} unix_resolver; |
||||
|
||||
static void unix_destroy(grpc_resolver *r); |
||||
|
||||
static void unix_maybe_finish_next_locked(unix_resolver *r); |
||||
|
||||
static void unix_shutdown(grpc_resolver *r); |
||||
static void unix_channel_saw_error(grpc_resolver *r, |
||||
struct sockaddr *failing_address, |
||||
int failing_address_len); |
||||
static void unix_next(grpc_resolver *r, grpc_client_config **target_config, |
||||
grpc_iomgr_closure *on_complete); |
||||
|
||||
static const grpc_resolver_vtable unix_resolver_vtable = { |
||||
unix_destroy, unix_shutdown, unix_channel_saw_error, unix_next}; |
||||
|
||||
static void unix_shutdown(grpc_resolver *resolver) { |
||||
unix_resolver *r = (unix_resolver *)resolver; |
||||
gpr_mu_lock(&r->mu); |
||||
if (r->next_completion != NULL) { |
||||
*r->target_config = NULL; |
||||
/* TODO(ctiller): add delayed callback */ |
||||
grpc_iomgr_add_callback(r->next_completion); |
||||
r->next_completion = NULL; |
||||
} |
||||
gpr_mu_unlock(&r->mu); |
||||
} |
||||
|
||||
static void unix_channel_saw_error(grpc_resolver *resolver, struct sockaddr *sa, |
||||
int len) {} |
||||
|
||||
static void unix_next(grpc_resolver *resolver, |
||||
grpc_client_config **target_config, |
||||
grpc_iomgr_closure *on_complete) { |
||||
unix_resolver *r = (unix_resolver *)resolver; |
||||
gpr_mu_lock(&r->mu); |
||||
GPR_ASSERT(!r->next_completion); |
||||
r->next_completion = on_complete; |
||||
r->target_config = target_config; |
||||
unix_maybe_finish_next_locked(r); |
||||
gpr_mu_unlock(&r->mu); |
||||
} |
||||
|
||||
static void unix_maybe_finish_next_locked(unix_resolver *r) { |
||||
grpc_client_config *cfg; |
||||
grpc_lb_policy *lb_policy; |
||||
grpc_subchannel *subchannel; |
||||
grpc_subchannel_args args; |
||||
|
||||
if (r->next_completion != NULL && !r->published) { |
||||
cfg = grpc_client_config_create(); |
||||
memset(&args, 0, sizeof(args)); |
||||
args.addr = (struct sockaddr *)&r->addr; |
||||
args.addr_len = r->addr_len; |
||||
subchannel = |
||||
grpc_subchannel_factory_create_subchannel(r->subchannel_factory, &args); |
||||
lb_policy = r->lb_policy_factory(&subchannel, 1); |
||||
grpc_client_config_set_lb_policy(cfg, lb_policy); |
||||
GRPC_LB_POLICY_UNREF(lb_policy, "unix"); |
||||
r->published = 1; |
||||
*r->target_config = cfg; |
||||
grpc_iomgr_add_callback(r->next_completion); |
||||
r->next_completion = NULL; |
||||
} |
||||
} |
||||
|
||||
static void unix_destroy(grpc_resolver *gr) { |
||||
unix_resolver *r = (unix_resolver *)gr; |
||||
gpr_mu_destroy(&r->mu); |
||||
grpc_subchannel_factory_unref(r->subchannel_factory); |
||||
gpr_free(r); |
||||
} |
||||
|
||||
static grpc_resolver *unix_create( |
||||
grpc_uri *uri, |
||||
grpc_lb_policy *(*lb_policy_factory)(grpc_subchannel **subchannels, |
||||
size_t num_subchannels), |
||||
grpc_subchannel_factory *subchannel_factory) { |
||||
unix_resolver *r; |
||||
|
||||
if (0 != strcmp(uri->authority, "")) { |
||||
gpr_log(GPR_ERROR, "authority based uri's not supported"); |
||||
return NULL; |
||||
} |
||||
|
||||
r = gpr_malloc(sizeof(unix_resolver)); |
||||
memset(r, 0, sizeof(*r)); |
||||
gpr_ref_init(&r->refs, 1); |
||||
gpr_mu_init(&r->mu); |
||||
grpc_resolver_init(&r->base, &unix_resolver_vtable); |
||||
r->subchannel_factory = subchannel_factory; |
||||
r->lb_policy_factory = lb_policy_factory; |
||||
|
||||
r->addr.sun_family = AF_UNIX; |
||||
strcpy(r->addr.sun_path, uri->path); |
||||
r->addr_len = strlen(r->addr.sun_path) + sizeof(r->addr.sun_family) + 1; |
||||
|
||||
grpc_subchannel_factory_ref(subchannel_factory); |
||||
return &r->base; |
||||
} |
||||
|
||||
/*
|
||||
* FACTORY |
||||
*/ |
||||
|
||||
static void unix_factory_ref(grpc_resolver_factory *factory) {} |
||||
|
||||
static void unix_factory_unref(grpc_resolver_factory *factory) {} |
||||
|
||||
static grpc_resolver *unix_factory_create_resolver( |
||||
grpc_resolver_factory *factory, grpc_uri *uri, |
||||
grpc_subchannel_factory *subchannel_factory) { |
||||
return unix_create(uri, grpc_create_pick_first_lb_policy, subchannel_factory); |
||||
} |
||||
|
||||
static const grpc_resolver_factory_vtable unix_factory_vtable = { |
||||
unix_factory_ref, unix_factory_unref, unix_factory_create_resolver}; |
||||
static grpc_resolver_factory unix_resolver_factory = {&unix_factory_vtable}; |
||||
|
||||
grpc_resolver_factory *grpc_unix_resolver_factory_create() { |
||||
return &unix_resolver_factory; |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,43 @@ |
||||
/*
|
||||
* |
||||
* 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. |
||||
* |
||||
*/ |
||||
|
||||
#include "src/core/client_config/subchannel_factory_decorators/add_channel_arg.h" |
||||
#include "src/core/client_config/subchannel_factory_decorators/merge_channel_args.h" |
||||
|
||||
grpc_subchannel_factory *grpc_subchannel_factory_add_channel_arg( |
||||
grpc_subchannel_factory *input, const grpc_arg *arg) { |
||||
grpc_channel_args args; |
||||
args.num_args = 1; |
||||
args.args = (grpc_arg *)arg; |
||||
return grpc_subchannel_factory_merge_channel_args(input, &args); |
||||
} |
@ -0,0 +1,45 @@ |
||||
/*
|
||||
* |
||||
* 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 GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_DECORATORS_ADD_CHANNEL_ARG_H |
||||
#define GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_DECORATORS_ADD_CHANNEL_ARG_H |
||||
|
||||
#include "src/core/client_config/subchannel_factory.h" |
||||
|
||||
/** Takes a subchannel factory, returns a new one that mutates incoming
|
||||
channel_args by adding a new argument; ownership of input, arg is retained |
||||
by the caller. */ |
||||
grpc_subchannel_factory *grpc_subchannel_factory_add_channel_arg( |
||||
grpc_subchannel_factory *input, const grpc_arg *arg); |
||||
|
||||
#endif /* GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_DECORATORS_ADD_CHANNEL_ARG_H */ |
@ -0,0 +1,84 @@ |
||||
/*
|
||||
* |
||||
* 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. |
||||
* |
||||
*/ |
||||
|
||||
#include "src/core/client_config/subchannel_factory_decorators/merge_channel_args.h" |
||||
#include <grpc/support/alloc.h> |
||||
#include "src/core/channel/channel_args.h" |
||||
|
||||
typedef struct { |
||||
grpc_subchannel_factory base; |
||||
gpr_refcount refs; |
||||
grpc_subchannel_factory *wrapped; |
||||
grpc_channel_args *merge_args; |
||||
} merge_args_factory; |
||||
|
||||
static void merge_args_factory_ref(grpc_subchannel_factory *scf) { |
||||
merge_args_factory *f = (merge_args_factory *)scf; |
||||
gpr_ref(&f->refs); |
||||
} |
||||
|
||||
static void merge_args_factory_unref(grpc_subchannel_factory *scf) { |
||||
merge_args_factory *f = (merge_args_factory *)scf; |
||||
if (gpr_unref(&f->refs)) { |
||||
grpc_subchannel_factory_unref(f->wrapped); |
||||
grpc_channel_args_destroy(f->merge_args); |
||||
gpr_free(f); |
||||
} |
||||
} |
||||
|
||||
static grpc_subchannel *merge_args_factory_create_subchannel( |
||||
grpc_subchannel_factory *scf, grpc_subchannel_args *args) { |
||||
merge_args_factory *f = (merge_args_factory *)scf; |
||||
grpc_channel_args *final_args = |
||||
grpc_channel_args_merge(args->args, f->merge_args); |
||||
grpc_subchannel *s; |
||||
args->args = final_args; |
||||
s = grpc_subchannel_factory_create_subchannel(f->wrapped, args); |
||||
grpc_channel_args_destroy(final_args); |
||||
return s; |
||||
} |
||||
|
||||
static const grpc_subchannel_factory_vtable merge_args_factory_vtable = { |
||||
merge_args_factory_ref, merge_args_factory_unref, |
||||
merge_args_factory_create_subchannel}; |
||||
|
||||
grpc_subchannel_factory *grpc_subchannel_factory_merge_channel_args( |
||||
grpc_subchannel_factory *input, const grpc_channel_args *args) { |
||||
merge_args_factory *f = gpr_malloc(sizeof(*f)); |
||||
f->base.vtable = &merge_args_factory_vtable; |
||||
gpr_ref_init(&f->refs, 1); |
||||
grpc_subchannel_factory_ref(input); |
||||
f->wrapped = input; |
||||
f->merge_args = grpc_channel_args_copy(args); |
||||
return &f->base; |
||||
} |
@ -0,0 +1,45 @@ |
||||
/*
|
||||
* |
||||
* 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 GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_DECORATORS_MERGE_CHANNEL_ARGS_H |
||||
#define GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_DECORATORS_MERGE_CHANNEL_ARGS_H |
||||
|
||||
#include "src/core/client_config/subchannel_factory.h" |
||||
|
||||
/** Takes a subchannel factory, returns a new one that mutates incoming
|
||||
channel_args by adding a new argument; ownership of input, args is retained |
||||
by the caller. */ |
||||
grpc_subchannel_factory *grpc_subchannel_factory_merge_channel_args( |
||||
grpc_subchannel_factory *input, const grpc_channel_args *args); |
||||
|
||||
#endif /* GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_DECORATORS_MERGE_CHANNEL_ARGS_H */ |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue