mirror of https://github.com/grpc/grpc.git
commit
6e080a3651
248 changed files with 21417 additions and 2200 deletions
After Width: | Height: | Size: 62 KiB |
@ -0,0 +1,92 @@ |
||||
# Stress Test framework for gRPC |
||||
|
||||
(Sree Kuchibhotla - sreek@) |
||||
|
||||
> Status: This is implemented. More details at [README.md](https://github.com/grpc/grpc/blob/master/tools/run_tests/stress_test/README.md) |
||||
|
||||
|
||||
**I. GOALS** |
||||
|
||||
1) Build a stress test suite for gRPC: |
||||
|
||||
* Build a stress test suite that can Identify bugs by testing the system (gRPC server/client) under extreme conditions: |
||||
* High load |
||||
* High concurrency |
||||
* Limited resources |
||||
* Intermittent failures |
||||
* Should be integrated with Jenkins CI |
||||
|
||||
2) Make it generic enough (i.e build a generic test framework) that can be used for: |
||||
|
||||
* Executing M instances of a client against N instances of a server with an arbitrarily defined connection matrix |
||||
* Execute heterogenous test configurations - for example: Java stress test clients against C++ servers or Node clients against Python servers or TSAN C++ clients vs ASAN C++ Servers etc. |
||||
* Easy and Flexible enough that Devs can use it to recreate complex test scenarios |
||||
|
||||
The implementation effort is divided into two parts: |
||||
|
||||
* Building a "Stress Test Framework" to run the stress test suites- More details in **Section II** (The idea is that the Stress Test framework is generic enough that it would be easier to modify it to run other suites like interop-tests or custom test scenarios) |
||||
* Building a 'Stress test suite' - More details in **section III** |
||||
|
||||
**Terminology:** |
||||
|
||||
GCE - Google compute engine |
||||
GKE - Google Container engine |
||||
Kubernetes - Google's open source service scheduler / orchestrator. |
||||
|
||||
**Note:** The terms GKE and Kubernetes are used interchangeably in this document |
||||
|
||||
# II. STRESS TEST FRAMEWORK |
||||
|
||||
(The details of each step are explained below)) |
||||
![image](images/stress_test_framework.png) |
||||
**Figure 1** |
||||
|
||||
### Step 1 Read the test config, generate base docker images |
||||
|
||||
**_Test Config:_** The test configuration contains the following information: |
||||
|
||||
* _GKE info:_ GKE project and cluster info |
||||
* _Docker images:_ Instructions to build docker images |
||||
* _Client templates:_ One or more client templates each containing the following information: |
||||
* Which docker image to use |
||||
* Path to the client program to launch (within the docker image) |
||||
* Parameters to the client program |
||||
* _Server templates:_ Similar to Client templates - except that these are for servers |
||||
* Test matrix containing the following: |
||||
* _Server groups:_ One or more groups of servers containing the following info for each group |
||||
* Which server template to use |
||||
* How many instances to launch |
||||
* _Client groups:_ One or more groups of clients containing the following (for each group): |
||||
* Which client template to use |
||||
* How many instances to launch |
||||
* Which server group to talk to (all clients in this group will talk to all servers in the server group) |
||||
|
||||
The first step is to read the test config and build the docker images |
||||
|
||||
**_Stress server docker image:_** The following are the main files in the server docker images |
||||
|
||||
* _Interop_server:_ The server program |
||||
* `run_server.py`: This is a python script which is the entry point of the docker image (i.e this is the script that is called when the docker image is run in GKE). This script launches the interop server and also updates the status in BigQuery. If the interop_server fails for whatever reason, the script launch_server.py logs that status in BigQuery |
||||
|
||||
**_Stress client docker image:_** |
||||
|
||||
* Stress client: The stress test client. In addition to talking to the interop_server, the stress client also exports metrics (which can be queried by the metrics_client described below) |
||||
* Metrics client: Metrics client connects to the stress_client to get the current qps metrics. |
||||
* `run_client.py`: This is a python script which is the entry point of the docker image (i.e this is the script that is called when the docker image is run in GKE). This script launches the stress client and also updates the status in BigQuery. The script then periodically launches metrics client to query the qps from the stress client and then uploads the qps to BigQuery. |
||||
|
||||
### Step 2) Upload the docker images to GKE |
||||
The docker images are uploaded to the GKE registry |
||||
|
||||
### Step 3) Launch the tests in GKE |
||||
The test driver reads the test matrix (described in step 1) and creates the necessary server and client pods in GKE. |
||||
|
||||
### Step 4) Tests are run in GKE |
||||
GKE starts running the tests by calling the entry points in *each* docker image (i.e `run_server.py` or `run_client.py` depending on whcih docker image it is) |
||||
|
||||
### Step 5) Upload the status to GKE and Monitor the status in GKE |
||||
* 5.1 The tests periodically update their status in BigQuery |
||||
* 5.2 The test driver periodically checks the status in Bigquery to see if any tests failed. If any tests failed, the driver immediately stops the tests. If not, the driver continues to run the tests for a configurable amount of time. |
||||
|
||||
### Step 6) Create a summary report |
||||
The test driver creates a final summary report containing details about any test failures and information about how to connect the failed pods in GKE for debugging. |
||||
|
@ -1,94 +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 "src/core/ext/client_channel/resolver_result.h" |
||||
|
||||
#include <string.h> |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/string_util.h> |
||||
|
||||
#include "src/core/lib/channel/channel_args.h" |
||||
|
||||
struct grpc_resolver_result { |
||||
gpr_refcount refs; |
||||
char* server_name; |
||||
grpc_lb_addresses* addresses; |
||||
char* lb_policy_name; |
||||
grpc_channel_args* lb_policy_args; |
||||
}; |
||||
|
||||
grpc_resolver_result* grpc_resolver_result_create( |
||||
const char* server_name, grpc_lb_addresses* addresses, |
||||
const char* lb_policy_name, grpc_channel_args* lb_policy_args) { |
||||
grpc_resolver_result* result = gpr_malloc(sizeof(*result)); |
||||
memset(result, 0, sizeof(*result)); |
||||
gpr_ref_init(&result->refs, 1); |
||||
result->server_name = gpr_strdup(server_name); |
||||
result->addresses = addresses; |
||||
result->lb_policy_name = gpr_strdup(lb_policy_name); |
||||
result->lb_policy_args = lb_policy_args; |
||||
return result; |
||||
} |
||||
|
||||
void grpc_resolver_result_ref(grpc_resolver_result* result) { |
||||
gpr_ref(&result->refs); |
||||
} |
||||
|
||||
void grpc_resolver_result_unref(grpc_exec_ctx* exec_ctx, |
||||
grpc_resolver_result* result) { |
||||
if (gpr_unref(&result->refs)) { |
||||
gpr_free(result->server_name); |
||||
grpc_lb_addresses_destroy(result->addresses, NULL /* user_data_destroy */); |
||||
gpr_free(result->lb_policy_name); |
||||
grpc_channel_args_destroy(result->lb_policy_args); |
||||
gpr_free(result); |
||||
} |
||||
} |
||||
|
||||
const char* grpc_resolver_result_get_server_name(grpc_resolver_result* result) { |
||||
return result->server_name; |
||||
} |
||||
|
||||
grpc_lb_addresses* grpc_resolver_result_get_addresses( |
||||
grpc_resolver_result* result) { |
||||
return result->addresses; |
||||
} |
||||
|
||||
const char* grpc_resolver_result_get_lb_policy_name( |
||||
grpc_resolver_result* result) { |
||||
return result->lb_policy_name; |
||||
} |
||||
|
||||
grpc_channel_args* grpc_resolver_result_get_lb_policy_args( |
||||
grpc_resolver_result* result) { |
||||
return result->lb_policy_args; |
||||
} |
@ -1,68 +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.
|
||||
//
|
||||
|
||||
#ifndef GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_RESULT_H |
||||
#define GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_RESULT_H |
||||
|
||||
#include "src/core/ext/client_channel/lb_policy_factory.h" |
||||
|
||||
// TODO(roth, ctiller): In the long term, we are considering replacing
|
||||
// the resolver_result data structure with grpc_channel_args. The idea is
|
||||
// that the resolver will return a set of channel args that contains the
|
||||
// information that is currently in the resolver_result struct. For
|
||||
// example, there will be specific args indicating the set of addresses
|
||||
// and the name of the LB policy to instantiate. Note that if we did
|
||||
// this, we would probably want to change the data structure of
|
||||
// grpc_channel_args such to a hash table or AVL or some other data
|
||||
// structure that does not require linear search to find keys.
|
||||
|
||||
/// Results reported from a grpc_resolver.
|
||||
typedef struct grpc_resolver_result grpc_resolver_result; |
||||
|
||||
/// Takes ownership of \a addresses and \a lb_policy_args.
|
||||
grpc_resolver_result* grpc_resolver_result_create( |
||||
const char* server_name, grpc_lb_addresses* addresses, |
||||
const char* lb_policy_name, grpc_channel_args* lb_policy_args); |
||||
|
||||
void grpc_resolver_result_ref(grpc_resolver_result* result); |
||||
void grpc_resolver_result_unref(grpc_exec_ctx* exec_ctx, |
||||
grpc_resolver_result* result); |
||||
|
||||
/// Accessors. Caller does NOT take ownership of results.
|
||||
const char* grpc_resolver_result_get_server_name(grpc_resolver_result* result); |
||||
grpc_lb_addresses* grpc_resolver_result_get_addresses( |
||||
grpc_resolver_result* result); |
||||
const char* grpc_resolver_result_get_lb_policy_name( |
||||
grpc_resolver_result* result); |
||||
grpc_channel_args* grpc_resolver_result_get_lb_policy_args( |
||||
grpc_resolver_result* result); |
||||
|
||||
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_RESULT_H */ |
@ -0,0 +1,49 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#include "src/core/lib/iomgr/port.h" |
||||
|
||||
#ifdef GRPC_UV |
||||
|
||||
#include "src/core/lib/debug/trace.h" |
||||
#include "src/core/lib/iomgr/pollset_uv.h" |
||||
#include "src/core/lib/iomgr/tcp_uv.h" |
||||
|
||||
void grpc_iomgr_platform_init(void) { |
||||
grpc_pollset_global_init(); |
||||
grpc_register_tracer("tcp", &grpc_tcp_trace); |
||||
} |
||||
void grpc_iomgr_platform_flush(void) {} |
||||
void grpc_iomgr_platform_shutdown(void) { grpc_pollset_global_shutdown(); } |
||||
|
||||
#endif /* GRPC_UV */ |
@ -0,0 +1,62 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#include "src/core/lib/iomgr/port.h" |
||||
|
||||
#ifdef GRPC_UV |
||||
|
||||
#include "src/core/lib/iomgr/pollset_set.h" |
||||
|
||||
grpc_pollset_set* grpc_pollset_set_create(void) { |
||||
return (grpc_pollset_set*)((intptr_t)0xdeafbeef); |
||||
} |
||||
|
||||
void grpc_pollset_set_destroy(grpc_pollset_set* pollset_set) {} |
||||
|
||||
void grpc_pollset_set_add_pollset(grpc_exec_ctx* exec_ctx, |
||||
grpc_pollset_set* pollset_set, |
||||
grpc_pollset* pollset) {} |
||||
|
||||
void grpc_pollset_set_del_pollset(grpc_exec_ctx* exec_ctx, |
||||
grpc_pollset_set* pollset_set, |
||||
grpc_pollset* pollset) {} |
||||
|
||||
void grpc_pollset_set_add_pollset_set(grpc_exec_ctx* exec_ctx, |
||||
grpc_pollset_set* bag, |
||||
grpc_pollset_set* item) {} |
||||
|
||||
void grpc_pollset_set_del_pollset_set(grpc_exec_ctx* exec_ctx, |
||||
grpc_pollset_set* bag, |
||||
grpc_pollset_set* item) {} |
||||
|
||||
#endif /* GRPC_UV */ |
@ -0,0 +1,142 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#include "src/core/lib/iomgr/port.h" |
||||
|
||||
#ifdef GRPC_UV |
||||
|
||||
#include <uv.h> |
||||
|
||||
#include <string.h> |
||||
|
||||
#include <grpc/support/log.h> |
||||
#include <grpc/support/sync.h> |
||||
|
||||
#include "src/core/lib/iomgr/pollset.h" |
||||
#include "src/core/lib/iomgr/pollset_uv.h" |
||||
|
||||
struct grpc_pollset { |
||||
uv_timer_t timer; |
||||
int shutting_down; |
||||
}; |
||||
|
||||
/* Indicates that grpc_pollset_work should run an iteration of the UV loop
|
||||
before running callbacks. This defaults to 1, and should be disabled if |
||||
grpc_pollset_work will be called within the callstack of uv_run */ |
||||
int grpc_pollset_work_run_loop; |
||||
|
||||
gpr_mu grpc_polling_mu; |
||||
|
||||
size_t grpc_pollset_size() { return sizeof(grpc_pollset); } |
||||
|
||||
void grpc_pollset_global_init(void) { |
||||
gpr_mu_init(&grpc_polling_mu); |
||||
grpc_pollset_work_run_loop = 1; |
||||
} |
||||
|
||||
void grpc_pollset_global_shutdown(void) { gpr_mu_destroy(&grpc_polling_mu); } |
||||
|
||||
void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu) { |
||||
*mu = &grpc_polling_mu; |
||||
memset(pollset, 0, sizeof(grpc_pollset)); |
||||
uv_timer_init(uv_default_loop(), &pollset->timer); |
||||
pollset->shutting_down = 0; |
||||
} |
||||
|
||||
static void timer_close_cb(uv_handle_t *handle) { handle->data = (void *)1; } |
||||
|
||||
void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, |
||||
grpc_closure *closure) { |
||||
GPR_ASSERT(!pollset->shutting_down); |
||||
pollset->shutting_down = 1; |
||||
if (grpc_pollset_work_run_loop) { |
||||
// Drain any pending UV callbacks without blocking
|
||||
uv_run(uv_default_loop(), UV_RUN_NOWAIT); |
||||
} |
||||
grpc_exec_ctx_sched(exec_ctx, closure, GRPC_ERROR_NONE, NULL); |
||||
} |
||||
|
||||
void grpc_pollset_destroy(grpc_pollset *pollset) { |
||||
uv_close((uv_handle_t *)&pollset->timer, timer_close_cb); |
||||
// timer.data is a boolean indicating that the timer has finished closing
|
||||
pollset->timer.data = (void *)0; |
||||
if (grpc_pollset_work_run_loop) { |
||||
while (!pollset->timer.data) { |
||||
uv_run(uv_default_loop(), UV_RUN_NOWAIT); |
||||
} |
||||
} |
||||
} |
||||
|
||||
void grpc_pollset_reset(grpc_pollset *pollset) { |
||||
GPR_ASSERT(pollset->shutting_down); |
||||
pollset->shutting_down = 0; |
||||
} |
||||
|
||||
static void timer_run_cb(uv_timer_t *timer) {} |
||||
|
||||
grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, |
||||
grpc_pollset_worker **worker_hdl, |
||||
gpr_timespec now, gpr_timespec deadline) { |
||||
uint64_t timeout; |
||||
gpr_mu_unlock(&grpc_polling_mu); |
||||
if (grpc_pollset_work_run_loop) { |
||||
if (gpr_time_cmp(deadline, now) >= 0) { |
||||
timeout = (uint64_t)gpr_time_to_millis(gpr_time_sub(deadline, now)); |
||||
} else { |
||||
timeout = 0; |
||||
} |
||||
/* We special-case timeout=0 so that we don't bother with the timer when
|
||||
the loop won't block anyway */ |
||||
if (timeout > 0) { |
||||
uv_timer_start(&pollset->timer, timer_run_cb, timeout, 0); |
||||
/* Run until there is some I/O activity or the timer triggers. It doesn't
|
||||
matter which happens */ |
||||
uv_run(uv_default_loop(), UV_RUN_ONCE); |
||||
uv_timer_stop(&pollset->timer); |
||||
} else { |
||||
uv_run(uv_default_loop(), UV_RUN_NOWAIT); |
||||
} |
||||
} |
||||
if (!grpc_closure_list_empty(exec_ctx->closure_list)) { |
||||
grpc_exec_ctx_flush(exec_ctx); |
||||
} |
||||
gpr_mu_lock(&grpc_polling_mu); |
||||
return GRPC_ERROR_NONE; |
||||
} |
||||
|
||||
grpc_error *grpc_pollset_kick(grpc_pollset *pollset, |
||||
grpc_pollset_worker *specific_worker) { |
||||
return GRPC_ERROR_NONE; |
||||
} |
||||
|
||||
#endif /* GRPC_UV */ |
@ -0,0 +1,42 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPC_CORE_LIB_IOMGR_POLLSET_UV_H |
||||
#define GRPC_CORE_LIB_IOMGR_POLLSET_UV_H |
||||
|
||||
extern int grpc_pollset_work_run_loop; |
||||
|
||||
void grpc_pollset_global_init(void); |
||||
void grpc_pollset_global_shutdown(void); |
||||
|
||||
#endif /* GRPC_CORE_LIB_IOMGR_POLLSET_UV_H */ |
@ -0,0 +1,131 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#ifndef GRPC_CORE_LIB_IOMGR_PORT_H |
||||
#define GRPC_CORE_LIB_IOMGR_PORT_H |
||||
|
||||
#if defined(GRPC_UV) |
||||
// Do nothing
|
||||
#elif defined(GPR_MANYLINUX1) |
||||
#define GRPC_HAVE_IPV6_RECVPKTINFO 1 |
||||
#define GRPC_HAVE_IP_PKTINFO 1 |
||||
#define GRPC_HAVE_MSG_NOSIGNAL 1 |
||||
#define GRPC_HAVE_UNIX_SOCKET 1 |
||||
#define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1 |
||||
#define GRPC_POSIX_SOCKET 1 |
||||
#define GRPC_POSIX_SOCKETADDR 1 |
||||
#define GRPC_POSIX_SOCKETUTILS 1 |
||||
#define GRPC_POSIX_WAKEUP_FD 1 |
||||
#define GRPC_TIMER_USE_GENERIC 1 |
||||
#elif defined(GPR_WINDOWS) |
||||
#define GRPC_TIMER_USE_GENERIC 1 |
||||
#define GRPC_WINSOCK_SOCKET 1 |
||||
#define GRPC_WINDOWS_SOCKETUTILS 1 |
||||
#elif defined(GPR_ANDROID) |
||||
#define GRPC_HAVE_IPV6_RECVPKTINFO 1 |
||||
#define GRPC_HAVE_IP_PKTINFO 1 |
||||
#define GRPC_HAVE_MSG_NOSIGNAL 1 |
||||
#define GRPC_HAVE_UNIX_SOCKET 1 |
||||
#define GRPC_LINUX_EVENTFD 1 |
||||
#define GRPC_POSIX_SOCKET 1 |
||||
#define GRPC_POSIX_SOCKETADDR 1 |
||||
#define GRPC_POSIX_SOCKETUTILS 1 |
||||
#define GRPC_POSIX_WAKEUP_FD 1 |
||||
#define GRPC_TIMER_USE_GENERIC 1 |
||||
#elif defined(GPR_LINUX) |
||||
#define GRPC_HAVE_IPV6_RECVPKTINFO 1 |
||||
#define GRPC_HAVE_IP_PKTINFO 1 |
||||
#define GRPC_HAVE_MSG_NOSIGNAL 1 |
||||
#define GRPC_HAVE_UNIX_SOCKET 1 |
||||
#define GRPC_LINUX_MULTIPOLL_WITH_EPOLL 1 |
||||
#define GRPC_POSIX_SOCKET 1 |
||||
#define GRPC_POSIX_SOCKETADDR 1 |
||||
#define GRPC_POSIX_WAKEUP_FD 1 |
||||
#define GRPC_TIMER_USE_GENERIC 1 |
||||
#ifdef __GLIBC_PREREQ |
||||
#if __GLIBC_PREREQ(2, 9) |
||||
#define GRPC_LINUX_EPOLL 1 |
||||
#define GRPC_LINUX_EVENTFD 1 |
||||
#endif |
||||
#if __GLIBC_PREREQ(2, 10) |
||||
#define GRPC_LINUX_SOCKETUTILS 1 |
||||
#endif |
||||
#endif |
||||
#ifndef GRPC_LINUX_EVENTFD |
||||
#define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1 |
||||
#endif |
||||
#ifndef GRPC_LINUX_SOCKETUTILS |
||||
#define GRPC_POSIX_SOCKETUTILS |
||||
#endif |
||||
#elif defined(GPR_APPLE) |
||||
#define GRPC_HAVE_IP_PKTINFO 1 |
||||
#define GRPC_HAVE_SO_NOSIGPIPE 1 |
||||
#define GRPC_HAVE_UNIX_SOCKET 1 |
||||
#define GRPC_MSG_IOVLEN_TYPE int |
||||
#define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1 |
||||
#define GRPC_POSIX_SOCKET 1 |
||||
#define GRPC_POSIX_SOCKETADDR 1 |
||||
#define GRPC_POSIX_SOCKETUTILS 1 |
||||
#define GRPC_POSIX_WAKEUP_FD 1 |
||||
#define GRPC_TIMER_USE_GENERIC 1 |
||||
#elif defined(GPR_FREEBSD) |
||||
#define GRPC_HAVE_IPV6_RECVPKTINFO 1 |
||||
#define GRPC_HAVE_IP_PKTINFO 1 |
||||
#define GRPC_HAVE_SO_NOSIGPIPE 1 |
||||
#define GRPC_HAVE_UNIX_SOCKET 1 |
||||
#define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1 |
||||
#define GRPC_POSIX_SOCKET 1 |
||||
#define GRPC_POSIX_SOCKETADDR 1 |
||||
#define GRPC_POSIX_SOCKETUTILS 1 |
||||
#define GRPC_POSIX_WAKEUP_FD 1 |
||||
#define GRPC_TIMER_USE_GENERIC 1 |
||||
#elif defined(GPR_NACL) |
||||
#define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1 |
||||
#define GRPC_POSIX_SOCKET 1 |
||||
#define GRPC_POSIX_SOCKETADDR 1 |
||||
#define GRPC_POSIX_SOCKETUTILS 1 |
||||
#define GRPC_POSIX_WAKEUP_FD 1 |
||||
#define GRPC_TIMER_USE_GENERIC 1 |
||||
#elif !defined(GPR_NO_AUTODETECT_PLATFORM) |
||||
#error "Platform not recognized" |
||||
#endif |
||||
|
||||
#if defined(GRPC_POSIX_SOCKET) + defined(GRPC_WINSOCK_SOCKET) + \ |
||||
defined(GRPC_CUSTOM_SOCKET) + defined(GRPC_UV) != \
|
||||
1 |
||||
#error Must define exactly one of GRPC_POSIX_SOCKET, GRPC_WINSOCK_SOCKET, GPR_CUSTOM_SOCKET |
||||
#endif |
||||
|
||||
#endif /* GRPC_CORE_LIB_IOMGR_PORT_H */ |
@ -0,0 +1,231 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#include "src/core/lib/iomgr/port.h" |
||||
#ifdef GRPC_UV |
||||
|
||||
#include <uv.h> |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/host_port.h> |
||||
#include <grpc/support/log.h> |
||||
#include <grpc/support/string_util.h> |
||||
|
||||
#include "src/core/lib/iomgr/closure.h" |
||||
#include "src/core/lib/iomgr/error.h" |
||||
#include "src/core/lib/iomgr/exec_ctx.h" |
||||
#include "src/core/lib/iomgr/resolve_address.h" |
||||
#include "src/core/lib/iomgr/sockaddr.h" |
||||
#include "src/core/lib/iomgr/sockaddr_utils.h" |
||||
|
||||
#include <string.h> |
||||
|
||||
typedef struct request { |
||||
grpc_closure *on_done; |
||||
grpc_resolved_addresses **addresses; |
||||
struct addrinfo *hints; |
||||
} request; |
||||
|
||||
static grpc_error *handle_addrinfo_result(int status, struct addrinfo *result, |
||||
grpc_resolved_addresses **addresses) { |
||||
struct addrinfo *resp; |
||||
size_t i; |
||||
if (status != 0) { |
||||
grpc_error *error; |
||||
*addresses = NULL; |
||||
error = GRPC_ERROR_CREATE("getaddrinfo failed"); |
||||
error = |
||||
grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, uv_strerror(status)); |
||||
return error; |
||||
} |
||||
(*addresses) = gpr_malloc(sizeof(grpc_resolved_addresses)); |
||||
(*addresses)->naddrs = 0; |
||||
for (resp = result; resp != NULL; resp = resp->ai_next) { |
||||
(*addresses)->naddrs++; |
||||
} |
||||
(*addresses)->addrs = |
||||
gpr_malloc(sizeof(grpc_resolved_address) * (*addresses)->naddrs); |
||||
i = 0; |
||||
for (resp = result; resp != NULL; resp = resp->ai_next) { |
||||
memcpy(&(*addresses)->addrs[i].addr, resp->ai_addr, resp->ai_addrlen); |
||||
(*addresses)->addrs[i].len = resp->ai_addrlen; |
||||
i++; |
||||
} |
||||
|
||||
{ |
||||
for (i = 0; i < (*addresses)->naddrs; i++) { |
||||
char *buf; |
||||
grpc_sockaddr_to_string(&buf, &(*addresses)->addrs[i], 0); |
||||
gpr_free(buf); |
||||
} |
||||
} |
||||
return GRPC_ERROR_NONE; |
||||
} |
||||
|
||||
static void getaddrinfo_callback(uv_getaddrinfo_t *req, int status, |
||||
struct addrinfo *res) { |
||||
request *r = (request *)req->data; |
||||
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
||||
grpc_error *error; |
||||
error = handle_addrinfo_result(status, res, r->addresses); |
||||
grpc_exec_ctx_sched(&exec_ctx, r->on_done, error, NULL); |
||||
grpc_exec_ctx_finish(&exec_ctx); |
||||
|
||||
gpr_free(r->hints); |
||||
gpr_free(r); |
||||
gpr_free(req); |
||||
uv_freeaddrinfo(res); |
||||
} |
||||
|
||||
static grpc_error *try_split_host_port(const char *name, |
||||
const char *default_port, char **host, |
||||
char **port) { |
||||
/* parse name, splitting it into host and port parts */ |
||||
grpc_error *error; |
||||
gpr_split_host_port(name, host, port); |
||||
if (host == NULL) { |
||||
char *msg; |
||||
gpr_asprintf(&msg, "unparseable host:port: '%s'", name); |
||||
error = GRPC_ERROR_CREATE(msg); |
||||
gpr_free(msg); |
||||
return error; |
||||
} |
||||
if (port == NULL) { |
||||
if (default_port == NULL) { |
||||
char *msg; |
||||
gpr_asprintf(&msg, "no port in name '%s'", name); |
||||
error = GRPC_ERROR_CREATE(msg); |
||||
gpr_free(msg); |
||||
return error; |
||||
} |
||||
*port = gpr_strdup(default_port); |
||||
} |
||||
return GRPC_ERROR_NONE; |
||||
} |
||||
|
||||
static grpc_error *blocking_resolve_address_impl( |
||||
const char *name, const char *default_port, |
||||
grpc_resolved_addresses **addresses) { |
||||
char *host; |
||||
char *port; |
||||
struct addrinfo hints; |
||||
uv_getaddrinfo_t req; |
||||
int s; |
||||
grpc_error *err; |
||||
|
||||
req.addrinfo = NULL; |
||||
|
||||
err = try_split_host_port(name, default_port, &host, &port); |
||||
if (err != GRPC_ERROR_NONE) { |
||||
goto done; |
||||
} |
||||
|
||||
/* Call getaddrinfo */ |
||||
memset(&hints, 0, sizeof(hints)); |
||||
hints.ai_family = AF_UNSPEC; /* ipv4 or ipv6 */ |
||||
hints.ai_socktype = SOCK_STREAM; /* stream socket */ |
||||
hints.ai_flags = AI_PASSIVE; /* for wildcard IP address */ |
||||
|
||||
s = uv_getaddrinfo(uv_default_loop(), &req, NULL, host, port, &hints); |
||||
err = handle_addrinfo_result(s, req.addrinfo, addresses); |
||||
|
||||
done: |
||||
gpr_free(host); |
||||
gpr_free(port); |
||||
if (req.addrinfo) { |
||||
uv_freeaddrinfo(req.addrinfo); |
||||
} |
||||
return err; |
||||
} |
||||
|
||||
grpc_error *(*grpc_blocking_resolve_address)( |
||||
const char *name, const char *default_port, |
||||
grpc_resolved_addresses **addresses) = blocking_resolve_address_impl; |
||||
|
||||
void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) { |
||||
if (addrs != NULL) { |
||||
gpr_free(addrs->addrs); |
||||
} |
||||
gpr_free(addrs); |
||||
} |
||||
|
||||
static void resolve_address_impl(grpc_exec_ctx *exec_ctx, const char *name, |
||||
const char *default_port, |
||||
grpc_closure *on_done, |
||||
grpc_resolved_addresses **addrs) { |
||||
uv_getaddrinfo_t *req; |
||||
request *r; |
||||
struct addrinfo *hints; |
||||
char *host; |
||||
char *port; |
||||
grpc_error *err; |
||||
int s; |
||||
err = try_split_host_port(name, default_port, &host, &port); |
||||
if (err != GRPC_ERROR_NONE) { |
||||
grpc_exec_ctx_sched(exec_ctx, on_done, err, NULL); |
||||
return; |
||||
} |
||||
r = gpr_malloc(sizeof(request)); |
||||
r->on_done = on_done; |
||||
r->addresses = addrs; |
||||
req = gpr_malloc(sizeof(uv_getaddrinfo_t)); |
||||
req->data = r; |
||||
|
||||
/* Call getaddrinfo */ |
||||
hints = gpr_malloc(sizeof(struct addrinfo)); |
||||
memset(hints, 0, sizeof(struct addrinfo)); |
||||
hints->ai_family = AF_UNSPEC; /* ipv4 or ipv6 */ |
||||
hints->ai_socktype = SOCK_STREAM; /* stream socket */ |
||||
hints->ai_flags = AI_PASSIVE; /* for wildcard IP address */ |
||||
r->hints = hints; |
||||
|
||||
s = uv_getaddrinfo(uv_default_loop(), req, getaddrinfo_callback, host, port, |
||||
hints); |
||||
|
||||
if (s != 0) { |
||||
*addrs = NULL; |
||||
err = GRPC_ERROR_CREATE("getaddrinfo failed"); |
||||
err = grpc_error_set_str(err, GRPC_ERROR_STR_OS_ERROR, uv_strerror(s)); |
||||
grpc_exec_ctx_sched(exec_ctx, on_done, err, NULL); |
||||
gpr_free(r); |
||||
gpr_free(req); |
||||
gpr_free(hints); |
||||
} |
||||
} |
||||
|
||||
void (*grpc_resolve_address)(grpc_exec_ctx *exec_ctx, const char *name, |
||||
const char *default_port, grpc_closure *on_done, |
||||
grpc_resolved_addresses **addrs) = |
||||
resolve_address_impl; |
||||
|
||||
#endif /* GRPC_UV */ |
@ -0,0 +1,42 @@ |
||||
/*
|
||||
* |
||||
* 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_CORE_LIB_IOMGR_SOCKET_UTILS_H |
||||
#define GRPC_CORE_LIB_IOMGR_SOCKET_UTILS_H |
||||
|
||||
#include <stddef.h> |
||||
|
||||
/* A wrapper for inet_ntop on POSIX systems and InetNtop on Windows systems */ |
||||
const char *grpc_inet_ntop(int af, const void *src, char *dst, size_t size); |
||||
|
||||
#endif /* GRPC_CORE_LIB_IOMGR_SOCKET_UTILS_H */ |
@ -0,0 +1,49 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#include "src/core/lib/iomgr/port.h" |
||||
|
||||
#ifdef GRPC_UV |
||||
|
||||
#include <uv.h> |
||||
|
||||
#include "src/core/lib/iomgr/socket_utils.h" |
||||
|
||||
#include <grpc/support/log.h> |
||||
|
||||
const char *grpc_inet_ntop(int af, const void *src, char *dst, size_t size) { |
||||
uv_inet_ntop(af, src, dst, size); |
||||
return dst; |
||||
} |
||||
|
||||
#endif /* GRPC_UV */ |
@ -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. |
||||
* |
||||
*/ |
||||
|
||||
#include "src/core/lib/iomgr/port.h" |
||||
|
||||
#ifdef GRPC_WINDOWS_SOCKETUTILS |
||||
|
||||
#include "src/core/lib/iomgr/sockaddr.h" |
||||
#include "src/core/lib/iomgr/socket_utils.h" |
||||
|
||||
#include <grpc/support/log.h> |
||||
|
||||
const char *grpc_inet_ntop(int af, const void *src, char *dst, size_t size) { |
||||
/* Windows InetNtopA wants a mutable ip pointer */ |
||||
return InetNtopA(af, (void *)src, dst, size); |
||||
} |
||||
|
||||
#endif /* GRPC_WINDOWS_SOCKETUTILS */ |
@ -0,0 +1,153 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#include "src/core/lib/iomgr/port.h" |
||||
|
||||
#ifdef GRPC_UV |
||||
|
||||
#include <string.h> |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/log.h> |
||||
|
||||
#include "src/core/lib/iomgr/error.h" |
||||
#include "src/core/lib/iomgr/sockaddr_utils.h" |
||||
#include "src/core/lib/iomgr/tcp_client.h" |
||||
#include "src/core/lib/iomgr/tcp_uv.h" |
||||
#include "src/core/lib/iomgr/timer.h" |
||||
|
||||
typedef struct grpc_uv_tcp_connect { |
||||
uv_connect_t connect_req; |
||||
grpc_timer alarm; |
||||
uv_tcp_t *tcp_handle; |
||||
grpc_closure *closure; |
||||
grpc_endpoint **endpoint; |
||||
int refs; |
||||
char *addr_name; |
||||
} grpc_uv_tcp_connect; |
||||
|
||||
static void uv_tcp_connect_cleanup(grpc_uv_tcp_connect *connect) { |
||||
gpr_free(connect); |
||||
} |
||||
|
||||
static void tcp_close_callback(uv_handle_t *handle) { gpr_free(handle); } |
||||
|
||||
static void uv_tc_on_alarm(grpc_exec_ctx *exec_ctx, void *acp, |
||||
grpc_error *error) { |
||||
int done; |
||||
grpc_uv_tcp_connect *connect = acp; |
||||
if (error == GRPC_ERROR_NONE) { |
||||
/* error == NONE implies that the timer ran out, and wasn't cancelled. If
|
||||
it was cancelled, then the handler that cancelled it also should close |
||||
the handle, if applicable */ |
||||
uv_close((uv_handle_t *)connect->tcp_handle, tcp_close_callback); |
||||
} |
||||
done = (--connect->refs == 0); |
||||
if (done) { |
||||
uv_tcp_connect_cleanup(connect); |
||||
} |
||||
} |
||||
|
||||
static void uv_tc_on_connect(uv_connect_t *req, int status) { |
||||
grpc_uv_tcp_connect *connect = req->data; |
||||
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
||||
grpc_error *error = GRPC_ERROR_NONE; |
||||
int done; |
||||
grpc_closure *closure = connect->closure; |
||||
grpc_timer_cancel(&exec_ctx, &connect->alarm); |
||||
if (status == 0) { |
||||
*connect->endpoint = |
||||
grpc_tcp_create(connect->tcp_handle, connect->addr_name); |
||||
} else { |
||||
error = GRPC_ERROR_CREATE("Failed to connect to remote host"); |
||||
error = grpc_error_set_int(error, GRPC_ERROR_INT_ERRNO, -status); |
||||
error = |
||||
grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, uv_strerror(status)); |
||||
if (status == UV_ECANCELED) { |
||||
error = grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, |
||||
"Timeout occurred"); |
||||
// This should only happen if the handle is already closed
|
||||
} else { |
||||
error = grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, |
||||
uv_strerror(status)); |
||||
uv_close((uv_handle_t *)connect->tcp_handle, tcp_close_callback); |
||||
} |
||||
} |
||||
done = (--connect->refs == 0); |
||||
if (done) { |
||||
uv_tcp_connect_cleanup(connect); |
||||
} |
||||
grpc_exec_ctx_sched(&exec_ctx, closure, error, NULL); |
||||
grpc_exec_ctx_finish(&exec_ctx); |
||||
} |
||||
|
||||
static void tcp_client_connect_impl(grpc_exec_ctx *exec_ctx, |
||||
grpc_closure *closure, grpc_endpoint **ep, |
||||
grpc_pollset_set *interested_parties, |
||||
const grpc_resolved_address *resolved_addr, |
||||
gpr_timespec deadline) { |
||||
grpc_uv_tcp_connect *connect; |
||||
(void)interested_parties; |
||||
connect = gpr_malloc(sizeof(grpc_uv_tcp_connect)); |
||||
memset(connect, 0, sizeof(grpc_uv_tcp_connect)); |
||||
connect->closure = closure; |
||||
connect->endpoint = ep; |
||||
connect->tcp_handle = gpr_malloc(sizeof(uv_tcp_t)); |
||||
connect->addr_name = grpc_sockaddr_to_uri(resolved_addr); |
||||
uv_tcp_init(uv_default_loop(), connect->tcp_handle); |
||||
connect->connect_req.data = connect; |
||||
// TODO(murgatroid99): figure out what the return value here means
|
||||
uv_tcp_connect(&connect->connect_req, connect->tcp_handle, |
||||
(const struct sockaddr *)resolved_addr->addr, |
||||
uv_tc_on_connect); |
||||
grpc_timer_init(exec_ctx, &connect->alarm, |
||||
gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC), |
||||
uv_tc_on_alarm, connect, gpr_now(GPR_CLOCK_MONOTONIC)); |
||||
} |
||||
|
||||
// overridden by api_fuzzer.c
|
||||
void (*grpc_tcp_client_connect_impl)( |
||||
grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_endpoint **ep, |
||||
grpc_pollset_set *interested_parties, const grpc_resolved_address *addr, |
||||
gpr_timespec deadline) = tcp_client_connect_impl; |
||||
|
||||
void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure, |
||||
grpc_endpoint **ep, |
||||
grpc_pollset_set *interested_parties, |
||||
const grpc_resolved_address *addr, |
||||
gpr_timespec deadline) { |
||||
grpc_tcp_client_connect_impl(exec_ctx, closure, ep, interested_parties, addr, |
||||
deadline); |
||||
} |
||||
|
||||
#endif /* GRPC_UV */ |
@ -0,0 +1,365 @@ |
||||
/*
|
||||
* |
||||
* 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/lib/iomgr/port.h" |
||||
|
||||
#ifdef GRPC_UV |
||||
|
||||
#include <string.h> |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/log.h> |
||||
|
||||
#include "src/core/lib/iomgr/error.h" |
||||
#include "src/core/lib/iomgr/exec_ctx.h" |
||||
#include "src/core/lib/iomgr/sockaddr.h" |
||||
#include "src/core/lib/iomgr/sockaddr_utils.h" |
||||
#include "src/core/lib/iomgr/tcp_server.h" |
||||
#include "src/core/lib/iomgr/tcp_uv.h" |
||||
|
||||
/* one listening port */ |
||||
typedef struct grpc_tcp_listener grpc_tcp_listener; |
||||
struct grpc_tcp_listener { |
||||
uv_tcp_t *handle; |
||||
grpc_tcp_server *server; |
||||
unsigned port_index; |
||||
int port; |
||||
/* linked list */ |
||||
struct grpc_tcp_listener *next; |
||||
}; |
||||
|
||||
struct grpc_tcp_server { |
||||
gpr_refcount refs; |
||||
|
||||
/* Called whenever accept() succeeds on a server port. */ |
||||
grpc_tcp_server_cb on_accept_cb; |
||||
void *on_accept_cb_arg; |
||||
|
||||
int open_ports; |
||||
|
||||
/* linked list of server ports */ |
||||
grpc_tcp_listener *head; |
||||
grpc_tcp_listener *tail; |
||||
|
||||
/* List of closures passed to shutdown_starting_add(). */ |
||||
grpc_closure_list shutdown_starting; |
||||
|
||||
/* shutdown callback */ |
||||
grpc_closure *shutdown_complete; |
||||
}; |
||||
|
||||
grpc_error *grpc_tcp_server_create(grpc_closure *shutdown_complete, |
||||
const grpc_channel_args *args, |
||||
grpc_tcp_server **server) { |
||||
grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server)); |
||||
(void)args; |
||||
gpr_ref_init(&s->refs, 1); |
||||
s->on_accept_cb = NULL; |
||||
s->on_accept_cb_arg = NULL; |
||||
s->open_ports = 0; |
||||
s->head = NULL; |
||||
s->tail = NULL; |
||||
s->shutdown_starting.head = NULL; |
||||
s->shutdown_starting.tail = NULL; |
||||
s->shutdown_complete = shutdown_complete; |
||||
*server = s; |
||||
return GRPC_ERROR_NONE; |
||||
} |
||||
|
||||
grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s) { |
||||
gpr_ref(&s->refs); |
||||
return s; |
||||
} |
||||
|
||||
void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s, |
||||
grpc_closure *shutdown_starting) { |
||||
grpc_closure_list_append(&s->shutdown_starting, shutdown_starting, |
||||
GRPC_ERROR_NONE); |
||||
} |
||||
|
||||
static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { |
||||
if (s->shutdown_complete != NULL) { |
||||
grpc_exec_ctx_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE, NULL); |
||||
} |
||||
|
||||
while (s->head) { |
||||
grpc_tcp_listener *sp = s->head; |
||||
s->head = sp->next; |
||||
sp->next = NULL; |
||||
gpr_free(sp->handle); |
||||
gpr_free(sp); |
||||
} |
||||
gpr_free(s); |
||||
} |
||||
|
||||
static void handle_close_callback(uv_handle_t *handle) { |
||||
grpc_tcp_listener *sp = (grpc_tcp_listener *)handle->data; |
||||
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
||||
sp->server->open_ports--; |
||||
if (sp->server->open_ports == 0) { |
||||
finish_shutdown(&exec_ctx, sp->server); |
||||
} |
||||
grpc_exec_ctx_finish(&exec_ctx); |
||||
} |
||||
|
||||
static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { |
||||
int immediately_done = 0; |
||||
grpc_tcp_listener *sp; |
||||
|
||||
if (s->open_ports == 0) { |
||||
immediately_done = 1; |
||||
} |
||||
for (sp = s->head; sp; sp = sp->next) { |
||||
uv_close((uv_handle_t *)sp->handle, handle_close_callback); |
||||
} |
||||
|
||||
if (immediately_done) { |
||||
finish_shutdown(exec_ctx, s); |
||||
} |
||||
} |
||||
|
||||
void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { |
||||
if (gpr_unref(&s->refs)) { |
||||
/* Complete shutdown_starting work before destroying. */ |
||||
grpc_exec_ctx local_exec_ctx = GRPC_EXEC_CTX_INIT; |
||||
grpc_exec_ctx_enqueue_list(&local_exec_ctx, &s->shutdown_starting, NULL); |
||||
if (exec_ctx == NULL) { |
||||
grpc_exec_ctx_flush(&local_exec_ctx); |
||||
tcp_server_destroy(&local_exec_ctx, s); |
||||
grpc_exec_ctx_finish(&local_exec_ctx); |
||||
} else { |
||||
grpc_exec_ctx_finish(&local_exec_ctx); |
||||
tcp_server_destroy(exec_ctx, s); |
||||
} |
||||
} |
||||
} |
||||
|
||||
static void accepted_connection_close_cb(uv_handle_t *handle) { |
||||
gpr_free(handle); |
||||
} |
||||
|
||||
static void on_connect(uv_stream_t *server, int status) { |
||||
grpc_tcp_listener *sp = (grpc_tcp_listener *)server->data; |
||||
grpc_tcp_server_acceptor acceptor = {sp->server, sp->port_index, 0}; |
||||
uv_tcp_t *client; |
||||
grpc_endpoint *ep = NULL; |
||||
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
||||
grpc_resolved_address peer_name; |
||||
char *peer_name_string; |
||||
int err; |
||||
|
||||
if (status < 0) { |
||||
gpr_log(GPR_INFO, "Skipping on_accept due to error: %s", |
||||
uv_strerror(status)); |
||||
return; |
||||
} |
||||
client = gpr_malloc(sizeof(uv_tcp_t)); |
||||
uv_tcp_init(uv_default_loop(), client); |
||||
// UV documentation says this is guaranteed to succeed
|
||||
uv_accept((uv_stream_t *)server, (uv_stream_t *)client); |
||||
// If the server has not been started, we discard incoming connections
|
||||
if (sp->server->on_accept_cb == NULL) { |
||||
uv_close((uv_handle_t *)client, accepted_connection_close_cb); |
||||
} else { |
||||
peer_name_string = NULL; |
||||
memset(&peer_name, 0, sizeof(grpc_resolved_address)); |
||||
peer_name.len = sizeof(struct sockaddr_storage); |
||||
err = uv_tcp_getpeername(client, (struct sockaddr *)&peer_name.addr, |
||||
(int *)&peer_name.len); |
||||
if (err == 0) { |
||||
peer_name_string = grpc_sockaddr_to_uri(&peer_name); |
||||
} else { |
||||
gpr_log(GPR_INFO, "uv_tcp_getpeername error: %s", uv_strerror(status)); |
||||
} |
||||
ep = grpc_tcp_create(client, peer_name_string); |
||||
sp->server->on_accept_cb(&exec_ctx, sp->server->on_accept_cb_arg, ep, NULL, |
||||
&acceptor); |
||||
grpc_exec_ctx_finish(&exec_ctx); |
||||
} |
||||
} |
||||
|
||||
static grpc_error *add_socket_to_server(grpc_tcp_server *s, uv_tcp_t *handle, |
||||
const grpc_resolved_address *addr, |
||||
unsigned port_index, |
||||
grpc_tcp_listener **listener) { |
||||
grpc_tcp_listener *sp = NULL; |
||||
int port = -1; |
||||
int status; |
||||
grpc_error *error; |
||||
grpc_resolved_address sockname_temp; |
||||
|
||||
// The last argument to uv_tcp_bind is flags
|
||||
status = uv_tcp_bind(handle, (struct sockaddr *)addr->addr, 0); |
||||
if (status != 0) { |
||||
error = GRPC_ERROR_CREATE("Failed to bind to port"); |
||||
error = |
||||
grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, uv_strerror(status)); |
||||
return error; |
||||
} |
||||
|
||||
status = uv_listen((uv_stream_t *)handle, SOMAXCONN, on_connect); |
||||
if (status != 0) { |
||||
error = GRPC_ERROR_CREATE("Failed to listen to port"); |
||||
error = |
||||
grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, uv_strerror(status)); |
||||
return error; |
||||
} |
||||
|
||||
sockname_temp.len = (int)sizeof(struct sockaddr_storage); |
||||
status = uv_tcp_getsockname(handle, (struct sockaddr *)&sockname_temp.addr, |
||||
(int *)&sockname_temp.len); |
||||
if (status != 0) { |
||||
error = GRPC_ERROR_CREATE("getsockname failed"); |
||||
error = |
||||
grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, uv_strerror(status)); |
||||
return error; |
||||
} |
||||
|
||||
port = grpc_sockaddr_get_port(&sockname_temp); |
||||
|
||||
GPR_ASSERT(port >= 0); |
||||
GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server"); |
||||
sp = gpr_malloc(sizeof(grpc_tcp_listener)); |
||||
sp->next = NULL; |
||||
if (s->head == NULL) { |
||||
s->head = sp; |
||||
} else { |
||||
s->tail->next = sp; |
||||
} |
||||
s->tail = sp; |
||||
sp->server = s; |
||||
sp->handle = handle; |
||||
sp->port = port; |
||||
sp->port_index = port_index; |
||||
handle->data = sp; |
||||
s->open_ports++; |
||||
GPR_ASSERT(sp->handle); |
||||
*listener = sp; |
||||
|
||||
return GRPC_ERROR_NONE; |
||||
} |
||||
|
||||
grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s, |
||||
const grpc_resolved_address *addr, |
||||
int *port) { |
||||
// This function is mostly copied from tcp_server_windows.c
|
||||
grpc_tcp_listener *sp = NULL; |
||||
uv_tcp_t *handle; |
||||
grpc_resolved_address addr6_v4mapped; |
||||
grpc_resolved_address wildcard; |
||||
grpc_resolved_address *allocated_addr = NULL; |
||||
grpc_resolved_address sockname_temp; |
||||
unsigned port_index = 0; |
||||
int status; |
||||
grpc_error *error = GRPC_ERROR_NONE; |
||||
|
||||
if (s->tail != NULL) { |
||||
port_index = s->tail->port_index + 1; |
||||
} |
||||
|
||||
/* Check if this is a wildcard port, and if so, try to keep the port the same
|
||||
as some previously created listener. */ |
||||
if (grpc_sockaddr_get_port(addr) == 0) { |
||||
for (sp = s->head; sp; sp = sp->next) { |
||||
sockname_temp.len = sizeof(struct sockaddr_storage); |
||||
if (0 == uv_tcp_getsockname(sp->handle, |
||||
(struct sockaddr *)&sockname_temp.addr, |
||||
(int *)&sockname_temp.len)) { |
||||
*port = grpc_sockaddr_get_port(&sockname_temp); |
||||
if (*port > 0) { |
||||
allocated_addr = gpr_malloc(sizeof(grpc_resolved_address)); |
||||
memcpy(allocated_addr, addr, sizeof(grpc_resolved_address)); |
||||
grpc_sockaddr_set_port(allocated_addr, *port); |
||||
addr = allocated_addr; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) { |
||||
addr = &addr6_v4mapped; |
||||
} |
||||
|
||||
/* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */ |
||||
if (grpc_sockaddr_is_wildcard(addr, port)) { |
||||
grpc_sockaddr_make_wildcard6(*port, &wildcard); |
||||
|
||||
addr = &wildcard; |
||||
} |
||||
|
||||
handle = gpr_malloc(sizeof(uv_tcp_t)); |
||||
status = uv_tcp_init(uv_default_loop(), handle); |
||||
if (status == 0) { |
||||
error = add_socket_to_server(s, handle, addr, port_index, &sp); |
||||
} else { |
||||
error = GRPC_ERROR_CREATE("Failed to initialize UV tcp handle"); |
||||
error = |
||||
grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, uv_strerror(status)); |
||||
} |
||||
|
||||
gpr_free(allocated_addr); |
||||
|
||||
if (error != GRPC_ERROR_NONE) { |
||||
grpc_error *error_out = GRPC_ERROR_CREATE_REFERENCING( |
||||
"Failed to add port to server", &error, 1); |
||||
GRPC_ERROR_UNREF(error); |
||||
error = error_out; |
||||
*port = -1; |
||||
} else { |
||||
GPR_ASSERT(sp != NULL); |
||||
*port = sp->port; |
||||
} |
||||
return error; |
||||
} |
||||
|
||||
void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *server, |
||||
grpc_pollset **pollsets, size_t pollset_count, |
||||
grpc_tcp_server_cb on_accept_cb, void *cb_arg) { |
||||
grpc_tcp_listener *sp; |
||||
(void)pollsets; |
||||
(void)pollset_count; |
||||
GPR_ASSERT(on_accept_cb); |
||||
GPR_ASSERT(!server->on_accept_cb); |
||||
server->on_accept_cb = on_accept_cb; |
||||
server->on_accept_cb_arg = cb_arg; |
||||
for (sp = server->head; sp; sp = sp->next) { |
||||
GPR_ASSERT(uv_listen((uv_stream_t *)sp->handle, SOMAXCONN, on_connect) == |
||||
0); |
||||
} |
||||
} |
||||
|
||||
void grpc_tcp_server_shutdown_listeners(grpc_exec_ctx *exec_ctx, |
||||
grpc_tcp_server *s) {} |
||||
|
||||
#endif /* GRPC_UV */ |
@ -0,0 +1,335 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#include "src/core/lib/iomgr/port.h" |
||||
|
||||
#ifdef GRPC_UV |
||||
|
||||
#include <limits.h> |
||||
#include <string.h> |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/log.h> |
||||
#include <grpc/support/slice_buffer.h> |
||||
#include <grpc/support/string_util.h> |
||||
|
||||
#include "src/core/lib/iomgr/error.h" |
||||
#include "src/core/lib/iomgr/network_status_tracker.h" |
||||
#include "src/core/lib/iomgr/tcp_uv.h" |
||||
#include "src/core/lib/support/string.h" |
||||
|
||||
int grpc_tcp_trace = 0; |
||||
|
||||
typedef struct { |
||||
grpc_endpoint base; |
||||
gpr_refcount refcount; |
||||
|
||||
uv_tcp_t *handle; |
||||
|
||||
grpc_closure *read_cb; |
||||
grpc_closure *write_cb; |
||||
|
||||
gpr_slice read_slice; |
||||
gpr_slice_buffer *read_slices; |
||||
gpr_slice_buffer *write_slices; |
||||
uv_buf_t *write_buffers; |
||||
|
||||
bool shutting_down; |
||||
char *peer_string; |
||||
grpc_pollset *pollset; |
||||
} grpc_tcp; |
||||
|
||||
static void uv_close_callback(uv_handle_t *handle) { gpr_free(handle); } |
||||
|
||||
static void tcp_free(grpc_tcp *tcp) { gpr_free(tcp); } |
||||
|
||||
/*#define GRPC_TCP_REFCOUNT_DEBUG*/ |
||||
#ifdef GRPC_TCP_REFCOUNT_DEBUG |
||||
#define TCP_UNREF(tcp, reason) tcp_unref((tcp), (reason), __FILE__, __LINE__) |
||||
#define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__) |
||||
static void tcp_unref(grpc_tcp *tcp, const char *reason, const char *file, |
||||
int line) { |
||||
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %d -> %d", tcp, |
||||
reason, tcp->refcount.count, tcp->refcount.count - 1); |
||||
if (gpr_unref(&tcp->refcount)) { |
||||
tcp_free(tcp); |
||||
} |
||||
} |
||||
|
||||
static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file, |
||||
int line) { |
||||
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP ref %p : %s %d -> %d", tcp, |
||||
reason, tcp->refcount.count, tcp->refcount.count + 1); |
||||
gpr_ref(&tcp->refcount); |
||||
} |
||||
#else |
||||
#define TCP_UNREF(tcp, reason) tcp_unref((tcp)) |
||||
#define TCP_REF(tcp, reason) tcp_ref((tcp)) |
||||
static void tcp_unref(grpc_tcp *tcp) { |
||||
if (gpr_unref(&tcp->refcount)) { |
||||
tcp_free(tcp); |
||||
} |
||||
} |
||||
|
||||
static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); } |
||||
#endif |
||||
|
||||
static void alloc_uv_buf(uv_handle_t *handle, size_t suggested_size, |
||||
uv_buf_t *buf) { |
||||
grpc_tcp *tcp = handle->data; |
||||
(void)suggested_size; |
||||
tcp->read_slice = gpr_slice_malloc(GRPC_TCP_DEFAULT_READ_SLICE_SIZE); |
||||
buf->base = (char *)GPR_SLICE_START_PTR(tcp->read_slice); |
||||
buf->len = GPR_SLICE_LENGTH(tcp->read_slice); |
||||
} |
||||
|
||||
static void read_callback(uv_stream_t *stream, ssize_t nread, |
||||
const uv_buf_t *buf) { |
||||
gpr_slice sub; |
||||
grpc_error *error; |
||||
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
||||
grpc_tcp *tcp = stream->data; |
||||
grpc_closure *cb = tcp->read_cb; |
||||
if (nread == 0) { |
||||
// Nothing happened. Wait for the next callback
|
||||
return; |
||||
} |
||||
TCP_UNREF(tcp, "read"); |
||||
tcp->read_cb = NULL; |
||||
// TODO(murgatroid99): figure out what the return value here means
|
||||
uv_read_stop(stream); |
||||
if (nread == UV_EOF) { |
||||
error = GRPC_ERROR_CREATE("EOF"); |
||||
} else if (nread > 0) { |
||||
// Successful read
|
||||
sub = gpr_slice_sub_no_ref(tcp->read_slice, 0, (size_t)nread); |
||||
gpr_slice_buffer_add(tcp->read_slices, sub); |
||||
error = GRPC_ERROR_NONE; |
||||
if (grpc_tcp_trace) { |
||||
size_t i; |
||||
const char *str = grpc_error_string(error); |
||||
gpr_log(GPR_DEBUG, "read: error=%s", str); |
||||
grpc_error_free_string(str); |
||||
for (i = 0; i < tcp->read_slices->count; i++) { |
||||
char *dump = gpr_dump_slice(tcp->read_slices->slices[i], |
||||
GPR_DUMP_HEX | GPR_DUMP_ASCII); |
||||
gpr_log(GPR_DEBUG, "READ %p (peer=%s): %s", tcp, tcp->peer_string, |
||||
dump); |
||||
gpr_free(dump); |
||||
} |
||||
} |
||||
} else { |
||||
// nread < 0: Error
|
||||
error = GRPC_ERROR_CREATE("TCP Read failed"); |
||||
} |
||||
grpc_exec_ctx_sched(&exec_ctx, cb, error, NULL); |
||||
grpc_exec_ctx_finish(&exec_ctx); |
||||
} |
||||
|
||||
static void uv_endpoint_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, |
||||
gpr_slice_buffer *read_slices, grpc_closure *cb) { |
||||
grpc_tcp *tcp = (grpc_tcp *)ep; |
||||
int status; |
||||
grpc_error *error = GRPC_ERROR_NONE; |
||||
GPR_ASSERT(tcp->read_cb == NULL); |
||||
tcp->read_cb = cb; |
||||
tcp->read_slices = read_slices; |
||||
gpr_slice_buffer_reset_and_unref(read_slices); |
||||
TCP_REF(tcp, "read"); |
||||
// TODO(murgatroid99): figure out what the return value here means
|
||||
status = |
||||
uv_read_start((uv_stream_t *)tcp->handle, alloc_uv_buf, read_callback); |
||||
if (status != 0) { |
||||
error = GRPC_ERROR_CREATE("TCP Read failed at start"); |
||||
error = |
||||
grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, uv_strerror(status)); |
||||
grpc_exec_ctx_sched(exec_ctx, cb, error, NULL); |
||||
} |
||||
if (grpc_tcp_trace) { |
||||
const char *str = grpc_error_string(error); |
||||
gpr_log(GPR_DEBUG, "Initiating read on %p: error=%s", tcp, str); |
||||
} |
||||
} |
||||
|
||||
static void write_callback(uv_write_t *req, int status) { |
||||
grpc_tcp *tcp = req->data; |
||||
grpc_error *error; |
||||
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
||||
grpc_closure *cb = tcp->write_cb; |
||||
tcp->write_cb = NULL; |
||||
TCP_UNREF(tcp, "write"); |
||||
if (status == 0) { |
||||
error = GRPC_ERROR_NONE; |
||||
} else { |
||||
error = GRPC_ERROR_CREATE("TCP Write failed"); |
||||
} |
||||
if (grpc_tcp_trace) { |
||||
const char *str = grpc_error_string(error); |
||||
gpr_log(GPR_DEBUG, "write complete on %p: error=%s", tcp, str); |
||||
} |
||||
gpr_free(tcp->write_buffers); |
||||
gpr_free(req); |
||||
grpc_exec_ctx_sched(&exec_ctx, cb, error, NULL); |
||||
grpc_exec_ctx_finish(&exec_ctx); |
||||
} |
||||
|
||||
static void uv_endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, |
||||
gpr_slice_buffer *write_slices, |
||||
grpc_closure *cb) { |
||||
grpc_tcp *tcp = (grpc_tcp *)ep; |
||||
uv_buf_t *buffers; |
||||
unsigned int buffer_count; |
||||
unsigned int i; |
||||
gpr_slice *slice; |
||||
uv_write_t *write_req; |
||||
|
||||
if (grpc_tcp_trace) { |
||||
size_t j; |
||||
|
||||
for (j = 0; j < write_slices->count; j++) { |
||||
char *data = gpr_dump_slice(write_slices->slices[j], |
||||
GPR_DUMP_HEX | GPR_DUMP_ASCII); |
||||
gpr_log(GPR_DEBUG, "WRITE %p (peer=%s): %s", tcp, tcp->peer_string, data); |
||||
gpr_free(data); |
||||
} |
||||
} |
||||
|
||||
if (tcp->shutting_down) { |
||||
grpc_exec_ctx_sched(exec_ctx, cb, |
||||
GRPC_ERROR_CREATE("TCP socket is shutting down"), NULL); |
||||
return; |
||||
} |
||||
|
||||
GPR_ASSERT(tcp->write_cb == NULL); |
||||
tcp->write_slices = write_slices; |
||||
GPR_ASSERT(tcp->write_slices->count <= UINT_MAX); |
||||
if (tcp->write_slices->count == 0) { |
||||
// No slices means we don't have to do anything,
|
||||
// and libuv doesn't like empty writes
|
||||
grpc_exec_ctx_sched(exec_ctx, cb, GRPC_ERROR_NONE, NULL); |
||||
return; |
||||
} |
||||
|
||||
tcp->write_cb = cb; |
||||
buffer_count = (unsigned int)tcp->write_slices->count; |
||||
buffers = gpr_malloc(sizeof(uv_buf_t) * buffer_count); |
||||
for (i = 0; i < buffer_count; i++) { |
||||
slice = &tcp->write_slices->slices[i]; |
||||
buffers[i].base = (char *)GPR_SLICE_START_PTR(*slice); |
||||
buffers[i].len = GPR_SLICE_LENGTH(*slice); |
||||
} |
||||
write_req = gpr_malloc(sizeof(uv_write_t)); |
||||
write_req->data = tcp; |
||||
TCP_REF(tcp, "write"); |
||||
// TODO(murgatroid99): figure out what the return value here means
|
||||
uv_write(write_req, (uv_stream_t *)tcp->handle, buffers, buffer_count, |
||||
write_callback); |
||||
} |
||||
|
||||
static void uv_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, |
||||
grpc_pollset *pollset) { |
||||
// No-op. We're ignoring pollsets currently
|
||||
(void)exec_ctx; |
||||
(void)ep; |
||||
(void)pollset; |
||||
grpc_tcp *tcp = (grpc_tcp *)ep; |
||||
tcp->pollset = pollset; |
||||
} |
||||
|
||||
static void uv_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, |
||||
grpc_pollset_set *pollset) { |
||||
// No-op. We're ignoring pollsets currently
|
||||
(void)exec_ctx; |
||||
(void)ep; |
||||
(void)pollset; |
||||
} |
||||
|
||||
static void shutdown_callback(uv_shutdown_t *req, int status) { gpr_free(req); } |
||||
|
||||
static void uv_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) { |
||||
grpc_tcp *tcp = (grpc_tcp *)ep; |
||||
if (!tcp->shutting_down) { |
||||
tcp->shutting_down = true; |
||||
uv_shutdown_t *req = gpr_malloc(sizeof(uv_shutdown_t)); |
||||
uv_shutdown(req, (uv_stream_t *)tcp->handle, shutdown_callback); |
||||
} |
||||
} |
||||
|
||||
static void uv_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) { |
||||
grpc_network_status_unregister_endpoint(ep); |
||||
grpc_tcp *tcp = (grpc_tcp *)ep; |
||||
uv_close((uv_handle_t *)tcp->handle, uv_close_callback); |
||||
TCP_UNREF(tcp, "destroy"); |
||||
} |
||||
|
||||
static char *uv_get_peer(grpc_endpoint *ep) { |
||||
grpc_tcp *tcp = (grpc_tcp *)ep; |
||||
return gpr_strdup(tcp->peer_string); |
||||
} |
||||
|
||||
static grpc_workqueue *uv_get_workqueue(grpc_endpoint *ep) { return NULL; } |
||||
|
||||
static grpc_endpoint_vtable vtable = {uv_endpoint_read, |
||||
uv_endpoint_write, |
||||
uv_get_workqueue, |
||||
uv_add_to_pollset, |
||||
uv_add_to_pollset_set, |
||||
uv_endpoint_shutdown, |
||||
uv_destroy, |
||||
uv_get_peer}; |
||||
|
||||
grpc_endpoint *grpc_tcp_create(uv_tcp_t *handle, char *peer_string) { |
||||
grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp)); |
||||
|
||||
if (grpc_tcp_trace) { |
||||
gpr_log(GPR_DEBUG, "Creating TCP endpoint %p", tcp); |
||||
} |
||||
|
||||
memset(tcp, 0, sizeof(grpc_tcp)); |
||||
tcp->base.vtable = &vtable; |
||||
tcp->handle = handle; |
||||
handle->data = tcp; |
||||
gpr_ref_init(&tcp->refcount, 1); |
||||
tcp->peer_string = gpr_strdup(peer_string); |
||||
tcp->shutting_down = false; |
||||
/* Tell network status tracking code about the new endpoint */ |
||||
grpc_network_status_register_endpoint(&tcp->base); |
||||
|
||||
#ifndef GRPC_UV_TCP_HOLD_LOOP |
||||
uv_unref((uv_handle_t *)handle); |
||||
#endif |
||||
|
||||
return &tcp->base; |
||||
} |
||||
|
||||
#endif /* GRPC_UV */ |
@ -0,0 +1,57 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPC_CORE_LIB_IOMGR_TCP_UV_H |
||||
#define GRPC_CORE_LIB_IOMGR_TCP_UV_H |
||||
/*
|
||||
Low level TCP "bottom half" implementation, for use by transports built on |
||||
top of a TCP connection. |
||||
|
||||
Note that this file does not (yet) include APIs for creating the socket in |
||||
the first place. |
||||
|
||||
All calls passing slice transfer ownership of a slice refcount unless |
||||
otherwise specified. |
||||
*/ |
||||
|
||||
#include "src/core/lib/iomgr/endpoint.h" |
||||
|
||||
#include <uv.h> |
||||
|
||||
extern int grpc_tcp_trace; |
||||
|
||||
#define GRPC_TCP_DEFAULT_READ_SLICE_SIZE 8192 |
||||
|
||||
grpc_endpoint *grpc_tcp_create(uv_tcp_t *handle, char *peer_string); |
||||
|
||||
#endif /* GRPC_CORE_LIB_IOMGR_TCP_UV_H */ |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue