aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Craig Tiller <ctiller@google.com>2017-04-01 07:42:20 -0700
committerGravatar Craig Tiller <ctiller@google.com>2017-04-01 07:42:20 -0700
commit5f95f1a4caff51459b77b0d6890e396e16617b9e (patch)
tree282c7e47f5a5f1a62964a47473c51472f7df995c /src/core
parentd35bb9ec62992cb01f44316a7267d39f1918149d (diff)
parentbd210c0bff6c8e52f49caa1cbc129359c24e2fbf (diff)
Merge github.com:grpc/grpc into cpparena
Diffstat (limited to 'src/core')
-rw-r--r--src/core/lib/channel/http_client_filter.c2
-rw-r--r--src/core/lib/channel/http_server_filter.c4
-rw-r--r--src/core/lib/channel/max_age_filter.c386
-rw-r--r--src/core/lib/channel/max_age_filter.h39
-rw-r--r--src/core/lib/security/credentials/jwt/json_token.c2
-rw-r--r--src/core/lib/security/credentials/jwt/jwt_verifier.c2
-rw-r--r--src/core/lib/slice/b64.c (renamed from src/core/lib/security/util/b64.c)2
-rw-r--r--src/core/lib/slice/b64.h (renamed from src/core/lib/security/util/b64.h)6
-rw-r--r--src/core/lib/surface/init.c4
9 files changed, 438 insertions, 9 deletions
diff --git a/src/core/lib/channel/http_client_filter.c b/src/core/lib/channel/http_client_filter.c
index 967904df1e..17af2013d9 100644
--- a/src/core/lib/channel/http_client_filter.c
+++ b/src/core/lib/channel/http_client_filter.c
@@ -36,7 +36,7 @@
#include <grpc/support/string_util.h>
#include <string.h>
#include "src/core/lib/profiling/timers.h"
-#include "src/core/lib/security/util/b64.h"
+#include "src/core/lib/slice/b64.h"
#include "src/core/lib/slice/percent_encoding.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
diff --git a/src/core/lib/channel/http_server_filter.c b/src/core/lib/channel/http_server_filter.c
index 8d3c488ea0..df0f95010b 100644
--- a/src/core/lib/channel/http_server_filter.c
+++ b/src/core/lib/channel/http_server_filter.c
@@ -37,7 +37,7 @@
#include <grpc/support/log.h>
#include <string.h>
#include "src/core/lib/profiling/timers.h"
-#include "src/core/lib/security/util/b64.h"
+#include "src/core/lib/slice/b64.h"
#include "src/core/lib/slice/percent_encoding.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
@@ -215,7 +215,7 @@ static grpc_error *server_filter_incoming_metadata(grpc_exec_ctx *exec_ctx,
size_t path_length = GRPC_SLICE_LENGTH(path_slice);
/* offset of the character '?' */
size_t offset = 0;
- for (offset = 0; *path_ptr != k_query_separator && offset < path_length;
+ for (offset = 0; offset < path_length && *path_ptr != k_query_separator;
path_ptr++, offset++)
;
if (offset < path_length) {
diff --git a/src/core/lib/channel/max_age_filter.c b/src/core/lib/channel/max_age_filter.c
new file mode 100644
index 0000000000..c25481486c
--- /dev/null
+++ b/src/core/lib/channel/max_age_filter.c
@@ -0,0 +1,386 @@
+/*
+ *
+ * Copyright 2017, 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/channel/message_size_filter.h"
+
+#include <limits.h>
+#include <string.h>
+
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/transport/http2_errors.h"
+#include "src/core/lib/transport/service_config.h"
+
+#define DEFAULT_MAX_CONNECTION_AGE_MS INT_MAX
+#define DEFAULT_MAX_CONNECTION_AGE_GRACE_MS INT_MAX
+#define DEFAULT_MAX_CONNECTION_IDLE_MS INT_MAX
+
+typedef struct channel_data {
+ /* We take a reference to the channel stack for the timer callback */
+ grpc_channel_stack* channel_stack;
+ /* Guards access to max_age_timer, max_age_timer_pending, max_age_grace_timer
+ and max_age_grace_timer_pending */
+ gpr_mu max_age_timer_mu;
+ /* True if the max_age timer callback is currently pending */
+ bool max_age_timer_pending;
+ /* True if the max_age_grace timer callback is currently pending */
+ bool max_age_grace_timer_pending;
+ /* The timer for checking if the channel has reached its max age */
+ grpc_timer max_age_timer;
+ /* The timer for checking if the max-aged channel has uesed up the grace
+ period */
+ grpc_timer max_age_grace_timer;
+ /* The timer for checking if the channel's idle duration reaches
+ max_connection_idle */
+ grpc_timer max_idle_timer;
+ /* Allowed max time a channel may have no outstanding rpcs */
+ gpr_timespec max_connection_idle;
+ /* Allowed max time a channel may exist */
+ gpr_timespec max_connection_age;
+ /* Allowed grace period after the channel reaches its max age */
+ gpr_timespec max_connection_age_grace;
+ /* Closure to run when the channel's idle duration reaches max_connection_idle
+ and should be closed gracefully */
+ grpc_closure close_max_idle_channel;
+ /* Closure to run when the channel reaches its max age and should be closed
+ gracefully */
+ grpc_closure close_max_age_channel;
+ /* Closure to run the channel uses up its max age grace time and should be
+ closed forcibly */
+ grpc_closure force_close_max_age_channel;
+ /* Closure to run when the init fo channel stack is done and the max_idle
+ timer should be started */
+ grpc_closure start_max_idle_timer_after_init;
+ /* Closure to run when the init fo channel stack is done and the max_age timer
+ should be started */
+ grpc_closure start_max_age_timer_after_init;
+ /* Closure to run when the goaway op is finished and the max_age_timer */
+ grpc_closure start_max_age_grace_timer_after_goaway_op;
+ /* Closure to run when the channel connectivity state changes */
+ grpc_closure channel_connectivity_changed;
+ /* Records the current connectivity state */
+ grpc_connectivity_state connectivity_state;
+ /* Number of active calls */
+ gpr_atm call_count;
+} channel_data;
+
+/* Increase the nubmer of active calls. Before the increasement, if there are no
+ calls, the max_idle_timer should be cancelled. */
+static void increase_call_count(grpc_exec_ctx* exec_ctx, channel_data* chand) {
+ if (gpr_atm_full_fetch_add(&chand->call_count, 1) == 0) {
+ grpc_timer_cancel(exec_ctx, &chand->max_idle_timer);
+ }
+}
+
+/* Decrease the nubmer of active calls. After the decrement, if there are no
+ calls, the max_idle_timer should be started. */
+static void decrease_call_count(grpc_exec_ctx* exec_ctx, channel_data* chand) {
+ if (gpr_atm_full_fetch_add(&chand->call_count, -1) == 1) {
+ GRPC_CHANNEL_STACK_REF(chand->channel_stack, "max_age max_idle_timer");
+ grpc_timer_init(
+ exec_ctx, &chand->max_idle_timer,
+ gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), chand->max_connection_idle),
+ &chand->close_max_idle_channel, gpr_now(GPR_CLOCK_MONOTONIC));
+ }
+}
+
+static void start_max_idle_timer_after_init(grpc_exec_ctx* exec_ctx, void* arg,
+ grpc_error* error) {
+ channel_data* chand = arg;
+ /* Decrease call_count. If there are no active calls at this time,
+ max_idle_timer will start here. If the number of active calls is not 0,
+ max_idle_timer will start after all the active calls end. */
+ decrease_call_count(exec_ctx, chand);
+ GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack,
+ "max_age start_max_idle_timer_after_init");
+}
+
+static void start_max_age_timer_after_init(grpc_exec_ctx* exec_ctx, void* arg,
+ grpc_error* error) {
+ channel_data* chand = arg;
+ gpr_mu_lock(&chand->max_age_timer_mu);
+ chand->max_age_timer_pending = true;
+ GRPC_CHANNEL_STACK_REF(chand->channel_stack, "max_age max_age_timer");
+ grpc_timer_init(
+ exec_ctx, &chand->max_age_timer,
+ gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), chand->max_connection_age),
+ &chand->close_max_age_channel, gpr_now(GPR_CLOCK_MONOTONIC));
+ gpr_mu_unlock(&chand->max_age_timer_mu);
+ grpc_transport_op* op = grpc_make_transport_op(NULL);
+ op->on_connectivity_state_change = &chand->channel_connectivity_changed,
+ op->connectivity_state = &chand->connectivity_state;
+ grpc_channel_next_op(exec_ctx,
+ grpc_channel_stack_element(chand->channel_stack, 0), op);
+ GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack,
+ "max_age start_max_age_timer_after_init");
+}
+
+static void start_max_age_grace_timer_after_goaway_op(grpc_exec_ctx* exec_ctx,
+ void* arg,
+ grpc_error* error) {
+ channel_data* chand = arg;
+ gpr_mu_lock(&chand->max_age_timer_mu);
+ chand->max_age_grace_timer_pending = true;
+ GRPC_CHANNEL_STACK_REF(chand->channel_stack, "max_age max_age_grace_timer");
+ grpc_timer_init(exec_ctx, &chand->max_age_grace_timer,
+ gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
+ chand->max_connection_age_grace),
+ &chand->force_close_max_age_channel,
+ gpr_now(GPR_CLOCK_MONOTONIC));
+ gpr_mu_unlock(&chand->max_age_timer_mu);
+ GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack,
+ "max_age start_max_age_grace_timer_after_goaway_op");
+}
+
+static void close_max_idle_channel(grpc_exec_ctx* exec_ctx, void* arg,
+ grpc_error* error) {
+ channel_data* chand = arg;
+ gpr_atm_no_barrier_fetch_add(&chand->call_count, 1);
+ if (error == GRPC_ERROR_NONE) {
+ grpc_transport_op* op = grpc_make_transport_op(NULL);
+ op->goaway_error =
+ grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("max_idle"),
+ GRPC_ERROR_INT_HTTP2_ERROR, GRPC_HTTP2_NO_ERROR);
+ grpc_channel_element* elem =
+ grpc_channel_stack_element(chand->channel_stack, 0);
+ elem->filter->start_transport_op(exec_ctx, elem, op);
+ } else if (error != GRPC_ERROR_CANCELLED) {
+ GRPC_LOG_IF_ERROR("close_max_idle_channel", error);
+ }
+ GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack,
+ "max_age max_idle_timer");
+}
+
+static void close_max_age_channel(grpc_exec_ctx* exec_ctx, void* arg,
+ grpc_error* error) {
+ channel_data* chand = arg;
+ gpr_mu_lock(&chand->max_age_timer_mu);
+ chand->max_age_timer_pending = false;
+ gpr_mu_unlock(&chand->max_age_timer_mu);
+ if (error == GRPC_ERROR_NONE) {
+ GRPC_CHANNEL_STACK_REF(chand->channel_stack,
+ "max_age start_max_age_grace_timer_after_goaway_op");
+ grpc_transport_op* op = grpc_make_transport_op(
+ &chand->start_max_age_grace_timer_after_goaway_op);
+ op->goaway_error =
+ grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("max_age"),
+ GRPC_ERROR_INT_HTTP2_ERROR, GRPC_HTTP2_NO_ERROR);
+ grpc_channel_element* elem =
+ grpc_channel_stack_element(chand->channel_stack, 0);
+ elem->filter->start_transport_op(exec_ctx, elem, op);
+ } else if (error != GRPC_ERROR_CANCELLED) {
+ GRPC_LOG_IF_ERROR("close_max_age_channel", error);
+ }
+ GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack,
+ "max_age max_age_timer");
+}
+
+static void force_close_max_age_channel(grpc_exec_ctx* exec_ctx, void* arg,
+ grpc_error* error) {
+ channel_data* chand = arg;
+ gpr_mu_lock(&chand->max_age_timer_mu);
+ chand->max_age_grace_timer_pending = false;
+ gpr_mu_unlock(&chand->max_age_timer_mu);
+ if (error == GRPC_ERROR_NONE) {
+ grpc_transport_op* op = grpc_make_transport_op(NULL);
+ op->disconnect_with_error =
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel reaches max age");
+ grpc_channel_element* elem =
+ grpc_channel_stack_element(chand->channel_stack, 0);
+ elem->filter->start_transport_op(exec_ctx, elem, op);
+ } else if (error != GRPC_ERROR_CANCELLED) {
+ GRPC_LOG_IF_ERROR("force_close_max_age_channel", error);
+ }
+ GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack,
+ "max_age max_age_grace_timer");
+}
+
+static void channel_connectivity_changed(grpc_exec_ctx* exec_ctx, void* arg,
+ grpc_error* error) {
+ channel_data* chand = arg;
+ if (chand->connectivity_state != GRPC_CHANNEL_SHUTDOWN) {
+ grpc_transport_op* op = grpc_make_transport_op(NULL);
+ op->on_connectivity_state_change = &chand->channel_connectivity_changed,
+ op->connectivity_state = &chand->connectivity_state;
+ grpc_channel_next_op(
+ exec_ctx, grpc_channel_stack_element(chand->channel_stack, 0), op);
+ } else {
+ gpr_mu_lock(&chand->max_age_timer_mu);
+ if (chand->max_age_timer_pending) {
+ grpc_timer_cancel(exec_ctx, &chand->max_age_timer);
+ chand->max_age_timer_pending = false;
+ }
+ if (chand->max_age_grace_timer_pending) {
+ grpc_timer_cancel(exec_ctx, &chand->max_age_grace_timer);
+ chand->max_age_grace_timer_pending = false;
+ }
+ gpr_mu_unlock(&chand->max_age_timer_mu);
+ /* If there are no active calls, this increasement will cancel
+ max_idle_timer, and prevent max_idle_timer from being started in the
+ future. */
+ increase_call_count(exec_ctx, chand);
+ }
+}
+
+/* Constructor for call_data. */
+static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
+ grpc_call_element* elem,
+ const grpc_call_element_args* args) {
+ channel_data* chand = elem->channel_data;
+ increase_call_count(exec_ctx, chand);
+ return GRPC_ERROR_NONE;
+}
+
+/* Destructor for call_data. */
+static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
+ const grpc_call_final_info* final_info,
+ grpc_closure* ignored) {
+ channel_data* chand = elem->channel_data;
+ decrease_call_count(exec_ctx, chand);
+}
+
+/* Constructor for channel_data. */
+static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx,
+ grpc_channel_element* elem,
+ grpc_channel_element_args* args) {
+ channel_data* chand = elem->channel_data;
+ gpr_mu_init(&chand->max_age_timer_mu);
+ chand->max_age_timer_pending = false;
+ chand->max_age_grace_timer_pending = false;
+ chand->channel_stack = args->channel_stack;
+ chand->max_connection_age =
+ DEFAULT_MAX_CONNECTION_AGE_MS == INT_MAX
+ ? gpr_inf_future(GPR_TIMESPAN)
+ : gpr_time_from_millis(DEFAULT_MAX_CONNECTION_AGE_MS, GPR_TIMESPAN);
+ chand->max_connection_age_grace =
+ DEFAULT_MAX_CONNECTION_AGE_GRACE_MS == INT_MAX
+ ? gpr_inf_future(GPR_TIMESPAN)
+ : gpr_time_from_millis(DEFAULT_MAX_CONNECTION_AGE_GRACE_MS,
+ GPR_TIMESPAN);
+ chand->max_connection_idle =
+ DEFAULT_MAX_CONNECTION_IDLE_MS == INT_MAX
+ ? gpr_inf_future(GPR_TIMESPAN)
+ : gpr_time_from_millis(DEFAULT_MAX_CONNECTION_IDLE_MS, GPR_TIMESPAN);
+ for (size_t i = 0; i < args->channel_args->num_args; ++i) {
+ if (0 == strcmp(args->channel_args->args[i].key,
+ GRPC_ARG_MAX_CONNECTION_AGE_MS)) {
+ const int value = grpc_channel_arg_get_integer(
+ &args->channel_args->args[i],
+ (grpc_integer_options){DEFAULT_MAX_CONNECTION_AGE_MS, 1, INT_MAX});
+ chand->max_connection_age =
+ value == INT_MAX ? gpr_inf_future(GPR_TIMESPAN)
+ : gpr_time_from_millis(value, GPR_TIMESPAN);
+ } else if (0 == strcmp(args->channel_args->args[i].key,
+ GRPC_ARG_MAX_CONNECTION_AGE_GRACE_MS)) {
+ const int value = grpc_channel_arg_get_integer(
+ &args->channel_args->args[i],
+ (grpc_integer_options){DEFAULT_MAX_CONNECTION_AGE_GRACE_MS, 0,
+ INT_MAX});
+ chand->max_connection_age_grace =
+ value == INT_MAX ? gpr_inf_future(GPR_TIMESPAN)
+ : gpr_time_from_millis(value, GPR_TIMESPAN);
+ } else if (0 == strcmp(args->channel_args->args[i].key,
+ GRPC_ARG_MAX_CONNECTION_IDLE_MS)) {
+ const int value = grpc_channel_arg_get_integer(
+ &args->channel_args->args[i],
+ (grpc_integer_options){DEFAULT_MAX_CONNECTION_IDLE_MS, 1, INT_MAX});
+ chand->max_connection_idle =
+ value == INT_MAX ? gpr_inf_future(GPR_TIMESPAN)
+ : gpr_time_from_millis(value, GPR_TIMESPAN);
+ }
+ }
+ grpc_closure_init(&chand->close_max_idle_channel, close_max_idle_channel,
+ chand, grpc_schedule_on_exec_ctx);
+ grpc_closure_init(&chand->close_max_age_channel, close_max_age_channel, chand,
+ grpc_schedule_on_exec_ctx);
+ grpc_closure_init(&chand->force_close_max_age_channel,
+ force_close_max_age_channel, chand,
+ grpc_schedule_on_exec_ctx);
+ grpc_closure_init(&chand->start_max_idle_timer_after_init,
+ start_max_idle_timer_after_init, chand,
+ grpc_schedule_on_exec_ctx);
+ grpc_closure_init(&chand->start_max_age_timer_after_init,
+ start_max_age_timer_after_init, chand,
+ grpc_schedule_on_exec_ctx);
+ grpc_closure_init(&chand->start_max_age_grace_timer_after_goaway_op,
+ start_max_age_grace_timer_after_goaway_op, chand,
+ grpc_schedule_on_exec_ctx);
+ grpc_closure_init(&chand->channel_connectivity_changed,
+ channel_connectivity_changed, chand,
+ grpc_schedule_on_exec_ctx);
+
+ if (gpr_time_cmp(chand->max_connection_age, gpr_inf_future(GPR_TIMESPAN)) !=
+ 0) {
+ /* When the channel reaches its max age, we send down an op with
+ goaway_error set. However, we can't send down any ops until after the
+ channel stack is fully initialized. If we start the timer here, we have
+ no guarantee that the timer won't pop before channel stack initialization
+ is finished. To avoid that problem, we create a closure to start the
+ timer, and we schedule that closure to be run after call stack
+ initialization is done. */
+ GRPC_CHANNEL_STACK_REF(chand->channel_stack,
+ "max_age start_max_age_timer_after_init");
+ grpc_closure_sched(exec_ctx, &chand->start_max_age_timer_after_init,
+ GRPC_ERROR_NONE);
+ }
+
+ /* Initialize the number of calls as 1, so that the max_idle_timer will not
+ start until start_max_idle_timer_after_init is invoked. */
+ gpr_atm_rel_store(&chand->call_count, 1);
+ if (gpr_time_cmp(chand->max_connection_idle, gpr_inf_future(GPR_TIMESPAN)) !=
+ 0) {
+ GRPC_CHANNEL_STACK_REF(chand->channel_stack,
+ "max_age start_max_idle_timer_after_init");
+ grpc_closure_sched(exec_ctx, &chand->start_max_idle_timer_after_init,
+ GRPC_ERROR_NONE);
+ }
+ return GRPC_ERROR_NONE;
+}
+
+/* Destructor for channel_data. */
+static void destroy_channel_elem(grpc_exec_ctx* exec_ctx,
+ grpc_channel_element* elem) {}
+
+const grpc_channel_filter grpc_max_age_filter = {
+ grpc_call_next_op,
+ grpc_channel_next_op,
+ 0, /* sizeof_call_data */
+ init_call_elem,
+ grpc_call_stack_ignore_set_pollset_or_pollset_set,
+ destroy_call_elem,
+ sizeof(channel_data),
+ init_channel_elem,
+ destroy_channel_elem,
+ grpc_call_next_get_peer,
+ grpc_channel_next_get_info,
+ "max_age"};
diff --git a/src/core/lib/channel/max_age_filter.h b/src/core/lib/channel/max_age_filter.h
new file mode 100644
index 0000000000..93e357a88e
--- /dev/null
+++ b/src/core/lib/channel/max_age_filter.h
@@ -0,0 +1,39 @@
+//
+// Copyright 2017, 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_CHANNEL_MAX_AGE_FILTER_H
+#define GRPC_CORE_LIB_CHANNEL_MAX_AGE_FILTER_H
+
+#include "src/core/lib/channel/channel_stack.h"
+
+extern const grpc_channel_filter grpc_max_age_filter;
+
+#endif /* GRPC_CORE_LIB_CHANNEL_MAX_AGE_FILTER_H */
diff --git a/src/core/lib/security/credentials/jwt/json_token.c b/src/core/lib/security/credentials/jwt/json_token.c
index 192a5f47ed..aa905725fc 100644
--- a/src/core/lib/security/credentials/jwt/json_token.c
+++ b/src/core/lib/security/credentials/jwt/json_token.c
@@ -40,8 +40,8 @@
#include <grpc/support/string_util.h>
#include <grpc/support/time.h>
-#include "src/core/lib/security/util/b64.h"
#include "src/core/lib/security/util/json_util.h"
+#include "src/core/lib/slice/b64.h"
#include "src/core/lib/support/string.h"
#include <openssl/bio.h>
diff --git a/src/core/lib/security/credentials/jwt/jwt_verifier.c b/src/core/lib/security/credentials/jwt/jwt_verifier.c
index b10a5da2a2..0e2a264371 100644
--- a/src/core/lib/security/credentials/jwt/jwt_verifier.c
+++ b/src/core/lib/security/credentials/jwt/jwt_verifier.c
@@ -45,7 +45,7 @@
#include "src/core/lib/http/httpcli.h"
#include "src/core/lib/iomgr/polling_entity.h"
-#include "src/core/lib/security/util/b64.h"
+#include "src/core/lib/slice/b64.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/support/string.h"
#include "src/core/tsi/ssl_types.h"
diff --git a/src/core/lib/security/util/b64.c b/src/core/lib/slice/b64.c
index 0d5a917660..2007cc4810 100644
--- a/src/core/lib/security/util/b64.c
+++ b/src/core/lib/slice/b64.c
@@ -31,7 +31,7 @@
*
*/
-#include "src/core/lib/security/util/b64.h"
+#include "src/core/lib/slice/b64.h"
#include <stdint.h>
#include <string.h>
diff --git a/src/core/lib/security/util/b64.h b/src/core/lib/slice/b64.h
index ef52291c6a..5cc821f4bf 100644
--- a/src/core/lib/security/util/b64.h
+++ b/src/core/lib/slice/b64.h
@@ -31,8 +31,8 @@
*
*/
-#ifndef GRPC_CORE_LIB_SECURITY_UTIL_B64_H
-#define GRPC_CORE_LIB_SECURITY_UTIL_B64_H
+#ifndef GRPC_CORE_LIB_SLICE_B64_H
+#define GRPC_CORE_LIB_SLICE_B64_H
#include <grpc/slice.h>
@@ -62,4 +62,4 @@ grpc_slice grpc_base64_decode(grpc_exec_ctx *exec_ctx, const char *b64,
grpc_slice grpc_base64_decode_with_len(grpc_exec_ctx *exec_ctx, const char *b64,
size_t b64_len, int url_safe);
-#endif /* GRPC_CORE_LIB_SECURITY_UTIL_B64_H */
+#endif /* GRPC_CORE_LIB_SLICE_B64_H */
diff --git a/src/core/lib/surface/init.c b/src/core/lib/surface/init.c
index 91bd014a0e..b46ecac18d 100644
--- a/src/core/lib/surface/init.c
+++ b/src/core/lib/surface/init.c
@@ -47,6 +47,7 @@
#include "src/core/lib/channel/handshaker_registry.h"
#include "src/core/lib/channel/http_client_filter.h"
#include "src/core/lib/channel/http_server_filter.h"
+#include "src/core/lib/channel/max_age_filter.h"
#include "src/core/lib/channel/message_size_filter.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/http/parser.h"
@@ -114,6 +115,9 @@ static void register_builtin_channel_init() {
GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, prepend_filter,
(void *)&grpc_server_deadline_filter);
grpc_channel_init_register_stage(
+ GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, prepend_filter,
+ (void *)&grpc_max_age_filter);
+ grpc_channel_init_register_stage(
GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
prepend_filter, (void *)&grpc_message_size_filter);
grpc_channel_init_register_stage(