diff options
author | 2015-11-21 09:00:11 -0800 | |
---|---|---|
committer | 2015-11-21 09:00:11 -0800 | |
commit | d653b394714b1fa342f0872c8262c8cde5511f4b (patch) | |
tree | 91573a209f253d58bb4a8b14d759db7e80167b3a /src/core | |
parent | 860f484f43841d14df61cfeda6ca5e637ed99d19 (diff) | |
parent | ceb7318d794b4174e18364f6780a5d20e6249e23 (diff) |
Merge github.com:grpc/grpc into better-profile
Diffstat (limited to 'src/core')
32 files changed, 1005 insertions, 721 deletions
diff --git a/src/core/client_config/subchannel.c b/src/core/client_config/subchannel.c index 49c2cf9a19..b15a9033af 100644 --- a/src/core/client_config/subchannel.c +++ b/src/core/client_config/subchannel.c @@ -697,10 +697,25 @@ static double generate_uniform_random_number(grpc_subchannel *c) { /* Update backoff_delta and next_attempt in subchannel */ static void update_reconnect_parameters(grpc_subchannel *c) { + size_t i; gpr_int32 backoff_delta_millis, jitter; gpr_int32 max_backoff_millis = GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS * 1000; double jitter_range; + + if (c->args) { + for (i = 0; i < c->args->num_args; i++) { + if (0 == strcmp(c->args->args[i].key, + "grpc.testing.fixed_reconnect_backoff")) { + GPR_ASSERT(c->args->args[i].type == GRPC_ARG_INTEGER); + c->next_attempt = gpr_time_add( + gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_millis(c->args->args[i].value.integer, GPR_TIMESPAN)); + return; + } + } + } + backoff_delta_millis = (gpr_int32)(gpr_time_to_millis(c->backoff_delta) * GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER); diff --git a/src/core/client_config/subchannel.h b/src/core/client_config/subchannel.h index 1fefa1888a..381b7689b8 100644 --- a/src/core/client_config/subchannel.h +++ b/src/core/client_config/subchannel.h @@ -77,10 +77,10 @@ void grpc_subchannel_call_unref(grpc_exec_ctx *exec_ctx, /** construct a subchannel call (possibly asynchronously). * - * If the returned status is 1, the call will return immediately and \a target - * will point to a connected \a subchannel_call instance. Note that \a notify + * If the returned status is 1, the call will return immediately and \a target + * will point to a connected \a subchannel_call instance. Note that \a notify * will \em not be invoked in this case. - * Otherwise, if the returned status is 0, the subchannel call will be created + * Otherwise, if the returned status is 0, the subchannel call will be created * asynchronously, invoking the \a notify callback upon completion. */ int grpc_subchannel_create_call(grpc_exec_ctx *exec_ctx, grpc_subchannel *subchannel, diff --git a/src/core/iomgr/pollset_windows.c b/src/core/iomgr/pollset_windows.c index c3f310ee27..deb661548d 100644 --- a/src/core/iomgr/pollset_windows.c +++ b/src/core/iomgr/pollset_windows.c @@ -126,7 +126,8 @@ void grpc_pollset_destroy(grpc_pollset *pollset) {} void grpc_pollset_reset(grpc_pollset *pollset) { GPR_ASSERT(pollset->shutting_down); - GPR_ASSERT(!has_workers(&pollset->root_worker, GRPC_POLLSET_WORKER_LINK_POLLSET)); + GPR_ASSERT( + !has_workers(&pollset->root_worker, GRPC_POLLSET_WORKER_LINK_POLLSET)); pollset->shutting_down = 0; pollset->is_iocp_worker = 0; pollset->kicked_without_pollers = 0; diff --git a/src/core/iomgr/tcp_server.h b/src/core/iomgr/tcp_server.h index 882635f638..3df36174e7 100644 --- a/src/core/iomgr/tcp_server.h +++ b/src/core/iomgr/tcp_server.h @@ -39,6 +39,9 @@ /* Forward decl of grpc_tcp_server */ typedef struct grpc_tcp_server grpc_tcp_server; +/* Forward decl of grpc_tcp_listener */ +typedef struct grpc_tcp_listener grpc_tcp_listener; + /* Called for newly connected TCP connections. */ typedef void (*grpc_tcp_server_cb)(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *ep); @@ -51,19 +54,18 @@ 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); -/* Add a port to the server, returning port number on success, or negative - on failure. +/* Add a port to the server, returning the newly created listener on success, + or a null pointer on failure. The :: and 0.0.0.0 wildcard addresses are treated identically, accepting both IPv4 and IPv6 connections, but :: is the preferred style. This usually creates one socket, but possibly two on systems which support IPv6, - but not dualstack sockets. - - For raw access to the underlying sockets, see grpc_tcp_server_get_fd(). */ + but not dualstack sockets. */ /* TODO(ctiller): deprecate this, and make grpc_tcp_server_add_ports to handle all of the multiple socket port matching logic in one place */ -int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr, - size_t addr_len); +grpc_tcp_listener *grpc_tcp_server_add_port(grpc_tcp_server *s, + const void *addr, + size_t addr_len); /* Returns the file descriptor of the Nth listening socket on this server, or -1 if the index is out of bounds. @@ -75,4 +77,8 @@ int grpc_tcp_server_get_fd(grpc_tcp_server *s, unsigned index); void grpc_tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *server, grpc_closure *closure); +int grpc_tcp_listener_get_port(grpc_tcp_listener *listener); +void grpc_tcp_listener_ref(grpc_tcp_listener *listener); +void grpc_tcp_listener_unref(grpc_tcp_listener *listener); + #endif /* GRPC_INTERNAL_CORE_IOMGR_TCP_SERVER_H */ diff --git a/src/core/iomgr/tcp_server_posix.c b/src/core/iomgr/tcp_server_posix.c index 99c76dcbe9..1439dfcd6e 100644 --- a/src/core/iomgr/tcp_server_posix.c +++ b/src/core/iomgr/tcp_server_posix.c @@ -67,14 +67,13 @@ #include <grpc/support/sync.h> #include <grpc/support/time.h> -#define INIT_PORT_CAP 2 #define MIN_SAFE_ACCEPT_QUEUE_SIZE 100 static gpr_once s_init_max_accept_queue_size; static int s_max_accept_queue_size; /* one listening port */ -typedef struct { +struct grpc_tcp_listener { int fd; grpc_fd *emfd; grpc_tcp_server *server; @@ -84,9 +83,18 @@ typedef struct { struct sockaddr_un un; } addr; size_t addr_len; + int port; grpc_closure read_closure; grpc_closure destroyed_closure; -} server_port; + gpr_refcount refs; + struct grpc_tcp_listener *next; + /* When we add a listener, more than one can be created, mainly because of + IPv6. A sibling will still be in the normal list, but will be flagged + as such. Any action, such as ref or unref, will affect all of the + siblings in the list. */ + struct grpc_tcp_listener *sibling; + int is_sibling; +}; static void unlink_if_unix_domain_socket(const struct sockaddr_un *un) { struct stat st; @@ -112,10 +120,9 @@ struct grpc_tcp_server { /* is this server shutting down? (boolean) */ int shutdown; - /* all listening ports */ - server_port *ports; - size_t nports; - size_t port_capacity; + /* linked list of server ports */ + grpc_tcp_listener *head; + unsigned nports; /* shutdown callback */ grpc_closure *shutdown_complete; @@ -134,9 +141,8 @@ grpc_tcp_server *grpc_tcp_server_create(void) { s->shutdown = 0; s->on_accept_cb = NULL; s->on_accept_cb_arg = NULL; - s->ports = gpr_malloc(sizeof(server_port) * INIT_PORT_CAP); + s->head = NULL; s->nports = 0; - s->port_capacity = INIT_PORT_CAP; return s; } @@ -145,7 +151,12 @@ static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { gpr_mu_destroy(&s->mu); - gpr_free(s->ports); + while (s->head) { + grpc_tcp_listener *sp = s->head; + s->head = sp->next; + grpc_tcp_listener_unref(sp); + } + gpr_free(s); } @@ -166,8 +177,6 @@ static void destroyed_port(grpc_exec_ctx *exec_ctx, void *server, int success) { events will be received on them - at this point it's safe to destroy things */ static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { - size_t i; - /* delete ALL the things */ gpr_mu_lock(&s->mu); @@ -176,9 +185,9 @@ static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { return; } - if (s->nports) { - for (i = 0; i < s->nports; i++) { - server_port *sp = &s->ports[i]; + if (s->head) { + grpc_tcp_listener *sp; + for (sp = s->head; sp; sp = sp->next) { if (sp->addr.sockaddr.sa_family == AF_UNIX) { unlink_if_unix_domain_socket(&sp->addr.un); } @@ -196,7 +205,6 @@ static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { void grpc_tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s, grpc_closure *closure) { - size_t i; gpr_mu_lock(&s->mu); GPR_ASSERT(!s->shutdown); @@ -206,8 +214,9 @@ void grpc_tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s, /* shutdown all fd's */ if (s->active_ports) { - for (i = 0; i < s->nports; i++) { - grpc_fd_shutdown(exec_ctx, s->ports[i].emfd); + grpc_tcp_listener *sp; + for (sp = s->head; sp; sp = sp->next) { + grpc_fd_shutdown(exec_ctx, sp->emfd); } gpr_mu_unlock(&s->mu); } else { @@ -298,7 +307,7 @@ error: /* event manager callback when reads are ready */ static void on_read(grpc_exec_ctx *exec_ctx, void *arg, int success) { - server_port *sp = arg; + grpc_tcp_listener *sp = arg; grpc_fd *fdobj; size_t i; @@ -364,9 +373,10 @@ error: } } -static int add_socket_to_server(grpc_tcp_server *s, int fd, - const struct sockaddr *addr, size_t addr_len) { - server_port *sp; +static grpc_tcp_listener *add_socket_to_server(grpc_tcp_server *s, int fd, + const struct sockaddr *addr, + size_t addr_len) { + grpc_tcp_listener *sp = NULL; int port; char *addr_str; char *name; @@ -376,32 +386,35 @@ static int add_socket_to_server(grpc_tcp_server *s, int fd, grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1); gpr_asprintf(&name, "tcp-server-listener:%s", addr_str); gpr_mu_lock(&s->mu); + s->nports++; GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server"); - /* append it to the list under a lock */ - if (s->nports == s->port_capacity) { - s->port_capacity *= 2; - s->ports = gpr_realloc(s->ports, sizeof(server_port) * s->port_capacity); - } - sp = &s->ports[s->nports++]; + sp = gpr_malloc(sizeof(grpc_tcp_listener)); + sp->next = s->head; + s->head = sp; sp->server = s; sp->fd = fd; sp->emfd = grpc_fd_create(fd, name); memcpy(sp->addr.untyped, addr, addr_len); sp->addr_len = addr_len; + sp->port = port; + sp->is_sibling = 0; + sp->sibling = NULL; + gpr_ref_init(&sp->refs, 1); GPR_ASSERT(sp->emfd); gpr_mu_unlock(&s->mu); gpr_free(addr_str); gpr_free(name); } - return port; + return sp; } -int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr, - size_t addr_len) { - int allocated_port1 = -1; - int allocated_port2 = -1; - unsigned i; +grpc_tcp_listener *grpc_tcp_server_add_port(grpc_tcp_server *s, + const void *addr, + size_t addr_len) { + int allocated_port = -1; + grpc_tcp_listener *sp; + grpc_tcp_listener *sp2 = NULL; int fd; grpc_dualstack_mode dsmode; struct sockaddr_in6 addr6_v4mapped; @@ -420,9 +433,9 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr, /* 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 (i = 0; i < s->nports; i++) { + for (sp = s->head; sp; sp = sp->next) { sockname_len = sizeof(sockname_temp); - if (0 == getsockname(s->ports[i].fd, (struct sockaddr *)&sockname_temp, + if (0 == getsockname(sp->fd, (struct sockaddr *)&sockname_temp, &sockname_len)) { port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp); if (port > 0) { @@ -436,6 +449,8 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr, } } + sp = NULL; + if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) { addr = (const struct sockaddr *)&addr6_v4mapped; addr_len = sizeof(addr6_v4mapped); @@ -449,14 +464,16 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr, addr = (struct sockaddr *)&wild6; addr_len = sizeof(wild6); fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode); - allocated_port1 = add_socket_to_server(s, fd, addr, addr_len); + sp = add_socket_to_server(s, fd, addr, addr_len); + allocated_port = sp->port; if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) { goto done; } /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */ - if (port == 0 && allocated_port1 > 0) { - grpc_sockaddr_set_port((struct sockaddr *)&wild4, allocated_port1); + if (port == 0 && allocated_port > 0) { + grpc_sockaddr_set_port((struct sockaddr *)&wild4, allocated_port); + sp2 = sp; } addr = (struct sockaddr *)&wild4; addr_len = sizeof(wild4); @@ -471,22 +488,31 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr, addr = (struct sockaddr *)&addr4_copy; addr_len = sizeof(addr4_copy); } - allocated_port2 = add_socket_to_server(s, fd, addr, addr_len); + sp = add_socket_to_server(s, fd, addr, addr_len); + sp->sibling = sp2; + if (sp2) sp2->is_sibling = 1; done: gpr_free(allocated_addr); - return allocated_port1 >= 0 ? allocated_port1 : allocated_port2; + return sp; } int grpc_tcp_server_get_fd(grpc_tcp_server *s, unsigned port_index) { - return (port_index < s->nports) ? s->ports[port_index].fd : -1; + grpc_tcp_listener *sp; + for (sp = s->head; sp && port_index != 0; sp = sp->next, port_index--); + if (port_index == 0 && sp) { + return sp->fd; + } else { + return -1; + } } void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s, grpc_pollset **pollsets, size_t pollset_count, grpc_tcp_server_cb on_accept_cb, void *on_accept_cb_arg) { - size_t i, j; + size_t i; + grpc_tcp_listener *sp; GPR_ASSERT(on_accept_cb); gpr_mu_lock(&s->mu); GPR_ASSERT(!s->on_accept_cb); @@ -495,17 +521,41 @@ void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s, s->on_accept_cb_arg = on_accept_cb_arg; s->pollsets = pollsets; s->pollset_count = pollset_count; - for (i = 0; i < s->nports; i++) { - for (j = 0; j < pollset_count; j++) { - grpc_pollset_add_fd(exec_ctx, pollsets[j], s->ports[i].emfd); + for (sp = s->head; sp; sp = sp->next) { + for (i = 0; i < pollset_count; i++) { + grpc_pollset_add_fd(exec_ctx, pollsets[i], sp->emfd); } - s->ports[i].read_closure.cb = on_read; - s->ports[i].read_closure.cb_arg = &s->ports[i]; - grpc_fd_notify_on_read(exec_ctx, s->ports[i].emfd, - &s->ports[i].read_closure); + sp->read_closure.cb = on_read; + sp->read_closure.cb_arg = sp; + grpc_fd_notify_on_read(exec_ctx, sp->emfd, + &sp->read_closure); s->active_ports++; } gpr_mu_unlock(&s->mu); } +int grpc_tcp_listener_get_port(grpc_tcp_listener *listener) { + grpc_tcp_listener *sp = listener; + return sp->port; +} + +void grpc_tcp_listener_ref(grpc_tcp_listener *listener) { + grpc_tcp_listener *sp = listener; + gpr_ref(&sp->refs); +} + +void grpc_tcp_listener_unref(grpc_tcp_listener *listener) { + grpc_tcp_listener *sp = listener; + if (sp->is_sibling) return; + if (gpr_unref(&sp->refs)) { + grpc_tcp_listener *sibling = sp->sibling; + while (sibling) { + sp = sibling; + sibling = sp->sibling; + gpr_free(sp); + } + gpr_free(listener); + } +} + #endif diff --git a/src/core/iomgr/tcp_server_windows.c b/src/core/iomgr/tcp_server_windows.c index 3fea8b5b35..e4a1d7f498 100644 --- a/src/core/iomgr/tcp_server_windows.c +++ b/src/core/iomgr/tcp_server_windows.c @@ -35,7 +35,8 @@ #ifdef GPR_WINSOCK_SOCKET -#define _GNU_SOURCE +#include <io.h> + #include "src/core/iomgr/sockaddr_utils.h" #include <grpc/support/alloc.h> @@ -51,25 +52,29 @@ #include "src/core/iomgr/tcp_server.h" #include "src/core/iomgr/tcp_windows.h" -#define INIT_PORT_CAP 2 #define MIN_SAFE_ACCEPT_QUEUE_SIZE 100 /* one listening port */ -typedef struct server_port { +struct grpc_tcp_listener { /* This seemingly magic number comes from AcceptEx's documentation. each address buffer needs to have at least 16 more bytes at their end. */ gpr_uint8 addresses[(sizeof(struct sockaddr_in6) + 16) * 2]; /* This will hold the socket for the next accept. */ SOCKET new_socket; - /* The listener winsocked. */ + /* The listener winsocket. */ grpc_winsocket *socket; + /* The actual TCP port number. */ + int port; grpc_tcp_server *server; /* The cached AcceptEx for that port. */ LPFN_ACCEPTEX AcceptEx; int shutting_down; /* closure for socket notification of accept being ready */ grpc_closure on_accept; -} server_port; + gpr_refcount refs; + /* linked list */ + struct grpc_tcp_listener *next; +}; /* the overall server */ struct grpc_tcp_server { @@ -82,10 +87,8 @@ struct grpc_tcp_server { /* active port count: how many ports are actually still listening */ int active_ports; - /* all listening ports */ - server_port *ports; - size_t nports; - size_t port_capacity; + /* linked list of server ports */ + grpc_tcp_listener *head; /* shutdown callback */ grpc_closure *shutdown_complete; @@ -99,9 +102,7 @@ grpc_tcp_server *grpc_tcp_server_create(void) { s->active_ports = 0; s->on_accept_cb = NULL; s->on_accept_cb_arg = NULL; - s->ports = gpr_malloc(sizeof(server_port) * INIT_PORT_CAP); - s->nports = 0; - s->port_capacity = INIT_PORT_CAP; + s->head = NULL; s->shutdown_complete = NULL; return s; } @@ -109,26 +110,26 @@ grpc_tcp_server *grpc_tcp_server_create(void) { static void dont_care_about_shutdown_completion(void *arg) {} static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { - size_t i; - grpc_exec_ctx_enqueue(exec_ctx, s->shutdown_complete, 1); /* Now that the accepts have been aborted, we can destroy the sockets. The IOCP won't get notified on these, so we can flag them as already closed by the system. */ - for (i = 0; i < s->nports; i++) { - server_port *sp = &s->ports[i]; + while (s->head) { + grpc_tcp_listener *sp = s->head; + s->head = sp->next; + sp->next = NULL; grpc_winsocket_destroy(sp->socket); + grpc_tcp_listener_unref(sp); } - gpr_free(s->ports); gpr_free(s); } /* Public function. Stops and destroys a grpc_tcp_server. */ void grpc_tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s, grpc_closure *shutdown_complete) { - size_t i; int immediately_done = 0; + grpc_tcp_listener *sp; gpr_mu_lock(&s->mu); s->shutdown_complete = shutdown_complete; @@ -138,8 +139,7 @@ void grpc_tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s, if (s->active_ports == 0) { immediately_done = 1; } - for (i = 0; i < s->nports; i++) { - server_port *sp = &s->ports[i]; + for (sp = s->head; sp; sp = sp->next) { sp->shutting_down = 1; grpc_winsocket_shutdown(sp->socket); } @@ -199,7 +199,7 @@ error: } static void decrement_active_ports_and_notify(grpc_exec_ctx *exec_ctx, - server_port *sp) { + grpc_tcp_listener *sp) { int notify = 0; sp->shutting_down = 0; gpr_mu_lock(&sp->server->mu); @@ -216,7 +216,7 @@ static void decrement_active_ports_and_notify(grpc_exec_ctx *exec_ctx, /* In order to do an async accept, we need to create a socket first which will be the one assigned to the new incoming connection. */ -static void start_accept(grpc_exec_ctx *exec_ctx, server_port *port) { +static void start_accept(grpc_exec_ctx *exec_ctx, grpc_tcp_listener *port) { SOCKET sock = INVALID_SOCKET; char *message; char *utf8_message; @@ -276,7 +276,7 @@ failure: /* Event manager callback when reads are ready. */ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, int from_iocp) { - server_port *sp = arg; + grpc_tcp_listener *sp = arg; SOCKET sock = sp->new_socket; grpc_winsocket_callback_info *info = &sp->socket->read_info; grpc_endpoint *ep = NULL; @@ -351,16 +351,17 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, int from_iocp) { start_accept(exec_ctx, sp); } -static int add_socket_to_server(grpc_tcp_server *s, SOCKET sock, - const struct sockaddr *addr, size_t addr_len) { - server_port *sp; +static grpc_tcp_listener *add_socket_to_server(grpc_tcp_server *s, SOCKET sock, + const struct sockaddr *addr, + size_t addr_len) { + grpc_tcp_listener *sp = NULL; int port; int status; GUID guid = WSAID_ACCEPTEX; DWORD ioctl_num_bytes; LPFN_ACCEPTEX AcceptEx; - if (sock == INVALID_SOCKET) return -1; + if (sock == INVALID_SOCKET) return NULL; /* We need to grab the AcceptEx pointer for that port, as it may be interface-dependent. We'll cache it to avoid doing that again. */ @@ -373,37 +374,35 @@ static int add_socket_to_server(grpc_tcp_server *s, SOCKET sock, gpr_log(GPR_ERROR, "on_connect error: %s", utf8_message); gpr_free(utf8_message); closesocket(sock); - return -1; + return NULL; } port = prepare_socket(sock, addr, addr_len); if (port >= 0) { gpr_mu_lock(&s->mu); GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server"); - /* append it to the list under a lock */ - if (s->nports == s->port_capacity) { - /* too many ports, and we need to store their address in a closure */ - /* TODO(ctiller): make server_port a linked list */ - abort(); - } - sp = &s->ports[s->nports++]; + sp = gpr_malloc(sizeof(grpc_tcp_listener)); + sp->next = s->head; + s->head = sp; sp->server = s; sp->socket = grpc_winsocket_create(sock, "listener"); sp->shutting_down = 0; sp->AcceptEx = AcceptEx; sp->new_socket = INVALID_SOCKET; + sp->port = port; + gpr_ref_init(&sp->refs, 1); grpc_closure_init(&sp->on_accept, on_accept, sp); GPR_ASSERT(sp->socket); gpr_mu_unlock(&s->mu); } - return port; + return sp; } -int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr, - size_t addr_len) { - int allocated_port = -1; - unsigned i; +grpc_tcp_listener *grpc_tcp_server_add_port(grpc_tcp_server *s, + const void *addr, + size_t addr_len) { + grpc_tcp_listener *sp; SOCKET sock; struct sockaddr_in6 addr6_v4mapped; struct sockaddr_in6 wildcard; @@ -415,9 +414,9 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr, /* 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 (i = 0; i < s->nports; i++) { + for (sp = s->head; sp; sp = sp->next) { sockname_len = sizeof(sockname_temp); - if (0 == getsockname(s->ports[i].socket->socket, + if (0 == getsockname(sp->socket->socket, (struct sockaddr *)&sockname_temp, &sockname_len)) { port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp); if (port > 0) { @@ -452,33 +451,55 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr, gpr_free(utf8_message); } - allocated_port = add_socket_to_server(s, sock, addr, addr_len); + sp = add_socket_to_server(s, sock, addr, addr_len); gpr_free(allocated_addr); - return allocated_port; + return sp; } -SOCKET -grpc_tcp_server_get_socket(grpc_tcp_server *s, unsigned index) { - return (index < s->nports) ? s->ports[index].socket->socket : INVALID_SOCKET; +int grpc_tcp_server_get_fd(grpc_tcp_server *s, unsigned port_index) { + grpc_tcp_listener *sp; + for (sp = s->head; sp && port_index != 0; sp = sp->next, port_index--); + if (port_index == 0 && sp) { + return _open_osfhandle(sp->socket->socket, 0); + } else { + return -1; + } } void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s, grpc_pollset **pollset, size_t pollset_count, grpc_tcp_server_cb on_accept_cb, void *on_accept_cb_arg) { - size_t i; + grpc_tcp_listener *sp; GPR_ASSERT(on_accept_cb); gpr_mu_lock(&s->mu); GPR_ASSERT(!s->on_accept_cb); GPR_ASSERT(s->active_ports == 0); s->on_accept_cb = on_accept_cb; s->on_accept_cb_arg = on_accept_cb_arg; - for (i = 0; i < s->nports; i++) { - start_accept(exec_ctx, s->ports + i); + for (sp = s->head; sp; sp = sp->next) { + start_accept(exec_ctx, sp); s->active_ports++; } gpr_mu_unlock(&s->mu); } +int grpc_tcp_listener_get_port(grpc_tcp_listener *listener) { + grpc_tcp_listener *sp = listener; + return sp->port; +} + +void grpc_tcp_listener_ref(grpc_tcp_listener *listener) { + grpc_tcp_listener *sp = listener; + gpr_ref(&sp->refs); +} + +void grpc_tcp_listener_unref(grpc_tcp_listener *listener) { + grpc_tcp_listener *sp = listener; + if (gpr_unref(&sp->refs)) { + gpr_free(listener); + } +} + #endif /* GPR_WINSOCK_SOCKET */ diff --git a/src/core/security/client_auth_filter.c b/src/core/security/client_auth_filter.c index c780b65873..be2522a7a0 100644 --- a/src/core/security/client_auth_filter.c +++ b/src/core/security/client_auth_filter.c @@ -50,7 +50,7 @@ /* We can have a per-call credentials. */ typedef struct { - grpc_credentials *creds; + grpc_call_credentials *creds; grpc_mdstr *host; grpc_mdstr *method; /* pollset bound to this call; if we need to make external @@ -143,39 +143,35 @@ static void send_security_metadata(grpc_exec_ctx *exec_ctx, channel_data *chand = elem->channel_data; grpc_client_security_context *ctx = (grpc_client_security_context *)op->context[GRPC_CONTEXT_SECURITY].value; - grpc_credentials *channel_creds = + grpc_call_credentials *channel_call_creds = chand->security_connector->request_metadata_creds; - int channel_creds_has_md = - (channel_creds != NULL) && - grpc_credentials_has_request_metadata(channel_creds); - int call_creds_has_md = (ctx != NULL) && (ctx->creds != NULL) && - grpc_credentials_has_request_metadata(ctx->creds); + int call_creds_has_md = (ctx != NULL) && (ctx->creds != NULL); - if (!channel_creds_has_md && !call_creds_has_md) { + if (channel_call_creds == NULL && !call_creds_has_md) { /* Skip sending metadata altogether. */ grpc_call_next_op(exec_ctx, elem, op); return; } - if (channel_creds_has_md && call_creds_has_md) { - calld->creds = - grpc_composite_credentials_create(channel_creds, ctx->creds, NULL); + if (channel_call_creds != NULL && call_creds_has_md) { + calld->creds = grpc_composite_call_credentials_create(channel_call_creds, + ctx->creds, NULL); if (calld->creds == NULL) { bubble_up_error(exec_ctx, elem, GRPC_STATUS_INVALID_ARGUMENT, "Incompatible credentials set on channel and call."); return; } } else { - calld->creds = - grpc_credentials_ref(call_creds_has_md ? ctx->creds : channel_creds); + calld->creds = grpc_call_credentials_ref( + call_creds_has_md ? ctx->creds : channel_call_creds); } build_service_url(chand->security_connector->base.url_scheme, calld); calld->op = *op; /* Copy op (originates from the caller's stack). */ GPR_ASSERT(calld->pollset); - grpc_credentials_get_request_metadata(exec_ctx, calld->creds, calld->pollset, - calld->service_url, - on_credentials_metadata, elem); + grpc_call_credentials_get_request_metadata(exec_ctx, calld->creds, + calld->pollset, calld->service_url, + on_credentials_metadata, elem); } static void on_host_checked(grpc_exec_ctx *exec_ctx, void *user_data, @@ -282,7 +278,7 @@ static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { call_data *calld = elem->call_data; - grpc_credentials_unref(calld->creds); + grpc_call_credentials_unref(calld->creds); if (calld->host != NULL) { GRPC_MDSTR_UNREF(calld->host); } diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c index 2a8ffae5d7..f7a2e73785 100644 --- a/src/core/security/credentials.c +++ b/src/core/security/credentials.c @@ -54,18 +54,18 @@ /* -- Common. -- */ struct grpc_credentials_metadata_request { - grpc_credentials *creds; + grpc_call_credentials *creds; grpc_credentials_metadata_cb cb; void *user_data; }; static grpc_credentials_metadata_request * -grpc_credentials_metadata_request_create(grpc_credentials *creds, +grpc_credentials_metadata_request_create(grpc_call_credentials *creds, grpc_credentials_metadata_cb cb, void *user_data) { grpc_credentials_metadata_request *r = gpr_malloc(sizeof(grpc_credentials_metadata_request)); - r->creds = grpc_credentials_ref(creds); + r->creds = grpc_call_credentials_ref(creds); r->cb = cb; r->user_data = user_data; return r; @@ -73,44 +73,56 @@ grpc_credentials_metadata_request_create(grpc_credentials *creds, static void grpc_credentials_metadata_request_destroy( grpc_credentials_metadata_request *r) { - grpc_credentials_unref(r->creds); + grpc_call_credentials_unref(r->creds); gpr_free(r); } -grpc_credentials *grpc_credentials_ref(grpc_credentials *creds) { +grpc_channel_credentials *grpc_channel_credentials_ref( + grpc_channel_credentials *creds) { if (creds == NULL) return NULL; gpr_ref(&creds->refcount); return creds; } -void grpc_credentials_unref(grpc_credentials *creds) { +void grpc_channel_credentials_unref(grpc_channel_credentials *creds) { if (creds == NULL) return; if (gpr_unref(&creds->refcount)) { - creds->vtable->destruct(creds); + if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds); gpr_free(creds); } } -void grpc_credentials_release(grpc_credentials *creds) { - GRPC_API_TRACE("grpc_credentials_release(creds=%p)", 1, (creds)); - grpc_credentials_unref(creds); +void grpc_channel_credentials_release(grpc_channel_credentials *creds) { + GRPC_API_TRACE("grpc_channel_credentials_release(creds=%p)", 1, (creds)); + grpc_channel_credentials_unref(creds); } -int grpc_credentials_has_request_metadata(grpc_credentials *creds) { - if (creds == NULL) return 0; - return creds->vtable->has_request_metadata(creds); +grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds) { + if (creds == NULL) return NULL; + gpr_ref(&creds->refcount); + return creds; +} + +void grpc_call_credentials_unref(grpc_call_credentials *creds) { + if (creds == NULL) return; + if (gpr_unref(&creds->refcount)) { + if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds); + gpr_free(creds); + } } -int grpc_credentials_has_request_metadata_only(grpc_credentials *creds) { - if (creds == NULL) return 0; - return creds->vtable->has_request_metadata_only(creds); +void grpc_call_credentials_release(grpc_call_credentials *creds) { + GRPC_API_TRACE("grpc_call_credentials_release(creds=%p)", 1, (creds)); + grpc_call_credentials_unref(creds); } -void grpc_credentials_get_request_metadata( - grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset, - const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { - if (creds == NULL || !grpc_credentials_has_request_metadata(creds) || - creds->vtable->get_request_metadata == NULL) { +void grpc_call_credentials_get_request_metadata(grpc_exec_ctx *exec_ctx, + grpc_call_credentials *creds, + grpc_pollset *pollset, + const char *service_url, + grpc_credentials_metadata_cb cb, + void *user_data) { + if (creds == NULL || creds->vtable->get_request_metadata == NULL) { if (cb != NULL) { cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK); } @@ -120,19 +132,17 @@ void grpc_credentials_get_request_metadata( user_data); } -grpc_security_status grpc_credentials_create_security_connector( - grpc_credentials *creds, const char *target, const grpc_channel_args *args, - grpc_credentials *request_metadata_creds, - grpc_channel_security_connector **sc, grpc_channel_args **new_args) { +grpc_security_status grpc_channel_credentials_create_security_connector( + grpc_channel_credentials *channel_creds, const char *target, + const grpc_channel_args *args, grpc_channel_security_connector **sc, + grpc_channel_args **new_args) { *new_args = NULL; - if (creds == NULL || creds->vtable->create_security_connector == NULL || - grpc_credentials_has_request_metadata_only(creds)) { - gpr_log(GPR_ERROR, - "Invalid credentials for creating a security connector."); + if (channel_creds == NULL) { return GRPC_SECURITY_ERROR; } - return creds->vtable->create_security_connector( - creds, target, args, request_metadata_creds, sc, new_args); + GPR_ASSERT(channel_creds->vtable->create_security_connector != NULL); + return channel_creds->vtable->create_security_connector( + channel_creds, NULL, target, args, sc, new_args); } grpc_server_credentials *grpc_server_credentials_ref( @@ -145,7 +155,7 @@ grpc_server_credentials *grpc_server_credentials_ref( void grpc_server_credentials_unref(grpc_server_credentials *creds) { if (creds == NULL) return; if (gpr_unref(&creds->refcount)) { - creds->vtable->destruct(creds); + if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds); if (creds->processor.destroy != NULL && creds->processor.state != NULL) { creds->processor.destroy(creds->processor.state); } @@ -224,7 +234,7 @@ grpc_server_credentials *grpc_find_server_credentials_in_args( /* -- Ssl credentials. -- */ -static void ssl_destruct(grpc_credentials *creds) { +static void ssl_destruct(grpc_channel_credentials *creds) { grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds; if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs); if (c->config.pem_private_key != NULL) gpr_free(c->config.pem_private_key); @@ -253,15 +263,9 @@ static void ssl_server_destruct(grpc_server_credentials *creds) { if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs); } -static int ssl_has_request_metadata(const grpc_credentials *creds) { return 0; } - -static int ssl_has_request_metadata_only(const grpc_credentials *creds) { - return 0; -} - static grpc_security_status ssl_create_security_connector( - grpc_credentials *creds, const char *target, const grpc_channel_args *args, - grpc_credentials *request_metadata_creds, + grpc_channel_credentials *creds, grpc_call_credentials *call_creds, + const char *target, const grpc_channel_args *args, grpc_channel_security_connector **sc, grpc_channel_args **new_args) { grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds; grpc_security_status status = GRPC_SECURITY_OK; @@ -278,7 +282,7 @@ static grpc_security_status ssl_create_security_connector( } } status = grpc_ssl_channel_security_connector_create( - request_metadata_creds, &c->config, target, overridden_target_name, sc); + call_creds, &c->config, target, overridden_target_name, sc); if (status != GRPC_SECURITY_OK) { return status; } @@ -295,9 +299,8 @@ static grpc_security_status ssl_server_create_security_connector( return grpc_ssl_server_security_connector_create(&c->config, sc); } -static grpc_credentials_vtable ssl_vtable = { - ssl_destruct, ssl_has_request_metadata, ssl_has_request_metadata_only, NULL, - ssl_create_security_connector}; +static grpc_channel_credentials_vtable ssl_vtable = { + ssl_destruct, ssl_create_security_connector}; static grpc_server_credentials_vtable ssl_server_vtable = { ssl_server_destruct, ssl_server_create_security_connector}; @@ -362,7 +365,7 @@ static void ssl_build_server_config( } } -grpc_credentials *grpc_ssl_credentials_create( +grpc_channel_credentials *grpc_ssl_credentials_create( const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair, void *reserved) { grpc_ssl_credentials *c = gpr_malloc(sizeof(grpc_ssl_credentials)); @@ -373,7 +376,7 @@ grpc_credentials *grpc_ssl_credentials_create( 3, (pem_root_certs, pem_key_cert_pair, reserved)); GPR_ASSERT(reserved == NULL); memset(c, 0, sizeof(grpc_ssl_credentials)); - c->base.type = GRPC_CREDENTIALS_TYPE_SSL; + c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL; c->base.vtable = &ssl_vtable; gpr_ref_init(&c->base.refcount, 1); ssl_build_config(pem_root_certs, pem_key_cert_pair, &c->config); @@ -393,7 +396,7 @@ grpc_server_credentials *grpc_ssl_server_credentials_create( force_client_auth, reserved)); GPR_ASSERT(reserved == NULL); memset(c, 0, sizeof(grpc_ssl_server_credentials)); - c->base.type = GRPC_CREDENTIALS_TYPE_SSL; + c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL; gpr_ref_init(&c->base.refcount, 1); c->base.vtable = &ssl_server_vtable; ssl_build_server_config(pem_root_certs, pem_key_cert_pairs, @@ -415,7 +418,7 @@ static void jwt_reset_cache(grpc_service_account_jwt_access_credentials *c) { c->cached.jwt_expiration = gpr_inf_past(GPR_CLOCK_REALTIME); } -static void jwt_destruct(grpc_credentials *creds) { +static void jwt_destruct(grpc_call_credentials *creds) { grpc_service_account_jwt_access_credentials *c = (grpc_service_account_jwt_access_credentials *)creds; grpc_auth_json_key_destruct(&c->key); @@ -423,15 +426,12 @@ static void jwt_destruct(grpc_credentials *creds) { gpr_mu_destroy(&c->cache_mu); } -static int jwt_has_request_metadata(const grpc_credentials *creds) { return 1; } - -static int jwt_has_request_metadata_only(const grpc_credentials *creds) { - return 1; -} - -static void jwt_get_request_metadata( - grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset, - const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { +static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx, + grpc_call_credentials *creds, + grpc_pollset *pollset, + const char *service_url, + grpc_credentials_metadata_cb cb, + void *user_data) { grpc_service_account_jwt_access_credentials *c = (grpc_service_account_jwt_access_credentials *)creds; gpr_timespec refresh_threshold = gpr_time_from_seconds( @@ -483,11 +483,10 @@ static void jwt_get_request_metadata( } } -static grpc_credentials_vtable jwt_vtable = { - jwt_destruct, jwt_has_request_metadata, jwt_has_request_metadata_only, - jwt_get_request_metadata, NULL}; +static grpc_call_credentials_vtable jwt_vtable = {jwt_destruct, + jwt_get_request_metadata}; -grpc_credentials * +grpc_call_credentials * grpc_service_account_jwt_access_credentials_create_from_auth_json_key( grpc_auth_json_key key, gpr_timespec token_lifetime) { grpc_service_account_jwt_access_credentials *c; @@ -497,7 +496,7 @@ grpc_service_account_jwt_access_credentials_create_from_auth_json_key( } c = gpr_malloc(sizeof(grpc_service_account_jwt_access_credentials)); memset(c, 0, sizeof(grpc_service_account_jwt_access_credentials)); - c->base.type = GRPC_CREDENTIALS_TYPE_JWT; + c->base.type = GRPC_CALL_CREDENTIALS_TYPE_JWT; gpr_ref_init(&c->base.refcount, 1); c->base.vtable = &jwt_vtable; c->key = key; @@ -507,7 +506,7 @@ grpc_service_account_jwt_access_credentials_create_from_auth_json_key( return &c->base; } -grpc_credentials *grpc_service_account_jwt_access_credentials_create( +grpc_call_credentials *grpc_service_account_jwt_access_credentials_create( const char *json_key, gpr_timespec token_lifetime, void *reserved) { GRPC_API_TRACE( "grpc_service_account_jwt_access_credentials_create(" @@ -524,7 +523,7 @@ grpc_credentials *grpc_service_account_jwt_access_credentials_create( /* -- Oauth2TokenFetcher credentials -- */ -static void oauth2_token_fetcher_destruct(grpc_credentials *creds) { +static void oauth2_token_fetcher_destruct(grpc_call_credentials *creds) { grpc_oauth2_token_fetcher_credentials *c = (grpc_oauth2_token_fetcher_credentials *)creds; grpc_credentials_md_store_unref(c->access_token_md); @@ -532,16 +531,6 @@ static void oauth2_token_fetcher_destruct(grpc_credentials *creds) { grpc_httpcli_context_destroy(&c->httpcli_context); } -static int oauth2_token_fetcher_has_request_metadata( - const grpc_credentials *creds) { - return 1; -} - -static int oauth2_token_fetcher_has_request_metadata_only( - const grpc_credentials *creds) { - return 1; -} - grpc_credentials_status grpc_oauth2_token_fetcher_credentials_parse_server_response( const grpc_httpcli_response *response, grpc_credentials_md_store **token_md, @@ -659,8 +648,9 @@ static void on_oauth2_token_fetcher_http_response( } static void oauth2_token_fetcher_get_request_metadata( - grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset, - const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { + grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, + grpc_pollset *pollset, const char *service_url, + grpc_credentials_metadata_cb cb, void *user_data) { grpc_oauth2_token_fetcher_credentials *c = (grpc_oauth2_token_fetcher_credentials *)creds; gpr_timespec refresh_threshold = gpr_time_from_seconds( @@ -693,7 +683,7 @@ static void oauth2_token_fetcher_get_request_metadata( static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c, grpc_fetch_oauth2_func fetch_func) { memset(c, 0, sizeof(grpc_oauth2_token_fetcher_credentials)); - c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2; + c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2; gpr_ref_init(&c->base.refcount, 1); gpr_mu_init(&c->mu); c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME); @@ -703,10 +693,8 @@ static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c, /* -- GoogleComputeEngine credentials. -- */ -static grpc_credentials_vtable compute_engine_vtable = { - oauth2_token_fetcher_destruct, oauth2_token_fetcher_has_request_metadata, - oauth2_token_fetcher_has_request_metadata_only, - oauth2_token_fetcher_get_request_metadata, NULL}; +static grpc_call_credentials_vtable compute_engine_vtable = { + oauth2_token_fetcher_destruct, oauth2_token_fetcher_get_request_metadata}; static void compute_engine_fetch_oauth2( grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req, @@ -723,7 +711,7 @@ static void compute_engine_fetch_oauth2( response_cb, metadata_req); } -grpc_credentials *grpc_google_compute_engine_credentials_create( +grpc_call_credentials *grpc_google_compute_engine_credentials_create( void *reserved) { grpc_oauth2_token_fetcher_credentials *c = gpr_malloc(sizeof(grpc_oauth2_token_fetcher_credentials)); @@ -737,17 +725,15 @@ grpc_credentials *grpc_google_compute_engine_credentials_create( /* -- GoogleRefreshToken credentials. -- */ -static void refresh_token_destruct(grpc_credentials *creds) { +static void refresh_token_destruct(grpc_call_credentials *creds) { grpc_google_refresh_token_credentials *c = (grpc_google_refresh_token_credentials *)creds; grpc_auth_refresh_token_destruct(&c->refresh_token); oauth2_token_fetcher_destruct(&c->base.base); } -static grpc_credentials_vtable refresh_token_vtable = { - refresh_token_destruct, oauth2_token_fetcher_has_request_metadata, - oauth2_token_fetcher_has_request_metadata_only, - oauth2_token_fetcher_get_request_metadata, NULL}; +static grpc_call_credentials_vtable refresh_token_vtable = { + refresh_token_destruct, oauth2_token_fetcher_get_request_metadata}; static void refresh_token_fetch_oauth2( grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req, @@ -773,7 +759,8 @@ static void refresh_token_fetch_oauth2( gpr_free(body); } -grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token( +grpc_call_credentials * +grpc_refresh_token_credentials_create_from_auth_refresh_token( grpc_auth_refresh_token refresh_token) { grpc_google_refresh_token_credentials *c; if (!grpc_auth_refresh_token_is_valid(&refresh_token)) { @@ -788,7 +775,7 @@ grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token( return &c->base.base; } -grpc_credentials *grpc_google_refresh_token_credentials_create( +grpc_call_credentials *grpc_google_refresh_token_credentials_create( const char *json_refresh_token, void *reserved) { GRPC_API_TRACE( "grpc_refresh_token_credentials_create(json_refresh_token=%s, " @@ -801,20 +788,11 @@ grpc_credentials *grpc_google_refresh_token_credentials_create( /* -- Metadata-only credentials. -- */ -static void md_only_test_destruct(grpc_credentials *creds) { +static void md_only_test_destruct(grpc_call_credentials *creds) { grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds; grpc_credentials_md_store_unref(c->md_store); } -static int md_only_test_has_request_metadata(const grpc_credentials *creds) { - return 1; -} - -static int md_only_test_has_request_metadata_only( - const grpc_credentials *creds) { - return 1; -} - static void on_simulated_token_fetch_done(void *user_data) { grpc_credentials_metadata_request *r = (grpc_credentials_metadata_request *)user_data; @@ -826,9 +804,12 @@ static void on_simulated_token_fetch_done(void *user_data) { grpc_exec_ctx_finish(&exec_ctx); } -static void md_only_test_get_request_metadata( - grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset, - const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { +static void md_only_test_get_request_metadata(grpc_exec_ctx *exec_ctx, + grpc_call_credentials *creds, + grpc_pollset *pollset, + const char *service_url, + grpc_credentials_metadata_cb cb, + void *user_data) { grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds; if (c->is_async) { @@ -841,18 +822,15 @@ static void md_only_test_get_request_metadata( } } -static grpc_credentials_vtable md_only_test_vtable = { - md_only_test_destruct, md_only_test_has_request_metadata, - md_only_test_has_request_metadata_only, md_only_test_get_request_metadata, - NULL}; +static grpc_call_credentials_vtable md_only_test_vtable = { + md_only_test_destruct, md_only_test_get_request_metadata}; -grpc_credentials *grpc_md_only_test_credentials_create(const char *md_key, - const char *md_value, - int is_async) { +grpc_call_credentials *grpc_md_only_test_credentials_create( + const char *md_key, const char *md_value, int is_async) { grpc_md_only_test_credentials *c = gpr_malloc(sizeof(grpc_md_only_test_credentials)); memset(c, 0, sizeof(grpc_md_only_test_credentials)); - c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2; + c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2; c->base.vtable = &md_only_test_vtable; gpr_ref_init(&c->base.refcount, 1); c->md_store = grpc_credentials_md_store_create(1); @@ -863,34 +841,26 @@ grpc_credentials *grpc_md_only_test_credentials_create(const char *md_key, /* -- Oauth2 Access Token credentials. -- */ -static void access_token_destruct(grpc_credentials *creds) { +static void access_token_destruct(grpc_call_credentials *creds) { grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds; grpc_credentials_md_store_unref(c->access_token_md); } -static int access_token_has_request_metadata(const grpc_credentials *creds) { - return 1; -} - -static int access_token_has_request_metadata_only( - const grpc_credentials *creds) { - return 1; -} - -static void access_token_get_request_metadata( - grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset, - const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { +static void access_token_get_request_metadata(grpc_exec_ctx *exec_ctx, + grpc_call_credentials *creds, + grpc_pollset *pollset, + const char *service_url, + grpc_credentials_metadata_cb cb, + void *user_data) { grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds; cb(exec_ctx, user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK); } -static grpc_credentials_vtable access_token_vtable = { - access_token_destruct, access_token_has_request_metadata, - access_token_has_request_metadata_only, access_token_get_request_metadata, - NULL}; +static grpc_call_credentials_vtable access_token_vtable = { + access_token_destruct, access_token_get_request_metadata}; -grpc_credentials *grpc_access_token_credentials_create(const char *access_token, - void *reserved) { +grpc_call_credentials *grpc_access_token_credentials_create( + const char *access_token, void *reserved) { grpc_access_token_credentials *c = gpr_malloc(sizeof(grpc_access_token_credentials)); char *token_md_value; @@ -900,7 +870,7 @@ grpc_credentials *grpc_access_token_credentials_create(const char *access_token, 2, (access_token, reserved)); GPR_ASSERT(reserved == NULL); memset(c, 0, sizeof(grpc_access_token_credentials)); - c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2; + c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2; c->base.vtable = &access_token_vtable; gpr_ref_init(&c->base.refcount, 1); c->access_token_md = grpc_credentials_md_store_create(1); @@ -913,31 +883,11 @@ grpc_credentials *grpc_access_token_credentials_create(const char *access_token, /* -- Fake transport security credentials. -- */ -static void fake_transport_security_credentials_destruct( - grpc_credentials *creds) { - /* Nothing to do here. */ -} - -static void fake_transport_security_server_credentials_destruct( - grpc_server_credentials *creds) { - /* Nothing to do here. */ -} - -static int fake_transport_security_has_request_metadata( - const grpc_credentials *creds) { - return 0; -} - -static int fake_transport_security_has_request_metadata_only( - const grpc_credentials *creds) { - return 0; -} - static grpc_security_status fake_transport_security_create_security_connector( - grpc_credentials *c, const char *target, const grpc_channel_args *args, - grpc_credentials *request_metadata_creds, + grpc_channel_credentials *c, grpc_call_credentials *call_creds, + const char *target, const grpc_channel_args *args, grpc_channel_security_connector **sc, grpc_channel_args **new_args) { - *sc = grpc_fake_channel_security_connector_create(request_metadata_creds, 1); + *sc = grpc_fake_channel_security_connector_create(call_creds, 1); return GRPC_SECURITY_OK; } @@ -948,21 +898,19 @@ fake_transport_security_server_create_security_connector( return GRPC_SECURITY_OK; } -static grpc_credentials_vtable fake_transport_security_credentials_vtable = { - fake_transport_security_credentials_destruct, - fake_transport_security_has_request_metadata, - fake_transport_security_has_request_metadata_only, NULL, - fake_transport_security_create_security_connector}; +static grpc_channel_credentials_vtable + fake_transport_security_credentials_vtable = { + NULL, fake_transport_security_create_security_connector}; static grpc_server_credentials_vtable fake_transport_security_server_credentials_vtable = { - fake_transport_security_server_credentials_destruct, - fake_transport_security_server_create_security_connector}; + NULL, fake_transport_security_server_create_security_connector}; -grpc_credentials *grpc_fake_transport_security_credentials_create(void) { - grpc_credentials *c = gpr_malloc(sizeof(grpc_credentials)); - memset(c, 0, sizeof(grpc_credentials)); - c->type = GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY; +grpc_channel_credentials *grpc_fake_transport_security_credentials_create( + void) { + grpc_channel_credentials *c = gpr_malloc(sizeof(grpc_channel_credentials)); + memset(c, 0, sizeof(grpc_channel_credentials)); + c->type = GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY; c->vtable = &fake_transport_security_credentials_vtable; gpr_ref_init(&c->refcount, 1); return c; @@ -972,69 +920,46 @@ grpc_server_credentials *grpc_fake_transport_security_server_credentials_create( void) { grpc_server_credentials *c = gpr_malloc(sizeof(grpc_server_credentials)); memset(c, 0, sizeof(grpc_server_credentials)); - c->type = GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY; + c->type = GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY; gpr_ref_init(&c->refcount, 1); c->vtable = &fake_transport_security_server_credentials_vtable; return c; } -/* -- Composite credentials. -- */ +/* -- Composite call credentials. -- */ typedef struct { - grpc_composite_credentials *composite_creds; + grpc_composite_call_credentials *composite_creds; size_t creds_index; grpc_credentials_md_store *md_elems; char *service_url; void *user_data; grpc_pollset *pollset; grpc_credentials_metadata_cb cb; -} grpc_composite_credentials_metadata_context; +} grpc_composite_call_credentials_metadata_context; -static void composite_destruct(grpc_credentials *creds) { - grpc_composite_credentials *c = (grpc_composite_credentials *)creds; +static void composite_call_destruct(grpc_call_credentials *creds) { + grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds; size_t i; for (i = 0; i < c->inner.num_creds; i++) { - grpc_credentials_unref(c->inner.creds_array[i]); + grpc_call_credentials_unref(c->inner.creds_array[i]); } gpr_free(c->inner.creds_array); } -static int composite_has_request_metadata(const grpc_credentials *creds) { - const grpc_composite_credentials *c = - (const grpc_composite_credentials *)creds; - size_t i; - for (i = 0; i < c->inner.num_creds; i++) { - if (grpc_credentials_has_request_metadata(c->inner.creds_array[i])) { - return 1; - } - } - return 0; -} - -static int composite_has_request_metadata_only(const grpc_credentials *creds) { - const grpc_composite_credentials *c = - (const grpc_composite_credentials *)creds; - size_t i; - for (i = 0; i < c->inner.num_creds; i++) { - if (!grpc_credentials_has_request_metadata_only(c->inner.creds_array[i])) { - return 0; - } - } - return 1; -} - -static void composite_md_context_destroy( - grpc_composite_credentials_metadata_context *ctx) { +static void composite_call_md_context_destroy( + grpc_composite_call_credentials_metadata_context *ctx) { grpc_credentials_md_store_unref(ctx->md_elems); if (ctx->service_url != NULL) gpr_free(ctx->service_url); gpr_free(ctx); } -static void composite_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data, - grpc_credentials_md *md_elems, size_t num_md, - grpc_credentials_status status) { - grpc_composite_credentials_metadata_context *ctx = - (grpc_composite_credentials_metadata_context *)user_data; +static void composite_call_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data, + grpc_credentials_md *md_elems, + size_t num_md, + grpc_credentials_status status) { + grpc_composite_call_credentials_metadata_context *ctx = + (grpc_composite_call_credentials_metadata_context *)user_data; if (status != GRPC_CREDENTIALS_OK) { ctx->cb(exec_ctx, ctx->user_data, NULL, 0, status); return; @@ -1050,158 +975,114 @@ static void composite_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data, } /* See if we need to get some more metadata. */ - while (ctx->creds_index < ctx->composite_creds->inner.num_creds) { - grpc_credentials *inner_creds = + if (ctx->creds_index < ctx->composite_creds->inner.num_creds) { + grpc_call_credentials *inner_creds = ctx->composite_creds->inner.creds_array[ctx->creds_index++]; - if (grpc_credentials_has_request_metadata(inner_creds)) { - grpc_credentials_get_request_metadata(exec_ctx, inner_creds, ctx->pollset, - ctx->service_url, - composite_metadata_cb, ctx); - return; - } + grpc_call_credentials_get_request_metadata(exec_ctx, inner_creds, + ctx->pollset, ctx->service_url, + composite_call_metadata_cb, ctx); + return; } /* We're done!. */ ctx->cb(exec_ctx, ctx->user_data, ctx->md_elems->entries, ctx->md_elems->num_entries, GRPC_CREDENTIALS_OK); - composite_md_context_destroy(ctx); + composite_call_md_context_destroy(ctx); } -static void composite_get_request_metadata( - grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset, - const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { - grpc_composite_credentials *c = (grpc_composite_credentials *)creds; - grpc_composite_credentials_metadata_context *ctx; - if (!grpc_credentials_has_request_metadata(creds)) { - cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK); - return; - } - ctx = gpr_malloc(sizeof(grpc_composite_credentials_metadata_context)); - memset(ctx, 0, sizeof(grpc_composite_credentials_metadata_context)); +static void composite_call_get_request_metadata(grpc_exec_ctx *exec_ctx, + grpc_call_credentials *creds, + grpc_pollset *pollset, + const char *service_url, + grpc_credentials_metadata_cb cb, + void *user_data) { + grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds; + grpc_composite_call_credentials_metadata_context *ctx; + + ctx = gpr_malloc(sizeof(grpc_composite_call_credentials_metadata_context)); + memset(ctx, 0, sizeof(grpc_composite_call_credentials_metadata_context)); ctx->service_url = gpr_strdup(service_url); ctx->user_data = user_data; ctx->cb = cb; ctx->composite_creds = c; ctx->pollset = pollset; ctx->md_elems = grpc_credentials_md_store_create(c->inner.num_creds); - while (ctx->creds_index < c->inner.num_creds) { - grpc_credentials *inner_creds = c->inner.creds_array[ctx->creds_index++]; - if (grpc_credentials_has_request_metadata(inner_creds)) { - grpc_credentials_get_request_metadata(exec_ctx, inner_creds, pollset, - service_url, composite_metadata_cb, - ctx); - return; - } - } - GPR_ASSERT(0); /* Should have exited before. */ -} - -static grpc_security_status composite_create_security_connector( - grpc_credentials *creds, const char *target, const grpc_channel_args *args, - grpc_credentials *request_metadata_creds, - grpc_channel_security_connector **sc, grpc_channel_args **new_args) { - grpc_composite_credentials *c = (grpc_composite_credentials *)creds; - if (c->connector_creds == NULL) { - gpr_log(GPR_ERROR, - "Cannot create security connector, missing connector credentials."); - return GRPC_SECURITY_ERROR; - } - return grpc_credentials_create_security_connector(c->connector_creds, target, - args, creds, sc, new_args); + grpc_call_credentials_get_request_metadata( + exec_ctx, c->inner.creds_array[ctx->creds_index++], pollset, service_url, + composite_call_metadata_cb, ctx); } -static grpc_credentials_vtable composite_credentials_vtable = { - composite_destruct, composite_has_request_metadata, - composite_has_request_metadata_only, composite_get_request_metadata, - composite_create_security_connector}; +static grpc_call_credentials_vtable composite_call_credentials_vtable = { + composite_call_destruct, composite_call_get_request_metadata}; -static grpc_credentials_array get_creds_array(grpc_credentials **creds_addr) { - grpc_credentials_array result; - grpc_credentials *creds = *creds_addr; +static grpc_call_credentials_array get_creds_array( + grpc_call_credentials **creds_addr) { + grpc_call_credentials_array result; + grpc_call_credentials *creds = *creds_addr; result.creds_array = creds_addr; result.num_creds = 1; - if (strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0) { - result = *grpc_composite_credentials_get_credentials(creds); + if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) { + result = *grpc_composite_call_credentials_get_credentials(creds); } return result; } -grpc_credentials *grpc_composite_credentials_create(grpc_credentials *creds1, - grpc_credentials *creds2, - void *reserved) { +grpc_call_credentials *grpc_composite_call_credentials_create( + grpc_call_credentials *creds1, grpc_call_credentials *creds2, + void *reserved) { size_t i; size_t creds_array_byte_size; - grpc_credentials_array creds1_array; - grpc_credentials_array creds2_array; - grpc_composite_credentials *c; + grpc_call_credentials_array creds1_array; + grpc_call_credentials_array creds2_array; + grpc_composite_call_credentials *c; GRPC_API_TRACE( - "grpc_composite_credentials_create(creds1=%p, creds2=%p, " + "grpc_composite_call_credentials_create(creds1=%p, creds2=%p, " "reserved=%p)", 3, (creds1, creds2, reserved)); GPR_ASSERT(reserved == NULL); GPR_ASSERT(creds1 != NULL); GPR_ASSERT(creds2 != NULL); - c = gpr_malloc(sizeof(grpc_composite_credentials)); - memset(c, 0, sizeof(grpc_composite_credentials)); - c->base.type = GRPC_CREDENTIALS_TYPE_COMPOSITE; - c->base.vtable = &composite_credentials_vtable; + c = gpr_malloc(sizeof(grpc_composite_call_credentials)); + memset(c, 0, sizeof(grpc_composite_call_credentials)); + c->base.type = GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE; + c->base.vtable = &composite_call_credentials_vtable; gpr_ref_init(&c->base.refcount, 1); creds1_array = get_creds_array(&creds1); creds2_array = get_creds_array(&creds2); c->inner.num_creds = creds1_array.num_creds + creds2_array.num_creds; - creds_array_byte_size = c->inner.num_creds * sizeof(grpc_credentials *); + creds_array_byte_size = c->inner.num_creds * sizeof(grpc_call_credentials *); c->inner.creds_array = gpr_malloc(creds_array_byte_size); memset(c->inner.creds_array, 0, creds_array_byte_size); for (i = 0; i < creds1_array.num_creds; i++) { - grpc_credentials *cur_creds = creds1_array.creds_array[i]; - if (!grpc_credentials_has_request_metadata_only(cur_creds)) { - if (c->connector_creds == NULL) { - c->connector_creds = cur_creds; - } else { - gpr_log(GPR_ERROR, "Cannot compose multiple connector credentials."); - goto fail; - } - } - c->inner.creds_array[i] = grpc_credentials_ref(cur_creds); + grpc_call_credentials *cur_creds = creds1_array.creds_array[i]; + c->inner.creds_array[i] = grpc_call_credentials_ref(cur_creds); } for (i = 0; i < creds2_array.num_creds; i++) { - grpc_credentials *cur_creds = creds2_array.creds_array[i]; - if (!grpc_credentials_has_request_metadata_only(cur_creds)) { - if (c->connector_creds == NULL) { - c->connector_creds = cur_creds; - } else { - gpr_log(GPR_ERROR, "Cannot compose multiple connector credentials."); - goto fail; - } - } + grpc_call_credentials *cur_creds = creds2_array.creds_array[i]; c->inner.creds_array[i + creds1_array.num_creds] = - grpc_credentials_ref(cur_creds); + grpc_call_credentials_ref(cur_creds); } return &c->base; - -fail: - grpc_credentials_unref(&c->base); - return NULL; } -const grpc_credentials_array *grpc_composite_credentials_get_credentials( - grpc_credentials *creds) { - const grpc_composite_credentials *c = - (const grpc_composite_credentials *)creds; - GPR_ASSERT(strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0); +const grpc_call_credentials_array * +grpc_composite_call_credentials_get_credentials(grpc_call_credentials *creds) { + const grpc_composite_call_credentials *c = + (const grpc_composite_call_credentials *)creds; + GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0); return &c->inner; } -grpc_credentials *grpc_credentials_contains_type( - grpc_credentials *creds, const char *type, - grpc_credentials **composite_creds) { +grpc_call_credentials *grpc_credentials_contains_type( + grpc_call_credentials *creds, const char *type, + grpc_call_credentials **composite_creds) { size_t i; if (strcmp(creds->type, type) == 0) { if (composite_creds != NULL) *composite_creds = NULL; return creds; - } else if (strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0) { - const grpc_credentials_array *inner_creds_array = - grpc_composite_credentials_get_credentials(creds); + } else if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) { + const grpc_call_credentials_array *inner_creds_array = + grpc_composite_call_credentials_get_credentials(creds); for (i = 0; i < inner_creds_array->num_creds; i++) { if (strcmp(type, inner_creds_array->creds_array[i]->type) == 0) { if (composite_creds != NULL) *composite_creds = creds; @@ -1214,30 +1095,26 @@ grpc_credentials *grpc_credentials_contains_type( /* -- IAM credentials. -- */ -static void iam_destruct(grpc_credentials *creds) { +static void iam_destruct(grpc_call_credentials *creds) { grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds; grpc_credentials_md_store_unref(c->iam_md); } -static int iam_has_request_metadata(const grpc_credentials *creds) { return 1; } - -static int iam_has_request_metadata_only(const grpc_credentials *creds) { - return 1; -} - -static void iam_get_request_metadata( - grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset, - const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { +static void iam_get_request_metadata(grpc_exec_ctx *exec_ctx, + grpc_call_credentials *creds, + grpc_pollset *pollset, + const char *service_url, + grpc_credentials_metadata_cb cb, + void *user_data) { grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds; cb(exec_ctx, user_data, c->iam_md->entries, c->iam_md->num_entries, GRPC_CREDENTIALS_OK); } -static grpc_credentials_vtable iam_vtable = { - iam_destruct, iam_has_request_metadata, iam_has_request_metadata_only, - iam_get_request_metadata, NULL}; +static grpc_call_credentials_vtable iam_vtable = {iam_destruct, + iam_get_request_metadata}; -grpc_credentials *grpc_google_iam_credentials_create( +grpc_call_credentials *grpc_google_iam_credentials_create( const char *token, const char *authority_selector, void *reserved) { grpc_google_iam_credentials *c; GRPC_API_TRACE( @@ -1249,7 +1126,7 @@ grpc_credentials *grpc_google_iam_credentials_create( GPR_ASSERT(authority_selector != NULL); c = gpr_malloc(sizeof(grpc_google_iam_credentials)); memset(c, 0, sizeof(grpc_google_iam_credentials)); - c->base.type = GRPC_CREDENTIALS_TYPE_IAM; + c->base.type = GRPC_CALL_CREDENTIALS_TYPE_IAM; c->base.vtable = &iam_vtable; gpr_ref_init(&c->base.refcount, 1); c->iam_md = grpc_credentials_md_store_create(2); @@ -1267,21 +1144,13 @@ typedef struct { grpc_credentials_metadata_cb cb; } grpc_metadata_plugin_request; -static void plugin_destruct(grpc_credentials *creds) { +static void plugin_destruct(grpc_call_credentials *creds) { grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds; if (c->plugin.state != NULL && c->plugin.destroy != NULL) { c->plugin.destroy(c->plugin.state); } } -static int plugin_has_request_metadata(const grpc_credentials *creds) { - return 1; -} - -static int plugin_has_request_metadata_only(const grpc_credentials *creds) { - return 1; -} - static void plugin_md_request_metadata_ready(void *request, const grpc_metadata *md, size_t num_md, @@ -1320,9 +1189,12 @@ static void plugin_md_request_metadata_ready(void *request, grpc_exec_ctx_finish(&exec_ctx); } -static void plugin_get_request_metadata( - grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset, - const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { +static void plugin_get_request_metadata(grpc_exec_ctx *exec_ctx, + grpc_call_credentials *creds, + grpc_pollset *pollset, + const char *service_url, + grpc_credentials_metadata_cb cb, + void *user_data) { grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds; if (c->plugin.get_metadata != NULL) { grpc_metadata_plugin_request *request = gpr_malloc(sizeof(*request)); @@ -1336,18 +1208,75 @@ static void plugin_get_request_metadata( } } -static grpc_credentials_vtable plugin_vtable = { - plugin_destruct, plugin_has_request_metadata, - plugin_has_request_metadata_only, plugin_get_request_metadata, NULL}; +static grpc_call_credentials_vtable plugin_vtable = { + plugin_destruct, plugin_get_request_metadata}; -grpc_credentials *grpc_metadata_credentials_create_from_plugin( +grpc_call_credentials *grpc_metadata_credentials_create_from_plugin( grpc_metadata_credentials_plugin plugin, void *reserved) { grpc_plugin_credentials *c = gpr_malloc(sizeof(*c)); + GRPC_API_TRACE("grpc_metadata_credentials_create_from_plugin(reserved=%p)", 1, + (reserved)); GPR_ASSERT(reserved == NULL); memset(c, 0, sizeof(*c)); - c->base.type = GRPC_CREDENTIALS_TYPE_METADATA_PLUGIN; + c->base.type = GRPC_CALL_CREDENTIALS_TYPE_METADATA_PLUGIN; c->base.vtable = &plugin_vtable; gpr_ref_init(&c->base.refcount, 1); c->plugin = plugin; return &c->base; } + +/* -- Composite channel credentials. -- */ + +static void composite_channel_destruct(grpc_channel_credentials *creds) { + grpc_composite_channel_credentials *c = + (grpc_composite_channel_credentials *)creds; + grpc_channel_credentials_unref(c->inner_creds); + grpc_call_credentials_unref(c->call_creds); +} + +static grpc_security_status composite_channel_create_security_connector( + grpc_channel_credentials *creds, grpc_call_credentials *call_creds, + const char *target, const grpc_channel_args *args, + grpc_channel_security_connector **sc, grpc_channel_args **new_args) { + grpc_composite_channel_credentials *c = + (grpc_composite_channel_credentials *)creds; + grpc_security_status status = GRPC_SECURITY_ERROR; + + GPR_ASSERT(c->inner_creds != NULL && c->call_creds != NULL && + c->inner_creds->vtable != NULL && + c->inner_creds->vtable->create_security_connector != NULL); + /* If we are passed a call_creds, create a call composite to pass it + downstream. */ + if (call_creds != NULL) { + grpc_call_credentials *composite_call_creds = + grpc_composite_call_credentials_create(c->call_creds, call_creds, NULL); + status = c->inner_creds->vtable->create_security_connector( + c->inner_creds, composite_call_creds, target, args, sc, new_args); + grpc_call_credentials_unref(composite_call_creds); + } else { + status = c->inner_creds->vtable->create_security_connector( + c->inner_creds, c->call_creds, target, args, sc, new_args); + } + return status; +} + +static grpc_channel_credentials_vtable composite_channel_credentials_vtable = { + composite_channel_destruct, composite_channel_create_security_connector}; + +grpc_channel_credentials *grpc_composite_channel_credentials_create( + grpc_channel_credentials *channel_creds, grpc_call_credentials *call_creds, + void *reserved) { + grpc_composite_channel_credentials *c = gpr_malloc(sizeof(*c)); + memset(c, 0, sizeof(*c)); + GPR_ASSERT(channel_creds != NULL && call_creds != NULL && reserved == NULL); + GRPC_API_TRACE( + "grpc_composite_channel_credentials_create(channel_creds=%p, " + "call_creds=%p, reserved=%p)", + 3, (channel_creds, call_creds, reserved)); + c->base.type = channel_creds->type; + c->base.vtable = &composite_channel_credentials_vtable; + gpr_ref_init(&c->base.refcount, 1); + c->inner_creds = grpc_channel_credentials_ref(channel_creds); + c->call_creds = grpc_call_credentials_ref(call_creds); + return &c->base; +} diff --git a/src/core/security/credentials.h b/src/core/security/credentials.h index c74beef0e4..132060910e 100644 --- a/src/core/security/credentials.h +++ b/src/core/security/credentials.h @@ -54,15 +54,17 @@ typedef enum { #define GRPC_FAKE_TRANSPORT_SECURITY_TYPE "fake" -#define GRPC_CREDENTIALS_TYPE_SSL "Ssl" -#define GRPC_CREDENTIALS_TYPE_OAUTH2 "Oauth2" -#define GRPC_CREDENTIALS_TYPE_METADATA_PLUGIN "Plugin" -#define GRPC_CREDENTIALS_TYPE_JWT "Jwt" -#define GRPC_CREDENTIALS_TYPE_IAM "Iam" -#define GRPC_CREDENTIALS_TYPE_COMPOSITE "Composite" -#define GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY "FakeTransportSecurity" - -#define GRPC_AUTHORIZATION_METADATA_KEY "Authorization" +#define GRPC_CHANNEL_CREDENTIALS_TYPE_SSL "Ssl" +#define GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY \ + "FakeTransportSecurity" + +#define GRPC_CALL_CREDENTIALS_TYPE_OAUTH2 "Oauth2" +#define GRPC_CALL_CREDENTIALS_TYPE_METADATA_PLUGIN "Plugin" +#define GRPC_CALL_CREDENTIALS_TYPE_JWT "Jwt" +#define GRPC_CALL_CREDENTIALS_TYPE_IAM "Iam" +#define GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE "Composite" + +#define GRPC_AUTHORIZATION_METADATA_KEY "authorization" #define GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY \ "x-goog-iam-authorization-token" #define GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY "x-goog-iam-authority-selector" @@ -87,6 +89,41 @@ typedef enum { #define GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING \ "client_id=%s&client_secret=%s&refresh_token=%s&grant_type=refresh_token" +/* --- Google utils --- */ + +/* It is the caller's responsibility to gpr_free the result if not NULL. */ +char *grpc_get_well_known_google_credentials_file_path(void); + +/* --- grpc_channel_credentials. --- */ + +typedef struct { + void (*destruct)(grpc_channel_credentials *c); + + grpc_security_status (*create_security_connector)( + grpc_channel_credentials *c, grpc_call_credentials *call_creds, + const char *target, const grpc_channel_args *args, + grpc_channel_security_connector **sc, grpc_channel_args **new_args); +} grpc_channel_credentials_vtable; + +struct grpc_channel_credentials { + const grpc_channel_credentials_vtable *vtable; + const char *type; + gpr_refcount refcount; +}; + +grpc_channel_credentials *grpc_channel_credentials_ref( + grpc_channel_credentials *creds); +void grpc_channel_credentials_unref(grpc_channel_credentials *creds); + +/* Creates a security connector for the channel. May also create new channel + args for the channel to be used in place of the passed in const args if + returned non NULL. In that case the caller is responsible for destroying + new_args after channel creation. */ +grpc_security_status grpc_channel_credentials_create_security_connector( + grpc_channel_credentials *creds, const char *target, + const grpc_channel_args *args, grpc_channel_security_connector **sc, + grpc_channel_args **new_args); + /* --- grpc_credentials_md. --- */ typedef struct { @@ -113,16 +150,7 @@ grpc_credentials_md_store *grpc_credentials_md_store_ref( grpc_credentials_md_store *store); void grpc_credentials_md_store_unref(grpc_credentials_md_store *store); -/* --- grpc_credentials. --- */ - -/* Creates a fake transport security credentials object for testing. */ -grpc_credentials *grpc_fake_transport_security_credentials_create(void); -/* Creates a fake server transport security credentials object for testing. */ -grpc_server_credentials *grpc_fake_transport_security_server_credentials_create( - void); - -/* It is the caller's responsibility to gpr_free the result if not NULL. */ -char *grpc_get_well_known_google_credentials_file_path(void); +/* --- grpc_call_credentials. --- */ typedef void (*grpc_credentials_metadata_cb)(grpc_exec_ctx *exec_ctx, void *user_data, @@ -131,57 +159,45 @@ typedef void (*grpc_credentials_metadata_cb)(grpc_exec_ctx *exec_ctx, grpc_credentials_status status); typedef struct { - void (*destruct)(grpc_credentials *c); - int (*has_request_metadata)(const grpc_credentials *c); - int (*has_request_metadata_only)(const grpc_credentials *c); - void (*get_request_metadata)(grpc_exec_ctx *exec_ctx, grpc_credentials *c, - grpc_pollset *pollset, const char *service_url, + void (*destruct)(grpc_call_credentials *c); + void (*get_request_metadata)(grpc_exec_ctx *exec_ctx, + grpc_call_credentials *c, grpc_pollset *pollset, + const char *service_url, grpc_credentials_metadata_cb cb, void *user_data); - grpc_security_status (*create_security_connector)( - grpc_credentials *c, const char *target, const grpc_channel_args *args, - grpc_credentials *request_metadata_creds, - grpc_channel_security_connector **sc, grpc_channel_args **new_args); -} grpc_credentials_vtable; +} grpc_call_credentials_vtable; -struct grpc_credentials { - const grpc_credentials_vtable *vtable; +struct grpc_call_credentials { + const grpc_call_credentials_vtable *vtable; const char *type; gpr_refcount refcount; }; -grpc_credentials *grpc_credentials_ref(grpc_credentials *creds); -void grpc_credentials_unref(grpc_credentials *creds); -int grpc_credentials_has_request_metadata(grpc_credentials *creds); -int grpc_credentials_has_request_metadata_only(grpc_credentials *creds); -void grpc_credentials_get_request_metadata( - grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset, - const char *service_url, grpc_credentials_metadata_cb cb, void *user_data); - -/* Creates a security connector for the channel. May also create new channel - args for the channel to be used in place of the passed in const args if - returned non NULL. In that case the caller is responsible for destroying - new_args after channel creation. */ -grpc_security_status grpc_credentials_create_security_connector( - grpc_credentials *creds, const char *target, const grpc_channel_args *args, - grpc_credentials *request_metadata_creds, - grpc_channel_security_connector **sc, grpc_channel_args **new_args); +grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds); +void grpc_call_credentials_unref(grpc_call_credentials *creds); +void grpc_call_credentials_get_request_metadata(grpc_exec_ctx *exec_ctx, + grpc_call_credentials *creds, + grpc_pollset *pollset, + const char *service_url, + grpc_credentials_metadata_cb cb, + void *user_data); typedef struct { - grpc_credentials **creds_array; + grpc_call_credentials **creds_array; size_t num_creds; -} grpc_credentials_array; +} grpc_call_credentials_array; -const grpc_credentials_array *grpc_composite_credentials_get_credentials( - grpc_credentials *composite_creds); +const grpc_call_credentials_array * +grpc_composite_call_credentials_get_credentials( + grpc_call_credentials *composite_creds); /* Returns creds if creds is of the specified type or the inner creds of the specified type (if found), if the creds is of type COMPOSITE. If composite_creds is not NULL, *composite_creds will point to creds if of type COMPOSITE in case of success. */ -grpc_credentials *grpc_credentials_contains_type( - grpc_credentials *creds, const char *type, - grpc_credentials **composite_creds); +grpc_call_credentials *grpc_credentials_contains_type( + grpc_call_credentials *creds, const char *type, + grpc_call_credentials **composite_creds); /* Exposed for testing only. */ grpc_credentials_status @@ -192,19 +208,19 @@ void grpc_flush_cached_google_default_credentials(void); /* Metadata-only credentials with the specified key and value where asynchronicity can be simulated for testing. */ -grpc_credentials *grpc_md_only_test_credentials_create(const char *md_key, - const char *md_value, - int is_async); +grpc_call_credentials *grpc_md_only_test_credentials_create( + const char *md_key, const char *md_value, int is_async); /* Private constructor for jwt credentials from an already parsed json key. Takes ownership of the key. */ -grpc_credentials * +grpc_call_credentials * grpc_service_account_jwt_access_credentials_create_from_auth_json_key( grpc_auth_json_key key, gpr_timespec token_lifetime); /* Private constructor for refresh token credentials from an already parsed refresh token. Takes ownership of the refresh token. */ -grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token( +grpc_call_credentials * +grpc_refresh_token_credentials_create_from_auth_refresh_token( grpc_auth_refresh_token token); /* --- grpc_server_credentials. --- */ @@ -237,10 +253,18 @@ grpc_server_credentials *grpc_server_credentials_from_arg(const grpc_arg *arg); grpc_server_credentials *grpc_find_server_credentials_in_args( const grpc_channel_args *args); +/* -- Fake transport security credentials. -- */ + +/* Creates a fake transport security credentials object for testing. */ +grpc_channel_credentials *grpc_fake_transport_security_credentials_create(void); +/* Creates a fake server transport security credentials object for testing. */ +grpc_server_credentials *grpc_fake_transport_security_server_credentials_create( + void); + /* -- Ssl credentials. -- */ typedef struct { - grpc_credentials base; + grpc_channel_credentials base; grpc_ssl_config config; } grpc_ssl_credentials; @@ -249,10 +273,18 @@ typedef struct { grpc_ssl_server_config config; } grpc_ssl_server_credentials; +/* -- Channel composite credentials. -- */ + +typedef struct { + grpc_channel_credentials base; + grpc_channel_credentials *inner_creds; + grpc_call_credentials *call_creds; +} grpc_composite_channel_credentials; + /* -- Jwt credentials -- */ typedef struct { - grpc_credentials base; + grpc_call_credentials base; /* Have a simple cache for now with just 1 entry. We could have a map based on the service_url for a more sophisticated one. */ @@ -283,7 +315,7 @@ typedef void (*grpc_fetch_oauth2_func)(grpc_exec_ctx *exec_ctx, gpr_timespec deadline); typedef struct { - grpc_credentials base; + grpc_call_credentials base; gpr_mu mu; grpc_credentials_md_store *access_token_md; gpr_timespec token_expiration; @@ -301,14 +333,14 @@ typedef struct { /* -- Oauth2 Access Token credentials. -- */ typedef struct { - grpc_credentials base; + grpc_call_credentials base; grpc_credentials_md_store *access_token_md; } grpc_access_token_credentials; /* -- Metadata-only Test credentials. -- */ typedef struct { - grpc_credentials base; + grpc_call_credentials base; grpc_credentials_md_store *md_store; int is_async; } grpc_md_only_test_credentials; @@ -316,22 +348,21 @@ typedef struct { /* -- GoogleIAM credentials. -- */ typedef struct { - grpc_credentials base; + grpc_call_credentials base; grpc_credentials_md_store *iam_md; } grpc_google_iam_credentials; /* -- Composite credentials. -- */ typedef struct { - grpc_credentials base; - grpc_credentials_array inner; - grpc_credentials *connector_creds; -} grpc_composite_credentials; + grpc_call_credentials base; + grpc_call_credentials_array inner; +} grpc_composite_call_credentials; /* -- Plugin credentials. -- */ typedef struct { - grpc_credentials base; + grpc_call_credentials base; grpc_metadata_credentials_plugin plugin; grpc_credentials_md_store *plugin_md; } grpc_plugin_credentials; diff --git a/src/core/security/google_default_credentials.c b/src/core/security/google_default_credentials.c index 45135305b2..6a54fe4e47 100644 --- a/src/core/security/google_default_credentials.c +++ b/src/core/security/google_default_credentials.c @@ -50,7 +50,7 @@ /* -- Default credentials. -- */ -static grpc_credentials *default_credentials = NULL; +static grpc_channel_credentials *default_credentials = NULL; static int compute_engine_detection_done = 0; static gpr_mu g_mu; static gpr_once g_once = GPR_ONCE_INIT; @@ -138,11 +138,11 @@ static int is_stack_running_on_compute_engine(void) { } /* Takes ownership of creds_path if not NULL. */ -static grpc_credentials *create_default_creds_from_path(char *creds_path) { +static grpc_call_credentials *create_default_creds_from_path(char *creds_path) { grpc_json *json = NULL; grpc_auth_json_key key; grpc_auth_refresh_token token; - grpc_credentials *result = NULL; + grpc_call_credentials *result = NULL; gpr_slice creds_data = gpr_empty_slice(); int file_ok = 0; if (creds_path == NULL) goto end; @@ -176,9 +176,9 @@ end: return result; } -grpc_credentials *grpc_google_default_credentials_create(void) { - grpc_credentials *result = NULL; - int serving_cached_credentials = 0; +grpc_channel_credentials *grpc_google_default_credentials_create(void) { + grpc_channel_credentials *result = NULL; + grpc_call_credentials *call_creds = NULL; GRPC_API_TRACE("grpc_google_default_credentials_create(void)", 0, ()); @@ -187,20 +187,19 @@ grpc_credentials *grpc_google_default_credentials_create(void) { gpr_mu_lock(&g_mu); if (default_credentials != NULL) { - result = grpc_credentials_ref(default_credentials); - serving_cached_credentials = 1; + result = grpc_channel_credentials_ref(default_credentials); goto end; } /* First, try the environment variable. */ - result = create_default_creds_from_path( + call_creds = create_default_creds_from_path( gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR)); - if (result != NULL) goto end; + if (call_creds != NULL) goto end; /* Then the well-known file. */ - result = create_default_creds_from_path( + call_creds = create_default_creds_from_path( grpc_get_well_known_google_credentials_file_path()); - if (result != NULL) goto end; + if (call_creds != NULL) goto end; /* At last try to see if we're on compute engine (do the detection only once since it requires a network test). */ @@ -208,21 +207,28 @@ grpc_credentials *grpc_google_default_credentials_create(void) { int need_compute_engine_creds = is_stack_running_on_compute_engine(); compute_engine_detection_done = 1; if (need_compute_engine_creds) { - result = grpc_google_compute_engine_credentials_create(NULL); + call_creds = grpc_google_compute_engine_credentials_create(NULL); } } end: - if (!serving_cached_credentials && result != NULL) { - /* Blend with default ssl credentials and add a global reference so that it - can be cached and re-served. */ - grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL, NULL); - default_credentials = grpc_credentials_ref( - grpc_composite_credentials_create(ssl_creds, result, NULL)); - GPR_ASSERT(default_credentials != NULL); - grpc_credentials_unref(ssl_creds); - grpc_credentials_unref(result); - result = default_credentials; + if (result == NULL) { + if (call_creds != NULL) { + /* Blend with default ssl credentials and add a global reference so that + it + can be cached and re-served. */ + grpc_channel_credentials *ssl_creds = + grpc_ssl_credentials_create(NULL, NULL, NULL); + default_credentials = grpc_channel_credentials_ref( + grpc_composite_channel_credentials_create(ssl_creds, call_creds, + NULL)); + GPR_ASSERT(default_credentials != NULL); + grpc_channel_credentials_unref(ssl_creds); + grpc_call_credentials_unref(call_creds); + result = default_credentials; + } else { + gpr_log(GPR_ERROR, "Could not create google default credentials."); + } } gpr_mu_unlock(&g_mu); return result; @@ -232,7 +238,7 @@ void grpc_flush_cached_google_default_credentials(void) { gpr_once_init(&g_once, init_default_credentials); gpr_mu_lock(&g_mu); if (default_credentials != NULL) { - grpc_credentials_unref(default_credentials); + grpc_channel_credentials_unref(default_credentials); default_credentials = NULL; } gpr_mu_unlock(&g_mu); diff --git a/src/core/security/security_connector.c b/src/core/security/security_connector.c index 7c4cf6f04d..3c54a4deae 100644 --- a/src/core/security/security_connector.c +++ b/src/core/security/security_connector.c @@ -203,16 +203,6 @@ grpc_security_connector *grpc_find_security_connector_in_args( return NULL; } -static int check_request_metadata_creds(grpc_credentials *creds) { - if (creds != NULL && !grpc_credentials_has_request_metadata(creds)) { - gpr_log(GPR_ERROR, - "Incompatible credentials for channel security connector: needs to " - "set request metadata."); - return 0; - } - return 1; -} - /* -- Fake implementation. -- */ typedef struct { @@ -222,7 +212,7 @@ typedef struct { static void fake_channel_destroy(grpc_security_connector *sc) { grpc_channel_security_connector *c = (grpc_channel_security_connector *)sc; - grpc_credentials_unref(c->request_metadata_creds); + grpc_call_credentials_unref(c->request_metadata_creds); GRPC_AUTH_CONTEXT_UNREF(sc->auth_context, "connector"); gpr_free(sc); } @@ -306,7 +296,8 @@ static grpc_security_connector_vtable fake_server_vtable = { fake_server_destroy, fake_server_do_handshake, fake_check_peer}; grpc_channel_security_connector *grpc_fake_channel_security_connector_create( - grpc_credentials *request_metadata_creds, int call_host_check_is_async) { + grpc_call_credentials *request_metadata_creds, + int call_host_check_is_async) { grpc_fake_channel_security_connector *c = gpr_malloc(sizeof(grpc_fake_channel_security_connector)); memset(c, 0, sizeof(grpc_fake_channel_security_connector)); @@ -314,8 +305,8 @@ grpc_channel_security_connector *grpc_fake_channel_security_connector_create( c->base.base.is_client_side = 1; c->base.base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME; c->base.base.vtable = &fake_channel_vtable; - GPR_ASSERT(check_request_metadata_creds(request_metadata_creds)); - c->base.request_metadata_creds = grpc_credentials_ref(request_metadata_creds); + c->base.request_metadata_creds = + grpc_call_credentials_ref(request_metadata_creds); c->base.check_call_host = fake_channel_check_call_host; c->call_host_check_is_async = call_host_check_is_async; return &c->base; @@ -349,7 +340,7 @@ typedef struct { static void ssl_channel_destroy(grpc_security_connector *sc) { grpc_ssl_channel_security_connector *c = (grpc_ssl_channel_security_connector *)sc; - grpc_credentials_unref(c->base.request_metadata_creds); + grpc_call_credentials_unref(c->base.request_metadata_creds); if (c->handshaker_factory != NULL) { tsi_ssl_handshaker_factory_destroy(c->handshaker_factory); } @@ -580,9 +571,9 @@ size_t grpc_get_default_ssl_roots(const unsigned char **pem_root_certs) { } grpc_security_status grpc_ssl_channel_security_connector_create( - grpc_credentials *request_metadata_creds, const grpc_ssl_config *config, - const char *target_name, const char *overridden_target_name, - grpc_channel_security_connector **sc) { + grpc_call_credentials *request_metadata_creds, + const grpc_ssl_config *config, const char *target_name, + const char *overridden_target_name, grpc_channel_security_connector **sc) { size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions(); const unsigned char **alpn_protocol_strings = gpr_malloc(sizeof(const char *) * num_alpn_protocols); @@ -606,9 +597,6 @@ grpc_security_status grpc_ssl_channel_security_connector_create( gpr_log(GPR_ERROR, "An ssl channel needs a config and a target name."); goto error; } - if (!check_request_metadata_creds(request_metadata_creds)) { - goto error; - } if (config->pem_root_certs == NULL) { pem_root_certs_size = grpc_get_default_ssl_roots(&pem_root_certs); if (pem_root_certs == NULL || pem_root_certs_size == 0) { @@ -627,7 +615,8 @@ grpc_security_status grpc_ssl_channel_security_connector_create( c->base.base.vtable = &ssl_channel_vtable; c->base.base.is_client_side = 1; c->base.base.url_scheme = GRPC_SSL_URL_SCHEME; - c->base.request_metadata_creds = grpc_credentials_ref(request_metadata_creds); + c->base.request_metadata_creds = + grpc_call_credentials_ref(request_metadata_creds); c->base.check_call_host = ssl_channel_check_call_host; gpr_split_host_port(target_name, &c->target_name, &port); gpr_free(port); diff --git a/src/core/security/security_connector.h b/src/core/security/security_connector.h index 9218a3caab..c5f00c5563 100644 --- a/src/core/security/security_connector.h +++ b/src/core/security/security_connector.h @@ -145,7 +145,7 @@ typedef struct grpc_channel_security_connector grpc_channel_security_connector; struct grpc_channel_security_connector { grpc_security_connector base; /* requires is_client_side to be non 0. */ - grpc_credentials *request_metadata_creds; + grpc_call_credentials *request_metadata_creds; grpc_security_status (*check_call_host)(grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc, const char *host, @@ -167,7 +167,8 @@ grpc_security_status grpc_channel_security_connector_check_call_host( /* For TESTING ONLY! Creates a fake connector that emulates real channel security. */ grpc_channel_security_connector *grpc_fake_channel_security_connector_create( - grpc_credentials *request_metadata_creds, int call_host_check_is_async); + grpc_call_credentials *request_metadata_creds, + int call_host_check_is_async); /* For TESTING ONLY! Creates a fake connector that emulates real server security. */ @@ -197,9 +198,9 @@ typedef struct { specific error code otherwise. */ grpc_security_status grpc_ssl_channel_security_connector_create( - grpc_credentials *request_metadata_creds, const grpc_ssl_config *config, - const char *target_name, const char *overridden_target_name, - grpc_channel_security_connector **sc); + grpc_call_credentials *request_metadata_creds, + const grpc_ssl_config *config, const char *target_name, + const char *overridden_target_name, grpc_channel_security_connector **sc); /* Gets the default ssl roots. */ size_t grpc_get_default_ssl_roots(const unsigned char **pem_root_certs); diff --git a/src/core/security/security_context.c b/src/core/security/security_context.c index ff3ad64d92..2068c97d78 100644 --- a/src/core/security/security_context.c +++ b/src/core/security/security_context.c @@ -46,7 +46,7 @@ /* --- grpc_call --- */ grpc_call_error grpc_call_set_credentials(grpc_call *call, - grpc_credentials *creds) { + grpc_call_credentials *creds) { grpc_client_security_context *ctx = NULL; GRPC_API_TRACE("grpc_call_set_credentials(call=%p, creds=%p)", 2, (call, creds)); @@ -54,20 +54,16 @@ grpc_call_error grpc_call_set_credentials(grpc_call *call, gpr_log(GPR_ERROR, "Method is client-side only."); return GRPC_CALL_ERROR_NOT_ON_SERVER; } - if (creds != NULL && !grpc_credentials_has_request_metadata_only(creds)) { - gpr_log(GPR_ERROR, "Incompatible credentials to set on a call."); - return GRPC_CALL_ERROR; - } ctx = (grpc_client_security_context *)grpc_call_context_get( call, GRPC_CONTEXT_SECURITY); if (ctx == NULL) { ctx = grpc_client_security_context_create(); - ctx->creds = grpc_credentials_ref(creds); + ctx->creds = grpc_call_credentials_ref(creds); grpc_call_context_set(call, GRPC_CONTEXT_SECURITY, ctx, grpc_client_security_context_destroy); } else { - grpc_credentials_unref(ctx->creds); - ctx->creds = grpc_credentials_ref(creds); + grpc_call_credentials_unref(ctx->creds); + ctx->creds = grpc_call_credentials_ref(creds); } return GRPC_CALL_OK; } @@ -101,7 +97,7 @@ grpc_client_security_context *grpc_client_security_context_create(void) { void grpc_client_security_context_destroy(void *ctx) { grpc_client_security_context *c = (grpc_client_security_context *)ctx; - grpc_credentials_unref(c->creds); + grpc_call_credentials_unref(c->creds); GRPC_AUTH_CONTEXT_UNREF(c->auth_context, "client_security_context"); gpr_free(ctx); } diff --git a/src/core/security/security_context.h b/src/core/security/security_context.h index 2bbdc4be97..794258edbc 100644 --- a/src/core/security/security_context.h +++ b/src/core/security/security_context.h @@ -85,7 +85,7 @@ void grpc_auth_property_reset(grpc_auth_property *property); Internal client-side security context. */ typedef struct { - grpc_credentials *creds; + grpc_call_credentials *creds; grpc_auth_context *auth_context; } grpc_client_security_context; diff --git a/src/core/security/server_secure_chttp2.c b/src/core/security/server_secure_chttp2.c index 851e0cfab3..1ea269bf8f 100644 --- a/src/core/security/server_secure_chttp2.c +++ b/src/core/security/server_secure_chttp2.c @@ -249,9 +249,11 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr, } for (i = 0; i < resolved->naddrs; i++) { - port_temp = grpc_tcp_server_add_port( + grpc_tcp_listener *listener; + listener = grpc_tcp_server_add_port( tcp, (struct sockaddr *)&resolved->addrs[i].addr, resolved->addrs[i].len); + port_temp = grpc_tcp_listener_get_port(listener); if (port_temp >= 0) { if (port_num == -1) { port_num = port_temp; diff --git a/src/core/support/slice_buffer.c b/src/core/support/slice_buffer.c index 17c0b6c0f6..856d3a2439 100644 --- a/src/core/support/slice_buffer.c +++ b/src/core/support/slice_buffer.c @@ -220,7 +220,7 @@ void gpr_slice_buffer_move_first(gpr_slice_buffer *src, size_t n, return; } src_idx = 0; - for (;;) { + while (src_idx < src->capacity) { gpr_slice slice = src->slices[src_idx]; size_t slice_len = GPR_SLICE_LENGTH(slice); if (n > slice_len) { diff --git a/src/core/support/time_win32.c b/src/core/support/time_win32.c index bc0586d069..623a8d9233 100644 --- a/src/core/support/time_win32.c +++ b/src/core/support/time_win32.c @@ -66,14 +66,12 @@ gpr_timespec gpr_now(gpr_clock_type clock) { now_tv.tv_nsec = now_tb.millitm * 1000000; break; case GPR_CLOCK_MONOTONIC: + case GPR_CLOCK_PRECISE: QueryPerformanceCounter(×tamp); now_dbl = (timestamp.QuadPart - g_start_time.QuadPart) * g_time_scale; now_tv.tv_sec = (time_t)now_dbl; now_tv.tv_nsec = (int)((now_dbl - (double)now_tv.tv_sec) * 1e9); break; - case GPR_CLOCK_PRECISE: - gpr_precise_clock_now(&now_tv); - break; } return now_tv; } diff --git a/src/core/surface/byte_buffer_reader.c b/src/core/surface/byte_buffer_reader.c index 9f830df68c..57417f41b0 100644 --- a/src/core/surface/byte_buffer_reader.c +++ b/src/core/surface/byte_buffer_reader.c @@ -121,4 +121,3 @@ gpr_slice grpc_byte_buffer_reader_readall(grpc_byte_buffer_reader *reader) { } return out_slice; } - diff --git a/src/core/surface/call.c b/src/core/surface/call.c index aa435d44d3..86d5fca388 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -922,7 +922,8 @@ static batch_control *allocate_batch_control(grpc_call *call) { size_t i; for (i = 0; i < MAX_CONCURRENT_BATCHES; i++) { if ((call->used_batches & (1 << i)) == 0) { - call->used_batches |= (gpr_uint8)(1 << i); + call->used_batches = + (gpr_uint8)(call->used_batches | (gpr_uint8)(1 << i)); return &call->active_batches[i]; } } diff --git a/src/core/surface/secure_channel_create.c b/src/core/surface/secure_channel_create.c index 1282ee99ed..0dd0a31169 100644 --- a/src/core/surface/secure_channel_create.c +++ b/src/core/surface/secure_channel_create.c @@ -230,7 +230,7 @@ static const grpc_subchannel_factory_vtable subchannel_factory_vtable = { Asynchronously: - resolve target - connect to it (trying alternatives as presented) - perform handshakes */ -grpc_channel *grpc_secure_channel_create(grpc_credentials *creds, +grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds, const char *target, const grpc_channel_args *args, void *reserved) { @@ -261,9 +261,9 @@ grpc_channel *grpc_secure_channel_create(grpc_credentials *creds, "Security connector exists in channel args."); } - if (grpc_credentials_create_security_connector( - creds, target, args, NULL, &security_connector, - &new_args_from_connector) != GRPC_SECURITY_OK) { + if (grpc_channel_credentials_create_security_connector( + creds, target, args, &security_connector, &new_args_from_connector) != + GRPC_SECURITY_OK) { grpc_exec_ctx_finish(&exec_ctx); return grpc_lame_client_channel_create( target, GRPC_STATUS_INVALID_ARGUMENT, diff --git a/src/core/surface/server_chttp2.c b/src/core/surface/server_chttp2.c index 580b91573c..1408f9c159 100644 --- a/src/core/surface/server_chttp2.c +++ b/src/core/surface/server_chttp2.c @@ -107,9 +107,11 @@ int grpc_server_add_insecure_http2_port(grpc_server *server, const char *addr) { } for (i = 0; i < resolved->naddrs; i++) { - port_temp = grpc_tcp_server_add_port( + grpc_tcp_listener *listener; + listener = grpc_tcp_server_add_port( tcp, (struct sockaddr *)&resolved->addrs[i].addr, resolved->addrs[i].len); + port_temp = grpc_tcp_listener_get_port(listener); if (port_temp >= 0) { if (port_num == -1) { port_num = port_temp; diff --git a/src/core/surface/version.c b/src/core/surface/version.c index e559d51448..962a72112a 100644 --- a/src/core/surface/version.c +++ b/src/core/surface/version.c @@ -36,4 +36,4 @@ #include <grpc/grpc.h> -const char *grpc_version_string(void) { return "0.11.0.0"; } +const char *grpc_version_string(void) { return "0.12.0.0"; } diff --git a/src/core/transport/chttp2/hpack_encoder.c b/src/core/transport/chttp2/hpack_encoder.c index 6c7c00b7c3..758babc3d0 100644 --- a/src/core/transport/chttp2/hpack_encoder.c +++ b/src/core/transport/chttp2/hpack_encoder.c @@ -36,8 +36,10 @@ #include <assert.h> #include <string.h> +#include <grpc/support/alloc.h> #include <grpc/support/log.h> #include <grpc/support/useful.h> + #include "src/core/transport/chttp2/bin_encoder.h" #include "src/core/transport/chttp2/hpack_table.h" #include "src/core/transport/chttp2/timeout_encoding.h" @@ -154,6 +156,18 @@ static gpr_uint8 *add_tiny_header_data(framer_state *st, size_t len) { return gpr_slice_buffer_tiny_add(st->output, len); } +static void evict_entry(grpc_chttp2_hpack_compressor *c) { + c->tail_remote_index++; + GPR_ASSERT(c->tail_remote_index > 0); + GPR_ASSERT(c->table_size >= + c->table_elem_size[c->tail_remote_index % c->cap_table_elems]); + GPR_ASSERT(c->table_elems > 0); + c->table_size = (gpr_uint16)( + c->table_size - + c->table_elem_size[c->tail_remote_index % c->cap_table_elems]); + c->table_elems--; +} + /* add an element to the decoder table */ static void add_elem(grpc_chttp2_hpack_compressor *c, grpc_mdelem *elem) { gpr_uint32 key_hash = elem->key->hash; @@ -164,26 +178,21 @@ static void add_elem(grpc_chttp2_hpack_compressor *c, grpc_mdelem *elem) { GPR_ASSERT(elem_size < 65536); + if (elem_size > c->max_table_size) { + while (c->table_size > 0) { + evict_entry(c); + } + return; + } + /* Reserve space for this element in the remote table: if this overflows the current table, drop elements until it fits, matching the decompressor algorithm */ - /* TODO(ctiller): constant */ - while (c->table_size + elem_size > 4096) { - c->tail_remote_index++; - GPR_ASSERT(c->tail_remote_index > 0); - GPR_ASSERT(c->table_size >= - c->table_elem_size[c->tail_remote_index % - GRPC_CHTTP2_HPACKC_MAX_TABLE_ELEMS]); - GPR_ASSERT(c->table_elems > 0); - c->table_size = - (gpr_uint16)(c->table_size - - c->table_elem_size[c->tail_remote_index % - GRPC_CHTTP2_HPACKC_MAX_TABLE_ELEMS]); - c->table_elems--; + while (c->table_size + elem_size > c->max_table_size) { + evict_entry(c); } - GPR_ASSERT(c->table_elems < GRPC_CHTTP2_HPACKC_MAX_TABLE_ELEMS); - c->table_elem_size[new_index % GRPC_CHTTP2_HPACKC_MAX_TABLE_ELEMS] = - (gpr_uint16)elem_size; + GPR_ASSERT(c->table_elems < c->max_table_size); + c->table_elem_size[new_index % c->cap_table_elems] = (gpr_uint16)elem_size; c->table_size = (gpr_uint16)(c->table_size + elem_size); c->table_elems++; @@ -329,6 +338,14 @@ static void emit_lithdr_noidx_v(grpc_chttp2_hpack_compressor *c, add_header_data(st, gpr_slice_ref(value_slice)); } +static void emit_advertise_table_size_change(grpc_chttp2_hpack_compressor *c, + framer_state *st) { + gpr_uint32 len = GRPC_CHTTP2_VARINT_LENGTH(c->max_table_size, 3); + GRPC_CHTTP2_WRITE_VARINT(c->max_table_size, 3, 0x20, + add_tiny_header_data(st, len), len); + c->advertise_table_size_change = 0; +} + static gpr_uint32 dynidx(grpc_chttp2_hpack_compressor *c, gpr_uint32 elem_index) { return 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY + c->tail_remote_index + @@ -447,11 +464,23 @@ gpr_slice grpc_chttp2_data_frame_create_empty_close(gpr_uint32 id) { return slice; } +static gpr_uint32 elems_for_bytes(gpr_uint32 bytes) { + return (bytes + 31) / 32; +} + void grpc_chttp2_hpack_compressor_init(grpc_chttp2_hpack_compressor *c, grpc_mdctx *ctx) { memset(c, 0, sizeof(*c)); c->mdctx = ctx; c->timeout_key_str = grpc_mdstr_from_string(ctx, "grpc-timeout"); + c->max_table_size = GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE; + c->cap_table_elems = elems_for_bytes(c->max_table_size); + c->max_table_elems = c->cap_table_elems; + c->max_usable_size = GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE; + c->table_elem_size = + gpr_malloc(sizeof(*c->table_elem_size) * c->cap_table_elems); + memset(c->table_elem_size, 0, + sizeof(*c->table_elem_size) * c->cap_table_elems); } void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor *c) { @@ -461,6 +490,54 @@ void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor *c) { if (c->entries_elems[i]) GRPC_MDELEM_UNREF(c->entries_elems[i]); } GRPC_MDSTR_UNREF(c->timeout_key_str); + gpr_free(c->table_elem_size); +} + +void grpc_chttp2_hpack_compressor_set_max_usable_size( + grpc_chttp2_hpack_compressor *c, gpr_uint32 max_table_size) { + c->max_usable_size = max_table_size; + grpc_chttp2_hpack_compressor_set_max_table_size( + c, GPR_MIN(c->max_table_size, max_table_size)); +} + +static void rebuild_elems(grpc_chttp2_hpack_compressor *c, gpr_uint32 new_cap) { + gpr_uint16 *table_elem_size = gpr_malloc(sizeof(*table_elem_size) * new_cap); + gpr_uint32 i; + + memset(table_elem_size, 0, sizeof(*table_elem_size) * new_cap); + GPR_ASSERT(c->table_elems <= new_cap); + + for (i = 0; i < c->table_elems; i++) { + gpr_uint32 ofs = c->tail_remote_index + i + 1; + table_elem_size[ofs % new_cap] = c->table_elem_size[ofs % c->cap_table_elems]; + } + + c->cap_table_elems = new_cap; + gpr_free(c->table_elem_size); + c->table_elem_size = table_elem_size; +} + +void grpc_chttp2_hpack_compressor_set_max_table_size( + grpc_chttp2_hpack_compressor *c, gpr_uint32 max_table_size) { + max_table_size = GPR_MIN(max_table_size, c->max_usable_size); + if (max_table_size == c->max_table_size) { + return; + } + while (c->table_size > 0 && c->table_size > max_table_size) { + evict_entry(c); + } + c->max_table_size = max_table_size; + c->max_table_elems = elems_for_bytes(max_table_size); + if (c->max_table_elems > c->cap_table_elems) { + rebuild_elems(c, GPR_MAX(c->max_table_elems, 2 * c->cap_table_elems)); + } else if (c->max_table_elems < c->cap_table_elems / 3) { + gpr_uint32 new_cap = GPR_MAX(c->max_table_elems, 16); + if (new_cap != c->cap_table_elems) { + rebuild_elems(c, new_cap); + } + } + c->advertise_table_size_change = 1; + gpr_log(GPR_DEBUG, "set max table size from encoder to %d", max_table_size); } void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor *c, @@ -483,6 +560,9 @@ void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor *c, slot. THIS MAY NOT BE THE SAME ELEMENT (if a decoder table slot got updated). After this loop, we'll do a batch unref of elements. */ begin_frame(&st); + if (c->advertise_table_size_change != 0) { + emit_advertise_table_size_change(c, &st); + } grpc_metadata_batch_assert_ok(metadata); for (l = metadata->list.head; l; l = l->next) { hpack_enc(c, l->md, &st); diff --git a/src/core/transport/chttp2/hpack_encoder.h b/src/core/transport/chttp2/hpack_encoder.h index 59b122dfda..ce83d101f2 100644 --- a/src/core/transport/chttp2/hpack_encoder.h +++ b/src/core/transport/chttp2/hpack_encoder.h @@ -43,14 +43,26 @@ #define GRPC_CHTTP2_HPACKC_NUM_FILTERS 256 #define GRPC_CHTTP2_HPACKC_NUM_VALUES 256 -#define GRPC_CHTTP2_HPACKC_MAX_TABLE_ELEMS (4096 / 32) +/* initial table size, per spec */ +#define GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE 4096 +/* maximum table size we'll actually use */ +#define GRPC_CHTTP2_HPACKC_MAX_TABLE_SIZE (1024 * 1024) typedef struct { gpr_uint32 filter_elems_sum; + gpr_uint32 max_table_size; + gpr_uint32 max_table_elems; + gpr_uint32 cap_table_elems; + /** if non-zero, advertise to the decoder that we'll start using a table + of this size */ + gpr_uint8 advertise_table_size_change; + /** maximum number of bytes we'll use for the decode table (to guard against + peers ooming us by setting decode table size high) */ + gpr_uint32 max_usable_size; /* one before the lowest usable table index */ gpr_uint32 tail_remote_index; - gpr_uint16 table_size; - gpr_uint16 table_elems; + gpr_uint32 table_size; + gpr_uint32 table_elems; /* filter tables for elems: this tables provides an approximate popularity count for particular hashes, and are used to determine whether @@ -71,12 +83,16 @@ typedef struct { gpr_uint32 indices_keys[GRPC_CHTTP2_HPACKC_NUM_VALUES]; gpr_uint32 indices_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES]; - gpr_uint16 table_elem_size[GRPC_CHTTP2_HPACKC_MAX_TABLE_ELEMS]; + gpr_uint16 *table_elem_size; } grpc_chttp2_hpack_compressor; void grpc_chttp2_hpack_compressor_init(grpc_chttp2_hpack_compressor *c, grpc_mdctx *mdctx); void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor *c); +void grpc_chttp2_hpack_compressor_set_max_table_size( + grpc_chttp2_hpack_compressor *c, gpr_uint32 max_table_size); +void grpc_chttp2_hpack_compressor_set_max_usable_size( + grpc_chttp2_hpack_compressor *c, gpr_uint32 max_table_size); void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor *c, gpr_uint32 id, grpc_metadata_batch *metadata, int is_eof, diff --git a/src/core/transport/chttp2/hpack_parser.c b/src/core/transport/chttp2/hpack_parser.c index 6eebfc3ce4..57a3a20b1d 100644 --- a/src/core/transport/chttp2/hpack_parser.c +++ b/src/core/transport/chttp2/hpack_parser.c @@ -74,6 +74,8 @@ static int parse_begin(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur, const gpr_uint8 *end); static int parse_error(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur, const gpr_uint8 *end); +static int parse_illegal_op(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur, + const gpr_uint8 *end); static int parse_string_prefix(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur, const gpr_uint8 *end); @@ -156,7 +158,7 @@ static const grpc_chttp2_hpack_parser_state first_byte_action[] = { parse_lithdr_incidx_x, parse_lithdr_incidx_v, parse_lithdr_notidx, parse_lithdr_notidx_x, parse_lithdr_notidx_v, parse_lithdr_nvridx, parse_lithdr_nvridx_x, parse_lithdr_nvridx_v, parse_max_tbl_size, - parse_max_tbl_size_x, parse_error}; + parse_max_tbl_size_x, parse_illegal_op}; /* indexes the first byte to a parse state function - generated by gen_hpack_tables.c */ @@ -169,7 +171,7 @@ static const gpr_uint8 first_byte_lut[256] = { LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX_X, - ILLEGAL, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, + MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, @@ -622,13 +624,15 @@ static const gpr_uint8 inverse_base64[256] = { }; /* emission helpers */ -static void on_hdr(grpc_chttp2_hpack_parser *p, grpc_mdelem *md, - int add_to_table) { +static int on_hdr(grpc_chttp2_hpack_parser *p, grpc_mdelem *md, + int add_to_table) { if (add_to_table) { - GRPC_MDELEM_REF(md); - grpc_chttp2_hptbl_add(&p->table, md); + if (!grpc_chttp2_hptbl_add(&p->table, md)) { + return 0; + } } p->on_header(p->on_header_user_data, md); + return 1; } static grpc_mdstr *take_string(grpc_chttp2_hpack_parser *p, @@ -714,9 +718,12 @@ static int parse_stream_dep0(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur, static int finish_indexed_field(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur, const gpr_uint8 *end) { grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index); + if (md == NULL) { + gpr_log(GPR_ERROR, "Invalid HPACK index received: %d", p->index); + return 0; + } GRPC_MDELEM_REF(md); - on_hdr(p, md, 0); - return parse_begin(p, cur, end); + return on_hdr(p, md, 0) && parse_begin(p, cur, end); } /* parse an indexed field with index < 127 */ @@ -742,21 +749,21 @@ static int parse_indexed_field_x(grpc_chttp2_hpack_parser *p, static int finish_lithdr_incidx(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur, const gpr_uint8 *end) { grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index); - on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx, - GRPC_MDSTR_REF(md->key), - take_string(p, &p->value)), - 1); - return parse_begin(p, cur, end); + return on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx, + GRPC_MDSTR_REF(md->key), + take_string(p, &p->value)), + 1) && + parse_begin(p, cur, end); } /* finish a literal header with incremental indexing with no index */ static int finish_lithdr_incidx_v(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur, const gpr_uint8 *end) { - on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx, - take_string(p, &p->key), - take_string(p, &p->value)), - 1); - return parse_begin(p, cur, end); + return on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx, + take_string(p, &p->key), + take_string(p, &p->value)), + 1) && + parse_begin(p, cur, end); } /* parse a literal header with incremental indexing; index < 63 */ @@ -795,21 +802,21 @@ static int parse_lithdr_incidx_v(grpc_chttp2_hpack_parser *p, static int finish_lithdr_notidx(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur, const gpr_uint8 *end) { grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index); - on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx, - GRPC_MDSTR_REF(md->key), - take_string(p, &p->value)), - 0); - return parse_begin(p, cur, end); + return on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx, + GRPC_MDSTR_REF(md->key), + take_string(p, &p->value)), + 0) && + parse_begin(p, cur, end); } /* finish a literal header without incremental indexing with index = 0 */ static int finish_lithdr_notidx_v(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur, const gpr_uint8 *end) { - on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx, - take_string(p, &p->key), - take_string(p, &p->value)), - 0); - return parse_begin(p, cur, end); + return on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx, + take_string(p, &p->key), + take_string(p, &p->value)), + 0) && + parse_begin(p, cur, end); } /* parse a literal header without incremental indexing; index < 15 */ @@ -848,21 +855,21 @@ static int parse_lithdr_notidx_v(grpc_chttp2_hpack_parser *p, static int finish_lithdr_nvridx(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur, const gpr_uint8 *end) { grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index); - on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx, - GRPC_MDSTR_REF(md->key), - take_string(p, &p->value)), - 0); - return parse_begin(p, cur, end); + return on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx, + GRPC_MDSTR_REF(md->key), + take_string(p, &p->value)), + 0) && + parse_begin(p, cur, end); } /* finish a literal header that is never indexed with an extra value */ static int finish_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur, const gpr_uint8 *end) { - on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx, - take_string(p, &p->key), - take_string(p, &p->value)), - 0); - return parse_begin(p, cur, end); + return on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx, + take_string(p, &p->key), + take_string(p, &p->value)), + 0) && + parse_begin(p, cur, end); } /* parse a literal header that is never indexed; index < 15 */ @@ -901,14 +908,14 @@ static int parse_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p, static int finish_max_tbl_size(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur, const gpr_uint8 *end) { gpr_log(GPR_INFO, "MAX TABLE SIZE: %d", p->index); - abort(); /* not implemented */ - return parse_begin(p, cur, end); + return grpc_chttp2_hptbl_set_current_table_size(&p->table, p->index) && + parse_begin(p, cur, end); } /* parse a max table size change, max size < 15 */ static int parse_max_tbl_size(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur, const gpr_uint8 *end) { - p->index = (*cur) & 0xf; + p->index = (*cur) & 0x1f; return finish_max_tbl_size(p, cur + 1, end); } @@ -918,7 +925,7 @@ static int parse_max_tbl_size_x(grpc_chttp2_hpack_parser *p, static const grpc_chttp2_hpack_parser_state and_then[] = { finish_max_tbl_size}; p->next_state = and_then; - p->index = 0xf; + p->index = 0x1f; p->parsing.value = &p->index; return parse_value0(p, cur + 1, end); } @@ -930,6 +937,13 @@ static int parse_error(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur, return 0; } +static int parse_illegal_op(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur, + const gpr_uint8 *end) { + GPR_ASSERT(cur != end); + gpr_log(GPR_DEBUG, "Illegal hpack op code %d", *cur); + return parse_error(p, cur, end); +} + /* parse the 1st byte of a varint into p->parsing.value no overflow is possible */ static int parse_value0(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur, diff --git a/src/core/transport/chttp2/hpack_table.c b/src/core/transport/chttp2/hpack_table.c index c442c2c341..f2362b056c 100644 --- a/src/core/transport/chttp2/hpack_table.c +++ b/src/core/transport/chttp2/hpack_table.c @@ -36,7 +36,9 @@ #include <assert.h> #include <string.h> +#include <grpc/support/alloc.h> #include <grpc/support/log.h> + #include "src/core/support/murmur_hash.h" static struct { @@ -169,12 +171,22 @@ static struct { {"www-authenticate", ""}, }; +static gpr_uint32 entries_for_bytes(gpr_uint32 bytes) { + return (bytes + GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD - 1) / + GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD; +} + void grpc_chttp2_hptbl_init(grpc_chttp2_hptbl *tbl, grpc_mdctx *mdctx) { size_t i; memset(tbl, 0, sizeof(*tbl)); tbl->mdctx = mdctx; - tbl->max_bytes = GRPC_CHTTP2_INITIAL_HPACK_TABLE_SIZE; + tbl->current_table_bytes = tbl->max_bytes = + GRPC_CHTTP2_INITIAL_HPACK_TABLE_SIZE; + tbl->max_entries = tbl->cap_entries = + entries_for_bytes(tbl->current_table_bytes); + tbl->ents = gpr_malloc(sizeof(*tbl->ents) * tbl->cap_entries); + memset(tbl->ents, 0, sizeof(*tbl->ents) * tbl->cap_entries); for (i = 1; i <= GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) { tbl->static_ents[i - 1] = grpc_mdelem_from_strings( mdctx, static_table[i].key, static_table[i].value); @@ -187,9 +199,9 @@ void grpc_chttp2_hptbl_destroy(grpc_chttp2_hptbl *tbl) { GRPC_MDELEM_UNREF(tbl->static_ents[i]); } for (i = 0; i < tbl->num_ents; i++) { - GRPC_MDELEM_UNREF( - tbl->ents[(tbl->first_ent + i) % GRPC_CHTTP2_MAX_TABLE_COUNT]); + GRPC_MDELEM_UNREF(tbl->ents[(tbl->first_ent + i) % tbl->cap_entries]); } + gpr_free(tbl->ents); } grpc_mdelem *grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl, @@ -201,8 +213,8 @@ grpc_mdelem *grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl, /* Otherwise, find the value in the list of valid entries */ tbl_index -= (GRPC_CHTTP2_LAST_STATIC_ENTRY + 1); if (tbl_index < tbl->num_ents) { - gpr_uint32 offset = (tbl->num_ents - 1u - tbl_index + tbl->first_ent) % - GRPC_CHTTP2_MAX_TABLE_COUNT; + gpr_uint32 offset = + (tbl->num_ents - 1u - tbl_index + tbl->first_ent) % tbl->cap_entries; return tbl->ents[offset]; } /* Invalid entry: return error */ @@ -216,21 +228,81 @@ static void evict1(grpc_chttp2_hptbl *tbl) { GPR_SLICE_LENGTH(first_ent->value->slice) + GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD; GPR_ASSERT(elem_bytes <= tbl->mem_used); - tbl->mem_used = (gpr_uint16)(tbl->mem_used - elem_bytes); - tbl->first_ent = - (gpr_uint16)((tbl->first_ent + 1) % GRPC_CHTTP2_MAX_TABLE_COUNT); + tbl->mem_used -= (gpr_uint32)elem_bytes; + tbl->first_ent = ((tbl->first_ent + 1) % tbl->cap_entries); tbl->num_ents--; GRPC_MDELEM_UNREF(first_ent); } -void grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) { +static void rebuild_ents(grpc_chttp2_hptbl *tbl, gpr_uint32 new_cap) { + grpc_mdelem **ents = gpr_malloc(sizeof(*ents) * new_cap); + gpr_uint32 i; + + for (i = 0; i < tbl->num_ents; i++) { + ents[i] = tbl->ents[(tbl->first_ent + i) % tbl->cap_entries]; + } + gpr_free(tbl->ents); + tbl->ents = ents; + tbl->cap_entries = new_cap; + tbl->first_ent = 0; +} + +void grpc_chttp2_hptbl_set_max_bytes(grpc_chttp2_hptbl *tbl, + gpr_uint32 max_bytes) { + if (tbl->max_bytes == max_bytes) { + return; + } + gpr_log(GPR_DEBUG, "Update hpack parser max size to %d", max_bytes); + while (tbl->mem_used > max_bytes) { + evict1(tbl); + } + tbl->max_bytes = max_bytes; +} + +int grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl, + gpr_uint32 bytes) { + if (tbl->current_table_bytes == bytes) { + return 1; + } + if (bytes > tbl->max_bytes) { + gpr_log(GPR_ERROR, + "Attempt to make hpack table %d bytes when max is %d bytes", bytes, + tbl->max_bytes); + return 0; + } + gpr_log(GPR_DEBUG, "Update hpack parser table size to %d", bytes); + while (tbl->mem_used > bytes) { + evict1(tbl); + } + tbl->current_table_bytes = bytes; + tbl->max_entries = entries_for_bytes(bytes); + if (tbl->max_entries > tbl->cap_entries) { + rebuild_ents(tbl, GPR_MAX(tbl->max_entries, 2 * tbl->cap_entries)); + } else if (tbl->max_entries < tbl->cap_entries / 3) { + gpr_uint32 new_cap = GPR_MAX(tbl->max_entries, 16u); + if (new_cap != tbl->cap_entries) { + rebuild_ents(tbl, new_cap); + } + } + return 1; +} + +int grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) { /* determine how many bytes of buffer this entry represents */ size_t elem_bytes = GPR_SLICE_LENGTH(md->key->slice) + GPR_SLICE_LENGTH(md->value->slice) + GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD; + if (tbl->current_table_bytes > tbl->max_bytes) { + gpr_log(GPR_ERROR, + "HPACK max table size reduced to %d but not reflected by hpack " + "stream (still at %d)", + tbl->max_bytes, tbl->current_table_bytes); + return 0; + } + /* we can't add elements bigger than the max table size */ - if (elem_bytes > tbl->max_bytes) { + if (elem_bytes > tbl->current_table_bytes) { /* HPACK draft 10 section 4.4 states: * If the size of the new entry is less than or equal to the maximum * size, that entry is added to the table. It is not an error to @@ -243,44 +315,43 @@ void grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) { while (tbl->num_ents) { evict1(tbl); } - return; + return 1; } /* evict entries to ensure no overflow */ - while (elem_bytes > (size_t)tbl->max_bytes - tbl->mem_used) { + while (elem_bytes > (size_t)tbl->current_table_bytes - tbl->mem_used) { evict1(tbl); } /* copy the finalized entry in */ - tbl->ents[tbl->last_ent] = md; + tbl->ents[(tbl->first_ent + tbl->num_ents) % tbl->cap_entries] = + GRPC_MDELEM_REF(md); /* update accounting values */ - tbl->last_ent = - (gpr_uint16)((tbl->last_ent + 1) % GRPC_CHTTP2_MAX_TABLE_COUNT); tbl->num_ents++; - tbl->mem_used = (gpr_uint16)(tbl->mem_used + elem_bytes); + tbl->mem_used += (gpr_uint32)elem_bytes; + return 1; } grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find( const grpc_chttp2_hptbl *tbl, grpc_mdelem *md) { grpc_chttp2_hptbl_find_result r = {0, 0}; - gpr_uint16 i; + gpr_uint32 i; /* See if the string is in the static table */ for (i = 0; i < GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) { grpc_mdelem *ent = tbl->static_ents[i]; if (md->key != ent->key) continue; - r.index = (gpr_uint16)(i + 1); + r.index = i + 1u; r.has_value = md->value == ent->value; if (r.has_value) return r; } /* Scan the dynamic table */ for (i = 0; i < tbl->num_ents; i++) { - gpr_uint16 idx = - (gpr_uint16)(tbl->num_ents - i + GRPC_CHTTP2_LAST_STATIC_ENTRY); - grpc_mdelem *ent = - tbl->ents[(tbl->first_ent + i) % GRPC_CHTTP2_MAX_TABLE_COUNT]; + gpr_uint32 idx = + (gpr_uint32)(tbl->num_ents - i + GRPC_CHTTP2_LAST_STATIC_ENTRY); + grpc_mdelem *ent = tbl->ents[(tbl->first_ent + i) % tbl->cap_entries]; if (md->key != ent->key) continue; r.index = idx; r.has_value = md->value == ent->value; diff --git a/src/core/transport/chttp2/hpack_table.h b/src/core/transport/chttp2/hpack_table.h index 4f882e2e03..e03b8c19b3 100644 --- a/src/core/transport/chttp2/hpack_table.h +++ b/src/core/transport/chttp2/hpack_table.h @@ -49,47 +49,59 @@ #define GRPC_CHTTP2_MAX_HPACK_TABLE_SIZE GRPC_CHTTP2_INITIAL_HPACK_TABLE_SIZE /* Per entry overhead bytes as per the spec */ #define GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD 32 +#if 0 /* Maximum number of entries we could possibly fit in the table, given defined overheads */ #define GRPC_CHTTP2_MAX_TABLE_COUNT \ ((GRPC_CHTTP2_MAX_HPACK_TABLE_SIZE + GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD - 1) / \ GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD) +#endif /* hpack decoder table */ typedef struct { grpc_mdctx *mdctx; /* the first used entry in ents */ - gpr_uint16 first_ent; - /* the last used entry in ents */ - gpr_uint16 last_ent; + gpr_uint32 first_ent; /* how many entries are in the table */ - gpr_uint16 num_ents; + gpr_uint32 num_ents; /* the amount of memory used by the table, according to the hpack algorithm */ - gpr_uint16 mem_used; + gpr_uint32 mem_used; /* the max memory allowed to be used by the table, according to the hpack algorithm */ - gpr_uint16 max_bytes; + gpr_uint32 max_bytes; + /* the currently agreed size of the table, according to the hpack algorithm */ + gpr_uint32 current_table_bytes; + /* Maximum number of entries we could possibly fit in the table, given defined + overheads */ + gpr_uint32 max_entries; + /* Number of entries allocated in ents */ + gpr_uint32 cap_entries; /* a circular buffer of headers - this is stored in the opposite order to what hpack specifies, in order to simplify table management a little... meaning lookups need to SUBTRACT from the end position */ - grpc_mdelem *ents[GRPC_CHTTP2_MAX_TABLE_COUNT]; + grpc_mdelem **ents; grpc_mdelem *static_ents[GRPC_CHTTP2_LAST_STATIC_ENTRY]; } grpc_chttp2_hptbl; /* initialize a hpack table */ void grpc_chttp2_hptbl_init(grpc_chttp2_hptbl *tbl, grpc_mdctx *mdctx); void grpc_chttp2_hptbl_destroy(grpc_chttp2_hptbl *tbl); +void grpc_chttp2_hptbl_set_max_bytes(grpc_chttp2_hptbl *tbl, + gpr_uint32 max_bytes); +int grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl, + gpr_uint32 bytes); /* lookup a table entry based on its hpack index */ grpc_mdelem *grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl, gpr_uint32 index); /* add a table entry to the index */ -void grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md); +int grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, + grpc_mdelem *md) GRPC_MUST_USE_RESULT; /* Find a key/value pair in the table... returns the index in the table of the most similar entry, or 0 if the value was not found */ typedef struct { - gpr_uint16 index; - gpr_uint8 has_value; + gpr_uint32 index; + int has_value; } grpc_chttp2_hptbl_find_result; grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find( const grpc_chttp2_hptbl *tbl, grpc_mdelem *md); diff --git a/src/core/transport/chttp2/internal.h b/src/core/transport/chttp2/internal.h index 2d0cb4abdb..216439549c 100644 --- a/src/core/transport/chttp2/internal.h +++ b/src/core/transport/chttp2/internal.h @@ -227,6 +227,9 @@ struct grpc_chttp2_transport_parsing { /** was a goaway frame received? */ gpr_uint8 goaway_received; + /** the last sent max_table_size setting */ + gpr_uint32 last_sent_max_table_size; + /** initial window change */ gpr_int64 initial_window_update; @@ -483,7 +486,8 @@ struct grpc_chttp2_stream { /** Someone is unlocking the transport mutex: check to see if writes are required, and schedule them if so */ int grpc_chttp2_unlocking_check_writes(grpc_chttp2_transport_global *global, - grpc_chttp2_transport_writing *writing); + grpc_chttp2_transport_writing *writing, + int is_parsing); void grpc_chttp2_perform_writes( grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing, grpc_endpoint *endpoint); diff --git a/src/core/transport/chttp2/parsing.c b/src/core/transport/chttp2/parsing.c index 8cef8fbb77..1e06532c03 100644 --- a/src/core/transport/chttp2/parsing.c +++ b/src/core/transport/chttp2/parsing.c @@ -78,6 +78,9 @@ void grpc_chttp2_prepare_to_read( GPR_TIMER_BEGIN("grpc_chttp2_prepare_to_read", 0); transport_parsing->next_stream_id = transport_global->next_stream_id; + transport_parsing->last_sent_max_table_size = + transport_global->settings[GRPC_SENT_SETTINGS] + [GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]; /* update the parsing view of incoming window */ while (grpc_chttp2_list_pop_unannounced_incoming_window_available( @@ -127,6 +130,7 @@ void grpc_chttp2_publish_reads( transport_global->settings[GRPC_SENT_SETTINGS], GRPC_CHTTP2_NUM_SETTINGS * sizeof(gpr_uint32)); transport_parsing->settings_ack_received = 0; + transport_global->sent_local_settings = 0; } /* move goaway to the global state if we received one (it will be @@ -819,6 +823,9 @@ static int init_settings_frame_parser( } if (transport_parsing->incoming_frame_flags & GRPC_CHTTP2_FLAG_ACK) { transport_parsing->settings_ack_received = 1; + grpc_chttp2_hptbl_set_max_bytes( + &transport_parsing->hpack_parser.table, + transport_parsing->last_sent_max_table_size); } transport_parsing->parser = grpc_chttp2_settings_parser_parse; transport_parsing->parser_data = &transport_parsing->simple.settings; diff --git a/src/core/transport/chttp2/writing.c b/src/core/transport/chttp2/writing.c index 7fe5649e5e..805d05222d 100644 --- a/src/core/transport/chttp2/writing.c +++ b/src/core/transport/chttp2/writing.c @@ -45,7 +45,7 @@ static void finalize_outbuf(grpc_exec_ctx *exec_ctx, int grpc_chttp2_unlocking_check_writes( grpc_chttp2_transport_global *transport_global, - grpc_chttp2_transport_writing *transport_writing) { + grpc_chttp2_transport_writing *transport_writing, int is_parsing) { grpc_chttp2_stream_global *stream_global; grpc_chttp2_stream_writing *stream_writing; @@ -55,8 +55,13 @@ int grpc_chttp2_unlocking_check_writes( gpr_slice_buffer_swap(&transport_global->qbuf, &transport_writing->outbuf); GPR_ASSERT(transport_global->qbuf.count == 0); + grpc_chttp2_hpack_compressor_set_max_table_size( + &transport_writing->hpack_compressor, + transport_global->settings[GRPC_PEER_SETTINGS] + [GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]); + if (transport_global->dirtied_local_settings && - !transport_global->sent_local_settings) { + !transport_global->sent_local_settings && !is_parsing) { gpr_slice_buffer_add( &transport_writing->outbuf, grpc_chttp2_settings_create( diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index f62294c7c5..fdd835def9 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -338,6 +338,31 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, t->global.next_stream_id = (gpr_uint32)channel_args->args[i].value.integer; } + } else if (0 == strcmp(channel_args->args[i].key, + GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER)) { + if (channel_args->args[i].type != GRPC_ARG_INTEGER) { + gpr_log(GPR_ERROR, "%s: must be an integer", + GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER); + } else if (channel_args->args[i].value.integer < 0) { + gpr_log(GPR_DEBUG, "%s: must be non-negative", + GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER); + } else { + push_setting(t, GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE, + (gpr_uint32)channel_args->args[i].value.integer); + } + } else if (0 == strcmp(channel_args->args[i].key, + GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER)) { + if (channel_args->args[i].type != GRPC_ARG_INTEGER) { + gpr_log(GPR_ERROR, "%s: must be an integer", + GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER); + } else if (channel_args->args[i].value.integer < 0) { + gpr_log(GPR_DEBUG, "%s: must be non-negative", + GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER); + } else { + grpc_chttp2_hpack_compressor_set_max_usable_size( + &t->writing.hpack_compressor, + (gpr_uint32)channel_args->args[i].value.integer); + } } } } @@ -563,7 +588,8 @@ static void lock(grpc_chttp2_transport *t) { gpr_mu_lock(&t->mu); } static void unlock(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { GPR_TIMER_BEGIN("unlock", 0); if (!t->writing_active && !t->closed && - grpc_chttp2_unlocking_check_writes(&t->global, &t->writing)) { + grpc_chttp2_unlocking_check_writes(&t->global, &t->writing, + t->parsing_active)) { t->writing_active = 1; REF_TRANSPORT(t, "writing"); grpc_exec_ctx_enqueue(exec_ctx, &t->writing_action, 1); @@ -735,6 +761,8 @@ static int contains_non_ok_status( return 0; } +static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, int success) {} + static void perform_stream_op_locked( grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, grpc_chttp2_stream_global *stream_global, grpc_transport_stream_op *op) { @@ -743,6 +771,9 @@ static void perform_stream_op_locked( GPR_TIMER_BEGIN("perform_stream_op_locked", 0); on_complete = op->on_complete; + if (on_complete == NULL) { + on_complete = grpc_closure_create(do_nothing, NULL); + } /* use final_data as a barrier until enqueue time; the inital counter is dropped at the end of this function */ on_complete->final_data = 2; @@ -806,7 +837,7 @@ static void perform_stream_op_locked( } if (stream_global->write_closed) { grpc_chttp2_complete_closure_step( - exec_ctx, &stream_global->send_trailing_metadata_finished, + exec_ctx, &stream_global->send_trailing_metadata_finished, grpc_metadata_batch_is_empty(op->send_trailing_metadata)); } else if (stream_global->id != 0) { /* TODO(ctiller): check if there's flow control for any outstanding @@ -1033,7 +1064,8 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, to the upper layers - drop what we've got, and then publish what we want - which is safe because we haven't told anyone about the metadata yet */ - if (!stream_global->published_trailing_metadata || stream_global->recv_trailing_metadata_finished != NULL) { + if (!stream_global->published_trailing_metadata || + stream_global->recv_trailing_metadata_finished != NULL) { grpc_mdctx *mdctx = TRANSPORT_FROM_GLOBAL(transport_global)->metadata_context; char status_string[GPR_LTOA_MIN_BUFSIZE]; diff --git a/src/core/tsi/test_creds/server1.pem b/src/core/tsi/test_creds/server1.pem index 8e582e571f..f3d43fcc5b 100644 --- a/src/core/tsi/test_creds/server1.pem +++ b/src/core/tsi/test_creds/server1.pem @@ -1,16 +1,16 @@ -----BEGIN CERTIFICATE----- -MIICmzCCAgSgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJBVTET -MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ -dHkgTHRkMQ8wDQYDVQQDDAZ0ZXN0Y2EwHhcNMTQwNzIyMDYwMDU3WhcNMjQwNzE5 -MDYwMDU3WjBkMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV -BAcTB0NoaWNhZ28xFDASBgNVBAoTC0dvb2dsZSBJbmMuMRowGAYDVQQDFBEqLnRl -c3QuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4cMVJygs -JUmlgMMzgdi0h1XoCR7+ww1pop04OMMyy7H/i0PJ2W6Y35+b4CM8QrkYeEafUGDO -RYX6yV/cHGGsD/x02ye6ey1UDtkGAD/mpDEx8YCrjAc1Vfvt8Fk6Cn1WVIxV/J30 -3xjBsFgByQ55RBp1OLZfVLo6AleBDSbcxaECAwEAAaNrMGkwCQYDVR0TBAIwADAL -BgNVHQ8EBAMCBeAwTwYDVR0RBEgwRoIQKi50ZXN0Lmdvb2dsZS5mcoIYd2F0ZXJ6 -b29pLnRlc3QuZ29vZ2xlLmJlghIqLnRlc3QueW91dHViZS5jb22HBMCoAQMwDQYJ -KoZIhvcNAQEFBQADgYEAM2Ii0LgTGbJ1j4oqX9bxVcxm+/R5Yf8oi0aZqTJlnLYS -wXcBykxTx181s7WyfJ49WwrYXo78zTDAnf1ma0fPq3e4mpspvyndLh1a+OarHa1e -aT0DIIYk7qeEa1YcVljx2KyLd0r1BBAfrwyGaEPVeJQVYWaOJRU2we/KD4ojf9s= +MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET +MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ +dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx +MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV +BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50 +ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco +LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg +zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd +9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw +CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy +em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G +CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6 +hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh +y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8 -----END CERTIFICATE----- |