mirror of https://github.com/grpc/grpc.git
parent
6257159a3a
commit
9030c81f20
73 changed files with 2719 additions and 109 deletions
@ -0,0 +1,51 @@ |
||||
/*
|
||||
* |
||||
* 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,84 @@ |
||||
/*
|
||||
* |
||||
* 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 <grpc/support/sync.h> |
||||
|
||||
#include "src/core/lib/iomgr/pollset.h" |
||||
#include "src/core/lib/iomgr/pollset_uv.h" |
||||
|
||||
gpr_mu grpc_polling_mu; |
||||
|
||||
size_t grpc_pollset_size() { |
||||
return 1; |
||||
} |
||||
|
||||
void grpc_pollset_global_init(void) { |
||||
gpr_mu_init(&grpc_polling_mu); |
||||
} |
||||
|
||||
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; |
||||
} |
||||
|
||||
void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, |
||||
grpc_closure *closure) { |
||||
grpc_exec_ctx_sched(exec_ctx, closure, GRPC_ERROR_NONE, NULL); |
||||
} |
||||
|
||||
void grpc_pollset_destroy(grpc_pollset *pollset) {} |
||||
|
||||
void grpc_pollset_reset(grpc_pollset *pollset) {} |
||||
|
||||
grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, |
||||
grpc_pollset_worker **worker_hdl, |
||||
gpr_timespec now, gpr_timespec deadline) { |
||||
if (!grpc_closure_list_empty(exec_ctx->closure_list)) { |
||||
gpr_mu_unlock(&grpc_polling_mu); |
||||
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,35 @@ |
||||
/*
|
||||
* |
||||
* 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. |
||||
* |
||||
*/ |
||||
|
||||
void grpc_pollset_global_init(void); |
||||
void grpc_pollset_global_shutdown(void); |
@ -0,0 +1,234 @@ |
||||
/*
|
||||
* |
||||
* 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_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, (struct sockaddr *)&(*addresses)->addrs[i].addr, 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; |
||||
|
||||
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,50 @@ |
||||
/*
|
||||
* |
||||
* 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, socklen_t size) { |
||||
GPR_ASSERT(sizeof(socklen_t) <= sizeof(size_t)); |
||||
uv_inet_ntop(af, src, dst, (size_t)size); |
||||
return dst; |
||||
} |
||||
|
||||
#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 <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_log(GPR_DEBUG, "Freeing uv_tcp_t handle %p", 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 */ |
||||
gpr_log(GPR_DEBUG, "Closing uv_tcp_t handle %p", connect->tcp_handle); |
||||
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)); |
||||
gpr_log(GPR_DEBUG, "Closing uv_tcp_t handle %p", connect->tcp_handle); |
||||
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); |
||||
} |
||||
|
||||
void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, |
||||
grpc_closure *closure, grpc_endpoint **ep, |
||||
grpc_pollset_set *interested_parties, |
||||
const struct sockaddr *addr, |
||||
size_t addr_len, 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)); |
||||
gpr_log(GPR_DEBUG, "Allocated uv_tcp_t handle %p", connect->tcp_handle); |
||||
connect->addr_name = grpc_sockaddr_to_uri(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, 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)); |
||||
} |
||||
|
||||
#endif /* GRPC_UV */ |
@ -0,0 +1,358 @@ |
||||
/*
|
||||
* |
||||
* 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_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_log(GPR_DEBUG, "Freeing uv_tcp_t handle %p", sp->handle); |
||||
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){ |
||||
gpr_log(GPR_DEBUG, "Closing uv_tcp_t handle %p", sp->handle); |
||||
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 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; |
||||
struct sockaddr_storage peer_name; |
||||
int peer_name_len = sizeof(peer_name); |
||||
char *peer_name_string; |
||||
int err; |
||||
|
||||
gpr_log(GPR_DEBUG, "Server %p received a connection", sp->server); |
||||
|
||||
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)); |
||||
gpr_log(GPR_DEBUG, "Allocated uv_tcp_t handle %p", client); |
||||
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); |
||||
peer_name_string = NULL; |
||||
err = uv_tcp_getpeername(client, (struct sockaddr *)&peer_name, |
||||
&peer_name_len); |
||||
if (err == 0) { |
||||
peer_name_string = grpc_sockaddr_to_uri((struct sockaddr *)&peer_name); |
||||
} else { |
||||
gpr_log(GPR_INFO, "uv_tcp_getpeername error: %s", |
||||
uv_strerror(status)); |
||||
} |
||||
ep = grpc_tcp_create(client, peer_name_string); |
||||
gpr_log(GPR_DEBUG, "Calling on_accept_cb for server %p", sp->server); |
||||
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, |
||||
struct sockaddr *addr, |
||||
size_t addr_len, unsigned port_index, |
||||
grpc_tcp_listener **listener) { |
||||
grpc_tcp_listener *sp = NULL; |
||||
int port = -1; |
||||
int status; |
||||
grpc_error *error; |
||||
struct sockaddr_storage sockname_temp; |
||||
int sockname_len; |
||||
|
||||
// The last argument to uv_tcp_bind is flags
|
||||
status = uv_tcp_bind(handle, 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; |
||||
} |
||||
|
||||
sockname_len = (int)sizeof(sockname_temp); |
||||
status = uv_tcp_getsockname(handle, (struct sockaddr *)&sockname_temp, |
||||
&sockname_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((struct sockaddr *)&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 void *addr, |
||||
size_t addr_len, int *port) { |
||||
// This function is mostly copied from tcp_server_windows.c
|
||||
grpc_tcp_listener *sp = NULL; |
||||
uv_tcp_t *handle; |
||||
struct sockaddr_in6 addr6_v4mapped; |
||||
struct sockaddr_in6 wildcard; |
||||
struct sockaddr *allocated_addr = NULL; |
||||
struct sockaddr_storage sockname_temp; |
||||
int sockname_len; |
||||
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_len = sizeof(sockname_temp); |
||||
if (0 == uv_tcp_getsockname(sp->handle, (struct sockaddr *)&sockname_temp, |
||||
&sockname_len)) { |
||||
*port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp); |
||||
if (*port > 0) { |
||||
allocated_addr = gpr_malloc(addr_len); |
||||
memcpy(allocated_addr, addr, addr_len); |
||||
grpc_sockaddr_set_port(allocated_addr, *port); |
||||
addr = allocated_addr; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) { |
||||
addr = (const struct sockaddr *)&addr6_v4mapped; |
||||
addr_len = sizeof(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 = (struct sockaddr *)&wildcard; |
||||
addr_len = sizeof(wildcard); |
||||
} |
||||
|
||||
handle = gpr_malloc(sizeof(uv_tcp_t)); |
||||
gpr_log(GPR_DEBUG, "Allocating uv_tcp_t handle %p", handle); |
||||
status = uv_tcp_init(uv_default_loop(), handle); |
||||
if (status == 0) { |
||||
error = add_socket_to_server(s, handle, (struct sockaddr *)addr, addr_len, |
||||
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,336 @@ |
||||
/*
|
||||
* |
||||
* 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; |
||||
|
||||
int shutting_down; |
||||
char *peer_string; |
||||
grpc_pollset *pollset; |
||||
} grpc_tcp; |
||||
|
||||
static void uv_close_callback(uv_handle_t *handle) { |
||||
gpr_log(GPR_DEBUG, "Freeing uv_tcp_t handle %p", 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, 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 i; |
||||
|
||||
for (i = 0; i < write_slices->count; i++) { |
||||
char *data = |
||||
gpr_dump_slice(write_slices->slices[i], 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; |
||||
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; |
||||
gpr_log(GPR_DEBUG, "Closing uv_tcp_t handle %p", tcp->handle); |
||||
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); |
||||
/* 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 */ |
@ -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. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPC_CORE_LIB_IOMGR_TIMER_GENERIC_H |
||||
#define GRPC_CORE_LIB_IOMGR_TIMER_GENERIC_H |
||||
|
||||
#include <grpc/support/time.h> |
||||
#include "src/core/lib/iomgr/exec_ctx.h" |
||||
|
||||
struct grpc_timer { |
||||
gpr_timespec deadline; |
||||
uint32_t heap_index; /* INVALID_HEAP_INDEX if not in heap */ |
||||
int triggered; |
||||
struct grpc_timer *next; |
||||
struct grpc_timer *prev; |
||||
grpc_closure closure; |
||||
}; |
||||
|
||||
#endif /* GRPC_CORE_LIB_IOMGR_TIMER_GENERIC_H */ |
@ -0,0 +1,103 @@ |
||||
/*
|
||||
* |
||||
* 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" |
||||
|
||||
#if GRPC_UV |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/log.h> |
||||
|
||||
#include "src/core/lib/iomgr/timer.h" |
||||
|
||||
#include <uv.h> |
||||
|
||||
static void timer_close_callback(uv_handle_t *handle) { |
||||
gpr_free(handle); |
||||
} |
||||
|
||||
static void stop_uv_timer(uv_timer_t *handle) { |
||||
uv_timer_stop(handle); |
||||
uv_unref((uv_handle_t*) handle); |
||||
gpr_log(GPR_DEBUG, "Closing uv_timer_t handle %p", handle); |
||||
uv_close((uv_handle_t*) handle, timer_close_callback); |
||||
} |
||||
|
||||
void run_expired_timer(uv_timer_t *handle) { |
||||
grpc_timer *timer = (grpc_timer*)handle->data; |
||||
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
||||
gpr_log(GPR_DEBUG, "Timer callback: %p", timer); |
||||
GPR_ASSERT(!timer->triggered); |
||||
timer->triggered = 1; |
||||
grpc_exec_ctx_sched(&exec_ctx, &timer->closure, GRPC_ERROR_NONE, NULL); |
||||
stop_uv_timer(handle); |
||||
grpc_exec_ctx_finish(&exec_ctx); |
||||
} |
||||
|
||||
void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer, |
||||
gpr_timespec deadline, grpc_iomgr_cb_func timer_cb, |
||||
void *timer_cb_arg, gpr_timespec now) { |
||||
uint64_t timeout; |
||||
grpc_closure_init(&timer->closure, timer_cb, timer_cb_arg); |
||||
if (gpr_time_cmp(deadline, now) <= 0) { |
||||
timer->triggered = 1; |
||||
grpc_exec_ctx_sched(exec_ctx, &timer->closure, GRPC_ERROR_NONE, NULL); |
||||
return; |
||||
} |
||||
timer->triggered = 0; |
||||
timeout = (uint64_t)gpr_time_to_millis(gpr_time_sub(deadline, now)); |
||||
gpr_log(GPR_DEBUG, "Setting timer %p: %lu", timer, timeout); |
||||
timer->uv_timer = gpr_malloc(sizeof(uv_timer_t)); |
||||
uv_timer_init(uv_default_loop(), timer->uv_timer); |
||||
timer->uv_timer->data = timer; |
||||
uv_timer_start(timer->uv_timer, run_expired_timer, timeout, 0); |
||||
} |
||||
|
||||
void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer) { |
||||
if (!timer->triggered) { |
||||
gpr_log(GPR_DEBUG, "Running cancelled timer callback"); |
||||
timer->triggered = 1; |
||||
grpc_exec_ctx_sched(exec_ctx, &timer->closure, GRPC_ERROR_CANCELLED, NULL); |
||||
stop_uv_timer(timer->uv_timer); |
||||
} |
||||
} |
||||
|
||||
bool grpc_timer_check(grpc_exec_ctx *exec_ctx, gpr_timespec now, |
||||
gpr_timespec *next) { |
||||
return false; |
||||
} |
||||
|
||||
void grpc_timer_list_init(gpr_timespec now) {} |
||||
void grpc_timer_list_shutdown(grpc_exec_ctx *exec_ctx) {} |
||||
|
||||
#endif /* GRPC_UV */ |
@ -0,0 +1,47 @@ |
||||
/*
|
||||
* |
||||
* 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_TIMER_GENERIC_H |
||||
#define GRPC_CORE_LIB_IOMGR_TIMER_GENERIC_H |
||||
|
||||
#include <uv.h> |
||||
|
||||
#include "src/core/lib/iomgr/exec_ctx.h" |
||||
|
||||
struct grpc_timer { |
||||
grpc_closure closure; |
||||
uv_timer_t *uv_timer; |
||||
int triggered; |
||||
}; |
||||
|
||||
#endif /* GRPC_CORE_LIB_IOMGR_TIMER_GENERIC_H */ |
@ -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/workqueue.h" |
||||
|
||||
// Minimal implementation of grpc_workqueue for libuv
|
||||
// Works by directly enqueuing workqueue items onto the current execution
|
||||
// context, which is at least correct, if not performant or in the spirit of
|
||||
// workqueues.
|
||||
|
||||
void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) {} |
||||
|
||||
#ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG |
||||
void grpc_workqueue_ref(grpc_workqueue *workqueue, const char *file, int line, |
||||
const char *reason) {} |
||||
void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, |
||||
const char *file, int line, const char *reason) {} |
||||
#else |
||||
void grpc_workqueue_ref(grpc_workqueue *workqueue) {} |
||||
void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) {} |
||||
#endif |
||||
|
||||
void grpc_workqueue_enqueue(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, |
||||
grpc_closure *closure, grpc_error *error) { |
||||
grpc_exec_ctx_sched(exec_ctx, closure, error, NULL); |
||||
} |
||||
|
||||
#endif /* GPR_UV */ |
@ -0,0 +1,37 @@ |
||||
/*
|
||||
* |
||||
* 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_WORKQUEUE_UV_H |
||||
#define GRPC_CORE_LIB_IOMGR_WORKQUEUE_UV_H |
||||
|
||||
#endif /* GRPC_CORE_LIB_IOMGR_WORKQUEUE_UV_H */ |
@ -0,0 +1,114 @@ |
||||
/*
|
||||
* |
||||
* 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 <uv.h> |
||||
#include <node.h> |
||||
#include <v8.h> |
||||
#include <grpc/grpc.h> |
||||
|
||||
#include "call.h" |
||||
#include "completion_queue.h" |
||||
#include "completion_queue_async_worker.h" |
||||
|
||||
namespace grpc { |
||||
namespace node { |
||||
|
||||
using v8::Local; |
||||
using v8::Object; |
||||
using v8::Value; |
||||
|
||||
grpc_completion_queue *queue; |
||||
uv_prepare_t prepare; |
||||
int pending_batches; |
||||
|
||||
void drain_completion_queue(uv_prepare_t *handle) { |
||||
Nan::HandleScope scope; |
||||
grpc_event event; |
||||
(void)handle; |
||||
do { |
||||
event = grpc_completion_queue_next( |
||||
queue, gpr_inf_past(GPR_CLOCK_MONOTONIC), NULL); |
||||
|
||||
if (event.type == GRPC_OP_COMPLETE) { |
||||
Nan::Callback *callback = grpc::node::GetTagCallback(event.tag); |
||||
if (event.success) { |
||||
Local<Value> argv[] = {Nan::Null(), |
||||
grpc::node::GetTagNodeValue(event.tag)}; |
||||
callback->Call(2, argv); |
||||
} else { |
||||
Local<Value> argv[] = {Nan::Error( |
||||
"The async function encountered an error")}; |
||||
callback->Call(1, argv); |
||||
} |
||||
grpc::node::CompleteTag(event.tag); |
||||
grpc::node::DestroyTag(event.tag); |
||||
pending_batches--; |
||||
if (pending_batches == 0) { |
||||
uv_prepare_stop(&prepare); |
||||
} |
||||
} |
||||
} while (event.type != GRPC_QUEUE_TIMEOUT); |
||||
} |
||||
|
||||
grpc_completion_queue *GetCompletionQueue() { |
||||
#ifdef GRPC_UV |
||||
return queue; |
||||
#else |
||||
return CompletionQueueAsyncWorker::GetQueue(); |
||||
#endif |
||||
} |
||||
|
||||
void CompletionQueueNext() { |
||||
#ifdef GRPC_UV |
||||
if (pending_batches == 0) { |
||||
GPR_ASSERT(!uv_is_active((uv_handle_t *)&prepare)); |
||||
uv_prepare_start(&prepare, drain_completion_queue); |
||||
} |
||||
pending_batches++; |
||||
#else |
||||
CompletionQueueAsyncWorker::Next(); |
||||
#endif |
||||
} |
||||
|
||||
void CompletionQueueInit(Local<Object> exports) { |
||||
#ifdef GRPC_UV |
||||
queue = grpc_completion_queue_create(NULL); |
||||
uv_prepare_init(uv_default_loop(), &prepare); |
||||
pending_batches = 0; |
||||
#else |
||||
CompletionQueueAsyncWorker::Init(exports); |
||||
#endif |
||||
} |
||||
|
||||
} // namespace node
|
||||
} // namespace grpc
|
@ -0,0 +1,46 @@ |
||||
/*
|
||||
* |
||||
* 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 <v8.h> |
||||
|
||||
namespace grpc { |
||||
namespace node { |
||||
|
||||
grpc_completion_queue *GetCompletionQueue(); |
||||
|
||||
void CompletionQueueNext(); |
||||
|
||||
void CompletionQueueInit(v8::Local<v8::Object> exports); |
||||
|
||||
} // namespace node
|
||||
} // namespace grpc
|
Loading…
Reference in new issue