aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Craig Tiller <ctiller@google.com>2015-02-26 11:23:01 -0800
committerGravatar Craig Tiller <ctiller@google.com>2015-02-26 11:23:01 -0800
commit29f131428272e3b0f5c13d9ec6417f9e3b6dbc9b (patch)
treecda68966326c8350e4385952d7bde9efe4e8ef2e /src/core
parenta348fa8a07c207617874127e110e6b952f447272 (diff)
parentbc53734c2ec3a329b10272f4dceb7612cbdcde7e (diff)
Merge github.com:grpc/grpc into credit
Diffstat (limited to 'src/core')
-rw-r--r--src/core/debug/trace.c2
-rw-r--r--src/core/debug/trace.h3
-rw-r--r--src/core/iomgr/fd_posix.c4
-rw-r--r--src/core/iomgr/pollset.h5
-rw-r--r--src/core/iomgr/pollset_posix.c155
-rw-r--r--src/core/iomgr/pollset_posix.h4
-rw-r--r--src/core/iomgr/pollset_windows.c6
-rw-r--r--src/core/iomgr/resolve_address_posix.c17
-rw-r--r--src/core/security/security_context.c64
-rw-r--r--src/core/statistics/census_init.c2
-rw-r--r--src/core/statistics/census_rpc_stats.c2
-rw-r--r--src/core/statistics/census_tracing.c2
-rw-r--r--src/core/support/cpu_posix.c3
-rw-r--r--src/core/surface/completion_queue.c9
-rw-r--r--src/core/transport/chttp2/frame_settings.c18
-rw-r--r--src/core/transport/chttp2_transport.c46
-rw-r--r--src/core/tsi/ssl_transport_security.c106
-rw-r--r--src/core/tsi/ssl_transport_security.h7
18 files changed, 357 insertions, 98 deletions
diff --git a/src/core/debug/trace.c b/src/core/debug/trace.c
index 92acbe924d..b8eb755bff 100644
--- a/src/core/debug/trace.c
+++ b/src/core/debug/trace.c
@@ -81,6 +81,8 @@ static void parse(const char *s) {
grpc_trace_bits |= GRPC_TRACE_TCP;
} else if (0 == strcmp(s, "secure_endpoint")) {
grpc_trace_bits |= GRPC_TRACE_SECURE_ENDPOINT;
+ } else if (0 == strcmp(s, "http")) {
+ grpc_trace_bits |= GRPC_TRACE_HTTP;
} else if (0 == strcmp(s, "all")) {
grpc_trace_bits = -1;
} else {
diff --git a/src/core/debug/trace.h b/src/core/debug/trace.h
index 167ef3c6ea..bf9b8a3642 100644
--- a/src/core/debug/trace.h
+++ b/src/core/debug/trace.h
@@ -45,7 +45,8 @@ typedef enum {
GRPC_TRACE_SURFACE = 1 << 0,
GRPC_TRACE_CHANNEL = 1 << 1,
GRPC_TRACE_TCP = 1 << 2,
- GRPC_TRACE_SECURE_ENDPOINT = 1 << 3
+ GRPC_TRACE_SECURE_ENDPOINT = 1 << 3,
+ GRPC_TRACE_HTTP = 1 << 4
} grpc_trace_bit_value;
#if GRPC_ENABLE_TRACING
diff --git a/src/core/iomgr/fd_posix.c b/src/core/iomgr/fd_posix.c
index 41fd24e05a..abdd49bbda 100644
--- a/src/core/iomgr/fd_posix.c
+++ b/src/core/iomgr/fd_posix.c
@@ -38,6 +38,7 @@
#include "src/core/iomgr/fd_posix.h"
#include <assert.h>
+#include <sys/socket.h>
#include <unistd.h>
#include "src/core/iomgr/iomgr_internal.h"
@@ -113,6 +114,7 @@ static void ref_by(grpc_fd *fd, int n) {
static void unref_by(grpc_fd *fd, int n) {
gpr_atm old = gpr_atm_full_fetch_add(&fd->refst, -n);
if (old == n) {
+ close(fd->fd);
grpc_iomgr_add_callback(fd->on_done, fd->on_done_user_data);
freelist_fd(fd);
grpc_iomgr_unref();
@@ -158,9 +160,9 @@ static void wake_watchers(grpc_fd *fd) {
void grpc_fd_orphan(grpc_fd *fd, grpc_iomgr_cb_func on_done, void *user_data) {
fd->on_done = on_done ? on_done : do_nothing;
fd->on_done_user_data = user_data;
+ shutdown(fd->fd, SHUT_RDWR);
ref_by(fd, 1); /* remove active status, but keep referenced */
wake_watchers(fd);
- close(fd->fd);
unref_by(fd, 2); /* drop the reference */
}
diff --git a/src/core/iomgr/pollset.h b/src/core/iomgr/pollset.h
index 9d04b014ba..c26947f37c 100644
--- a/src/core/iomgr/pollset.h
+++ b/src/core/iomgr/pollset.h
@@ -52,9 +52,14 @@
#include "src/core/iomgr/pollset_windows.h"
#endif
+
void grpc_pollset_init(grpc_pollset *pollset);
+void grpc_pollset_shutdown(grpc_pollset *pollset,
+ void (*shutdown_done)(void *arg),
+ void *shutdown_done_arg);
void grpc_pollset_destroy(grpc_pollset *pollset);
+
/* Do some work on a pollset.
May involve invoking asynchronous callbacks, or actually polling file
descriptors.
diff --git a/src/core/iomgr/pollset_posix.c b/src/core/iomgr/pollset_posix.c
index 87e7aa85ee..f0a8453fd7 100644
--- a/src/core/iomgr/pollset_posix.c
+++ b/src/core/iomgr/pollset_posix.c
@@ -55,6 +55,7 @@
static grpc_pollset g_backup_pollset;
static int g_shutdown_backup_poller;
static gpr_event g_backup_poller_done;
+static gpr_event g_backup_pollset_shutdown_done;
static void backup_poller(void *p) {
gpr_timespec delta = gpr_time_from_millis(100);
@@ -104,9 +105,14 @@ void grpc_pollset_global_init(void) {
/* start the backup poller thread */
g_shutdown_backup_poller = 0;
gpr_event_init(&g_backup_poller_done);
+ gpr_event_init(&g_backup_pollset_shutdown_done);
gpr_thd_new(&id, backup_poller, NULL, NULL);
}
+static void on_backup_pollset_shutdown_done(void *arg) {
+ gpr_event_set(&g_backup_pollset_shutdown_done, (void *)1);
+}
+
void grpc_pollset_global_shutdown(void) {
/* terminate the backup poller thread */
gpr_mu_lock(&g_backup_pollset.mu);
@@ -114,6 +120,10 @@ void grpc_pollset_global_shutdown(void) {
gpr_mu_unlock(&g_backup_pollset.mu);
gpr_event_wait(&g_backup_poller_done, gpr_inf_future);
+ grpc_pollset_shutdown(&g_backup_pollset, on_backup_pollset_shutdown_done,
+ NULL);
+ gpr_event_wait(&g_backup_pollset_shutdown_done, gpr_inf_future);
+
/* destroy the backup pollset */
grpc_pollset_destroy(&g_backup_pollset);
@@ -130,6 +140,8 @@ void grpc_pollset_init(grpc_pollset *pollset) {
gpr_mu_init(&pollset->mu);
gpr_cv_init(&pollset->cv);
grpc_pollset_kick_init(&pollset->kick_state);
+ pollset->in_flight_cbs = 0;
+ pollset->shutting_down = 0;
become_empty_pollset(pollset);
}
@@ -163,7 +175,24 @@ int grpc_pollset_work(grpc_pollset *pollset, gpr_timespec deadline) {
return pollset->vtable->maybe_work(pollset, deadline, now, 1);
}
+void grpc_pollset_shutdown(grpc_pollset *pollset,
+ void (*shutdown_done)(void *arg),
+ void *shutdown_done_arg) {
+ int in_flight_cbs;
+ gpr_mu_lock(&pollset->mu);
+ pollset->shutting_down = 1;
+ in_flight_cbs = pollset->in_flight_cbs;
+ pollset->shutdown_done_cb = shutdown_done;
+ pollset->shutdown_done_arg = shutdown_done_arg;
+ gpr_mu_unlock(&pollset->mu);
+ if (in_flight_cbs == 0) {
+ shutdown_done(shutdown_done_arg);
+ }
+}
+
void grpc_pollset_destroy(grpc_pollset *pollset) {
+ GPR_ASSERT(pollset->shutting_down);
+ GPR_ASSERT(pollset->in_flight_cbs == 0);
pollset->vtable->destroy(pollset);
grpc_pollset_kick_destroy(&pollset->kick_state);
gpr_mu_destroy(&pollset->mu);
@@ -201,21 +230,119 @@ static void become_empty_pollset(grpc_pollset *pollset) {
* via poll()
*/
+
+typedef struct grpc_unary_promote_args {
+ const grpc_pollset_vtable *original_vtable;
+ grpc_pollset *pollset;
+ grpc_fd *fd;
+} grpc_unary_promote_args;
+
+static void unary_poll_do_promote(void *args, int success) {
+ grpc_unary_promote_args *up_args = args;
+ const grpc_pollset_vtable *original_vtable = up_args->original_vtable;
+ grpc_pollset *pollset = up_args->pollset;
+ grpc_fd *fd = up_args->fd;
+ int do_shutdown_cb = 0;
+ gpr_free(up_args);
+
+ /*
+ * This is quite tricky. There are a number of cases to keep in mind here:
+ * 1. fd may have been orphaned
+ * 2. The pollset may no longer be a unary poller (and we can't let case #1
+ * leak to other pollset types!)
+ * 3. pollset's fd (which may have changed) may have been orphaned
+ * 4. The pollset may be shutting down.
+ */
+
+ gpr_mu_lock(&pollset->mu);
+ /* First we need to ensure that nobody is polling concurrently */
+ while (pollset->counter != 0) {
+ grpc_pollset_kick(pollset);
+ gpr_cv_wait(&pollset->cv, &pollset->mu, gpr_inf_future);
+ }
+ /* At this point the pollset may no longer be a unary poller. In that case
+ * we should just call the right add function and be done. */
+ /* TODO(klempner): If we're not careful this could cause infinite recursion.
+ * That's not a problem for now because empty_pollset has a trivial poller
+ * and we don't have any mechanism to unbecome multipoller. */
+ pollset->in_flight_cbs--;
+ if (pollset->shutting_down) {
+ gpr_log(GPR_INFO, "Shutting down");
+ /* We don't care about this pollset anymore. */
+ if (pollset->in_flight_cbs == 0) {
+ do_shutdown_cb = 1;
+ }
+ } else if (grpc_fd_is_orphaned(fd)) {
+ /* Don't try to add it to anything, we'll drop our ref on it below */
+ } else if (pollset->vtable != original_vtable) {
+ gpr_log(GPR_INFO, "Not original vtable");
+ pollset->vtable->add_fd(pollset, fd);
+ } else if (fd != pollset->data.ptr) {
+ grpc_fd *fds[2];
+ fds[0] = pollset->data.ptr;
+ fds[1] = fd;
+
+ if (!grpc_fd_is_orphaned(fds[0])) {
+ grpc_platform_become_multipoller(pollset, fds, GPR_ARRAY_SIZE(fds));
+ grpc_fd_unref(fds[0]);
+ } else {
+ /* old fd is orphaned and we haven't cleaned it up until now, so remain a
+ * unary poller */
+ /* Note that it is possible that fds[1] is also orphaned at this point.
+ * That's okay, we'll correct it at the next add or poll. */
+ grpc_fd_unref(fds[0]);
+ pollset->data.ptr = fd;
+ grpc_fd_ref(fd);
+ }
+ }
+
+ gpr_cv_broadcast(&pollset->cv);
+ gpr_mu_unlock(&pollset->mu);
+
+ if (do_shutdown_cb) {
+ pollset->shutdown_done_cb(pollset->shutdown_done_arg);
+ }
+
+ /* Matching ref in unary_poll_pollset_add_fd */
+ grpc_fd_unref(fd);
+}
+
static void unary_poll_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd) {
- grpc_fd *fds[2];
+ grpc_unary_promote_args *up_args;
if (fd == pollset->data.ptr) return;
- fds[0] = pollset->data.ptr;
- fds[1] = fd;
- if (!grpc_fd_is_orphaned(fds[0])) {
- grpc_platform_become_multipoller(pollset, fds, GPR_ARRAY_SIZE(fds));
- grpc_fd_unref(fds[0]);
- } else {
- /* old fd is orphaned and we haven't cleaned it up until now, so remain a
- * unary poller */
- grpc_fd_unref(fds[0]);
- pollset->data.ptr = fd;
- grpc_fd_ref(fd);
+
+ if (!pollset->counter) {
+ /* Fast path -- no in flight cbs */
+ /* TODO(klempner): Comment this out and fix any test failures or establish
+ * they are due to timing issues */
+ grpc_fd *fds[2];
+ fds[0] = pollset->data.ptr;
+ fds[1] = fd;
+
+ if (!grpc_fd_is_orphaned(fds[0])) {
+ grpc_platform_become_multipoller(pollset, fds, GPR_ARRAY_SIZE(fds));
+ grpc_fd_unref(fds[0]);
+ } else {
+ /* old fd is orphaned and we haven't cleaned it up until now, so remain a
+ * unary poller */
+ grpc_fd_unref(fds[0]);
+ pollset->data.ptr = fd;
+ grpc_fd_ref(fd);
+ }
+ return;
}
+
+ /* Now we need to promote. This needs to happen when we're not polling. Since
+ * this may be called from poll, the wait needs to happen asynchronously. */
+ grpc_fd_ref(fd);
+ pollset->in_flight_cbs++;
+ up_args = gpr_malloc(sizeof(*up_args));
+ up_args->pollset = pollset;
+ up_args->fd = fd;
+ up_args->original_vtable = pollset->vtable;
+ grpc_iomgr_add_callback(unary_poll_do_promote, up_args);
+
+ grpc_pollset_kick(pollset);
}
static void unary_poll_pollset_del_fd(grpc_pollset *pollset, grpc_fd *fd) {
@@ -238,6 +365,10 @@ static int unary_poll_pollset_maybe_work(grpc_pollset *pollset,
if (pollset->counter) {
return 0;
}
+ if (pollset->in_flight_cbs) {
+ /* Give do_promote priority so we don't starve it out */
+ return 0;
+ }
fd = pollset->data.ptr;
if (grpc_fd_is_orphaned(fd)) {
grpc_fd_unref(fd);
diff --git a/src/core/iomgr/pollset_posix.h b/src/core/iomgr/pollset_posix.h
index 03b4c775b7..86b6c9f20e 100644
--- a/src/core/iomgr/pollset_posix.h
+++ b/src/core/iomgr/pollset_posix.h
@@ -55,6 +55,10 @@ typedef struct grpc_pollset {
gpr_cv cv;
grpc_pollset_kick_state kick_state;
int counter;
+ int in_flight_cbs;
+ int shutting_down;
+ void (*shutdown_done_cb)(void *arg);
+ void *shutdown_done_arg;
union {
int fd;
void *ptr;
diff --git a/src/core/iomgr/pollset_windows.c b/src/core/iomgr/pollset_windows.c
index d21072b283..bea6711611 100644
--- a/src/core/iomgr/pollset_windows.c
+++ b/src/core/iomgr/pollset_windows.c
@@ -46,6 +46,12 @@ void grpc_pollset_init(grpc_pollset *pollset) {
gpr_cv_init(&pollset->cv);
}
+void grpc_pollset_shutdown(grpc_pollset *pollset,
+ void (*shutdown_done)(void *arg),
+ void *shutdown_done_arg) {
+ shutdown_done(shutdown_done_arg);
+}
+
void grpc_pollset_destroy(grpc_pollset *pollset) {
gpr_mu_destroy(&pollset->mu);
gpr_cv_destroy(&pollset->cv);
diff --git a/src/core/iomgr/resolve_address_posix.c b/src/core/iomgr/resolve_address_posix.c
index edf40b5ad1..989b968ae2 100644
--- a/src/core/iomgr/resolve_address_posix.c
+++ b/src/core/iomgr/resolve_address_posix.c
@@ -66,7 +66,6 @@ grpc_resolved_addresses *grpc_blocking_resolve_address(
int s;
size_t i;
grpc_resolved_addresses *addrs = NULL;
- const gpr_timespec start_time = gpr_now();
struct sockaddr_un *un;
if (name[0] == 'u' && name[1] == 'n' && name[2] == 'i' && name[3] == 'x' &&
@@ -121,22 +120,6 @@ grpc_resolved_addresses *grpc_blocking_resolve_address(
i++;
}
- /* Temporary logging, to help identify flakiness in dualstack_socket_test. */
- {
- const gpr_timespec delay = gpr_time_sub(gpr_now(), start_time);
- const int delay_ms =
- delay.tv_sec * GPR_MS_PER_SEC + delay.tv_nsec / GPR_NS_PER_MS;
- gpr_log(GPR_INFO, "logspam: getaddrinfo(%s, %s) resolved %d addrs in %dms:",
- host, port, addrs->naddrs, delay_ms);
- for (i = 0; i < addrs->naddrs; i++) {
- char *buf;
- grpc_sockaddr_to_string(&buf, (struct sockaddr *)&addrs->addrs[i].addr,
- 0);
- gpr_log(GPR_INFO, "logspam: [%d] %s", i, buf);
- gpr_free(buf);
- }
- }
-
done:
gpr_free(host);
gpr_free(port);
diff --git a/src/core/security/security_context.c b/src/core/security/security_context.c
index 0a65480b2f..62264e4105 100644
--- a/src/core/security/security_context.c
+++ b/src/core/security/security_context.c
@@ -43,7 +43,9 @@
#include "src/core/support/file.h"
#include "src/core/support/string.h"
#include "src/core/transport/chttp2/alpn.h"
+
#include <grpc/support/alloc.h>
+#include <grpc/support/host_port.h>
#include <grpc/support/log.h>
#include <grpc/support/slice_buffer.h>
#include "src/core/tsi/fake_transport_security.h"
@@ -51,20 +53,33 @@
/* -- Constants. -- */
-/* Defines the cipher suites that we accept. All these cipher suites are
- compliant with TLS 1.2 and use an RSA public key. We prefer GCM over CBC
- and ECDHE-RSA over just RSA. */
-#define GRPC_SSL_CIPHER_SUITES \
- "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:AES128-GCM-SHA256:" \
- "AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-" \
- "SHA256:AES256-SHA256"
-
#ifndef INSTALL_PREFIX
static const char *installed_roots_path = "/usr/share/grpc/roots.pem";
#else
static const char *installed_roots_path = INSTALL_PREFIX "/share/grpc/roots.pem";
#endif
+/* -- Cipher suites. -- */
+
+/* Defines the cipher suites that we accept by default. All these cipher suites
+ are compliant with HTTP2. */
+#define GRPC_SSL_CIPHER_SUITES \
+ "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-" \
+ "SHA384:ECDHE-RSA-AES256-GCM-SHA384"
+
+static gpr_once cipher_suites_once = GPR_ONCE_INIT;
+static const char *cipher_suites = NULL;
+
+static void init_cipher_suites(void) {
+ char *overridden = gpr_getenv("GRPC_SSL_CIPHER_SUITES");
+ cipher_suites = overridden != NULL ? overridden : GRPC_SSL_CIPHER_SUITES;
+}
+
+static const char *ssl_cipher_suites(void) {
+ gpr_once_init(&cipher_suites_once, init_cipher_suites);
+ return cipher_suites;
+}
+
/* -- Common methods. -- */
grpc_security_status grpc_security_context_create_handshaker(
@@ -322,6 +337,24 @@ static grpc_security_status ssl_server_create_handshaker(
return ssl_create_handshaker(c->handshaker_factory, 0, NULL, handshaker);
}
+static int ssl_host_matches_name(const tsi_peer *peer,
+ const char *peer_name) {
+ char *allocated_name = NULL;
+ int r;
+
+ if (strchr(peer_name, ':') != NULL) {
+ char *ignored_port;
+ gpr_split_host_port(peer_name, &allocated_name, &ignored_port);
+ gpr_free(ignored_port);
+ peer_name = allocated_name;
+ if (!peer_name) return 0;
+ }
+
+ r = tsi_ssl_peer_matches_name(peer, peer_name);
+ gpr_free(allocated_name);
+ return r;
+}
+
static grpc_security_status ssl_check_peer(const char *peer_name,
const tsi_peer *peer) {
/* Check the ALPN. */
@@ -343,10 +376,11 @@ static grpc_security_status ssl_check_peer(const char *peer_name,
/* Check the peer name if specified. */
if (peer_name != NULL &&
- !tsi_ssl_peer_matches_name(peer, peer_name)) {
+ !ssl_host_matches_name(peer, peer_name)) {
gpr_log(GPR_ERROR, "Peer name %s is not in peer certificate", peer_name);
return GRPC_SECURITY_ERROR;
}
+
return GRPC_SECURITY_OK;
}
@@ -382,7 +416,7 @@ static grpc_security_status ssl_channel_check_call_host(
grpc_ssl_channel_security_context *c =
(grpc_ssl_channel_security_context *)ctx;
- if (tsi_ssl_peer_matches_name(&c->peer, host)) return GRPC_SECURITY_OK;
+ if (ssl_host_matches_name(&c->peer, host)) return GRPC_SECURITY_OK;
/* If the target name was overridden, then the original target_name was
'checked' transitively during the previous peer check at the end of the
@@ -442,6 +476,7 @@ grpc_security_status grpc_ssl_channel_security_context_create(
size_t i;
const unsigned char *pem_root_certs;
size_t pem_root_certs_size;
+ char *port;
for (i = 0; i < num_alpn_protocols; i++) {
alpn_protocol_strings[i] =
@@ -467,9 +502,8 @@ grpc_security_status grpc_ssl_channel_security_context_create(
c->base.base.url_scheme = GRPC_SSL_URL_SCHEME;
c->base.request_metadata_creds = grpc_credentials_ref(request_metadata_creds);
c->base.check_call_host = ssl_channel_check_call_host;
- if (target_name != NULL) {
- c->target_name = gpr_strdup(target_name);
- }
+ gpr_split_host_port(target_name, &c->target_name, &port);
+ gpr_free(port);
if (overridden_target_name != NULL) {
c->overridden_target_name = gpr_strdup(overridden_target_name);
}
@@ -486,7 +520,7 @@ grpc_security_status grpc_ssl_channel_security_context_create(
result = tsi_create_ssl_client_handshaker_factory(
config->pem_private_key, config->pem_private_key_size,
config->pem_cert_chain, config->pem_cert_chain_size, pem_root_certs,
- pem_root_certs_size, GRPC_SSL_CIPHER_SUITES, alpn_protocol_strings,
+ pem_root_certs_size, ssl_cipher_suites(), alpn_protocol_strings,
alpn_protocol_string_lengths, num_alpn_protocols, &c->handshaker_factory);
if (result != TSI_OK) {
gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
@@ -540,7 +574,7 @@ grpc_security_status grpc_ssl_server_security_context_create(
(const unsigned char **)config->pem_cert_chains,
config->pem_cert_chains_sizes, config->num_key_cert_pairs,
config->pem_root_certs, config->pem_root_certs_size,
- GRPC_SSL_CIPHER_SUITES, alpn_protocol_strings,
+ ssl_cipher_suites(), alpn_protocol_strings,
alpn_protocol_string_lengths, num_alpn_protocols, &c->handshaker_factory);
if (result != TSI_OK) {
gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
diff --git a/src/core/statistics/census_init.c b/src/core/statistics/census_init.c
index 820d75f795..e6306f5e6f 100644
--- a/src/core/statistics/census_init.c
+++ b/src/core/statistics/census_init.c
@@ -38,13 +38,11 @@
#include "src/core/statistics/census_tracing.h"
void census_init(void) {
- gpr_log(GPR_INFO, "Initialize census library.");
census_tracing_init();
census_stats_store_init();
}
void census_shutdown(void) {
- gpr_log(GPR_INFO, "Shutdown census library.");
census_stats_store_shutdown();
census_tracing_shutdown();
}
diff --git a/src/core/statistics/census_rpc_stats.c b/src/core/statistics/census_rpc_stats.c
index 388ce4fe2c..0491c91947 100644
--- a/src/core/statistics/census_rpc_stats.c
+++ b/src/core/statistics/census_rpc_stats.c
@@ -222,7 +222,6 @@ void census_get_server_stats(census_aggregated_rpc_stats* data) {
}
void census_stats_store_init(void) {
- gpr_log(GPR_INFO, "Initialize census stats store.");
init_mutex_once();
gpr_mu_lock(&g_mu);
if (g_client_stats_store == NULL && g_server_stats_store == NULL) {
@@ -235,7 +234,6 @@ void census_stats_store_init(void) {
}
void census_stats_store_shutdown(void) {
- gpr_log(GPR_INFO, "Shutdown census stats store.");
init_mutex_once();
gpr_mu_lock(&g_mu);
if (g_client_stats_store != NULL) {
diff --git a/src/core/statistics/census_tracing.c b/src/core/statistics/census_tracing.c
index adfcbecb4c..05e72b99c0 100644
--- a/src/core/statistics/census_tracing.c
+++ b/src/core/statistics/census_tracing.c
@@ -154,7 +154,6 @@ void census_tracing_end_op(census_op_id op_id) {
}
void census_tracing_init(void) {
- gpr_log(GPR_INFO, "Initialize census trace store.");
init_mutex_once();
gpr_mu_lock(&g_mu);
if (g_trace_store == NULL) {
@@ -167,7 +166,6 @@ void census_tracing_init(void) {
}
void census_tracing_shutdown(void) {
- gpr_log(GPR_INFO, "Shutdown census trace store.");
gpr_mu_lock(&g_mu);
if (g_trace_store != NULL) {
census_ht_destroy(g_trace_store);
diff --git a/src/core/support/cpu_posix.c b/src/core/support/cpu_posix.c
index 33c7b90b0b..5f45fb0bc3 100644
--- a/src/core/support/cpu_posix.c
+++ b/src/core/support/cpu_posix.c
@@ -40,6 +40,7 @@
#include <string.h>
#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
static __thread char magic_thread_local;
@@ -55,7 +56,7 @@ static void init_ncpus() {
unsigned gpr_cpu_num_cores(void) {
static gpr_once once = GPR_ONCE_INIT;
- gpr_once_init(&once, init_num_cpus);
+ gpr_once_init(&once, init_ncpus);
return ncpus;
}
diff --git a/src/core/surface/completion_queue.c b/src/core/surface/completion_queue.c
index 2efc084d7b..c4b8d60782 100644
--- a/src/core/surface/completion_queue.c
+++ b/src/core/surface/completion_queue.c
@@ -389,12 +389,17 @@ void grpc_completion_queue_shutdown(grpc_completion_queue *cc) {
}
}
-void grpc_completion_queue_destroy(grpc_completion_queue *cc) {
- GPR_ASSERT(cc->queue == NULL);
+static void on_pollset_destroy_done(void *arg) {
+ grpc_completion_queue *cc = arg;
grpc_pollset_destroy(&cc->pollset);
gpr_free(cc);
}
+void grpc_completion_queue_destroy(grpc_completion_queue *cc) {
+ GPR_ASSERT(cc->queue == NULL);
+ grpc_pollset_shutdown(&cc->pollset, on_pollset_destroy_done, cc);
+}
+
void grpc_event_finish(grpc_event *base) {
event *ev = (event *)base;
ev->on_finish(ev->on_finish_user_data, GRPC_OP_OK);
diff --git a/src/core/transport/chttp2/frame_settings.c b/src/core/transport/chttp2/frame_settings.c
index 06429e220b..e6c4b7e38f 100644
--- a/src/core/transport/chttp2/frame_settings.c
+++ b/src/core/transport/chttp2/frame_settings.c
@@ -35,6 +35,7 @@
#include <string.h>
+#include "src/core/debug/trace.h"
#include "src/core/transport/chttp2/frame.h"
#include <grpc/support/log.h>
#include <grpc/support/useful.h>
@@ -53,7 +54,8 @@ const grpc_chttp2_setting_parameters
{"MAX_FRAME_SIZE", 16384, 16384, 16777215,
GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE},
{"MAX_HEADER_LIST_SIZE", 0xffffffffu, 0, 0xffffffffu,
- GRPC_CHTTP2_CLAMP_INVALID_VALUE}, };
+ GRPC_CHTTP2_CLAMP_INVALID_VALUE},
+};
static gpr_uint8 *fill_header(gpr_uint8 *out, gpr_uint32 length,
gpr_uint8 flags) {
@@ -155,7 +157,7 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
}
return GRPC_CHTTP2_PARSE_OK;
}
- parser->id = ((gpr_uint16) * cur) << 8;
+ parser->id = ((gpr_uint16)*cur) << 8;
cur++;
/* fallthrough */
case GRPC_CHTTP2_SPS_ID1:
@@ -171,7 +173,7 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
parser->state = GRPC_CHTTP2_SPS_VAL0;
return GRPC_CHTTP2_PARSE_OK;
}
- parser->value = ((gpr_uint32) * cur) << 24;
+ parser->value = ((gpr_uint32)*cur) << 24;
cur++;
/* fallthrough */
case GRPC_CHTTP2_SPS_VAL1:
@@ -179,7 +181,7 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
parser->state = GRPC_CHTTP2_SPS_VAL1;
return GRPC_CHTTP2_PARSE_OK;
}
- parser->value |= ((gpr_uint32) * cur) << 16;
+ parser->value |= ((gpr_uint32)*cur) << 16;
cur++;
/* fallthrough */
case GRPC_CHTTP2_SPS_VAL2:
@@ -187,7 +189,7 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
parser->state = GRPC_CHTTP2_SPS_VAL2;
return GRPC_CHTTP2_PARSE_OK;
}
- parser->value |= ((gpr_uint32) * cur) << 8;
+ parser->value |= ((gpr_uint32)*cur) << 8;
cur++;
/* fallthrough */
case GRPC_CHTTP2_SPS_VAL3:
@@ -216,8 +218,10 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
}
}
parser->incoming_settings[parser->id] = parser->value;
- gpr_log(GPR_DEBUG, "CHTTP2: got setting %d = %d", parser->id,
- parser->value);
+ if (grpc_trace_bits & GRPC_TRACE_HTTP) {
+ gpr_log(GPR_DEBUG, "CHTTP2: got setting %d = %d", parser->id,
+ parser->value);
+ }
} else {
gpr_log(GPR_ERROR, "CHTTP2: Ignoring unknown setting %d (value %d)",
parser->id, parser->value);
diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c
index ccd8d0c376..476cc4b226 100644
--- a/src/core/transport/chttp2_transport.c
+++ b/src/core/transport/chttp2_transport.c
@@ -37,6 +37,7 @@
#include <stdio.h>
#include <string.h>
+#include "src/core/debug/trace.h"
#include "src/core/support/string.h"
#include "src/core/transport/chttp2/frame_data.h"
#include "src/core/transport/chttp2/frame_goaway.h"
@@ -66,6 +67,12 @@
typedef struct transport transport;
typedef struct stream stream;
+#define IF_TRACING(stmt) \
+ if (!(grpc_trace_bits & GRPC_TRACE_HTTP)) \
+ ; \
+ else \
+ stmt
+
/* streams are kept in various linked lists depending on what things need to
happen to them... this enum labels each list */
typedef enum {
@@ -301,7 +308,7 @@ static void push_setting(transport *t, grpc_chttp2_setting_id id,
gpr_uint32 value);
static int prepare_callbacks(transport *t);
-static void run_callbacks(transport *t);
+static void run_callbacks(transport *t, const grpc_transport_callbacks *cb);
static int prepare_write(transport *t);
static void perform_write(transport *t, grpc_endpoint *ep);
@@ -552,7 +559,7 @@ static int init_stream(grpc_transport *gt, grpc_stream *gs,
lock(t);
s->id = 0;
} else {
- s->id = (gpr_uint32)(gpr_uintptr)server_data;
+ s->id = (gpr_uint32)(gpr_uintptr) server_data;
t->incoming_stream = s;
grpc_chttp2_stream_map_add(&t->stream_map, s->id, s);
}
@@ -706,6 +713,7 @@ static void unlock(transport *t) {
pending_goaway *goaways = NULL;
grpc_endpoint *ep = t->ep;
grpc_stream_op_buffer nuke_now;
+ const grpc_transport_callbacks *cb = t->cb;
grpc_sopb_init(&nuke_now);
if (t->nuke_later_sopb.nops) {
@@ -725,7 +733,7 @@ static void unlock(transport *t) {
}
/* gather any callbacks that need to be made */
- if (!t->calling_back && t->cb) {
+ if (!t->calling_back && cb) {
perform_callbacks = prepare_callbacks(t);
if (perform_callbacks) {
t->calling_back = 1;
@@ -733,6 +741,7 @@ static void unlock(transport *t) {
if (t->error_state == ERROR_STATE_SEEN) {
call_closed = 1;
t->calling_back = 1;
+ t->cb = NULL; /* no more callbacks */
t->error_state = ERROR_STATE_NOTIFIED;
}
if (t->num_pending_goaways) {
@@ -754,16 +763,16 @@ static void unlock(transport *t) {
/* perform some callbacks if necessary */
for (i = 0; i < num_goaways; i++) {
- t->cb->goaway(t->cb_user_data, &t->base, goaways[i].status,
- goaways[i].debug);
+ cb->goaway(t->cb_user_data, &t->base, goaways[i].status,
+ goaways[i].debug);
}
if (perform_callbacks) {
- run_callbacks(t);
+ run_callbacks(t, cb);
}
if (call_closed) {
- t->cb->closed(t->cb_user_data, &t->base);
+ cb->closed(t->cb_user_data, &t->base);
}
/* write some bytes if necessary */
@@ -1206,6 +1215,11 @@ static void on_header(void *tp, grpc_mdelem *md) {
stream *s = t->incoming_stream;
GPR_ASSERT(s);
+
+ IF_TRACING(gpr_log(GPR_INFO, "HTTP:%d:HDR: %s: %s", s->id,
+ grpc_mdstr_as_c_string(md->key),
+ grpc_mdstr_as_c_string(md->value)));
+
stream_list_join(t, s, PENDING_CALLBACKS);
if (md->key == t->str_grpc_timeout) {
gpr_timespec *cached_timeout = grpc_mdelem_get_user_data(md, free_timeout);
@@ -1269,7 +1283,7 @@ static int init_header_frame_parser(transport *t, int is_continuation) {
t->incoming_stream = NULL;
/* if stream is accepted, we set incoming_stream in init_stream */
t->cb->accept_stream(t->cb_user_data, &t->base,
- (void *)(gpr_uintptr)t->incoming_stream_id);
+ (void *)(gpr_uintptr) t->incoming_stream_id);
s = t->incoming_stream;
if (!s) {
gpr_log(GPR_ERROR, "stream not accepted");
@@ -1534,8 +1548,8 @@ static int process_read(transport *t, gpr_slice slice) {
"Connect string mismatch: expected '%c' (%d) got '%c' (%d) "
"at byte %d",
CLIENT_CONNECT_STRING[t->deframe_state],
- (int)(gpr_uint8)CLIENT_CONNECT_STRING[t->deframe_state], *cur,
- (int)*cur, t->deframe_state);
+ (int)(gpr_uint8) CLIENT_CONNECT_STRING[t->deframe_state],
+ *cur, (int)*cur, t->deframe_state);
drop_connection(t);
return 0;
}
@@ -1741,13 +1755,13 @@ static int prepare_callbacks(transport *t) {
return n;
}
-static void run_callbacks(transport *t) {
+static void run_callbacks(transport *t, const grpc_transport_callbacks *cb) {
stream *s;
while ((s = stream_list_remove_head(t, EXECUTING_CALLBACKS))) {
size_t nops = s->callback_sopb.nops;
s->callback_sopb.nops = 0;
- t->cb->recv_batch(t->cb_user_data, &t->base, (grpc_stream *)s,
- s->callback_sopb.ops, nops, s->callback_state);
+ cb->recv_batch(t->cb_user_data, &t->base, (grpc_stream *)s,
+ s->callback_sopb.ops, nops, s->callback_state);
}
}
@@ -1765,9 +1779,9 @@ static void add_to_pollset(grpc_transport *gt, grpc_pollset *pollset) {
*/
static const grpc_transport_vtable vtable = {
- sizeof(stream), init_stream, send_batch, set_allow_window_updates,
- add_to_pollset, destroy_stream, abort_stream, goaway, close_transport,
- send_ping, destroy_transport};
+ sizeof(stream), init_stream, send_batch, set_allow_window_updates,
+ add_to_pollset, destroy_stream, abort_stream, goaway,
+ close_transport, send_ping, destroy_transport};
void grpc_create_chttp2_transport(grpc_transport_setup_callback setup,
void *arg,
diff --git a/src/core/tsi/ssl_transport_security.c b/src/core/tsi/ssl_transport_security.c
index 85b0922a43..8446cc4fdc 100644
--- a/src/core/tsi/ssl_transport_security.c
+++ b/src/core/tsi/ssl_transport_security.c
@@ -180,6 +180,30 @@ static void ssl_info_callback(const SSL* ssl, int where, int ret) {
ssl_log_where_info(ssl, where, SSL_CB_HANDSHAKE_DONE, "HANDSHAKE DONE");
}
+/* Returns 1 if name looks like an IP address, 0 otherwise.
+ This is a very rough heuristic as it does not handle IPV6 or things like:
+ 0300.0250.00.01, 0xC0.0Xa8.0x0.0x1, 000030052000001, 0xc0.052000001 */
+static int looks_like_ip_address(const char *name) {
+ size_t i;
+ size_t dot_count = 0;
+ size_t num_size = 0;
+ for (i = 0; i < strlen(name); i++) {
+ if (name[i] >= '0' && name[i] <= '9') {
+ if (num_size > 3) return 0;
+ num_size++;
+ } else if (name[i] == '.') {
+ if (dot_count > 3 || num_size == 0) return 0;
+ dot_count++;
+ num_size = 0;
+ } else {
+ return 0;
+ }
+ }
+ if (dot_count < 3 || num_size == 0) return 0;
+ return 1;
+}
+
+
/* Gets the subject CN from an X509 cert. */
static tsi_result ssl_get_x509_common_name(X509* cert, unsigned char** utf8,
size_t* utf8_size) {
@@ -226,10 +250,18 @@ static tsi_result peer_property_from_x509_common_name(
size_t common_name_size;
tsi_result result =
ssl_get_x509_common_name(cert, &common_name, &common_name_size);
- if (result != TSI_OK) return result;
+ if (result != TSI_OK) {
+ if (result == TSI_NOT_FOUND) {
+ common_name = NULL;
+ common_name_size = 0;
+ } else {
+ return result;
+ }
+ }
result = tsi_construct_string_peer_property(
- TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, (const char*)common_name,
- common_name_size, property);
+ TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY,
+ common_name == NULL ? "" : (const char*)common_name, common_name_size,
+ property);
OPENSSL_free(common_name);
return result;
}
@@ -1036,9 +1068,22 @@ static void ssl_server_handshaker_factory_destroy(
static int does_entry_match_name(const char* entry, size_t entry_length,
const char* name) {
+ const char *dot;
const char* name_subdomain = NULL;
+ size_t name_length = strlen(name);
+ size_t name_subdomain_length;
if (entry_length == 0) return 0;
- if (!strncmp(name, entry, entry_length) && (strlen(name) == entry_length)) {
+
+ /* Take care of '.' terminations. */
+ if (name[name_length - 1] == '.') {
+ name_length--;
+ }
+ if (entry[entry_length - 1] == '.') {
+ entry_length--;
+ if (entry_length == 0) return 0;
+ }
+
+ if ((name_length == entry_length) && !strncmp(name, entry, entry_length)) {
return 1; /* Perfect match. */
}
if (entry[0] != '*') return 0;
@@ -1049,18 +1094,29 @@ static int does_entry_match_name(const char* entry, size_t entry_length,
return 0;
}
name_subdomain = strchr(name, '.');
- if (name_subdomain == NULL || strlen(name_subdomain) < 2) return 0;
+ if (name_subdomain == NULL) return 0;
+ name_subdomain_length = strlen(name_subdomain);
+ if (name_subdomain_length < 2) return 0;
name_subdomain++; /* Starts after the dot. */
+ name_subdomain_length--;
entry += 2; /* Remove *. */
entry_length -= 2;
- return (!strncmp(entry, name_subdomain, entry_length) &&
- (strlen(name_subdomain) == entry_length));
+ dot = strchr(name_subdomain, '.');
+ if ((dot == NULL) || (dot == &name_subdomain[name_subdomain_length - 1])) {
+ gpr_log(GPR_ERROR, "Invalid toplevel subdomain: %s", name_subdomain);
+ return 0;
+ }
+ if (name_subdomain[name_subdomain_length - 1] == '.') {
+ name_subdomain_length--;
+ }
+ return ((entry_length > 0) && (name_subdomain_length == entry_length) &&
+ !strncmp(entry, name_subdomain, entry_length));
}
static int ssl_server_handshaker_factory_servername_callback(SSL* ssl, int* ap,
void* arg) {
tsi_ssl_server_handshaker_factory* impl =
- (tsi_ssl_server_handshaker_factory*)arg;
+ (tsi_ssl_server_handshaker_factory*)arg;
size_t i = 0;
const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
if (servername == NULL || strlen(servername) == 0) {
@@ -1283,17 +1339,13 @@ tsi_result tsi_create_ssl_server_handshaker_factory(
int tsi_ssl_peer_matches_name(const tsi_peer* peer, const char* name) {
size_t i = 0;
- const tsi_peer_property* property = tsi_peer_get_property_by_name(
- peer, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY);
- if (property == NULL || property->type != TSI_PEER_PROPERTY_TYPE_STRING) {
- gpr_log(GPR_ERROR, "Invalid x509 subject common name property.");
- return 0;
- }
- if (does_entry_match_name(property->value.string.data,
- property->value.string.length, name)) {
- return 1;
- }
+ size_t san_count = 0;
+ const tsi_peer_property* property = NULL;
+ /* For now reject what looks like an IP address. */
+ if (looks_like_ip_address(name)) return 0;
+
+ /* Check the SAN first. */
property = tsi_peer_get_property_by_name(
peer, TSI_X509_SUBJECT_ALTERNATIVE_NAMES_PEER_PROPERTY);
if (property == NULL || property->type != TSI_PEER_PROPERTY_TYPE_LIST) {
@@ -1301,7 +1353,8 @@ int tsi_ssl_peer_matches_name(const tsi_peer* peer, const char* name) {
return 0;
}
- for (i = 0; i < property->value.list.child_count; i++) {
+ san_count = property->value.list.child_count;
+ for (i = 0; i < san_count; i++) {
const tsi_peer_property* alt_name_property =
&property->value.list.children[i];
if (alt_name_property->type != TSI_PEER_PROPERTY_TYPE_STRING) {
@@ -1313,5 +1366,20 @@ int tsi_ssl_peer_matches_name(const tsi_peer* peer, const char* name) {
return 1;
}
}
+
+ /* If there's no SAN, try the CN. */
+ if (san_count == 0) {
+ property = tsi_peer_get_property_by_name(
+ peer, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY);
+ if (property == NULL || property->type != TSI_PEER_PROPERTY_TYPE_STRING) {
+ gpr_log(GPR_ERROR, "Invalid x509 subject common name property.");
+ return 0;
+ }
+ if (does_entry_match_name(property->value.string.data,
+ property->value.string.length, name)) {
+ return 1;
+ }
+ }
+
return 0; /* Not found. */
}
diff --git a/src/core/tsi/ssl_transport_security.h b/src/core/tsi/ssl_transport_security.h
index 3c1c4c01a2..eecf2d7c2d 100644
--- a/src/core/tsi/ssl_transport_security.h
+++ b/src/core/tsi/ssl_transport_security.h
@@ -158,7 +158,12 @@ tsi_result tsi_ssl_handshaker_factory_create_handshaker(
while handshakers created with this factory are still in use. */
void tsi_ssl_handshaker_factory_destroy(tsi_ssl_handshaker_factory* self);
-/* Util that checks that an ssl peer matches a specific name. */
+/* Util that checks that an ssl peer matches a specific name.
+ Still TODO(jboeuf):
+ - handle mixed case.
+ - handle %encoded chars.
+ - handle public suffix wildchar more strictly (e.g. *.co.uk)
+ - handle IP addresses in SAN. */
int tsi_ssl_peer_matches_name(const tsi_peer* peer, const char* name);
#ifdef __cplusplus