diff options
author | Craig Tiller <ctiller@google.com> | 2016-03-28 22:53:34 -0700 |
---|---|---|
committer | Craig Tiller <ctiller@google.com> | 2016-03-28 22:53:34 -0700 |
commit | c2011586fae18c7b247686428a2469198589a1f9 (patch) | |
tree | dfcd31dd1d881e6c2bda9b565f853cb0d6ccb7d3 /src/core/lib | |
parent | 3bd96959398d0671fee3785d4b2aee6042649b15 (diff) | |
parent | c91504ed57c93d30f654d9f3a0fee62c1236fad8 (diff) |
Merge github.com:grpc/grpc into idempotent
Diffstat (limited to 'src/core/lib')
54 files changed, 40 insertions, 11102 deletions
diff --git a/src/core/lib/iomgr/socket_utils_common_posix.c b/src/core/lib/iomgr/socket_utils_common_posix.c index 9dbc2784e4..b433aee7fa 100644 --- a/src/core/lib/iomgr/socket_utils_common_posix.c +++ b/src/core/lib/iomgr/socket_utils_common_posix.c @@ -89,6 +89,28 @@ int grpc_set_socket_no_sigpipe_if_possible(int fd) { #endif } +int grpc_set_socket_ip_pktinfo_if_possible(int fd) { +#ifdef GPR_HAVE_IP_PKTINFO + int get_local_ip = 1; + return 0 == setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &get_local_ip, + sizeof(get_local_ip)); +#else + (void)fd; + return 1; +#endif +} + +int grpc_set_socket_ipv6_recvpktinfo_if_possible(int fd) { +#ifdef GPR_HAVE_IPV6_RECVPKTINFO + int get_local_ip = 1; + return 0 == setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &get_local_ip, + sizeof(get_local_ip)); +#else + (void)fd; + return 1; +#endif +} + /* set a socket to close on exec */ int grpc_set_socket_cloexec(int fd, int close_on_exec) { int oldflags = fcntl(fd, F_GETFD, 0); diff --git a/src/core/lib/iomgr/socket_utils_posix.h b/src/core/lib/iomgr/socket_utils_posix.h index 063f298d72..f73ad6317d 100644 --- a/src/core/lib/iomgr/socket_utils_posix.h +++ b/src/core/lib/iomgr/socket_utils_posix.h @@ -68,6 +68,16 @@ int grpc_ipv6_loopback_available(void); If SO_NO_SIGPIPE is not available, returns 1. */ int grpc_set_socket_no_sigpipe_if_possible(int fd); +/* Tries to set IP_PKTINFO if available on this platform. + Returns 1 on success, 0 on failure. + If IP_PKTINFO is not available, returns 1. */ +int grpc_set_socket_ip_pktinfo_if_possible(int fd); + +/* Tries to set IPV6_RECVPKTINFO if available on this platform. + Returns 1 on success, 0 on failure. + If IPV6_RECVPKTINFO is not available, returns 1. */ +int grpc_set_socket_ipv6_recvpktinfo_if_possible(int fd); + /* An enum to keep track of IPv4/IPv6 socket modes. Currently, this information is only used when a socket is first created, but diff --git a/src/core/lib/iomgr/udp_server.c b/src/core/lib/iomgr/udp_server.c index 3d8bcc9c81..9068109c3a 100644 --- a/src/core/lib/iomgr/udp_server.c +++ b/src/core/lib/iomgr/udp_server.c @@ -208,8 +208,6 @@ static int prepare_socket(int fd, const struct sockaddr *addr, size_t addr_len) { struct sockaddr_storage sockname_temp; socklen_t sockname_len; - int get_local_ip; - int rc; if (fd < 0) { goto error; @@ -220,14 +218,9 @@ static int prepare_socket(int fd, const struct sockaddr *addr, strerror(errno)); } - get_local_ip = 1; - rc = setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &get_local_ip, - sizeof(get_local_ip)); - if (rc == 0 && addr->sa_family == AF_INET6) { -#if !defined(__APPLE__) - rc = setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &get_local_ip, - sizeof(get_local_ip)); -#endif + if (grpc_set_socket_ip_pktinfo_if_possible(fd) && + addr->sa_family == AF_INET6) { + grpc_set_socket_ipv6_recvpktinfo_if_possible(fd); } GPR_ASSERT(addr_len < ~(socklen_t)0); diff --git a/src/core/lib/security/client_auth_filter.c b/src/core/lib/security/client_auth_filter.c index b9e5bf0339..af6073e560 100644 --- a/src/core/lib/security/client_auth_filter.c +++ b/src/core/lib/security/client_auth_filter.c @@ -172,7 +172,7 @@ static void send_security_metadata(grpc_exec_ctx *exec_ctx, 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, + bubble_up_error(exec_ctx, elem, GRPC_STATUS_INTERNAL, "Incompatible credentials set on channel and call."); return; } @@ -201,7 +201,7 @@ static void on_host_checked(grpc_exec_ctx *exec_ctx, void *user_data, char *error_msg; gpr_asprintf(&error_msg, "Invalid host %s set in :authority metadata.", grpc_mdstr_as_c_string(calld->host)); - bubble_up_error(exec_ctx, elem, GRPC_STATUS_INVALID_ARGUMENT, error_msg); + bubble_up_error(exec_ctx, elem, GRPC_STATUS_INTERNAL, error_msg); gpr_free(error_msg); } } diff --git a/src/core/lib/security/security_connector.c b/src/core/lib/security/security_connector.c index 5474bc3a9e..48b23a9dcf 100644 --- a/src/core/lib/security/security_connector.c +++ b/src/core/lib/security/security_connector.c @@ -42,6 +42,7 @@ #include <grpc/support/slice_buffer.h> #include <grpc/support/string_util.h> +#include "src/core/ext/transport/chttp2/transport/alpn.h" #include "src/core/lib/security/credentials.h" #include "src/core/lib/security/handshake.h" #include "src/core/lib/security/secure_endpoint.h" @@ -49,7 +50,6 @@ #include "src/core/lib/support/env.h" #include "src/core/lib/support/load_file.h" #include "src/core/lib/support/string.h" -#include "src/core/lib/transport/chttp2/alpn.h" #include "src/core/lib/tsi/fake_transport_security.h" #include "src/core/lib/tsi/ssl_transport_security.h" diff --git a/src/core/lib/security/server_secure_chttp2.c b/src/core/lib/security/server_secure_chttp2.c deleted file mode 100644 index 7c9dd221ed..0000000000 --- a/src/core/lib/security/server_secure_chttp2.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/grpc.h> - -#include <string.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/sync.h> -#include <grpc/support/useful.h> -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/channel/http_server_filter.h" -#include "src/core/lib/iomgr/endpoint.h" -#include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/tcp_server.h" -#include "src/core/lib/security/auth_filters.h" -#include "src/core/lib/security/credentials.h" -#include "src/core/lib/security/security_connector.h" -#include "src/core/lib/security/security_context.h" -#include "src/core/lib/surface/api_trace.h" -#include "src/core/lib/surface/server.h" -#include "src/core/lib/transport/chttp2_transport.h" - -typedef struct grpc_server_secure_state { - grpc_server *server; - grpc_tcp_server *tcp; - grpc_server_security_connector *sc; - grpc_server_credentials *creds; - int is_shutdown; - gpr_mu mu; - gpr_refcount refcount; - grpc_closure destroy_closure; - grpc_closure *destroy_callback; -} grpc_server_secure_state; - -static void state_ref(grpc_server_secure_state *state) { - gpr_ref(&state->refcount); -} - -static void state_unref(grpc_server_secure_state *state) { - if (gpr_unref(&state->refcount)) { - /* ensure all threads have unlocked */ - gpr_mu_lock(&state->mu); - gpr_mu_unlock(&state->mu); - /* clean up */ - GRPC_SECURITY_CONNECTOR_UNREF(&state->sc->base, "server"); - grpc_server_credentials_unref(state->creds); - gpr_free(state); - } -} - -static void setup_transport(grpc_exec_ctx *exec_ctx, void *statep, - grpc_transport *transport, - grpc_auth_context *auth_context) { - grpc_server_secure_state *state = statep; - grpc_channel_args *args_copy; - grpc_arg args_to_add[2]; - args_to_add[0] = grpc_server_credentials_to_arg(state->creds); - args_to_add[1] = grpc_auth_context_to_arg(auth_context); - args_copy = grpc_channel_args_copy_and_add( - grpc_server_get_channel_args(state->server), args_to_add, - GPR_ARRAY_SIZE(args_to_add)); - grpc_server_setup_transport(exec_ctx, state->server, transport, args_copy); - grpc_channel_args_destroy(args_copy); -} - -static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *statep, - grpc_security_status status, - grpc_endpoint *secure_endpoint, - grpc_auth_context *auth_context) { - grpc_server_secure_state *state = statep; - grpc_transport *transport; - if (status == GRPC_SECURITY_OK) { - if (secure_endpoint) { - gpr_mu_lock(&state->mu); - if (!state->is_shutdown) { - transport = grpc_create_chttp2_transport( - exec_ctx, grpc_server_get_channel_args(state->server), - secure_endpoint, 0); - setup_transport(exec_ctx, state, transport, auth_context); - grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL, 0); - } else { - /* We need to consume this here, because the server may already have - * gone away. */ - grpc_endpoint_destroy(exec_ctx, secure_endpoint); - } - gpr_mu_unlock(&state->mu); - } - } else { - gpr_log(GPR_ERROR, "Secure transport failed with error %d", status); - } - state_unref(state); -} - -static void on_accept(grpc_exec_ctx *exec_ctx, void *statep, grpc_endpoint *tcp, - grpc_tcp_server_acceptor *acceptor) { - grpc_server_secure_state *state = statep; - state_ref(state); - grpc_server_security_connector_do_handshake( - exec_ctx, state->sc, acceptor, tcp, on_secure_handshake_done, state); -} - -/* Server callback: start listening on our ports */ -static void start(grpc_exec_ctx *exec_ctx, grpc_server *server, void *statep, - grpc_pollset **pollsets, size_t pollset_count) { - grpc_server_secure_state *state = statep; - grpc_tcp_server_start(exec_ctx, state->tcp, pollsets, pollset_count, - on_accept, state); -} - -static void destroy_done(grpc_exec_ctx *exec_ctx, void *statep, bool success) { - grpc_server_secure_state *state = statep; - if (state->destroy_callback != NULL) { - state->destroy_callback->cb(exec_ctx, state->destroy_callback->cb_arg, - success); - } - grpc_server_security_connector_shutdown(exec_ctx, state->sc); - state_unref(state); -} - -/* Server callback: destroy the tcp listener (so we don't generate further - callbacks) */ -static void destroy(grpc_exec_ctx *exec_ctx, grpc_server *server, void *statep, - grpc_closure *callback) { - grpc_server_secure_state *state = statep; - grpc_tcp_server *tcp; - gpr_mu_lock(&state->mu); - state->is_shutdown = 1; - state->destroy_callback = callback; - tcp = state->tcp; - gpr_mu_unlock(&state->mu); - grpc_tcp_server_unref(exec_ctx, tcp); -} - -int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr, - grpc_server_credentials *creds) { - grpc_resolved_addresses *resolved = NULL; - grpc_tcp_server *tcp = NULL; - grpc_server_secure_state *state = NULL; - size_t i; - unsigned count = 0; - int port_num = -1; - int port_temp; - grpc_security_status status = GRPC_SECURITY_ERROR; - grpc_server_security_connector *sc = NULL; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - GRPC_API_TRACE( - "grpc_server_add_secure_http2_port(" - "server=%p, addr=%s, creds=%p)", - 3, (server, addr, creds)); - - /* create security context */ - if (creds == NULL) goto error; - status = grpc_server_credentials_create_security_connector(creds, &sc); - if (status != GRPC_SECURITY_OK) { - gpr_log(GPR_ERROR, - "Unable to create secure server with credentials of type %s.", - creds->type); - goto error; - } - sc->channel_args = grpc_server_get_channel_args(server); - - /* resolve address */ - resolved = grpc_blocking_resolve_address(addr, "https"); - if (!resolved) { - goto error; - } - state = gpr_malloc(sizeof(*state)); - memset(state, 0, sizeof(*state)); - grpc_closure_init(&state->destroy_closure, destroy_done, state); - tcp = grpc_tcp_server_create(&state->destroy_closure); - if (!tcp) { - goto error; - } - - state->server = server; - state->tcp = tcp; - state->sc = sc; - state->creds = grpc_server_credentials_ref(creds); - state->is_shutdown = 0; - gpr_mu_init(&state->mu); - gpr_ref_init(&state->refcount, 1); - - for (i = 0; i < resolved->naddrs; i++) { - port_temp = grpc_tcp_server_add_port( - tcp, (struct sockaddr *)&resolved->addrs[i].addr, - resolved->addrs[i].len); - if (port_temp > 0) { - if (port_num == -1) { - port_num = port_temp; - } else { - GPR_ASSERT(port_num == port_temp); - } - count++; - } - } - if (count == 0) { - gpr_log(GPR_ERROR, "No address added out of total %d resolved", - resolved->naddrs); - goto error; - } - if (count != resolved->naddrs) { - gpr_log(GPR_ERROR, "Only %d addresses added out of total %d resolved", - count, resolved->naddrs); - /* if it's an error, don't we want to goto error; here ? */ - } - grpc_resolved_addresses_destroy(resolved); - - /* Register with the server only upon success */ - grpc_server_add_listener(&exec_ctx, server, state, start, destroy); - - grpc_exec_ctx_finish(&exec_ctx); - return port_num; - -/* Error path: cleanup and return */ -error: - if (resolved) { - grpc_resolved_addresses_destroy(resolved); - } - if (tcp) { - grpc_tcp_server_unref(&exec_ctx, tcp); - } else { - if (sc) { - GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "server"); - } - if (state) { - gpr_free(state); - } - } - grpc_exec_ctx_finish(&exec_ctx); - return 0; -} diff --git a/src/core/lib/surface/channel_create.c b/src/core/lib/surface/channel_create.c deleted file mode 100644 index e8777ce816..0000000000 --- a/src/core/lib/surface/channel_create.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/grpc.h> - -#include <stdlib.h> -#include <string.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/slice.h> -#include <grpc/support/slice_buffer.h> - -#include "src/core/lib/census/grpc_filter.h" -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/channel/client_channel.h" -#include "src/core/lib/channel/compress_filter.h" -#include "src/core/lib/channel/http_client_filter.h" -#include "src/core/lib/client_config/resolver_registry.h" -#include "src/core/lib/iomgr/tcp_client.h" -#include "src/core/lib/surface/api_trace.h" -#include "src/core/lib/surface/channel.h" -#include "src/core/lib/transport/chttp2_transport.h" - -typedef struct { - grpc_connector base; - gpr_refcount refs; - - grpc_closure *notify; - grpc_connect_in_args args; - grpc_connect_out_args *result; - grpc_closure initial_string_sent; - gpr_slice_buffer initial_string_buffer; - - grpc_endpoint *tcp; - - grpc_closure connected; -} connector; - -static void connector_ref(grpc_connector *con) { - connector *c = (connector *)con; - gpr_ref(&c->refs); -} - -static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) { - connector *c = (connector *)con; - if (gpr_unref(&c->refs)) { - /* c->initial_string_buffer does not need to be destroyed */ - gpr_free(c); - } -} - -static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg, - bool success) { - connector_unref(exec_ctx, arg); -} - -static void connected(grpc_exec_ctx *exec_ctx, void *arg, bool success) { - connector *c = arg; - grpc_closure *notify; - grpc_endpoint *tcp = c->tcp; - if (tcp != NULL) { - if (!GPR_SLICE_IS_EMPTY(c->args.initial_connect_string)) { - grpc_closure_init(&c->initial_string_sent, on_initial_connect_string_sent, - c); - gpr_slice_buffer_init(&c->initial_string_buffer); - gpr_slice_buffer_add(&c->initial_string_buffer, - c->args.initial_connect_string); - connector_ref(arg); - grpc_endpoint_write(exec_ctx, tcp, &c->initial_string_buffer, - &c->initial_string_sent); - } - c->result->transport = - grpc_create_chttp2_transport(exec_ctx, c->args.channel_args, tcp, 1); - grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL, - 0); - GPR_ASSERT(c->result->transport); - c->result->channel_args = c->args.channel_args; - } else { - memset(c->result, 0, sizeof(*c->result)); - } - notify = c->notify; - c->notify = NULL; - notify->cb(exec_ctx, notify->cb_arg, 1); -} - -static void connector_shutdown(grpc_exec_ctx *exec_ctx, grpc_connector *con) {} - -static void connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *con, - const grpc_connect_in_args *args, - grpc_connect_out_args *result, - grpc_closure *notify) { - connector *c = (connector *)con; - GPR_ASSERT(c->notify == NULL); - GPR_ASSERT(notify->cb); - c->notify = notify; - c->args = *args; - c->result = result; - c->tcp = NULL; - grpc_closure_init(&c->connected, connected, c); - grpc_tcp_client_connect(exec_ctx, &c->connected, &c->tcp, - args->interested_parties, args->addr, args->addr_len, - args->deadline); -} - -static const grpc_connector_vtable connector_vtable = { - connector_ref, connector_unref, connector_shutdown, connector_connect}; - -typedef struct { - grpc_subchannel_factory base; - gpr_refcount refs; - grpc_channel_args *merge_args; - grpc_channel *master; -} subchannel_factory; - -static void subchannel_factory_ref(grpc_subchannel_factory *scf) { - subchannel_factory *f = (subchannel_factory *)scf; - gpr_ref(&f->refs); -} - -static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx, - grpc_subchannel_factory *scf) { - subchannel_factory *f = (subchannel_factory *)scf; - if (gpr_unref(&f->refs)) { - GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master, "subchannel_factory"); - grpc_channel_args_destroy(f->merge_args); - gpr_free(f); - } -} - -static grpc_subchannel *subchannel_factory_create_subchannel( - grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *scf, - grpc_subchannel_args *args) { - subchannel_factory *f = (subchannel_factory *)scf; - connector *c = gpr_malloc(sizeof(*c)); - grpc_channel_args *final_args = - grpc_channel_args_merge(args->args, f->merge_args); - grpc_subchannel *s; - memset(c, 0, sizeof(*c)); - c->base.vtable = &connector_vtable; - gpr_ref_init(&c->refs, 1); - args->args = final_args; - s = grpc_subchannel_create(exec_ctx, &c->base, args); - grpc_connector_unref(exec_ctx, &c->base); - grpc_channel_args_destroy(final_args); - return s; -} - -static const grpc_subchannel_factory_vtable subchannel_factory_vtable = { - subchannel_factory_ref, subchannel_factory_unref, - subchannel_factory_create_subchannel}; - -/* Create a client channel: - Asynchronously: - resolve target - - connect to it (trying alternatives as presented) - - perform handshakes */ -grpc_channel *grpc_insecure_channel_create(const char *target, - const grpc_channel_args *args, - void *reserved) { - grpc_channel *channel = NULL; - grpc_resolver *resolver; - subchannel_factory *f; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - GRPC_API_TRACE( - "grpc_insecure_channel_create(target=%p, args=%p, reserved=%p)", 3, - (target, args, reserved)); - GPR_ASSERT(!reserved); - - channel = - grpc_channel_create(&exec_ctx, target, args, GRPC_CLIENT_CHANNEL, NULL); - - f = gpr_malloc(sizeof(*f)); - f->base.vtable = &subchannel_factory_vtable; - gpr_ref_init(&f->refs, 1); - f->merge_args = grpc_channel_args_copy(args); - f->master = channel; - GRPC_CHANNEL_INTERNAL_REF(f->master, "subchannel_factory"); - resolver = grpc_resolver_create(target, &f->base); - if (!resolver) { - GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, f->master, "subchannel_factory"); - grpc_subchannel_factory_unref(&exec_ctx, &f->base); - grpc_exec_ctx_finish(&exec_ctx); - return NULL; - } - - grpc_client_channel_set_resolver( - &exec_ctx, grpc_channel_get_channel_stack(channel), resolver); - GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "create"); - grpc_subchannel_factory_unref(&exec_ctx, &f->base); - - grpc_exec_ctx_finish(&exec_ctx); - - return channel; -} diff --git a/src/core/lib/surface/init.c b/src/core/lib/surface/init.c index dcb9c62d36..dbfc8a9336 100644 --- a/src/core/lib/surface/init.c +++ b/src/core/lib/surface/init.c @@ -40,6 +40,7 @@ #include <grpc/support/alloc.h> #include <grpc/support/time.h> /* TODO(ctiller): find another way? - better not to include census here */ +#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/census/grpc_plugin.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/client_channel.h" @@ -67,7 +68,6 @@ #include "src/core/lib/surface/lame_client.h" #include "src/core/lib/surface/server.h" #include "src/core/lib/surface/surface_trace.h" -#include "src/core/lib/transport/chttp2_transport.h" #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/transport_impl.h" diff --git a/src/core/lib/surface/secure_channel_create.c b/src/core/lib/surface/secure_channel_create.c deleted file mode 100644 index dcb367023e..0000000000 --- a/src/core/lib/surface/secure_channel_create.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/grpc.h> - -#include <stdlib.h> -#include <string.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/slice.h> -#include <grpc/support/slice_buffer.h> - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/channel/client_channel.h" -#include "src/core/lib/client_config/resolver_registry.h" -#include "src/core/lib/iomgr/tcp_client.h" -#include "src/core/lib/security/auth_filters.h" -#include "src/core/lib/security/credentials.h" -#include "src/core/lib/security/security_context.h" -#include "src/core/lib/surface/api_trace.h" -#include "src/core/lib/surface/channel.h" -#include "src/core/lib/transport/chttp2_transport.h" -#include "src/core/lib/tsi/transport_security_interface.h" - -typedef struct { - grpc_connector base; - gpr_refcount refs; - - grpc_channel_security_connector *security_connector; - - grpc_closure *notify; - grpc_connect_in_args args; - grpc_connect_out_args *result; - grpc_closure initial_string_sent; - gpr_slice_buffer initial_string_buffer; - - gpr_mu mu; - grpc_endpoint *connecting_endpoint; - grpc_endpoint *newly_connecting_endpoint; - - grpc_closure connected_closure; -} connector; - -static void connector_ref(grpc_connector *con) { - connector *c = (connector *)con; - gpr_ref(&c->refs); -} - -static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) { - connector *c = (connector *)con; - if (gpr_unref(&c->refs)) { - /* c->initial_string_buffer does not need to be destroyed */ - gpr_free(c); - } -} - -static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *arg, - grpc_security_status status, - grpc_endpoint *secure_endpoint, - grpc_auth_context *auth_context) { - connector *c = arg; - grpc_closure *notify; - grpc_channel_args *args_copy = NULL; - gpr_mu_lock(&c->mu); - if (c->connecting_endpoint == NULL) { - memset(c->result, 0, sizeof(*c->result)); - gpr_mu_unlock(&c->mu); - } else if (status != GRPC_SECURITY_OK) { - gpr_log(GPR_ERROR, "Secure handshake failed with error %d.", status); - memset(c->result, 0, sizeof(*c->result)); - c->connecting_endpoint = NULL; - gpr_mu_unlock(&c->mu); - } else { - grpc_arg auth_context_arg; - c->connecting_endpoint = NULL; - gpr_mu_unlock(&c->mu); - c->result->transport = grpc_create_chttp2_transport( - exec_ctx, c->args.channel_args, secure_endpoint, 1); - grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL, - 0); - auth_context_arg = grpc_auth_context_to_arg(auth_context); - args_copy = grpc_channel_args_copy_and_add(c->args.channel_args, - &auth_context_arg, 1); - c->result->channel_args = args_copy; - } - notify = c->notify; - c->notify = NULL; - /* look at c->args which are connector args. */ - notify->cb(exec_ctx, notify->cb_arg, 1); - if (args_copy != NULL) grpc_channel_args_destroy(args_copy); -} - -static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg, - bool success) { - connector *c = arg; - grpc_channel_security_connector_do_handshake(exec_ctx, c->security_connector, - c->connecting_endpoint, - on_secure_handshake_done, c); -} - -static void connected(grpc_exec_ctx *exec_ctx, void *arg, bool success) { - connector *c = arg; - grpc_closure *notify; - grpc_endpoint *tcp = c->newly_connecting_endpoint; - if (tcp != NULL) { - gpr_mu_lock(&c->mu); - GPR_ASSERT(c->connecting_endpoint == NULL); - c->connecting_endpoint = tcp; - gpr_mu_unlock(&c->mu); - if (!GPR_SLICE_IS_EMPTY(c->args.initial_connect_string)) { - grpc_closure_init(&c->initial_string_sent, on_initial_connect_string_sent, - c); - gpr_slice_buffer_init(&c->initial_string_buffer); - gpr_slice_buffer_add(&c->initial_string_buffer, - c->args.initial_connect_string); - grpc_endpoint_write(exec_ctx, tcp, &c->initial_string_buffer, - &c->initial_string_sent); - } else { - grpc_channel_security_connector_do_handshake( - exec_ctx, c->security_connector, tcp, on_secure_handshake_done, c); - } - } else { - memset(c->result, 0, sizeof(*c->result)); - notify = c->notify; - c->notify = NULL; - notify->cb(exec_ctx, notify->cb_arg, 1); - } -} - -static void connector_shutdown(grpc_exec_ctx *exec_ctx, grpc_connector *con) { - connector *c = (connector *)con; - grpc_endpoint *ep; - gpr_mu_lock(&c->mu); - ep = c->connecting_endpoint; - c->connecting_endpoint = NULL; - gpr_mu_unlock(&c->mu); - if (ep) { - grpc_endpoint_shutdown(exec_ctx, ep); - } -} - -static void connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *con, - const grpc_connect_in_args *args, - grpc_connect_out_args *result, - grpc_closure *notify) { - connector *c = (connector *)con; - GPR_ASSERT(c->notify == NULL); - GPR_ASSERT(notify->cb); - c->notify = notify; - c->args = *args; - c->result = result; - gpr_mu_lock(&c->mu); - GPR_ASSERT(c->connecting_endpoint == NULL); - gpr_mu_unlock(&c->mu); - grpc_closure_init(&c->connected_closure, connected, c); - grpc_tcp_client_connect( - exec_ctx, &c->connected_closure, &c->newly_connecting_endpoint, - args->interested_parties, args->addr, args->addr_len, args->deadline); -} - -static const grpc_connector_vtable connector_vtable = { - connector_ref, connector_unref, connector_shutdown, connector_connect}; - -typedef struct { - grpc_subchannel_factory base; - gpr_refcount refs; - grpc_channel_args *merge_args; - grpc_channel_security_connector *security_connector; - grpc_channel *master; -} subchannel_factory; - -static void subchannel_factory_ref(grpc_subchannel_factory *scf) { - subchannel_factory *f = (subchannel_factory *)scf; - gpr_ref(&f->refs); -} - -static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx, - grpc_subchannel_factory *scf) { - subchannel_factory *f = (subchannel_factory *)scf; - if (gpr_unref(&f->refs)) { - GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base, - "subchannel_factory"); - GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master, "subchannel_factory"); - grpc_channel_args_destroy(f->merge_args); - gpr_free(f); - } -} - -static grpc_subchannel *subchannel_factory_create_subchannel( - grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *scf, - grpc_subchannel_args *args) { - subchannel_factory *f = (subchannel_factory *)scf; - connector *c = gpr_malloc(sizeof(*c)); - grpc_channel_args *final_args = - grpc_channel_args_merge(args->args, f->merge_args); - grpc_subchannel *s; - memset(c, 0, sizeof(*c)); - c->base.vtable = &connector_vtable; - c->security_connector = f->security_connector; - gpr_mu_init(&c->mu); - gpr_ref_init(&c->refs, 1); - args->args = final_args; - s = grpc_subchannel_create(exec_ctx, &c->base, args); - grpc_connector_unref(exec_ctx, &c->base); - grpc_channel_args_destroy(final_args); - return s; -} - -static const grpc_subchannel_factory_vtable subchannel_factory_vtable = { - subchannel_factory_ref, subchannel_factory_unref, - subchannel_factory_create_subchannel}; - -/* Create a secure client channel: - Asynchronously: - resolve target - - connect to it (trying alternatives as presented) - - perform handshakes */ -grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds, - const char *target, - const grpc_channel_args *args, - void *reserved) { - grpc_channel *channel; - grpc_arg connector_arg; - grpc_channel_args *args_copy; - grpc_channel_args *new_args_from_connector; - grpc_channel_security_connector *security_connector; - grpc_resolver *resolver; - subchannel_factory *f; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - GRPC_API_TRACE( - "grpc_secure_channel_create(creds=%p, target=%s, args=%p, " - "reserved=%p)", - 4, (creds, target, args, reserved)); - GPR_ASSERT(reserved == NULL); - - if (grpc_find_security_connector_in_args(args) != NULL) { - gpr_log(GPR_ERROR, "Cannot set security context in channel args."); - grpc_exec_ctx_finish(&exec_ctx); - return grpc_lame_client_channel_create( - target, GRPC_STATUS_INVALID_ARGUMENT, - "Security connector exists in channel args."); - } - - 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, - "Failed to create security connector."); - } - - connector_arg = grpc_security_connector_to_arg(&security_connector->base); - args_copy = grpc_channel_args_copy_and_add( - new_args_from_connector != NULL ? new_args_from_connector : args, - &connector_arg, 1); - - channel = grpc_channel_create(&exec_ctx, target, args_copy, - GRPC_CLIENT_CHANNEL, NULL); - - f = gpr_malloc(sizeof(*f)); - f->base.vtable = &subchannel_factory_vtable; - gpr_ref_init(&f->refs, 1); - GRPC_SECURITY_CONNECTOR_REF(&security_connector->base, "subchannel_factory"); - f->security_connector = security_connector; - f->merge_args = grpc_channel_args_copy(args_copy); - f->master = channel; - GRPC_CHANNEL_INTERNAL_REF(channel, "subchannel_factory"); - resolver = grpc_resolver_create(target, &f->base); - if (resolver) { - grpc_client_channel_set_resolver( - &exec_ctx, grpc_channel_get_channel_stack(channel), resolver); - GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "create"); - } - grpc_subchannel_factory_unref(&exec_ctx, &f->base); - GRPC_SECURITY_CONNECTOR_UNREF(&security_connector->base, "channel_create"); - grpc_channel_args_destroy(args_copy); - if (new_args_from_connector != NULL) { - grpc_channel_args_destroy(new_args_from_connector); - } - - if (!resolver) { - GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, channel, "subchannel_factory"); - channel = NULL; - } - grpc_exec_ctx_finish(&exec_ctx); - - return channel; -} diff --git a/src/core/lib/surface/server_chttp2.c b/src/core/lib/surface/server_chttp2.c deleted file mode 100644 index f0c2ee5153..0000000000 --- a/src/core/lib/surface/server_chttp2.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/grpc.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/useful.h> -#include "src/core/lib/channel/http_server_filter.h" -#include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/tcp_server.h" -#include "src/core/lib/surface/api_trace.h" -#include "src/core/lib/surface/server.h" -#include "src/core/lib/transport/chttp2_transport.h" - -static void setup_transport(grpc_exec_ctx *exec_ctx, void *server, - grpc_transport *transport) { - grpc_server_setup_transport(exec_ctx, server, transport, - grpc_server_get_channel_args(server)); -} - -static void new_transport(grpc_exec_ctx *exec_ctx, void *server, - grpc_endpoint *tcp, - grpc_tcp_server_acceptor *acceptor) { - /* - * Beware that the call to grpc_create_chttp2_transport() has to happen before - * grpc_tcp_server_destroy(). This is fine here, but similar code - * asynchronously doing a handshake instead of calling grpc_tcp_server_start() - * (as in server_secure_chttp2.c) needs to add synchronization to avoid this - * case. - */ - grpc_transport *transport = grpc_create_chttp2_transport( - exec_ctx, grpc_server_get_channel_args(server), tcp, 0); - setup_transport(exec_ctx, server, transport); - grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL, 0); -} - -/* Server callback: start listening on our ports */ -static void start(grpc_exec_ctx *exec_ctx, grpc_server *server, void *tcpp, - grpc_pollset **pollsets, size_t pollset_count) { - grpc_tcp_server *tcp = tcpp; - grpc_tcp_server_start(exec_ctx, tcp, pollsets, pollset_count, new_transport, - server); -} - -/* Server callback: destroy the tcp listener (so we don't generate further - callbacks) */ -static void destroy(grpc_exec_ctx *exec_ctx, grpc_server *server, void *tcpp, - grpc_closure *destroy_done) { - grpc_tcp_server *tcp = tcpp; - grpc_tcp_server_unref(exec_ctx, tcp); - grpc_exec_ctx_enqueue(exec_ctx, destroy_done, true, NULL); -} - -int grpc_server_add_insecure_http2_port(grpc_server *server, const char *addr) { - grpc_resolved_addresses *resolved = NULL; - grpc_tcp_server *tcp = NULL; - size_t i; - unsigned count = 0; - int port_num = -1; - int port_temp; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - GRPC_API_TRACE("grpc_server_add_insecure_http2_port(server=%p, addr=%s)", 2, - (server, addr)); - - resolved = grpc_blocking_resolve_address(addr, "http"); - if (!resolved) { - goto error; - } - - tcp = grpc_tcp_server_create(NULL); - GPR_ASSERT(tcp); - - for (i = 0; i < resolved->naddrs; i++) { - port_temp = grpc_tcp_server_add_port( - tcp, (struct sockaddr *)&resolved->addrs[i].addr, - resolved->addrs[i].len); - if (port_temp > 0) { - if (port_num == -1) { - port_num = port_temp; - } else { - GPR_ASSERT(port_num == port_temp); - } - count++; - } - } - if (count == 0) { - gpr_log(GPR_ERROR, "No address added out of total %d resolved", - resolved->naddrs); - goto error; - } - if (count != resolved->naddrs) { - gpr_log(GPR_ERROR, "Only %d addresses added out of total %d resolved", - count, resolved->naddrs); - } - grpc_resolved_addresses_destroy(resolved); - - /* Register with the server only upon success */ - grpc_server_add_listener(&exec_ctx, server, tcp, start, destroy); - goto done; - -/* Error path: cleanup and return */ -error: - if (resolved) { - grpc_resolved_addresses_destroy(resolved); - } - if (tcp) { - grpc_tcp_server_unref(&exec_ctx, tcp); - } - port_num = 0; - -done: - grpc_exec_ctx_finish(&exec_ctx); - return port_num; -} diff --git a/src/core/lib/transport/chttp2/alpn.c b/src/core/lib/transport/chttp2/alpn.c deleted file mode 100644 index befe319180..0000000000 --- a/src/core/lib/transport/chttp2/alpn.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/lib/transport/chttp2/alpn.h" -#include <grpc/support/log.h> -#include <grpc/support/useful.h> - -/* in order of preference */ -static const char *const supported_versions[] = {"h2"}; - -int grpc_chttp2_is_alpn_version_supported(const char *version, size_t size) { - size_t i; - for (i = 0; i < GPR_ARRAY_SIZE(supported_versions); i++) { - if (!strncmp(version, supported_versions[i], size)) return 1; - } - return 0; -} - -size_t grpc_chttp2_num_alpn_versions(void) { - return GPR_ARRAY_SIZE(supported_versions); -} - -const char *grpc_chttp2_get_alpn_version_index(size_t i) { - GPR_ASSERT(i < GPR_ARRAY_SIZE(supported_versions)); - return supported_versions[i]; -} diff --git a/src/core/lib/transport/chttp2/alpn.h b/src/core/lib/transport/chttp2/alpn.h deleted file mode 100644 index a9184e63a4..0000000000 --- a/src/core/lib/transport/chttp2/alpn.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_TRANSPORT_CHTTP2_ALPN_H -#define GRPC_CORE_LIB_TRANSPORT_CHTTP2_ALPN_H - -#include <string.h> - -/* Retuns 1 if the version is supported, 0 otherwise. */ -int grpc_chttp2_is_alpn_version_supported(const char *version, size_t size); - -/* Returns the number of protocol versions to advertise */ -size_t grpc_chttp2_num_alpn_versions(void); - -/* Returns the protocol version at index i (0 <= i < - * grpc_chttp2_num_alpn_versions()) */ -const char *grpc_chttp2_get_alpn_version_index(size_t i); - -#endif /* GRPC_CORE_LIB_TRANSPORT_CHTTP2_ALPN_H */ diff --git a/src/core/lib/transport/chttp2/bin_encoder.c b/src/core/lib/transport/chttp2/bin_encoder.c deleted file mode 100644 index 79d0aa3d6f..0000000000 --- a/src/core/lib/transport/chttp2/bin_encoder.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/lib/transport/chttp2/bin_encoder.h" - -#include <string.h> - -#include <grpc/support/log.h> -#include "src/core/lib/transport/chttp2/huffsyms.h" - -static const char alphabet[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -typedef struct { - uint16_t bits; - uint8_t length; -} b64_huff_sym; - -static const b64_huff_sym huff_alphabet[64] = { - {0x21, 6}, {0x5d, 7}, {0x5e, 7}, {0x5f, 7}, {0x60, 7}, {0x61, 7}, - {0x62, 7}, {0x63, 7}, {0x64, 7}, {0x65, 7}, {0x66, 7}, {0x67, 7}, - {0x68, 7}, {0x69, 7}, {0x6a, 7}, {0x6b, 7}, {0x6c, 7}, {0x6d, 7}, - {0x6e, 7}, {0x6f, 7}, {0x70, 7}, {0x71, 7}, {0x72, 7}, {0xfc, 8}, - {0x73, 7}, {0xfd, 8}, {0x3, 5}, {0x23, 6}, {0x4, 5}, {0x24, 6}, - {0x5, 5}, {0x25, 6}, {0x26, 6}, {0x27, 6}, {0x6, 5}, {0x74, 7}, - {0x75, 7}, {0x28, 6}, {0x29, 6}, {0x2a, 6}, {0x7, 5}, {0x2b, 6}, - {0x76, 7}, {0x2c, 6}, {0x8, 5}, {0x9, 5}, {0x2d, 6}, {0x77, 7}, - {0x78, 7}, {0x79, 7}, {0x7a, 7}, {0x7b, 7}, {0x0, 5}, {0x1, 5}, - {0x2, 5}, {0x19, 6}, {0x1a, 6}, {0x1b, 6}, {0x1c, 6}, {0x1d, 6}, - {0x1e, 6}, {0x1f, 6}, {0x7fb, 11}, {0x18, 6}}; - -static const uint8_t tail_xtra[3] = {0, 2, 3}; - -gpr_slice grpc_chttp2_base64_encode(gpr_slice input) { - size_t input_length = GPR_SLICE_LENGTH(input); - size_t input_triplets = input_length / 3; - size_t tail_case = input_length % 3; - size_t output_length = input_triplets * 4 + tail_xtra[tail_case]; - gpr_slice output = gpr_slice_malloc(output_length); - uint8_t *in = GPR_SLICE_START_PTR(input); - char *out = (char *)GPR_SLICE_START_PTR(output); - size_t i; - - /* encode full triplets */ - for (i = 0; i < input_triplets; i++) { - out[0] = alphabet[in[0] >> 2]; - out[1] = alphabet[((in[0] & 0x3) << 4) | (in[1] >> 4)]; - out[2] = alphabet[((in[1] & 0xf) << 2) | (in[2] >> 6)]; - out[3] = alphabet[in[2] & 0x3f]; - out += 4; - in += 3; - } - - /* encode the remaining bytes */ - switch (tail_case) { - case 0: - break; - case 1: - out[0] = alphabet[in[0] >> 2]; - out[1] = alphabet[(in[0] & 0x3) << 4]; - out += 2; - in += 1; - break; - case 2: - out[0] = alphabet[in[0] >> 2]; - out[1] = alphabet[((in[0] & 0x3) << 4) | (in[1] >> 4)]; - out[2] = alphabet[(in[1] & 0xf) << 2]; - out += 3; - in += 2; - break; - } - - GPR_ASSERT(out == (char *)GPR_SLICE_END_PTR(output)); - GPR_ASSERT(in == GPR_SLICE_END_PTR(input)); - return output; -} - -gpr_slice grpc_chttp2_huffman_compress(gpr_slice input) { - size_t nbits; - uint8_t *in; - uint8_t *out; - gpr_slice output; - uint32_t temp = 0; - uint32_t temp_length = 0; - - nbits = 0; - for (in = GPR_SLICE_START_PTR(input); in != GPR_SLICE_END_PTR(input); ++in) { - nbits += grpc_chttp2_huffsyms[*in].length; - } - - output = gpr_slice_malloc(nbits / 8 + (nbits % 8 != 0)); - out = GPR_SLICE_START_PTR(output); - for (in = GPR_SLICE_START_PTR(input); in != GPR_SLICE_END_PTR(input); ++in) { - int sym = *in; - temp <<= grpc_chttp2_huffsyms[sym].length; - temp |= grpc_chttp2_huffsyms[sym].bits; - temp_length += grpc_chttp2_huffsyms[sym].length; - - while (temp_length > 8) { - temp_length -= 8; - *out++ = (uint8_t)(temp >> temp_length); - } - } - - if (temp_length) { - /* NB: the following integer arithmetic operation needs to be in its - * expanded form due to the "integral promotion" performed (see section - * 3.2.1.1 of the C89 draft standard). A cast to the smaller container type - * is then required to avoid the compiler warning */ - *out++ = (uint8_t)((uint8_t)(temp << (8u - temp_length)) | - (uint8_t)(0xffu >> temp_length)); - } - - GPR_ASSERT(out == GPR_SLICE_END_PTR(output)); - - return output; -} - -typedef struct { - uint32_t temp; - uint32_t temp_length; - uint8_t *out; -} huff_out; - -static void enc_flush_some(huff_out *out) { - while (out->temp_length > 8) { - out->temp_length -= 8; - *out->out++ = (uint8_t)(out->temp >> out->temp_length); - } -} - -static void enc_add2(huff_out *out, uint8_t a, uint8_t b) { - b64_huff_sym sa = huff_alphabet[a]; - b64_huff_sym sb = huff_alphabet[b]; - out->temp = (out->temp << (sa.length + sb.length)) | - ((uint32_t)sa.bits << sb.length) | sb.bits; - out->temp_length += (uint32_t)sa.length + (uint32_t)sb.length; - enc_flush_some(out); -} - -static void enc_add1(huff_out *out, uint8_t a) { - b64_huff_sym sa = huff_alphabet[a]; - out->temp = (out->temp << sa.length) | sa.bits; - out->temp_length += sa.length; - enc_flush_some(out); -} - -gpr_slice grpc_chttp2_base64_encode_and_huffman_compress(gpr_slice input) { - size_t input_length = GPR_SLICE_LENGTH(input); - size_t input_triplets = input_length / 3; - size_t tail_case = input_length % 3; - size_t output_syms = input_triplets * 4 + tail_xtra[tail_case]; - size_t max_output_bits = 11 * output_syms; - size_t max_output_length = max_output_bits / 8 + (max_output_bits % 8 != 0); - gpr_slice output = gpr_slice_malloc(max_output_length); - uint8_t *in = GPR_SLICE_START_PTR(input); - uint8_t *start_out = GPR_SLICE_START_PTR(output); - huff_out out; - size_t i; - - out.temp = 0; - out.temp_length = 0; - out.out = start_out; - - /* encode full triplets */ - for (i = 0; i < input_triplets; i++) { - enc_add2(&out, in[0] >> 2, (uint8_t)((in[0] & 0x3) << 4) | (in[1] >> 4)); - enc_add2(&out, (uint8_t)((in[1] & 0xf) << 2) | (in[2] >> 6), - (uint8_t)(in[2] & 0x3f)); - in += 3; - } - - /* encode the remaining bytes */ - switch (tail_case) { - case 0: - break; - case 1: - enc_add2(&out, in[0] >> 2, (uint8_t)((in[0] & 0x3) << 4)); - in += 1; - break; - case 2: - enc_add2(&out, in[0] >> 2, - (uint8_t)((in[0] & 0x3) << 4) | (uint8_t)(in[1] >> 4)); - enc_add1(&out, (uint8_t)((in[1] & 0xf) << 2)); - in += 2; - break; - } - - if (out.temp_length) { - /* NB: the following integer arithmetic operation needs to be in its - * expanded form due to the "integral promotion" performed (see section - * 3.2.1.1 of the C89 draft standard). A cast to the smaller container type - * is then required to avoid the compiler warning */ - *out.out++ = (uint8_t)((uint8_t)(out.temp << (8u - out.temp_length)) | - (uint8_t)(0xffu >> out.temp_length)); - } - - GPR_ASSERT(out.out <= GPR_SLICE_END_PTR(output)); - GPR_SLICE_SET_LENGTH(output, out.out - start_out); - - GPR_ASSERT(in == GPR_SLICE_END_PTR(input)); - return output; -} diff --git a/src/core/lib/transport/chttp2/bin_encoder.h b/src/core/lib/transport/chttp2/bin_encoder.h deleted file mode 100644 index 1c5cd1e1c6..0000000000 --- a/src/core/lib/transport/chttp2/bin_encoder.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_TRANSPORT_CHTTP2_BIN_ENCODER_H -#define GRPC_CORE_LIB_TRANSPORT_CHTTP2_BIN_ENCODER_H - -#include <grpc/support/slice.h> - -/* base64 encode a slice. Returns a new slice, does not take ownership of the - input */ -gpr_slice grpc_chttp2_base64_encode(gpr_slice input); - -/* Compress a slice with the static huffman encoder detailed in the hpack - standard. Returns a new slice, does not take ownership of the input */ -gpr_slice grpc_chttp2_huffman_compress(gpr_slice input); - -/* equivalent to: - gpr_slice x = grpc_chttp2_base64_encode(input); - gpr_slice y = grpc_chttp2_huffman_compress(x); - gpr_slice_unref(x); - return y; */ -gpr_slice grpc_chttp2_base64_encode_and_huffman_compress(gpr_slice input); - -#endif /* GRPC_CORE_LIB_TRANSPORT_CHTTP2_BIN_ENCODER_H */ diff --git a/src/core/lib/transport/chttp2/frame.h b/src/core/lib/transport/chttp2/frame.h deleted file mode 100644 index 4674bc9703..0000000000 --- a/src/core/lib/transport/chttp2/frame.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_TRANSPORT_CHTTP2_FRAME_H -#define GRPC_CORE_LIB_TRANSPORT_CHTTP2_FRAME_H - -#include <grpc/support/port_platform.h> -#include <grpc/support/slice.h> - -/* Common definitions for frame handling in the chttp2 transport */ - -typedef enum { - GRPC_CHTTP2_PARSE_OK, - GRPC_CHTTP2_STREAM_ERROR, - GRPC_CHTTP2_CONNECTION_ERROR -} grpc_chttp2_parse_error; - -/* defined in internal.h */ -typedef struct grpc_chttp2_stream_parsing grpc_chttp2_stream_parsing; -typedef struct grpc_chttp2_transport_parsing grpc_chttp2_transport_parsing; - -#define GRPC_CHTTP2_FRAME_DATA 0 -#define GRPC_CHTTP2_FRAME_HEADER 1 -#define GRPC_CHTTP2_FRAME_CONTINUATION 9 -#define GRPC_CHTTP2_FRAME_RST_STREAM 3 -#define GRPC_CHTTP2_FRAME_SETTINGS 4 -#define GRPC_CHTTP2_FRAME_PING 6 -#define GRPC_CHTTP2_FRAME_GOAWAY 7 -#define GRPC_CHTTP2_FRAME_WINDOW_UPDATE 8 - -#define GRPC_CHTTP2_MAX_PAYLOAD_LENGTH ((1 << 14) - 1) - -#define GRPC_CHTTP2_DATA_FLAG_END_STREAM 1 -#define GRPC_CHTTP2_FLAG_ACK 1 -#define GRPC_CHTTP2_DATA_FLAG_END_HEADERS 4 -#define GRPC_CHTTP2_DATA_FLAG_PADDED 8 -#define GRPC_CHTTP2_FLAG_HAS_PRIORITY 0x20 - -#endif /* GRPC_CORE_LIB_TRANSPORT_CHTTP2_FRAME_H */ diff --git a/src/core/lib/transport/chttp2/frame_data.c b/src/core/lib/transport/chttp2/frame_data.c deleted file mode 100644 index cf25c3ccc1..0000000000 --- a/src/core/lib/transport/chttp2/frame_data.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/lib/transport/chttp2/frame_data.h" - -#include <string.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/useful.h> -#include "src/core/lib/support/string.h" -#include "src/core/lib/transport/chttp2/internal.h" -#include "src/core/lib/transport/transport.h" - -grpc_chttp2_parse_error grpc_chttp2_data_parser_init( - grpc_chttp2_data_parser *parser) { - parser->state = GRPC_CHTTP2_DATA_FH_0; - parser->parsing_frame = NULL; - return GRPC_CHTTP2_PARSE_OK; -} - -void grpc_chttp2_data_parser_destroy(grpc_exec_ctx *exec_ctx, - grpc_chttp2_data_parser *parser) { - grpc_byte_stream *bs; - if (parser->parsing_frame) { - grpc_chttp2_incoming_byte_stream_finished(exec_ctx, parser->parsing_frame, - 0, 1); - } - while ( - (bs = grpc_chttp2_incoming_frame_queue_pop(&parser->incoming_frames))) { - grpc_byte_stream_destroy(exec_ctx, bs); - } -} - -grpc_chttp2_parse_error grpc_chttp2_data_parser_begin_frame( - grpc_chttp2_data_parser *parser, uint8_t flags) { - if (flags & ~GRPC_CHTTP2_DATA_FLAG_END_STREAM) { - gpr_log(GPR_ERROR, "unsupported data flags: 0x%02x", flags); - return GRPC_CHTTP2_STREAM_ERROR; - } - - if (flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) { - parser->is_last_frame = 1; - } else { - parser->is_last_frame = 0; - } - - return GRPC_CHTTP2_PARSE_OK; -} - -void grpc_chttp2_incoming_frame_queue_merge( - grpc_chttp2_incoming_frame_queue *head_dst, - grpc_chttp2_incoming_frame_queue *tail_src) { - if (tail_src->head == NULL) { - return; - } - - if (head_dst->head == NULL) { - *head_dst = *tail_src; - memset(tail_src, 0, sizeof(*tail_src)); - return; - } - - head_dst->tail->next_message = tail_src->head; - head_dst->tail = tail_src->tail; - memset(tail_src, 0, sizeof(*tail_src)); -} - -grpc_byte_stream *grpc_chttp2_incoming_frame_queue_pop( - grpc_chttp2_incoming_frame_queue *q) { - grpc_byte_stream *out; - if (q->head == NULL) { - return NULL; - } - out = &q->head->base; - if (q->head == q->tail) { - memset(q, 0, sizeof(*q)); - } else { - q->head = q->head->next_message; - } - return out; -} - -void grpc_chttp2_encode_data(uint32_t id, gpr_slice_buffer *inbuf, - uint32_t write_bytes, int is_eof, - gpr_slice_buffer *outbuf) { - gpr_slice hdr; - uint8_t *p; - - hdr = gpr_slice_malloc(9); - p = GPR_SLICE_START_PTR(hdr); - GPR_ASSERT(write_bytes < (1 << 24)); - *p++ = (uint8_t)(write_bytes >> 16); - *p++ = (uint8_t)(write_bytes >> 8); - *p++ = (uint8_t)(write_bytes); - *p++ = GRPC_CHTTP2_FRAME_DATA; - *p++ = is_eof ? GRPC_CHTTP2_DATA_FLAG_END_STREAM : 0; - *p++ = (uint8_t)(id >> 24); - *p++ = (uint8_t)(id >> 16); - *p++ = (uint8_t)(id >> 8); - *p++ = (uint8_t)(id); - gpr_slice_buffer_add(outbuf, hdr); - - gpr_slice_buffer_move_first(inbuf, write_bytes, outbuf); -} - -grpc_chttp2_parse_error grpc_chttp2_data_parser_parse( - grpc_exec_ctx *exec_ctx, void *parser, - grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) { - uint8_t *const beg = GPR_SLICE_START_PTR(slice); - uint8_t *const end = GPR_SLICE_END_PTR(slice); - uint8_t *cur = beg; - grpc_chttp2_data_parser *p = parser; - uint32_t message_flags; - grpc_chttp2_incoming_byte_stream *incoming_byte_stream; - - if (is_last && p->is_last_frame) { - stream_parsing->received_close = 1; - } - - if (cur == end) { - return GRPC_CHTTP2_PARSE_OK; - } - - switch (p->state) { - fh_0: - case GRPC_CHTTP2_DATA_FH_0: - p->frame_type = *cur; - switch (p->frame_type) { - case 0: - p->is_frame_compressed = 0; /* GPR_FALSE */ - break; - case 1: - p->is_frame_compressed = 1; /* GPR_TRUE */ - break; - default: - gpr_log(GPR_ERROR, "Bad GRPC frame type 0x%02x", p->frame_type); - return GRPC_CHTTP2_STREAM_ERROR; - } - if (++cur == end) { - p->state = GRPC_CHTTP2_DATA_FH_1; - return GRPC_CHTTP2_PARSE_OK; - } - /* fallthrough */ - case GRPC_CHTTP2_DATA_FH_1: - p->frame_size = ((uint32_t)*cur) << 24; - if (++cur == end) { - p->state = GRPC_CHTTP2_DATA_FH_2; - return GRPC_CHTTP2_PARSE_OK; - } - /* fallthrough */ - case GRPC_CHTTP2_DATA_FH_2: - p->frame_size |= ((uint32_t)*cur) << 16; - if (++cur == end) { - p->state = GRPC_CHTTP2_DATA_FH_3; - return GRPC_CHTTP2_PARSE_OK; - } - /* fallthrough */ - case GRPC_CHTTP2_DATA_FH_3: - p->frame_size |= ((uint32_t)*cur) << 8; - if (++cur == end) { - p->state = GRPC_CHTTP2_DATA_FH_4; - return GRPC_CHTTP2_PARSE_OK; - } - /* fallthrough */ - case GRPC_CHTTP2_DATA_FH_4: - p->frame_size |= ((uint32_t)*cur); - p->state = GRPC_CHTTP2_DATA_FRAME; - ++cur; - message_flags = 0; - if (p->is_frame_compressed) { - message_flags |= GRPC_WRITE_INTERNAL_COMPRESS; - } - p->parsing_frame = incoming_byte_stream = - grpc_chttp2_incoming_byte_stream_create( - exec_ctx, transport_parsing, stream_parsing, p->frame_size, - message_flags, &p->incoming_frames); - /* fallthrough */ - case GRPC_CHTTP2_DATA_FRAME: - if (cur == end) { - grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, - stream_parsing); - return GRPC_CHTTP2_PARSE_OK; - } - grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, - stream_parsing); - if ((uint32_t)(end - cur) == p->frame_size) { - grpc_chttp2_incoming_byte_stream_push( - exec_ctx, p->parsing_frame, - gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg))); - grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame, 1, - 1); - p->parsing_frame = NULL; - p->state = GRPC_CHTTP2_DATA_FH_0; - return GRPC_CHTTP2_PARSE_OK; - } else if ((uint32_t)(end - cur) > p->frame_size) { - grpc_chttp2_incoming_byte_stream_push( - exec_ctx, p->parsing_frame, - gpr_slice_sub(slice, (size_t)(cur - beg), - (size_t)(cur + p->frame_size - beg))); - grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame, 1, - 1); - p->parsing_frame = NULL; - cur += p->frame_size; - goto fh_0; /* loop */ - } else { - grpc_chttp2_incoming_byte_stream_push( - exec_ctx, p->parsing_frame, - gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg))); - GPR_ASSERT((size_t)(end - cur) <= p->frame_size); - p->frame_size -= (uint32_t)(end - cur); - return GRPC_CHTTP2_PARSE_OK; - } - } - - GPR_UNREACHABLE_CODE(return GRPC_CHTTP2_CONNECTION_ERROR); -} diff --git a/src/core/lib/transport/chttp2/frame_data.h b/src/core/lib/transport/chttp2/frame_data.h deleted file mode 100644 index da404a42c6..0000000000 --- a/src/core/lib/transport/chttp2/frame_data.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_TRANSPORT_CHTTP2_FRAME_DATA_H -#define GRPC_CORE_LIB_TRANSPORT_CHTTP2_FRAME_DATA_H - -/* Parser for GRPC streams embedded in DATA frames */ - -#include <grpc/support/slice.h> -#include <grpc/support/slice_buffer.h> -#include "src/core/lib/iomgr/exec_ctx.h" -#include "src/core/lib/transport/byte_stream.h" -#include "src/core/lib/transport/chttp2/frame.h" - -typedef enum { - GRPC_CHTTP2_DATA_FH_0, - GRPC_CHTTP2_DATA_FH_1, - GRPC_CHTTP2_DATA_FH_2, - GRPC_CHTTP2_DATA_FH_3, - GRPC_CHTTP2_DATA_FH_4, - GRPC_CHTTP2_DATA_FRAME -} grpc_chttp2_stream_state; - -typedef struct grpc_chttp2_incoming_byte_stream - grpc_chttp2_incoming_byte_stream; - -typedef struct grpc_chttp2_incoming_frame_queue { - grpc_chttp2_incoming_byte_stream *head; - grpc_chttp2_incoming_byte_stream *tail; -} grpc_chttp2_incoming_frame_queue; - -typedef struct { - grpc_chttp2_stream_state state; - uint8_t is_last_frame; - uint8_t frame_type; - uint32_t frame_size; - - int is_frame_compressed; - grpc_chttp2_incoming_frame_queue incoming_frames; - grpc_chttp2_incoming_byte_stream *parsing_frame; -} grpc_chttp2_data_parser; - -void grpc_chttp2_incoming_frame_queue_merge( - grpc_chttp2_incoming_frame_queue *head_dst, - grpc_chttp2_incoming_frame_queue *tail_src); -grpc_byte_stream *grpc_chttp2_incoming_frame_queue_pop( - grpc_chttp2_incoming_frame_queue *q); - -/* initialize per-stream state for data frame parsing */ -grpc_chttp2_parse_error grpc_chttp2_data_parser_init( - grpc_chttp2_data_parser *parser); - -void grpc_chttp2_data_parser_destroy(grpc_exec_ctx *exec_ctx, - grpc_chttp2_data_parser *parser); - -/* start processing a new data frame */ -grpc_chttp2_parse_error grpc_chttp2_data_parser_begin_frame( - grpc_chttp2_data_parser *parser, uint8_t flags); - -/* handle a slice of a data frame - is_last indicates the last slice of a - frame */ -grpc_chttp2_parse_error grpc_chttp2_data_parser_parse( - grpc_exec_ctx *exec_ctx, void *parser, - grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last); - -void grpc_chttp2_encode_data(uint32_t id, gpr_slice_buffer *inbuf, - uint32_t write_bytes, int is_eof, - gpr_slice_buffer *outbuf); - -#endif /* GRPC_CORE_LIB_TRANSPORT_CHTTP2_FRAME_DATA_H */ diff --git a/src/core/lib/transport/chttp2/frame_goaway.c b/src/core/lib/transport/chttp2/frame_goaway.c deleted file mode 100644 index bb8c28df90..0000000000 --- a/src/core/lib/transport/chttp2/frame_goaway.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/lib/transport/chttp2/frame_goaway.h" -#include "src/core/lib/transport/chttp2/internal.h" - -#include <string.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> - -void grpc_chttp2_goaway_parser_init(grpc_chttp2_goaway_parser *p) { - p->debug_data = NULL; -} - -void grpc_chttp2_goaway_parser_destroy(grpc_chttp2_goaway_parser *p) { - gpr_free(p->debug_data); -} - -grpc_chttp2_parse_error grpc_chttp2_goaway_parser_begin_frame( - grpc_chttp2_goaway_parser *p, uint32_t length, uint8_t flags) { - if (length < 8) { - gpr_log(GPR_ERROR, "goaway frame too short (%d bytes)", length); - return GRPC_CHTTP2_CONNECTION_ERROR; - } - - gpr_free(p->debug_data); - p->debug_length = length - 8; - p->debug_data = gpr_malloc(p->debug_length); - p->debug_pos = 0; - p->state = GRPC_CHTTP2_GOAWAY_LSI0; - return GRPC_CHTTP2_PARSE_OK; -} - -grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse( - grpc_exec_ctx *exec_ctx, void *parser, - grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) { - uint8_t *const beg = GPR_SLICE_START_PTR(slice); - uint8_t *const end = GPR_SLICE_END_PTR(slice); - uint8_t *cur = beg; - grpc_chttp2_goaway_parser *p = parser; - - switch (p->state) { - case GRPC_CHTTP2_GOAWAY_LSI0: - if (cur == end) { - p->state = GRPC_CHTTP2_GOAWAY_LSI0; - return GRPC_CHTTP2_PARSE_OK; - } - p->last_stream_id = ((uint32_t)*cur) << 24; - ++cur; - /* fallthrough */ - case GRPC_CHTTP2_GOAWAY_LSI1: - if (cur == end) { - p->state = GRPC_CHTTP2_GOAWAY_LSI1; - return GRPC_CHTTP2_PARSE_OK; - } - p->last_stream_id |= ((uint32_t)*cur) << 16; - ++cur; - /* fallthrough */ - case GRPC_CHTTP2_GOAWAY_LSI2: - if (cur == end) { - p->state = GRPC_CHTTP2_GOAWAY_LSI2; - return GRPC_CHTTP2_PARSE_OK; - } - p->last_stream_id |= ((uint32_t)*cur) << 8; - ++cur; - /* fallthrough */ - case GRPC_CHTTP2_GOAWAY_LSI3: - if (cur == end) { - p->state = GRPC_CHTTP2_GOAWAY_LSI3; - return GRPC_CHTTP2_PARSE_OK; - } - p->last_stream_id |= ((uint32_t)*cur); - ++cur; - /* fallthrough */ - case GRPC_CHTTP2_GOAWAY_ERR0: - if (cur == end) { - p->state = GRPC_CHTTP2_GOAWAY_ERR0; - return GRPC_CHTTP2_PARSE_OK; - } - p->error_code = ((uint32_t)*cur) << 24; - ++cur; - /* fallthrough */ - case GRPC_CHTTP2_GOAWAY_ERR1: - if (cur == end) { - p->state = GRPC_CHTTP2_GOAWAY_ERR1; - return GRPC_CHTTP2_PARSE_OK; - } - p->error_code |= ((uint32_t)*cur) << 16; - ++cur; - /* fallthrough */ - case GRPC_CHTTP2_GOAWAY_ERR2: - if (cur == end) { - p->state = GRPC_CHTTP2_GOAWAY_ERR2; - return GRPC_CHTTP2_PARSE_OK; - } - p->error_code |= ((uint32_t)*cur) << 8; - ++cur; - /* fallthrough */ - case GRPC_CHTTP2_GOAWAY_ERR3: - if (cur == end) { - p->state = GRPC_CHTTP2_GOAWAY_ERR3; - return GRPC_CHTTP2_PARSE_OK; - } - p->error_code |= ((uint32_t)*cur); - ++cur; - /* fallthrough */ - case GRPC_CHTTP2_GOAWAY_DEBUG: - memcpy(p->debug_data + p->debug_pos, cur, (size_t)(end - cur)); - GPR_ASSERT((size_t)(end - cur) < UINT32_MAX - p->debug_pos); - p->debug_pos += (uint32_t)(end - cur); - p->state = GRPC_CHTTP2_GOAWAY_DEBUG; - if (is_last) { - transport_parsing->goaway_received = 1; - transport_parsing->goaway_last_stream_index = p->last_stream_id; - gpr_slice_unref(transport_parsing->goaway_text); - transport_parsing->goaway_error = (grpc_status_code)p->error_code; - transport_parsing->goaway_text = - gpr_slice_new(p->debug_data, p->debug_length, gpr_free); - p->debug_data = NULL; - } - return GRPC_CHTTP2_PARSE_OK; - } - GPR_UNREACHABLE_CODE(return GRPC_CHTTP2_CONNECTION_ERROR); -} - -void grpc_chttp2_goaway_append(uint32_t last_stream_id, uint32_t error_code, - gpr_slice debug_data, - gpr_slice_buffer *slice_buffer) { - gpr_slice header = gpr_slice_malloc(9 + 4 + 4); - uint8_t *p = GPR_SLICE_START_PTR(header); - uint32_t frame_length; - GPR_ASSERT(GPR_SLICE_LENGTH(debug_data) < UINT32_MAX - 4 - 4); - frame_length = 4 + 4 + (uint32_t)GPR_SLICE_LENGTH(debug_data); - - /* frame header: length */ - *p++ = (uint8_t)(frame_length >> 16); - *p++ = (uint8_t)(frame_length >> 8); - *p++ = (uint8_t)(frame_length); - /* frame header: type */ - *p++ = GRPC_CHTTP2_FRAME_GOAWAY; - /* frame header: flags */ - *p++ = 0; - /* frame header: stream id */ - *p++ = 0; - *p++ = 0; - *p++ = 0; - *p++ = 0; - /* payload: last stream id */ - *p++ = (uint8_t)(last_stream_id >> 24); - *p++ = (uint8_t)(last_stream_id >> 16); - *p++ = (uint8_t)(last_stream_id >> 8); - *p++ = (uint8_t)(last_stream_id); - /* payload: error code */ - *p++ = (uint8_t)(error_code >> 24); - *p++ = (uint8_t)(error_code >> 16); - *p++ = (uint8_t)(error_code >> 8); - *p++ = (uint8_t)(error_code); - GPR_ASSERT(p == GPR_SLICE_END_PTR(header)); - gpr_slice_buffer_add(slice_buffer, header); - gpr_slice_buffer_add(slice_buffer, debug_data); -} diff --git a/src/core/lib/transport/chttp2/frame_goaway.h b/src/core/lib/transport/chttp2/frame_goaway.h deleted file mode 100644 index f64c44f3d9..0000000000 --- a/src/core/lib/transport/chttp2/frame_goaway.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_TRANSPORT_CHTTP2_FRAME_GOAWAY_H -#define GRPC_CORE_LIB_TRANSPORT_CHTTP2_FRAME_GOAWAY_H - -#include <grpc/support/port_platform.h> -#include <grpc/support/slice.h> -#include <grpc/support/slice_buffer.h> -#include "src/core/lib/iomgr/exec_ctx.h" -#include "src/core/lib/transport/chttp2/frame.h" - -typedef enum { - GRPC_CHTTP2_GOAWAY_LSI0, - GRPC_CHTTP2_GOAWAY_LSI1, - GRPC_CHTTP2_GOAWAY_LSI2, - GRPC_CHTTP2_GOAWAY_LSI3, - GRPC_CHTTP2_GOAWAY_ERR0, - GRPC_CHTTP2_GOAWAY_ERR1, - GRPC_CHTTP2_GOAWAY_ERR2, - GRPC_CHTTP2_GOAWAY_ERR3, - GRPC_CHTTP2_GOAWAY_DEBUG -} grpc_chttp2_goaway_parse_state; - -typedef struct { - grpc_chttp2_goaway_parse_state state; - uint32_t last_stream_id; - uint32_t error_code; - char *debug_data; - uint32_t debug_length; - uint32_t debug_pos; -} grpc_chttp2_goaway_parser; - -void grpc_chttp2_goaway_parser_init(grpc_chttp2_goaway_parser *p); -void grpc_chttp2_goaway_parser_destroy(grpc_chttp2_goaway_parser *p); -grpc_chttp2_parse_error grpc_chttp2_goaway_parser_begin_frame( - grpc_chttp2_goaway_parser *parser, uint32_t length, uint8_t flags); -grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse( - grpc_exec_ctx *exec_ctx, void *parser, - grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last); - -void grpc_chttp2_goaway_append(uint32_t last_stream_id, uint32_t error_code, - gpr_slice debug_data, - gpr_slice_buffer *slice_buffer); - -#endif /* GRPC_CORE_LIB_TRANSPORT_CHTTP2_FRAME_GOAWAY_H */ diff --git a/src/core/lib/transport/chttp2/frame_ping.c b/src/core/lib/transport/chttp2/frame_ping.c deleted file mode 100644 index 14ca394264..0000000000 --- a/src/core/lib/transport/chttp2/frame_ping.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/lib/transport/chttp2/frame_ping.h" -#include "src/core/lib/transport/chttp2/internal.h" - -#include <string.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> - -gpr_slice grpc_chttp2_ping_create(uint8_t ack, uint8_t *opaque_8bytes) { - gpr_slice slice = gpr_slice_malloc(9 + 8); - uint8_t *p = GPR_SLICE_START_PTR(slice); - - *p++ = 0; - *p++ = 0; - *p++ = 8; - *p++ = GRPC_CHTTP2_FRAME_PING; - *p++ = ack ? 1 : 0; - *p++ = 0; - *p++ = 0; - *p++ = 0; - *p++ = 0; - memcpy(p, opaque_8bytes, 8); - - return slice; -} - -grpc_chttp2_parse_error grpc_chttp2_ping_parser_begin_frame( - grpc_chttp2_ping_parser *parser, uint32_t length, uint8_t flags) { - if (flags & 0xfe || length != 8) { - gpr_log(GPR_ERROR, "invalid ping: length=%d, flags=%02x", length, flags); - return GRPC_CHTTP2_CONNECTION_ERROR; - } - parser->byte = 0; - parser->is_ack = flags; - return GRPC_CHTTP2_PARSE_OK; -} - -grpc_chttp2_parse_error grpc_chttp2_ping_parser_parse( - grpc_exec_ctx *exec_ctx, void *parser, - grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) { - uint8_t *const beg = GPR_SLICE_START_PTR(slice); - uint8_t *const end = GPR_SLICE_END_PTR(slice); - uint8_t *cur = beg; - grpc_chttp2_ping_parser *p = parser; - - while (p->byte != 8 && cur != end) { - p->opaque_8bytes[p->byte] = *cur; - cur++; - p->byte++; - } - - if (p->byte == 8) { - GPR_ASSERT(is_last); - if (p->is_ack) { - grpc_chttp2_ack_ping(exec_ctx, transport_parsing, p->opaque_8bytes); - } else { - gpr_slice_buffer_add(&transport_parsing->qbuf, - grpc_chttp2_ping_create(1, p->opaque_8bytes)); - } - } - - return GRPC_CHTTP2_PARSE_OK; -} diff --git a/src/core/lib/transport/chttp2/frame_ping.h b/src/core/lib/transport/chttp2/frame_ping.h deleted file mode 100644 index 7640fc4773..0000000000 --- a/src/core/lib/transport/chttp2/frame_ping.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_TRANSPORT_CHTTP2_FRAME_PING_H -#define GRPC_CORE_LIB_TRANSPORT_CHTTP2_FRAME_PING_H - -#include <grpc/support/slice.h> -#include "src/core/lib/iomgr/exec_ctx.h" -#include "src/core/lib/transport/chttp2/frame.h" - -typedef struct { - uint8_t byte; - uint8_t is_ack; - uint8_t opaque_8bytes[8]; -} grpc_chttp2_ping_parser; - -gpr_slice grpc_chttp2_ping_create(uint8_t ack, uint8_t *opaque_8bytes); - -grpc_chttp2_parse_error grpc_chttp2_ping_parser_begin_frame( - grpc_chttp2_ping_parser *parser, uint32_t length, uint8_t flags); -grpc_chttp2_parse_error grpc_chttp2_ping_parser_parse( - grpc_exec_ctx *exec_ctx, void *parser, - grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last); - -#endif /* GRPC_CORE_LIB_TRANSPORT_CHTTP2_FRAME_PING_H */ diff --git a/src/core/lib/transport/chttp2/frame_rst_stream.c b/src/core/lib/transport/chttp2/frame_rst_stream.c deleted file mode 100644 index 060912afc4..0000000000 --- a/src/core/lib/transport/chttp2/frame_rst_stream.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/lib/transport/chttp2/frame_rst_stream.h" -#include "src/core/lib/transport/chttp2/internal.h" - -#include <grpc/support/log.h> - -#include "src/core/lib/transport/chttp2/frame.h" - -gpr_slice grpc_chttp2_rst_stream_create(uint32_t id, uint32_t code) { - gpr_slice slice = gpr_slice_malloc(13); - uint8_t *p = GPR_SLICE_START_PTR(slice); - - *p++ = 0; - *p++ = 0; - *p++ = 4; - *p++ = GRPC_CHTTP2_FRAME_RST_STREAM; - *p++ = 0; - *p++ = (uint8_t)(id >> 24); - *p++ = (uint8_t)(id >> 16); - *p++ = (uint8_t)(id >> 8); - *p++ = (uint8_t)(id); - *p++ = (uint8_t)(code >> 24); - *p++ = (uint8_t)(code >> 16); - *p++ = (uint8_t)(code >> 8); - *p++ = (uint8_t)(code); - - return slice; -} - -grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_begin_frame( - grpc_chttp2_rst_stream_parser *parser, uint32_t length, uint8_t flags) { - if (length != 4) { - gpr_log(GPR_ERROR, "invalid rst_stream: length=%d, flags=%02x", length, - flags); - return GRPC_CHTTP2_CONNECTION_ERROR; - } - parser->byte = 0; - return GRPC_CHTTP2_PARSE_OK; -} - -grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_parse( - grpc_exec_ctx *exec_ctx, void *parser, - grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) { - uint8_t *const beg = GPR_SLICE_START_PTR(slice); - uint8_t *const end = GPR_SLICE_END_PTR(slice); - uint8_t *cur = beg; - grpc_chttp2_rst_stream_parser *p = parser; - - while (p->byte != 4 && cur != end) { - p->reason_bytes[p->byte] = *cur; - cur++; - p->byte++; - } - - if (p->byte == 4) { - GPR_ASSERT(is_last); - stream_parsing->received_close = 1; - stream_parsing->saw_rst_stream = 1; - stream_parsing->rst_stream_reason = (((uint32_t)p->reason_bytes[0]) << 24) | - (((uint32_t)p->reason_bytes[1]) << 16) | - (((uint32_t)p->reason_bytes[2]) << 8) | - (((uint32_t)p->reason_bytes[3])); - } - - return GRPC_CHTTP2_PARSE_OK; -} diff --git a/src/core/lib/transport/chttp2/frame_rst_stream.h b/src/core/lib/transport/chttp2/frame_rst_stream.h deleted file mode 100644 index 93155fde9d..0000000000 --- a/src/core/lib/transport/chttp2/frame_rst_stream.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_TRANSPORT_CHTTP2_FRAME_RST_STREAM_H -#define GRPC_CORE_LIB_TRANSPORT_CHTTP2_FRAME_RST_STREAM_H - -#include <grpc/support/slice.h> -#include "src/core/lib/iomgr/exec_ctx.h" -#include "src/core/lib/transport/chttp2/frame.h" - -typedef struct { - uint8_t byte; - uint8_t reason_bytes[4]; -} grpc_chttp2_rst_stream_parser; - -gpr_slice grpc_chttp2_rst_stream_create(uint32_t stream_id, uint32_t code); - -grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_begin_frame( - grpc_chttp2_rst_stream_parser *parser, uint32_t length, uint8_t flags); -grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_parse( - grpc_exec_ctx *exec_ctx, void *parser, - grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last); - -#endif /* GRPC_CORE_LIB_TRANSPORT_CHTTP2_FRAME_RST_STREAM_H */ diff --git a/src/core/lib/transport/chttp2/frame_settings.c b/src/core/lib/transport/chttp2/frame_settings.c deleted file mode 100644 index 48429c2a78..0000000000 --- a/src/core/lib/transport/chttp2/frame_settings.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/lib/transport/chttp2/frame_settings.h" -#include "src/core/lib/transport/chttp2/internal.h" - -#include <string.h> - -#include <grpc/support/log.h> -#include <grpc/support/useful.h> - -#include "src/core/lib/debug/trace.h" -#include "src/core/lib/transport/chttp2/frame.h" -#include "src/core/lib/transport/chttp2/http2_errors.h" -#include "src/core/lib/transport/chttp2_transport.h" - -#define MAX_MAX_HEADER_LIST_SIZE (1024 * 1024 * 1024) - -/* HTTP/2 mandated initial connection settings */ -const grpc_chttp2_setting_parameters - grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS] = { - {NULL, 0, 0, 0, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, - GRPC_CHTTP2_PROTOCOL_ERROR}, - {"HEADER_TABLE_SIZE", 4096, 0, 0xffffffff, - GRPC_CHTTP2_CLAMP_INVALID_VALUE, GRPC_CHTTP2_PROTOCOL_ERROR}, - {"ENABLE_PUSH", 1, 0, 1, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, - GRPC_CHTTP2_PROTOCOL_ERROR}, - {"MAX_CONCURRENT_STREAMS", 0xffffffffu, 0, 0xffffffffu, - GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_CHTTP2_PROTOCOL_ERROR}, - {"INITIAL_WINDOW_SIZE", 65535, 0, 0x7fffffffu, - GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, - GRPC_CHTTP2_FLOW_CONTROL_ERROR}, - {"MAX_FRAME_SIZE", 16384, 16384, 16777215, - GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_CHTTP2_PROTOCOL_ERROR}, - {"MAX_HEADER_LIST_SIZE", MAX_MAX_HEADER_LIST_SIZE, 0, - MAX_MAX_HEADER_LIST_SIZE, GRPC_CHTTP2_CLAMP_INVALID_VALUE, - GRPC_CHTTP2_PROTOCOL_ERROR}, -}; - -static uint8_t *fill_header(uint8_t *out, uint32_t length, uint8_t flags) { - *out++ = (uint8_t)(length >> 16); - *out++ = (uint8_t)(length >> 8); - *out++ = (uint8_t)(length); - *out++ = GRPC_CHTTP2_FRAME_SETTINGS; - *out++ = flags; - *out++ = 0; - *out++ = 0; - *out++ = 0; - *out++ = 0; - return out; -} - -gpr_slice grpc_chttp2_settings_create(uint32_t *old, const uint32_t *new, - uint32_t force_mask, size_t count) { - size_t i; - uint32_t n = 0; - gpr_slice output; - uint8_t *p; - - for (i = 0; i < count; i++) { - n += (new[i] != old[i] || (force_mask & (1u << i)) != 0); - } - - output = gpr_slice_malloc(9 + 6 * n); - p = fill_header(GPR_SLICE_START_PTR(output), 6 * n, 0); - - for (i = 0; i < count; i++) { - if (new[i] != old[i] || (force_mask & (1u << i)) != 0) { - GPR_ASSERT(i); - *p++ = (uint8_t)(i >> 8); - *p++ = (uint8_t)(i); - *p++ = (uint8_t)(new[i] >> 24); - *p++ = (uint8_t)(new[i] >> 16); - *p++ = (uint8_t)(new[i] >> 8); - *p++ = (uint8_t)(new[i]); - old[i] = new[i]; - } - } - - GPR_ASSERT(p == GPR_SLICE_END_PTR(output)); - - return output; -} - -gpr_slice grpc_chttp2_settings_ack_create(void) { - gpr_slice output = gpr_slice_malloc(9); - fill_header(GPR_SLICE_START_PTR(output), 0, GRPC_CHTTP2_FLAG_ACK); - return output; -} - -grpc_chttp2_parse_error grpc_chttp2_settings_parser_begin_frame( - grpc_chttp2_settings_parser *parser, uint32_t length, uint8_t flags, - uint32_t *settings) { - parser->target_settings = settings; - memcpy(parser->incoming_settings, settings, - GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t)); - parser->is_ack = 0; - parser->state = GRPC_CHTTP2_SPS_ID0; - if (flags == GRPC_CHTTP2_FLAG_ACK) { - parser->is_ack = 1; - if (length != 0) { - gpr_log(GPR_ERROR, "non-empty settings ack frame received"); - return GRPC_CHTTP2_CONNECTION_ERROR; - } - return GRPC_CHTTP2_PARSE_OK; - } else if (flags != 0) { - gpr_log(GPR_ERROR, "invalid flags on settings frame"); - return GRPC_CHTTP2_CONNECTION_ERROR; - } else if (length % 6 != 0) { - gpr_log(GPR_ERROR, "settings frames must be a multiple of six bytes"); - return GRPC_CHTTP2_CONNECTION_ERROR; - } else { - return GRPC_CHTTP2_PARSE_OK; - } -} - -grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse( - grpc_exec_ctx *exec_ctx, void *p, - grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) { - grpc_chttp2_settings_parser *parser = p; - const uint8_t *cur = GPR_SLICE_START_PTR(slice); - const uint8_t *end = GPR_SLICE_END_PTR(slice); - - if (parser->is_ack) { - return GRPC_CHTTP2_PARSE_OK; - } - - for (;;) { - switch (parser->state) { - case GRPC_CHTTP2_SPS_ID0: - if (cur == end) { - parser->state = GRPC_CHTTP2_SPS_ID0; - if (is_last) { - transport_parsing->settings_updated = 1; - memcpy(parser->target_settings, parser->incoming_settings, - GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t)); - gpr_slice_buffer_add(&transport_parsing->qbuf, - grpc_chttp2_settings_ack_create()); - } - return GRPC_CHTTP2_PARSE_OK; - } - parser->id = (uint16_t)(((uint16_t)*cur) << 8); - cur++; - /* fallthrough */ - case GRPC_CHTTP2_SPS_ID1: - if (cur == end) { - parser->state = GRPC_CHTTP2_SPS_ID1; - return GRPC_CHTTP2_PARSE_OK; - } - parser->id = (uint16_t)(parser->id | (*cur)); - cur++; - /* fallthrough */ - case GRPC_CHTTP2_SPS_VAL0: - if (cur == end) { - parser->state = GRPC_CHTTP2_SPS_VAL0; - return GRPC_CHTTP2_PARSE_OK; - } - parser->value = ((uint32_t)*cur) << 24; - cur++; - /* fallthrough */ - case GRPC_CHTTP2_SPS_VAL1: - if (cur == end) { - parser->state = GRPC_CHTTP2_SPS_VAL1; - return GRPC_CHTTP2_PARSE_OK; - } - parser->value |= ((uint32_t)*cur) << 16; - cur++; - /* fallthrough */ - case GRPC_CHTTP2_SPS_VAL2: - if (cur == end) { - parser->state = GRPC_CHTTP2_SPS_VAL2; - return GRPC_CHTTP2_PARSE_OK; - } - parser->value |= ((uint32_t)*cur) << 8; - cur++; - /* fallthrough */ - case GRPC_CHTTP2_SPS_VAL3: - if (cur == end) { - parser->state = GRPC_CHTTP2_SPS_VAL3; - return GRPC_CHTTP2_PARSE_OK; - } else { - parser->state = GRPC_CHTTP2_SPS_ID0; - } - parser->value |= *cur; - cur++; - - if (parser->id > 0 && parser->id < GRPC_CHTTP2_NUM_SETTINGS) { - const grpc_chttp2_setting_parameters *sp = - &grpc_chttp2_settings_parameters[parser->id]; - if (parser->value < sp->min_value || parser->value > sp->max_value) { - switch (sp->invalid_value_behavior) { - case GRPC_CHTTP2_CLAMP_INVALID_VALUE: - parser->value = - GPR_CLAMP(parser->value, sp->min_value, sp->max_value); - break; - case GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE: - grpc_chttp2_goaway_append( - transport_parsing->last_incoming_stream_id, sp->error_value, - gpr_slice_from_static_string("HTTP2 settings error"), - &transport_parsing->qbuf); - gpr_log(GPR_ERROR, "invalid value %u passed for %s", - parser->value, sp->name); - return GRPC_CHTTP2_CONNECTION_ERROR; - } - } - if (parser->id == GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE && - parser->incoming_settings[parser->id] != parser->value) { - transport_parsing->initial_window_update = - (int64_t)parser->value - parser->incoming_settings[parser->id]; - if (grpc_http_trace) { - gpr_log(GPR_DEBUG, "adding %d for initial_window change", - (int)transport_parsing->initial_window_update); - } - } - parser->incoming_settings[parser->id] = parser->value; - if (grpc_http_trace) { - gpr_log(GPR_DEBUG, "CHTTP2:%s: got setting %d = %d", - transport_parsing->is_client ? "CLI" : "SVR", parser->id, - parser->value); - } - } else { - gpr_log(GPR_ERROR, "CHTTP2: Ignoring unknown setting %d (value %d)", - parser->id, parser->value); - } - break; - } - } -} diff --git a/src/core/lib/transport/chttp2/frame_settings.h b/src/core/lib/transport/chttp2/frame_settings.h deleted file mode 100644 index 8b294de021..0000000000 --- a/src/core/lib/transport/chttp2/frame_settings.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_TRANSPORT_CHTTP2_FRAME_SETTINGS_H -#define GRPC_CORE_LIB_TRANSPORT_CHTTP2_FRAME_SETTINGS_H - -#include <grpc/support/port_platform.h> -#include <grpc/support/slice.h> -#include "src/core/lib/iomgr/exec_ctx.h" -#include "src/core/lib/transport/chttp2/frame.h" - -typedef enum { - GRPC_CHTTP2_SPS_ID0, - GRPC_CHTTP2_SPS_ID1, - GRPC_CHTTP2_SPS_VAL0, - GRPC_CHTTP2_SPS_VAL1, - GRPC_CHTTP2_SPS_VAL2, - GRPC_CHTTP2_SPS_VAL3 -} grpc_chttp2_settings_parse_state; - -/* The things HTTP/2 defines as connection level settings */ -typedef enum { - GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE = 1, - GRPC_CHTTP2_SETTINGS_ENABLE_PUSH = 2, - GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS = 3, - GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE = 4, - GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE = 5, - GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE = 6, - GRPC_CHTTP2_NUM_SETTINGS -} grpc_chttp2_setting_id; - -typedef struct { - grpc_chttp2_settings_parse_state state; - uint32_t *target_settings; - uint8_t is_ack; - uint16_t id; - uint32_t value; - uint32_t incoming_settings[GRPC_CHTTP2_NUM_SETTINGS]; -} grpc_chttp2_settings_parser; - -typedef enum { - GRPC_CHTTP2_CLAMP_INVALID_VALUE, - GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE -} grpc_chttp2_invalid_value_behavior; - -typedef struct { - const char *name; - uint32_t default_value; - uint32_t min_value; - uint32_t max_value; - grpc_chttp2_invalid_value_behavior invalid_value_behavior; - uint32_t error_value; -} grpc_chttp2_setting_parameters; - -/* HTTP/2 mandated connection setting parameters */ -extern const grpc_chttp2_setting_parameters - grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS]; - -/* Create a settings frame by diffing old & new, and updating old to be new */ -gpr_slice grpc_chttp2_settings_create(uint32_t *old, const uint32_t *new, - uint32_t force_mask, size_t count); -/* Create an ack settings frame */ -gpr_slice grpc_chttp2_settings_ack_create(void); - -grpc_chttp2_parse_error grpc_chttp2_settings_parser_begin_frame( - grpc_chttp2_settings_parser *parser, uint32_t length, uint8_t flags, - uint32_t *settings); -grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse( - grpc_exec_ctx *exec_ctx, void *parser, - grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last); - -#endif /* GRPC_CORE_LIB_TRANSPORT_CHTTP2_FRAME_SETTINGS_H */ diff --git a/src/core/lib/transport/chttp2/frame_window_update.c b/src/core/lib/transport/chttp2/frame_window_update.c deleted file mode 100644 index 2ab5003316..0000000000 --- a/src/core/lib/transport/chttp2/frame_window_update.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/lib/transport/chttp2/frame_window_update.h" -#include "src/core/lib/transport/chttp2/internal.h" - -#include <grpc/support/log.h> - -gpr_slice grpc_chttp2_window_update_create(uint32_t id, - uint32_t window_update) { - gpr_slice slice = gpr_slice_malloc(13); - uint8_t *p = GPR_SLICE_START_PTR(slice); - - GPR_ASSERT(window_update); - - *p++ = 0; - *p++ = 0; - *p++ = 4; - *p++ = GRPC_CHTTP2_FRAME_WINDOW_UPDATE; - *p++ = 0; - *p++ = (uint8_t)(id >> 24); - *p++ = (uint8_t)(id >> 16); - *p++ = (uint8_t)(id >> 8); - *p++ = (uint8_t)(id); - *p++ = (uint8_t)(window_update >> 24); - *p++ = (uint8_t)(window_update >> 16); - *p++ = (uint8_t)(window_update >> 8); - *p++ = (uint8_t)(window_update); - - return slice; -} - -grpc_chttp2_parse_error grpc_chttp2_window_update_parser_begin_frame( - grpc_chttp2_window_update_parser *parser, uint32_t length, uint8_t flags) { - if (flags || length != 4) { - gpr_log(GPR_ERROR, "invalid window update: length=%d, flags=%02x", length, - flags); - return GRPC_CHTTP2_CONNECTION_ERROR; - } - parser->byte = 0; - parser->amount = 0; - return GRPC_CHTTP2_PARSE_OK; -} - -grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse( - grpc_exec_ctx *exec_ctx, void *parser, - grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) { - uint8_t *const beg = GPR_SLICE_START_PTR(slice); - uint8_t *const end = GPR_SLICE_END_PTR(slice); - uint8_t *cur = beg; - grpc_chttp2_window_update_parser *p = parser; - - while (p->byte != 4 && cur != end) { - p->amount |= ((uint32_t)*cur) << (8 * (3 - p->byte)); - cur++; - p->byte++; - } - - if (p->byte == 4) { - uint32_t received_update = p->amount; - if (received_update == 0 || (received_update & 0x80000000u)) { - gpr_log(GPR_ERROR, "invalid window update bytes: %d", p->amount); - return GRPC_CHTTP2_CONNECTION_ERROR; - } - GPR_ASSERT(is_last); - - if (transport_parsing->incoming_stream_id != 0) { - if (stream_parsing != NULL) { - GRPC_CHTTP2_FLOW_CREDIT_STREAM("parse", transport_parsing, - stream_parsing, outgoing_window, - received_update); - grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, - stream_parsing); - } - } else { - GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parse", transport_parsing, - outgoing_window, received_update); - } - } - - return GRPC_CHTTP2_PARSE_OK; -} diff --git a/src/core/lib/transport/chttp2/frame_window_update.h b/src/core/lib/transport/chttp2/frame_window_update.h deleted file mode 100644 index 4b1aea294d..0000000000 --- a/src/core/lib/transport/chttp2/frame_window_update.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_TRANSPORT_CHTTP2_FRAME_WINDOW_UPDATE_H -#define GRPC_CORE_LIB_TRANSPORT_CHTTP2_FRAME_WINDOW_UPDATE_H - -#include <grpc/support/slice.h> -#include "src/core/lib/iomgr/exec_ctx.h" -#include "src/core/lib/transport/chttp2/frame.h" - -typedef struct { - uint8_t byte; - uint8_t is_connection_update; - uint32_t amount; -} grpc_chttp2_window_update_parser; - -gpr_slice grpc_chttp2_window_update_create(uint32_t id, uint32_t window_delta); - -grpc_chttp2_parse_error grpc_chttp2_window_update_parser_begin_frame( - grpc_chttp2_window_update_parser *parser, uint32_t length, uint8_t flags); -grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse( - grpc_exec_ctx *exec_ctx, void *parser, - grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last); - -#endif /* GRPC_CORE_LIB_TRANSPORT_CHTTP2_FRAME_WINDOW_UPDATE_H */ diff --git a/src/core/lib/transport/chttp2/hpack_encoder.c b/src/core/lib/transport/chttp2/hpack_encoder.c deleted file mode 100644 index 6b45929b04..0000000000 --- a/src/core/lib/transport/chttp2/hpack_encoder.c +++ /dev/null @@ -1,568 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/lib/transport/chttp2/hpack_encoder.h" - -#include <assert.h> -#include <string.h> - -/* This is here for grpc_is_binary_header - * TODO(murgatroid99): Remove this - */ -#include <grpc/grpc.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/useful.h> - -#include "src/core/lib/transport/chttp2/bin_encoder.h" -#include "src/core/lib/transport/chttp2/hpack_table.h" -#include "src/core/lib/transport/chttp2/timeout_encoding.h" -#include "src/core/lib/transport/chttp2/varint.h" -#include "src/core/lib/transport/static_metadata.h" - -#define HASH_FRAGMENT_1(x) ((x)&255) -#define HASH_FRAGMENT_2(x) ((x >> 8) & 255) -#define HASH_FRAGMENT_3(x) ((x >> 16) & 255) -#define HASH_FRAGMENT_4(x) ((x >> 24) & 255) - -/* if the probability of this item being seen again is < 1/x then don't add - it to the table */ -#define ONE_ON_ADD_PROBABILITY 128 -/* don't consider adding anything bigger than this to the hpack table */ -#define MAX_DECODER_SPACE_USAGE 512 - -typedef struct { - int is_first_frame; - /* number of bytes in 'output' when we started the frame - used to calculate - frame length */ - size_t output_length_at_start_of_frame; - /* index (in output) of the header for the current frame */ - size_t header_idx; - /* have we seen a regular (non-colon-prefixed) header yet? */ - uint8_t seen_regular_header; - /* output stream id */ - uint32_t stream_id; - gpr_slice_buffer *output; -} framer_state; - -/* fills p (which is expected to be 9 bytes long) with a data frame header */ -static void fill_header(uint8_t *p, uint8_t type, uint32_t id, size_t len, - uint8_t flags) { - GPR_ASSERT(len < 16777316); - *p++ = (uint8_t)(len >> 16); - *p++ = (uint8_t)(len >> 8); - *p++ = (uint8_t)(len); - *p++ = type; - *p++ = flags; - *p++ = (uint8_t)(id >> 24); - *p++ = (uint8_t)(id >> 16); - *p++ = (uint8_t)(id >> 8); - *p++ = (uint8_t)(id); -} - -/* finish a frame - fill in the previously reserved header */ -static void finish_frame(framer_state *st, int is_header_boundary, - int is_last_in_stream) { - uint8_t type = 0xff; - type = st->is_first_frame ? GRPC_CHTTP2_FRAME_HEADER - : GRPC_CHTTP2_FRAME_CONTINUATION; - fill_header( - GPR_SLICE_START_PTR(st->output->slices[st->header_idx]), type, - st->stream_id, st->output->length - st->output_length_at_start_of_frame, - (uint8_t)((is_last_in_stream ? GRPC_CHTTP2_DATA_FLAG_END_STREAM : 0) | - (is_header_boundary ? GRPC_CHTTP2_DATA_FLAG_END_HEADERS : 0))); - st->is_first_frame = 0; -} - -/* begin a new frame: reserve off header space, remember how many bytes we'd - output before beginning */ -static void begin_frame(framer_state *st) { - st->header_idx = - gpr_slice_buffer_add_indexed(st->output, gpr_slice_malloc(9)); - st->output_length_at_start_of_frame = st->output->length; -} - -/* make sure that the current frame is of the type desired, and has sufficient - space to add at least about_to_add bytes -- finishes the current frame if - needed */ -static void ensure_space(framer_state *st, size_t need_bytes) { - if (st->output->length - st->output_length_at_start_of_frame + need_bytes <= - GRPC_CHTTP2_MAX_PAYLOAD_LENGTH) { - return; - } - finish_frame(st, 0, 0); - begin_frame(st); -} - -/* increment a filter count, halve all counts if one element reaches max */ -static void inc_filter(uint8_t idx, uint32_t *sum, uint8_t *elems) { - elems[idx]++; - if (elems[idx] < 255) { - (*sum)++; - } else { - int i; - *sum = 0; - for (i = 0; i < GRPC_CHTTP2_HPACKC_NUM_FILTERS; i++) { - elems[i] /= 2; - (*sum) += elems[i]; - } - } -} - -static void add_header_data(framer_state *st, gpr_slice slice) { - size_t len = GPR_SLICE_LENGTH(slice); - size_t remaining; - if (len == 0) return; - remaining = GRPC_CHTTP2_MAX_PAYLOAD_LENGTH + - st->output_length_at_start_of_frame - st->output->length; - if (len <= remaining) { - gpr_slice_buffer_add(st->output, slice); - } else { - gpr_slice_buffer_add(st->output, gpr_slice_split_head(&slice, remaining)); - finish_frame(st, 0, 0); - begin_frame(st); - add_header_data(st, slice); - } -} - -static uint8_t *add_tiny_header_data(framer_state *st, size_t len) { - ensure_space(st, 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 = - (uint16_t)(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) { - uint32_t key_hash = elem->key->hash; - uint32_t elem_hash = GRPC_MDSTR_KV_HASH(key_hash, elem->value->hash); - uint32_t new_index = c->tail_remote_index + c->table_elems + 1; - size_t elem_size = 32 + GPR_SLICE_LENGTH(elem->key->slice) + - GPR_SLICE_LENGTH(elem->value->slice); - - 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 */ - while (c->table_size + elem_size > c->max_table_size) { - evict_entry(c); - } - GPR_ASSERT(c->table_elems < c->max_table_size); - c->table_elem_size[new_index % c->cap_table_elems] = (uint16_t)elem_size; - c->table_size = (uint16_t)(c->table_size + elem_size); - c->table_elems++; - - /* Store this element into {entries,indices}_elem */ - if (c->entries_elems[HASH_FRAGMENT_2(elem_hash)] == elem) { - /* already there: update with new index */ - c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index; - } else if (c->entries_elems[HASH_FRAGMENT_3(elem_hash)] == elem) { - /* already there (cuckoo): update with new index */ - c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index; - } else if (c->entries_elems[HASH_FRAGMENT_2(elem_hash)] == NULL) { - /* not there, but a free element: add */ - c->entries_elems[HASH_FRAGMENT_2(elem_hash)] = GRPC_MDELEM_REF(elem); - c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index; - } else if (c->entries_elems[HASH_FRAGMENT_3(elem_hash)] == NULL) { - /* not there (cuckoo), but a free element: add */ - c->entries_elems[HASH_FRAGMENT_3(elem_hash)] = GRPC_MDELEM_REF(elem); - c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index; - } else if (c->indices_elems[HASH_FRAGMENT_2(elem_hash)] < - c->indices_elems[HASH_FRAGMENT_3(elem_hash)]) { - /* not there: replace oldest */ - GRPC_MDELEM_UNREF(c->entries_elems[HASH_FRAGMENT_2(elem_hash)]); - c->entries_elems[HASH_FRAGMENT_2(elem_hash)] = GRPC_MDELEM_REF(elem); - c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index; - } else { - /* not there: replace oldest */ - GRPC_MDELEM_UNREF(c->entries_elems[HASH_FRAGMENT_3(elem_hash)]); - c->entries_elems[HASH_FRAGMENT_3(elem_hash)] = GRPC_MDELEM_REF(elem); - c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index; - } - - /* do exactly the same for the key (so we can find by that again too) */ - - if (c->entries_keys[HASH_FRAGMENT_2(key_hash)] == elem->key) { - c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index; - } else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == elem->key) { - c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index; - } else if (c->entries_keys[HASH_FRAGMENT_2(key_hash)] == NULL) { - c->entries_keys[HASH_FRAGMENT_2(key_hash)] = GRPC_MDSTR_REF(elem->key); - c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index; - } else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == NULL) { - c->entries_keys[HASH_FRAGMENT_3(key_hash)] = GRPC_MDSTR_REF(elem->key); - c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index; - } else if (c->indices_keys[HASH_FRAGMENT_2(key_hash)] < - c->indices_keys[HASH_FRAGMENT_3(key_hash)]) { - GRPC_MDSTR_UNREF(c->entries_keys[HASH_FRAGMENT_2(key_hash)]); - c->entries_keys[HASH_FRAGMENT_2(key_hash)] = GRPC_MDSTR_REF(elem->key); - c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index; - } else { - GRPC_MDSTR_UNREF(c->entries_keys[HASH_FRAGMENT_3(key_hash)]); - c->entries_keys[HASH_FRAGMENT_3(key_hash)] = GRPC_MDSTR_REF(elem->key); - c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index; - } -} - -static void emit_indexed(grpc_chttp2_hpack_compressor *c, uint32_t elem_index, - framer_state *st) { - uint32_t len = GRPC_CHTTP2_VARINT_LENGTH(elem_index, 1); - GRPC_CHTTP2_WRITE_VARINT(elem_index, 1, 0x80, add_tiny_header_data(st, len), - len); -} - -static gpr_slice get_wire_value(grpc_mdelem *elem, uint8_t *huffman_prefix) { - if (grpc_is_binary_header((const char *)GPR_SLICE_START_PTR(elem->key->slice), - GPR_SLICE_LENGTH(elem->key->slice))) { - *huffman_prefix = 0x80; - return grpc_mdstr_as_base64_encoded_and_huffman_compressed(elem->value); - } - /* TODO(ctiller): opportunistically compress non-binary headers */ - *huffman_prefix = 0x00; - return elem->value->slice; -} - -static void emit_lithdr_incidx(grpc_chttp2_hpack_compressor *c, - uint32_t key_index, grpc_mdelem *elem, - framer_state *st) { - uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 2); - uint8_t huffman_prefix; - gpr_slice value_slice = get_wire_value(elem, &huffman_prefix); - size_t len_val = GPR_SLICE_LENGTH(value_slice); - uint32_t len_val_len; - GPR_ASSERT(len_val <= UINT32_MAX); - len_val_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)len_val, 1); - GRPC_CHTTP2_WRITE_VARINT(key_index, 2, 0x40, - add_tiny_header_data(st, len_pfx), len_pfx); - GRPC_CHTTP2_WRITE_VARINT((uint32_t)len_val, 1, huffman_prefix, - add_tiny_header_data(st, len_val_len), len_val_len); - add_header_data(st, gpr_slice_ref(value_slice)); -} - -static void emit_lithdr_noidx(grpc_chttp2_hpack_compressor *c, - uint32_t key_index, grpc_mdelem *elem, - framer_state *st) { - uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 4); - uint8_t huffman_prefix; - gpr_slice value_slice = get_wire_value(elem, &huffman_prefix); - size_t len_val = GPR_SLICE_LENGTH(value_slice); - uint32_t len_val_len; - GPR_ASSERT(len_val <= UINT32_MAX); - len_val_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)len_val, 1); - GRPC_CHTTP2_WRITE_VARINT(key_index, 4, 0x00, - add_tiny_header_data(st, len_pfx), len_pfx); - GRPC_CHTTP2_WRITE_VARINT((uint32_t)len_val, 1, huffman_prefix, - add_tiny_header_data(st, len_val_len), len_val_len); - add_header_data(st, gpr_slice_ref(value_slice)); -} - -static void emit_lithdr_incidx_v(grpc_chttp2_hpack_compressor *c, - grpc_mdelem *elem, framer_state *st) { - uint32_t len_key = (uint32_t)GPR_SLICE_LENGTH(elem->key->slice); - uint8_t huffman_prefix; - gpr_slice value_slice = get_wire_value(elem, &huffman_prefix); - uint32_t len_val = (uint32_t)GPR_SLICE_LENGTH(value_slice); - uint32_t len_key_len = GRPC_CHTTP2_VARINT_LENGTH(len_key, 1); - uint32_t len_val_len = GRPC_CHTTP2_VARINT_LENGTH(len_val, 1); - GPR_ASSERT(len_key <= UINT32_MAX); - GPR_ASSERT(GPR_SLICE_LENGTH(value_slice) <= UINT32_MAX); - *add_tiny_header_data(st, 1) = 0x40; - GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00, - add_tiny_header_data(st, len_key_len), len_key_len); - add_header_data(st, gpr_slice_ref(elem->key->slice)); - GRPC_CHTTP2_WRITE_VARINT(len_val, 1, huffman_prefix, - add_tiny_header_data(st, len_val_len), len_val_len); - add_header_data(st, gpr_slice_ref(value_slice)); -} - -static void emit_lithdr_noidx_v(grpc_chttp2_hpack_compressor *c, - grpc_mdelem *elem, framer_state *st) { - uint32_t len_key = (uint32_t)GPR_SLICE_LENGTH(elem->key->slice); - uint8_t huffman_prefix; - gpr_slice value_slice = get_wire_value(elem, &huffman_prefix); - uint32_t len_val = (uint32_t)GPR_SLICE_LENGTH(value_slice); - uint32_t len_key_len = GRPC_CHTTP2_VARINT_LENGTH(len_key, 1); - uint32_t len_val_len = GRPC_CHTTP2_VARINT_LENGTH(len_val, 1); - GPR_ASSERT(len_key <= UINT32_MAX); - GPR_ASSERT(GPR_SLICE_LENGTH(value_slice) <= UINT32_MAX); - *add_tiny_header_data(st, 1) = 0x00; - GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00, - add_tiny_header_data(st, len_key_len), len_key_len); - add_header_data(st, gpr_slice_ref(elem->key->slice)); - GRPC_CHTTP2_WRITE_VARINT(len_val, 1, huffman_prefix, - add_tiny_header_data(st, len_val_len), len_val_len); - add_header_data(st, gpr_slice_ref(value_slice)); -} - -static void emit_advertise_table_size_change(grpc_chttp2_hpack_compressor *c, - framer_state *st) { - uint32_t 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 uint32_t dynidx(grpc_chttp2_hpack_compressor *c, uint32_t elem_index) { - return 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY + c->tail_remote_index + - c->table_elems - elem_index; -} - -/* encode an mdelem */ -static void hpack_enc(grpc_chttp2_hpack_compressor *c, grpc_mdelem *elem, - framer_state *st) { - uint32_t key_hash = elem->key->hash; - uint32_t elem_hash = GRPC_MDSTR_KV_HASH(key_hash, elem->value->hash); - size_t decoder_space_usage; - uint32_t indices_key; - int should_add_elem; - - GPR_ASSERT(GPR_SLICE_LENGTH(elem->key->slice) > 0); - if (GPR_SLICE_START_PTR(elem->key->slice)[0] != ':') { /* regular header */ - st->seen_regular_header = 1; - } else { - GPR_ASSERT( - st->seen_regular_header == 0 && - "Reserved header (colon-prefixed) happening after regular ones."); - } - - inc_filter(HASH_FRAGMENT_1(elem_hash), &c->filter_elems_sum, c->filter_elems); - - /* is this elem currently in the decoders table? */ - - if (c->entries_elems[HASH_FRAGMENT_2(elem_hash)] == elem && - c->indices_elems[HASH_FRAGMENT_2(elem_hash)] > c->tail_remote_index) { - /* HIT: complete element (first cuckoo hash) */ - emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_2(elem_hash)]), - st); - return; - } - - if (c->entries_elems[HASH_FRAGMENT_3(elem_hash)] == elem && - c->indices_elems[HASH_FRAGMENT_3(elem_hash)] > c->tail_remote_index) { - /* HIT: complete element (second cuckoo hash) */ - emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_3(elem_hash)]), - st); - return; - } - - /* should this elem be in the table? */ - decoder_space_usage = 32 + GPR_SLICE_LENGTH(elem->key->slice) + - GPR_SLICE_LENGTH(elem->value->slice); - should_add_elem = decoder_space_usage < MAX_DECODER_SPACE_USAGE && - c->filter_elems[HASH_FRAGMENT_1(elem_hash)] >= - c->filter_elems_sum / ONE_ON_ADD_PROBABILITY; - - /* no hits for the elem... maybe there's a key? */ - - indices_key = c->indices_keys[HASH_FRAGMENT_2(key_hash)]; - if (c->entries_keys[HASH_FRAGMENT_2(key_hash)] == elem->key && - indices_key > c->tail_remote_index) { - /* HIT: key (first cuckoo hash) */ - if (should_add_elem) { - emit_lithdr_incidx(c, dynidx(c, indices_key), elem, st); - add_elem(c, elem); - return; - } else { - emit_lithdr_noidx(c, dynidx(c, indices_key), elem, st); - return; - } - GPR_UNREACHABLE_CODE(return ); - } - - indices_key = c->indices_keys[HASH_FRAGMENT_3(key_hash)]; - if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == elem->key && - indices_key > c->tail_remote_index) { - /* HIT: key (first cuckoo hash) */ - if (should_add_elem) { - emit_lithdr_incidx(c, dynidx(c, indices_key), elem, st); - add_elem(c, elem); - return; - } else { - emit_lithdr_noidx(c, dynidx(c, indices_key), elem, st); - return; - } - GPR_UNREACHABLE_CODE(return ); - } - - /* no elem, key in the table... fall back to literal emission */ - - if (should_add_elem) { - emit_lithdr_incidx_v(c, elem, st); - add_elem(c, elem); - return; - } else { - emit_lithdr_noidx_v(c, elem, st); - return; - } - GPR_UNREACHABLE_CODE(return ); -} - -#define STRLEN_LIT(x) (sizeof(x) - 1) -#define TIMEOUT_KEY "grpc-timeout" - -static void deadline_enc(grpc_chttp2_hpack_compressor *c, gpr_timespec deadline, - framer_state *st) { - char timeout_str[GRPC_CHTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE]; - grpc_mdelem *mdelem; - grpc_chttp2_encode_timeout( - gpr_time_sub(deadline, gpr_now(deadline.clock_type)), timeout_str); - mdelem = grpc_mdelem_from_metadata_strings( - GRPC_MDSTR_GRPC_TIMEOUT, grpc_mdstr_from_string(timeout_str)); - hpack_enc(c, mdelem, st); - GRPC_MDELEM_UNREF(mdelem); -} - -static uint32_t elems_for_bytes(uint32_t bytes) { return (bytes + 31) / 32; } - -void grpc_chttp2_hpack_compressor_init(grpc_chttp2_hpack_compressor *c) { - memset(c, 0, sizeof(*c)); - 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) { - int i; - for (i = 0; i < GRPC_CHTTP2_HPACKC_NUM_VALUES; i++) { - if (c->entries_keys[i]) GRPC_MDSTR_UNREF(c->entries_keys[i]); - if (c->entries_elems[i]) GRPC_MDELEM_UNREF(c->entries_elems[i]); - } - gpr_free(c->table_elem_size); -} - -void grpc_chttp2_hpack_compressor_set_max_usable_size( - grpc_chttp2_hpack_compressor *c, uint32_t 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, uint32_t new_cap) { - uint16_t *table_elem_size = gpr_malloc(sizeof(*table_elem_size) * new_cap); - uint32_t 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++) { - uint32_t 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, uint32_t 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) { - uint32_t 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, - uint32_t stream_id, - grpc_metadata_batch *metadata, int is_eof, - gpr_slice_buffer *outbuf) { - framer_state st; - grpc_linked_mdelem *l; - gpr_timespec deadline; - - GPR_ASSERT(stream_id != 0); - - st.seen_regular_header = 0; - st.stream_id = stream_id; - st.output = outbuf; - st.is_first_frame = 1; - - /* Encode a metadata batch; store the returned values, representing - a metadata element that needs to be unreffed back into the metadata - 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); - } - deadline = metadata->deadline; - if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) != 0) { - deadline_enc(c, deadline, &st); - } - - finish_frame(&st, 1, is_eof); -} diff --git a/src/core/lib/transport/chttp2/hpack_encoder.h b/src/core/lib/transport/chttp2/hpack_encoder.h deleted file mode 100644 index de46a8f146..0000000000 --- a/src/core/lib/transport/chttp2/hpack_encoder.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_TRANSPORT_CHTTP2_HPACK_ENCODER_H -#define GRPC_CORE_LIB_TRANSPORT_CHTTP2_HPACK_ENCODER_H - -#include <grpc/support/port_platform.h> -#include <grpc/support/slice.h> -#include <grpc/support/slice_buffer.h> -#include "src/core/lib/transport/chttp2/frame.h" -#include "src/core/lib/transport/metadata.h" -#include "src/core/lib/transport/metadata_batch.h" - -#define GRPC_CHTTP2_HPACKC_NUM_FILTERS 256 -#define GRPC_CHTTP2_HPACKC_NUM_VALUES 256 -/* 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 { - uint32_t filter_elems_sum; - uint32_t max_table_size; - uint32_t max_table_elems; - uint32_t cap_table_elems; - /** if non-zero, advertise to the decoder that we'll start using a table - of this size */ - uint8_t 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) */ - uint32_t max_usable_size; - /* one before the lowest usable table index */ - uint32_t tail_remote_index; - uint32_t table_size; - uint32_t table_elems; - - /* filter tables for elems: this tables provides an approximate - popularity count for particular hashes, and are used to determine whether - a new literal should be added to the compression table or not. - They track a single integer that counts how often a particular value has - been seen. When that count reaches max (255), all values are halved. */ - uint8_t filter_elems[GRPC_CHTTP2_HPACKC_NUM_FILTERS]; - - /* entry tables for keys & elems: these tables track values that have been - seen and *may* be in the decompressor table */ - grpc_mdstr *entries_keys[GRPC_CHTTP2_HPACKC_NUM_VALUES]; - grpc_mdelem *entries_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES]; - uint32_t indices_keys[GRPC_CHTTP2_HPACKC_NUM_VALUES]; - uint32_t indices_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES]; - - uint16_t *table_elem_size; -} grpc_chttp2_hpack_compressor; - -void grpc_chttp2_hpack_compressor_init(grpc_chttp2_hpack_compressor *c); -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, uint32_t max_table_size); -void grpc_chttp2_hpack_compressor_set_max_usable_size( - grpc_chttp2_hpack_compressor *c, uint32_t max_table_size); - -void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor *c, uint32_t id, - grpc_metadata_batch *metadata, int is_eof, - gpr_slice_buffer *outbuf); - -#endif /* GRPC_CORE_LIB_TRANSPORT_CHTTP2_HPACK_ENCODER_H */ diff --git a/src/core/lib/transport/chttp2/hpack_parser.c b/src/core/lib/transport/chttp2/hpack_parser.c deleted file mode 100644 index d41ebab147..0000000000 --- a/src/core/lib/transport/chttp2/hpack_parser.c +++ /dev/null @@ -1,1449 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/lib/transport/chttp2/hpack_parser.h" -#include "src/core/lib/transport/chttp2/internal.h" - -#include <assert.h> -#include <stddef.h> -#include <string.h> - -/* This is here for grpc_is_binary_header - * TODO(murgatroid99): Remove this - */ -#include <grpc/grpc.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/port_platform.h> -#include <grpc/support/useful.h> - -#include "src/core/lib/profiling/timers.h" -#include "src/core/lib/support/string.h" -#include "src/core/lib/transport/chttp2/bin_encoder.h" - -typedef enum { - NOT_BINARY, - B64_BYTE0, - B64_BYTE1, - B64_BYTE2, - B64_BYTE3 -} binary_state; - -/* How parsing works: - - The parser object keeps track of a function pointer which represents the - current parse state. - - Each time new bytes are presented, we call into the current state, which - recursively parses until all bytes in the given chunk are exhausted. - - The parse state that terminates then saves its function pointer to be the - current state so that it can resume when more bytes are available. - - It's expected that most optimizing compilers will turn this code into - a set of indirect jumps, and so not waste stack space. */ - -/* forward declarations for parsing states */ -static int parse_begin(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end); -static int parse_error(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end); -static int parse_illegal_op(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end); - -static int parse_string_prefix(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end); -static int parse_key_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end); -static int parse_value_string_with_indexed_key(grpc_chttp2_hpack_parser *p, - const uint8_t *cur, - const uint8_t *end); -static int parse_value_string_with_literal_key(grpc_chttp2_hpack_parser *p, - const uint8_t *cur, - const uint8_t *end); - -static int parse_value0(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end); -static int parse_value1(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end); -static int parse_value2(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end); -static int parse_value3(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end); -static int parse_value4(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end); -static int parse_value5up(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end); - -static int parse_indexed_field(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end); -static int parse_indexed_field_x(grpc_chttp2_hpack_parser *p, - const uint8_t *cur, const uint8_t *end); -static int parse_lithdr_incidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end); -static int parse_lithdr_incidx_x(grpc_chttp2_hpack_parser *p, - const uint8_t *cur, const uint8_t *end); -static int parse_lithdr_incidx_v(grpc_chttp2_hpack_parser *p, - const uint8_t *cur, const uint8_t *end); -static int parse_lithdr_notidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end); -static int parse_lithdr_notidx_x(grpc_chttp2_hpack_parser *p, - const uint8_t *cur, const uint8_t *end); -static int parse_lithdr_notidx_v(grpc_chttp2_hpack_parser *p, - const uint8_t *cur, const uint8_t *end); -static int parse_lithdr_nvridx(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end); -static int parse_lithdr_nvridx_x(grpc_chttp2_hpack_parser *p, - const uint8_t *cur, const uint8_t *end); -static int parse_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p, - const uint8_t *cur, const uint8_t *end); -static int parse_max_tbl_size(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end); -static int parse_max_tbl_size_x(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end); - -/* we translate the first byte of a hpack field into one of these decoding - cases, then use a lookup table to jump directly to the appropriate parser. - - _X => the integer index is all ones, meaning we need to do varint decoding - _V => the integer index is all zeros, meaning we need to decode an additional - string value */ -typedef enum { - INDEXED_FIELD, - INDEXED_FIELD_X, - LITHDR_INCIDX, - LITHDR_INCIDX_X, - LITHDR_INCIDX_V, - LITHDR_NOTIDX, - LITHDR_NOTIDX_X, - LITHDR_NOTIDX_V, - LITHDR_NVRIDX, - LITHDR_NVRIDX_X, - LITHDR_NVRIDX_V, - MAX_TBL_SIZE, - MAX_TBL_SIZE_X, - ILLEGAL -} first_byte_type; - -/* jump table of parse state functions -- order must match first_byte_type - above */ -static const grpc_chttp2_hpack_parser_state first_byte_action[] = { - parse_indexed_field, parse_indexed_field_x, parse_lithdr_incidx, - 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_illegal_op}; - -/* indexes the first byte to a parse state function - generated by - gen_hpack_tables.c */ -static const uint8_t first_byte_lut[256] = { - LITHDR_NOTIDX_V, LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX, - LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX, - LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX, - LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX_X, - LITHDR_NVRIDX_V, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, - 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, - 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, 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_X, - LITHDR_INCIDX_V, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, - LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, - LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, - LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, - LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, - LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, - LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, - LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, - LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, - LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, - LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, - LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, - LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, - LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, - LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, - LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX_X, - ILLEGAL, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, - INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD_X, -}; - -/* state table for huffman decoding: given a state, gives an index/16 into - next_sub_tbl. Taking that index and adding the value of the nibble being - considered returns the next state. - - generated by gen_hpack_tables.c */ -static const uint8_t next_tbl[256] = { - 0, 1, 2, 3, 4, 1, 2, 5, 6, 1, 7, 8, 1, 3, 3, 9, 10, 11, 1, 1, - 1, 12, 1, 2, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, - 14, 1, 15, 16, 1, 17, 1, 15, 2, 7, 3, 18, 19, 1, 1, 1, 1, 20, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 15, 2, 2, 7, 21, 1, 22, 1, 1, 1, 1, 1, - 1, 1, 1, 15, 2, 2, 2, 2, 2, 2, 23, 24, 25, 1, 1, 1, 1, 2, 2, 2, - 26, 3, 3, 27, 10, 28, 1, 1, 1, 1, 1, 1, 2, 3, 29, 10, 30, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 31, 1, 1, 1, 1, 1, 1, 1, 2, - 2, 2, 2, 2, 2, 2, 2, 32, 1, 1, 15, 33, 1, 34, 35, 9, 36, 1, 1, 1, - 1, 1, 1, 1, 37, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 26, 9, - 38, 1, 1, 1, 1, 1, 1, 1, 15, 2, 2, 2, 2, 26, 3, 3, 39, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 7, 3, 3, 3, 40, 2, - 41, 1, 1, 1, 42, 43, 1, 1, 44, 1, 1, 1, 1, 15, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 45, 46, 1, 1, 2, 2, 2, 35, 3, 3, 18, 47, 2, -}; - -/* next state, based upon current state and the current nibble: see above. - generated by gen_hpack_tables.c */ -static const int16_t next_sub_tbl[48 * 16] = { - 1, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, - 218, 2, 6, 10, 13, 14, 15, 16, 17, 2, 6, 10, 13, 14, 15, - 16, 17, 3, 7, 11, 24, 3, 7, 11, 24, 3, 7, 11, 24, 3, - 7, 11, 24, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, - 4, 8, 4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, - 199, 200, 201, 202, 203, 4, 8, 4, 8, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 9, 133, 134, 135, 136, 137, 138, 139, 140, - 141, 142, 143, 144, 145, 146, 147, 3, 7, 11, 24, 3, 7, 11, 24, - 4, 8, 4, 8, 4, 8, 4, 8, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 12, 132, 4, 8, 4, 8, 4, 8, - 4, 8, 4, 8, 4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 18, 19, 20, 21, 4, 8, 4, - 8, 4, 8, 4, 8, 4, 8, 0, 0, 0, 22, 23, 91, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 3, - 7, 11, 24, 3, 7, 11, 24, 0, 0, 0, 0, 0, 41, 42, 43, - 2, 6, 10, 13, 14, 15, 16, 17, 3, 7, 11, 24, 3, 7, 11, - 24, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 0, 0, - 44, 45, 2, 6, 10, 13, 14, 15, 16, 17, 46, 47, 48, 49, 50, - 51, 52, 57, 4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 53, 54, 55, 56, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 73, 75, 76, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 88, 89, 90, 3, 7, 11, 24, 3, 7, 11, - 24, 3, 7, 11, 24, 0, 0, 0, 0, 3, 7, 11, 24, 3, 7, - 11, 24, 4, 8, 4, 8, 0, 0, 0, 92, 0, 0, 0, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 3, 7, 11, 24, - 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, - 8, 4, 8, 4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 4, - 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 0, 0, - 0, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, - 131, 2, 6, 10, 13, 14, 15, 16, 17, 4, 8, 4, 8, 4, 8, - 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 148, - 149, 150, 151, 3, 7, 11, 24, 4, 8, 4, 8, 0, 0, 0, 0, - 0, 0, 152, 153, 3, 7, 11, 24, 3, 7, 11, 24, 3, 7, 11, - 24, 154, 155, 156, 164, 3, 7, 11, 24, 3, 7, 11, 24, 3, 7, - 11, 24, 4, 8, 4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 157, 158, 159, 160, 161, 162, 163, 165, 166, 167, 168, 169, 170, 171, 172, - 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, 196, 4, 8, 4, 8, 4, 8, - 4, 8, 4, 8, 4, 8, 4, 8, 197, 198, 4, 8, 4, 8, 4, - 8, 4, 8, 0, 0, 0, 0, 0, 0, 219, 220, 3, 7, 11, 24, - 4, 8, 4, 8, 4, 8, 0, 0, 221, 222, 223, 224, 3, 7, 11, - 24, 3, 7, 11, 24, 4, 8, 4, 8, 4, 8, 225, 228, 4, 8, - 4, 8, 4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 226, 227, 229, - 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, - 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 245, 246, 247, 248, 249, 250, 251, 252, - 253, 254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 255, -}; - -/* emission table: indexed like next_tbl, ultimately gives the byte to be - emitted, or -1 for no byte, or 256 for end of stream - - generated by gen_hpack_tables.c */ -static const uint16_t emit_tbl[256] = { - 0, 1, 2, 3, 4, 5, 6, 7, 0, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 0, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 0, - 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 0, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, - 0, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, - 219, 220, 221, 0, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, - 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, -}; - -/* generated by gen_hpack_tables.c */ -static const int16_t emit_sub_tbl[249 * 16] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, - 49, 49, 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 97, - 97, 97, 97, 48, 48, 49, 49, 50, 50, 97, 97, 99, 99, 101, 101, - 105, 105, 111, 111, 48, 49, 50, 97, 99, 101, 105, 111, 115, 116, -1, - -1, -1, -1, -1, -1, 32, 32, 32, 32, 32, 32, 32, 32, 37, 37, - 37, 37, 37, 37, 37, 37, 99, 99, 99, 99, 101, 101, 101, 101, 105, - 105, 105, 105, 111, 111, 111, 111, 115, 115, 116, 116, 32, 37, 45, 46, - 47, 51, 52, 53, 54, 55, 56, 57, 61, 61, 61, 61, 61, 61, 61, - 61, 65, 65, 65, 65, 65, 65, 65, 65, 115, 115, 115, 115, 116, 116, - 116, 116, 32, 32, 37, 37, 45, 45, 46, 46, 61, 65, 95, 98, 100, - 102, 103, 104, 108, 109, 110, 112, 114, 117, -1, -1, 58, 58, 58, 58, - 58, 58, 58, 58, 66, 66, 66, 66, 66, 66, 66, 66, 47, 47, 51, - 51, 52, 52, 53, 53, 54, 54, 55, 55, 56, 56, 57, 57, 61, 61, - 65, 65, 95, 95, 98, 98, 100, 100, 102, 102, 103, 103, 104, 104, 108, - 108, 109, 109, 110, 110, 112, 112, 114, 114, 117, 117, 58, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 89, 106, 107, 113, 118, 119, 120, 121, 122, -1, -1, - -1, -1, 38, 38, 38, 38, 38, 38, 38, 38, 42, 42, 42, 42, 42, - 42, 42, 42, 44, 44, 44, 44, 44, 44, 44, 44, 59, 59, 59, 59, - 59, 59, 59, 59, 88, 88, 88, 88, 88, 88, 88, 88, 90, 90, 90, - 90, 90, 90, 90, 90, 33, 33, 34, 34, 40, 40, 41, 41, 63, 63, - 39, 43, 124, -1, -1, -1, 35, 35, 35, 35, 35, 35, 35, 35, 62, - 62, 62, 62, 62, 62, 62, 62, 0, 0, 0, 0, 36, 36, 36, 36, - 64, 64, 64, 64, 91, 91, 91, 91, 69, 69, 69, 69, 69, 69, 69, - 69, 70, 70, 70, 70, 70, 70, 70, 70, 71, 71, 71, 71, 71, 71, - 71, 71, 72, 72, 72, 72, 72, 72, 72, 72, 73, 73, 73, 73, 73, - 73, 73, 73, 74, 74, 74, 74, 74, 74, 74, 74, 75, 75, 75, 75, - 75, 75, 75, 75, 76, 76, 76, 76, 76, 76, 76, 76, 77, 77, 77, - 77, 77, 77, 77, 77, 78, 78, 78, 78, 78, 78, 78, 78, 79, 79, - 79, 79, 79, 79, 79, 79, 80, 80, 80, 80, 80, 80, 80, 80, 81, - 81, 81, 81, 81, 81, 81, 81, 82, 82, 82, 82, 82, 82, 82, 82, - 83, 83, 83, 83, 83, 83, 83, 83, 84, 84, 84, 84, 84, 84, 84, - 84, 85, 85, 85, 85, 85, 85, 85, 85, 86, 86, 86, 86, 86, 86, - 86, 86, 87, 87, 87, 87, 87, 87, 87, 87, 89, 89, 89, 89, 89, - 89, 89, 89, 106, 106, 106, 106, 106, 106, 106, 106, 107, 107, 107, 107, - 107, 107, 107, 107, 113, 113, 113, 113, 113, 113, 113, 113, 118, 118, 118, - 118, 118, 118, 118, 118, 119, 119, 119, 119, 119, 119, 119, 119, 120, 120, - 120, 120, 120, 120, 120, 120, 121, 121, 121, 121, 121, 121, 121, 121, 122, - 122, 122, 122, 122, 122, 122, 122, 38, 38, 38, 38, 42, 42, 42, 42, - 44, 44, 44, 44, 59, 59, 59, 59, 88, 88, 88, 88, 90, 90, 90, - 90, 33, 34, 40, 41, 63, -1, -1, -1, 39, 39, 39, 39, 39, 39, - 39, 39, 43, 43, 43, 43, 43, 43, 43, 43, 124, 124, 124, 124, 124, - 124, 124, 124, 35, 35, 35, 35, 62, 62, 62, 62, 0, 0, 36, 36, - 64, 64, 91, 91, 93, 93, 126, 126, 94, 125, -1, -1, 60, 60, 60, - 60, 60, 60, 60, 60, 96, 96, 96, 96, 96, 96, 96, 96, 123, 123, - 123, 123, 123, 123, 123, 123, -1, -1, -1, -1, -1, -1, -1, -1, 92, - 92, 92, 92, 92, 92, 92, 92, 195, 195, 195, 195, 195, 195, 195, 195, - 208, 208, 208, 208, 208, 208, 208, 208, 128, 128, 128, 128, 130, 130, 130, - 130, 131, 131, 131, 131, 162, 162, 162, 162, 184, 184, 184, 184, 194, 194, - 194, 194, 224, 224, 224, 224, 226, 226, 226, 226, 153, 153, 161, 161, 167, - 167, 172, 172, 176, 176, 177, 177, 179, 179, 209, 209, 216, 216, 217, 217, - 227, 227, 229, 229, 230, 230, 129, 132, 133, 134, 136, 146, 154, 156, 160, - 163, 164, 169, 170, 173, 178, 181, 185, 186, 187, 189, 190, 196, 198, 228, - 232, 233, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 135, - 135, 135, 135, 135, 135, 135, 135, 137, 137, 137, 137, 137, 137, 137, 137, - 138, 138, 138, 138, 138, 138, 138, 138, 139, 139, 139, 139, 139, 139, 139, - 139, 140, 140, 140, 140, 140, 140, 140, 140, 141, 141, 141, 141, 141, 141, - 141, 141, 143, 143, 143, 143, 143, 143, 143, 143, 147, 147, 147, 147, 147, - 147, 147, 147, 149, 149, 149, 149, 149, 149, 149, 149, 150, 150, 150, 150, - 150, 150, 150, 150, 151, 151, 151, 151, 151, 151, 151, 151, 152, 152, 152, - 152, 152, 152, 152, 152, 155, 155, 155, 155, 155, 155, 155, 155, 157, 157, - 157, 157, 157, 157, 157, 157, 158, 158, 158, 158, 158, 158, 158, 158, 165, - 165, 165, 165, 165, 165, 165, 165, 166, 166, 166, 166, 166, 166, 166, 166, - 168, 168, 168, 168, 168, 168, 168, 168, 174, 174, 174, 174, 174, 174, 174, - 174, 175, 175, 175, 175, 175, 175, 175, 175, 180, 180, 180, 180, 180, 180, - 180, 180, 182, 182, 182, 182, 182, 182, 182, 182, 183, 183, 183, 183, 183, - 183, 183, 183, 188, 188, 188, 188, 188, 188, 188, 188, 191, 191, 191, 191, - 191, 191, 191, 191, 197, 197, 197, 197, 197, 197, 197, 197, 231, 231, 231, - 231, 231, 231, 231, 231, 239, 239, 239, 239, 239, 239, 239, 239, 9, 9, - 9, 9, 142, 142, 142, 142, 144, 144, 144, 144, 145, 145, 145, 145, 148, - 148, 148, 148, 159, 159, 159, 159, 171, 171, 171, 171, 206, 206, 206, 206, - 215, 215, 215, 215, 225, 225, 225, 225, 236, 236, 236, 236, 237, 237, 237, - 237, 199, 199, 207, 207, 234, 234, 235, 235, 192, 193, 200, 201, 202, 205, - 210, 213, 218, 219, 238, 240, 242, 243, 255, -1, 203, 203, 203, 203, 203, - 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 211, 211, 211, 211, - 211, 211, 211, 211, 212, 212, 212, 212, 212, 212, 212, 212, 214, 214, 214, - 214, 214, 214, 214, 214, 221, 221, 221, 221, 221, 221, 221, 221, 222, 222, - 222, 222, 222, 222, 222, 222, 223, 223, 223, 223, 223, 223, 223, 223, 241, - 241, 241, 241, 241, 241, 241, 241, 244, 244, 244, 244, 244, 244, 244, 244, - 245, 245, 245, 245, 245, 245, 245, 245, 246, 246, 246, 246, 246, 246, 246, - 246, 247, 247, 247, 247, 247, 247, 247, 247, 248, 248, 248, 248, 248, 248, - 248, 248, 250, 250, 250, 250, 250, 250, 250, 250, 251, 251, 251, 251, 251, - 251, 251, 251, 252, 252, 252, 252, 252, 252, 252, 252, 253, 253, 253, 253, - 253, 253, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 2, 2, 2, - 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, - 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 11, 11, 11, 11, 12, - 12, 12, 12, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, - 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, - 20, 21, 21, 21, 21, 23, 23, 23, 23, 24, 24, 24, 24, 25, 25, - 25, 25, 26, 26, 26, 26, 27, 27, 27, 27, 28, 28, 28, 28, 29, - 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 127, 127, 127, 127, - 220, 220, 220, 220, 249, 249, 249, 249, 10, 13, 22, 256, 93, 93, 93, - 93, 126, 126, 126, 126, 94, 94, 125, 125, 60, 96, 123, -1, 92, 195, - 208, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 128, - 128, 128, 128, 128, 128, 128, 128, 130, 130, 130, 130, 130, 130, 130, 130, - 131, 131, 131, 131, 131, 131, 131, 131, 162, 162, 162, 162, 162, 162, 162, - 162, 184, 184, 184, 184, 184, 184, 184, 184, 194, 194, 194, 194, 194, 194, - 194, 194, 224, 224, 224, 224, 224, 224, 224, 224, 226, 226, 226, 226, 226, - 226, 226, 226, 153, 153, 153, 153, 161, 161, 161, 161, 167, 167, 167, 167, - 172, 172, 172, 172, 176, 176, 176, 176, 177, 177, 177, 177, 179, 179, 179, - 179, 209, 209, 209, 209, 216, 216, 216, 216, 217, 217, 217, 217, 227, 227, - 227, 227, 229, 229, 229, 229, 230, 230, 230, 230, 129, 129, 132, 132, 133, - 133, 134, 134, 136, 136, 146, 146, 154, 154, 156, 156, 160, 160, 163, 163, - 164, 164, 169, 169, 170, 170, 173, 173, 178, 178, 181, 181, 185, 185, 186, - 186, 187, 187, 189, 189, 190, 190, 196, 196, 198, 198, 228, 228, 232, 232, - 233, 233, 1, 135, 137, 138, 139, 140, 141, 143, 147, 149, 150, 151, 152, - 155, 157, 158, 165, 166, 168, 174, 175, 180, 182, 183, 188, 191, 197, 231, - 239, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, 9, 9, - 9, 9, 9, 9, 9, 142, 142, 142, 142, 142, 142, 142, 142, 144, 144, - 144, 144, 144, 144, 144, 144, 145, 145, 145, 145, 145, 145, 145, 145, 148, - 148, 148, 148, 148, 148, 148, 148, 159, 159, 159, 159, 159, 159, 159, 159, - 171, 171, 171, 171, 171, 171, 171, 171, 206, 206, 206, 206, 206, 206, 206, - 206, 215, 215, 215, 215, 215, 215, 215, 215, 225, 225, 225, 225, 225, 225, - 225, 225, 236, 236, 236, 236, 236, 236, 236, 236, 237, 237, 237, 237, 237, - 237, 237, 237, 199, 199, 199, 199, 207, 207, 207, 207, 234, 234, 234, 234, - 235, 235, 235, 235, 192, 192, 193, 193, 200, 200, 201, 201, 202, 202, 205, - 205, 210, 210, 213, 213, 218, 218, 219, 219, 238, 238, 240, 240, 242, 242, - 243, 243, 255, 255, 203, 204, 211, 212, 214, 221, 222, 223, 241, 244, 245, - 246, 247, 248, 250, 251, 252, 253, 254, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 2, 2, 2, 2, 2, 2, 2, - 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, - 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, - 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, - 8, 8, 8, 8, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, - 12, 12, 12, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, - 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 17, - 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, - 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, - 20, 21, 21, 21, 21, 21, 21, 21, 21, 23, 23, 23, 23, 23, 23, - 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, - 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, - 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, - 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, - 31, 31, 31, 31, 31, 31, 127, 127, 127, 127, 127, 127, 127, 127, 220, - 220, 220, 220, 220, 220, 220, 220, 249, 249, 249, 249, 249, 249, 249, 249, - 10, 10, 13, 13, 22, 22, 256, 256, 67, 67, 67, 67, 67, 67, 67, - 67, 68, 68, 68, 68, 68, 68, 68, 68, 95, 95, 95, 95, 95, 95, - 95, 95, 98, 98, 98, 98, 98, 98, 98, 98, 100, 100, 100, 100, 100, - 100, 100, 100, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 103, - 103, 103, 103, 103, 104, 104, 104, 104, 104, 104, 104, 104, 108, 108, 108, - 108, 108, 108, 108, 108, 109, 109, 109, 109, 109, 109, 109, 109, 110, 110, - 110, 110, 110, 110, 110, 110, 112, 112, 112, 112, 112, 112, 112, 112, 114, - 114, 114, 114, 114, 114, 114, 114, 117, 117, 117, 117, 117, 117, 117, 117, - 58, 58, 58, 58, 66, 66, 66, 66, 67, 67, 67, 67, 68, 68, 68, - 68, 69, 69, 69, 69, 70, 70, 70, 70, 71, 71, 71, 71, 72, 72, - 72, 72, 73, 73, 73, 73, 74, 74, 74, 74, 75, 75, 75, 75, 76, - 76, 76, 76, 77, 77, 77, 77, 78, 78, 78, 78, 79, 79, 79, 79, - 80, 80, 80, 80, 81, 81, 81, 81, 82, 82, 82, 82, 83, 83, 83, - 83, 84, 84, 84, 84, 85, 85, 85, 85, 86, 86, 86, 86, 87, 87, - 87, 87, 89, 89, 89, 89, 106, 106, 106, 106, 107, 107, 107, 107, 113, - 113, 113, 113, 118, 118, 118, 118, 119, 119, 119, 119, 120, 120, 120, 120, - 121, 121, 121, 121, 122, 122, 122, 122, 38, 38, 42, 42, 44, 44, 59, - 59, 88, 88, 90, 90, -1, -1, -1, -1, 33, 33, 33, 33, 33, 33, - 33, 33, 34, 34, 34, 34, 34, 34, 34, 34, 40, 40, 40, 40, 40, - 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 63, 63, 63, 63, - 63, 63, 63, 63, 39, 39, 39, 39, 43, 43, 43, 43, 124, 124, 124, - 124, 35, 35, 62, 62, 0, 36, 64, 91, 93, 126, -1, -1, 94, 94, - 94, 94, 94, 94, 94, 94, 125, 125, 125, 125, 125, 125, 125, 125, 60, - 60, 60, 60, 96, 96, 96, 96, 123, 123, 123, 123, -1, -1, -1, -1, - 92, 92, 92, 92, 195, 195, 195, 195, 208, 208, 208, 208, 128, 128, 130, - 130, 131, 131, 162, 162, 184, 184, 194, 194, 224, 224, 226, 226, 153, 161, - 167, 172, 176, 177, 179, 209, 216, 217, 227, 229, 230, -1, -1, -1, -1, - -1, -1, -1, 129, 129, 129, 129, 129, 129, 129, 129, 132, 132, 132, 132, - 132, 132, 132, 132, 133, 133, 133, 133, 133, 133, 133, 133, 134, 134, 134, - 134, 134, 134, 134, 134, 136, 136, 136, 136, 136, 136, 136, 136, 146, 146, - 146, 146, 146, 146, 146, 146, 154, 154, 154, 154, 154, 154, 154, 154, 156, - 156, 156, 156, 156, 156, 156, 156, 160, 160, 160, 160, 160, 160, 160, 160, - 163, 163, 163, 163, 163, 163, 163, 163, 164, 164, 164, 164, 164, 164, 164, - 164, 169, 169, 169, 169, 169, 169, 169, 169, 170, 170, 170, 170, 170, 170, - 170, 170, 173, 173, 173, 173, 173, 173, 173, 173, 178, 178, 178, 178, 178, - 178, 178, 178, 181, 181, 181, 181, 181, 181, 181, 181, 185, 185, 185, 185, - 185, 185, 185, 185, 186, 186, 186, 186, 186, 186, 186, 186, 187, 187, 187, - 187, 187, 187, 187, 187, 189, 189, 189, 189, 189, 189, 189, 189, 190, 190, - 190, 190, 190, 190, 190, 190, 196, 196, 196, 196, 196, 196, 196, 196, 198, - 198, 198, 198, 198, 198, 198, 198, 228, 228, 228, 228, 228, 228, 228, 228, - 232, 232, 232, 232, 232, 232, 232, 232, 233, 233, 233, 233, 233, 233, 233, - 233, 1, 1, 1, 1, 135, 135, 135, 135, 137, 137, 137, 137, 138, 138, - 138, 138, 139, 139, 139, 139, 140, 140, 140, 140, 141, 141, 141, 141, 143, - 143, 143, 143, 147, 147, 147, 147, 149, 149, 149, 149, 150, 150, 150, 150, - 151, 151, 151, 151, 152, 152, 152, 152, 155, 155, 155, 155, 157, 157, 157, - 157, 158, 158, 158, 158, 165, 165, 165, 165, 166, 166, 166, 166, 168, 168, - 168, 168, 174, 174, 174, 174, 175, 175, 175, 175, 180, 180, 180, 180, 182, - 182, 182, 182, 183, 183, 183, 183, 188, 188, 188, 188, 191, 191, 191, 191, - 197, 197, 197, 197, 231, 231, 231, 231, 239, 239, 239, 239, 9, 9, 142, - 142, 144, 144, 145, 145, 148, 148, 159, 159, 171, 171, 206, 206, 215, 215, - 225, 225, 236, 236, 237, 237, 199, 207, 234, 235, 192, 192, 192, 192, 192, - 192, 192, 192, 193, 193, 193, 193, 193, 193, 193, 193, 200, 200, 200, 200, - 200, 200, 200, 200, 201, 201, 201, 201, 201, 201, 201, 201, 202, 202, 202, - 202, 202, 202, 202, 202, 205, 205, 205, 205, 205, 205, 205, 205, 210, 210, - 210, 210, 210, 210, 210, 210, 213, 213, 213, 213, 213, 213, 213, 213, 218, - 218, 218, 218, 218, 218, 218, 218, 219, 219, 219, 219, 219, 219, 219, 219, - 238, 238, 238, 238, 238, 238, 238, 238, 240, 240, 240, 240, 240, 240, 240, - 240, 242, 242, 242, 242, 242, 242, 242, 242, 243, 243, 243, 243, 243, 243, - 243, 243, 255, 255, 255, 255, 255, 255, 255, 255, 203, 203, 203, 203, 204, - 204, 204, 204, 211, 211, 211, 211, 212, 212, 212, 212, 214, 214, 214, 214, - 221, 221, 221, 221, 222, 222, 222, 222, 223, 223, 223, 223, 241, 241, 241, - 241, 244, 244, 244, 244, 245, 245, 245, 245, 246, 246, 246, 246, 247, 247, - 247, 247, 248, 248, 248, 248, 250, 250, 250, 250, 251, 251, 251, 251, 252, - 252, 252, 252, 253, 253, 253, 253, 254, 254, 254, 254, 2, 2, 3, 3, - 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 11, 11, 12, 12, 14, - 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, - 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, - 30, 31, 31, 127, 127, 220, 220, 249, 249, -1, -1, 10, 10, 10, 10, - 10, 10, 10, 10, 13, 13, 13, 13, 13, 13, 13, 13, 22, 22, 22, - 22, 22, 22, 22, 22, 256, 256, 256, 256, 256, 256, 256, 256, 45, 45, - 45, 45, 45, 45, 45, 45, 46, 46, 46, 46, 46, 46, 46, 46, 47, - 47, 47, 47, 47, 47, 47, 47, 51, 51, 51, 51, 51, 51, 51, 51, - 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 53, - 53, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, - 55, 55, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, - 57, 57, 57, 50, 50, 50, 50, 50, 50, 50, 50, 97, 97, 97, 97, - 97, 97, 97, 97, 99, 99, 99, 99, 99, 99, 99, 99, 101, 101, 101, - 101, 101, 101, 101, 101, 105, 105, 105, 105, 105, 105, 105, 105, 111, 111, - 111, 111, 111, 111, 111, 111, 115, 115, 115, 115, 115, 115, 115, 115, 116, - 116, 116, 116, 116, 116, 116, 116, 32, 32, 32, 32, 37, 37, 37, 37, - 45, 45, 45, 45, 46, 46, 46, 46, 47, 47, 47, 47, 51, 51, 51, - 51, 52, 52, 52, 52, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, - 55, 55, 56, 56, 56, 56, 57, 57, 57, 57, 61, 61, 61, 61, 65, - 65, 65, 65, 95, 95, 95, 95, 98, 98, 98, 98, 100, 100, 100, 100, - 102, 102, 102, 102, 103, 103, 103, 103, 104, 104, 104, 104, 108, 108, 108, - 108, 109, 109, 109, 109, 110, 110, 110, 110, 112, 112, 112, 112, 114, 114, - 114, 114, 117, 117, 117, 117, 58, 58, 66, 66, 67, 67, 68, 68, 69, - 69, 70, 70, 71, 71, 72, 72, 73, 73, 74, 74, 75, 75, 76, 76, - 77, 77, 78, 78, 79, 79, 80, 80, 81, 81, 82, 82, 83, 83, 84, - 84, 85, 85, 86, 86, 87, 87, 89, 89, 106, 106, 107, 107, 113, 113, - 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 38, 42, 44, 59, 88, - 90, -1, -1, 33, 33, 33, 33, 34, 34, 34, 34, 40, 40, 40, 40, - 41, 41, 41, 41, 63, 63, 63, 63, 39, 39, 43, 43, 124, 124, 35, - 62, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 36, 36, - 36, 36, 36, 36, 36, 36, 64, 64, 64, 64, 64, 64, 64, 64, 91, - 91, 91, 91, 91, 91, 91, 91, 93, 93, 93, 93, 93, 93, 93, 93, - 126, 126, 126, 126, 126, 126, 126, 126, 94, 94, 94, 94, 125, 125, 125, - 125, 60, 60, 96, 96, 123, 123, -1, -1, 92, 92, 195, 195, 208, 208, - 128, 130, 131, 162, 184, 194, 224, 226, -1, -1, 153, 153, 153, 153, 153, - 153, 153, 153, 161, 161, 161, 161, 161, 161, 161, 161, 167, 167, 167, 167, - 167, 167, 167, 167, 172, 172, 172, 172, 172, 172, 172, 172, 176, 176, 176, - 176, 176, 176, 176, 176, 177, 177, 177, 177, 177, 177, 177, 177, 179, 179, - 179, 179, 179, 179, 179, 179, 209, 209, 209, 209, 209, 209, 209, 209, 216, - 216, 216, 216, 216, 216, 216, 216, 217, 217, 217, 217, 217, 217, 217, 217, - 227, 227, 227, 227, 227, 227, 227, 227, 229, 229, 229, 229, 229, 229, 229, - 229, 230, 230, 230, 230, 230, 230, 230, 230, 129, 129, 129, 129, 132, 132, - 132, 132, 133, 133, 133, 133, 134, 134, 134, 134, 136, 136, 136, 136, 146, - 146, 146, 146, 154, 154, 154, 154, 156, 156, 156, 156, 160, 160, 160, 160, - 163, 163, 163, 163, 164, 164, 164, 164, 169, 169, 169, 169, 170, 170, 170, - 170, 173, 173, 173, 173, 178, 178, 178, 178, 181, 181, 181, 181, 185, 185, - 185, 185, 186, 186, 186, 186, 187, 187, 187, 187, 189, 189, 189, 189, 190, - 190, 190, 190, 196, 196, 196, 196, 198, 198, 198, 198, 228, 228, 228, 228, - 232, 232, 232, 232, 233, 233, 233, 233, 1, 1, 135, 135, 137, 137, 138, - 138, 139, 139, 140, 140, 141, 141, 143, 143, 147, 147, 149, 149, 150, 150, - 151, 151, 152, 152, 155, 155, 157, 157, 158, 158, 165, 165, 166, 166, 168, - 168, 174, 174, 175, 175, 180, 180, 182, 182, 183, 183, 188, 188, 191, 191, - 197, 197, 231, 231, 239, 239, 9, 142, 144, 145, 148, 159, 171, 206, 215, - 225, 236, 237, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 199, 199, - 199, 199, 199, 199, 199, 199, 207, 207, 207, 207, 207, 207, 207, 207, 234, - 234, 234, 234, 234, 234, 234, 234, 235, 235, 235, 235, 235, 235, 235, 235, - 192, 192, 192, 192, 193, 193, 193, 193, 200, 200, 200, 200, 201, 201, 201, - 201, 202, 202, 202, 202, 205, 205, 205, 205, 210, 210, 210, 210, 213, 213, - 213, 213, 218, 218, 218, 218, 219, 219, 219, 219, 238, 238, 238, 238, 240, - 240, 240, 240, 242, 242, 242, 242, 243, 243, 243, 243, 255, 255, 255, 255, - 203, 203, 204, 204, 211, 211, 212, 212, 214, 214, 221, 221, 222, 222, 223, - 223, 241, 241, 244, 244, 245, 245, 246, 246, 247, 247, 248, 248, 250, 250, - 251, 251, 252, 252, 253, 253, 254, 254, 2, 3, 4, 5, 6, 7, 8, - 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 127, 220, 249, -1, 10, 10, 10, 10, 13, 13, 13, - 13, 22, 22, 22, 22, 256, 256, 256, 256, -}; - -static const uint8_t inverse_base64[256] = { - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, - 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, - 255, 64, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 255, 255, 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, -}; - -/* emission helpers */ -static int on_hdr(grpc_chttp2_hpack_parser *p, grpc_mdelem *md, - int add_to_table) { - if (add_to_table) { - 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, - grpc_chttp2_hpack_parser_string *str) { - grpc_mdstr *s = grpc_mdstr_from_buffer((uint8_t *)str->str, str->length); - str->length = 0; - return s; -} - -/* jump to the next state */ -static int parse_next(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - p->state = *p->next_state++; - return p->state(p, cur, end); -} - -/* begin parsing a header: all functionality is encoded into lookup tables - above */ -static int parse_begin(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - if (cur == end) { - p->state = parse_begin; - return 1; - } - - return first_byte_action[first_byte_lut[*cur]](p, cur, end); -} - -/* stream dependency and prioritization data: we just skip it */ -static int parse_stream_weight(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - if (cur == end) { - p->state = parse_stream_weight; - return 1; - } - - return p->after_prioritization(p, cur + 1, end); -} - -static int parse_stream_dep3(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - if (cur == end) { - p->state = parse_stream_dep3; - return 1; - } - - return parse_stream_weight(p, cur + 1, end); -} - -static int parse_stream_dep2(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - if (cur == end) { - p->state = parse_stream_dep2; - return 1; - } - - return parse_stream_dep3(p, cur + 1, end); -} - -static int parse_stream_dep1(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - if (cur == end) { - p->state = parse_stream_dep1; - return 1; - } - - return parse_stream_dep2(p, cur + 1, end); -} - -static int parse_stream_dep0(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - if (cur == end) { - p->state = parse_stream_dep0; - return 1; - } - - return parse_stream_dep1(p, cur + 1, end); -} - -/* emit an indexed field; for now just logs it to console; jumps to - begin the next field on completion */ -static int finish_indexed_field(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *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); - return on_hdr(p, md, 0) && parse_begin(p, cur, end); -} - -/* parse an indexed field with index < 127 */ -static int parse_indexed_field(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - p->dynamic_table_update_allowed = 0; - p->index = (*cur) & 0x7f; - return finish_indexed_field(p, cur + 1, end); -} - -/* parse an indexed field with index >= 127 */ -static int parse_indexed_field_x(grpc_chttp2_hpack_parser *p, - const uint8_t *cur, const uint8_t *end) { - static const grpc_chttp2_hpack_parser_state and_then[] = { - finish_indexed_field}; - p->dynamic_table_update_allowed = 0; - p->next_state = and_then; - p->index = 0x7f; - p->parsing.value = &p->index; - return parse_value0(p, cur + 1, end); -} - -/* finish a literal header with incremental indexing: just log, and jump to ' - begin */ -static int finish_lithdr_incidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index); - GPR_ASSERT(md != NULL); /* handled in string parsing */ - return on_hdr(p, grpc_mdelem_from_metadata_strings(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 uint8_t *cur, const uint8_t *end) { - return on_hdr(p, grpc_mdelem_from_metadata_strings(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 */ -static int parse_lithdr_incidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - static const grpc_chttp2_hpack_parser_state and_then[] = { - parse_value_string_with_indexed_key, finish_lithdr_incidx}; - p->dynamic_table_update_allowed = 0; - p->next_state = and_then; - p->index = (*cur) & 0x3f; - return parse_string_prefix(p, cur + 1, end); -} - -/* parse a literal header with incremental indexing; index >= 63 */ -static int parse_lithdr_incidx_x(grpc_chttp2_hpack_parser *p, - const uint8_t *cur, const uint8_t *end) { - static const grpc_chttp2_hpack_parser_state and_then[] = { - parse_string_prefix, parse_value_string_with_indexed_key, - finish_lithdr_incidx}; - p->dynamic_table_update_allowed = 0; - p->next_state = and_then; - p->index = 0x3f; - p->parsing.value = &p->index; - return parse_value0(p, cur + 1, end); -} - -/* parse a literal header with incremental indexing; index = 0 */ -static int parse_lithdr_incidx_v(grpc_chttp2_hpack_parser *p, - const uint8_t *cur, const uint8_t *end) { - static const grpc_chttp2_hpack_parser_state and_then[] = { - parse_key_string, parse_string_prefix, - parse_value_string_with_literal_key, finish_lithdr_incidx_v}; - p->dynamic_table_update_allowed = 0; - p->next_state = and_then; - return parse_string_prefix(p, cur + 1, end); -} - -/* finish a literal header without incremental indexing */ -static int finish_lithdr_notidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index); - GPR_ASSERT(md != NULL); /* handled in string parsing */ - return on_hdr(p, grpc_mdelem_from_metadata_strings(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 uint8_t *cur, const uint8_t *end) { - return on_hdr(p, grpc_mdelem_from_metadata_strings(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 */ -static int parse_lithdr_notidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - static const grpc_chttp2_hpack_parser_state and_then[] = { - parse_value_string_with_indexed_key, finish_lithdr_notidx}; - p->dynamic_table_update_allowed = 0; - p->next_state = and_then; - p->index = (*cur) & 0xf; - return parse_string_prefix(p, cur + 1, end); -} - -/* parse a literal header without incremental indexing; index >= 15 */ -static int parse_lithdr_notidx_x(grpc_chttp2_hpack_parser *p, - const uint8_t *cur, const uint8_t *end) { - static const grpc_chttp2_hpack_parser_state and_then[] = { - parse_string_prefix, parse_value_string_with_indexed_key, - finish_lithdr_notidx}; - p->dynamic_table_update_allowed = 0; - p->next_state = and_then; - p->index = 0xf; - p->parsing.value = &p->index; - return parse_value0(p, cur + 1, end); -} - -/* parse a literal header without incremental indexing; index == 0 */ -static int parse_lithdr_notidx_v(grpc_chttp2_hpack_parser *p, - const uint8_t *cur, const uint8_t *end) { - static const grpc_chttp2_hpack_parser_state and_then[] = { - parse_key_string, parse_string_prefix, - parse_value_string_with_literal_key, finish_lithdr_notidx_v}; - p->dynamic_table_update_allowed = 0; - p->next_state = and_then; - return parse_string_prefix(p, cur + 1, end); -} - -/* finish a literal header that is never indexed */ -static int finish_lithdr_nvridx(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index); - GPR_ASSERT(md != NULL); /* handled in string parsing */ - return on_hdr(p, grpc_mdelem_from_metadata_strings(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 uint8_t *cur, const uint8_t *end) { - return on_hdr(p, grpc_mdelem_from_metadata_strings(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 */ -static int parse_lithdr_nvridx(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - static const grpc_chttp2_hpack_parser_state and_then[] = { - parse_value_string_with_indexed_key, finish_lithdr_nvridx}; - p->dynamic_table_update_allowed = 0; - p->next_state = and_then; - p->index = (*cur) & 0xf; - return parse_string_prefix(p, cur + 1, end); -} - -/* parse a literal header that is never indexed; index >= 15 */ -static int parse_lithdr_nvridx_x(grpc_chttp2_hpack_parser *p, - const uint8_t *cur, const uint8_t *end) { - static const grpc_chttp2_hpack_parser_state and_then[] = { - parse_string_prefix, parse_value_string_with_indexed_key, - finish_lithdr_nvridx}; - p->dynamic_table_update_allowed = 0; - p->next_state = and_then; - p->index = 0xf; - p->parsing.value = &p->index; - return parse_value0(p, cur + 1, end); -} - -/* parse a literal header that is never indexed; index == 0 */ -static int parse_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p, - const uint8_t *cur, const uint8_t *end) { - static const grpc_chttp2_hpack_parser_state and_then[] = { - parse_key_string, parse_string_prefix, - parse_value_string_with_literal_key, finish_lithdr_nvridx_v}; - p->dynamic_table_update_allowed = 0; - p->next_state = and_then; - return parse_string_prefix(p, cur + 1, end); -} - -/* finish parsing a max table size change */ -static int finish_max_tbl_size(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - gpr_log(GPR_INFO, "MAX TABLE SIZE: %d", p->index); - 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 uint8_t *cur, - const uint8_t *end) { - if (p->dynamic_table_update_allowed == 0) { - return 0; - } - p->dynamic_table_update_allowed--; - p->index = (*cur) & 0x1f; - return finish_max_tbl_size(p, cur + 1, end); -} - -/* parse a max table size change, max size >= 15 */ -static int parse_max_tbl_size_x(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - static const grpc_chttp2_hpack_parser_state and_then[] = { - finish_max_tbl_size}; - if (p->dynamic_table_update_allowed == 0) { - return 0; - } - p->dynamic_table_update_allowed--; - p->next_state = and_then; - p->index = 0x1f; - p->parsing.value = &p->index; - return parse_value0(p, cur + 1, end); -} - -/* a parse error: jam the parse state into parse_error, and return error */ -static int parse_error(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - p->state = parse_error; - return 0; -} - -static int parse_illegal_op(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *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 uint8_t *cur, - const uint8_t *end) { - if (cur == end) { - p->state = parse_value0; - return 1; - } - - *p->parsing.value += (*cur) & 0x7f; - - if ((*cur) & 0x80) { - return parse_value1(p, cur + 1, end); - } else { - return parse_next(p, cur + 1, end); - } -} - -/* parse the 2nd byte of a varint into p->parsing.value - no overflow is possible */ -static int parse_value1(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - if (cur == end) { - p->state = parse_value1; - return 1; - } - - *p->parsing.value += (((uint32_t)*cur) & 0x7f) << 7; - - if ((*cur) & 0x80) { - return parse_value2(p, cur + 1, end); - } else { - return parse_next(p, cur + 1, end); - } -} - -/* parse the 3rd byte of a varint into p->parsing.value - no overflow is possible */ -static int parse_value2(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - if (cur == end) { - p->state = parse_value2; - return 1; - } - - *p->parsing.value += (((uint32_t)*cur) & 0x7f) << 14; - - if ((*cur) & 0x80) { - return parse_value3(p, cur + 1, end); - } else { - return parse_next(p, cur + 1, end); - } -} - -/* parse the 4th byte of a varint into p->parsing.value - no overflow is possible */ -static int parse_value3(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - if (cur == end) { - p->state = parse_value3; - return 1; - } - - *p->parsing.value += (((uint32_t)*cur) & 0x7f) << 21; - - if ((*cur) & 0x80) { - return parse_value4(p, cur + 1, end); - } else { - return parse_next(p, cur + 1, end); - } -} - -/* parse the 5th byte of a varint into p->parsing.value - depending on the byte, we may overflow, and care must be taken */ -static int parse_value4(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - uint8_t c; - uint32_t cur_value; - uint32_t add_value; - - if (cur == end) { - p->state = parse_value4; - return 1; - } - - c = (*cur) & 0x7f; - if (c > 0xf) { - goto error; - } - - cur_value = *p->parsing.value; - add_value = ((uint32_t)c) << 28; - if (add_value > 0xffffffffu - cur_value) { - goto error; - } - - *p->parsing.value = cur_value + add_value; - - if ((*cur) & 0x80) { - return parse_value5up(p, cur + 1, end); - } else { - return parse_next(p, cur + 1, end); - } - -error: - gpr_log(GPR_ERROR, - "integer overflow in hpack integer decoding: have 0x%08x, " - "got byte 0x%02x on byte 5", - *p->parsing.value, *cur); - return parse_error(p, cur, end); -} - -/* parse any trailing bytes in a varint: it's possible to append an arbitrary - number of 0x80's and not affect the value - a zero will terminate - and - anything else will overflow */ -static int parse_value5up(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - while (cur != end && *cur == 0x80) { - ++cur; - } - - if (cur == end) { - p->state = parse_value5up; - return 1; - } - - if (*cur == 0) { - return parse_next(p, cur + 1, end); - } - - gpr_log(GPR_ERROR, - "integer overflow in hpack integer decoding: have 0x%08x, " - "got byte 0x%02x sometime after byte 5", - *p->parsing.value, *cur); - return parse_error(p, cur, end); -} - -/* parse a string prefix */ -static int parse_string_prefix(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - if (cur == end) { - p->state = parse_string_prefix; - return 1; - } - - p->strlen = (*cur) & 0x7f; - p->huff = (*cur) >> 7; - if (p->strlen == 0x7f) { - p->parsing.value = &p->strlen; - return parse_value0(p, cur + 1, end); - } else { - return parse_next(p, cur + 1, end); - } -} - -/* append some bytes to a string */ -static void append_bytes(grpc_chttp2_hpack_parser_string *str, - const uint8_t *data, size_t length) { - if (length + str->length > str->capacity) { - GPR_ASSERT(str->length + length <= UINT32_MAX); - str->capacity = (uint32_t)(str->length + length); - str->str = gpr_realloc(str->str, str->capacity); - } - memcpy(str->str + str->length, data, length); - GPR_ASSERT(length <= UINT32_MAX - str->length); - str->length += (uint32_t)length; -} - -static int append_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - grpc_chttp2_hpack_parser_string *str = p->parsing.str; - uint32_t bits; - uint8_t decoded[3]; - switch ((binary_state)p->binary) { - case NOT_BINARY: - append_bytes(str, cur, (size_t)(end - cur)); - return 1; - b64_byte0: - case B64_BYTE0: - if (cur == end) { - p->binary = B64_BYTE0; - return 1; - } - bits = inverse_base64[*cur]; - ++cur; - if (bits == 255) - return 0; - else if (bits == 64) - goto b64_byte0; - p->base64_buffer = bits << 18; - /* fallthrough */ - b64_byte1: - case B64_BYTE1: - if (cur == end) { - p->binary = B64_BYTE1; - return 1; - } - bits = inverse_base64[*cur]; - ++cur; - if (bits == 255) - return 0; - else if (bits == 64) - goto b64_byte1; - p->base64_buffer |= bits << 12; - /* fallthrough */ - b64_byte2: - case B64_BYTE2: - if (cur == end) { - p->binary = B64_BYTE2; - return 1; - } - bits = inverse_base64[*cur]; - ++cur; - if (bits == 255) - return 0; - else if (bits == 64) - goto b64_byte2; - p->base64_buffer |= bits << 6; - /* fallthrough */ - b64_byte3: - case B64_BYTE3: - if (cur == end) { - p->binary = B64_BYTE3; - return 1; - } - bits = inverse_base64[*cur]; - ++cur; - if (bits == 255) - return 0; - else if (bits == 64) - goto b64_byte3; - p->base64_buffer |= bits; - bits = p->base64_buffer; - decoded[0] = (uint8_t)(bits >> 16); - decoded[1] = (uint8_t)(bits >> 8); - decoded[2] = (uint8_t)(bits); - append_bytes(str, decoded, 3); - goto b64_byte0; - } - GPR_UNREACHABLE_CODE(return 1); -} - -/* append a null terminator to a string */ -static int finish_str(grpc_chttp2_hpack_parser *p) { - uint8_t terminator = 0; - uint8_t decoded[2]; - uint32_t bits; - grpc_chttp2_hpack_parser_string *str = p->parsing.str; - switch ((binary_state)p->binary) { - case NOT_BINARY: - break; - case B64_BYTE0: - break; - case B64_BYTE1: - gpr_log(GPR_ERROR, "illegal base64 encoding"); - return 0; /* illegal encoding */ - case B64_BYTE2: - bits = p->base64_buffer; - if (bits & 0xffff) { - gpr_log(GPR_ERROR, "trailing bits in base64 encoding: 0x%04x", - bits & 0xffff); - return 0; - } - decoded[0] = (uint8_t)(bits >> 16); - append_bytes(str, decoded, 1); - break; - case B64_BYTE3: - bits = p->base64_buffer; - if (bits & 0xff) { - gpr_log(GPR_ERROR, "trailing bits in base64 encoding: 0x%02x", - bits & 0xff); - return 0; - } - decoded[0] = (uint8_t)(bits >> 16); - decoded[1] = (uint8_t)(bits >> 8); - append_bytes(str, decoded, 2); - break; - } - append_bytes(str, &terminator, 1); - p->parsing.str->length--; /* don't actually count the null terminator */ - return 1; -} - -/* decode a nibble from a huffman encoded stream */ -static int huff_nibble(grpc_chttp2_hpack_parser *p, uint8_t nibble) { - int16_t emit = emit_sub_tbl[16 * emit_tbl[p->huff_state] + nibble]; - int16_t next = next_sub_tbl[16 * next_tbl[p->huff_state] + nibble]; - if (emit != -1) { - if (emit >= 0 && emit < 256) { - uint8_t c = (uint8_t)emit; - if (!append_string(p, &c, (&c) + 1)) return 0; - } else { - assert(emit == 256); - } - } - p->huff_state = next; - return 1; -} - -/* decode full bytes from a huffman encoded stream */ -static int add_huff_bytes(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - for (; cur != end; ++cur) { - if (!huff_nibble(p, *cur >> 4) || !huff_nibble(p, *cur & 0xf)) return 0; - } - return 1; -} - -/* decode some string bytes based on the current decoding mode - (huffman or not) */ -static int add_str_bytes(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - if (p->huff) { - return add_huff_bytes(p, cur, end); - } else { - return append_string(p, cur, end); - } -} - -/* parse a string - tries to do large chunks at a time */ -static int parse_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - size_t remaining = p->strlen - p->strgot; - size_t given = (size_t)(end - cur); - if (remaining <= given) { - return add_str_bytes(p, cur, cur + remaining) && finish_str(p) && - parse_next(p, cur + remaining, end); - } else { - if (!add_str_bytes(p, cur, cur + given)) return 0; - GPR_ASSERT(given <= UINT32_MAX - p->strgot); - p->strgot += (uint32_t)given; - p->state = parse_string; - return 1; - } -} - -/* begin parsing a string - performs setup, calls parse_string */ -static int begin_parse_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end, uint8_t binary, - grpc_chttp2_hpack_parser_string *str) { - p->strgot = 0; - str->length = 0; - p->parsing.str = str; - p->huff_state = 0; - p->binary = binary; - return parse_string(p, cur, end); -} - -/* parse the key string */ -static int parse_key_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end) { - return begin_parse_string(p, cur, end, NOT_BINARY, &p->key); -} - -/* check if a key represents a binary header or not */ -typedef enum { BINARY_HEADER, PLAINTEXT_HEADER, ERROR_HEADER } is_binary_header; - -static is_binary_header is_binary_literal_header(grpc_chttp2_hpack_parser *p) { - return grpc_is_binary_header(p->key.str, p->key.length) ? BINARY_HEADER - : PLAINTEXT_HEADER; -} - -static is_binary_header is_binary_indexed_header(grpc_chttp2_hpack_parser *p) { - grpc_mdelem *elem = grpc_chttp2_hptbl_lookup(&p->table, p->index); - if (!elem) { - gpr_log(GPR_ERROR, "Invalid HPACK index received: %d", p->index); - return ERROR_HEADER; - } - return grpc_is_binary_header( - (const char *)GPR_SLICE_START_PTR(elem->key->slice), - GPR_SLICE_LENGTH(elem->key->slice)) - ? BINARY_HEADER - : PLAINTEXT_HEADER; -} - -/* parse the value string */ -static int parse_value_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur, - const uint8_t *end, is_binary_header type) { - switch (type) { - case BINARY_HEADER: - return begin_parse_string(p, cur, end, B64_BYTE0, &p->value); - case PLAINTEXT_HEADER: - return begin_parse_string(p, cur, end, NOT_BINARY, &p->value); - case ERROR_HEADER: - return 0; - } - /* Add code to prevent return without value error */ - GPR_UNREACHABLE_CODE(return 0); -} - -static int parse_value_string_with_indexed_key(grpc_chttp2_hpack_parser *p, - const uint8_t *cur, - const uint8_t *end) { - return parse_value_string(p, cur, end, is_binary_indexed_header(p)); -} - -static int parse_value_string_with_literal_key(grpc_chttp2_hpack_parser *p, - const uint8_t *cur, - const uint8_t *end) { - return parse_value_string(p, cur, end, is_binary_literal_header(p)); -} - -/* PUBLIC INTERFACE */ - -static void on_header_not_set(void *user_data, grpc_mdelem *md) { - GPR_UNREACHABLE_CODE(return ); -} - -void grpc_chttp2_hpack_parser_init(grpc_chttp2_hpack_parser *p) { - p->on_header = on_header_not_set; - p->on_header_user_data = NULL; - p->state = parse_begin; - p->key.str = NULL; - p->key.capacity = 0; - p->key.length = 0; - p->value.str = NULL; - p->value.capacity = 0; - p->value.length = 0; - p->dynamic_table_update_allowed = 2; - grpc_chttp2_hptbl_init(&p->table); -} - -void grpc_chttp2_hpack_parser_set_has_priority(grpc_chttp2_hpack_parser *p) { - p->after_prioritization = p->state; - p->state = parse_stream_dep0; -} - -void grpc_chttp2_hpack_parser_destroy(grpc_chttp2_hpack_parser *p) { - grpc_chttp2_hptbl_destroy(&p->table); - gpr_free(p->key.str); - gpr_free(p->value.str); -} - -int grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser *p, - const uint8_t *beg, const uint8_t *end) { - /* TODO(ctiller): limit the distance of end from beg, and perform multiple - steps in the event of a large chunk of data to limit - stack space usage when no tail call optimization is - available */ - return p->state(p, beg, end); -} - -grpc_chttp2_parse_error grpc_chttp2_header_parser_parse( - grpc_exec_ctx *exec_ctx, void *hpack_parser, - grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) { - grpc_chttp2_hpack_parser *parser = hpack_parser; - GPR_TIMER_BEGIN("grpc_chttp2_hpack_parser_parse", 0); - if (!grpc_chttp2_hpack_parser_parse(parser, GPR_SLICE_START_PTR(slice), - GPR_SLICE_END_PTR(slice))) { - GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0); - return GRPC_CHTTP2_CONNECTION_ERROR; - } - if (is_last) { - if (parser->is_boundary && parser->state != parse_begin) { - gpr_log(GPR_ERROR, - "end of header frame not aligned with a hpack record boundary"); - GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0); - return GRPC_CHTTP2_CONNECTION_ERROR; - } - /* need to check for null stream: this can occur if we receive an invalid - stream id on a header */ - if (stream_parsing != NULL) { - if (parser->is_boundary) { - stream_parsing - ->got_metadata_on_parse[stream_parsing->header_frames_received] = 1; - stream_parsing->header_frames_received++; - grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, - stream_parsing); - } - if (parser->is_eof) { - stream_parsing->received_close = 1; - } - } - parser->on_header = on_header_not_set; - parser->on_header_user_data = NULL; - parser->is_boundary = 0xde; - parser->is_eof = 0xde; - parser->dynamic_table_update_allowed = 2; - } - GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0); - return GRPC_CHTTP2_PARSE_OK; -} diff --git a/src/core/lib/transport/chttp2/hpack_parser.h b/src/core/lib/transport/chttp2/hpack_parser.h deleted file mode 100644 index a534fd5cf4..0000000000 --- a/src/core/lib/transport/chttp2/hpack_parser.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_TRANSPORT_CHTTP2_HPACK_PARSER_H -#define GRPC_CORE_LIB_TRANSPORT_CHTTP2_HPACK_PARSER_H - -#include <stddef.h> - -#include <grpc/support/port_platform.h> -#include "src/core/lib/iomgr/exec_ctx.h" -#include "src/core/lib/transport/chttp2/frame.h" -#include "src/core/lib/transport/chttp2/hpack_table.h" -#include "src/core/lib/transport/metadata.h" - -typedef struct grpc_chttp2_hpack_parser grpc_chttp2_hpack_parser; - -typedef int (*grpc_chttp2_hpack_parser_state)(grpc_chttp2_hpack_parser *p, - const uint8_t *beg, - const uint8_t *end); - -typedef struct { - char *str; - uint32_t length; - uint32_t capacity; -} grpc_chttp2_hpack_parser_string; - -struct grpc_chttp2_hpack_parser { - /* user specified callback for each header output */ - void (*on_header)(void *user_data, grpc_mdelem *md); - void *on_header_user_data; - - /* current parse state - or a function that implements it */ - grpc_chttp2_hpack_parser_state state; - /* future states dependent on the opening op code */ - const grpc_chttp2_hpack_parser_state *next_state; - /* what to do after skipping prioritization data */ - grpc_chttp2_hpack_parser_state after_prioritization; - /* the value we're currently parsing */ - union { - uint32_t *value; - grpc_chttp2_hpack_parser_string *str; - } parsing; - /* string parameters for each chunk */ - grpc_chttp2_hpack_parser_string key; - grpc_chttp2_hpack_parser_string value; - /* parsed index */ - uint32_t index; - /* length of source bytes for the currently parsing string */ - uint32_t strlen; - /* number of source bytes read for the currently parsing string */ - uint32_t strgot; - /* huffman decoding state */ - int16_t huff_state; - /* is the string being decoded binary? */ - uint8_t binary; - /* is the current string huffman encoded? */ - uint8_t huff; - /* is a dynamic table update allowed? */ - uint8_t dynamic_table_update_allowed; - /* set by higher layers, used by grpc_chttp2_header_parser_parse to signal - it should append a metadata boundary at the end of frame */ - uint8_t is_boundary; - uint8_t is_eof; - uint32_t base64_buffer; - - /* hpack table */ - grpc_chttp2_hptbl table; -}; - -void grpc_chttp2_hpack_parser_init(grpc_chttp2_hpack_parser *p); -void grpc_chttp2_hpack_parser_destroy(grpc_chttp2_hpack_parser *p); - -void grpc_chttp2_hpack_parser_set_has_priority(grpc_chttp2_hpack_parser *p); - -/* returns 1 on success, 0 on error */ -int grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser *p, - const uint8_t *beg, const uint8_t *end); - -/* wraps grpc_chttp2_hpack_parser_parse to provide a frame level parser for - the transport */ -grpc_chttp2_parse_error grpc_chttp2_header_parser_parse( - grpc_exec_ctx *exec_ctx, void *hpack_parser, - grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last); - -#endif /* GRPC_CORE_LIB_TRANSPORT_CHTTP2_HPACK_PARSER_H */ diff --git a/src/core/lib/transport/chttp2/hpack_table.c b/src/core/lib/transport/chttp2/hpack_table.c deleted file mode 100644 index f92bc26585..0000000000 --- a/src/core/lib/transport/chttp2/hpack_table.c +++ /dev/null @@ -1,361 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/lib/transport/chttp2/hpack_table.h" - -#include <assert.h> -#include <string.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> - -#include "src/core/lib/support/murmur_hash.h" - -static struct { - const char *key; - const char *value; -} static_table[] = { - /* 0: */ - {NULL, NULL}, - /* 1: */ - {":authority", ""}, - /* 2: */ - {":method", "GET"}, - /* 3: */ - {":method", "POST"}, - /* 4: */ - {":path", "/"}, - /* 5: */ - {":path", "/index.html"}, - /* 6: */ - {":scheme", "http"}, - /* 7: */ - {":scheme", "https"}, - /* 8: */ - {":status", "200"}, - /* 9: */ - {":status", "204"}, - /* 10: */ - {":status", "206"}, - /* 11: */ - {":status", "304"}, - /* 12: */ - {":status", "400"}, - /* 13: */ - {":status", "404"}, - /* 14: */ - {":status", "500"}, - /* 15: */ - {"accept-charset", ""}, - /* 16: */ - {"accept-encoding", "gzip, deflate"}, - /* 17: */ - {"accept-language", ""}, - /* 18: */ - {"accept-ranges", ""}, - /* 19: */ - {"accept", ""}, - /* 20: */ - {"access-control-allow-origin", ""}, - /* 21: */ - {"age", ""}, - /* 22: */ - {"allow", ""}, - /* 23: */ - {"authorization", ""}, - /* 24: */ - {"cache-control", ""}, - /* 25: */ - {"content-disposition", ""}, - /* 26: */ - {"content-encoding", ""}, - /* 27: */ - {"content-language", ""}, - /* 28: */ - {"content-length", ""}, - /* 29: */ - {"content-location", ""}, - /* 30: */ - {"content-range", ""}, - /* 31: */ - {"content-type", ""}, - /* 32: */ - {"cookie", ""}, - /* 33: */ - {"date", ""}, - /* 34: */ - {"etag", ""}, - /* 35: */ - {"expect", ""}, - /* 36: */ - {"expires", ""}, - /* 37: */ - {"from", ""}, - /* 38: */ - {"host", ""}, - /* 39: */ - {"if-match", ""}, - /* 40: */ - {"if-modified-since", ""}, - /* 41: */ - {"if-none-match", ""}, - /* 42: */ - {"if-range", ""}, - /* 43: */ - {"if-unmodified-since", ""}, - /* 44: */ - {"last-modified", ""}, - /* 45: */ - {"link", ""}, - /* 46: */ - {"location", ""}, - /* 47: */ - {"max-forwards", ""}, - /* 48: */ - {"proxy-authenticate", ""}, - /* 49: */ - {"proxy-authorization", ""}, - /* 50: */ - {"range", ""}, - /* 51: */ - {"referer", ""}, - /* 52: */ - {"refresh", ""}, - /* 53: */ - {"retry-after", ""}, - /* 54: */ - {"server", ""}, - /* 55: */ - {"set-cookie", ""}, - /* 56: */ - {"strict-transport-security", ""}, - /* 57: */ - {"transfer-encoding", ""}, - /* 58: */ - {"user-agent", ""}, - /* 59: */ - {"vary", ""}, - /* 60: */ - {"via", ""}, - /* 61: */ - {"www-authenticate", ""}, -}; - -static uint32_t entries_for_bytes(uint32_t bytes) { - return (bytes + GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD - 1) / - GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD; -} - -void grpc_chttp2_hptbl_init(grpc_chttp2_hptbl *tbl) { - size_t i; - - memset(tbl, 0, sizeof(*tbl)); - 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(static_table[i].key, static_table[i].value); - } -} - -void grpc_chttp2_hptbl_destroy(grpc_chttp2_hptbl *tbl) { - size_t i; - for (i = 0; i < GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) { - GRPC_MDELEM_UNREF(tbl->static_ents[i]); - } - for (i = 0; i < tbl->num_ents; i++) { - 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, - uint32_t tbl_index) { - /* Static table comes first, just return an entry from it */ - if (tbl_index <= GRPC_CHTTP2_LAST_STATIC_ENTRY) { - return tbl->static_ents[tbl_index - 1]; - } - /* Otherwise, find the value in the list of valid entries */ - tbl_index -= (GRPC_CHTTP2_LAST_STATIC_ENTRY + 1); - if (tbl_index < tbl->num_ents) { - uint32_t offset = - (tbl->num_ents - 1u - tbl_index + tbl->first_ent) % tbl->cap_entries; - return tbl->ents[offset]; - } - /* Invalid entry: return error */ - return NULL; -} - -/* Evict one element from the table */ -static void evict1(grpc_chttp2_hptbl *tbl) { - grpc_mdelem *first_ent = tbl->ents[tbl->first_ent]; - size_t elem_bytes = GPR_SLICE_LENGTH(first_ent->key->slice) + - GPR_SLICE_LENGTH(first_ent->value->slice) + - GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD; - GPR_ASSERT(elem_bytes <= tbl->mem_used); - tbl->mem_used -= (uint32_t)elem_bytes; - tbl->first_ent = ((tbl->first_ent + 1) % tbl->cap_entries); - tbl->num_ents--; - GRPC_MDELEM_UNREF(first_ent); -} - -static void rebuild_ents(grpc_chttp2_hptbl *tbl, uint32_t new_cap) { - grpc_mdelem **ents = gpr_malloc(sizeof(*ents) * new_cap); - uint32_t 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, - uint32_t 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, - uint32_t 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) { - uint32_t 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->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 - * attempt to add an entry that is larger than the maximum size; an - * attempt to add an entry larger than the entire table causes - * the table - * to be emptied of all existing entries, and results in an - * empty table. - */ - while (tbl->num_ents) { - evict1(tbl); - } - return 1; - } - - /* evict entries to ensure no overflow */ - while (elem_bytes > (size_t)tbl->current_table_bytes - tbl->mem_used) { - evict1(tbl); - } - - /* copy the finalized entry in */ - tbl->ents[(tbl->first_ent + tbl->num_ents) % tbl->cap_entries] = - GRPC_MDELEM_REF(md); - - /* update accounting values */ - tbl->num_ents++; - tbl->mem_used += (uint32_t)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}; - uint32_t 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 = 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++) { - uint32_t idx = - (uint32_t)(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; - if (r.has_value) return r; - } - - return r; -} diff --git a/src/core/lib/transport/chttp2/hpack_table.h b/src/core/lib/transport/chttp2/hpack_table.h deleted file mode 100644 index 2cbc02dd9c..0000000000 --- a/src/core/lib/transport/chttp2/hpack_table.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_TRANSPORT_CHTTP2_HPACK_TABLE_H -#define GRPC_CORE_LIB_TRANSPORT_CHTTP2_HPACK_TABLE_H - -#include <grpc/support/port_platform.h> -#include <grpc/support/slice.h> -#include "src/core/lib/transport/metadata.h" - -/* HPACK header table */ - -/* last index in the static table */ -#define GRPC_CHTTP2_LAST_STATIC_ENTRY 61 - -/* Initial table size as per the spec */ -#define GRPC_CHTTP2_INITIAL_HPACK_TABLE_SIZE 4096 -/* Maximum table size that we'll use */ -#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 { - /* the first used entry in ents */ - uint32_t first_ent; - /* how many entries are in the table */ - uint32_t num_ents; - /* the amount of memory used by the table, according to the hpack algorithm */ - uint32_t mem_used; - /* the max memory allowed to be used by the table, according to the hpack - algorithm */ - uint32_t max_bytes; - /* the currently agreed size of the table, according to the hpack algorithm */ - uint32_t current_table_bytes; - /* Maximum number of entries we could possibly fit in the table, given defined - overheads */ - uint32_t max_entries; - /* Number of entries allocated in ents */ - uint32_t 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_mdelem *static_ents[GRPC_CHTTP2_LAST_STATIC_ENTRY]; -} grpc_chttp2_hptbl; - -/* initialize a hpack table */ -void grpc_chttp2_hptbl_init(grpc_chttp2_hptbl *tbl); -void grpc_chttp2_hptbl_destroy(grpc_chttp2_hptbl *tbl); -void grpc_chttp2_hptbl_set_max_bytes(grpc_chttp2_hptbl *tbl, - uint32_t max_bytes); -int grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl, - uint32_t bytes); - -/* lookup a table entry based on its hpack index */ -grpc_mdelem *grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl, - uint32_t index); -/* add a table entry to the index */ -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 { - uint32_t 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); - -#endif /* GRPC_CORE_LIB_TRANSPORT_CHTTP2_HPACK_TABLE_H */ diff --git a/src/core/lib/transport/chttp2/hpack_tables.txt b/src/core/lib/transport/chttp2/hpack_tables.txt deleted file mode 100644 index 08842a0267..0000000000 --- a/src/core/lib/transport/chttp2/hpack_tables.txt +++ /dev/null @@ -1,66 +0,0 @@ -Static table, from the spec: - +-------+-----------------------------+---------------+ - | Index | Header Name | Header Value | - +-------+-----------------------------+---------------+ - | 1 | :authority | | - | 2 | :method | GET | - | 3 | :method | POST | - | 4 | :path | / | - | 5 | :path | /index.html | - | 6 | :scheme | http | - | 7 | :scheme | https | - | 8 | :status | 200 | - | 9 | :status | 204 | - | 10 | :status | 206 | - | 11 | :status | 304 | - | 12 | :status | 400 | - | 13 | :status | 404 | - | 14 | :status | 500 | - | 15 | accept-charset | | - | 16 | accept-encoding | gzip, deflate | - | 17 | accept-language | | - | 18 | accept-ranges | | - | 19 | accept | | - | 20 | access-control-allow-origin | | - | 21 | age | | - | 22 | allow | | - | 23 | authorization | | - | 24 | cache-control | | - | 25 | content-disposition | | - | 26 | content-encoding | | - | 27 | content-language | | - | 28 | content-length | | - | 29 | content-location | | - | 30 | content-range | | - | 31 | content-type | | - | 32 | cookie | | - | 33 | date | | - | 34 | etag | | - | 35 | expect | | - | 36 | expires | | - | 37 | from | | - | 38 | host | | - | 39 | if-match | | - | 40 | if-modified-since | | - | 41 | if-none-match | | - | 42 | if-range | | - | 43 | if-unmodified-since | | - | 44 | last-modified | | - | 45 | link | | - | 46 | location | | - | 47 | max-forwards | | - | 48 | proxy-authenticate | | - | 49 | proxy-authorization | | - | 50 | range | | - | 51 | referer | | - | 52 | refresh | | - | 53 | retry-after | | - | 54 | server | | - | 55 | set-cookie | | - | 56 | strict-transport-security | | - | 57 | transfer-encoding | | - | 58 | user-agent | | - | 59 | vary | | - | 60 | via | | - | 61 | www-authenticate | | - +-------+-----------------------------+---------------+ diff --git a/src/core/lib/transport/chttp2/http2_errors.h b/src/core/lib/transport/chttp2/http2_errors.h deleted file mode 100644 index 0238f9d80b..0000000000 --- a/src/core/lib/transport/chttp2/http2_errors.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_TRANSPORT_CHTTP2_HTTP2_ERRORS_H -#define GRPC_CORE_LIB_TRANSPORT_CHTTP2_HTTP2_ERRORS_H - -/* error codes for RST_STREAM from http2 draft 14 section 7 */ -typedef enum { - GRPC_CHTTP2_NO_ERROR = 0x0, - GRPC_CHTTP2_PROTOCOL_ERROR = 0x1, - GRPC_CHTTP2_INTERNAL_ERROR = 0x2, - GRPC_CHTTP2_FLOW_CONTROL_ERROR = 0x3, - GRPC_CHTTP2_SETTINGS_TIMEOUT = 0x4, - GRPC_CHTTP2_STREAM_CLOSED = 0x5, - GRPC_CHTTP2_FRAME_SIZE_ERROR = 0x6, - GRPC_CHTTP2_REFUSED_STREAM = 0x7, - GRPC_CHTTP2_CANCEL = 0x8, - GRPC_CHTTP2_COMPRESSION_ERROR = 0x9, - GRPC_CHTTP2_CONNECT_ERROR = 0xa, - GRPC_CHTTP2_ENHANCE_YOUR_CALM = 0xb, - GRPC_CHTTP2_INADEQUATE_SECURITY = 0xc, - /* force use of a default clause */ - GRPC_CHTTP2__ERROR_DO_NOT_USE = -1 -} grpc_chttp2_error_code; - -#endif /* GRPC_CORE_LIB_TRANSPORT_CHTTP2_HTTP2_ERRORS_H */ diff --git a/src/core/lib/transport/chttp2/huffsyms.c b/src/core/lib/transport/chttp2/huffsyms.c deleted file mode 100644 index 27497e6ae0..0000000000 --- a/src/core/lib/transport/chttp2/huffsyms.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/lib/transport/chttp2/huffsyms.h" - -/* Constants pulled from the HPACK spec, and converted to C using the vim - command: - :%s/.* \([0-9a-f]\+\) \[ *\([0-9]\+\)\]/{0x\1, \2},/g */ -const grpc_chttp2_huffsym grpc_chttp2_huffsyms[GRPC_CHTTP2_NUM_HUFFSYMS] = { - {0x1ff8, 13}, {0x7fffd8, 23}, {0xfffffe2, 28}, {0xfffffe3, 28}, - {0xfffffe4, 28}, {0xfffffe5, 28}, {0xfffffe6, 28}, {0xfffffe7, 28}, - {0xfffffe8, 28}, {0xffffea, 24}, {0x3ffffffc, 30}, {0xfffffe9, 28}, - {0xfffffea, 28}, {0x3ffffffd, 30}, {0xfffffeb, 28}, {0xfffffec, 28}, - {0xfffffed, 28}, {0xfffffee, 28}, {0xfffffef, 28}, {0xffffff0, 28}, - {0xffffff1, 28}, {0xffffff2, 28}, {0x3ffffffe, 30}, {0xffffff3, 28}, - {0xffffff4, 28}, {0xffffff5, 28}, {0xffffff6, 28}, {0xffffff7, 28}, - {0xffffff8, 28}, {0xffffff9, 28}, {0xffffffa, 28}, {0xffffffb, 28}, - {0x14, 6}, {0x3f8, 10}, {0x3f9, 10}, {0xffa, 12}, - {0x1ff9, 13}, {0x15, 6}, {0xf8, 8}, {0x7fa, 11}, - {0x3fa, 10}, {0x3fb, 10}, {0xf9, 8}, {0x7fb, 11}, - {0xfa, 8}, {0x16, 6}, {0x17, 6}, {0x18, 6}, - {0x0, 5}, {0x1, 5}, {0x2, 5}, {0x19, 6}, - {0x1a, 6}, {0x1b, 6}, {0x1c, 6}, {0x1d, 6}, - {0x1e, 6}, {0x1f, 6}, {0x5c, 7}, {0xfb, 8}, - {0x7ffc, 15}, {0x20, 6}, {0xffb, 12}, {0x3fc, 10}, - {0x1ffa, 13}, {0x21, 6}, {0x5d, 7}, {0x5e, 7}, - {0x5f, 7}, {0x60, 7}, {0x61, 7}, {0x62, 7}, - {0x63, 7}, {0x64, 7}, {0x65, 7}, {0x66, 7}, - {0x67, 7}, {0x68, 7}, {0x69, 7}, {0x6a, 7}, - {0x6b, 7}, {0x6c, 7}, {0x6d, 7}, {0x6e, 7}, - {0x6f, 7}, {0x70, 7}, {0x71, 7}, {0x72, 7}, - {0xfc, 8}, {0x73, 7}, {0xfd, 8}, {0x1ffb, 13}, - {0x7fff0, 19}, {0x1ffc, 13}, {0x3ffc, 14}, {0x22, 6}, - {0x7ffd, 15}, {0x3, 5}, {0x23, 6}, {0x4, 5}, - {0x24, 6}, {0x5, 5}, {0x25, 6}, {0x26, 6}, - {0x27, 6}, {0x6, 5}, {0x74, 7}, {0x75, 7}, - {0x28, 6}, {0x29, 6}, {0x2a, 6}, {0x7, 5}, - {0x2b, 6}, {0x76, 7}, {0x2c, 6}, {0x8, 5}, - {0x9, 5}, {0x2d, 6}, {0x77, 7}, {0x78, 7}, - {0x79, 7}, {0x7a, 7}, {0x7b, 7}, {0x7ffe, 15}, - {0x7fc, 11}, {0x3ffd, 14}, {0x1ffd, 13}, {0xffffffc, 28}, - {0xfffe6, 20}, {0x3fffd2, 22}, {0xfffe7, 20}, {0xfffe8, 20}, - {0x3fffd3, 22}, {0x3fffd4, 22}, {0x3fffd5, 22}, {0x7fffd9, 23}, - {0x3fffd6, 22}, {0x7fffda, 23}, {0x7fffdb, 23}, {0x7fffdc, 23}, - {0x7fffdd, 23}, {0x7fffde, 23}, {0xffffeb, 24}, {0x7fffdf, 23}, - {0xffffec, 24}, {0xffffed, 24}, {0x3fffd7, 22}, {0x7fffe0, 23}, - {0xffffee, 24}, {0x7fffe1, 23}, {0x7fffe2, 23}, {0x7fffe3, 23}, - {0x7fffe4, 23}, {0x1fffdc, 21}, {0x3fffd8, 22}, {0x7fffe5, 23}, - {0x3fffd9, 22}, {0x7fffe6, 23}, {0x7fffe7, 23}, {0xffffef, 24}, - {0x3fffda, 22}, {0x1fffdd, 21}, {0xfffe9, 20}, {0x3fffdb, 22}, - {0x3fffdc, 22}, {0x7fffe8, 23}, {0x7fffe9, 23}, {0x1fffde, 21}, - {0x7fffea, 23}, {0x3fffdd, 22}, {0x3fffde, 22}, {0xfffff0, 24}, - {0x1fffdf, 21}, {0x3fffdf, 22}, {0x7fffeb, 23}, {0x7fffec, 23}, - {0x1fffe0, 21}, {0x1fffe1, 21}, {0x3fffe0, 22}, {0x1fffe2, 21}, - {0x7fffed, 23}, {0x3fffe1, 22}, {0x7fffee, 23}, {0x7fffef, 23}, - {0xfffea, 20}, {0x3fffe2, 22}, {0x3fffe3, 22}, {0x3fffe4, 22}, - {0x7ffff0, 23}, {0x3fffe5, 22}, {0x3fffe6, 22}, {0x7ffff1, 23}, - {0x3ffffe0, 26}, {0x3ffffe1, 26}, {0xfffeb, 20}, {0x7fff1, 19}, - {0x3fffe7, 22}, {0x7ffff2, 23}, {0x3fffe8, 22}, {0x1ffffec, 25}, - {0x3ffffe2, 26}, {0x3ffffe3, 26}, {0x3ffffe4, 26}, {0x7ffffde, 27}, - {0x7ffffdf, 27}, {0x3ffffe5, 26}, {0xfffff1, 24}, {0x1ffffed, 25}, - {0x7fff2, 19}, {0x1fffe3, 21}, {0x3ffffe6, 26}, {0x7ffffe0, 27}, - {0x7ffffe1, 27}, {0x3ffffe7, 26}, {0x7ffffe2, 27}, {0xfffff2, 24}, - {0x1fffe4, 21}, {0x1fffe5, 21}, {0x3ffffe8, 26}, {0x3ffffe9, 26}, - {0xffffffd, 28}, {0x7ffffe3, 27}, {0x7ffffe4, 27}, {0x7ffffe5, 27}, - {0xfffec, 20}, {0xfffff3, 24}, {0xfffed, 20}, {0x1fffe6, 21}, - {0x3fffe9, 22}, {0x1fffe7, 21}, {0x1fffe8, 21}, {0x7ffff3, 23}, - {0x3fffea, 22}, {0x3fffeb, 22}, {0x1ffffee, 25}, {0x1ffffef, 25}, - {0xfffff4, 24}, {0xfffff5, 24}, {0x3ffffea, 26}, {0x7ffff4, 23}, - {0x3ffffeb, 26}, {0x7ffffe6, 27}, {0x3ffffec, 26}, {0x3ffffed, 26}, - {0x7ffffe7, 27}, {0x7ffffe8, 27}, {0x7ffffe9, 27}, {0x7ffffea, 27}, - {0x7ffffeb, 27}, {0xffffffe, 28}, {0x7ffffec, 27}, {0x7ffffed, 27}, - {0x7ffffee, 27}, {0x7ffffef, 27}, {0x7fffff0, 27}, {0x3ffffee, 26}, - {0x3fffffff, 30}, -}; diff --git a/src/core/lib/transport/chttp2/huffsyms.h b/src/core/lib/transport/chttp2/huffsyms.h deleted file mode 100644 index 1ca77b9207..0000000000 --- a/src/core/lib/transport/chttp2/huffsyms.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_TRANSPORT_CHTTP2_HUFFSYMS_H -#define GRPC_CORE_LIB_TRANSPORT_CHTTP2_HUFFSYMS_H - -/* HPACK static huffman table */ - -#define GRPC_CHTTP2_NUM_HUFFSYMS 257 - -typedef struct { - unsigned bits; - unsigned length; -} grpc_chttp2_huffsym; - -extern const grpc_chttp2_huffsym grpc_chttp2_huffsyms[GRPC_CHTTP2_NUM_HUFFSYMS]; - -#endif /* GRPC_CORE_LIB_TRANSPORT_CHTTP2_HUFFSYMS_H */ diff --git a/src/core/lib/transport/chttp2/incoming_metadata.c b/src/core/lib/transport/chttp2/incoming_metadata.c deleted file mode 100644 index a1a8d37562..0000000000 --- a/src/core/lib/transport/chttp2/incoming_metadata.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/lib/transport/chttp2/incoming_metadata.h" - -#include <string.h> - -#include "src/core/lib/transport/chttp2/internal.h" - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> - -void grpc_chttp2_incoming_metadata_buffer_init( - grpc_chttp2_incoming_metadata_buffer *buffer) { - buffer->deadline = gpr_inf_future(GPR_CLOCK_REALTIME); -} - -void grpc_chttp2_incoming_metadata_buffer_destroy( - grpc_chttp2_incoming_metadata_buffer *buffer) { - size_t i; - if (!buffer->published) { - for (i = 0; i < buffer->count; i++) { - GRPC_MDELEM_UNREF(buffer->elems[i].md); - } - } - gpr_free(buffer->elems); -} - -void grpc_chttp2_incoming_metadata_buffer_add( - grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem *elem) { - GPR_ASSERT(!buffer->published); - if (buffer->capacity == buffer->count) { - buffer->capacity = GPR_MAX(8, 2 * buffer->capacity); - buffer->elems = - gpr_realloc(buffer->elems, sizeof(*buffer->elems) * buffer->capacity); - } - buffer->elems[buffer->count++].md = elem; -} - -void grpc_chttp2_incoming_metadata_buffer_set_deadline( - grpc_chttp2_incoming_metadata_buffer *buffer, gpr_timespec deadline) { - GPR_ASSERT(!buffer->published); - buffer->deadline = deadline; -} - -void grpc_chttp2_incoming_metadata_buffer_publish( - grpc_chttp2_incoming_metadata_buffer *buffer, grpc_metadata_batch *batch) { - GPR_ASSERT(!buffer->published); - buffer->published = 1; - if (buffer->count > 0) { - size_t i; - for (i = 1; i < buffer->count; i++) { - buffer->elems[i].prev = &buffer->elems[i - 1]; - } - for (i = 0; i < buffer->count - 1; i++) { - buffer->elems[i].next = &buffer->elems[i + 1]; - } - buffer->elems[0].prev = NULL; - buffer->elems[buffer->count - 1].next = NULL; - batch->list.head = &buffer->elems[0]; - batch->list.tail = &buffer->elems[buffer->count - 1]; - } else { - batch->list.head = batch->list.tail = NULL; - } - batch->deadline = buffer->deadline; -} diff --git a/src/core/lib/transport/chttp2/incoming_metadata.h b/src/core/lib/transport/chttp2/incoming_metadata.h deleted file mode 100644 index edfa0adf9d..0000000000 --- a/src/core/lib/transport/chttp2/incoming_metadata.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_TRANSPORT_CHTTP2_INCOMING_METADATA_H -#define GRPC_CORE_LIB_TRANSPORT_CHTTP2_INCOMING_METADATA_H - -#include "src/core/lib/transport/transport.h" - -typedef struct { - grpc_linked_mdelem *elems; - size_t count; - size_t capacity; - gpr_timespec deadline; - int published; -} grpc_chttp2_incoming_metadata_buffer; - -/** assumes everything initially zeroed */ -void grpc_chttp2_incoming_metadata_buffer_init( - grpc_chttp2_incoming_metadata_buffer *buffer); -void grpc_chttp2_incoming_metadata_buffer_destroy( - grpc_chttp2_incoming_metadata_buffer *buffer); -void grpc_chttp2_incoming_metadata_buffer_publish( - grpc_chttp2_incoming_metadata_buffer *buffer, grpc_metadata_batch *batch); - -void grpc_chttp2_incoming_metadata_buffer_add( - grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem *elem); -void grpc_chttp2_incoming_metadata_buffer_set_deadline( - grpc_chttp2_incoming_metadata_buffer *buffer, gpr_timespec deadline); - -#endif /* GRPC_CORE_LIB_TRANSPORT_CHTTP2_INCOMING_METADATA_H */ diff --git a/src/core/lib/transport/chttp2/internal.h b/src/core/lib/transport/chttp2/internal.h deleted file mode 100644 index 346e404204..0000000000 --- a/src/core/lib/transport/chttp2/internal.h +++ /dev/null @@ -1,780 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_TRANSPORT_CHTTP2_INTERNAL_H -#define GRPC_CORE_LIB_TRANSPORT_CHTTP2_INTERNAL_H - -#include <assert.h> -#include <stdbool.h> - -#include "src/core/lib/iomgr/endpoint.h" -#include "src/core/lib/transport/chttp2/frame.h" -#include "src/core/lib/transport/chttp2/frame_data.h" -#include "src/core/lib/transport/chttp2/frame_goaway.h" -#include "src/core/lib/transport/chttp2/frame_ping.h" -#include "src/core/lib/transport/chttp2/frame_rst_stream.h" -#include "src/core/lib/transport/chttp2/frame_settings.h" -#include "src/core/lib/transport/chttp2/frame_window_update.h" -#include "src/core/lib/transport/chttp2/hpack_encoder.h" -#include "src/core/lib/transport/chttp2/hpack_parser.h" -#include "src/core/lib/transport/chttp2/incoming_metadata.h" -#include "src/core/lib/transport/chttp2/stream_map.h" -#include "src/core/lib/transport/connectivity_state.h" -#include "src/core/lib/transport/transport_impl.h" - -typedef struct grpc_chttp2_transport grpc_chttp2_transport; -typedef struct grpc_chttp2_stream grpc_chttp2_stream; - -/* streams are kept in various linked lists depending on what things need to - happen to them... this enum labels each list */ -typedef enum { - GRPC_CHTTP2_LIST_ALL_STREAMS, - GRPC_CHTTP2_LIST_CHECK_READ_OPS, - GRPC_CHTTP2_LIST_UNANNOUNCED_INCOMING_WINDOW_AVAILABLE, - GRPC_CHTTP2_LIST_WRITABLE, - GRPC_CHTTP2_LIST_WRITING, - GRPC_CHTTP2_LIST_WRITTEN, - GRPC_CHTTP2_LIST_PARSING_SEEN, - GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_PARSING, - GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_WRITING, - GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT, - /* streams waiting for the outgoing window in the writing path, they will be - * merged to the stalled list or writable list under transport lock. */ - GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT, - /** streams that are waiting to start because there are too many concurrent - streams on the connection */ - GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY, - STREAM_LIST_COUNT /* must be last */ -} grpc_chttp2_stream_list_id; - -/* deframer state for the overall http2 stream of bytes */ -typedef enum { - /* prefix: one entry per http2 connection prefix byte */ - GRPC_DTS_CLIENT_PREFIX_0 = 0, - GRPC_DTS_CLIENT_PREFIX_1, - GRPC_DTS_CLIENT_PREFIX_2, - GRPC_DTS_CLIENT_PREFIX_3, - GRPC_DTS_CLIENT_PREFIX_4, - GRPC_DTS_CLIENT_PREFIX_5, - GRPC_DTS_CLIENT_PREFIX_6, - GRPC_DTS_CLIENT_PREFIX_7, - GRPC_DTS_CLIENT_PREFIX_8, - GRPC_DTS_CLIENT_PREFIX_9, - GRPC_DTS_CLIENT_PREFIX_10, - GRPC_DTS_CLIENT_PREFIX_11, - GRPC_DTS_CLIENT_PREFIX_12, - GRPC_DTS_CLIENT_PREFIX_13, - GRPC_DTS_CLIENT_PREFIX_14, - GRPC_DTS_CLIENT_PREFIX_15, - GRPC_DTS_CLIENT_PREFIX_16, - GRPC_DTS_CLIENT_PREFIX_17, - GRPC_DTS_CLIENT_PREFIX_18, - GRPC_DTS_CLIENT_PREFIX_19, - GRPC_DTS_CLIENT_PREFIX_20, - GRPC_DTS_CLIENT_PREFIX_21, - GRPC_DTS_CLIENT_PREFIX_22, - GRPC_DTS_CLIENT_PREFIX_23, - /* frame header byte 0... */ - /* must follow from the prefix states */ - GRPC_DTS_FH_0, - GRPC_DTS_FH_1, - GRPC_DTS_FH_2, - GRPC_DTS_FH_3, - GRPC_DTS_FH_4, - GRPC_DTS_FH_5, - GRPC_DTS_FH_6, - GRPC_DTS_FH_7, - /* ... frame header byte 8 */ - GRPC_DTS_FH_8, - /* inside a http2 frame */ - GRPC_DTS_FRAME -} grpc_chttp2_deframe_transport_state; - -typedef struct { - grpc_chttp2_stream *head; - grpc_chttp2_stream *tail; -} grpc_chttp2_stream_list; - -typedef struct { - grpc_chttp2_stream *next; - grpc_chttp2_stream *prev; -} grpc_chttp2_stream_link; - -/* We keep several sets of connection wide parameters */ -typedef enum { - /* The settings our peer has asked for (and we have acked) */ - GRPC_PEER_SETTINGS = 0, - /* The settings we'd like to have */ - GRPC_LOCAL_SETTINGS, - /* The settings we've published to our peer */ - GRPC_SENT_SETTINGS, - /* The settings the peer has acked */ - GRPC_ACKED_SETTINGS, - GRPC_NUM_SETTING_SETS -} grpc_chttp2_setting_set; - -/* Outstanding ping request data */ -typedef struct grpc_chttp2_outstanding_ping { - uint8_t id[8]; - grpc_closure *on_recv; - struct grpc_chttp2_outstanding_ping *next; - struct grpc_chttp2_outstanding_ping *prev; -} grpc_chttp2_outstanding_ping; - -/* forward declared in frame_data.h */ -struct grpc_chttp2_incoming_byte_stream { - grpc_byte_stream base; - gpr_refcount refs; - struct grpc_chttp2_incoming_byte_stream *next_message; - int failed; - - grpc_chttp2_transport *transport; - grpc_chttp2_stream *stream; - int is_tail; - gpr_slice_buffer slices; - grpc_closure *on_next; - gpr_slice *next; -}; - -typedef struct { - /** data to write next write */ - gpr_slice_buffer qbuf; - - /** window available for us to send to peer */ - int64_t outgoing_window; - /** window available to announce to peer */ - int64_t announce_incoming_window; - /** how much window would we like to have for incoming_window */ - uint32_t connection_window_target; - - /** have we seen a goaway */ - uint8_t seen_goaway; - /** have we sent a goaway */ - uint8_t sent_goaway; - - /** is this transport a client? */ - uint8_t is_client; - /** are the local settings dirty and need to be sent? */ - uint8_t dirtied_local_settings; - /** have local settings been sent? */ - uint8_t sent_local_settings; - /** bitmask of setting indexes to send out */ - uint32_t force_send_settings; - /** settings values */ - uint32_t settings[GRPC_NUM_SETTING_SETS][GRPC_CHTTP2_NUM_SETTINGS]; - - /** what is the next stream id to be allocated by this peer? - copied to next_stream_id in parsing when parsing commences */ - uint32_t next_stream_id; - - /** how far to lookahead in a stream? */ - uint32_t stream_lookahead; - - /** last received stream id */ - uint32_t last_incoming_stream_id; - - /** pings awaiting responses */ - grpc_chttp2_outstanding_ping pings; - /** next payload for an outgoing ping */ - uint64_t ping_counter; - - /** concurrent stream count: updated when not parsing, - so this is a strict over-estimation on the client */ - uint32_t concurrent_stream_count; -} grpc_chttp2_transport_global; - -typedef struct { - /** data to write now */ - gpr_slice_buffer outbuf; - /** hpack encoding */ - grpc_chttp2_hpack_compressor hpack_compressor; - int64_t outgoing_window; - /** is this a client? */ - uint8_t is_client; - /** callback for when writing is done */ - grpc_closure done_cb; -} grpc_chttp2_transport_writing; - -struct grpc_chttp2_transport_parsing { - /** is this transport a client? (boolean) */ - uint8_t is_client; - - /** were settings updated? */ - uint8_t settings_updated; - /** was a settings ack received? */ - uint8_t settings_ack_received; - /** was a goaway frame received? */ - uint8_t goaway_received; - - /** the last sent max_table_size setting */ - uint32_t last_sent_max_table_size; - - /** initial window change */ - int64_t initial_window_update; - - /** data to write later - after parsing */ - gpr_slice_buffer qbuf; - /** parser for headers */ - grpc_chttp2_hpack_parser hpack_parser; - /** simple one shot parsers */ - union { - grpc_chttp2_window_update_parser window_update; - grpc_chttp2_settings_parser settings; - grpc_chttp2_ping_parser ping; - grpc_chttp2_rst_stream_parser rst_stream; - } simple; - /** parser for goaway frames */ - grpc_chttp2_goaway_parser goaway_parser; - - /** window available for peer to send to us */ - int64_t incoming_window; - - /** next stream id available at the time of beginning parsing */ - uint32_t next_stream_id; - uint32_t last_incoming_stream_id; - - /* deframing */ - grpc_chttp2_deframe_transport_state deframe_state; - uint8_t incoming_frame_type; - uint8_t incoming_frame_flags; - uint8_t header_eof; - uint32_t expect_continuation_stream_id; - uint32_t incoming_frame_size; - uint32_t incoming_stream_id; - - /* active parser */ - void *parser_data; - grpc_chttp2_stream_parsing *incoming_stream; - grpc_chttp2_parse_error (*parser)( - grpc_exec_ctx *exec_ctx, void *parser_user_data, - grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last); - - /* received settings */ - uint32_t settings[GRPC_CHTTP2_NUM_SETTINGS]; - - /* goaway data */ - grpc_status_code goaway_error; - uint32_t goaway_last_stream_index; - gpr_slice goaway_text; - - int64_t outgoing_window; -}; - -struct grpc_chttp2_transport { - grpc_transport base; /* must be first */ - grpc_endpoint *ep; - gpr_refcount refs; - char *peer_string; - - /** when this drops to zero it's safe to shutdown the endpoint */ - gpr_refcount shutdown_ep_refs; - - gpr_mu mu; - - /** is the transport destroying itself? */ - uint8_t destroying; - /** has the upper layer closed the transport? */ - uint8_t closed; - - /** is a thread currently writing */ - uint8_t writing_active; - /** is a thread currently parsing */ - uint8_t parsing_active; - - /** is there a read request to the endpoint outstanding? */ - uint8_t endpoint_reading; - - /** various lists of streams */ - grpc_chttp2_stream_list lists[STREAM_LIST_COUNT]; - - /** global state for reading/writing */ - grpc_chttp2_transport_global global; - /** state only accessible by the chain of execution that - set writing_active=1 */ - grpc_chttp2_transport_writing writing; - /** state only accessible by the chain of execution that - set parsing_active=1 */ - grpc_chttp2_transport_parsing parsing; - - /** maps stream id to grpc_chttp2_stream objects; - owned by the parsing thread when parsing */ - grpc_chttp2_stream_map parsing_stream_map; - - /** streams created by the client (possibly during parsing); - merged with parsing_stream_map during unlock when no - parsing is occurring */ - grpc_chttp2_stream_map new_stream_map; - - /** closure to execute writing */ - grpc_closure writing_action; - /** closure to finish reading from the endpoint */ - grpc_closure recv_data; - - /** incoming read bytes */ - gpr_slice_buffer read_buffer; - - /** address to place a newly accepted stream - set and unset by - grpc_chttp2_parsing_accept_stream; used by init_stream to - publish the accepted server stream */ - grpc_chttp2_stream **accepting_stream; - - struct { - /* accept stream callback */ - void (*accept_stream)(grpc_exec_ctx *exec_ctx, void *user_data, - grpc_transport *transport, const void *server_data); - void *accept_stream_user_data; - - /** connectivity tracking */ - grpc_connectivity_state_tracker state_tracker; - } channel_callback; - - /** Transport op to be applied post-parsing */ - grpc_transport_op *post_parsing_op; -}; - -typedef struct { - /** HTTP2 stream id for this stream, or zero if one has not been assigned */ - uint32_t id; - - /** window available for us to send to peer */ - int64_t outgoing_window; - /** The number of bytes the upper layers have offered to receive. - As the upper layer offers more bytes, this value increases. - As bytes are read, this value decreases. */ - uint32_t max_recv_bytes; - /** The number of bytes the upper layer has offered to read but we have - not yet announced to HTTP2 flow control. - As the upper layers offer to read more bytes, this value increases. - As we advertise incoming flow control window, this value decreases. */ - uint32_t unannounced_incoming_window_for_parse; - uint32_t unannounced_incoming_window_for_writing; - /** things the upper layers would like to send */ - grpc_metadata_batch *send_initial_metadata; - grpc_closure *send_initial_metadata_finished; - grpc_byte_stream *send_message; - grpc_closure *send_message_finished; - grpc_metadata_batch *send_trailing_metadata; - grpc_closure *send_trailing_metadata_finished; - - grpc_metadata_batch *recv_initial_metadata; - grpc_closure *recv_initial_metadata_ready; - grpc_byte_stream **recv_message; - grpc_closure *recv_message_ready; - grpc_metadata_batch *recv_trailing_metadata; - grpc_closure *recv_trailing_metadata_finished; - - /** when the application requests writes be closed, the write_closed is - 'queued'; when the close is flow controlled into the send path, we are - 'sending' it; when the write has been performed it is 'sent' */ - uint8_t write_closed; - /** is this stream reading half-closed (boolean) */ - uint8_t read_closed; - /** is this stream in the stream map? (boolean) */ - uint8_t in_stream_map; - /** has this stream seen an error? if 1, then pending incoming frames - can be thrown away */ - uint8_t seen_error; - - uint8_t published_initial_metadata; - uint8_t published_trailing_metadata; - uint8_t faked_trailing_metadata; - - grpc_chttp2_incoming_metadata_buffer received_initial_metadata; - grpc_chttp2_incoming_metadata_buffer received_trailing_metadata; - - grpc_chttp2_incoming_frame_queue incoming_frames; -} grpc_chttp2_stream_global; - -typedef struct { - /** HTTP2 stream id for this stream, or zero if one has not been assigned */ - uint32_t id; - uint8_t fetching; - bool sent_initial_metadata; - uint8_t sent_message; - uint8_t sent_trailing_metadata; - uint8_t read_closed; - /** send this initial metadata */ - grpc_metadata_batch *send_initial_metadata; - grpc_byte_stream *send_message; - grpc_metadata_batch *send_trailing_metadata; - int64_t outgoing_window; - /** how much window should we announce? */ - uint32_t announce_window; - gpr_slice_buffer flow_controlled_buffer; - gpr_slice fetching_slice; - size_t stream_fetched; - grpc_closure finished_fetch; -} grpc_chttp2_stream_writing; - -struct grpc_chttp2_stream_parsing { - /** HTTP2 stream id for this stream, or zero if one has not been assigned */ - uint32_t id; - /** has this stream received a close */ - uint8_t received_close; - /** saw a rst_stream */ - uint8_t saw_rst_stream; - /** how many header frames have we received? */ - uint8_t header_frames_received; - /** which metadata did we get (on this parse) */ - uint8_t got_metadata_on_parse[2]; - /** should we raise the seen_error flag in transport_global */ - uint8_t seen_error; - /** window available for peer to send to us */ - int64_t incoming_window; - /** parsing state for data frames */ - grpc_chttp2_data_parser data_parser; - /** reason give to rst_stream */ - uint32_t rst_stream_reason; - /** amount of window given */ - int64_t outgoing_window; - /** number of bytes received - reset at end of parse thread execution */ - int64_t received_bytes; - - /** incoming metadata */ - grpc_chttp2_incoming_metadata_buffer metadata_buffer[2]; -}; - -struct grpc_chttp2_stream { - grpc_stream_refcount *refcount; - grpc_chttp2_stream_global global; - grpc_chttp2_stream_writing writing; - grpc_chttp2_stream_parsing parsing; - - grpc_chttp2_stream_link links[STREAM_LIST_COUNT]; - uint8_t included[STREAM_LIST_COUNT]; -}; - -/** Transport writing call flow: - chttp2_transport.c calls grpc_chttp2_unlocking_check_writes to see if writes - are required; - if they are, chttp2_transport.c calls grpc_chttp2_perform_writes to do the - writes. - Once writes have been completed (meaning another write could potentially be - started), - grpc_chttp2_terminate_writing is called. This will call - grpc_chttp2_cleanup_writing, at which - point the write phase is complete. */ - -/** 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_exec_ctx *exec_ctx, - grpc_chttp2_transport_global *global, - 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); -void grpc_chttp2_terminate_writing(grpc_exec_ctx *exec_ctx, - void *transport_writing, bool success); -void grpc_chttp2_cleanup_writing(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport_global *global, - grpc_chttp2_transport_writing *writing); - -void grpc_chttp2_prepare_to_read(grpc_chttp2_transport_global *global, - grpc_chttp2_transport_parsing *parsing); -/** Process one slice of incoming data; return 1 if the connection is still - viable after reading, or 0 if the connection should be torn down */ -int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport_parsing *transport_parsing, - gpr_slice slice); -void grpc_chttp2_publish_reads(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport_global *global, - grpc_chttp2_transport_parsing *parsing); - -bool grpc_chttp2_list_add_writable_stream( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global); -/** Get a writable stream - returns non-zero if there was a stream available */ -int grpc_chttp2_list_pop_writable_stream( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_transport_writing *transport_writing, - grpc_chttp2_stream_global **stream_global, - grpc_chttp2_stream_writing **stream_writing); -bool grpc_chttp2_list_remove_writable_stream( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global) GRPC_MUST_USE_RESULT; - -void grpc_chttp2_list_add_writing_stream( - grpc_chttp2_transport_writing *transport_writing, - grpc_chttp2_stream_writing *stream_writing); -int grpc_chttp2_list_have_writing_streams( - grpc_chttp2_transport_writing *transport_writing); -int grpc_chttp2_list_pop_writing_stream( - grpc_chttp2_transport_writing *transport_writing, - grpc_chttp2_stream_writing **stream_writing); - -void grpc_chttp2_list_add_written_stream( - grpc_chttp2_transport_writing *transport_writing, - grpc_chttp2_stream_writing *stream_writing); -int grpc_chttp2_list_pop_written_stream( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_transport_writing *transport_writing, - grpc_chttp2_stream_global **stream_global, - grpc_chttp2_stream_writing **stream_writing); - -void grpc_chttp2_list_add_parsing_seen_stream( - grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_parsing *stream_parsing); -int grpc_chttp2_list_pop_parsing_seen_stream( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_global **stream_global, - grpc_chttp2_stream_parsing **stream_parsing); - -void grpc_chttp2_list_add_waiting_for_concurrency( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global); -int grpc_chttp2_list_pop_waiting_for_concurrency( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global **stream_global); - -void grpc_chttp2_list_add_check_read_ops( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global); -int grpc_chttp2_list_pop_check_read_ops( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global **stream_global); - -void grpc_chttp2_list_add_writing_stalled_by_transport( - grpc_chttp2_transport_writing *transport_writing, - grpc_chttp2_stream_writing *stream_writing); -void grpc_chttp2_list_flush_writing_stalled_by_transport( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing, - bool is_window_available); - -void grpc_chttp2_list_add_stalled_by_transport( - grpc_chttp2_transport_writing *transport_writing, - grpc_chttp2_stream_writing *stream_writing); -int grpc_chttp2_list_pop_stalled_by_transport( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global **stream_global); -void grpc_chttp2_list_remove_stalled_by_transport( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global); - -void grpc_chttp2_list_add_unannounced_incoming_window_available( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global); -void grpc_chttp2_list_remove_unannounced_incoming_window_available( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global); -int grpc_chttp2_list_pop_unannounced_incoming_window_available( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_global **stream_global, - grpc_chttp2_stream_parsing **stream_parsing); - -void grpc_chttp2_list_add_closed_waiting_for_parsing( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global); -int grpc_chttp2_list_pop_closed_waiting_for_parsing( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global **stream_global); - -void grpc_chttp2_list_add_closed_waiting_for_writing( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global); -int grpc_chttp2_list_pop_closed_waiting_for_writing( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global **stream_global); - -grpc_chttp2_stream_parsing *grpc_chttp2_parsing_lookup_stream( - grpc_chttp2_transport_parsing *transport_parsing, uint32_t id); -grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing, - uint32_t id); - -void grpc_chttp2_add_incoming_goaway( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, - uint32_t goaway_error, gpr_slice goaway_text); - -void grpc_chttp2_register_stream(grpc_chttp2_transport *t, - grpc_chttp2_stream *s); -/* returns 1 if this is the last stream, 0 otherwise */ -int grpc_chttp2_unregister_stream(grpc_chttp2_transport *t, - grpc_chttp2_stream *s) GRPC_MUST_USE_RESULT; -int grpc_chttp2_has_streams(grpc_chttp2_transport *t); -void grpc_chttp2_for_all_streams( - grpc_chttp2_transport_global *transport_global, void *user_data, - void (*cb)(grpc_chttp2_transport_global *transport_global, void *user_data, - grpc_chttp2_stream_global *stream_global)); - -void grpc_chttp2_parsing_become_skip_parser( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing); - -void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx, - grpc_closure **pclosure, int success); - -#define GRPC_CHTTP2_CLIENT_CONNECT_STRING "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" -#define GRPC_CHTTP2_CLIENT_CONNECT_STRLEN \ - (sizeof(GRPC_CHTTP2_CLIENT_CONNECT_STRING) - 1) - -extern int grpc_http_trace; -extern int grpc_flowctl_trace; - -#define GRPC_CHTTP2_IF_TRACING(stmt) \ - if (!(grpc_http_trace)) \ - ; \ - else \ - stmt - -typedef enum { - GRPC_CHTTP2_FLOWCTL_MOVE, - GRPC_CHTTP2_FLOWCTL_CREDIT, - GRPC_CHTTP2_FLOWCTL_DEBIT -} grpc_chttp2_flowctl_op; - -#define GRPC_CHTTP2_FLOW_MOVE_COMMON(phase, transport, id1, id2, dst_context, \ - dst_var, src_context, src_var) \ - do { \ - assert(id1 == id2); \ - if (grpc_flowctl_trace) { \ - grpc_chttp2_flowctl_trace( \ - __FILE__, __LINE__, phase, GRPC_CHTTP2_FLOWCTL_MOVE, #dst_context, \ - #dst_var, #src_context, #src_var, transport->is_client, id1, \ - dst_context->dst_var, src_context->src_var); \ - } \ - dst_context->dst_var += src_context->src_var; \ - src_context->src_var = 0; \ - } while (0) - -#define GRPC_CHTTP2_FLOW_MOVE_STREAM(phase, transport, dst_context, dst_var, \ - src_context, src_var) \ - GRPC_CHTTP2_FLOW_MOVE_COMMON(phase, transport, dst_context->id, \ - src_context->id, dst_context, dst_var, \ - src_context, src_var) -#define GRPC_CHTTP2_FLOW_MOVE_TRANSPORT(phase, dst_context, dst_var, \ - src_context, src_var) \ - GRPC_CHTTP2_FLOW_MOVE_COMMON(phase, dst_context, 0, 0, dst_context, dst_var, \ - src_context, src_var) - -#define GRPC_CHTTP2_FLOW_CREDIT_COMMON(phase, transport, id, dst_context, \ - dst_var, amount) \ - do { \ - if (grpc_flowctl_trace) { \ - grpc_chttp2_flowctl_trace(__FILE__, __LINE__, phase, \ - GRPC_CHTTP2_FLOWCTL_CREDIT, #dst_context, \ - #dst_var, NULL, #amount, transport->is_client, \ - id, dst_context->dst_var, amount); \ - } \ - dst_context->dst_var += amount; \ - } while (0) - -#define GRPC_CHTTP2_FLOW_CREDIT_STREAM(phase, transport, dst_context, dst_var, \ - amount) \ - GRPC_CHTTP2_FLOW_CREDIT_COMMON(phase, transport, dst_context->id, \ - dst_context, dst_var, amount) -#define GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT(phase, dst_context, dst_var, amount) \ - GRPC_CHTTP2_FLOW_CREDIT_COMMON(phase, dst_context, 0, dst_context, dst_var, \ - amount) - -#define GRPC_CHTTP2_FLOW_DEBIT_COMMON(phase, transport, id, dst_context, \ - dst_var, amount) \ - do { \ - if (grpc_flowctl_trace) { \ - grpc_chttp2_flowctl_trace(__FILE__, __LINE__, phase, \ - GRPC_CHTTP2_FLOWCTL_DEBIT, #dst_context, \ - #dst_var, NULL, #amount, transport->is_client, \ - id, dst_context->dst_var, amount); \ - } \ - dst_context->dst_var -= amount; \ - } while (0) - -#define GRPC_CHTTP2_FLOW_DEBIT_STREAM(phase, transport, dst_context, dst_var, \ - amount) \ - GRPC_CHTTP2_FLOW_DEBIT_COMMON(phase, transport, dst_context->id, \ - dst_context, dst_var, amount) -#define GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT(phase, dst_context, dst_var, amount) \ - GRPC_CHTTP2_FLOW_DEBIT_COMMON(phase, dst_context, 0, dst_context, dst_var, \ - amount) - -void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase, - grpc_chttp2_flowctl_op op, const char *context1, - const char *var1, const char *context2, - const char *var2, int is_client, - uint32_t stream_id, int64_t val1, int64_t val2); - -void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream, - grpc_status_code status, gpr_slice *details); -void grpc_chttp2_mark_stream_closed( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global, int close_reads, - int close_writes); -void grpc_chttp2_start_writing(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport_global *transport_global); - -#ifdef GRPC_STREAM_REFCOUNT_DEBUG -#define GRPC_CHTTP2_STREAM_REF(stream_global, reason) \ - grpc_chttp2_stream_ref(stream_global, reason) -#define GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, reason) \ - grpc_chttp2_stream_unref(exec_ctx, stream_global, reason) -void grpc_chttp2_stream_ref(grpc_chttp2_stream_global *stream_global, - const char *reason); -void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx, - grpc_chttp2_stream_global *stream_global, - const char *reason); -#else -#define GRPC_CHTTP2_STREAM_REF(stream_global, reason) \ - grpc_chttp2_stream_ref(stream_global) -#define GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, reason) \ - grpc_chttp2_stream_unref(exec_ctx, stream_global) -void grpc_chttp2_stream_ref(grpc_chttp2_stream_global *stream_global); -void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx, - grpc_chttp2_stream_global *stream_global); -#endif - -grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_parsing *stream_parsing, uint32_t frame_size, - uint32_t flags, grpc_chttp2_incoming_frame_queue *add_to_queue); -void grpc_chttp2_incoming_byte_stream_push(grpc_exec_ctx *exec_ctx, - grpc_chttp2_incoming_byte_stream *bs, - gpr_slice slice); -void grpc_chttp2_incoming_byte_stream_finished( - grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs, int success, - int from_parsing_thread); - -void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport_parsing *parsing, - const uint8_t *opaque_8bytes); - -/** add a ref to the stream and add it to the writable list; - ref will be dropped in writing.c */ -void grpc_chttp2_become_writable(grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global); - -#endif /* GRPC_CORE_LIB_TRANSPORT_CHTTP2_INTERNAL_H */ diff --git a/src/core/lib/transport/chttp2/parsing.c b/src/core/lib/transport/chttp2/parsing.c deleted file mode 100644 index 9ee52f63f2..0000000000 --- a/src/core/lib/transport/chttp2/parsing.c +++ /dev/null @@ -1,866 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/lib/transport/chttp2/internal.h" - -#include <string.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/string_util.h> - -#include "src/core/lib/profiling/timers.h" -#include "src/core/lib/transport/chttp2/http2_errors.h" -#include "src/core/lib/transport/chttp2/status_conversion.h" -#include "src/core/lib/transport/chttp2/timeout_encoding.h" -#include "src/core/lib/transport/static_metadata.h" - -static int init_frame_parser(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport_parsing *transport_parsing); -static int init_header_frame_parser( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing, - int is_continuation); -static int init_data_frame_parser( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing); -static int init_rst_stream_parser( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing); -static int init_settings_frame_parser( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing); -static int init_window_update_frame_parser( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing); -static int init_ping_parser(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport_parsing *transport_parsing); -static int init_goaway_parser(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport_parsing *transport_parsing); -static int init_skip_frame_parser( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing, - int is_header); - -static int parse_frame_slice(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport_parsing *transport_parsing, - gpr_slice slice, int is_last); - -void grpc_chttp2_prepare_to_read( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_transport_parsing *transport_parsing) { - grpc_chttp2_stream_global *stream_global; - grpc_chttp2_stream_parsing *stream_parsing; - - 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( - transport_global, transport_parsing, &stream_global, &stream_parsing)) { - GRPC_CHTTP2_FLOW_MOVE_STREAM("parse", transport_parsing, stream_parsing, - incoming_window, stream_global, - unannounced_incoming_window_for_parse); - } - - GPR_TIMER_END("grpc_chttp2_prepare_to_read", 0); -} - -void grpc_chttp2_publish_reads( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, - grpc_chttp2_transport_parsing *transport_parsing) { - grpc_chttp2_stream_global *stream_global; - grpc_chttp2_stream_parsing *stream_parsing; - int was_zero; - int is_zero; - - /* transport_parsing->last_incoming_stream_id is used as - last-grpc_chttp2_stream-id when - sending GOAWAY frame. - https://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-6.8 - says that last-grpc_chttp2_stream-id is peer-initiated grpc_chttp2_stream - ID. So, - since we don't have server pushed streams, client should send - GOAWAY last-grpc_chttp2_stream-id=0 in this case. */ - if (!transport_parsing->is_client) { - transport_global->last_incoming_stream_id = - transport_parsing->incoming_stream_id; - } - - /* update global settings */ - if (transport_parsing->settings_updated) { - memcpy(transport_global->settings[GRPC_PEER_SETTINGS], - transport_parsing->settings, sizeof(transport_parsing->settings)); - transport_parsing->settings_updated = 0; - } - - /* update settings based on ack if received */ - if (transport_parsing->settings_ack_received) { - memcpy(transport_global->settings[GRPC_ACKED_SETTINGS], - transport_global->settings[GRPC_SENT_SETTINGS], - GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t)); - 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 - published later */ - if (transport_parsing->goaway_received) { - grpc_chttp2_add_incoming_goaway(exec_ctx, transport_global, - (uint32_t)transport_parsing->goaway_error, - transport_parsing->goaway_text); - transport_parsing->goaway_text = gpr_empty_slice(); - transport_parsing->goaway_received = 0; - } - - /* propagate flow control tokens to global state */ - was_zero = transport_global->outgoing_window <= 0; - GRPC_CHTTP2_FLOW_MOVE_TRANSPORT("parsed", transport_global, outgoing_window, - transport_parsing, outgoing_window); - is_zero = transport_global->outgoing_window <= 0; - if (was_zero && !is_zero) { - while (grpc_chttp2_list_pop_stalled_by_transport(transport_global, - &stream_global)) { - grpc_chttp2_become_writable(transport_global, stream_global); - } - } - - if (transport_parsing->incoming_window < - transport_global->connection_window_target * 3 / 4) { - int64_t announce_bytes = transport_global->connection_window_target - - transport_parsing->incoming_window; - GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", transport_global, - announce_incoming_window, announce_bytes); - GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", transport_parsing, - incoming_window, announce_bytes); - } - - /* for each stream that saw an update, fixup global state */ - while (grpc_chttp2_list_pop_parsing_seen_stream( - transport_global, transport_parsing, &stream_global, &stream_parsing)) { - if (stream_parsing->seen_error) { - stream_global->seen_error = 1; - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); - } - - /* update outgoing flow control window */ - was_zero = stream_global->outgoing_window <= 0; - GRPC_CHTTP2_FLOW_MOVE_STREAM("parsed", transport_global, stream_global, - outgoing_window, stream_parsing, - outgoing_window); - is_zero = stream_global->outgoing_window <= 0; - if (was_zero && !is_zero) { - grpc_chttp2_become_writable(transport_global, stream_global); - } - - stream_global->max_recv_bytes -= (uint32_t)GPR_MIN( - stream_global->max_recv_bytes, stream_parsing->received_bytes); - stream_parsing->received_bytes = 0; - - /* publish incoming stream ops */ - if (stream_global->incoming_frames.tail != NULL) { - stream_global->incoming_frames.tail->is_tail = 0; - } - if (stream_parsing->data_parser.incoming_frames.head != NULL) { - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); - } - grpc_chttp2_incoming_frame_queue_merge( - &stream_global->incoming_frames, - &stream_parsing->data_parser.incoming_frames); - if (stream_global->incoming_frames.tail != NULL) { - stream_global->incoming_frames.tail->is_tail = 1; - } - - if (!stream_global->published_initial_metadata && - stream_parsing->got_metadata_on_parse[0]) { - stream_parsing->got_metadata_on_parse[0] = 0; - stream_global->published_initial_metadata = 1; - GPR_SWAP(grpc_chttp2_incoming_metadata_buffer, - stream_parsing->metadata_buffer[0], - stream_global->received_initial_metadata); - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); - } - if (!stream_global->published_trailing_metadata && - stream_parsing->got_metadata_on_parse[1]) { - stream_parsing->got_metadata_on_parse[1] = 0; - stream_global->published_trailing_metadata = 1; - GPR_SWAP(grpc_chttp2_incoming_metadata_buffer, - stream_parsing->metadata_buffer[1], - stream_global->received_trailing_metadata); - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); - } - - if (stream_parsing->saw_rst_stream) { - if (stream_parsing->rst_stream_reason != GRPC_CHTTP2_NO_ERROR) { - grpc_status_code status_code = grpc_chttp2_http2_error_to_grpc_status( - (grpc_chttp2_error_code)stream_parsing->rst_stream_reason); - char *status_details; - gpr_slice slice_details; - gpr_asprintf(&status_details, "Received RST_STREAM err=%d", - stream_parsing->rst_stream_reason); - slice_details = gpr_slice_from_copied_string(status_details); - gpr_free(status_details); - grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global, - status_code, &slice_details); - } - grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, - 1, 1); - } - - if (stream_parsing->received_close) { - grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, - 1, 0); - } - } -} - -int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport_parsing *transport_parsing, - gpr_slice slice) { - uint8_t *beg = GPR_SLICE_START_PTR(slice); - uint8_t *end = GPR_SLICE_END_PTR(slice); - uint8_t *cur = beg; - - if (cur == end) return 1; - - switch (transport_parsing->deframe_state) { - case GRPC_DTS_CLIENT_PREFIX_0: - case GRPC_DTS_CLIENT_PREFIX_1: - case GRPC_DTS_CLIENT_PREFIX_2: - case GRPC_DTS_CLIENT_PREFIX_3: - case GRPC_DTS_CLIENT_PREFIX_4: - case GRPC_DTS_CLIENT_PREFIX_5: - case GRPC_DTS_CLIENT_PREFIX_6: - case GRPC_DTS_CLIENT_PREFIX_7: - case GRPC_DTS_CLIENT_PREFIX_8: - case GRPC_DTS_CLIENT_PREFIX_9: - case GRPC_DTS_CLIENT_PREFIX_10: - case GRPC_DTS_CLIENT_PREFIX_11: - case GRPC_DTS_CLIENT_PREFIX_12: - case GRPC_DTS_CLIENT_PREFIX_13: - case GRPC_DTS_CLIENT_PREFIX_14: - case GRPC_DTS_CLIENT_PREFIX_15: - case GRPC_DTS_CLIENT_PREFIX_16: - case GRPC_DTS_CLIENT_PREFIX_17: - case GRPC_DTS_CLIENT_PREFIX_18: - case GRPC_DTS_CLIENT_PREFIX_19: - case GRPC_DTS_CLIENT_PREFIX_20: - case GRPC_DTS_CLIENT_PREFIX_21: - case GRPC_DTS_CLIENT_PREFIX_22: - case GRPC_DTS_CLIENT_PREFIX_23: - while (cur != end && transport_parsing->deframe_state != GRPC_DTS_FH_0) { - if (*cur != GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing - ->deframe_state]) { - gpr_log(GPR_INFO, - "Connect string mismatch: expected '%c' (%d) got '%c' (%d) " - "at byte %d", - GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing - ->deframe_state], - (int)(uint8_t)GRPC_CHTTP2_CLIENT_CONNECT_STRING - [transport_parsing->deframe_state], - *cur, (int)*cur, transport_parsing->deframe_state); - return 0; - } - ++cur; - ++transport_parsing->deframe_state; - } - if (cur == end) { - return 1; - } - /* fallthrough */ - dts_fh_0: - case GRPC_DTS_FH_0: - GPR_ASSERT(cur < end); - transport_parsing->incoming_frame_size = ((uint32_t)*cur) << 16; - if (++cur == end) { - transport_parsing->deframe_state = GRPC_DTS_FH_1; - return 1; - } - /* fallthrough */ - case GRPC_DTS_FH_1: - GPR_ASSERT(cur < end); - transport_parsing->incoming_frame_size |= ((uint32_t)*cur) << 8; - if (++cur == end) { - transport_parsing->deframe_state = GRPC_DTS_FH_2; - return 1; - } - /* fallthrough */ - case GRPC_DTS_FH_2: - GPR_ASSERT(cur < end); - transport_parsing->incoming_frame_size |= *cur; - if (++cur == end) { - transport_parsing->deframe_state = GRPC_DTS_FH_3; - return 1; - } - /* fallthrough */ - case GRPC_DTS_FH_3: - GPR_ASSERT(cur < end); - transport_parsing->incoming_frame_type = *cur; - if (++cur == end) { - transport_parsing->deframe_state = GRPC_DTS_FH_4; - return 1; - } - /* fallthrough */ - case GRPC_DTS_FH_4: - GPR_ASSERT(cur < end); - transport_parsing->incoming_frame_flags = *cur; - if (++cur == end) { - transport_parsing->deframe_state = GRPC_DTS_FH_5; - return 1; - } - /* fallthrough */ - case GRPC_DTS_FH_5: - GPR_ASSERT(cur < end); - transport_parsing->incoming_stream_id = (((uint32_t)*cur) & 0x7f) << 24; - if (++cur == end) { - transport_parsing->deframe_state = GRPC_DTS_FH_6; - return 1; - } - /* fallthrough */ - case GRPC_DTS_FH_6: - GPR_ASSERT(cur < end); - transport_parsing->incoming_stream_id |= ((uint32_t)*cur) << 16; - if (++cur == end) { - transport_parsing->deframe_state = GRPC_DTS_FH_7; - return 1; - } - /* fallthrough */ - case GRPC_DTS_FH_7: - GPR_ASSERT(cur < end); - transport_parsing->incoming_stream_id |= ((uint32_t)*cur) << 8; - if (++cur == end) { - transport_parsing->deframe_state = GRPC_DTS_FH_8; - return 1; - } - /* fallthrough */ - case GRPC_DTS_FH_8: - GPR_ASSERT(cur < end); - transport_parsing->incoming_stream_id |= ((uint32_t)*cur); - transport_parsing->deframe_state = GRPC_DTS_FRAME; - if (!init_frame_parser(exec_ctx, transport_parsing)) { - return 0; - } - if (transport_parsing->incoming_stream_id) { - transport_parsing->last_incoming_stream_id = - transport_parsing->incoming_stream_id; - } - if (transport_parsing->incoming_frame_size == 0) { - if (!parse_frame_slice(exec_ctx, transport_parsing, gpr_empty_slice(), - 1)) { - return 0; - } - transport_parsing->incoming_stream = NULL; - if (++cur == end) { - transport_parsing->deframe_state = GRPC_DTS_FH_0; - return 1; - } - goto dts_fh_0; /* loop */ - } - if (++cur == end) { - return 1; - } - /* fallthrough */ - case GRPC_DTS_FRAME: - GPR_ASSERT(cur < end); - if ((uint32_t)(end - cur) == transport_parsing->incoming_frame_size) { - if (!parse_frame_slice(exec_ctx, transport_parsing, - gpr_slice_sub_no_ref(slice, (size_t)(cur - beg), - (size_t)(end - beg)), - 1)) { - return 0; - } - transport_parsing->deframe_state = GRPC_DTS_FH_0; - transport_parsing->incoming_stream = NULL; - return 1; - } else if ((uint32_t)(end - cur) > - transport_parsing->incoming_frame_size) { - size_t cur_offset = (size_t)(cur - beg); - if (!parse_frame_slice( - exec_ctx, transport_parsing, - gpr_slice_sub_no_ref( - slice, cur_offset, - cur_offset + transport_parsing->incoming_frame_size), - 1)) { - return 0; - } - cur += transport_parsing->incoming_frame_size; - transport_parsing->incoming_stream = NULL; - goto dts_fh_0; /* loop */ - } else { - if (!parse_frame_slice(exec_ctx, transport_parsing, - gpr_slice_sub_no_ref(slice, (size_t)(cur - beg), - (size_t)(end - beg)), - 0)) { - return 0; - } - transport_parsing->incoming_frame_size -= (uint32_t)(end - cur); - return 1; - } - GPR_UNREACHABLE_CODE(return 0); - } - - GPR_UNREACHABLE_CODE(return 0); -} - -static int init_frame_parser(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport_parsing *transport_parsing) { - if (transport_parsing->expect_continuation_stream_id != 0) { - if (transport_parsing->incoming_frame_type != - GRPC_CHTTP2_FRAME_CONTINUATION) { - gpr_log(GPR_ERROR, "Expected CONTINUATION frame, got frame type %02x", - transport_parsing->incoming_frame_type); - return 0; - } - if (transport_parsing->expect_continuation_stream_id != - transport_parsing->incoming_stream_id) { - gpr_log(GPR_ERROR, - "Expected CONTINUATION frame for grpc_chttp2_stream %08x, got " - "grpc_chttp2_stream %08x", - transport_parsing->expect_continuation_stream_id, - transport_parsing->incoming_stream_id); - return 0; - } - return init_header_frame_parser(exec_ctx, transport_parsing, 1); - } - switch (transport_parsing->incoming_frame_type) { - case GRPC_CHTTP2_FRAME_DATA: - return init_data_frame_parser(exec_ctx, transport_parsing); - case GRPC_CHTTP2_FRAME_HEADER: - return init_header_frame_parser(exec_ctx, transport_parsing, 0); - case GRPC_CHTTP2_FRAME_CONTINUATION: - gpr_log(GPR_ERROR, "Unexpected CONTINUATION frame"); - return 0; - case GRPC_CHTTP2_FRAME_RST_STREAM: - return init_rst_stream_parser(exec_ctx, transport_parsing); - case GRPC_CHTTP2_FRAME_SETTINGS: - return init_settings_frame_parser(exec_ctx, transport_parsing); - case GRPC_CHTTP2_FRAME_WINDOW_UPDATE: - return init_window_update_frame_parser(exec_ctx, transport_parsing); - case GRPC_CHTTP2_FRAME_PING: - return init_ping_parser(exec_ctx, transport_parsing); - case GRPC_CHTTP2_FRAME_GOAWAY: - return init_goaway_parser(exec_ctx, transport_parsing); - default: - gpr_log(GPR_ERROR, "Unknown frame type %02x", - transport_parsing->incoming_frame_type); - return init_skip_frame_parser(exec_ctx, transport_parsing, 0); - } -} - -static grpc_chttp2_parse_error skip_parser( - grpc_exec_ctx *exec_ctx, void *parser, - grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) { - return GRPC_CHTTP2_PARSE_OK; -} - -static void skip_header(void *tp, grpc_mdelem *md) { GRPC_MDELEM_UNREF(md); } - -static int init_skip_frame_parser( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing, - int is_header) { - if (is_header) { - uint8_t is_eoh = transport_parsing->expect_continuation_stream_id != 0; - transport_parsing->parser = grpc_chttp2_header_parser_parse; - transport_parsing->parser_data = &transport_parsing->hpack_parser; - transport_parsing->hpack_parser.on_header = skip_header; - transport_parsing->hpack_parser.on_header_user_data = NULL; - transport_parsing->hpack_parser.is_boundary = is_eoh; - transport_parsing->hpack_parser.is_eof = - (uint8_t)(is_eoh ? transport_parsing->header_eof : 0); - } else { - transport_parsing->parser = skip_parser; - } - return 1; -} - -void grpc_chttp2_parsing_become_skip_parser( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) { - init_skip_frame_parser( - exec_ctx, transport_parsing, - transport_parsing->parser == grpc_chttp2_header_parser_parse); -} - -static grpc_chttp2_parse_error update_incoming_window( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_parsing *stream_parsing) { - uint32_t incoming_frame_size = transport_parsing->incoming_frame_size; - if (incoming_frame_size > transport_parsing->incoming_window) { - gpr_log(GPR_ERROR, "frame of size %d overflows incoming window of %d", - transport_parsing->incoming_frame_size, - transport_parsing->incoming_window); - return GRPC_CHTTP2_CONNECTION_ERROR; - } - - if (incoming_frame_size > stream_parsing->incoming_window) { - gpr_log(GPR_ERROR, "frame of size %d overflows incoming window of %d", - transport_parsing->incoming_frame_size, - stream_parsing->incoming_window); - return GRPC_CHTTP2_CONNECTION_ERROR; - } - - GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("parse", transport_parsing, incoming_window, - incoming_frame_size); - GRPC_CHTTP2_FLOW_DEBIT_STREAM("parse", transport_parsing, stream_parsing, - incoming_window, incoming_frame_size); - stream_parsing->received_bytes += incoming_frame_size; - - grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing); - - return GRPC_CHTTP2_PARSE_OK; -} - -static int init_data_frame_parser( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) { - grpc_chttp2_stream_parsing *stream_parsing = - grpc_chttp2_parsing_lookup_stream(transport_parsing, - transport_parsing->incoming_stream_id); - grpc_chttp2_parse_error err = GRPC_CHTTP2_PARSE_OK; - if (!stream_parsing || stream_parsing->received_close) - return init_skip_frame_parser(exec_ctx, transport_parsing, 0); - if (err == GRPC_CHTTP2_PARSE_OK) { - err = update_incoming_window(exec_ctx, transport_parsing, stream_parsing); - } - if (err == GRPC_CHTTP2_PARSE_OK) { - err = grpc_chttp2_data_parser_begin_frame( - &stream_parsing->data_parser, transport_parsing->incoming_frame_flags); - } - switch (err) { - case GRPC_CHTTP2_PARSE_OK: - transport_parsing->incoming_stream = stream_parsing; - transport_parsing->parser = grpc_chttp2_data_parser_parse; - transport_parsing->parser_data = &stream_parsing->data_parser; - return 1; - case GRPC_CHTTP2_STREAM_ERROR: - stream_parsing->received_close = 1; - stream_parsing->saw_rst_stream = 1; - stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR; - gpr_slice_buffer_add( - &transport_parsing->qbuf, - grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id, - GRPC_CHTTP2_PROTOCOL_ERROR)); - return init_skip_frame_parser(exec_ctx, transport_parsing, 0); - case GRPC_CHTTP2_CONNECTION_ERROR: - return 0; - } - GPR_UNREACHABLE_CODE(return 0); -} - -static void free_timeout(void *p) { gpr_free(p); } - -static void on_initial_header(void *tp, grpc_mdelem *md) { - grpc_chttp2_transport_parsing *transport_parsing = tp; - grpc_chttp2_stream_parsing *stream_parsing = - transport_parsing->incoming_stream; - - GPR_TIMER_BEGIN("on_initial_header", 0); - - GPR_ASSERT(stream_parsing); - - GRPC_CHTTP2_IF_TRACING(gpr_log( - GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", stream_parsing->id, - transport_parsing->is_client ? "CLI" : "SVR", - grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value))); - - if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) { - /* TODO(ctiller): check for a status like " 0" */ - stream_parsing->seen_error = 1; - } - - if (md->key == GRPC_MDSTR_GRPC_TIMEOUT) { - gpr_timespec *cached_timeout = grpc_mdelem_get_user_data(md, free_timeout); - if (!cached_timeout) { - /* not already parsed: parse it now, and store the result away */ - cached_timeout = gpr_malloc(sizeof(gpr_timespec)); - if (!grpc_chttp2_decode_timeout(grpc_mdstr_as_c_string(md->value), - cached_timeout)) { - gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", - grpc_mdstr_as_c_string(md->value)); - *cached_timeout = gpr_inf_future(GPR_TIMESPAN); - } - grpc_mdelem_set_user_data(md, free_timeout, cached_timeout); - } - grpc_chttp2_incoming_metadata_buffer_set_deadline( - &stream_parsing->metadata_buffer[0], - gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), *cached_timeout)); - GRPC_MDELEM_UNREF(md); - } else { - grpc_chttp2_incoming_metadata_buffer_add( - &stream_parsing->metadata_buffer[0], md); - } - - grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing); - - GPR_TIMER_END("on_initial_header", 0); -} - -static void on_trailing_header(void *tp, grpc_mdelem *md) { - grpc_chttp2_transport_parsing *transport_parsing = tp; - grpc_chttp2_stream_parsing *stream_parsing = - transport_parsing->incoming_stream; - - GPR_TIMER_BEGIN("on_trailing_header", 0); - - GPR_ASSERT(stream_parsing); - - GRPC_CHTTP2_IF_TRACING(gpr_log( - GPR_INFO, "HTTP:%d:TRL:%s: %s: %s", stream_parsing->id, - transport_parsing->is_client ? "CLI" : "SVR", - grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value))); - - if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) { - /* TODO(ctiller): check for a status like " 0" */ - stream_parsing->seen_error = 1; - } - - grpc_chttp2_incoming_metadata_buffer_add(&stream_parsing->metadata_buffer[1], - md); - - grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing); - - GPR_TIMER_END("on_trailing_header", 0); -} - -static int init_header_frame_parser( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing, - int is_continuation) { - uint8_t is_eoh = (transport_parsing->incoming_frame_flags & - GRPC_CHTTP2_DATA_FLAG_END_HEADERS) != 0; - int via_accept = 0; - grpc_chttp2_stream_parsing *stream_parsing; - - /* TODO(ctiller): when to increment header_frames_received? */ - - if (is_eoh) { - transport_parsing->expect_continuation_stream_id = 0; - } else { - transport_parsing->expect_continuation_stream_id = - transport_parsing->incoming_stream_id; - } - - if (!is_continuation) { - transport_parsing->header_eof = (transport_parsing->incoming_frame_flags & - GRPC_CHTTP2_DATA_FLAG_END_STREAM) != 0; - } - - /* could be a new grpc_chttp2_stream or an existing grpc_chttp2_stream */ - stream_parsing = grpc_chttp2_parsing_lookup_stream( - transport_parsing, transport_parsing->incoming_stream_id); - if (stream_parsing == NULL) { - if (is_continuation) { - gpr_log(GPR_ERROR, - "grpc_chttp2_stream disbanded before CONTINUATION received"); - return init_skip_frame_parser(exec_ctx, transport_parsing, 1); - } - if (transport_parsing->is_client) { - if ((transport_parsing->incoming_stream_id & 1) && - transport_parsing->incoming_stream_id < - transport_parsing->next_stream_id) { - /* this is an old (probably cancelled) grpc_chttp2_stream */ - } else { - gpr_log(GPR_ERROR, - "ignoring new grpc_chttp2_stream creation on client"); - } - return init_skip_frame_parser(exec_ctx, transport_parsing, 1); - } else if (transport_parsing->last_incoming_stream_id > - transport_parsing->incoming_stream_id) { - gpr_log(GPR_ERROR, - "ignoring out of order new grpc_chttp2_stream request on server; " - "last grpc_chttp2_stream " - "id=%d, new grpc_chttp2_stream id=%d", - transport_parsing->last_incoming_stream_id, - transport_parsing->incoming_stream_id); - return init_skip_frame_parser(exec_ctx, transport_parsing, 1); - } else if ((transport_parsing->incoming_stream_id & 1) == 0) { - gpr_log(GPR_ERROR, - "ignoring grpc_chttp2_stream with non-client generated index %d", - transport_parsing->incoming_stream_id); - return init_skip_frame_parser(exec_ctx, transport_parsing, 1); - } - stream_parsing = transport_parsing->incoming_stream = - grpc_chttp2_parsing_accept_stream( - exec_ctx, transport_parsing, transport_parsing->incoming_stream_id); - if (stream_parsing == NULL) { - gpr_log(GPR_ERROR, "grpc_chttp2_stream not accepted"); - return init_skip_frame_parser(exec_ctx, transport_parsing, 1); - } - via_accept = 1; - } else { - transport_parsing->incoming_stream = stream_parsing; - } - GPR_ASSERT(stream_parsing != NULL && (via_accept == 0 || via_accept == 1)); - if (stream_parsing->received_close) { - gpr_log(GPR_ERROR, "skipping already closed grpc_chttp2_stream header"); - transport_parsing->incoming_stream = NULL; - return init_skip_frame_parser(exec_ctx, transport_parsing, 1); - } - transport_parsing->parser = grpc_chttp2_header_parser_parse; - transport_parsing->parser_data = &transport_parsing->hpack_parser; - switch (stream_parsing->header_frames_received) { - case 0: - transport_parsing->hpack_parser.on_header = on_initial_header; - break; - case 1: - transport_parsing->hpack_parser.on_header = on_trailing_header; - break; - case 2: - gpr_log(GPR_ERROR, "too many header frames received"); - return init_skip_frame_parser(exec_ctx, transport_parsing, 1); - } - transport_parsing->hpack_parser.on_header_user_data = transport_parsing; - transport_parsing->hpack_parser.is_boundary = is_eoh; - transport_parsing->hpack_parser.is_eof = - (uint8_t)(is_eoh ? transport_parsing->header_eof : 0); - if (!is_continuation && (transport_parsing->incoming_frame_flags & - GRPC_CHTTP2_FLAG_HAS_PRIORITY)) { - grpc_chttp2_hpack_parser_set_has_priority(&transport_parsing->hpack_parser); - } - return 1; -} - -static int init_window_update_frame_parser( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) { - int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_window_update_parser_begin_frame( - &transport_parsing->simple.window_update, - transport_parsing->incoming_frame_size, - transport_parsing->incoming_frame_flags); - if (transport_parsing->incoming_stream_id) { - transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream( - transport_parsing, transport_parsing->incoming_stream_id); - } - transport_parsing->parser = grpc_chttp2_window_update_parser_parse; - transport_parsing->parser_data = &transport_parsing->simple.window_update; - return ok; -} - -static int init_ping_parser(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport_parsing *transport_parsing) { - int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_ping_parser_begin_frame( - &transport_parsing->simple.ping, - transport_parsing->incoming_frame_size, - transport_parsing->incoming_frame_flags); - transport_parsing->parser = grpc_chttp2_ping_parser_parse; - transport_parsing->parser_data = &transport_parsing->simple.ping; - return ok; -} - -static int init_rst_stream_parser( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) { - int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_rst_stream_parser_begin_frame( - &transport_parsing->simple.rst_stream, - transport_parsing->incoming_frame_size, - transport_parsing->incoming_frame_flags); - transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream( - transport_parsing, transport_parsing->incoming_stream_id); - if (!transport_parsing->incoming_stream) { - return init_skip_frame_parser(exec_ctx, transport_parsing, 0); - } - transport_parsing->parser = grpc_chttp2_rst_stream_parser_parse; - transport_parsing->parser_data = &transport_parsing->simple.rst_stream; - return ok; -} - -static int init_goaway_parser( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) { - int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_goaway_parser_begin_frame( - &transport_parsing->goaway_parser, - transport_parsing->incoming_frame_size, - transport_parsing->incoming_frame_flags); - transport_parsing->parser = grpc_chttp2_goaway_parser_parse; - transport_parsing->parser_data = &transport_parsing->goaway_parser; - return ok; -} - -static int init_settings_frame_parser( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) { - int ok; - - if (transport_parsing->incoming_stream_id != 0) { - gpr_log(GPR_ERROR, "settings frame received for grpc_chttp2_stream %d", - transport_parsing->incoming_stream_id); - return 0; - } - - ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_settings_parser_begin_frame( - &transport_parsing->simple.settings, - transport_parsing->incoming_frame_size, - transport_parsing->incoming_frame_flags, - transport_parsing->settings); - if (!ok) { - return 0; - } - 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; - return ok; -} - -/* -static int is_window_update_legal(int64_t window_update, int64_t window) { - return window + window_update < MAX_WINDOW; -} -*/ - -static int parse_frame_slice(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport_parsing *transport_parsing, - gpr_slice slice, int is_last) { - grpc_chttp2_stream_parsing *stream_parsing = - transport_parsing->incoming_stream; - switch (transport_parsing->parser(exec_ctx, transport_parsing->parser_data, - transport_parsing, stream_parsing, slice, - is_last)) { - case GRPC_CHTTP2_PARSE_OK: - if (stream_parsing) { - grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, - stream_parsing); - } - return 1; - case GRPC_CHTTP2_STREAM_ERROR: - grpc_chttp2_parsing_become_skip_parser(exec_ctx, transport_parsing); - if (stream_parsing) { - stream_parsing->saw_rst_stream = 1; - stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR; - gpr_slice_buffer_add( - &transport_parsing->qbuf, - grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id, - GRPC_CHTTP2_PROTOCOL_ERROR)); - } - return 1; - case GRPC_CHTTP2_CONNECTION_ERROR: - return 0; - } - GPR_UNREACHABLE_CODE(return 0); -} diff --git a/src/core/lib/transport/chttp2/status_conversion.c b/src/core/lib/transport/chttp2/status_conversion.c deleted file mode 100644 index 73dd63e720..0000000000 --- a/src/core/lib/transport/chttp2/status_conversion.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/lib/transport/chttp2/status_conversion.h" - -int grpc_chttp2_grpc_status_to_http2_error(grpc_status_code status) { - switch (status) { - case GRPC_STATUS_OK: - return GRPC_CHTTP2_NO_ERROR; - case GRPC_STATUS_CANCELLED: - return GRPC_CHTTP2_CANCEL; - case GRPC_STATUS_RESOURCE_EXHAUSTED: - return GRPC_CHTTP2_ENHANCE_YOUR_CALM; - case GRPC_STATUS_PERMISSION_DENIED: - return GRPC_CHTTP2_INADEQUATE_SECURITY; - case GRPC_STATUS_UNAVAILABLE: - return GRPC_CHTTP2_REFUSED_STREAM; - default: - return GRPC_CHTTP2_INTERNAL_ERROR; - } -} - -grpc_status_code grpc_chttp2_http2_error_to_grpc_status( - grpc_chttp2_error_code error) { - switch (error) { - case GRPC_CHTTP2_NO_ERROR: - /* should never be received */ - return GRPC_STATUS_INTERNAL; - case GRPC_CHTTP2_CANCEL: - return GRPC_STATUS_CANCELLED; - case GRPC_CHTTP2_ENHANCE_YOUR_CALM: - return GRPC_STATUS_RESOURCE_EXHAUSTED; - case GRPC_CHTTP2_INADEQUATE_SECURITY: - return GRPC_STATUS_PERMISSION_DENIED; - case GRPC_CHTTP2_REFUSED_STREAM: - return GRPC_STATUS_UNAVAILABLE; - default: - return GRPC_STATUS_INTERNAL; - } -} - -grpc_status_code grpc_chttp2_http2_status_to_grpc_status(int status) { - switch (status) { - /* these HTTP2 status codes are called out explicitly in status.proto */ - case 200: - return GRPC_STATUS_OK; - case 400: - return GRPC_STATUS_INVALID_ARGUMENT; - case 401: - return GRPC_STATUS_UNAUTHENTICATED; - case 403: - return GRPC_STATUS_PERMISSION_DENIED; - case 404: - return GRPC_STATUS_NOT_FOUND; - case 409: - return GRPC_STATUS_ABORTED; - case 412: - return GRPC_STATUS_FAILED_PRECONDITION; - case 429: - return GRPC_STATUS_RESOURCE_EXHAUSTED; - case 499: - return GRPC_STATUS_CANCELLED; - case 500: - return GRPC_STATUS_UNKNOWN; - case 501: - return GRPC_STATUS_UNIMPLEMENTED; - case 503: - return GRPC_STATUS_UNAVAILABLE; - case 504: - return GRPC_STATUS_DEADLINE_EXCEEDED; - /* everything else is unknown */ - default: - return GRPC_STATUS_UNKNOWN; - } -} - -int grpc_chttp2_grpc_status_to_http2_status(grpc_status_code status) { - return 200; -} diff --git a/src/core/lib/transport/chttp2/status_conversion.h b/src/core/lib/transport/chttp2/status_conversion.h deleted file mode 100644 index 241417d32e..0000000000 --- a/src/core/lib/transport/chttp2/status_conversion.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_TRANSPORT_CHTTP2_STATUS_CONVERSION_H -#define GRPC_CORE_LIB_TRANSPORT_CHTTP2_STATUS_CONVERSION_H - -#include <grpc/grpc.h> -#include "src/core/lib/transport/chttp2/http2_errors.h" - -/* Conversion of grpc status codes to http2 error codes (for RST_STREAM) */ -grpc_chttp2_error_code grpc_chttp2_grpc_status_to_http2_error( - grpc_status_code status); -grpc_status_code grpc_chttp2_http2_error_to_grpc_status( - grpc_chttp2_error_code error); - -/* Conversion of HTTP status codes (:status) to grpc status codes */ -grpc_status_code grpc_chttp2_http2_status_to_grpc_status(int status); -int grpc_chttp2_grpc_status_to_http2_status(grpc_status_code status); - -#endif /* GRPC_CORE_LIB_TRANSPORT_CHTTP2_STATUS_CONVERSION_H */ diff --git a/src/core/lib/transport/chttp2/stream_lists.c b/src/core/lib/transport/chttp2/stream_lists.c deleted file mode 100644 index b51a041dc7..0000000000 --- a/src/core/lib/transport/chttp2/stream_lists.c +++ /dev/null @@ -1,442 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/lib/transport/chttp2/internal.h" - -#include <grpc/support/log.h> - -#define TRANSPORT_FROM_GLOBAL(tg) \ - ((grpc_chttp2_transport *)((char *)(tg)-offsetof(grpc_chttp2_transport, \ - global))) - -#define STREAM_FROM_GLOBAL(sg) \ - ((grpc_chttp2_stream *)((char *)(sg)-offsetof(grpc_chttp2_stream, global))) - -#define TRANSPORT_FROM_WRITING(tw) \ - ((grpc_chttp2_transport *)((char *)(tw)-offsetof(grpc_chttp2_transport, \ - writing))) - -#define STREAM_FROM_WRITING(sw) \ - ((grpc_chttp2_stream *)((char *)(sw)-offsetof(grpc_chttp2_stream, writing))) - -#define TRANSPORT_FROM_PARSING(tp) \ - ((grpc_chttp2_transport *)((char *)(tp)-offsetof(grpc_chttp2_transport, \ - parsing))) - -#define STREAM_FROM_PARSING(sp) \ - ((grpc_chttp2_stream *)((char *)(sp)-offsetof(grpc_chttp2_stream, parsing))) - -/* core list management */ - -static int stream_list_empty(grpc_chttp2_transport *t, - grpc_chttp2_stream_list_id id) { - return t->lists[id].head == NULL; -} - -static int stream_list_pop(grpc_chttp2_transport *t, - grpc_chttp2_stream **stream, - grpc_chttp2_stream_list_id id) { - grpc_chttp2_stream *s = t->lists[id].head; - if (s) { - grpc_chttp2_stream *new_head = s->links[id].next; - GPR_ASSERT(s->included[id]); - if (new_head) { - t->lists[id].head = new_head; - new_head->links[id].prev = NULL; - } else { - t->lists[id].head = NULL; - t->lists[id].tail = NULL; - } - s->included[id] = 0; - } - *stream = s; - return s != 0; -} - -static void stream_list_remove(grpc_chttp2_transport *t, grpc_chttp2_stream *s, - grpc_chttp2_stream_list_id id) { - GPR_ASSERT(s->included[id]); - s->included[id] = 0; - if (s->links[id].prev) { - s->links[id].prev->links[id].next = s->links[id].next; - } else { - GPR_ASSERT(t->lists[id].head == s); - t->lists[id].head = s->links[id].next; - } - if (s->links[id].next) { - s->links[id].next->links[id].prev = s->links[id].prev; - } else { - t->lists[id].tail = s->links[id].prev; - } -} - -static bool stream_list_maybe_remove(grpc_chttp2_transport *t, - grpc_chttp2_stream *s, - grpc_chttp2_stream_list_id id) { - if (s->included[id]) { - stream_list_remove(t, s, id); - return true; - } else { - return false; - } -} - -static void stream_list_add_tail(grpc_chttp2_transport *t, - grpc_chttp2_stream *s, - grpc_chttp2_stream_list_id id) { - grpc_chttp2_stream *old_tail; - GPR_ASSERT(!s->included[id]); - old_tail = t->lists[id].tail; - s->links[id].next = NULL; - s->links[id].prev = old_tail; - if (old_tail) { - old_tail->links[id].next = s; - } else { - t->lists[id].head = s; - } - t->lists[id].tail = s; - s->included[id] = 1; -} - -static bool stream_list_add(grpc_chttp2_transport *t, grpc_chttp2_stream *s, - grpc_chttp2_stream_list_id id) { - if (s->included[id]) { - return false; - } - stream_list_add_tail(t, s, id); - return true; -} - -/* wrappers for specializations */ - -bool grpc_chttp2_list_add_writable_stream( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global) { - GPR_ASSERT(stream_global->id != 0); - return stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global), - STREAM_FROM_GLOBAL(stream_global), - GRPC_CHTTP2_LIST_WRITABLE); -} - -int grpc_chttp2_list_pop_writable_stream( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_transport_writing *transport_writing, - grpc_chttp2_stream_global **stream_global, - grpc_chttp2_stream_writing **stream_writing) { - grpc_chttp2_stream *stream; - int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream, - GRPC_CHTTP2_LIST_WRITABLE); - if (r != 0) { - *stream_global = &stream->global; - *stream_writing = &stream->writing; - } - return r; -} - -bool grpc_chttp2_list_remove_writable_stream( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global) { - return stream_list_maybe_remove(TRANSPORT_FROM_GLOBAL(transport_global), - STREAM_FROM_GLOBAL(stream_global), - GRPC_CHTTP2_LIST_WRITABLE); -} - -void grpc_chttp2_list_add_writing_stream( - grpc_chttp2_transport_writing *transport_writing, - grpc_chttp2_stream_writing *stream_writing) { - GPR_ASSERT(stream_list_add(TRANSPORT_FROM_WRITING(transport_writing), - STREAM_FROM_WRITING(stream_writing), - GRPC_CHTTP2_LIST_WRITING)); -} - -int grpc_chttp2_list_have_writing_streams( - grpc_chttp2_transport_writing *transport_writing) { - return !stream_list_empty(TRANSPORT_FROM_WRITING(transport_writing), - GRPC_CHTTP2_LIST_WRITING); -} - -int grpc_chttp2_list_pop_writing_stream( - grpc_chttp2_transport_writing *transport_writing, - grpc_chttp2_stream_writing **stream_writing) { - grpc_chttp2_stream *stream; - int r = stream_list_pop(TRANSPORT_FROM_WRITING(transport_writing), &stream, - GRPC_CHTTP2_LIST_WRITING); - if (r != 0) { - *stream_writing = &stream->writing; - } - return r; -} - -void grpc_chttp2_list_add_written_stream( - grpc_chttp2_transport_writing *transport_writing, - grpc_chttp2_stream_writing *stream_writing) { - stream_list_add(TRANSPORT_FROM_WRITING(transport_writing), - STREAM_FROM_WRITING(stream_writing), - GRPC_CHTTP2_LIST_WRITTEN); -} - -int grpc_chttp2_list_pop_written_stream( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_transport_writing *transport_writing, - grpc_chttp2_stream_global **stream_global, - grpc_chttp2_stream_writing **stream_writing) { - grpc_chttp2_stream *stream; - int r = stream_list_pop(TRANSPORT_FROM_WRITING(transport_writing), &stream, - GRPC_CHTTP2_LIST_WRITTEN); - if (r != 0) { - *stream_global = &stream->global; - *stream_writing = &stream->writing; - } - return r; -} - -void grpc_chttp2_list_add_unannounced_incoming_window_available( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global) { - GPR_ASSERT(stream_global->id != 0); - stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global), - STREAM_FROM_GLOBAL(stream_global), - GRPC_CHTTP2_LIST_UNANNOUNCED_INCOMING_WINDOW_AVAILABLE); -} - -void grpc_chttp2_list_remove_unannounced_incoming_window_available( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global) { - stream_list_maybe_remove( - TRANSPORT_FROM_GLOBAL(transport_global), - STREAM_FROM_GLOBAL(stream_global), - GRPC_CHTTP2_LIST_UNANNOUNCED_INCOMING_WINDOW_AVAILABLE); -} - -int grpc_chttp2_list_pop_unannounced_incoming_window_available( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_global **stream_global, - grpc_chttp2_stream_parsing **stream_parsing) { - grpc_chttp2_stream *stream; - int r = - stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream, - GRPC_CHTTP2_LIST_UNANNOUNCED_INCOMING_WINDOW_AVAILABLE); - if (r != 0) { - *stream_global = &stream->global; - *stream_parsing = &stream->parsing; - } - return r; -} - -void grpc_chttp2_list_add_parsing_seen_stream( - grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_parsing *stream_parsing) { - stream_list_add(TRANSPORT_FROM_PARSING(transport_parsing), - STREAM_FROM_PARSING(stream_parsing), - GRPC_CHTTP2_LIST_PARSING_SEEN); -} - -int grpc_chttp2_list_pop_parsing_seen_stream( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_global **stream_global, - grpc_chttp2_stream_parsing **stream_parsing) { - grpc_chttp2_stream *stream; - int r = stream_list_pop(TRANSPORT_FROM_PARSING(transport_parsing), &stream, - GRPC_CHTTP2_LIST_PARSING_SEEN); - if (r != 0) { - *stream_global = &stream->global; - *stream_parsing = &stream->parsing; - } - return r; -} - -void grpc_chttp2_list_add_waiting_for_concurrency( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global) { - stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global), - STREAM_FROM_GLOBAL(stream_global), - GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY); -} - -int grpc_chttp2_list_pop_waiting_for_concurrency( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global **stream_global) { - grpc_chttp2_stream *stream; - int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream, - GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY); - if (r != 0) { - *stream_global = &stream->global; - } - return r; -} - -void grpc_chttp2_list_add_check_read_ops( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global) { - stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global), - STREAM_FROM_GLOBAL(stream_global), - GRPC_CHTTP2_LIST_CHECK_READ_OPS); -} - -int grpc_chttp2_list_pop_check_read_ops( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global **stream_global) { - grpc_chttp2_stream *stream; - int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream, - GRPC_CHTTP2_LIST_CHECK_READ_OPS); - if (r != 0) { - *stream_global = &stream->global; - } - return r; -} - -void grpc_chttp2_list_add_writing_stalled_by_transport( - grpc_chttp2_transport_writing *transport_writing, - grpc_chttp2_stream_writing *stream_writing) { - grpc_chttp2_stream *stream = STREAM_FROM_WRITING(stream_writing); - if (!stream->included[GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT]) { - GRPC_CHTTP2_STREAM_REF(&stream->global, "chttp2_writing_stalled"); - } - stream_list_add(TRANSPORT_FROM_WRITING(transport_writing), stream, - GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT); -} - -void grpc_chttp2_list_flush_writing_stalled_by_transport( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing, - bool is_window_available) { - grpc_chttp2_stream *stream; - grpc_chttp2_transport *transport = TRANSPORT_FROM_WRITING(transport_writing); - while (stream_list_pop(transport, &stream, - GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT)) { - if (is_window_available) { - grpc_chttp2_become_writable(&transport->global, &stream->global); - } else { - grpc_chttp2_list_add_stalled_by_transport(transport_writing, - &stream->writing); - } - GRPC_CHTTP2_STREAM_UNREF(exec_ctx, &stream->global, - "chttp2_writing_stalled"); - } -} - -void grpc_chttp2_list_add_stalled_by_transport( - grpc_chttp2_transport_writing *transport_writing, - grpc_chttp2_stream_writing *stream_writing) { - stream_list_add(TRANSPORT_FROM_WRITING(transport_writing), - STREAM_FROM_WRITING(stream_writing), - GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT); -} - -int grpc_chttp2_list_pop_stalled_by_transport( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global **stream_global) { - grpc_chttp2_stream *stream; - int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream, - GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT); - if (r != 0) { - *stream_global = &stream->global; - } - return r; -} - -void grpc_chttp2_list_remove_stalled_by_transport( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global) { - stream_list_maybe_remove(TRANSPORT_FROM_GLOBAL(transport_global), - STREAM_FROM_GLOBAL(stream_global), - GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT); -} - -void grpc_chttp2_list_add_closed_waiting_for_parsing( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global) { - stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global), - STREAM_FROM_GLOBAL(stream_global), - GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_PARSING); -} - -int grpc_chttp2_list_pop_closed_waiting_for_parsing( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global **stream_global) { - grpc_chttp2_stream *stream; - int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream, - GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_PARSING); - if (r != 0) { - *stream_global = &stream->global; - } - return r; -} - -void grpc_chttp2_list_add_closed_waiting_for_writing( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global) { - stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global), - STREAM_FROM_GLOBAL(stream_global), - GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_WRITING); -} - -int grpc_chttp2_list_pop_closed_waiting_for_writing( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global **stream_global) { - grpc_chttp2_stream *stream; - int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream, - GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_WRITING); - if (r != 0) { - *stream_global = &stream->global; - } - return r; -} - -void grpc_chttp2_register_stream(grpc_chttp2_transport *t, - grpc_chttp2_stream *s) { - stream_list_add_tail(t, s, GRPC_CHTTP2_LIST_ALL_STREAMS); -} - -int grpc_chttp2_unregister_stream(grpc_chttp2_transport *t, - grpc_chttp2_stream *s) { - stream_list_maybe_remove(t, s, GRPC_CHTTP2_LIST_ALL_STREAMS); - return stream_list_empty(t, GRPC_CHTTP2_LIST_ALL_STREAMS); -} - -int grpc_chttp2_has_streams(grpc_chttp2_transport *t) { - return !stream_list_empty(t, GRPC_CHTTP2_LIST_ALL_STREAMS); -} - -void grpc_chttp2_for_all_streams( - grpc_chttp2_transport_global *transport_global, void *user_data, - void (*cb)(grpc_chttp2_transport_global *transport_global, void *user_data, - grpc_chttp2_stream_global *stream_global)) { - grpc_chttp2_stream *s; - grpc_chttp2_transport *t = TRANSPORT_FROM_GLOBAL(transport_global); - for (s = t->lists[GRPC_CHTTP2_LIST_ALL_STREAMS].head; s != NULL; - s = s->links[GRPC_CHTTP2_LIST_ALL_STREAMS].next) { - cb(transport_global, user_data, &s->global); - } -} diff --git a/src/core/lib/transport/chttp2/stream_map.c b/src/core/lib/transport/chttp2/stream_map.c deleted file mode 100644 index dbbbe783bf..0000000000 --- a/src/core/lib/transport/chttp2/stream_map.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/lib/transport/chttp2/stream_map.h" - -#include <string.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/useful.h> - -void grpc_chttp2_stream_map_init(grpc_chttp2_stream_map *map, - size_t initial_capacity) { - GPR_ASSERT(initial_capacity > 1); - map->keys = gpr_malloc(sizeof(uint32_t) * initial_capacity); - map->values = gpr_malloc(sizeof(void *) * initial_capacity); - map->count = 0; - map->free = 0; - map->capacity = initial_capacity; -} - -void grpc_chttp2_stream_map_destroy(grpc_chttp2_stream_map *map) { - gpr_free(map->keys); - gpr_free(map->values); -} - -static size_t compact(uint32_t *keys, void **values, size_t count) { - size_t i, out; - - for (i = 0, out = 0; i < count; i++) { - if (values[i]) { - keys[out] = keys[i]; - values[out] = values[i]; - out++; - } - } - - return out; -} - -void grpc_chttp2_stream_map_add(grpc_chttp2_stream_map *map, uint32_t key, - void *value) { - size_t count = map->count; - size_t capacity = map->capacity; - uint32_t *keys = map->keys; - void **values = map->values; - - GPR_ASSERT(count == 0 || keys[count - 1] < key); - GPR_ASSERT(value); - - if (count == capacity) { - if (map->free > capacity / 4) { - count = compact(keys, values, count); - map->free = 0; - } else { - /* resize when less than 25% of the table is free, because compaction - won't help much */ - map->capacity = capacity = 3 * capacity / 2; - map->keys = keys = gpr_realloc(keys, capacity * sizeof(uint32_t)); - map->values = values = gpr_realloc(values, capacity * sizeof(void *)); - } - } - - keys[count] = key; - values[count] = value; - map->count = count + 1; -} - -void grpc_chttp2_stream_map_move_into(grpc_chttp2_stream_map *src, - grpc_chttp2_stream_map *dst) { - /* if src is empty we dont need to do anything */ - if (src->count == src->free) { - return; - } - /* if dst is empty we simply need to swap */ - if (dst->count == dst->free) { - GPR_SWAP(grpc_chttp2_stream_map, *src, *dst); - return; - } - /* the first element of src must be greater than the last of dst... - * however the maps may need compacting for this property to hold */ - if (src->keys[0] <= dst->keys[dst->count - 1]) { - src->count = compact(src->keys, src->values, src->count); - src->free = 0; - dst->count = compact(dst->keys, dst->values, dst->count); - dst->free = 0; - } - GPR_ASSERT(src->keys[0] > dst->keys[dst->count - 1]); - /* if dst doesn't have capacity, resize */ - if (dst->count + src->count > dst->capacity) { - dst->capacity = GPR_MAX(dst->capacity * 3 / 2, dst->count + src->count); - dst->keys = gpr_realloc(dst->keys, dst->capacity * sizeof(uint32_t)); - dst->values = gpr_realloc(dst->values, dst->capacity * sizeof(void *)); - } - memcpy(dst->keys + dst->count, src->keys, src->count * sizeof(uint32_t)); - memcpy(dst->values + dst->count, src->values, src->count * sizeof(void *)); - dst->count += src->count; - dst->free += src->free; - src->count = 0; - src->free = 0; -} - -static void **find(grpc_chttp2_stream_map *map, uint32_t key) { - size_t min_idx = 0; - size_t max_idx = map->count; - size_t mid_idx; - uint32_t *keys = map->keys; - void **values = map->values; - uint32_t mid_key; - - if (max_idx == 0) return NULL; - - while (min_idx < max_idx) { - /* find the midpoint, avoiding overflow */ - mid_idx = min_idx + ((max_idx - min_idx) / 2); - mid_key = keys[mid_idx]; - - if (mid_key < key) { - min_idx = mid_idx + 1; - } else if (mid_key > key) { - max_idx = mid_idx; - } else /* mid_key == key */ - { - return &values[mid_idx]; - } - } - - return NULL; -} - -void *grpc_chttp2_stream_map_delete(grpc_chttp2_stream_map *map, uint32_t key) { - void **pvalue = find(map, key); - void *out = NULL; - if (pvalue != NULL) { - out = *pvalue; - *pvalue = NULL; - map->free += (out != NULL); - /* recognize complete emptyness and ensure we can skip - * defragmentation later */ - if (map->free == map->count) { - map->free = map->count = 0; - } - } - return out; -} - -void *grpc_chttp2_stream_map_find(grpc_chttp2_stream_map *map, uint32_t key) { - void **pvalue = find(map, key); - return pvalue != NULL ? *pvalue : NULL; -} - -size_t grpc_chttp2_stream_map_size(grpc_chttp2_stream_map *map) { - return map->count - map->free; -} - -void grpc_chttp2_stream_map_for_each(grpc_chttp2_stream_map *map, - void (*f)(void *user_data, uint32_t key, - void *value), - void *user_data) { - size_t i; - - for (i = 0; i < map->count; i++) { - if (map->values[i]) { - f(user_data, map->keys[i], map->values[i]); - } - } -} diff --git a/src/core/lib/transport/chttp2/stream_map.h b/src/core/lib/transport/chttp2/stream_map.h deleted file mode 100644 index 1c56b18e54..0000000000 --- a/src/core/lib/transport/chttp2/stream_map.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_TRANSPORT_CHTTP2_STREAM_MAP_H -#define GRPC_CORE_LIB_TRANSPORT_CHTTP2_STREAM_MAP_H - -#include <grpc/support/port_platform.h> - -#include <stddef.h> - -/* Data structure to map a uint32_t to a data object (represented by a void*) - - Represented as a sorted array of keys, and a corresponding array of values. - Lookups are performed with binary search. - Adds are restricted to strictly higher keys than previously seen (this is - guaranteed by http2). */ -typedef struct { - uint32_t *keys; - void **values; - size_t count; - size_t free; - size_t capacity; -} grpc_chttp2_stream_map; - -void grpc_chttp2_stream_map_init(grpc_chttp2_stream_map *map, - size_t initial_capacity); -void grpc_chttp2_stream_map_destroy(grpc_chttp2_stream_map *map); - -/* Add a new key: given http2 semantics, new keys must always be greater than - existing keys - this is asserted */ -void grpc_chttp2_stream_map_add(grpc_chttp2_stream_map *map, uint32_t key, - void *value); - -/* Delete an existing key - returns the previous value of the key if it existed, - or NULL otherwise */ -void *grpc_chttp2_stream_map_delete(grpc_chttp2_stream_map *map, uint32_t key); - -/* Move all elements of src into dst */ -void grpc_chttp2_stream_map_move_into(grpc_chttp2_stream_map *src, - grpc_chttp2_stream_map *dst); - -/* Return an existing key, or NULL if it does not exist */ -void *grpc_chttp2_stream_map_find(grpc_chttp2_stream_map *map, uint32_t key); - -/* How many (populated) entries are in the stream map? */ -size_t grpc_chttp2_stream_map_size(grpc_chttp2_stream_map *map); - -/* Callback on each stream */ -void grpc_chttp2_stream_map_for_each(grpc_chttp2_stream_map *map, - void (*f)(void *user_data, uint32_t key, - void *value), - void *user_data); - -#endif /* GRPC_CORE_LIB_TRANSPORT_CHTTP2_STREAM_MAP_H */ diff --git a/src/core/lib/transport/chttp2/timeout_encoding.c b/src/core/lib/transport/chttp2/timeout_encoding.c deleted file mode 100644 index 0edacaafd3..0000000000 --- a/src/core/lib/transport/chttp2/timeout_encoding.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/lib/transport/chttp2/timeout_encoding.h" - -#include <stdio.h> -#include <string.h> - -#include <grpc/support/port_platform.h> -#include "src/core/lib/support/string.h" - -static int64_t round_up(int64_t x, int64_t divisor) { - return (x / divisor + (x % divisor != 0)) * divisor; -} - -/* round an integer up to the next value with three significant figures */ -static int64_t round_up_to_three_sig_figs(int64_t x) { - if (x < 1000) return x; - if (x < 10000) return round_up(x, 10); - if (x < 100000) return round_up(x, 100); - if (x < 1000000) return round_up(x, 1000); - if (x < 10000000) return round_up(x, 10000); - if (x < 100000000) return round_up(x, 100000); - if (x < 1000000000) return round_up(x, 1000000); - return round_up(x, 10000000); -} - -/* encode our minimum viable timeout value */ -static void enc_tiny(char *buffer) { memcpy(buffer, "1n", 3); } - -static void enc_ext(char *buffer, int64_t value, char ext) { - int n = int64_ttoa(value, buffer); - buffer[n] = ext; - buffer[n + 1] = 0; -} - -static void enc_seconds(char *buffer, int64_t sec) { - if (sec % 3600 == 0) { - enc_ext(buffer, sec / 3600, 'H'); - } else if (sec % 60 == 0) { - enc_ext(buffer, sec / 60, 'M'); - } else { - enc_ext(buffer, sec, 'S'); - } -} - -static void enc_nanos(char *buffer, int64_t x) { - x = round_up_to_three_sig_figs(x); - if (x < 100000) { - if (x % 1000 == 0) { - enc_ext(buffer, x / 1000, 'u'); - } else { - enc_ext(buffer, x, 'n'); - } - } else if (x < 100000000) { - if (x % 1000000 == 0) { - enc_ext(buffer, x / 1000000, 'm'); - } else { - enc_ext(buffer, x / 1000, 'u'); - } - } else if (x < 1000000000) { - enc_ext(buffer, x / 1000000, 'm'); - } else { - /* note that this is only ever called with times of less than one second, - so if we reach here the time must have been rounded up to a whole second - (and no more) */ - memcpy(buffer, "1S", 3); - } -} - -static void enc_micros(char *buffer, int64_t x) { - x = round_up_to_three_sig_figs(x); - if (x < 100000) { - if (x % 1000 == 0) { - enc_ext(buffer, x / 1000, 'm'); - } else { - enc_ext(buffer, x, 'u'); - } - } else if (x < 100000000) { - if (x % 1000000 == 0) { - enc_ext(buffer, x / 1000000, 'S'); - } else { - enc_ext(buffer, x / 1000, 'm'); - } - } else { - enc_ext(buffer, x / 1000000, 'S'); - } -} - -void grpc_chttp2_encode_timeout(gpr_timespec timeout, char *buffer) { - if (timeout.tv_sec < 0) { - enc_tiny(buffer); - } else if (timeout.tv_sec == 0) { - enc_nanos(buffer, timeout.tv_nsec); - } else if (timeout.tv_sec < 1000 && timeout.tv_nsec != 0) { - enc_micros(buffer, - (int64_t)(timeout.tv_sec * 1000000) + - (timeout.tv_nsec / 1000 + (timeout.tv_nsec % 1000 != 0))); - } else { - enc_seconds(buffer, timeout.tv_sec + (timeout.tv_nsec != 0)); - } -} - -static int is_all_whitespace(const char *p) { - while (*p == ' ') p++; - return *p == 0; -} - -int grpc_chttp2_decode_timeout(const char *buffer, gpr_timespec *timeout) { - int32_t x = 0; - const uint8_t *p = (const uint8_t *)buffer; - int have_digit = 0; - /* skip whitespace */ - for (; *p == ' '; p++) - ; - /* decode numeric part */ - for (; *p >= '0' && *p <= '9'; p++) { - int32_t digit = (int32_t)(*p - (uint8_t)'0'); - have_digit = 1; - /* spec allows max. 8 digits, but we allow values up to 1,000,000,000 */ - if (x >= (100 * 1000 * 1000)) { - if (x != (100 * 1000 * 1000) || digit != 0) { - *timeout = gpr_inf_future(GPR_TIMESPAN); - return 1; - } - } - x = x * 10 + digit; - } - if (!have_digit) return 0; - /* skip whitespace */ - for (; *p == ' '; p++) - ; - /* decode unit specifier */ - switch (*p) { - case 'n': - *timeout = gpr_time_from_nanos(x, GPR_TIMESPAN); - break; - case 'u': - *timeout = gpr_time_from_micros(x, GPR_TIMESPAN); - break; - case 'm': - *timeout = gpr_time_from_millis(x, GPR_TIMESPAN); - break; - case 'S': - *timeout = gpr_time_from_seconds(x, GPR_TIMESPAN); - break; - case 'M': - *timeout = gpr_time_from_minutes(x, GPR_TIMESPAN); - break; - case 'H': - *timeout = gpr_time_from_hours(x, GPR_TIMESPAN); - break; - default: - return 0; - } - p++; - return is_all_whitespace((const char *)p); -} diff --git a/src/core/lib/transport/chttp2/timeout_encoding.h b/src/core/lib/transport/chttp2/timeout_encoding.h deleted file mode 100644 index 731beb5a37..0000000000 --- a/src/core/lib/transport/chttp2/timeout_encoding.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_TRANSPORT_CHTTP2_TIMEOUT_ENCODING_H -#define GRPC_CORE_LIB_TRANSPORT_CHTTP2_TIMEOUT_ENCODING_H - -#include <grpc/support/time.h> -#include "src/core/lib/support/string.h" - -#define GRPC_CHTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE (GPR_LTOA_MIN_BUFSIZE + 1) - -/* Encode/decode timeouts to the GRPC over HTTP2 format; - encoding may round up arbitrarily */ -void grpc_chttp2_encode_timeout(gpr_timespec timeout, char *buffer); -int grpc_chttp2_decode_timeout(const char *buffer, gpr_timespec *timeout); - -#endif /* GRPC_CORE_LIB_TRANSPORT_CHTTP2_TIMEOUT_ENCODING_H */ diff --git a/src/core/lib/transport/chttp2/varint.c b/src/core/lib/transport/chttp2/varint.c deleted file mode 100644 index 6dfef45362..0000000000 --- a/src/core/lib/transport/chttp2/varint.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/lib/transport/chttp2/varint.h" - -uint32_t grpc_chttp2_hpack_varint_length(uint32_t tail_value) { - if (tail_value < (1 << 7)) { - return 2; - } else if (tail_value < (1 << 14)) { - return 3; - } else if (tail_value < (1 << 21)) { - return 4; - } else if (tail_value < (1 << 28)) { - return 5; - } else { - return 6; - } -} - -void grpc_chttp2_hpack_write_varint_tail(uint32_t tail_value, uint8_t* target, - uint32_t tail_length) { - switch (tail_length) { - case 5: - target[4] = (uint8_t)((tail_value >> 28) | 0x80); - case 4: - target[3] = (uint8_t)((tail_value >> 21) | 0x80); - case 3: - target[2] = (uint8_t)((tail_value >> 14) | 0x80); - case 2: - target[1] = (uint8_t)((tail_value >> 7) | 0x80); - case 1: - target[0] = (uint8_t)((tail_value) | 0x80); - } - target[tail_length - 1] &= 0x7f; -} diff --git a/src/core/lib/transport/chttp2/varint.h b/src/core/lib/transport/chttp2/varint.h deleted file mode 100644 index e4a0ae3c22..0000000000 --- a/src/core/lib/transport/chttp2/varint.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_TRANSPORT_CHTTP2_VARINT_H -#define GRPC_CORE_LIB_TRANSPORT_CHTTP2_VARINT_H - -#include <grpc/support/port_platform.h> - -/* Helpers for hpack varint encoding */ - -/* length of a value that needs varint tail encoding (it's bigger than can be - bitpacked into the opcode byte) - returned value includes the length of the - opcode byte */ -uint32_t grpc_chttp2_hpack_varint_length(uint32_t tail_value); - -void grpc_chttp2_hpack_write_varint_tail(uint32_t tail_value, uint8_t* target, - uint32_t tail_length); - -/* maximum value that can be bitpacked with the opcode if the opcode has a - prefix - of length prefix_bits */ -#define GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits) \ - ((uint32_t)((1 << (8 - (prefix_bits))) - 1)) - -/* length required to bitpack a value */ -#define GRPC_CHTTP2_VARINT_LENGTH(n, prefix_bits) \ - ((n) < GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits) \ - ? 1u \ - : grpc_chttp2_hpack_varint_length( \ - (n)-GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits))) - -#define GRPC_CHTTP2_WRITE_VARINT(n, prefix_bits, prefix_or, target, length) \ - do { \ - uint8_t* tgt = target; \ - if ((length) == 1u) { \ - (tgt)[0] = (uint8_t)((prefix_or) | (n)); \ - } else { \ - (tgt)[0] = \ - (prefix_or) | (uint8_t)GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits); \ - grpc_chttp2_hpack_write_varint_tail( \ - (n)-GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits), (tgt) + 1, (length)-1); \ - } \ - } while (0) - -#endif /* GRPC_CORE_LIB_TRANSPORT_CHTTP2_VARINT_H */ diff --git a/src/core/lib/transport/chttp2/writing.c b/src/core/lib/transport/chttp2/writing.c deleted file mode 100644 index daea331d31..0000000000 --- a/src/core/lib/transport/chttp2/writing.c +++ /dev/null @@ -1,350 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/lib/transport/chttp2/internal.h" - -#include <limits.h> - -#include <grpc/support/log.h> - -#include "src/core/lib/profiling/timers.h" -#include "src/core/lib/transport/chttp2/http2_errors.h" - -static void finalize_outbuf(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport_writing *transport_writing); - -int grpc_chttp2_unlocking_check_writes( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, - grpc_chttp2_transport_writing *transport_writing, int is_parsing) { - grpc_chttp2_stream_global *stream_global; - grpc_chttp2_stream_writing *stream_writing; - - GPR_TIMER_BEGIN("grpc_chttp2_unlocking_check_writes", 0); - - /* simple writes are queued to qbuf, and flushed here */ - 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 && !is_parsing) { - gpr_slice_buffer_add( - &transport_writing->outbuf, - grpc_chttp2_settings_create( - transport_global->settings[GRPC_SENT_SETTINGS], - transport_global->settings[GRPC_LOCAL_SETTINGS], - transport_global->force_send_settings, GRPC_CHTTP2_NUM_SETTINGS)); - transport_global->force_send_settings = 0; - transport_global->dirtied_local_settings = 0; - transport_global->sent_local_settings = 1; - } - - GRPC_CHTTP2_FLOW_MOVE_TRANSPORT("write", transport_writing, outgoing_window, - transport_global, outgoing_window); - bool is_window_available = transport_writing->outgoing_window > 0; - grpc_chttp2_list_flush_writing_stalled_by_transport( - exec_ctx, transport_writing, is_window_available); - - /* for each grpc_chttp2_stream that's become writable, frame it's data - (according to available window sizes) and add to the output buffer */ - while (grpc_chttp2_list_pop_writable_stream( - transport_global, transport_writing, &stream_global, &stream_writing)) { - bool sent_initial_metadata = stream_writing->sent_initial_metadata; - bool become_writable = false; - - stream_writing->id = stream_global->id; - stream_writing->read_closed = stream_global->read_closed; - - GRPC_CHTTP2_FLOW_MOVE_STREAM("write", transport_writing, stream_writing, - outgoing_window, stream_global, - outgoing_window); - - if (!sent_initial_metadata && stream_global->send_initial_metadata) { - stream_writing->send_initial_metadata = - stream_global->send_initial_metadata; - stream_global->send_initial_metadata = NULL; - become_writable = true; - sent_initial_metadata = true; - } - if (sent_initial_metadata) { - if (stream_global->send_message != NULL) { - gpr_slice hdr = gpr_slice_malloc(5); - uint8_t *p = GPR_SLICE_START_PTR(hdr); - uint32_t len = stream_global->send_message->length; - GPR_ASSERT(stream_writing->send_message == NULL); - p[0] = (stream_global->send_message->flags & - GRPC_WRITE_INTERNAL_COMPRESS) != 0; - p[1] = (uint8_t)(len >> 24); - p[2] = (uint8_t)(len >> 16); - p[3] = (uint8_t)(len >> 8); - p[4] = (uint8_t)(len); - gpr_slice_buffer_add(&stream_writing->flow_controlled_buffer, hdr); - if (stream_global->send_message->length > 0) { - stream_writing->send_message = stream_global->send_message; - } else { - stream_writing->send_message = NULL; - } - stream_writing->stream_fetched = 0; - stream_global->send_message = NULL; - } - if ((stream_writing->send_message != NULL || - stream_writing->flow_controlled_buffer.length > 0) && - stream_writing->outgoing_window > 0) { - if (transport_writing->outgoing_window > 0) { - become_writable = true; - } else { - grpc_chttp2_list_add_stalled_by_transport(transport_writing, - stream_writing); - } - } - if (stream_global->send_trailing_metadata) { - stream_writing->send_trailing_metadata = - stream_global->send_trailing_metadata; - stream_global->send_trailing_metadata = NULL; - become_writable = true; - } - } - - if (!stream_global->read_closed && - stream_global->unannounced_incoming_window_for_writing > 1024) { - GRPC_CHTTP2_FLOW_MOVE_STREAM("write", transport_global, stream_writing, - announce_window, stream_global, - unannounced_incoming_window_for_writing); - become_writable = true; - } - - if (become_writable) { - grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing); - } else { - GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing"); - } - } - - /* if the grpc_chttp2_transport is ready to send a window update, do so here - also; 3/4 is a magic number that will likely get tuned soon */ - if (transport_global->announce_incoming_window > 0) { - uint32_t announced = (uint32_t)GPR_MIN( - transport_global->announce_incoming_window, UINT32_MAX); - GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("write", transport_global, - announce_incoming_window, announced); - gpr_slice_buffer_add(&transport_writing->outbuf, - grpc_chttp2_window_update_create(0, announced)); - } - - GPR_TIMER_END("grpc_chttp2_unlocking_check_writes", 0); - - return transport_writing->outbuf.count > 0 || - grpc_chttp2_list_have_writing_streams(transport_writing); -} - -void grpc_chttp2_perform_writes( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing, - grpc_endpoint *endpoint) { - GPR_ASSERT(transport_writing->outbuf.count > 0 || - grpc_chttp2_list_have_writing_streams(transport_writing)); - - finalize_outbuf(exec_ctx, transport_writing); - - GPR_ASSERT(endpoint); - - if (transport_writing->outbuf.count > 0) { - grpc_endpoint_write(exec_ctx, endpoint, &transport_writing->outbuf, - &transport_writing->done_cb); - } else { - grpc_exec_ctx_enqueue(exec_ctx, &transport_writing->done_cb, true, NULL); - } -} - -static void finalize_outbuf(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport_writing *transport_writing) { - grpc_chttp2_stream_writing *stream_writing; - - GPR_TIMER_BEGIN("finalize_outbuf", 0); - - while ( - grpc_chttp2_list_pop_writing_stream(transport_writing, &stream_writing)) { - uint32_t max_outgoing = - (uint32_t)GPR_MIN(GRPC_CHTTP2_MAX_PAYLOAD_LENGTH, - GPR_MIN(stream_writing->outgoing_window, - transport_writing->outgoing_window)); - /* send initial metadata if it's available */ - if (stream_writing->send_initial_metadata != NULL) { - grpc_chttp2_encode_header( - &transport_writing->hpack_compressor, stream_writing->id, - stream_writing->send_initial_metadata, 0, &transport_writing->outbuf); - stream_writing->send_initial_metadata = NULL; - stream_writing->sent_initial_metadata = 1; - } - /* send any window updates */ - if (stream_writing->announce_window > 0 && - stream_writing->send_initial_metadata == NULL) { - uint32_t announce = stream_writing->announce_window; - gpr_slice_buffer_add( - &transport_writing->outbuf, - grpc_chttp2_window_update_create(stream_writing->id, - stream_writing->announce_window)); - GRPC_CHTTP2_FLOW_DEBIT_STREAM("write", transport_writing, stream_writing, - announce_window, announce); - stream_writing->announce_window = 0; - } - /* fetch any body bytes */ - while (!stream_writing->fetching && stream_writing->send_message && - stream_writing->flow_controlled_buffer.length < max_outgoing && - stream_writing->stream_fetched < - stream_writing->send_message->length) { - if (grpc_byte_stream_next(exec_ctx, stream_writing->send_message, - &stream_writing->fetching_slice, max_outgoing, - &stream_writing->finished_fetch)) { - stream_writing->stream_fetched += - GPR_SLICE_LENGTH(stream_writing->fetching_slice); - if (stream_writing->stream_fetched == - stream_writing->send_message->length) { - stream_writing->send_message = NULL; - } - gpr_slice_buffer_add(&stream_writing->flow_controlled_buffer, - stream_writing->fetching_slice); - } else { - stream_writing->fetching = 1; - } - } - /* send any body bytes */ - if (stream_writing->flow_controlled_buffer.length > 0) { - if (max_outgoing > 0) { - uint32_t send_bytes = (uint32_t)GPR_MIN( - max_outgoing, stream_writing->flow_controlled_buffer.length); - int is_last_data_frame = - stream_writing->send_message == NULL && - send_bytes == stream_writing->flow_controlled_buffer.length; - int is_last_frame = is_last_data_frame && - stream_writing->send_trailing_metadata != NULL && - grpc_metadata_batch_is_empty( - stream_writing->send_trailing_metadata); - grpc_chttp2_encode_data( - stream_writing->id, &stream_writing->flow_controlled_buffer, - send_bytes, is_last_frame, &transport_writing->outbuf); - GRPC_CHTTP2_FLOW_DEBIT_STREAM("write", transport_writing, - stream_writing, outgoing_window, - send_bytes); - GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("write", transport_writing, - outgoing_window, send_bytes); - if (is_last_frame) { - stream_writing->send_trailing_metadata = NULL; - stream_writing->sent_trailing_metadata = 1; - } - if (is_last_data_frame) { - GPR_ASSERT(stream_writing->send_message == NULL); - stream_writing->sent_message = 1; - } - } else if (transport_writing->outgoing_window == 0) { - grpc_chttp2_list_add_writing_stalled_by_transport(transport_writing, - stream_writing); - grpc_chttp2_list_add_written_stream(transport_writing, stream_writing); - } - } - /* send trailing metadata if it's available and we're ready for it */ - if (stream_writing->send_message == NULL && - stream_writing->flow_controlled_buffer.length == 0 && - stream_writing->send_trailing_metadata != NULL) { - if (grpc_metadata_batch_is_empty( - stream_writing->send_trailing_metadata)) { - grpc_chttp2_encode_data(stream_writing->id, - &stream_writing->flow_controlled_buffer, 0, 1, - &transport_writing->outbuf); - } else { - grpc_chttp2_encode_header(&transport_writing->hpack_compressor, - stream_writing->id, - stream_writing->send_trailing_metadata, 1, - &transport_writing->outbuf); - } - if (!transport_writing->is_client && !stream_writing->read_closed) { - gpr_slice_buffer_add(&transport_writing->outbuf, - grpc_chttp2_rst_stream_create( - stream_writing->id, GRPC_CHTTP2_NO_ERROR)); - } - stream_writing->send_trailing_metadata = NULL; - stream_writing->sent_trailing_metadata = 1; - } - /* if there's more to write, then loop, otherwise prepare to finish the - * write */ - if ((stream_writing->flow_controlled_buffer.length > 0 || - (stream_writing->send_message && !stream_writing->fetching)) && - stream_writing->outgoing_window > 0) { - if (transport_writing->outgoing_window > 0) { - grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing); - } else { - grpc_chttp2_list_add_writing_stalled_by_transport(transport_writing, - stream_writing); - grpc_chttp2_list_add_written_stream(transport_writing, stream_writing); - } - } else { - grpc_chttp2_list_add_written_stream(transport_writing, stream_writing); - } - } - - GPR_TIMER_END("finalize_outbuf", 0); -} - -void grpc_chttp2_cleanup_writing( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, - grpc_chttp2_transport_writing *transport_writing) { - grpc_chttp2_stream_writing *stream_writing; - grpc_chttp2_stream_global *stream_global; - - while (grpc_chttp2_list_pop_written_stream( - transport_global, transport_writing, &stream_global, &stream_writing)) { - if (stream_writing->sent_initial_metadata) { - grpc_chttp2_complete_closure_step( - exec_ctx, &stream_global->send_initial_metadata_finished, 1); - } - if (stream_writing->sent_message) { - GPR_ASSERT(stream_writing->send_message == NULL); - grpc_chttp2_complete_closure_step( - exec_ctx, &stream_global->send_message_finished, 1); - stream_writing->sent_message = 0; - } - if (stream_writing->sent_trailing_metadata) { - grpc_chttp2_complete_closure_step( - exec_ctx, &stream_global->send_trailing_metadata_finished, 1); - } - if (stream_writing->sent_trailing_metadata) { - grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, - !transport_global->is_client, 1); - } - GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing"); - } - gpr_slice_buffer_reset_and_unref(&transport_writing->outbuf); -} diff --git a/src/core/lib/transport/chttp2_transport.c b/src/core/lib/transport/chttp2_transport.c deleted file mode 100644 index 7fed3d8b47..0000000000 --- a/src/core/lib/transport/chttp2_transport.c +++ /dev/null @@ -1,1785 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/lib/transport/chttp2_transport.h" - -#include <math.h> -#include <stdio.h> -#include <string.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/slice_buffer.h> -#include <grpc/support/string_util.h> -#include <grpc/support/useful.h> - -#include "src/core/lib/profiling/timers.h" -#include "src/core/lib/support/string.h" -#include "src/core/lib/transport/chttp2/http2_errors.h" -#include "src/core/lib/transport/chttp2/internal.h" -#include "src/core/lib/transport/chttp2/status_conversion.h" -#include "src/core/lib/transport/chttp2/timeout_encoding.h" -#include "src/core/lib/transport/static_metadata.h" -#include "src/core/lib/transport/transport_impl.h" - -#define DEFAULT_WINDOW 65535 -#define DEFAULT_CONNECTION_WINDOW_TARGET (1024 * 1024) -#define MAX_WINDOW 0x7fffffffu - -#define MAX_CLIENT_STREAM_ID 0x7fffffffu - -int grpc_http_trace = 0; -int grpc_flowctl_trace = 0; - -#define TRANSPORT_FROM_WRITING(tw) \ - ((grpc_chttp2_transport *)((char *)(tw)-offsetof(grpc_chttp2_transport, \ - writing))) - -#define TRANSPORT_FROM_PARSING(tw) \ - ((grpc_chttp2_transport *)((char *)(tw)-offsetof(grpc_chttp2_transport, \ - parsing))) - -#define TRANSPORT_FROM_GLOBAL(tg) \ - ((grpc_chttp2_transport *)((char *)(tg)-offsetof(grpc_chttp2_transport, \ - global))) - -#define STREAM_FROM_GLOBAL(sg) \ - ((grpc_chttp2_stream *)((char *)(sg)-offsetof(grpc_chttp2_stream, global))) - -#define STREAM_FROM_PARSING(sg) \ - ((grpc_chttp2_stream *)((char *)(sg)-offsetof(grpc_chttp2_stream, parsing))) - -static const grpc_transport_vtable vtable; - -static void lock(grpc_chttp2_transport *t); -static void unlock(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t); - -/* forward declarations of various callbacks that we'll build closures around */ -static void writing_action(grpc_exec_ctx *exec_ctx, void *t, - bool iomgr_success_ignored); - -/** Set a transport level setting, and push it to our peer */ -static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id, - uint32_t value); - -/** Endpoint callback to process incoming data */ -static void recv_data(grpc_exec_ctx *exec_ctx, void *tp, bool success); - -/** Start disconnection chain */ -static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t); - -/** Perform a transport_op */ -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); - -/** Cancel a stream: coming from the transport API */ -static void cancel_from_api(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global, - grpc_status_code status); - -static void close_from_api(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global, - grpc_status_code status, - gpr_slice *optional_message); - -/** Add endpoint from this transport to pollset */ -static void add_to_pollset_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_pollset *pollset); -static void add_to_pollset_set_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_pollset_set *pollset_set); - -/** Start new streams that have been created if we can */ -static void maybe_start_some_streams( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global); - -static void connectivity_state_set( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, - grpc_connectivity_state state, const char *reason); - -static void check_read_ops(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport_global *transport_global); - -static void incoming_byte_stream_update_flow_control( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global, size_t max_size_hint, - size_t have_already); - -static void fail_pending_writes(grpc_exec_ctx *exec_ctx, - grpc_chttp2_stream_global *stream_global); - -/******************************************************************************* - * CONSTRUCTION/DESTRUCTION/REFCOUNTING - */ - -static void destruct_transport(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t) { - size_t i; - - gpr_mu_lock(&t->mu); - - GPR_ASSERT(t->ep == NULL); - - gpr_slice_buffer_destroy(&t->global.qbuf); - - gpr_slice_buffer_destroy(&t->writing.outbuf); - grpc_chttp2_hpack_compressor_destroy(&t->writing.hpack_compressor); - - gpr_slice_buffer_destroy(&t->parsing.qbuf); - gpr_slice_buffer_destroy(&t->read_buffer); - grpc_chttp2_hpack_parser_destroy(&t->parsing.hpack_parser); - grpc_chttp2_goaway_parser_destroy(&t->parsing.goaway_parser); - - for (i = 0; i < STREAM_LIST_COUNT; i++) { - GPR_ASSERT(t->lists[i].head == NULL); - GPR_ASSERT(t->lists[i].tail == NULL); - } - - GPR_ASSERT(grpc_chttp2_stream_map_size(&t->parsing_stream_map) == 0); - GPR_ASSERT(grpc_chttp2_stream_map_size(&t->new_stream_map) == 0); - - grpc_chttp2_stream_map_destroy(&t->parsing_stream_map); - grpc_chttp2_stream_map_destroy(&t->new_stream_map); - grpc_connectivity_state_destroy(exec_ctx, &t->channel_callback.state_tracker); - - gpr_mu_unlock(&t->mu); - gpr_mu_destroy(&t->mu); - - /* callback remaining pings: they're not allowed to call into the transpot, - and maybe they hold resources that need to be freed */ - while (t->global.pings.next != &t->global.pings) { - grpc_chttp2_outstanding_ping *ping = t->global.pings.next; - grpc_exec_ctx_enqueue(exec_ctx, ping->on_recv, false, NULL); - ping->next->prev = ping->prev; - ping->prev->next = ping->next; - gpr_free(ping); - } - - gpr_free(t->peer_string); - gpr_free(t); -} - -#ifdef REFCOUNTING_DEBUG -#define REF_TRANSPORT(t, r) ref_transport(t, r, __FILE__, __LINE__) -#define UNREF_TRANSPORT(cl, t, r) unref_transport(cl, t, r, __FILE__, __LINE__) -static void unref_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, - const char *reason, const char *file, int line) { - gpr_log(GPR_DEBUG, "chttp2:unref:%p %d->%d %s [%s:%d]", t, t->refs.count, - t->refs.count - 1, reason, file, line); - if (!gpr_unref(&t->refs)) return; - destruct_transport(exec_ctx, t); -} - -static void ref_transport(grpc_chttp2_transport *t, const char *reason, - const char *file, int line) { - gpr_log(GPR_DEBUG, "chttp2: ref:%p %d->%d %s [%s:%d]", t, t->refs.count, - t->refs.count + 1, reason, file, line); - gpr_ref(&t->refs); -} -#else -#define REF_TRANSPORT(t, r) ref_transport(t) -#define UNREF_TRANSPORT(cl, t, r) unref_transport(cl, t) -static void unref_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { - if (!gpr_unref(&t->refs)) return; - destruct_transport(exec_ctx, t); -} - -static void ref_transport(grpc_chttp2_transport *t) { gpr_ref(&t->refs); } -#endif - -static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, - const grpc_channel_args *channel_args, - grpc_endpoint *ep, uint8_t is_client) { - size_t i; - int j; - - GPR_ASSERT(strlen(GRPC_CHTTP2_CLIENT_CONNECT_STRING) == - GRPC_CHTTP2_CLIENT_CONNECT_STRLEN); - - memset(t, 0, sizeof(*t)); - - t->base.vtable = &vtable; - t->ep = ep; - /* one ref is for destroy, the other for when ep becomes NULL */ - gpr_ref_init(&t->refs, 2); - /* ref is dropped at transport close() */ - gpr_ref_init(&t->shutdown_ep_refs, 1); - gpr_mu_init(&t->mu); - t->peer_string = grpc_endpoint_get_peer(ep); - t->endpoint_reading = 1; - t->global.next_stream_id = is_client ? 1 : 2; - t->global.is_client = is_client; - t->writing.outgoing_window = DEFAULT_WINDOW; - t->parsing.incoming_window = DEFAULT_WINDOW; - t->global.stream_lookahead = DEFAULT_WINDOW; - t->global.connection_window_target = DEFAULT_CONNECTION_WINDOW_TARGET; - t->global.ping_counter = 1; - t->global.pings.next = t->global.pings.prev = &t->global.pings; - t->parsing.is_client = is_client; - t->parsing.deframe_state = - is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0; - t->writing.is_client = is_client; - grpc_connectivity_state_init( - &t->channel_callback.state_tracker, GRPC_CHANNEL_READY, - is_client ? "client_transport" : "server_transport"); - - gpr_slice_buffer_init(&t->global.qbuf); - - gpr_slice_buffer_init(&t->writing.outbuf); - grpc_chttp2_hpack_compressor_init(&t->writing.hpack_compressor); - grpc_closure_init(&t->writing_action, writing_action, t); - - gpr_slice_buffer_init(&t->parsing.qbuf); - grpc_chttp2_goaway_parser_init(&t->parsing.goaway_parser); - grpc_chttp2_hpack_parser_init(&t->parsing.hpack_parser); - - grpc_closure_init(&t->writing.done_cb, grpc_chttp2_terminate_writing, - &t->writing); - grpc_closure_init(&t->recv_data, recv_data, t); - gpr_slice_buffer_init(&t->read_buffer); - - if (is_client) { - gpr_slice_buffer_add( - &t->global.qbuf, - gpr_slice_from_copied_string(GRPC_CHTTP2_CLIENT_CONNECT_STRING)); - } - /* 8 is a random stab in the dark as to a good initial size: it's small enough - that it shouldn't waste memory for infrequently used connections, yet - large enough that the exponential growth should happen nicely when it's - needed. - TODO(ctiller): tune this */ - grpc_chttp2_stream_map_init(&t->parsing_stream_map, 8); - grpc_chttp2_stream_map_init(&t->new_stream_map, 8); - - /* copy in initial settings to all setting sets */ - for (i = 0; i < GRPC_CHTTP2_NUM_SETTINGS; i++) { - t->parsing.settings[i] = grpc_chttp2_settings_parameters[i].default_value; - for (j = 0; j < GRPC_NUM_SETTING_SETS; j++) { - t->global.settings[j][i] = - grpc_chttp2_settings_parameters[i].default_value; - } - } - t->global.dirtied_local_settings = 1; - /* Hack: it's common for implementations to assume 65536 bytes initial send - window -- this should by rights be 0 */ - t->global.force_send_settings = 1 << GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; - t->global.sent_local_settings = 0; - - /* configure http2 the way we like it */ - if (is_client) { - push_setting(t, GRPC_CHTTP2_SETTINGS_ENABLE_PUSH, 0); - push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 0); - } - push_setting(t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, DEFAULT_WINDOW); - - if (channel_args) { - for (i = 0; i < channel_args->num_args; i++) { - if (0 == - strcmp(channel_args->args[i].key, GRPC_ARG_MAX_CONCURRENT_STREAMS)) { - if (is_client) { - gpr_log(GPR_ERROR, "%s: is ignored on the client", - GRPC_ARG_MAX_CONCURRENT_STREAMS); - } else if (channel_args->args[i].type != GRPC_ARG_INTEGER) { - gpr_log(GPR_ERROR, "%s: must be an integer", - GRPC_ARG_MAX_CONCURRENT_STREAMS); - } else { - push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, - (uint32_t)channel_args->args[i].value.integer); - } - } else if (0 == strcmp(channel_args->args[i].key, - GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER)) { - if (channel_args->args[i].type != GRPC_ARG_INTEGER) { - gpr_log(GPR_ERROR, "%s: must be an integer", - GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER); - } else if ((t->global.next_stream_id & 1) != - (channel_args->args[i].value.integer & 1)) { - gpr_log(GPR_ERROR, "%s: low bit must be %d on %s", - GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER, - t->global.next_stream_id & 1, - is_client ? "client" : "server"); - } else { - t->global.next_stream_id = - (uint32_t)channel_args->args[i].value.integer; - } - } else if (0 == strcmp(channel_args->args[i].key, - GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES)) { - if (channel_args->args[i].type != GRPC_ARG_INTEGER) { - gpr_log(GPR_ERROR, "%s: must be an integer", - GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES); - } else if (channel_args->args[i].value.integer <= 5) { - gpr_log(GPR_ERROR, "%s: must be at least 5", - GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES); - } else { - t->global.stream_lookahead = - (uint32_t)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_ERROR, "%s: must be non-negative", - GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER); - } else { - push_setting(t, GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE, - (uint32_t)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_ERROR, "%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, - (uint32_t)channel_args->args[i].value.integer); - } - } - } - } -} - -static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) { - grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; - - lock(t); - t->destroying = 1; - drop_connection(exec_ctx, t); - unlock(exec_ctx, t); - - UNREF_TRANSPORT(exec_ctx, t, "destroy"); -} - -/** block grpc_endpoint_shutdown being called until a paired - allow_endpoint_shutdown is made */ -static void prevent_endpoint_shutdown(grpc_chttp2_transport *t) { - GPR_ASSERT(t->ep); - gpr_ref(&t->shutdown_ep_refs); -} - -static void allow_endpoint_shutdown_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t) { - if (gpr_unref(&t->shutdown_ep_refs)) { - if (t->ep) { - grpc_endpoint_shutdown(exec_ctx, t->ep); - } - } -} - -static void allow_endpoint_shutdown_unlocked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t) { - if (gpr_unref(&t->shutdown_ep_refs)) { - gpr_mu_lock(&t->mu); - if (t->ep) { - grpc_endpoint_shutdown(exec_ctx, t->ep); - } - gpr_mu_unlock(&t->mu); - } -} - -static void destroy_endpoint(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t) { - grpc_endpoint_destroy(exec_ctx, t->ep); - t->ep = NULL; - /* safe because we'll still have the ref for write */ - UNREF_TRANSPORT(exec_ctx, t, "disconnect"); -} - -static void close_transport_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t) { - if (!t->closed) { - t->closed = 1; - connectivity_state_set(exec_ctx, &t->global, GRPC_CHANNEL_FATAL_FAILURE, - "close_transport"); - if (t->ep) { - allow_endpoint_shutdown_locked(exec_ctx, t); - } - - /* flush writable stream list to avoid dangling references */ - grpc_chttp2_stream_global *stream_global; - grpc_chttp2_stream_writing *stream_writing; - while (grpc_chttp2_list_pop_writable_stream( - &t->global, &t->writing, &stream_global, &stream_writing)) { - GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing"); - } - } -} - -#ifdef GRPC_STREAM_REFCOUNT_DEBUG -void grpc_chttp2_stream_ref(grpc_chttp2_stream_global *stream_global, - const char *reason) { - grpc_stream_ref(STREAM_FROM_GLOBAL(stream_global)->refcount, reason); -} -void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx, - grpc_chttp2_stream_global *stream_global, - const char *reason) { - grpc_stream_unref(exec_ctx, STREAM_FROM_GLOBAL(stream_global)->refcount, - reason); -} -#else -void grpc_chttp2_stream_ref(grpc_chttp2_stream_global *stream_global) { - grpc_stream_ref(STREAM_FROM_GLOBAL(stream_global)->refcount); -} -void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx, - grpc_chttp2_stream_global *stream_global) { - grpc_stream_unref(exec_ctx, STREAM_FROM_GLOBAL(stream_global)->refcount); -} -#endif - -static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, - grpc_stream *gs, grpc_stream_refcount *refcount, - const void *server_data) { - grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; - grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; - - memset(s, 0, sizeof(*s)); - - s->refcount = refcount; - GRPC_CHTTP2_STREAM_REF(&s->global, "chttp2"); - - grpc_chttp2_incoming_metadata_buffer_init(&s->parsing.metadata_buffer[0]); - grpc_chttp2_incoming_metadata_buffer_init(&s->parsing.metadata_buffer[1]); - grpc_chttp2_incoming_metadata_buffer_init( - &s->global.received_initial_metadata); - grpc_chttp2_incoming_metadata_buffer_init( - &s->global.received_trailing_metadata); - grpc_chttp2_data_parser_init(&s->parsing.data_parser); - gpr_slice_buffer_init(&s->writing.flow_controlled_buffer); - - REF_TRANSPORT(t, "stream"); - - lock(t); - grpc_chttp2_register_stream(t, s); - if (server_data) { - GPR_ASSERT(t->parsing_active); - s->global.id = (uint32_t)(uintptr_t)server_data; - s->parsing.id = s->global.id; - s->global.outgoing_window = - t->global.settings[GRPC_PEER_SETTINGS] - [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]; - s->parsing.incoming_window = s->global.max_recv_bytes = - t->global.settings[GRPC_SENT_SETTINGS] - [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]; - *t->accepting_stream = s; - grpc_chttp2_stream_map_add(&t->parsing_stream_map, s->global.id, s); - s->global.in_stream_map = 1; - } - unlock(exec_ctx, t); - - return 0; -} - -static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, - grpc_stream *gs) { - grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; - grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; - int i; - grpc_byte_stream *bs; - - GPR_TIMER_BEGIN("destroy_stream", 0); - - gpr_mu_lock(&t->mu); - - GPR_ASSERT((s->global.write_closed && s->global.read_closed) || - s->global.id == 0); - GPR_ASSERT(!s->global.in_stream_map); - if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) { - close_transport_locked(exec_ctx, t); - } - if (!t->parsing_active && s->global.id) { - GPR_ASSERT(grpc_chttp2_stream_map_find(&t->parsing_stream_map, - s->global.id) == NULL); - } - - grpc_chttp2_list_remove_unannounced_incoming_window_available(&t->global, - &s->global); - grpc_chttp2_list_remove_stalled_by_transport(&t->global, &s->global); - - gpr_mu_unlock(&t->mu); - - for (i = 0; i < STREAM_LIST_COUNT; i++) { - if (s->included[i]) { - gpr_log(GPR_ERROR, "%s stream %d still included in list %d", - t->global.is_client ? "client" : "server", s->global.id, i); - abort(); - } - } - - while ( - (bs = grpc_chttp2_incoming_frame_queue_pop(&s->global.incoming_frames))) { - grpc_byte_stream_destroy(exec_ctx, bs); - } - - GPR_ASSERT(s->global.send_initial_metadata_finished == NULL); - GPR_ASSERT(s->global.send_message_finished == NULL); - GPR_ASSERT(s->global.send_trailing_metadata_finished == NULL); - GPR_ASSERT(s->global.recv_initial_metadata_ready == NULL); - GPR_ASSERT(s->global.recv_message_ready == NULL); - GPR_ASSERT(s->global.recv_trailing_metadata_finished == NULL); - grpc_chttp2_data_parser_destroy(exec_ctx, &s->parsing.data_parser); - grpc_chttp2_incoming_metadata_buffer_destroy(&s->parsing.metadata_buffer[0]); - grpc_chttp2_incoming_metadata_buffer_destroy(&s->parsing.metadata_buffer[1]); - grpc_chttp2_incoming_metadata_buffer_destroy( - &s->global.received_initial_metadata); - grpc_chttp2_incoming_metadata_buffer_destroy( - &s->global.received_trailing_metadata); - gpr_slice_buffer_destroy(&s->writing.flow_controlled_buffer); - - UNREF_TRANSPORT(exec_ctx, t, "stream"); - - GPR_TIMER_END("destroy_stream", 0); -} - -grpc_chttp2_stream_parsing *grpc_chttp2_parsing_lookup_stream( - grpc_chttp2_transport_parsing *transport_parsing, uint32_t id) { - grpc_chttp2_transport *t = TRANSPORT_FROM_PARSING(transport_parsing); - grpc_chttp2_stream *s = - grpc_chttp2_stream_map_find(&t->parsing_stream_map, id); - return s ? &s->parsing : NULL; -} - -grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing, - uint32_t id) { - grpc_chttp2_stream *accepting; - grpc_chttp2_transport *t = TRANSPORT_FROM_PARSING(transport_parsing); - GPR_ASSERT(t->accepting_stream == NULL); - t->accepting_stream = &accepting; - t->channel_callback.accept_stream(exec_ctx, - t->channel_callback.accept_stream_user_data, - &t->base, (void *)(uintptr_t)id); - t->accepting_stream = NULL; - return &accepting->parsing; -} - -/******************************************************************************* - * LOCK MANAGEMENT - */ - -/* We take a grpc_chttp2_transport-global lock in response to calls coming in - from above, - and in response to data being received from below. New data to be written - is always queued, as are callbacks to process data. During unlock() we - check our todo lists and initiate callbacks and flush writes. */ - -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(exec_ctx, &t->global, &t->writing, - t->parsing_active)) { - t->writing_active = 1; - REF_TRANSPORT(t, "writing"); - grpc_exec_ctx_enqueue(exec_ctx, &t->writing_action, true, NULL); - prevent_endpoint_shutdown(t); - } - check_read_ops(exec_ctx, &t->global); - - gpr_mu_unlock(&t->mu); - GPR_TIMER_END("unlock", 0); -} - -/******************************************************************************* - * OUTPUT PROCESSING - */ - -void grpc_chttp2_become_writable(grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global) { - if (!TRANSPORT_FROM_GLOBAL(transport_global)->closed && - grpc_chttp2_list_add_writable_stream(transport_global, stream_global)) { - GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing"); - } -} - -static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id, - uint32_t value) { - const grpc_chttp2_setting_parameters *sp = - &grpc_chttp2_settings_parameters[id]; - uint32_t use_value = GPR_CLAMP(value, sp->min_value, sp->max_value); - if (use_value != value) { - gpr_log(GPR_INFO, "Requested parameter %s clamped from %d to %d", sp->name, - value, use_value); - } - if (use_value != t->global.settings[GRPC_LOCAL_SETTINGS][id]) { - t->global.settings[GRPC_LOCAL_SETTINGS][id] = use_value; - t->global.dirtied_local_settings = 1; - } -} - -void grpc_chttp2_terminate_writing(grpc_exec_ctx *exec_ctx, - void *transport_writing_ptr, bool success) { - grpc_chttp2_transport_writing *transport_writing = transport_writing_ptr; - grpc_chttp2_transport *t = TRANSPORT_FROM_WRITING(transport_writing); - grpc_chttp2_stream_global *stream_global; - - GPR_TIMER_BEGIN("grpc_chttp2_terminate_writing", 0); - - lock(t); - - allow_endpoint_shutdown_locked(exec_ctx, t); - - if (!success) { - drop_connection(exec_ctx, t); - } - - grpc_chttp2_cleanup_writing(exec_ctx, &t->global, &t->writing); - - while (grpc_chttp2_list_pop_closed_waiting_for_writing(&t->global, - &stream_global)) { - fail_pending_writes(exec_ctx, stream_global); - GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "finish_writes"); - } - - /* leave the writing flag up on shutdown to prevent further writes in unlock() - from starting */ - t->writing_active = 0; - if (t->ep && !t->endpoint_reading) { - destroy_endpoint(exec_ctx, t); - } - - unlock(exec_ctx, t); - - UNREF_TRANSPORT(exec_ctx, t, "writing"); - - GPR_TIMER_END("grpc_chttp2_terminate_writing", 0); -} - -static void writing_action(grpc_exec_ctx *exec_ctx, void *gt, - bool iomgr_success_ignored) { - grpc_chttp2_transport *t = gt; - GPR_TIMER_BEGIN("writing_action", 0); - grpc_chttp2_perform_writes(exec_ctx, &t->writing, t->ep); - GPR_TIMER_END("writing_action", 0); -} - -void grpc_chttp2_add_incoming_goaway( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, - uint32_t goaway_error, gpr_slice goaway_text) { - char *msg = gpr_dump_slice(goaway_text, GPR_DUMP_HEX | GPR_DUMP_ASCII); - gpr_log(GPR_DEBUG, "got goaway [%d]: %s", goaway_error, msg); - gpr_free(msg); - gpr_slice_unref(goaway_text); - transport_global->seen_goaway = 1; - connectivity_state_set(exec_ctx, transport_global, GRPC_CHANNEL_FATAL_FAILURE, - "got_goaway"); -} - -static void maybe_start_some_streams( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global) { - grpc_chttp2_stream_global *stream_global; - uint32_t stream_incoming_window; - /* start streams where we have free grpc_chttp2_stream ids and free - * concurrency */ - while (transport_global->next_stream_id <= MAX_CLIENT_STREAM_ID && - transport_global->concurrent_stream_count < - transport_global - ->settings[GRPC_PEER_SETTINGS] - [GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS] && - grpc_chttp2_list_pop_waiting_for_concurrency(transport_global, - &stream_global)) { - /* safe since we can't (legally) be parsing this stream yet */ - grpc_chttp2_stream_parsing *stream_parsing = - &STREAM_FROM_GLOBAL(stream_global)->parsing; - GRPC_CHTTP2_IF_TRACING(gpr_log( - GPR_DEBUG, "HTTP:%s: Allocating new grpc_chttp2_stream %p to id %d", - transport_global->is_client ? "CLI" : "SVR", stream_global, - transport_global->next_stream_id)); - - GPR_ASSERT(stream_global->id == 0); - stream_global->id = stream_parsing->id = transport_global->next_stream_id; - transport_global->next_stream_id += 2; - - if (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID) { - connectivity_state_set(exec_ctx, transport_global, - GRPC_CHANNEL_TRANSIENT_FAILURE, - "no_more_stream_ids"); - } - - stream_global->outgoing_window = - transport_global->settings[GRPC_PEER_SETTINGS] - [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]; - stream_parsing->incoming_window = stream_incoming_window = - transport_global->settings[GRPC_SENT_SETTINGS] - [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]; - stream_global->max_recv_bytes = - GPR_MAX(stream_incoming_window, stream_global->max_recv_bytes); - grpc_chttp2_stream_map_add( - &TRANSPORT_FROM_GLOBAL(transport_global)->new_stream_map, - stream_global->id, STREAM_FROM_GLOBAL(stream_global)); - stream_global->in_stream_map = 1; - transport_global->concurrent_stream_count++; - grpc_chttp2_become_writable(transport_global, stream_global); - } - /* cancel out streams that will never be started */ - while (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID && - grpc_chttp2_list_pop_waiting_for_concurrency(transport_global, - &stream_global)) { - cancel_from_api(exec_ctx, transport_global, stream_global, - GRPC_STATUS_UNAVAILABLE); - } -} - -static grpc_closure *add_closure_barrier(grpc_closure *closure) { - closure->final_data += 2; - return closure; -} - -void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx, - grpc_closure **pclosure, int success) { - grpc_closure *closure = *pclosure; - if (closure == NULL) { - return; - } - closure->final_data -= 2; - if (!success) { - closure->final_data |= 1; - } - if (closure->final_data < 2) { - grpc_exec_ctx_enqueue(exec_ctx, closure, closure->final_data == 0, NULL); - } - *pclosure = NULL; -} - -static int contains_non_ok_status( - grpc_chttp2_transport_global *transport_global, - grpc_metadata_batch *batch) { - grpc_linked_mdelem *l; - for (l = batch->list.head; l; l = l->next) { - if (l->md->key == GRPC_MDSTR_GRPC_STATUS && - l->md != GRPC_MDELEM_GRPC_STATUS_0) { - return 1; - } - } - return 0; -} - -static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, bool 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) { - grpc_closure *on_complete; - - 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; - - if (op->cancel_with_status != GRPC_STATUS_OK) { - cancel_from_api(exec_ctx, transport_global, stream_global, - op->cancel_with_status); - } - - if (op->close_with_status != GRPC_STATUS_OK) { - close_from_api(exec_ctx, transport_global, stream_global, - op->close_with_status, op->optional_close_message); - } - - if (op->send_initial_metadata != NULL) { - GPR_ASSERT(stream_global->send_initial_metadata_finished == NULL); - stream_global->send_initial_metadata_finished = - add_closure_barrier(on_complete); - stream_global->send_initial_metadata = op->send_initial_metadata; - if (contains_non_ok_status(transport_global, op->send_initial_metadata)) { - stream_global->seen_error = 1; - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); - } - if (!stream_global->write_closed) { - if (transport_global->is_client) { - GPR_ASSERT(stream_global->id == 0); - grpc_chttp2_list_add_waiting_for_concurrency(transport_global, - stream_global); - maybe_start_some_streams(exec_ctx, transport_global); - } else { - GPR_ASSERT(stream_global->id != 0); - grpc_chttp2_become_writable(transport_global, stream_global); - } - } else { - grpc_chttp2_complete_closure_step( - exec_ctx, &stream_global->send_initial_metadata_finished, 0); - } - } - - if (op->send_message != NULL) { - GPR_ASSERT(stream_global->send_message_finished == NULL); - GPR_ASSERT(stream_global->send_message == NULL); - stream_global->send_message_finished = add_closure_barrier(on_complete); - if (stream_global->write_closed) { - grpc_chttp2_complete_closure_step( - exec_ctx, &stream_global->send_message_finished, 0); - } else { - stream_global->send_message = op->send_message; - if (stream_global->id != 0) { - grpc_chttp2_become_writable(transport_global, stream_global); - } - } - } - - if (op->send_trailing_metadata != NULL) { - GPR_ASSERT(stream_global->send_trailing_metadata_finished == NULL); - stream_global->send_trailing_metadata_finished = - add_closure_barrier(on_complete); - stream_global->send_trailing_metadata = op->send_trailing_metadata; - if (contains_non_ok_status(transport_global, op->send_trailing_metadata)) { - stream_global->seen_error = 1; - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); - } - if (stream_global->write_closed) { - grpc_chttp2_complete_closure_step( - 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 - bytes before going writable */ - grpc_chttp2_become_writable(transport_global, stream_global); - } - } - - if (op->recv_initial_metadata != NULL) { - GPR_ASSERT(stream_global->recv_initial_metadata_ready == NULL); - stream_global->recv_initial_metadata_ready = - op->recv_initial_metadata_ready; - stream_global->recv_initial_metadata = op->recv_initial_metadata; - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); - } - - if (op->recv_message != NULL) { - GPR_ASSERT(stream_global->recv_message_ready == NULL); - stream_global->recv_message_ready = op->recv_message_ready; - stream_global->recv_message = op->recv_message; - if (stream_global->id != 0 && - (stream_global->incoming_frames.head == NULL || - stream_global->incoming_frames.head->is_tail)) { - incoming_byte_stream_update_flow_control( - transport_global, stream_global, transport_global->stream_lookahead, - 0); - } - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); - } - - if (op->recv_trailing_metadata != NULL) { - GPR_ASSERT(stream_global->recv_trailing_metadata_finished == NULL); - stream_global->recv_trailing_metadata_finished = - add_closure_barrier(on_complete); - stream_global->recv_trailing_metadata = op->recv_trailing_metadata; - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); - } - - grpc_chttp2_complete_closure_step(exec_ctx, &on_complete, 1); - - GPR_TIMER_END("perform_stream_op_locked", 0); -} - -static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, - grpc_stream *gs, grpc_transport_stream_op *op) { - grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; - grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; - - lock(t); - perform_stream_op_locked(exec_ctx, &t->global, &s->global, op); - unlock(exec_ctx, t); -} - -static void send_ping_locked(grpc_chttp2_transport *t, grpc_closure *on_recv) { - grpc_chttp2_outstanding_ping *p = gpr_malloc(sizeof(*p)); - p->next = &t->global.pings; - p->prev = p->next->prev; - p->prev->next = p->next->prev = p; - p->id[0] = (uint8_t)((t->global.ping_counter >> 56) & 0xff); - p->id[1] = (uint8_t)((t->global.ping_counter >> 48) & 0xff); - p->id[2] = (uint8_t)((t->global.ping_counter >> 40) & 0xff); - p->id[3] = (uint8_t)((t->global.ping_counter >> 32) & 0xff); - p->id[4] = (uint8_t)((t->global.ping_counter >> 24) & 0xff); - p->id[5] = (uint8_t)((t->global.ping_counter >> 16) & 0xff); - p->id[6] = (uint8_t)((t->global.ping_counter >> 8) & 0xff); - p->id[7] = (uint8_t)(t->global.ping_counter & 0xff); - p->on_recv = on_recv; - gpr_slice_buffer_add(&t->global.qbuf, grpc_chttp2_ping_create(0, p->id)); -} - -void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport_parsing *transport_parsing, - const uint8_t *opaque_8bytes) { - grpc_chttp2_outstanding_ping *ping; - grpc_chttp2_transport *t = TRANSPORT_FROM_PARSING(transport_parsing); - grpc_chttp2_transport_global *transport_global = &t->global; - lock(t); - for (ping = transport_global->pings.next; ping != &transport_global->pings; - ping = ping->next) { - if (0 == memcmp(opaque_8bytes, ping->id, 8)) { - grpc_exec_ctx_enqueue(exec_ctx, ping->on_recv, true, NULL); - ping->next->prev = ping->prev; - ping->prev->next = ping->next; - gpr_free(ping); - break; - } - } - unlock(exec_ctx, t); -} - -static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_transport_op *op) { - bool close_transport = false; - - grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, true, NULL); - - if (op->on_connectivity_state_change != NULL) { - grpc_connectivity_state_notify_on_state_change( - exec_ctx, &t->channel_callback.state_tracker, op->connectivity_state, - op->on_connectivity_state_change); - } - - if (op->send_goaway) { - t->global.sent_goaway = 1; - grpc_chttp2_goaway_append( - t->global.last_incoming_stream_id, - (uint32_t)grpc_chttp2_grpc_status_to_http2_error(op->goaway_status), - gpr_slice_ref(*op->goaway_message), &t->global.qbuf); - close_transport = !grpc_chttp2_has_streams(t); - } - - if (op->set_accept_stream) { - t->channel_callback.accept_stream = op->set_accept_stream_fn; - t->channel_callback.accept_stream_user_data = - op->set_accept_stream_user_data; - } - - if (op->bind_pollset) { - add_to_pollset_locked(exec_ctx, t, op->bind_pollset); - } - - if (op->bind_pollset_set) { - add_to_pollset_set_locked(exec_ctx, t, op->bind_pollset_set); - } - - if (op->send_ping) { - send_ping_locked(t, op->send_ping); - } - - if (op->disconnect) { - close_transport_locked(exec_ctx, t); - } - - if (close_transport) { - close_transport_locked(exec_ctx, t); - } -} - -static void perform_transport_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, - grpc_transport_op *op) { - grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; - - lock(t); - - /* If there's a set_accept_stream ensure that we're not parsing - to avoid changing things out from underneath */ - if (t->parsing_active && op->set_accept_stream) { - GPR_ASSERT(t->post_parsing_op == NULL); - t->post_parsing_op = gpr_malloc(sizeof(*op)); - memcpy(t->post_parsing_op, op, sizeof(*op)); - } else { - perform_transport_op_locked(exec_ctx, t, op); - } - - unlock(exec_ctx, t); -} - -/******************************************************************************* - * INPUT PROCESSING - */ - -static void check_read_ops(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport_global *transport_global) { - grpc_chttp2_stream_global *stream_global; - grpc_byte_stream *bs; - while ( - grpc_chttp2_list_pop_check_read_ops(transport_global, &stream_global)) { - if (stream_global->recv_initial_metadata_ready != NULL && - stream_global->published_initial_metadata) { - grpc_chttp2_incoming_metadata_buffer_publish( - &stream_global->received_initial_metadata, - stream_global->recv_initial_metadata); - grpc_exec_ctx_enqueue( - exec_ctx, stream_global->recv_initial_metadata_ready, true, NULL); - stream_global->recv_initial_metadata_ready = NULL; - } - if (stream_global->recv_message_ready != NULL) { - while (stream_global->seen_error && - (bs = grpc_chttp2_incoming_frame_queue_pop( - &stream_global->incoming_frames)) != NULL) { - grpc_byte_stream_destroy(exec_ctx, bs); - } - if (stream_global->incoming_frames.head != NULL) { - *stream_global->recv_message = grpc_chttp2_incoming_frame_queue_pop( - &stream_global->incoming_frames); - GPR_ASSERT(*stream_global->recv_message != NULL); - grpc_exec_ctx_enqueue(exec_ctx, stream_global->recv_message_ready, true, - NULL); - stream_global->recv_message_ready = NULL; - } else if (stream_global->published_trailing_metadata) { - *stream_global->recv_message = NULL; - grpc_exec_ctx_enqueue(exec_ctx, stream_global->recv_message_ready, true, - NULL); - stream_global->recv_message_ready = NULL; - } - } - if (stream_global->recv_trailing_metadata_finished != NULL && - stream_global->read_closed && stream_global->write_closed) { - while (stream_global->seen_error && - (bs = grpc_chttp2_incoming_frame_queue_pop( - &stream_global->incoming_frames)) != NULL) { - grpc_byte_stream_destroy(exec_ctx, bs); - } - if (stream_global->incoming_frames.head == NULL) { - grpc_chttp2_incoming_metadata_buffer_publish( - &stream_global->received_trailing_metadata, - stream_global->recv_trailing_metadata); - grpc_chttp2_complete_closure_step( - exec_ctx, &stream_global->recv_trailing_metadata_finished, 1); - } - } - } -} - -static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, - uint32_t id) { - size_t new_stream_count; - grpc_chttp2_stream *s = - grpc_chttp2_stream_map_delete(&t->parsing_stream_map, id); - if (!s) { - s = grpc_chttp2_stream_map_delete(&t->new_stream_map, id); - } - GPR_ASSERT(s); - s->global.in_stream_map = 0; - if (t->parsing.incoming_stream == &s->parsing) { - t->parsing.incoming_stream = NULL; - grpc_chttp2_parsing_become_skip_parser(exec_ctx, &t->parsing); - } - if (s->parsing.data_parser.parsing_frame != NULL) { - grpc_chttp2_incoming_byte_stream_finished( - exec_ctx, s->parsing.data_parser.parsing_frame, 0, 0); - s->parsing.data_parser.parsing_frame = NULL; - } - - if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) { - close_transport_locked(exec_ctx, t); - } - if (grpc_chttp2_list_remove_writable_stream(&t->global, &s->global)) { - GRPC_CHTTP2_STREAM_UNREF(exec_ctx, &s->global, "chttp2_writing"); - } - - new_stream_count = grpc_chttp2_stream_map_size(&t->parsing_stream_map) + - grpc_chttp2_stream_map_size(&t->new_stream_map); - GPR_ASSERT(new_stream_count <= UINT32_MAX); - if (new_stream_count != t->global.concurrent_stream_count) { - t->global.concurrent_stream_count = (uint32_t)new_stream_count; - maybe_start_some_streams(exec_ctx, &t->global); - } -} - -static void cancel_from_api(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global, - grpc_status_code status) { - if (stream_global->id != 0) { - gpr_slice_buffer_add( - &transport_global->qbuf, - grpc_chttp2_rst_stream_create( - stream_global->id, - (uint32_t)grpc_chttp2_grpc_status_to_http2_error(status))); - } - grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global, status, - NULL); - grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1, - 1); -} - -void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global, - grpc_status_code status, gpr_slice *slice) { - if (status != GRPC_STATUS_OK) { - stream_global->seen_error = 1; - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); - } - /* stream_global->recv_trailing_metadata_finished gives us a - last chance replacement: we've received trailing metadata, - but something more important has become available to signal - 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) { - char status_string[GPR_LTOA_MIN_BUFSIZE]; - gpr_ltoa(status, status_string); - grpc_chttp2_incoming_metadata_buffer_add( - &stream_global->received_trailing_metadata, - grpc_mdelem_from_metadata_strings( - GRPC_MDSTR_GRPC_STATUS, grpc_mdstr_from_string(status_string))); - if (slice) { - grpc_chttp2_incoming_metadata_buffer_add( - &stream_global->received_trailing_metadata, - grpc_mdelem_from_metadata_strings( - GRPC_MDSTR_GRPC_MESSAGE, - grpc_mdstr_from_slice(gpr_slice_ref(*slice)))); - } - stream_global->published_trailing_metadata = 1; - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); - } - if (slice) { - gpr_slice_unref(*slice); - } -} - -static void fail_pending_writes(grpc_exec_ctx *exec_ctx, - grpc_chttp2_stream_global *stream_global) { - grpc_chttp2_complete_closure_step( - exec_ctx, &stream_global->send_initial_metadata_finished, 0); - grpc_chttp2_complete_closure_step( - exec_ctx, &stream_global->send_trailing_metadata_finished, 0); - grpc_chttp2_complete_closure_step(exec_ctx, - &stream_global->send_message_finished, 0); -} - -void grpc_chttp2_mark_stream_closed( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global, int close_reads, - int close_writes) { - if (stream_global->read_closed && stream_global->write_closed) { - /* already closed */ - return; - } - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); - if (close_reads && !stream_global->read_closed) { - stream_global->read_closed = 1; - stream_global->published_initial_metadata = 1; - stream_global->published_trailing_metadata = 1; - } - if (close_writes && !stream_global->write_closed) { - stream_global->write_closed = 1; - if (TRANSPORT_FROM_GLOBAL(transport_global)->writing_active) { - GRPC_CHTTP2_STREAM_REF(stream_global, "finish_writes"); - grpc_chttp2_list_add_closed_waiting_for_writing(transport_global, - stream_global); - } else { - fail_pending_writes(exec_ctx, stream_global); - } - } - if (stream_global->read_closed && stream_global->write_closed) { - if (stream_global->id != 0 && - TRANSPORT_FROM_GLOBAL(transport_global)->parsing_active) { - grpc_chttp2_list_add_closed_waiting_for_parsing(transport_global, - stream_global); - } else { - if (stream_global->id != 0) { - remove_stream(exec_ctx, TRANSPORT_FROM_GLOBAL(transport_global), - stream_global->id); - } - GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2"); - } - } -} - -static void close_from_api(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global, - grpc_status_code status, - gpr_slice *optional_message) { - gpr_slice hdr; - gpr_slice status_hdr; - gpr_slice message_pfx; - uint8_t *p; - uint32_t len = 0; - - GPR_ASSERT(status >= 0 && (int)status < 100); - - GPR_ASSERT(stream_global->id != 0); - - /* Hand roll a header block. - This is unnecessarily ugly - at some point we should find a more elegant - solution. - It's complicated by the fact that our send machinery would be dead by the - time we got around to sending this, so instead we ignore HPACK compression - and just write the uncompressed bytes onto the wire. */ - status_hdr = gpr_slice_malloc(15 + (status >= 10)); - p = GPR_SLICE_START_PTR(status_hdr); - *p++ = 0x40; /* literal header */ - *p++ = 11; /* len(grpc-status) */ - *p++ = 'g'; - *p++ = 'r'; - *p++ = 'p'; - *p++ = 'c'; - *p++ = '-'; - *p++ = 's'; - *p++ = 't'; - *p++ = 'a'; - *p++ = 't'; - *p++ = 'u'; - *p++ = 's'; - if (status < 10) { - *p++ = 1; - *p++ = (uint8_t)('0' + status); - } else { - *p++ = 2; - *p++ = (uint8_t)('0' + (status / 10)); - *p++ = (uint8_t)('0' + (status % 10)); - } - GPR_ASSERT(p == GPR_SLICE_END_PTR(status_hdr)); - len += (uint32_t)GPR_SLICE_LENGTH(status_hdr); - - if (optional_message) { - GPR_ASSERT(GPR_SLICE_LENGTH(*optional_message) < 127); - message_pfx = gpr_slice_malloc(15); - p = GPR_SLICE_START_PTR(message_pfx); - *p++ = 0x40; - *p++ = 12; /* len(grpc-message) */ - *p++ = 'g'; - *p++ = 'r'; - *p++ = 'p'; - *p++ = 'c'; - *p++ = '-'; - *p++ = 'm'; - *p++ = 'e'; - *p++ = 's'; - *p++ = 's'; - *p++ = 'a'; - *p++ = 'g'; - *p++ = 'e'; - *p++ = (uint8_t)GPR_SLICE_LENGTH(*optional_message); - GPR_ASSERT(p == GPR_SLICE_END_PTR(message_pfx)); - len += (uint32_t)GPR_SLICE_LENGTH(message_pfx); - len += (uint32_t)GPR_SLICE_LENGTH(*optional_message); - } - - hdr = gpr_slice_malloc(9); - p = GPR_SLICE_START_PTR(hdr); - *p++ = (uint8_t)(len >> 16); - *p++ = (uint8_t)(len >> 8); - *p++ = (uint8_t)(len); - *p++ = GRPC_CHTTP2_FRAME_HEADER; - *p++ = GRPC_CHTTP2_DATA_FLAG_END_STREAM | GRPC_CHTTP2_DATA_FLAG_END_HEADERS; - *p++ = (uint8_t)(stream_global->id >> 24); - *p++ = (uint8_t)(stream_global->id >> 16); - *p++ = (uint8_t)(stream_global->id >> 8); - *p++ = (uint8_t)(stream_global->id); - GPR_ASSERT(p == GPR_SLICE_END_PTR(hdr)); - - gpr_slice_buffer_add(&transport_global->qbuf, hdr); - gpr_slice_buffer_add(&transport_global->qbuf, status_hdr); - if (optional_message) { - gpr_slice_buffer_add(&transport_global->qbuf, message_pfx); - gpr_slice_buffer_add(&transport_global->qbuf, - gpr_slice_ref(*optional_message)); - } - - gpr_slice_buffer_add( - &transport_global->qbuf, - grpc_chttp2_rst_stream_create(stream_global->id, GRPC_CHTTP2_NO_ERROR)); - - if (optional_message) { - gpr_slice_ref(*optional_message); - } - grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global, status, - optional_message); - grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1, - 1); -} - -static void cancel_stream_cb(grpc_chttp2_transport_global *transport_global, - void *user_data, - grpc_chttp2_stream_global *stream_global) { - cancel_from_api(user_data, transport_global, stream_global, - GRPC_STATUS_UNAVAILABLE); -} - -static void end_all_the_calls(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t) { - grpc_chttp2_for_all_streams(&t->global, exec_ctx, cancel_stream_cb); -} - -static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { - close_transport_locked(exec_ctx, t); - end_all_the_calls(exec_ctx, t); -} - -/** update window from a settings change */ -static void update_global_window(void *args, uint32_t id, void *stream) { - grpc_chttp2_transport *t = args; - grpc_chttp2_stream *s = stream; - grpc_chttp2_transport_global *transport_global = &t->global; - grpc_chttp2_stream_global *stream_global = &s->global; - int was_zero; - int is_zero; - int64_t initial_window_update = t->parsing.initial_window_update; - - was_zero = stream_global->outgoing_window <= 0; - GRPC_CHTTP2_FLOW_CREDIT_STREAM("settings", transport_global, stream_global, - outgoing_window, initial_window_update); - is_zero = stream_global->outgoing_window <= 0; - - if (was_zero && !is_zero) { - grpc_chttp2_become_writable(transport_global, stream_global); - } -} - -static void read_error_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t) { - t->endpoint_reading = 0; - if (!t->writing_active && t->ep) { - destroy_endpoint(exec_ctx, t); - } -} - -/* tcp read callback */ -static void recv_data(grpc_exec_ctx *exec_ctx, void *tp, bool success) { - size_t i; - int keep_reading = 0; - grpc_chttp2_transport *t = tp; - grpc_chttp2_transport_global *transport_global = &t->global; - grpc_chttp2_transport_parsing *transport_parsing = &t->parsing; - grpc_chttp2_stream_global *stream_global; - - GPR_TIMER_BEGIN("recv_data", 0); - - lock(t); - i = 0; - GPR_ASSERT(!t->parsing_active); - if (!t->closed) { - t->parsing_active = 1; - /* merge stream lists */ - grpc_chttp2_stream_map_move_into(&t->new_stream_map, - &t->parsing_stream_map); - grpc_chttp2_prepare_to_read(transport_global, transport_parsing); - gpr_mu_unlock(&t->mu); - GPR_TIMER_BEGIN("recv_data.parse", 0); - for (; i < t->read_buffer.count && - grpc_chttp2_perform_read(exec_ctx, transport_parsing, - t->read_buffer.slices[i]); - i++) - ; - GPR_TIMER_END("recv_data.parse", 0); - gpr_mu_lock(&t->mu); - /* copy parsing qbuf to global qbuf */ - gpr_slice_buffer_move_into(&t->parsing.qbuf, &t->global.qbuf); - if (i != t->read_buffer.count) { - unlock(exec_ctx, t); - lock(t); - drop_connection(exec_ctx, t); - } - /* merge stream lists */ - grpc_chttp2_stream_map_move_into(&t->new_stream_map, - &t->parsing_stream_map); - transport_global->concurrent_stream_count = - (uint32_t)grpc_chttp2_stream_map_size(&t->parsing_stream_map); - if (transport_parsing->initial_window_update != 0) { - grpc_chttp2_stream_map_for_each(&t->parsing_stream_map, - update_global_window, t); - transport_parsing->initial_window_update = 0; - } - /* handle higher level things */ - grpc_chttp2_publish_reads(exec_ctx, transport_global, transport_parsing); - t->parsing_active = 0; - /* handle delayed transport ops (if there is one) */ - if (t->post_parsing_op) { - grpc_transport_op *op = t->post_parsing_op; - t->post_parsing_op = NULL; - perform_transport_op_locked(exec_ctx, t, op); - gpr_free(op); - } - /* if a stream is in the stream map, and gets cancelled, we need to ensure - * we are not parsing before continuing the cancellation to keep things in - * a sane state */ - while (grpc_chttp2_list_pop_closed_waiting_for_parsing(transport_global, - &stream_global)) { - GPR_ASSERT(stream_global->in_stream_map); - GPR_ASSERT(stream_global->write_closed); - GPR_ASSERT(stream_global->read_closed); - remove_stream(exec_ctx, t, stream_global->id); - GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2"); - } - } - if (!success || i != t->read_buffer.count || t->closed) { - drop_connection(exec_ctx, t); - read_error_locked(exec_ctx, t); - } else if (!t->closed) { - keep_reading = 1; - REF_TRANSPORT(t, "keep_reading"); - prevent_endpoint_shutdown(t); - } - gpr_slice_buffer_reset_and_unref(&t->read_buffer); - unlock(exec_ctx, t); - - if (keep_reading) { - grpc_endpoint_read(exec_ctx, t->ep, &t->read_buffer, &t->recv_data); - allow_endpoint_shutdown_unlocked(exec_ctx, t); - UNREF_TRANSPORT(exec_ctx, t, "keep_reading"); - } else { - UNREF_TRANSPORT(exec_ctx, t, "recv_data"); - } - - GPR_TIMER_END("recv_data", 0); -} - -/******************************************************************************* - * CALLBACK LOOP - */ - -static void connectivity_state_set( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, - grpc_connectivity_state state, const char *reason) { - GRPC_CHTTP2_IF_TRACING( - gpr_log(GPR_DEBUG, "set connectivity_state=%d", state)); - grpc_connectivity_state_set( - exec_ctx, - &TRANSPORT_FROM_GLOBAL(transport_global)->channel_callback.state_tracker, - state, reason); -} - -/******************************************************************************* - * POLLSET STUFF - */ - -static void add_to_pollset_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_pollset *pollset) { - if (t->ep) { - grpc_endpoint_add_to_pollset(exec_ctx, t->ep, pollset); - } -} - -static void add_to_pollset_set_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_pollset_set *pollset_set) { - if (t->ep) { - grpc_endpoint_add_to_pollset_set(exec_ctx, t->ep, pollset_set); - } -} - -static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_transport *gt, - grpc_stream *gs, grpc_pollset *pollset) { - grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; - lock(t); - add_to_pollset_locked(exec_ctx, t, pollset); - unlock(exec_ctx, t); -} - -/******************************************************************************* - * BYTE STREAM - */ - -static void incoming_byte_stream_update_flow_control( - grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global, size_t max_size_hint, - size_t have_already) { - uint32_t max_recv_bytes; - - /* clamp max recv hint to an allowable size */ - if (max_size_hint >= UINT32_MAX - transport_global->stream_lookahead) { - max_recv_bytes = UINT32_MAX - transport_global->stream_lookahead; - } else { - max_recv_bytes = (uint32_t)max_size_hint; - } - - /* account for bytes already received but unknown to higher layers */ - if (max_recv_bytes >= have_already) { - max_recv_bytes -= (uint32_t)have_already; - } else { - max_recv_bytes = 0; - } - - /* add some small lookahead to keep pipelines flowing */ - GPR_ASSERT(max_recv_bytes <= UINT32_MAX - transport_global->stream_lookahead); - max_recv_bytes += transport_global->stream_lookahead; - if (stream_global->max_recv_bytes < max_recv_bytes) { - uint32_t add_max_recv_bytes = - max_recv_bytes - stream_global->max_recv_bytes; - GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", transport_global, stream_global, - max_recv_bytes, add_max_recv_bytes); - GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", transport_global, stream_global, - unannounced_incoming_window_for_parse, - add_max_recv_bytes); - GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", transport_global, stream_global, - unannounced_incoming_window_for_writing, - add_max_recv_bytes); - grpc_chttp2_list_add_unannounced_incoming_window_available(transport_global, - stream_global); - grpc_chttp2_become_writable(transport_global, stream_global); - } -} - -static int incoming_byte_stream_next(grpc_exec_ctx *exec_ctx, - grpc_byte_stream *byte_stream, - gpr_slice *slice, size_t max_size_hint, - grpc_closure *on_complete) { - grpc_chttp2_incoming_byte_stream *bs = - (grpc_chttp2_incoming_byte_stream *)byte_stream; - grpc_chttp2_transport_global *transport_global = &bs->transport->global; - grpc_chttp2_stream_global *stream_global = &bs->stream->global; - - lock(bs->transport); - if (bs->is_tail) { - incoming_byte_stream_update_flow_control(transport_global, stream_global, - max_size_hint, bs->slices.length); - } - if (bs->slices.count > 0) { - *slice = gpr_slice_buffer_take_first(&bs->slices); - unlock(exec_ctx, bs->transport); - return 1; - } else if (bs->failed) { - grpc_exec_ctx_enqueue(exec_ctx, on_complete, false, NULL); - unlock(exec_ctx, bs->transport); - return 0; - } else { - bs->on_next = on_complete; - bs->next = slice; - unlock(exec_ctx, bs->transport); - return 0; - } -} - -static void incoming_byte_stream_unref(grpc_chttp2_incoming_byte_stream *bs) { - if (gpr_unref(&bs->refs)) { - gpr_slice_buffer_destroy(&bs->slices); - gpr_free(bs); - } -} - -static void incoming_byte_stream_destroy(grpc_exec_ctx *exec_ctx, - grpc_byte_stream *byte_stream) { - incoming_byte_stream_unref((grpc_chttp2_incoming_byte_stream *)byte_stream); -} - -void grpc_chttp2_incoming_byte_stream_push(grpc_exec_ctx *exec_ctx, - grpc_chttp2_incoming_byte_stream *bs, - gpr_slice slice) { - gpr_mu_lock(&bs->transport->mu); - if (bs->on_next != NULL) { - *bs->next = slice; - grpc_exec_ctx_enqueue(exec_ctx, bs->on_next, true, NULL); - bs->on_next = NULL; - } else { - gpr_slice_buffer_add(&bs->slices, slice); - } - gpr_mu_unlock(&bs->transport->mu); -} - -void grpc_chttp2_incoming_byte_stream_finished( - grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs, int success, - int from_parsing_thread) { - if (!success) { - if (from_parsing_thread) { - gpr_mu_lock(&bs->transport->mu); - } - grpc_exec_ctx_enqueue(exec_ctx, bs->on_next, false, NULL); - bs->on_next = NULL; - bs->failed = 1; - if (from_parsing_thread) { - gpr_mu_unlock(&bs->transport->mu); - } - } else { -#ifndef NDEBUG - if (from_parsing_thread) { - gpr_mu_lock(&bs->transport->mu); - } - GPR_ASSERT(bs->on_next == NULL); - if (from_parsing_thread) { - gpr_mu_unlock(&bs->transport->mu); - } -#endif - } - incoming_byte_stream_unref(bs); -} - -grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing, - grpc_chttp2_stream_parsing *stream_parsing, uint32_t frame_size, - uint32_t flags, grpc_chttp2_incoming_frame_queue *add_to_queue) { - grpc_chttp2_incoming_byte_stream *incoming_byte_stream = - gpr_malloc(sizeof(*incoming_byte_stream)); - incoming_byte_stream->base.length = frame_size; - incoming_byte_stream->base.flags = flags; - incoming_byte_stream->base.next = incoming_byte_stream_next; - incoming_byte_stream->base.destroy = incoming_byte_stream_destroy; - gpr_ref_init(&incoming_byte_stream->refs, 2); - incoming_byte_stream->next_message = NULL; - incoming_byte_stream->transport = TRANSPORT_FROM_PARSING(transport_parsing); - incoming_byte_stream->stream = STREAM_FROM_PARSING(stream_parsing); - gpr_slice_buffer_init(&incoming_byte_stream->slices); - incoming_byte_stream->on_next = NULL; - incoming_byte_stream->is_tail = 1; - incoming_byte_stream->failed = 0; - if (add_to_queue->head == NULL) { - add_to_queue->head = incoming_byte_stream; - } else { - add_to_queue->tail->is_tail = 0; - add_to_queue->tail->next_message = incoming_byte_stream; - } - add_to_queue->tail = incoming_byte_stream; - return incoming_byte_stream; -} - -/******************************************************************************* - * TRACING - */ - -static char *format_flowctl_context_var(const char *context, const char *var, - int64_t val, uint32_t id, - char **scope) { - char *underscore_pos; - char *result; - if (context == NULL) { - *scope = NULL; - gpr_asprintf(&result, "%s(%lld)", var, val); - return result; - } - underscore_pos = strchr(context, '_'); - *scope = gpr_strdup(context); - (*scope)[underscore_pos - context] = 0; - if (id != 0) { - char *tmp = *scope; - gpr_asprintf(scope, "%s[%d]", tmp, id); - gpr_free(tmp); - } - gpr_asprintf(&result, "%s.%s(%lld)", underscore_pos + 1, var, val); - return result; -} - -static int samestr(char *a, char *b) { - if (a == NULL) { - return b == NULL; - } - if (b == NULL) { - return 0; - } - return 0 == strcmp(a, b); -} - -void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase, - grpc_chttp2_flowctl_op op, const char *context1, - const char *var1, const char *context2, - const char *var2, int is_client, - uint32_t stream_id, int64_t val1, int64_t val2) { - char *scope1; - char *scope2; - char *label1 = - format_flowctl_context_var(context1, var1, val1, stream_id, &scope1); - char *label2 = - format_flowctl_context_var(context2, var2, val2, stream_id, &scope2); - char *clisvr = is_client ? "client" : "server"; - char *prefix; - - gpr_asprintf(&prefix, "FLOW % 8s: %s % 11s ", phase, clisvr, scope1); - - switch (op) { - case GRPC_CHTTP2_FLOWCTL_MOVE: - GPR_ASSERT(samestr(scope1, scope2)); - if (val2 != 0) { - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, - "%sMOVE % 40s <- % 40s giving %d", prefix, label1, label2, - val1 + val2); - } - break; - case GRPC_CHTTP2_FLOWCTL_CREDIT: - GPR_ASSERT(val2 >= 0); - if (val2 != 0) { - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, - "%sCREDIT % 40s by % 40s giving %d", prefix, label1, label2, - val1 + val2); - } - break; - case GRPC_CHTTP2_FLOWCTL_DEBIT: - GPR_ASSERT(val2 >= 0); - if (val2 != 0) { - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, - "%sDEBIT % 40s by % 40s giving %d", prefix, label1, label2, - val1 - val2); - } - break; - } - - gpr_free(scope1); - gpr_free(scope2); - gpr_free(label1); - gpr_free(label2); - gpr_free(prefix); -} - -/******************************************************************************* - * INTEGRATION GLUE - */ - -static char *chttp2_get_peer(grpc_exec_ctx *exec_ctx, grpc_transport *t) { - return gpr_strdup(((grpc_chttp2_transport *)t)->peer_string); -} - -static const grpc_transport_vtable vtable = {sizeof(grpc_chttp2_stream), - "chttp2", - init_stream, - set_pollset, - perform_stream_op, - perform_transport_op, - destroy_stream, - destroy_transport, - chttp2_get_peer}; - -grpc_transport *grpc_create_chttp2_transport( - grpc_exec_ctx *exec_ctx, const grpc_channel_args *channel_args, - grpc_endpoint *ep, int is_client) { - grpc_chttp2_transport *t = gpr_malloc(sizeof(grpc_chttp2_transport)); - init_transport(exec_ctx, t, channel_args, ep, is_client != 0); - return &t->base; -} - -void grpc_chttp2_transport_start_reading(grpc_exec_ctx *exec_ctx, - grpc_transport *transport, - gpr_slice *slices, size_t nslices) { - grpc_chttp2_transport *t = (grpc_chttp2_transport *)transport; - REF_TRANSPORT(t, "recv_data"); /* matches unref inside recv_data */ - gpr_slice_buffer_addn(&t->read_buffer, slices, nslices); - recv_data(exec_ctx, t, 1); -} diff --git a/src/core/lib/transport/chttp2_transport.h b/src/core/lib/transport/chttp2_transport.h deleted file mode 100644 index 5008cab7f8..0000000000 --- a/src/core/lib/transport/chttp2_transport.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_TRANSPORT_CHTTP2_TRANSPORT_H -#define GRPC_CORE_LIB_TRANSPORT_CHTTP2_TRANSPORT_H - -#include "src/core/lib/iomgr/endpoint.h" -#include "src/core/lib/transport/transport.h" - -extern int grpc_http_trace; -extern int grpc_flowctl_trace; - -grpc_transport *grpc_create_chttp2_transport( - grpc_exec_ctx *exec_ctx, const grpc_channel_args *channel_args, - grpc_endpoint *ep, int is_client); - -void grpc_chttp2_transport_start_reading(grpc_exec_ctx *exec_ctx, - grpc_transport *transport, - gpr_slice *slices, size_t nslices); - -#endif /* GRPC_CORE_LIB_TRANSPORT_CHTTP2_TRANSPORT_H */ diff --git a/src/core/lib/transport/metadata.c b/src/core/lib/transport/metadata.c index 7605f09991..451c8d1cd3 100644 --- a/src/core/lib/transport/metadata.c +++ b/src/core/lib/transport/metadata.c @@ -44,11 +44,11 @@ #include <grpc/support/string_util.h> #include <grpc/support/time.h> +#include "src/core/ext/transport/chttp2/transport/bin_encoder.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/support/murmur_hash.h" #include "src/core/lib/support/string.h" -#include "src/core/lib/transport/chttp2/bin_encoder.h" #include "src/core/lib/transport/static_metadata.h" /* There are two kinds of mdelem and mdstr instances. |