aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Tim Emiola <temiola@google.com>2015-01-21 16:26:34 -0800
committerGravatar Tim Emiola <temiola@google.com>2015-01-21 16:26:34 -0800
commitec12a7d972f1b9a64961efde535f466db9226d78 (patch)
tree183d04da35fe09f1d8d199c29746119cada11adb
parent8a3ca244b789a36edfcfaa7cf1c5f4a5ece1427a (diff)
parent2021d031687418fe4fe09d2e2efcdc4b3e833ffc (diff)
Merge remote-tracking branch 'upstream/master'
-rw-r--r--.clang-format54
-rw-r--r--.gitignore2
-rw-r--r--include/grpc++/server_credentials.h8
-rw-r--r--include/grpc/grpc.h3
-rw-r--r--include/grpc/grpc_security.h56
-rw-r--r--src/core/iomgr/pollset_kick_posix.c30
-rw-r--r--src/core/security/credentials.c113
-rw-r--r--src/core/security/credentials.h13
-rw-r--r--src/core/security/security_context.c19
-rw-r--r--src/core/security/security_context.h2
-rw-r--r--src/core/security/server_secure_chttp2.c16
-rw-r--r--src/cpp/client/credentials.cc22
-rw-r--r--src/cpp/server/server_credentials.cc23
-rw-r--r--src/node/binding.gyp3
-rw-r--r--src/node/common.js5
-rw-r--r--src/node/credentials.cc24
-rw-r--r--src/node/examples/math_server.js8
-rw-r--r--src/node/interop/empty.proto19
-rw-r--r--src/node/interop/interop_client.js274
-rw-r--r--src/node/interop/interop_server.js203
-rw-r--r--src/node/interop/messages.proto94
-rw-r--r--src/node/interop/test.proto42
-rw-r--r--src/node/main.js12
-rw-r--r--src/node/package.json6
-rw-r--r--src/node/server.cc4
-rw-r--r--src/node/server.js4
-rw-r--r--src/node/server_credentials.cc18
-rw-r--r--src/node/surface_client.js12
-rw-r--r--src/node/surface_server.js13
-rw-r--r--src/node/test/client_server_test.js159
-rw-r--r--src/node/test/end_to_end_test.js239
-rw-r--r--src/node/test/interop_sanity_test.js (renamed from src/node/port_picker.js)53
-rw-r--r--src/node/test/math_client_test.js18
-rw-r--r--src/node/test/server_test.js87
-rw-r--r--src/node/test/surface_test.js6
-rw-r--r--src/php/ext/grpc/credentials.c13
-rw-r--r--src/php/ext/grpc/server_credentials.c14
-rwxr-xr-xsrc/ruby/bin/interop/interop_client.rb16
-rwxr-xr-xsrc/ruby/bin/interop/interop_server.rb2
-rw-r--r--src/ruby/ext/grpc/extconf.rb2
-rw-r--r--src/ruby/ext/grpc/rb_credentials.c19
-rw-r--r--src/ruby/ext/grpc/rb_server_credentials.c14
-rw-r--r--test/core/end2end/data/prod_roots_certs.c5
-rw-r--r--test/core/end2end/data/server1_cert.c5
-rw-r--r--test/core/end2end/data/server1_key.c5
-rw-r--r--test/core/end2end/data/ssl_test_data.h12
-rw-r--r--test/core/end2end/data/test_root_cert.c5
-rw-r--r--test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c11
-rw-r--r--test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c10
-rw-r--r--test/core/fling/server.c7
-rw-r--r--test/core/iomgr/poll_kick_test.c30
-rw-r--r--test/core/security/credentials_test.c10
-rw-r--r--test/cpp/client/credentials_test.cc9
-rw-r--r--test/cpp/interop/server.cc6
-rw-r--r--test/cpp/util/create_test_channel.cc7
-rw-r--r--tools/dockerfile/grpc_base/Dockerfile25
-rw-r--r--tools/dockerfile/grpc_cxx/Dockerfile19
-rw-r--r--tools/dockerfile/grpc_php/Dockerfile5
-rw-r--r--tools/dockerfile/grpc_php_base/Dockerfile20
-rw-r--r--tools/dockerfile/grpc_ruby/Dockerfile9
-rw-r--r--tools/dockerfile/grpc_ruby_base/Dockerfile26
-rwxr-xr-xtools/gce_setup/shared_startup_funcs.sh44
62 files changed, 1342 insertions, 672 deletions
diff --git a/.clang-format b/.clang-format
index 651e1296ba..4b3f13fa55 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,57 +1,5 @@
---
Language: Cpp
-# BasedOnStyle: Google
-AccessModifierOffset: -1
-ConstructorInitializerIndentWidth: 4
-AlignEscapedNewlinesLeft: true
-AlignTrailingComments: true
-AllowAllParametersOfDeclarationOnNextLine: true
-AllowShortBlocksOnASingleLine: false
-AllowShortIfStatementsOnASingleLine: true
-AllowShortLoopsOnASingleLine: true
-AllowShortFunctionsOnASingleLine: All
-AlwaysBreakTemplateDeclarations: true
-AlwaysBreakBeforeMultilineStrings: true
-BreakBeforeBinaryOperators: false
-BreakBeforeTernaryOperators: true
-BreakConstructorInitializersBeforeComma: false
-BinPackParameters: true
-ColumnLimit: 80
-ConstructorInitializerAllOnOneLineOrOnePerLine: true
-DerivePointerAlignment: true
-ExperimentalAutoDetectBinPacking: false
-IndentCaseLabels: true
-IndentWrappedFunctionNames: false
-IndentFunctionDeclarationAfterType: false
-MaxEmptyLinesToKeep: 1
-KeepEmptyLinesAtTheStartOfBlocks: false
-NamespaceIndentation: None
-ObjCSpaceAfterProperty: false
-ObjCSpaceBeforeProtocolList: false
-PenaltyBreakBeforeFirstCallParameter: 1
-PenaltyBreakComment: 300
-PenaltyBreakString: 1000
-PenaltyBreakFirstLessLess: 120
-PenaltyExcessCharacter: 1000000
-PenaltyReturnTypeOnItsOwnLine: 200
-PointerAlignment: Left
-SpacesBeforeTrailingComments: 2
-Cpp11BracedListStyle: true
-Standard: Auto
-IndentWidth: 2
-TabWidth: 8
-UseTab: Never
-BreakBeforeBraces: Attach
-SpacesInParentheses: false
-SpacesInAngles: false
-SpaceInEmptyParentheses: false
-SpacesInCStyleCastParentheses: false
-SpacesInContainerLiterals: true
-SpaceBeforeAssignmentOperators: true
-ContinuationIndentWidth: 4
-CommentPragmas: '^ IWYU pragma:'
-ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
-SpaceBeforeParens: ControlStatements
-DisableFormat: false
+BasedOnStyle: Google
...
diff --git a/.gitignore b/.gitignore
index 3efc25aafb..63332d1b16 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,3 +17,5 @@ coverage
# cache for run_tests.py
.run_tests_cache
+# emacs temp files
+*~ \ No newline at end of file
diff --git a/include/grpc++/server_credentials.h b/include/grpc++/server_credentials.h
index cf08870f42..91504ae0ae 100644
--- a/include/grpc++/server_credentials.h
+++ b/include/grpc++/server_credentials.h
@@ -35,6 +35,7 @@
#define __GRPCPP_SERVER_CREDENTIALS_H_
#include <memory>
+#include <vector>
#include <grpc++/config.h>
@@ -60,9 +61,12 @@ class ServerCredentials final {
// Options to create ServerCredentials with SSL
struct SslServerCredentialsOptions {
+ struct PemKeyCertPair{
+ grpc::string private_key;
+ grpc::string cert_chain;
+ };
grpc::string pem_root_certs;
- grpc::string pem_private_key;
- grpc::string pem_cert_chain;
+ std::vector<PemKeyCertPair> pem_key_cert_pairs;
};
// Factory for building different types of ServerCredentials
diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h
index 3c5b0de195..f03f61d84e 100644
--- a/include/grpc/grpc.h
+++ b/include/grpc/grpc.h
@@ -428,7 +428,8 @@ grpc_server *grpc_server_create(grpc_completion_queue *cq,
REQUIRES: server not started */
int grpc_server_add_http2_port(grpc_server *server, const char *addr);
-/* Add a secure port to server; returns 1 on success, 0 on failure
+/* Add a secure port to server.
+ Returns bound port number on success, 0 on failure.
REQUIRES: server not started */
int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr);
diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h
index 644b31f763..0732a8f83a 100644
--- a/include/grpc/grpc_security.h
+++ b/include/grpc/grpc_security.h
@@ -54,22 +54,26 @@ void grpc_credentials_release(grpc_credentials *creds);
/* Creates default credentials. */
grpc_credentials *grpc_default_credentials_create(void);
+/* Object that holds a private key / certificate chain pair in PEM format. */
+typedef struct {
+ /* private_key is the NULL-terminated string containing the PEM encoding of
+ the client's private key. */
+ const char *private_key;
+
+ /* cert_chain is the NULL-terminated string containing the PEM encoding of
+ the client's certificate chain. */
+ const char *cert_chain;
+} grpc_ssl_pem_key_cert_pair;
+
/* Creates an SSL credentials object.
- - pem_roots_cert is the buffer containing the PEM encoding of the server
- root certificates. This parameter cannot be NULL.
- - pem_roots_cert_size is the size of the associated buffer.
- - pem_private_key is the buffer containing the PEM encoding of the client's
- private key. This parameter can be NULL if the client does not have a
- private key.
- - pem_private_key_size is the size of the associated buffer.
- - pem_cert_chain is the buffer containing the PEM encoding of the client's
- certificate chain. This parameter can be NULL if the client does not have
- a certificate chain.
- - pem_cert_chain_size is the size of the associated buffer. */
+ - pem_roots_cert is the NULL-terminated string containing the PEM encoding
+ of the server root certificates. If this parameter is NULL, the default
+ roots will be used.
+ - pem_key_cert_pair is a pointer on the object containing client's private
+ key and certificate chain. This parameter can be NULL if the client does
+ not have such a key/cert pair. */
grpc_credentials *grpc_ssl_credentials_create(
- const unsigned char *pem_root_certs, size_t pem_root_certs_size,
- const unsigned char *pem_private_key, size_t pem_private_key_size,
- const unsigned char *pem_cert_chain, size_t pem_cert_chain_size);
+ const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair);
/* Creates a composite credentials object. */
grpc_credentials *grpc_composite_credentials_create(grpc_credentials *creds1,
@@ -130,22 +134,16 @@ typedef struct grpc_server_credentials grpc_server_credentials;
void grpc_server_credentials_release(grpc_server_credentials *creds);
/* Creates an SSL server_credentials object.
- TODO(jboeuf): Change the constructor so that it can support multiple
- key/cert pairs.
- - pem_roots_cert is the buffer containing the PEM encoding of the server
- root certificates. This parameter may be NULL if the server does not want
- the client to be authenticated with SSL.
- - pem_roots_cert_size is the size of the associated buffer.
- - pem_private_key is the buffer containing the PEM encoding of the client's
- private key. This parameter cannot be NULL.
- - pem_private_key_size is the size of the associated buffer.
- - pem_cert_chain is the buffer containing the PEM encoding of the client's
- certificate chain. This parameter cannot be NULL.
- - pem_cert_chain_size is the size of the associated buffer. */
+ - pem_roots_cert is the NULL-terminated string containing the PEM encoding of
+ the client root certificates. This parameter may be NULL if the server does
+ not want the client to be authenticated with SSL.
+ - pem_key_cert_pairs is an array private key / certificate chains of the
+ server. This parameter cannot be NULL.
+ - num_key_cert_pairs indicates the number of items in the private_key_files
+ and cert_chain_files parameters. It should be at least 1. */
grpc_server_credentials *grpc_ssl_server_credentials_create(
- const unsigned char *pem_root_certs, size_t pem_root_certs_size,
- const unsigned char *pem_private_key, size_t pem_private_key_size,
- const unsigned char *pem_cert_chain, size_t pem_cert_chain_size);
+ const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
+ size_t num_key_cert_pairs);
/* Creates a fake server transport security credentials object for testing. */
grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
diff --git a/src/core/iomgr/pollset_kick_posix.c b/src/core/iomgr/pollset_kick_posix.c
index d16e49e459..9f85b6137a 100644
--- a/src/core/iomgr/pollset_kick_posix.c
+++ b/src/core/iomgr/pollset_kick_posix.c
@@ -43,6 +43,9 @@
/* This implementation is based on a freelist of pipes. */
+#define GRPC_MAX_CACHED_PIPES 50
+#define GRPC_PIPE_LOW_WATERMARK 25
+
typedef struct grpc_kick_pipe_info {
int pipe_read_fd;
int pipe_write_fd;
@@ -50,14 +53,16 @@ typedef struct grpc_kick_pipe_info {
} grpc_kick_pipe_info;
static grpc_kick_pipe_info *pipe_freelist = NULL;
+static int pipe_freelist_count = 0;
static gpr_mu pipe_freelist_mu;
-static grpc_kick_pipe_info *allocate_pipe() {
+static grpc_kick_pipe_info *allocate_pipe(void) {
grpc_kick_pipe_info *info;
gpr_mu_lock(&pipe_freelist_mu);
if (pipe_freelist != NULL) {
info = pipe_freelist;
pipe_freelist = pipe_freelist->next;
+ --pipe_freelist_count;
} else {
int pipefd[2];
/* TODO(klempner): Make this nonfatal */
@@ -73,11 +78,26 @@ static grpc_kick_pipe_info *allocate_pipe() {
return info;
}
+static void destroy_pipe(void) {
+ /* assumes pipe_freelist_mu is held */
+ grpc_kick_pipe_info *current = pipe_freelist;
+ pipe_freelist = pipe_freelist->next;
+ pipe_freelist_count--;
+ close(current->pipe_read_fd);
+ close(current->pipe_write_fd);
+ gpr_free(current);
+}
+
static void free_pipe(grpc_kick_pipe_info *pipe_info) {
- /* TODO(klempner): Start closing pipes if the free list gets too large */
gpr_mu_lock(&pipe_freelist_mu);
pipe_info->next = pipe_freelist;
pipe_freelist = pipe_info;
+ pipe_freelist_count++;
+ if (pipe_freelist_count > GRPC_MAX_CACHED_PIPES) {
+ while (pipe_freelist_count > GRPC_PIPE_LOW_WATERMARK) {
+ destroy_pipe();
+ }
+ }
gpr_mu_unlock(&pipe_freelist_mu);
}
@@ -88,11 +108,7 @@ void grpc_pollset_kick_global_init() {
void grpc_pollset_kick_global_destroy() {
while (pipe_freelist != NULL) {
- grpc_kick_pipe_info *current = pipe_freelist;
- pipe_freelist = pipe_freelist->next;
- close(current->pipe_read_fd);
- close(current->pipe_write_fd);
- gpr_free(current);
+ destroy_pipe();
}
gpr_mu_destroy(&pipe_freelist_mu);
}
diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c
index 006d863e27..628963e46c 100644
--- a/src/core/security/credentials.c
+++ b/src/core/security/credentials.c
@@ -139,7 +139,7 @@ typedef struct {
typedef struct {
grpc_server_credentials base;
- grpc_ssl_config config;
+ grpc_ssl_server_config config;
} grpc_ssl_server_credentials;
static void ssl_destroy(grpc_credentials *creds) {
@@ -152,9 +152,24 @@ static void ssl_destroy(grpc_credentials *creds) {
static void ssl_server_destroy(grpc_server_credentials *creds) {
grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds;
+ size_t i;
+ for (i = 0; i < c->config.num_key_cert_pairs; i++) {
+ if (c->config.pem_private_keys[i] != NULL) {
+ gpr_free(c->config.pem_private_keys[i]);
+ }
+ if (c->config.pem_cert_chains[i]!= NULL) {
+ gpr_free(c->config.pem_cert_chains[i]);
+ }
+ }
+ if (c->config.pem_private_keys != NULL) gpr_free(c->config.pem_private_keys);
+ if (c->config.pem_private_keys_sizes != NULL) {
+ gpr_free(c->config.pem_private_keys_sizes);
+ }
+ if (c->config.pem_cert_chains != NULL) gpr_free(c->config.pem_cert_chains);
+ if (c->config.pem_cert_chains_sizes != NULL) {
+ gpr_free(c->config.pem_cert_chains_sizes);
+ }
if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
- if (c->config.pem_private_key != NULL) gpr_free(c->config.pem_private_key);
- if (c->config.pem_cert_chain != NULL) gpr_free(c->config.pem_cert_chain);
gpr_free(creds);
}
@@ -179,7 +194,7 @@ const grpc_ssl_config *grpc_ssl_credentials_get_config(
}
}
-const grpc_ssl_config *grpc_ssl_server_credentials_get_config(
+const grpc_ssl_server_config *grpc_ssl_server_credentials_get_config(
const grpc_server_credentials *creds) {
if (creds == NULL || strcmp(creds->type, GRPC_CREDENTIALS_TYPE_SSL)) {
return NULL;
@@ -189,57 +204,89 @@ const grpc_ssl_config *grpc_ssl_server_credentials_get_config(
}
}
-static void ssl_build_config(const unsigned char *pem_root_certs,
- size_t pem_root_certs_size,
- const unsigned char *pem_private_key,
- size_t pem_private_key_size,
- const unsigned char *pem_cert_chain,
- size_t pem_cert_chain_size,
+static void ssl_copy_key_material(const char *input, unsigned char **output,
+ size_t *output_size) {
+ *output_size = strlen(input);
+ *output = gpr_malloc(*output_size);
+ memcpy(*output, input, *output_size);
+}
+
+static void ssl_build_config(const char *pem_root_certs,
+ grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
grpc_ssl_config *config) {
+ if (pem_root_certs == NULL) {
+ /* TODO(jboeuf): Get them from the environment. */
+ gpr_log(GPR_ERROR, "Default SSL roots not yet implemented.");
+ } else {
+ ssl_copy_key_material(pem_root_certs, &config->pem_root_certs,
+ &config->pem_root_certs_size);
+ }
+
+ if (pem_key_cert_pair != NULL) {
+ GPR_ASSERT(pem_key_cert_pair->private_key != NULL);
+ GPR_ASSERT(pem_key_cert_pair->cert_chain != NULL);
+ ssl_copy_key_material(pem_key_cert_pair->private_key,
+ &config->pem_private_key,
+ &config->pem_private_key_size);
+ ssl_copy_key_material(pem_key_cert_pair->cert_chain,
+ &config->pem_cert_chain,
+ &config->pem_cert_chain_size);
+ }
+}
+
+static void ssl_build_server_config(
+ const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
+ size_t num_key_cert_pairs, grpc_ssl_server_config *config) {
+ size_t i;
if (pem_root_certs != NULL) {
- config->pem_root_certs = gpr_malloc(pem_root_certs_size);
- memcpy(config->pem_root_certs, pem_root_certs, pem_root_certs_size);
- config->pem_root_certs_size = pem_root_certs_size;
+ ssl_copy_key_material(pem_root_certs, &config->pem_root_certs,
+ &config->pem_root_certs_size);
}
- if (pem_private_key != NULL) {
- config->pem_private_key = gpr_malloc(pem_private_key_size);
- memcpy(config->pem_private_key, pem_private_key, pem_private_key_size);
- config->pem_private_key_size = pem_private_key_size;
+ if (num_key_cert_pairs > 0) {
+ GPR_ASSERT(pem_key_cert_pairs != NULL);
+ config->pem_private_keys =
+ gpr_malloc(num_key_cert_pairs * sizeof(unsigned char *));
+ config->pem_cert_chains =
+ gpr_malloc(num_key_cert_pairs * sizeof(unsigned char *));
+ config->pem_private_keys_sizes =
+ gpr_malloc(num_key_cert_pairs * sizeof(size_t));
+ config->pem_cert_chains_sizes =
+ gpr_malloc(num_key_cert_pairs * sizeof(size_t));
}
- if (pem_cert_chain != NULL) {
- config->pem_cert_chain = gpr_malloc(pem_cert_chain_size);
- memcpy(config->pem_cert_chain, pem_cert_chain, pem_cert_chain_size);
- config->pem_cert_chain_size = pem_cert_chain_size;
+ config->num_key_cert_pairs = num_key_cert_pairs;
+ for (i = 0; i < num_key_cert_pairs; i++) {
+ GPR_ASSERT(pem_key_cert_pairs[i].private_key != NULL);
+ GPR_ASSERT(pem_key_cert_pairs[i].cert_chain != NULL);
+ ssl_copy_key_material(pem_key_cert_pairs[i].private_key,
+ &config->pem_private_keys[i],
+ &config->pem_private_keys_sizes[i]);
+ ssl_copy_key_material(pem_key_cert_pairs[i].cert_chain,
+ &config->pem_cert_chains[i],
+ &config->pem_cert_chains_sizes[i]);
}
}
grpc_credentials *grpc_ssl_credentials_create(
- const unsigned char *pem_root_certs, size_t pem_root_certs_size,
- const unsigned char *pem_private_key, size_t pem_private_key_size,
- const unsigned char *pem_cert_chain, size_t pem_cert_chain_size) {
+ const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair) {
grpc_ssl_credentials *c = gpr_malloc(sizeof(grpc_ssl_credentials));
memset(c, 0, sizeof(grpc_ssl_credentials));
c->base.type = GRPC_CREDENTIALS_TYPE_SSL;
c->base.vtable = &ssl_vtable;
gpr_ref_init(&c->base.refcount, 1);
- ssl_build_config(pem_root_certs, pem_root_certs_size, pem_private_key,
- pem_private_key_size, pem_cert_chain, pem_cert_chain_size,
- &c->config);
+ ssl_build_config(pem_root_certs, pem_key_cert_pair, &c->config);
return &c->base;
}
grpc_server_credentials *grpc_ssl_server_credentials_create(
- const unsigned char *pem_root_certs, size_t pem_root_certs_size,
- const unsigned char *pem_private_key, size_t pem_private_key_size,
- const unsigned char *pem_cert_chain, size_t pem_cert_chain_size) {
+ const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
+ size_t num_key_cert_pairs) {
grpc_ssl_server_credentials *c =
gpr_malloc(sizeof(grpc_ssl_server_credentials));
memset(c, 0, sizeof(grpc_ssl_server_credentials));
c->base.type = GRPC_CREDENTIALS_TYPE_SSL;
c->base.vtable = &ssl_server_vtable;
- ssl_build_config(pem_root_certs, pem_root_certs_size, pem_private_key,
- pem_private_key_size, pem_cert_chain, pem_cert_chain_size,
- &c->config);
+ ssl_build_server_config(pem_root_certs, pem_key_cert_pairs,
+ num_key_cert_pairs, &c->config);
return &c->base;
}
diff --git a/src/core/security/credentials.h b/src/core/security/credentials.h
index 4a2532d7c4..8a9ff41e10 100644
--- a/src/core/security/credentials.h
+++ b/src/core/security/credentials.h
@@ -137,10 +137,17 @@ struct grpc_server_credentials {
const char *type;
};
-/* TODO(jboeuf): Have an ssl_server_config that can contain multiple key/cert
- pairs. */
+typedef struct {
+ unsigned char **pem_private_keys;
+ size_t *pem_private_keys_sizes;
+ unsigned char **pem_cert_chains;
+ size_t *pem_cert_chains_sizes;
+ size_t num_key_cert_pairs;
+ unsigned char *pem_root_certs;
+ size_t pem_root_certs_size;
+} grpc_ssl_server_config;
-const grpc_ssl_config *grpc_ssl_server_credentials_get_config(
+const grpc_ssl_server_config *grpc_ssl_server_credentials_get_config(
const grpc_server_credentials *ssl_creds);
#endif /* __GRPC_INTERNAL_SECURITY_CREDENTIALS_H__ */
diff --git a/src/core/security/security_context.c b/src/core/security/security_context.c
index 3a70f44a0a..cce3c7fe04 100644
--- a/src/core/security/security_context.c
+++ b/src/core/security/security_context.c
@@ -382,7 +382,7 @@ error:
}
grpc_security_status grpc_ssl_server_security_context_create(
- const grpc_ssl_config *config, grpc_security_context **ctx) {
+ const grpc_ssl_server_config *config, grpc_security_context **ctx) {
size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions();
const unsigned char **alpn_protocol_strings =
gpr_malloc(sizeof(const char *) * num_alpn_protocols);
@@ -399,8 +399,7 @@ grpc_security_status grpc_ssl_server_security_context_create(
strlen(grpc_chttp2_get_alpn_version_index(i));
}
- if (config == NULL || config->pem_private_key == NULL ||
- config->pem_cert_chain == NULL) {
+ if (config == NULL || config->num_key_cert_pairs == 0) {
gpr_log(GPR_ERROR, "An SSL server needs a key and a cert.");
goto error;
}
@@ -410,13 +409,13 @@ grpc_security_status grpc_ssl_server_security_context_create(
gpr_ref_init(&c->base.refcount, 1);
c->base.vtable = &ssl_server_vtable;
result = tsi_create_ssl_server_handshaker_factory(
- (const unsigned char **)&config->pem_private_key,
- &config->pem_private_key_size,
- (const unsigned char **)&config->pem_cert_chain,
- &config->pem_cert_chain_size, 1, config->pem_root_certs,
- config->pem_root_certs_size, GRPC_SSL_CIPHER_SUITES,
- alpn_protocol_strings, alpn_protocol_string_lengths, num_alpn_protocols,
- &c->handshaker_factory);
+ (const unsigned char **)config->pem_private_keys,
+ config->pem_private_keys_sizes,
+ (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,
+ alpn_protocol_string_lengths, num_alpn_protocols, &c->handshaker_factory);
if (result != TSI_OK) {
gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
tsi_result_to_string(result));
diff --git a/src/core/security/security_context.h b/src/core/security/security_context.h
index 9ace7f1ccb..2caa2d3690 100644
--- a/src/core/security/security_context.h
+++ b/src/core/security/security_context.h
@@ -157,7 +157,7 @@ grpc_security_status grpc_ssl_channel_security_context_create(
specific error code otherwise.
*/
grpc_security_status grpc_ssl_server_security_context_create(
- const grpc_ssl_config *config, grpc_security_context **ctx);
+ const grpc_ssl_server_config *config, grpc_security_context **ctx);
/* --- Creation of high level objects. --- */
diff --git a/src/core/security/server_secure_chttp2.c b/src/core/security/server_secure_chttp2.c
index 931fa95651..9dd4327822 100644
--- a/src/core/security/server_secure_chttp2.c
+++ b/src/core/security/server_secure_chttp2.c
@@ -93,6 +93,8 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr) {
grpc_tcp_server *tcp = NULL;
size_t i;
int count = 0;
+ int port_num = -1;
+ int port_temp;
resolved = grpc_blocking_resolve_address(addr, "https");
if (!resolved) {
@@ -105,9 +107,15 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr) {
}
for (i = 0; i < resolved->naddrs; i++) {
- if (grpc_tcp_server_add_port(tcp,
- (struct sockaddr *)&resolved->addrs[i].addr,
- resolved->addrs[i].len)) {
+ 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++;
}
}
@@ -125,7 +133,7 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr) {
/* Register with the server only upon success */
grpc_server_add_listener(server, tcp, start, destroy);
- return 1;
+ return port_num;
/* Error path: cleanup and return */
error:
diff --git a/src/cpp/client/credentials.cc b/src/cpp/client/credentials.cc
index 0955fa28ae..8e3a988477 100644
--- a/src/cpp/client/credentials.cc
+++ b/src/cpp/client/credentials.cc
@@ -54,26 +54,12 @@ std::unique_ptr<Credentials> CredentialsFactory::DefaultCredentials() {
// Builds SSL Credentials given SSL specific options
std::unique_ptr<Credentials> CredentialsFactory::SslCredentials(
const SslCredentialsOptions &options) {
- const unsigned char *pem_root_certs =
- options.pem_root_certs.empty() ? nullptr
- : reinterpret_cast<const unsigned char *>(
- options.pem_root_certs.c_str());
- if (pem_root_certs == nullptr) {
- return std::unique_ptr<Credentials>();
- }
- const unsigned char *pem_private_key =
- options.pem_private_key.empty() ? nullptr
- : reinterpret_cast<const unsigned char *>(
- options.pem_private_key.c_str());
- const unsigned char *pem_cert_chain =
- options.pem_cert_chain.empty() ? nullptr
- : reinterpret_cast<const unsigned char *>(
- options.pem_cert_chain.c_str());
+ grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {
+ options.pem_private_key.c_str(), options.pem_cert_chain.c_str()};
grpc_credentials *c_creds = grpc_ssl_credentials_create(
- pem_root_certs, options.pem_root_certs.size(), pem_private_key,
- options.pem_private_key.size(), pem_cert_chain,
- options.pem_cert_chain.size());
+ options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(),
+ options.pem_private_key.empty() ? nullptr : &pem_key_cert_pair);
std::unique_ptr<Credentials> cpp_creds(
c_creds == nullptr ? nullptr : new Credentials(c_creds));
return cpp_creds;
diff --git a/src/cpp/server/server_credentials.cc b/src/cpp/server/server_credentials.cc
index b82a2d821a..ce0271b6a0 100644
--- a/src/cpp/server/server_credentials.cc
+++ b/src/cpp/server/server_credentials.cc
@@ -48,23 +48,14 @@ grpc_server_credentials *ServerCredentials::GetRawCreds() { return creds_; }
std::shared_ptr<ServerCredentials> ServerCredentialsFactory::SslCredentials(
const SslServerCredentialsOptions &options) {
- const unsigned char *pem_root_certs =
- options.pem_root_certs.empty() ? nullptr
- : reinterpret_cast<const unsigned char *>(
- options.pem_root_certs.c_str());
- const unsigned char *pem_private_key =
- options.pem_private_key.empty() ? nullptr
- : reinterpret_cast<const unsigned char *>(
- options.pem_private_key.c_str());
- const unsigned char *pem_cert_chain =
- options.pem_cert_chain.empty() ? nullptr
- : reinterpret_cast<const unsigned char *>(
- options.pem_cert_chain.c_str());
-
+ std::vector<grpc_ssl_pem_key_cert_pair> pem_key_cert_pairs;
+ for (const auto &key_cert_pair : options.pem_key_cert_pairs) {
+ pem_key_cert_pairs.push_back(
+ {key_cert_pair.private_key.c_str(), key_cert_pair.cert_chain.c_str()});
+ }
grpc_server_credentials *c_creds = grpc_ssl_server_credentials_create(
- pem_root_certs, options.pem_root_certs.size(), pem_private_key,
- options.pem_private_key.size(), pem_cert_chain,
- options.pem_cert_chain.size());
+ options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(),
+ &pem_key_cert_pairs[0], pem_key_cert_pairs.size());
return std::shared_ptr<ServerCredentials>(new ServerCredentials(c_creds));
}
diff --git a/src/node/binding.gyp b/src/node/binding.gyp
index 4a1fd7aaf0..da4a943491 100644
--- a/src/node/binding.gyp
+++ b/src/node/binding.gyp
@@ -19,9 +19,6 @@
'link_settings': {
'libraries': [
'-lgrpc',
- '-levent',
- '-levent_pthreads',
- '-levent_core',
'-lrt',
'-lgpr',
'-lpthread'
diff --git a/src/node/common.js b/src/node/common.js
index 656a4aca95..54247e3fa1 100644
--- a/src/node/common.js
+++ b/src/node/common.js
@@ -31,6 +31,8 @@
*
*/
+var capitalize = require('underscore.string/capitalize');
+
/**
* Get a function that deserializes a specific type of protobuf.
* @param {function()} cls The constructor of the message type to deserialize
@@ -73,6 +75,9 @@ function fullyQualifiedName(value) {
return '';
}
var name = value.name;
+ if (value.className === 'Service.RPCMethod') {
+ name = capitalize(name);
+ }
if (value.hasOwnProperty('parent')) {
var parent_name = fullyQualifiedName(value.parent);
if (parent_name !== '') {
diff --git a/src/node/credentials.cc b/src/node/credentials.cc
index d58b7eda89..f9cd2fcfe0 100644
--- a/src/node/credentials.cc
+++ b/src/node/credentials.cc
@@ -136,33 +136,29 @@ NAN_METHOD(Credentials::CreateDefault) {
NAN_METHOD(Credentials::CreateSsl) {
NanScope();
- char *root_certs;
- char *private_key = NULL;
- char *cert_chain = NULL;
- int root_certs_length, private_key_length = 0, cert_chain_length = 0;
- if (!Buffer::HasInstance(args[0])) {
+ char *root_certs = NULL;
+ grpc_ssl_pem_key_cert_pair key_cert_pair = {NULL, NULL};
+ if (Buffer::HasInstance(args[0])) {
+ root_certs = Buffer::Data(args[0]);
+ } else if (!(args[0]->IsNull() || args[0]->IsUndefined())) {
return NanThrowTypeError("createSsl's first argument must be a Buffer");
}
- root_certs = Buffer::Data(args[0]);
- root_certs_length = Buffer::Length(args[0]);
if (Buffer::HasInstance(args[1])) {
- private_key = Buffer::Data(args[1]);
- private_key_length = Buffer::Length(args[1]);
+ key_cert_pair.private_key = Buffer::Data(args[1]);
} else if (!(args[1]->IsNull() || args[1]->IsUndefined())) {
return NanThrowTypeError(
"createSSl's second argument must be a Buffer if provided");
}
if (Buffer::HasInstance(args[2])) {
- cert_chain = Buffer::Data(args[2]);
- cert_chain_length = Buffer::Length(args[2]);
+ key_cert_pair.cert_chain = Buffer::Data(args[2]);
} else if (!(args[2]->IsNull() || args[2]->IsUndefined())) {
return NanThrowTypeError(
"createSSl's third argument must be a Buffer if provided");
}
+
NanReturnValue(WrapStruct(grpc_ssl_credentials_create(
- reinterpret_cast<unsigned char *>(root_certs), root_certs_length,
- reinterpret_cast<unsigned char *>(private_key), private_key_length,
- reinterpret_cast<unsigned char *>(cert_chain), cert_chain_length)));
+ root_certs,
+ key_cert_pair.private_key == NULL ? NULL : &key_cert_pair)));
}
NAN_METHOD(Credentials::CreateComposite) {
diff --git a/src/node/examples/math_server.js b/src/node/examples/math_server.js
index 366513dc17..d649b4fd6d 100644
--- a/src/node/examples/math_server.js
+++ b/src/node/examples/math_server.js
@@ -119,10 +119,10 @@ function mathDivMany(stream) {
var server = new Server({
'math.Math' : {
- Div: mathDiv,
- Fib: mathFib,
- Sum: mathSum,
- DivMany: mathDivMany
+ div: mathDiv,
+ fib: mathFib,
+ sum: mathSum,
+ divMany: mathDivMany
}
});
diff --git a/src/node/interop/empty.proto b/src/node/interop/empty.proto
new file mode 100644
index 0000000000..c9920a22ee
--- /dev/null
+++ b/src/node/interop/empty.proto
@@ -0,0 +1,19 @@
+syntax = "proto2";
+
+package grpc.testing;
+
+// An empty message that you can re-use to avoid defining duplicated empty
+// messages in your project. A typical example is to use it as argument or the
+// return value of a service API. For instance:
+//
+// service Foo {
+// rpc Bar (grpc.testing.Empty) returns (grpc.testing.Empty) { };
+// };
+//
+// MOE:begin_strip
+// The difference between this one and net/rpc/empty-message.proto is that
+// 1) The generated message here is in proto2 C++ API.
+// 2) The proto2.Empty has minimum dependencies
+// (no message_set or net/rpc dependencies)
+// MOE:end_strip
+message Empty {}
diff --git a/src/node/interop/interop_client.js b/src/node/interop/interop_client.js
new file mode 100644
index 0000000000..cf75b9a77a
--- /dev/null
+++ b/src/node/interop/interop_client.js
@@ -0,0 +1,274 @@
+/*
+ *
+ * Copyright 2014, 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.
+ *
+ */
+
+var fs = require('fs');
+var path = require('path');
+var grpc = require('..');
+var testProto = grpc.load(__dirname + '/test.proto').grpc.testing;
+
+var assert = require('assert');
+
+/**
+ * Create a buffer filled with size zeroes
+ * @param {number} size The length of the buffer
+ * @return {Buffer} The new buffer
+ */
+function zeroBuffer(size) {
+ var zeros = new Buffer(size);
+ zeros.fill(0);
+ return zeros;
+}
+
+/**
+ * Run the empty_unary test
+ * @param {Client} client The client to test against
+ * @param {function} done Callback to call when the test is completed. Included
+ * primarily for use with mocha
+ */
+function emptyUnary(client, done) {
+ var call = client.emptyCall({}, function(err, resp) {
+ assert.ifError(err);
+ });
+ call.on('status', function(status) {
+ assert.strictEqual(status.code, grpc.status.OK);
+ if (done) {
+ done();
+ }
+ });
+}
+
+/**
+ * Run the large_unary test
+ * @param {Client} client The client to test against
+ * @param {function} done Callback to call when the test is completed. Included
+ * primarily for use with mocha
+ */
+function largeUnary(client, done) {
+ var arg = {
+ response_type: testProto.PayloadType.COMPRESSABLE,
+ response_size: 314159,
+ payload: {
+ body: zeroBuffer(271828)
+ }
+ };
+ var call = client.unaryCall(arg, function(err, resp) {
+ assert.ifError(err);
+ assert.strictEqual(resp.payload.type, testProto.PayloadType.COMPRESSABLE);
+ assert.strictEqual(resp.payload.body.limit - resp.payload.body.offset,
+ 314159);
+ });
+ call.on('status', function(status) {
+ assert.strictEqual(status.code, grpc.status.OK);
+ if (done) {
+ done();
+ }
+ });
+}
+
+/**
+ * Run the client_streaming test
+ * @param {Client} client The client to test against
+ * @param {function} done Callback to call when the test is completed. Included
+ * primarily for use with mocha
+ */
+function clientStreaming(client, done) {
+ var call = client.streamingInputCall(function(err, resp) {
+ assert.ifError(err);
+ assert.strictEqual(resp.aggregated_payload_size, 74922);
+ });
+ call.on('status', function(status) {
+ assert.strictEqual(status.code, grpc.status.OK);
+ if (done) {
+ done();
+ }
+ });
+ var payload_sizes = [27182, 8, 1828, 45904];
+ for (var i = 0; i < payload_sizes.length; i++) {
+ call.write({payload: {body: zeroBuffer(payload_sizes[i])}});
+ }
+ call.end();
+}
+
+/**
+ * Run the server_streaming test
+ * @param {Client} client The client to test against
+ * @param {function} done Callback to call when the test is completed. Included
+ * primarily for use with mocha
+ */
+function serverStreaming(client, done) {
+ var arg = {
+ response_type: testProto.PayloadType.COMPRESSABLE,
+ response_parameters: [
+ {size: 31415},
+ {size: 9},
+ {size: 2653},
+ {size: 58979}
+ ]
+ };
+ var call = client.streamingOutputCall(arg);
+ var resp_index = 0;
+ call.on('data', function(value) {
+ assert(resp_index < 4);
+ assert.strictEqual(value.payload.type, testProto.PayloadType.COMPRESSABLE);
+ assert.strictEqual(value.payload.body.limit - value.payload.body.offset,
+ arg.response_parameters[resp_index].size);
+ resp_index += 1;
+ });
+ call.on('status', function(status) {
+ assert.strictEqual(resp_index, 4);
+ assert.strictEqual(status.code, grpc.status.OK);
+ if (done) {
+ done();
+ }
+ });
+}
+
+/**
+ * Run the ping_pong test
+ * @param {Client} client The client to test against
+ * @param {function} done Callback to call when the test is completed. Included
+ * primarily for use with mocha
+ */
+function pingPong(client, done) {
+ var payload_sizes = [27182, 8, 1828, 45904];
+ var response_sizes = [31415, 9, 2653, 58979];
+ var call = client.fullDuplexCall();
+ call.on('status', function(status) {
+ assert.strictEqual(status.code, grpc.status.OK);
+ if (done) {
+ done();
+ }
+ });
+ var index = 0;
+ call.write({
+ response_type: testProto.PayloadType.COMPRESSABLE,
+ response_parameters: [
+ {size: response_sizes[index]}
+ ],
+ payload: {body: zeroBuffer(payload_sizes[index])}
+ });
+ call.on('data', function(response) {
+ assert.strictEqual(response.payload.type,
+ testProto.PayloadType.COMPRESSABLE);
+ assert.equal(response.payload.body.limit - response.payload.body.offset,
+ response_sizes[index]);
+ index += 1;
+ if (index == 4) {
+ call.end();
+ } else {
+ call.write({
+ response_type: testProto.PayloadType.COMPRESSABLE,
+ response_parameters: [
+ {size: response_sizes[index]}
+ ],
+ payload: {body: zeroBuffer(payload_sizes[index])}
+ });
+ }
+ });
+}
+
+/**
+ * Run the empty_stream test.
+ * NOTE: This does not work, but should with the new invoke API
+ * @param {Client} client The client to test against
+ * @param {function} done Callback to call when the test is completed. Included
+ * primarily for use with mocha
+ */
+function emptyStream(client, done) {
+ var call = client.fullDuplexCall();
+ call.on('status', function(status) {
+ assert.strictEqual(status.code, grpc.status.OK);
+ if (done) {
+ done();
+ }
+ });
+ call.on('data', function(value) {
+ assert.fail(value, null, 'No data should have been received', '!==');
+ });
+ call.end();
+}
+
+/**
+ * Map from test case names to test functions
+ */
+var test_cases = {
+ empty_unary: emptyUnary,
+ large_unary: largeUnary,
+ client_streaming: clientStreaming,
+ server_streaming: serverStreaming,
+ ping_pong: pingPong,
+ empty_stream: emptyStream
+};
+
+/**
+ * Execute a single test case.
+ * @param {string} address The address of the server to connect to, in the
+ * format "hostname:port"
+ * @param {string} host_overrirde The hostname of the server to use as an SSL
+ * override
+ * @param {string} test_case The name of the test case to run
+ * @param {bool} tls Indicates that a secure channel should be used
+ * @param {function} done Callback to call when the test is completed. Included
+ * primarily for use with mocha
+ */
+function runTest(address, host_override, test_case, tls, done) {
+ // TODO(mlumish): enable TLS functionality
+ var options = {};
+ if (tls) {
+ var ca_path = path.join(__dirname, '../test/data/ca.pem');
+ var ca_data = fs.readFileSync(ca_path);
+ var creds = grpc.Credentials.createSsl(ca_data);
+ options.credentials = creds;
+ if (host_override) {
+ options['grpc.ssl_target_name_override'] = host_override;
+ }
+ }
+ var client = new testProto.TestService(address, options);
+
+ test_cases[test_case](client, done);
+}
+
+if (require.main === module) {
+ var parseArgs = require('minimist');
+ var argv = parseArgs(process.argv, {
+ string: ['server_host', 'server_host_override', 'server_port', 'test_case',
+ 'use_tls', 'use_test_ca']
+ });
+ runTest(argv.server_host + ':' + argv.server_port, argv.server_host_override,
+ argv.test_case, argv.use_tls === 'true');
+}
+
+/**
+ * See docs for runTest
+ */
+exports.runTest = runTest;
diff --git a/src/node/interop/interop_server.js b/src/node/interop/interop_server.js
new file mode 100644
index 0000000000..6d2bd7ae0d
--- /dev/null
+++ b/src/node/interop/interop_server.js
@@ -0,0 +1,203 @@
+/*
+ *
+ * Copyright 2014, 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.
+ *
+ */
+
+var fs = require('fs');
+var path = require('path');
+var _ = require('underscore');
+var grpc = require('..');
+var testProto = grpc.load(__dirname + '/test.proto').grpc.testing;
+var Server = grpc.buildServer([testProto.TestService.service]);
+
+/**
+ * Create a buffer filled with size zeroes
+ * @param {number} size The length of the buffer
+ * @return {Buffer} The new buffer
+ */
+function zeroBuffer(size) {
+ var zeros = new Buffer(size);
+ zeros.fill(0);
+ return zeros;
+}
+
+/**
+ * Respond to an empty parameter with an empty response.
+ * NOTE: this currently does not work due to issue #137
+ * @param {Call} call Call to handle
+ * @param {function(Error, Object)} callback Callback to call with result
+ * or error
+ */
+function handleEmpty(call, callback) {
+ callback(null, {});
+}
+
+/**
+ * Handle a unary request by sending the requested payload
+ * @param {Call} call Call to handle
+ * @param {function(Error, Object)} callback Callback to call with result or
+ * error
+ */
+function handleUnary(call, callback) {
+ var req = call.request;
+ var zeros = zeroBuffer(req.response_size);
+ var payload_type = req.response_type;
+ if (payload_type === testProto.PayloadType.RANDOM) {
+ payload_type = [
+ testProto.PayloadType.COMPRESSABLE,
+ testProto.PayloadType.UNCOMPRESSABLE][Math.random() < 0.5 ? 0 : 1];
+ }
+ callback(null, {payload: {type: payload_type, body: zeros}});
+}
+
+/**
+ * Respond to a streaming call with the total size of all payloads
+ * @param {Call} call Call to handle
+ * @param {function(Error, Object)} callback Callback to call with result or
+ * error
+ */
+function handleStreamingInput(call, callback) {
+ var aggregate_size = 0;
+ call.on('data', function(value) {
+ aggregate_size += value.payload.body.limit - value.payload.body.offset;
+ });
+ call.on('end', function() {
+ callback(null, {aggregated_payload_size: aggregate_size});
+ });
+}
+
+/**
+ * Respond to a payload request with a stream of the requested payloads
+ * @param {Call} call Call to handle
+ */
+function handleStreamingOutput(call) {
+ var req = call.request;
+ var payload_type = req.response_type;
+ if (payload_type === testProto.PayloadType.RANDOM) {
+ payload_type = [
+ testProto.PayloadType.COMPRESSABLE,
+ testProto.PayloadType.UNCOMPRESSABLE][Math.random() < 0.5 ? 0 : 1];
+ }
+ _.each(req.response_parameters, function(resp_param) {
+ call.write({
+ payload: {
+ body: zeroBuffer(resp_param.size),
+ type: payload_type
+ }
+ });
+ });
+ call.end();
+}
+
+/**
+ * Respond to a stream of payload requests with a stream of payload responses as
+ * they arrive.
+ * @param {Call} call Call to handle
+ */
+function handleFullDuplex(call) {
+ call.on('data', function(value) {
+ var payload_type = value.response_type;
+ if (payload_type === testProto.PayloadType.RANDOM) {
+ payload_type = [
+ testProto.PayloadType.COMPRESSABLE,
+ testProto.PayloadType.UNCOMPRESSABLE][Math.random() < 0.5 ? 0 : 1];
+ }
+ _.each(value.response_parameters, function(resp_param) {
+ call.write({
+ payload: {
+ body: zeroBuffer(resp_param.size),
+ type: payload_type
+ }
+ });
+ });
+ });
+ call.on('end', function() {
+ call.end();
+ });
+}
+
+/**
+ * Respond to a stream of payload requests with a stream of payload responses
+ * after all requests have arrived
+ * @param {Call} call Call to handle
+ */
+function handleHalfDuplex(call) {
+ throw new Error('HalfDuplexCall not yet implemented');
+}
+
+/**
+ * Get a server object bound to the given port
+ * @param {string} port Port to which to bind
+ * @param {boolean} tls Indicates that the bound port should use TLS
+ * @return {{server: Server, port: number}} Server object bound to the support,
+ * and port number that the server is bound to
+ */
+function getServer(port, tls) {
+ // TODO(mlumish): enable TLS functionality
+ var options = {};
+ if (tls) {
+ var key_path = path.join(__dirname, '../test/data/server1.key');
+ var pem_path = path.join(__dirname, '../test/data/server1.pem');
+
+ var key_data = fs.readFileSync(key_path);
+ var pem_data = fs.readFileSync(pem_path);
+ var server_creds = grpc.ServerCredentials.createSsl(null,
+ key_data,
+ pem_data);
+ options.credentials = server_creds;
+ }
+ var server = new Server({
+ 'grpc.testing.TestService' : {
+ emptyCall: handleEmpty,
+ unaryCall: handleUnary,
+ streamingOutputCall: handleStreamingOutput,
+ streamingInputCall: handleStreamingInput,
+ fullDuplexCall: handleFullDuplex,
+ halfDuplexCall: handleHalfDuplex
+ }
+ }, options);
+ var port_num = server.bind('0.0.0.0:' + port, tls);
+ return {server: server, port: port_num};
+}
+
+if (require.main === module) {
+ var parseArgs = require('minimist');
+ var argv = parseArgs(process.argv, {
+ string: ['port', 'use_tls']
+ });
+ var server_obj = getServer(argv.port, argv.use_tls === 'true');
+ server_obj.server.start();
+}
+
+/**
+ * See docs for getServer
+ */
+exports.getServer = getServer;
diff --git a/src/node/interop/messages.proto b/src/node/interop/messages.proto
new file mode 100644
index 0000000000..29db0dd8b1
--- /dev/null
+++ b/src/node/interop/messages.proto
@@ -0,0 +1,94 @@
+// Message definitions to be used by integration test service definitions.
+
+syntax = "proto2";
+
+package grpc.testing;
+
+// The type of payload that should be returned.
+enum PayloadType {
+ // Compressable text format.
+ COMPRESSABLE = 0;
+
+ // Uncompressable binary format.
+ UNCOMPRESSABLE = 1;
+
+ // Randomly chosen from all other formats defined in this enum.
+ RANDOM = 2;
+}
+
+// A block of data, to simply increase gRPC message size.
+message Payload {
+ // The type of data in body.
+ optional PayloadType type = 1;
+ // Primary contents of payload.
+ optional bytes body = 2;
+}
+
+// Unary request.
+message SimpleRequest {
+ // Desired payload type in the response from the server.
+ // If response_type is RANDOM, server randomly chooses one from other formats.
+ optional PayloadType response_type = 1;
+
+ // Desired payload size in the response from the server.
+ // If response_type is COMPRESSABLE, this denotes the size before compression.
+ optional int32 response_size = 2;
+
+ // Optional input payload sent along with the request.
+ optional Payload payload = 3;
+}
+
+// Unary response, as configured by the request.
+message SimpleResponse {
+ // Payload to increase message size.
+ optional Payload payload = 1;
+ // The user the request came from, for verifying authentication was
+ // successful when the client expected it.
+ optional int64 effective_gaia_user_id = 2;
+}
+
+// Client-streaming request.
+message StreamingInputCallRequest {
+ // Optional input payload sent along with the request.
+ optional Payload payload = 1;
+
+ // Not expecting any payload from the response.
+}
+
+// Client-streaming response.
+message StreamingInputCallResponse {
+ // Aggregated size of payloads received from the client.
+ optional int32 aggregated_payload_size = 1;
+}
+
+// Configuration for a particular response.
+message ResponseParameters {
+ // Desired payload sizes in responses from the server.
+ // If response_type is COMPRESSABLE, this denotes the size before compression.
+ optional int32 size = 1;
+
+ // Desired interval between consecutive responses in the response stream in
+ // microseconds.
+ optional int32 interval_us = 2;
+}
+
+// Server-streaming request.
+message StreamingOutputCallRequest {
+ // Desired payload type in the response from the server.
+ // If response_type is RANDOM, the payload from each response in the stream
+ // might be of different types. This is to simulate a mixed type of payload
+ // stream.
+ optional PayloadType response_type = 1;
+
+ // Configuration for each expected response message.
+ repeated ResponseParameters response_parameters = 2;
+
+ // Optional input payload sent along with the request.
+ optional Payload payload = 3;
+}
+
+// Server-streaming response, as configured by the request and parameters.
+message StreamingOutputCallResponse {
+ // Payload to increase response size.
+ optional Payload payload = 1;
+}
diff --git a/src/node/interop/test.proto b/src/node/interop/test.proto
new file mode 100644
index 0000000000..8380ebb31d
--- /dev/null
+++ b/src/node/interop/test.proto
@@ -0,0 +1,42 @@
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+syntax = "proto2";
+
+import "empty.proto";
+import "messages.proto";
+
+package grpc.testing;
+
+// A simple service to test the various types of RPCs and experiment with
+// performance with various types of payload.
+service TestService {
+ // One empty request followed by one empty response.
+ rpc EmptyCall(grpc.testing.Empty) returns (grpc.testing.Empty);
+
+ // One request followed by one response.
+ // The server returns the client payload as-is.
+ rpc UnaryCall(SimpleRequest) returns (SimpleResponse);
+
+ // One request followed by a sequence of responses (streamed download).
+ // The server returns the payload with client desired type and sizes.
+ rpc StreamingOutputCall(StreamingOutputCallRequest)
+ returns (stream StreamingOutputCallResponse);
+
+ // A sequence of requests followed by one response (streamed upload).
+ // The server returns the aggregated size of client payload as the result.
+ rpc StreamingInputCall(stream StreamingInputCallRequest)
+ returns (StreamingInputCallResponse);
+
+ // A sequence of requests with each request served by the server immediately.
+ // As one request could lead to multiple responses, this interface
+ // demonstrates the idea of full duplexing.
+ rpc FullDuplexCall(stream StreamingOutputCallRequest)
+ returns (stream StreamingOutputCallResponse);
+
+ // A sequence of requests followed by a sequence of responses.
+ // The server buffers all the client requests and then serves them in order. A
+ // stream of responses are returned to the client when the server starts with
+ // first request.
+ rpc HalfDuplexCall(stream StreamingOutputCallRequest)
+ returns (stream StreamingOutputCallResponse);
+}
diff --git a/src/node/main.js b/src/node/main.js
index a8dfa20024..751c3525d3 100644
--- a/src/node/main.js
+++ b/src/node/main.js
@@ -55,7 +55,7 @@ function loadObject(value) {
return result;
} else if (value.className === 'Service') {
return surface_client.makeClientConstructor(value);
- } else if (value.className === 'Service.Message') {
+ } else if (value.className === 'Message' || value.className === 'Enum') {
return value.build();
} else {
return value;
@@ -96,3 +96,13 @@ exports.status = grpc.status;
* Call error name to code number mapping
*/
exports.callError = grpc.callError;
+
+/**
+ * Credentials factories
+ */
+exports.Credentials = grpc.Credentials;
+
+/**
+ * ServerCredentials factories
+ */
+exports.ServerCredentials = grpc.ServerCredentials;
diff --git a/src/node/package.json b/src/node/package.json
index ed93c4ff41..5f3c6fa345 100644
--- a/src/node/package.json
+++ b/src/node/package.json
@@ -8,12 +8,14 @@
"dependencies": {
"bindings": "^1.2.1",
"nan": "~1.3.0",
+ "protobufjs": "murgatroid99/ProtoBuf.js",
"underscore": "^1.7.0",
- "protobufjs": "murgatroid99/ProtoBuf.js"
+ "underscore.string": "^3.0.0"
},
"devDependencies": {
+ "highland": "~2.2.0",
"mocha": "~1.21.0",
- "highland": "~2.0.0"
+ "minimist": "^1.1.0"
},
"main": "main.js"
}
diff --git a/src/node/server.cc b/src/node/server.cc
index 64826897cd..b102775d33 100644
--- a/src/node/server.cc
+++ b/src/node/server.cc
@@ -194,7 +194,7 @@ NAN_METHOD(Server::AddHttp2Port) {
return NanThrowTypeError("addHttp2Port's argument must be a String");
}
Server *server = ObjectWrap::Unwrap<Server>(args.This());
- NanReturnValue(NanNew<Boolean>(grpc_server_add_http2_port(
+ NanReturnValue(NanNew<Number>(grpc_server_add_http2_port(
server->wrapped_server, *NanUtf8String(args[0]))));
}
@@ -208,7 +208,7 @@ NAN_METHOD(Server::AddSecureHttp2Port) {
return NanThrowTypeError("addSecureHttp2Port's argument must be a String");
}
Server *server = ObjectWrap::Unwrap<Server>(args.This());
- NanReturnValue(NanNew<Boolean>(grpc_server_add_secure_http2_port(
+ NanReturnValue(NanNew<Number>(grpc_server_add_secure_http2_port(
server->wrapped_server, *NanUtf8String(args[0]))));
}
diff --git a/src/node/server.js b/src/node/server.js
index e947032b29..9cee1dc57e 100644
--- a/src/node/server.js
+++ b/src/node/server.js
@@ -256,9 +256,9 @@ Server.prototype.register = function(name, handler) {
*/
Server.prototype.bind = function(port, secure) {
if (secure) {
- this._server.addSecureHttp2Port(port);
+ return this._server.addSecureHttp2Port(port);
} else {
- this._server.addHttp2Port(port);
+ return this._server.addHttp2Port(port);
}
};
diff --git a/src/node/server_credentials.cc b/src/node/server_credentials.cc
index 38df547527..393f3a6305 100644
--- a/src/node/server_credentials.cc
+++ b/src/node/server_credentials.cc
@@ -123,14 +123,12 @@ NAN_METHOD(ServerCredentials::New) {
}
NAN_METHOD(ServerCredentials::CreateSsl) {
+ // TODO: have the node API support multiple key/cert pairs.
NanScope();
char *root_certs = NULL;
- char *private_key;
- char *cert_chain;
- int root_certs_length = 0, private_key_length, cert_chain_length;
+ grpc_ssl_pem_key_cert_pair key_cert_pair;
if (Buffer::HasInstance(args[0])) {
root_certs = Buffer::Data(args[0]);
- root_certs_length = Buffer::Length(args[0]);
} else if (!(args[0]->IsNull() || args[0]->IsUndefined())) {
return NanThrowTypeError(
"createSSl's first argument must be a Buffer if provided");
@@ -138,17 +136,13 @@ NAN_METHOD(ServerCredentials::CreateSsl) {
if (!Buffer::HasInstance(args[1])) {
return NanThrowTypeError("createSsl's second argument must be a Buffer");
}
- private_key = Buffer::Data(args[1]);
- private_key_length = Buffer::Length(args[1]);
+ key_cert_pair.private_key = Buffer::Data(args[1]);
if (!Buffer::HasInstance(args[2])) {
return NanThrowTypeError("createSsl's third argument must be a Buffer");
}
- cert_chain = Buffer::Data(args[2]);
- cert_chain_length = Buffer::Length(args[2]);
- NanReturnValue(WrapStruct(grpc_ssl_server_credentials_create(
- reinterpret_cast<unsigned char *>(root_certs), root_certs_length,
- reinterpret_cast<unsigned char *>(private_key), private_key_length,
- reinterpret_cast<unsigned char *>(cert_chain), cert_chain_length)));
+ key_cert_pair.cert_chain = Buffer::Data(args[2]);
+ NanReturnValue(WrapStruct(
+ grpc_ssl_server_credentials_create(root_certs, &key_cert_pair, 1)));
}
NAN_METHOD(ServerCredentials::CreateFake) {
diff --git a/src/node/surface_client.js b/src/node/surface_client.js
index 77dab5ca6f..996e3d101f 100644
--- a/src/node/surface_client.js
+++ b/src/node/surface_client.js
@@ -33,6 +33,9 @@
var _ = require('underscore');
+var capitalize = require('underscore.string/capitalize');
+var decapitalize = require('underscore.string/decapitalize');
+
var client = require('./client.js');
var common = require('./common.js');
@@ -352,10 +355,11 @@ function makeClientConstructor(service) {
method_type = 'unary';
}
}
- SurfaceClient.prototype[method.name] = requester_makers[method_type](
- prefix + method.name,
- common.serializeCls(method.resolvedRequestType.build()),
- common.deserializeCls(method.resolvedResponseType.build()));
+ SurfaceClient.prototype[decapitalize(method.name)] =
+ requester_makers[method_type](
+ prefix + capitalize(method.name),
+ common.serializeCls(method.resolvedRequestType.build()),
+ common.deserializeCls(method.resolvedResponseType.build()));
});
SurfaceClient.service = service;
diff --git a/src/node/surface_server.js b/src/node/surface_server.js
index b6e0c37b4c..bc688839fe 100644
--- a/src/node/surface_server.js
+++ b/src/node/surface_server.js
@@ -33,6 +33,9 @@
var _ = require('underscore');
+var capitalize = require('underscore.string/capitalize');
+var decapitalize = require('underscore.string/decapitalize');
+
var Server = require('./server.js');
var stream = require('stream');
@@ -332,15 +335,16 @@ function makeServerConstructor(services) {
method_type = 'unary';
}
}
- if (service_handlers[service_name][method.name] === undefined) {
+ if (service_handlers[service_name][decapitalize(method.name)] ===
+ undefined) {
throw new Error('Method handler for ' +
common.fullyQualifiedName(method) + ' not provided.');
}
var binary_handler = handler_makers[method_type](
- service_handlers[service_name][method.name],
+ service_handlers[service_name][decapitalize(method.name)],
common.serializeCls(method.resolvedResponseType.build()),
common.deserializeCls(method.resolvedRequestType.build()));
- server.register(prefix + method.name, binary_handler);
+ server.register(prefix + capitalize(method.name), binary_handler);
});
}, this);
}
@@ -353,8 +357,7 @@ function makeServerConstructor(services) {
* @return {SurfaceServer} this
*/
SurfaceServer.prototype.bind = function(port, secure) {
- this.inner_server.bind(port, secure);
- return this;
+ return this.inner_server.bind(port, secure);
};
/**
diff --git a/src/node/test/client_server_test.js b/src/node/test/client_server_test.js
index 534a5c464f..2a25908684 100644
--- a/src/node/test/client_server_test.js
+++ b/src/node/test/client_server_test.js
@@ -37,7 +37,6 @@ var path = require('path');
var grpc = require('bindings')('grpc.node');
var Server = require('../server');
var client = require('../client');
-var port_picker = require('../port_picker');
var common = require('../common');
var _ = require('highland');
@@ -80,55 +79,50 @@ function errorHandler(stream) {
describe('echo client', function() {
it('should receive echo responses', function(done) {
- port_picker.nextAvailablePort(function(port) {
- var server = new Server();
- server.bind(port);
- server.register('echo', echoHandler);
- server.start();
-
- var messages = ['echo1', 'echo2', 'echo3', 'echo4'];
- var channel = new grpc.Channel(port);
- var stream = client.makeRequest(
- channel,
- 'echo');
- _(messages).map(function(val) {
- return new Buffer(val);
- }).pipe(stream);
- var index = 0;
- stream.on('data', function(chunk) {
- assert.equal(messages[index], chunk.toString());
- index += 1;
- });
- stream.on('end', function() {
- server.shutdown();
- done();
- });
+ var server = new Server();
+ var port_num = server.bind('0.0.0.0:0');
+ server.register('echo', echoHandler);
+ server.start();
+
+ var messages = ['echo1', 'echo2', 'echo3', 'echo4'];
+ var channel = new grpc.Channel('localhost:' + port_num);
+ var stream = client.makeRequest(
+ channel,
+ 'echo');
+ _(messages).map(function(val) {
+ return new Buffer(val);
+ }).pipe(stream);
+ var index = 0;
+ stream.on('data', function(chunk) {
+ assert.equal(messages[index], chunk.toString());
+ index += 1;
+ });
+ stream.on('end', function() {
+ server.shutdown();
+ done();
});
});
it('should get an error status that the server throws', function(done) {
- port_picker.nextAvailablePort(function(port) {
- var server = new Server();
- server.bind(port);
- server.register('error', errorHandler);
- server.start();
-
- var channel = new grpc.Channel(port);
- var stream = client.makeRequest(
- channel,
- 'error',
- null,
- getDeadline(1));
-
- stream.on('data', function() {});
- stream.write(new Buffer('test'));
- stream.end();
- stream.on('status', function(status) {
- assert.equal(status.code, grpc.status.UNIMPLEMENTED);
- assert.equal(status.details, 'error details');
- server.shutdown();
- done();
- });
-
+ var server = new Server();
+ var port_num = server.bind('0.0.0.0:0');
+ server.register('error', errorHandler);
+ server.start();
+
+ var channel = new grpc.Channel('localhost:' + port_num);
+ var stream = client.makeRequest(
+ channel,
+ 'error',
+ null,
+ getDeadline(1));
+
+ stream.on('data', function() {});
+ stream.write(new Buffer('test'));
+ stream.end();
+ stream.on('status', function(status) {
+ assert.equal(status.code, grpc.status.UNIMPLEMENTED);
+ assert.equal(status.details, 'error details');
+ server.shutdown();
+ done();
});
});
});
@@ -136,46 +130,43 @@ describe('echo client', function() {
* and the insecure echo client test */
describe('secure echo client', function() {
it('should recieve echo responses', function(done) {
- port_picker.nextAvailablePort(function(port) {
- fs.readFile(ca_path, function(err, ca_data) {
+ fs.readFile(ca_path, function(err, ca_data) {
+ assert.ifError(err);
+ fs.readFile(key_path, function(err, key_data) {
assert.ifError(err);
- fs.readFile(key_path, function(err, key_data) {
+ fs.readFile(pem_path, function(err, pem_data) {
assert.ifError(err);
- fs.readFile(pem_path, function(err, pem_data) {
- assert.ifError(err);
- var creds = grpc.Credentials.createSsl(ca_data);
- var server_creds = grpc.ServerCredentials.createSsl(null,
- key_data,
- pem_data);
-
- var server = new Server({'credentials' : server_creds});
- server.bind(port, true);
- server.register('echo', echoHandler);
- server.start();
-
- var messages = ['echo1', 'echo2', 'echo3', 'echo4'];
- var channel = new grpc.Channel(port, {
- 'grpc.ssl_target_name_override' : 'foo.test.google.com',
- 'credentials' : creds
- });
- var stream = client.makeRequest(
- channel,
- 'echo');
-
- _(messages).map(function(val) {
- return new Buffer(val);
- }).pipe(stream);
- var index = 0;
- stream.on('data', function(chunk) {
- assert.equal(messages[index], chunk.toString());
- index += 1;
- });
- stream.on('end', function() {
- server.shutdown();
- done();
- });
+ var creds = grpc.Credentials.createSsl(ca_data);
+ var server_creds = grpc.ServerCredentials.createSsl(null,
+ key_data,
+ pem_data);
+
+ var server = new Server({'credentials' : server_creds});
+ var port_num = server.bind('0.0.0.0:0', true);
+ server.register('echo', echoHandler);
+ server.start();
+
+ var messages = ['echo1', 'echo2', 'echo3', 'echo4'];
+ var channel = new grpc.Channel('localhost:' + port_num, {
+ 'grpc.ssl_target_name_override' : 'foo.test.google.com',
+ 'credentials' : creds
+ });
+ var stream = client.makeRequest(
+ channel,
+ 'echo');
+
+ _(messages).map(function(val) {
+ return new Buffer(val);
+ }).pipe(stream);
+ var index = 0;
+ stream.on('data', function(chunk) {
+ assert.equal(messages[index], chunk.toString());
+ index += 1;
+ });
+ stream.on('end', function() {
+ server.shutdown();
+ done();
});
-
});
});
});
diff --git a/src/node/test/end_to_end_test.js b/src/node/test/end_to_end_test.js
index 40bb5f3bbd..db3834dbba 100644
--- a/src/node/test/end_to_end_test.js
+++ b/src/node/test/end_to_end_test.js
@@ -33,7 +33,6 @@
var assert = require('assert');
var grpc = require('bindings')('grpc.node');
-var port_picker = require('../port_picker');
/**
* This is used for testing functions with multiple asynchronous calls that
@@ -58,143 +57,139 @@ function multiDone(done, count) {
describe('end-to-end', function() {
it('should start and end a request without error', function(complete) {
- port_picker.nextAvailablePort(function(port) {
- var server = new grpc.Server();
- var done = multiDone(function() {
- complete();
- server.shutdown();
- }, 2);
- server.addHttp2Port(port);
- var channel = new grpc.Channel(port);
- var deadline = new Date();
- deadline.setSeconds(deadline.getSeconds() + 3);
- var status_text = 'xyz';
- var call = new grpc.Call(channel,
- 'dummy_method',
- deadline);
- call.startInvoke(function(event) {
- assert.strictEqual(event.type,
- grpc.completionType.INVOKE_ACCEPTED);
+ var server = new grpc.Server();
+ var done = multiDone(function() {
+ complete();
+ server.shutdown();
+ }, 2);
+ var port_num = server.addHttp2Port('0.0.0.0:0');
+ var channel = new grpc.Channel('localhost:' + port_num);
+ var deadline = new Date();
+ deadline.setSeconds(deadline.getSeconds() + 3);
+ var status_text = 'xyz';
+ var call = new grpc.Call(channel,
+ 'dummy_method',
+ deadline);
+ call.startInvoke(function(event) {
+ assert.strictEqual(event.type,
+ grpc.completionType.INVOKE_ACCEPTED);
- call.writesDone(function(event) {
- assert.strictEqual(event.type,
- grpc.completionType.FINISH_ACCEPTED);
- assert.strictEqual(event.data, grpc.opError.OK);
- });
- },function(event) {
+ call.writesDone(function(event) {
assert.strictEqual(event.type,
- grpc.completionType.CLIENT_METADATA_READ);
- },function(event) {
+ grpc.completionType.FINISH_ACCEPTED);
+ assert.strictEqual(event.data, grpc.opError.OK);
+ });
+ },function(event) {
+ assert.strictEqual(event.type,
+ grpc.completionType.CLIENT_METADATA_READ);
+ },function(event) {
+ assert.strictEqual(event.type, grpc.completionType.FINISHED);
+ var status = event.data;
+ assert.strictEqual(status.code, grpc.status.OK);
+ assert.strictEqual(status.details, status_text);
+ done();
+ }, 0);
+
+ server.start();
+ server.requestCall(function(event) {
+ assert.strictEqual(event.type, grpc.completionType.SERVER_RPC_NEW);
+ var server_call = event.call;
+ assert.notEqual(server_call, null);
+ server_call.serverAccept(function(event) {
assert.strictEqual(event.type, grpc.completionType.FINISHED);
- var status = event.data;
- assert.strictEqual(status.code, grpc.status.OK);
- assert.strictEqual(status.details, status_text);
- done();
}, 0);
+ server_call.serverEndInitialMetadata(0);
+ server_call.startWriteStatus(
+ grpc.status.OK,
+ status_text,
+ function(event) {
+ assert.strictEqual(event.type,
+ grpc.completionType.FINISH_ACCEPTED);
+ assert.strictEqual(event.data, grpc.opError.OK);
+ done();
+ });
+ });
+ });
- server.start();
- server.requestCall(function(event) {
- assert.strictEqual(event.type, grpc.completionType.SERVER_RPC_NEW);
- var server_call = event.call;
- assert.notEqual(server_call, null);
- server_call.serverAccept(function(event) {
- assert.strictEqual(event.type, grpc.completionType.FINISHED);
- }, 0);
- server_call.serverEndInitialMetadata(0);
- server_call.startWriteStatus(
- grpc.status.OK,
- status_text,
- function(event) {
+ it('should send and receive data without error', function(complete) {
+ var req_text = 'client_request';
+ var reply_text = 'server_response';
+ var server = new grpc.Server();
+ var done = multiDone(function() {
+ complete();
+ server.shutdown();
+ }, 6);
+ var port_num = server.addHttp2Port('0.0.0.0:0');
+ var channel = new grpc.Channel('localhost:' + port_num);
+ var deadline = new Date();
+ deadline.setSeconds(deadline.getSeconds() + 3);
+ var status_text = 'success';
+ var call = new grpc.Call(channel,
+ 'dummy_method',
+ deadline);
+ call.startInvoke(function(event) {
+ assert.strictEqual(event.type,
+ grpc.completionType.INVOKE_ACCEPTED);
+ call.startWrite(
+ new Buffer(req_text),
+ function(event) {
+ assert.strictEqual(event.type,
+ grpc.completionType.WRITE_ACCEPTED);
+ assert.strictEqual(event.data, grpc.opError.OK);
+ call.writesDone(function(event) {
assert.strictEqual(event.type,
grpc.completionType.FINISH_ACCEPTED);
assert.strictEqual(event.data, grpc.opError.OK);
done();
});
+ }, 0);
+ call.startRead(function(event) {
+ assert.strictEqual(event.type, grpc.completionType.READ);
+ assert.strictEqual(event.data.toString(), reply_text);
+ done();
});
- });
- });
+ },function(event) {
+ assert.strictEqual(event.type,
+ grpc.completionType.CLIENT_METADATA_READ);
+ done();
+ },function(event) {
+ assert.strictEqual(event.type, grpc.completionType.FINISHED);
+ var status = event.data;
+ assert.strictEqual(status.code, grpc.status.OK);
+ assert.strictEqual(status.details, status_text);
+ done();
+ }, 0);
- it('should send and receive data without error', function(complete) {
- port_picker.nextAvailablePort(function(port) {
- var req_text = 'client_request';
- var reply_text = 'server_response';
- var server = new grpc.Server();
- var done = multiDone(function() {
- complete();
- server.shutdown();
- }, 6);
- server.addHttp2Port(port);
- var channel = new grpc.Channel(port);
- var deadline = new Date();
- deadline.setSeconds(deadline.getSeconds() + 3);
- var status_text = 'success';
- var call = new grpc.Call(channel,
- 'dummy_method',
- deadline);
- call.startInvoke(function(event) {
- assert.strictEqual(event.type,
- grpc.completionType.INVOKE_ACCEPTED);
- call.startWrite(
- new Buffer(req_text),
+ server.start();
+ server.requestCall(function(event) {
+ assert.strictEqual(event.type, grpc.completionType.SERVER_RPC_NEW);
+ var server_call = event.call;
+ assert.notEqual(server_call, null);
+ server_call.serverAccept(function(event) {
+ assert.strictEqual(event.type, grpc.completionType.FINISHED);
+ done();
+ });
+ server_call.serverEndInitialMetadata(0);
+ server_call.startRead(function(event) {
+ assert.strictEqual(event.type, grpc.completionType.READ);
+ assert.strictEqual(event.data.toString(), req_text);
+ server_call.startWrite(
+ new Buffer(reply_text),
function(event) {
assert.strictEqual(event.type,
grpc.completionType.WRITE_ACCEPTED);
- assert.strictEqual(event.data, grpc.opError.OK);
- call.writesDone(function(event) {
- assert.strictEqual(event.type,
- grpc.completionType.FINISH_ACCEPTED);
- assert.strictEqual(event.data, grpc.opError.OK);
- done();
- });
+ assert.strictEqual(event.data,
+ grpc.opError.OK);
+ server_call.startWriteStatus(
+ grpc.status.OK,
+ status_text,
+ function(event) {
+ assert.strictEqual(event.type,
+ grpc.completionType.FINISH_ACCEPTED);
+ assert.strictEqual(event.data, grpc.opError.OK);
+ done();
+ });
}, 0);
- call.startRead(function(event) {
- assert.strictEqual(event.type, grpc.completionType.READ);
- assert.strictEqual(event.data.toString(), reply_text);
- done();
- });
- },function(event) {
- assert.strictEqual(event.type,
- grpc.completionType.CLIENT_METADATA_READ);
- done();
- },function(event) {
- assert.strictEqual(event.type, grpc.completionType.FINISHED);
- var status = event.data;
- assert.strictEqual(status.code, grpc.status.OK);
- assert.strictEqual(status.details, status_text);
- done();
- }, 0);
-
- server.start();
- server.requestCall(function(event) {
- assert.strictEqual(event.type, grpc.completionType.SERVER_RPC_NEW);
- var server_call = event.call;
- assert.notEqual(server_call, null);
- server_call.serverAccept(function(event) {
- assert.strictEqual(event.type, grpc.completionType.FINISHED);
- done();
- });
- server_call.serverEndInitialMetadata(0);
- server_call.startRead(function(event) {
- assert.strictEqual(event.type, grpc.completionType.READ);
- assert.strictEqual(event.data.toString(), req_text);
- server_call.startWrite(
- new Buffer(reply_text),
- function(event) {
- assert.strictEqual(event.type,
- grpc.completionType.WRITE_ACCEPTED);
- assert.strictEqual(event.data,
- grpc.opError.OK);
- server_call.startWriteStatus(
- grpc.status.OK,
- status_text,
- function(event) {
- assert.strictEqual(event.type,
- grpc.completionType.FINISH_ACCEPTED);
- assert.strictEqual(event.data, grpc.opError.OK);
- done();
- });
- }, 0);
- });
});
});
});
diff --git a/src/node/port_picker.js b/src/node/test/interop_sanity_test.js
index ad82f2a7f8..b0fc8f8200 100644
--- a/src/node/port_picker.js
+++ b/src/node/test/interop_sanity_test.js
@@ -31,22 +31,41 @@
*
*/
-var net = require('net');
+var interop_server = require('../interop/interop_server.js');
+var interop_client = require('../interop/interop_client.js');
-/**
- * Finds a free port that a server can bind to, in the format
- * "address:port"
- * @param {function(string)} cb The callback that should execute when the port
- * is available
- */
-function nextAvailablePort(cb) {
- var server = net.createServer();
- server.listen(function() {
- var address = server.address();
- server.close(function() {
- cb(address.address + ':' + address.port.toString());
- });
- });
-}
+var server;
+
+var port;
-exports.nextAvailablePort = nextAvailablePort;
+var name_override = 'foo.test.google.com';
+
+describe('Interop tests', function() {
+ before(function(done) {
+ var server_obj = interop_server.getServer(0, true);
+ server = server_obj.server;
+ server.listen();
+ port = 'localhost:' + server_obj.port;
+ done();
+ });
+ // This depends on not using a binary stream
+ it.skip('should pass empty_unary', function(done) {
+ interop_client.runTest(port, name_override, 'empty_unary', true, done);
+ });
+ it('should pass large_unary', function(done) {
+ interop_client.runTest(port, name_override, 'large_unary', true, done);
+ });
+ it('should pass client_streaming', function(done) {
+ interop_client.runTest(port, name_override, 'client_streaming', true, done);
+ });
+ it('should pass server_streaming', function(done) {
+ interop_client.runTest(port, name_override, 'server_streaming', true, done);
+ });
+ it('should pass ping_pong', function(done) {
+ interop_client.runTest(port, name_override, 'ping_pong', true, done);
+ });
+ // This depends on the new invoke API
+ it.skip('should pass empty_stream', function(done) {
+ interop_client.runTest(port, name_override, 'empty_stream', true, done);
+ });
+});
diff --git a/src/node/test/math_client_test.js b/src/node/test/math_client_test.js
index 45c956d179..0e365bf870 100644
--- a/src/node/test/math_client_test.js
+++ b/src/node/test/math_client_test.js
@@ -32,7 +32,6 @@
*/
var assert = require('assert');
-var port_picker = require('../port_picker');
var grpc = require('..');
var math = grpc.load(__dirname + '/../examples/math.proto').math;
@@ -50,18 +49,17 @@ var server = require('../examples/math_server.js');
describe('Math client', function() {
before(function(done) {
- port_picker.nextAvailablePort(function(port) {
- server.bind(port).listen();
- math_client = new math.Math(port);
- done();
- });
+ var port_num = server.bind('0.0.0.0:0');
+ server.listen();
+ math_client = new math.Math('localhost:' + port_num);
+ done();
});
after(function() {
server.shutdown();
});
it('should handle a single request', function(done) {
var arg = {dividend: 7, divisor: 4};
- var call = math_client.Div(arg, function handleDivResult(err, value) {
+ var call = math_client.div(arg, function handleDivResult(err, value) {
assert.ifError(err);
assert.equal(value.quotient, 1);
assert.equal(value.remainder, 3);
@@ -72,7 +70,7 @@ describe('Math client', function() {
});
});
it('should handle a server streaming request', function(done) {
- var call = math_client.Fib({limit: 7});
+ var call = math_client.fib({limit: 7});
var expected_results = [1, 1, 2, 3, 5, 8, 13];
var next_expected = 0;
call.on('data', function checkResponse(value) {
@@ -85,7 +83,7 @@ describe('Math client', function() {
});
});
it('should handle a client streaming request', function(done) {
- var call = math_client.Sum(function handleSumResult(err, value) {
+ var call = math_client.sum(function handleSumResult(err, value) {
assert.ifError(err);
assert.equal(value.num, 21);
});
@@ -103,7 +101,7 @@ describe('Math client', function() {
assert.equal(value.quotient, index);
assert.equal(value.remainder, 1);
}
- var call = math_client.DivMany();
+ var call = math_client.divMany();
var response_index = 0;
call.on('data', function(value) {
checkResponse(response_index, value);
diff --git a/src/node/test/server_test.js b/src/node/test/server_test.js
index 79f7b32948..61aef4677e 100644
--- a/src/node/test/server_test.js
+++ b/src/node/test/server_test.js
@@ -34,7 +34,6 @@
var assert = require('assert');
var grpc = require('bindings')('grpc.node');
var Server = require('../server');
-var port_picker = require('../port_picker');
/**
* This is used for testing functions with multiple asynchronous calls that
@@ -68,54 +67,52 @@ function echoHandler(stream) {
describe('echo server', function() {
it('should echo inputs as responses', function(done) {
done = multiDone(done, 4);
- port_picker.nextAvailablePort(function(port) {
- var server = new Server();
- server.bind(port);
- server.register('echo', echoHandler);
- server.start();
+ var server = new Server();
+ var port_num = server.bind('[::]:0');
+ server.register('echo', echoHandler);
+ server.start();
- var req_text = 'echo test string';
- var status_text = 'OK';
+ var req_text = 'echo test string';
+ var status_text = 'OK';
- var channel = new grpc.Channel(port);
- var deadline = new Date();
- deadline.setSeconds(deadline.getSeconds() + 3);
- var call = new grpc.Call(channel,
- 'echo',
- deadline);
- call.startInvoke(function(event) {
- assert.strictEqual(event.type,
- grpc.completionType.INVOKE_ACCEPTED);
- call.startWrite(
- new Buffer(req_text),
- function(event) {
+ var channel = new grpc.Channel('localhost:' + port_num);
+ var deadline = new Date();
+ deadline.setSeconds(deadline.getSeconds() + 3);
+ var call = new grpc.Call(channel,
+ 'echo',
+ deadline);
+ call.startInvoke(function(event) {
+ assert.strictEqual(event.type,
+ grpc.completionType.INVOKE_ACCEPTED);
+ call.startWrite(
+ new Buffer(req_text),
+ function(event) {
+ assert.strictEqual(event.type,
+ grpc.completionType.WRITE_ACCEPTED);
+ assert.strictEqual(event.data, grpc.opError.OK);
+ call.writesDone(function(event) {
assert.strictEqual(event.type,
- grpc.completionType.WRITE_ACCEPTED);
+ grpc.completionType.FINISH_ACCEPTED);
assert.strictEqual(event.data, grpc.opError.OK);
- call.writesDone(function(event) {
- assert.strictEqual(event.type,
- grpc.completionType.FINISH_ACCEPTED);
- assert.strictEqual(event.data, grpc.opError.OK);
- done();
- });
- }, 0);
- call.startRead(function(event) {
- assert.strictEqual(event.type, grpc.completionType.READ);
- assert.strictEqual(event.data.toString(), req_text);
- done();
- });
- },function(event) {
- assert.strictEqual(event.type,
- grpc.completionType.CLIENT_METADATA_READ);
+ done();
+ });
+ }, 0);
+ call.startRead(function(event) {
+ assert.strictEqual(event.type, grpc.completionType.READ);
+ assert.strictEqual(event.data.toString(), req_text);
done();
- },function(event) {
- assert.strictEqual(event.type, grpc.completionType.FINISHED);
- var status = event.data;
- assert.strictEqual(status.code, grpc.status.OK);
- assert.strictEqual(status.details, status_text);
- server.shutdown();
- done();
- }, 0);
- });
+ });
+ },function(event) {
+ assert.strictEqual(event.type,
+ grpc.completionType.CLIENT_METADATA_READ);
+ done();
+ },function(event) {
+ assert.strictEqual(event.type, grpc.completionType.FINISHED);
+ var status = event.data;
+ assert.strictEqual(status.code, grpc.status.OK);
+ assert.strictEqual(status.details, status_text);
+ server.shutdown();
+ done();
+ }, 0);
});
});
diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js
index 8d0d8ec3bc..34f1a156eb 100644
--- a/src/node/test/surface_test.js
+++ b/src/node/test/surface_test.js
@@ -59,9 +59,9 @@ describe('Surface server constructor', function() {
assert.throws(function() {
new Server({
'math.Math': {
- 'Div': function() {},
- 'DivMany': function() {},
- 'Fib': function() {}
+ 'div': function() {},
+ 'divMany': function() {},
+ 'fib': function() {}
}
});
}, /math.Math.Sum/);
diff --git a/src/php/ext/grpc/credentials.c b/src/php/ext/grpc/credentials.c
index 2a83d1cbc1..c63196bf90 100644
--- a/src/php/ext/grpc/credentials.c
+++ b/src/php/ext/grpc/credentials.c
@@ -77,24 +77,23 @@ PHP_METHOD(Credentials, createDefault) {
*/
PHP_METHOD(Credentials, createSsl) {
char *pem_root_certs;
- char *pem_private_key = NULL;
- char *pem_cert_chain = NULL;
+ grpc_ssl_pem_key_cert_pair pem_key_cert_pair;
int root_certs_length, private_key_length = 0, cert_chain_length = 0;
/* "s|s!s! == 1 string, 2 optional nullable strings */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!s!",
&pem_root_certs, &root_certs_length,
- &pem_private_key, &private_key_length,
- &pem_cert_chain, &cert_chain_length) == FAILURE) {
+ &pem_key_cert_pair.private_key, &private_key_length,
+ &pem_key_cert_pair.cert_chain,
+ &cert_chain_length) == FAILURE) {
zend_throw_exception(spl_ce_InvalidArgumentException,
"createSsl expects 1 to 3 strings", 1 TSRMLS_CC);
return;
}
grpc_credentials *creds = grpc_ssl_credentials_create(
- (unsigned char *)pem_root_certs, (size_t)root_certs_length,
- (unsigned char *)pem_private_key, (size_t)private_key_length,
- (unsigned char *)pem_cert_chain, (size_t)cert_chain_length);
+ pem_root_certs,
+ pem_key_cert_pair.private_key == NULL ? NULL : &pem_key_cert_pair);
zval *creds_object = grpc_php_wrap_credentials(creds);
RETURN_DESTROY_ZVAL(creds_object);
}
diff --git a/src/php/ext/grpc/server_credentials.c b/src/php/ext/grpc/server_credentials.c
index 1f8e58aa4d..3d43d6a78c 100644
--- a/src/php/ext/grpc/server_credentials.c
+++ b/src/php/ext/grpc/server_credentials.c
@@ -66,24 +66,22 @@ zval *grpc_php_wrap_server_credentials(grpc_server_credentials *wrapped) {
*/
PHP_METHOD(ServerCredentials, createSsl) {
char *pem_root_certs = 0;
- char *pem_private_key;
- char *pem_cert_chain;
+ grpc_ssl_pem_key_cert_pair pem_key_cert_pair;
int root_certs_length = 0, private_key_length, cert_chain_length;
/* "s!ss" == 1 nullable string, 2 strings */
+ /* TODO: support multiple key cert pairs. */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!ss", &pem_root_certs,
- &root_certs_length, &pem_private_key,
- &private_key_length, &pem_cert_chain,
+ &root_certs_length, &pem_key_cert_pair.private_key,
+ &private_key_length, &pem_key_cert_pair.cert_chain,
&cert_chain_length) == FAILURE) {
zend_throw_exception(spl_ce_InvalidArgumentException,
"createSsl expects 3 strings", 1 TSRMLS_CC);
return;
}
- grpc_server_credentials *creds = grpc_ssl_server_credentials_create(
- (unsigned char *)pem_root_certs, (size_t)root_certs_length,
- (unsigned char *)pem_private_key, (size_t)private_key_length,
- (unsigned char *)pem_cert_chain, (size_t)cert_chain_length);
+ grpc_server_credentials *creds =
+ grpc_ssl_server_credentials_create(pem_root_certs, &pem_key_cert_pair, 1);
zval *creds_object = grpc_php_wrap_server_credentials(creds);
RETURN_DESTROY_ZVAL(creds_object);
}
diff --git a/src/ruby/bin/interop/interop_client.rb b/src/ruby/bin/interop/interop_client.rb
index 0ce10d9e30..0ea7f376be 100755
--- a/src/ruby/bin/interop/interop_client.rb
+++ b/src/ruby/bin/interop/interop_client.rb
@@ -107,11 +107,11 @@ class PingPongPlayer
@msg_sizes.each do |m|
req_size, resp_size = m
req = req_cls.new(payload: Payload.new(body: nulls(req_size)),
- response_type: COMPRESSABLE,
+ response_type: :COMPRESSABLE,
response_parameters: [p_cls.new(size: resp_size)])
yield req
resp = @queue.pop
- assert_equal(PayloadType.lookup(COMPRESSABLE), resp.payload.type,
+ assert_equal(:COMPRESSABLE, resp.payload.type,
'payload type is wrong')
assert_equal(resp_size, resp.payload.body.length,
'payload body #{i} has the wrong length')
@@ -149,11 +149,13 @@ class NamedTests
# FAILED
def large_unary
req_size, wanted_response_size = 271_828, 314_159
- payload = Payload.new(type: COMPRESSABLE, body: nulls(req_size))
- req = SimpleRequest.new(response_type: COMPRESSABLE,
+ payload = Payload.new(type: :COMPRESSABLE, body: nulls(req_size))
+ req = SimpleRequest.new(response_type: :COMPRESSABLE,
response_size: wanted_response_size,
payload: payload)
resp = @stub.unary_call(req)
+ assert_equal(:COMPRESSABLE, resp.payload.type,
+ 'large_unary: payload had the wrong type')
assert_equal(wanted_response_size, resp.payload.body.length,
'large_unary: payload had the wrong length')
assert_equal(nulls(wanted_response_size), resp.payload.body,
@@ -185,12 +187,12 @@ class NamedTests
def server_streaming
msg_sizes = [31_415, 9, 2653, 58_979]
response_spec = msg_sizes.map { |s| ResponseParameters.new(size: s) }
- req = StreamingOutputCallRequest.new(response_type: COMPRESSABLE,
+ req = StreamingOutputCallRequest.new(response_type: :COMPRESSABLE,
response_parameters: response_spec)
resps = @stub.streaming_output_call(req)
resps.each_with_index do |r, i|
assert i < msg_sizes.length, 'too many responses'
- assert_equal(PayloadType.lookup(COMPRESSABLE), r.payload.type,
+ assert_equal(:COMPRESSABLE, r.payload.type,
'payload type is wrong')
assert_equal(msg_sizes[i], r.payload.body.length,
'payload body #{i} has the wrong length')
@@ -235,7 +237,7 @@ def parse_options
end
end.parse!
- %w(server_host, server_port, test_case).each do |arg|
+ %w(server_host server_port test_case).each do |arg|
if options[arg].nil?
fail(OptionParser::MissingArgument, "please specify --#{arg}")
end
diff --git a/src/ruby/bin/interop/interop_server.rb b/src/ruby/bin/interop/interop_server.rb
index 9273dcdf91..1a08eb97df 100755
--- a/src/ruby/bin/interop/interop_server.rb
+++ b/src/ruby/bin/interop/interop_server.rb
@@ -104,7 +104,7 @@ class TestTarget < Grpc::Testing::TestService::Service
def unary_call(simple_req, _call)
req_size = simple_req.response_size
- SimpleResponse.new(payload: Payload.new(type: COMPRESSABLE,
+ SimpleResponse.new(payload: Payload.new(type: :COMPRESSABLE,
body: nulls(req_size)))
end
diff --git a/src/ruby/ext/grpc/extconf.rb b/src/ruby/ext/grpc/extconf.rb
index e948504e9e..a6dbbf3aca 100644
--- a/src/ruby/ext/grpc/extconf.rb
+++ b/src/ruby/ext/grpc/extconf.rb
@@ -68,7 +68,7 @@ $CFLAGS << ' -Wno-return-type '
$CFLAGS << ' -Wall '
$CFLAGS << ' -pedantic '
-$LDFLAGS << ' -lgrpc -lgpr -levent -levent_pthreads -levent_core'
+$LDFLAGS << ' -lgrpc -lgpr'
# crash('need grpc lib') unless have_library('grpc', 'grpc_channel_destroy')
#
diff --git a/src/ruby/ext/grpc/rb_credentials.c b/src/ruby/ext/grpc/rb_credentials.c
index 5dec51824d..31f47f3b76 100644
--- a/src/ruby/ext/grpc/rb_credentials.c
+++ b/src/ruby/ext/grpc/rb_credentials.c
@@ -214,6 +214,7 @@ static VALUE grpc_rb_credentials_init(int argc, VALUE *argv, VALUE self) {
VALUE pem_cert_chain = Qnil;
grpc_rb_credentials *wrapper = NULL;
grpc_credentials *creds = NULL;
+ /* TODO: Remove mandatory arg when we support default roots. */
/* "12" == 1 mandatory arg, 2 (credentials) is optional */
rb_scan_args(argc, argv, "12", &pem_root_certs, &pem_private_key,
&pem_cert_chain);
@@ -225,22 +226,12 @@ static VALUE grpc_rb_credentials_init(int argc, VALUE *argv, VALUE self) {
return Qnil;
}
if (pem_private_key == Qnil && pem_cert_chain == Qnil) {
- creds = grpc_ssl_credentials_create(RSTRING_PTR(pem_root_certs),
- RSTRING_LEN(pem_root_certs), NULL, 0,
- NULL, 0);
- } else if (pem_cert_chain == Qnil) {
- creds = grpc_ssl_credentials_create(
- RSTRING_PTR(pem_root_certs), RSTRING_LEN(pem_root_certs),
- RSTRING_PTR(pem_private_key), RSTRING_LEN(pem_private_key),
- RSTRING_PTR(pem_cert_chain), RSTRING_LEN(pem_cert_chain));
- } else if (pem_private_key == Qnil) {
- creds = grpc_ssl_credentials_create(
- RSTRING_PTR(pem_root_certs), RSTRING_LEN(pem_root_certs), NULL, 0,
- RSTRING_PTR(pem_cert_chain), RSTRING_LEN(pem_cert_chain));
+ creds = grpc_ssl_credentials_create(RSTRING_PTR(pem_root_certs), NULL);
} else {
+ grpc_ssl_pem_key_cert_pair key_cert_pair = {RSTRING_PTR(pem_private_key),
+ RSTRING_PTR(pem_cert_chain)};
creds = grpc_ssl_credentials_create(
- RSTRING_PTR(pem_root_certs), RSTRING_LEN(pem_root_certs),
- RSTRING_PTR(pem_private_key), RSTRING_LEN(pem_private_key), NULL, 0);
+ RSTRING_PTR(pem_root_certs), &key_cert_pair);
}
if (creds == NULL) {
rb_raise(rb_eRuntimeError, "could not create a credentials, not sure why");
diff --git a/src/ruby/ext/grpc/rb_server_credentials.c b/src/ruby/ext/grpc/rb_server_credentials.c
index e534c11444..4f6c67ea5e 100644
--- a/src/ruby/ext/grpc/rb_server_credentials.c
+++ b/src/ruby/ext/grpc/rb_server_credentials.c
@@ -145,8 +145,10 @@ static ID id_pem_cert_chain;
static VALUE grpc_rb_server_credentials_init(VALUE self, VALUE pem_root_certs,
VALUE pem_private_key,
VALUE pem_cert_chain) {
+ /* TODO support multiple key cert pairs in the ruby API. */
grpc_rb_server_credentials *wrapper = NULL;
grpc_server_credentials *creds = NULL;
+ grpc_ssl_pem_key_cert_pair key_cert_pair = {NULL, NULL};
Data_Get_Struct(self, grpc_rb_server_credentials, wrapper);
if (pem_cert_chain == Qnil) {
rb_raise(rb_eRuntimeError,
@@ -157,15 +159,13 @@ static VALUE grpc_rb_server_credentials_init(VALUE self, VALUE pem_root_certs,
"could not create a server credential: nil pem_private_key");
return Qnil;
}
+ key_cert_pair.private_key = RSTRING_PTR(pem_private_key);
+ key_cert_pair.cert_chain = RSTRING_PTR(pem_cert_chain);
if (pem_root_certs == Qnil) {
- creds = grpc_ssl_server_credentials_create(
- NULL, 0, RSTRING_PTR(pem_private_key), RSTRING_LEN(pem_private_key),
- RSTRING_PTR(pem_cert_chain), RSTRING_LEN(pem_cert_chain));
+ creds = grpc_ssl_server_credentials_create(NULL, &key_cert_pair, 1);
} else {
- creds = grpc_ssl_server_credentials_create(
- RSTRING_PTR(pem_root_certs), RSTRING_LEN(pem_root_certs),
- RSTRING_PTR(pem_private_key), RSTRING_LEN(pem_private_key),
- RSTRING_PTR(pem_cert_chain), RSTRING_LEN(pem_cert_chain));
+ creds = grpc_ssl_server_credentials_create(RSTRING_PTR(pem_root_certs),
+ &key_cert_pair, 1);
}
if (creds == NULL) {
rb_raise(rb_eRuntimeError, "could not create a credentials, not sure why");
diff --git a/test/core/end2end/data/prod_roots_certs.c b/test/core/end2end/data/prod_roots_certs.c
index 21a199ce37..3b66d236c3 100644
--- a/test/core/end2end/data/prod_roots_certs.c
+++ b/test/core/end2end/data/prod_roots_certs.c
@@ -31,7 +31,7 @@
*
*/
-unsigned char prod_roots_certs[] = {
+const char prod_roots_certs[] = {
0x23, 0x20, 0x49, 0x73, 0x73, 0x75, 0x65, 0x72, 0x3a, 0x20, 0x43, 0x4e,
0x3d, 0x47, 0x54, 0x45, 0x20, 0x43, 0x79, 0x62, 0x65, 0x72, 0x54, 0x72,
0x75, 0x73, 0x74, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x52,
@@ -11270,5 +11270,4 @@ unsigned char prod_roots_certs[] = {
0x33, 0x50, 0x59, 0x74, 0x6c, 0x4e, 0x58, 0x4c, 0x66, 0x62, 0x51, 0x34,
0x64, 0x64, 0x49, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44,
0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45,
- 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a};
-unsigned int prod_roots_certs_size = 134862;
+ 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x00};
diff --git a/test/core/end2end/data/server1_cert.c b/test/core/end2end/data/server1_cert.c
index da1d36653c..134b9cb98e 100644
--- a/test/core/end2end/data/server1_cert.c
+++ b/test/core/end2end/data/server1_cert.c
@@ -31,7 +31,7 @@
*
*/
-unsigned char test_server1_cert[] = {
+const char test_server1_cert[] = {
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43,
0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d,
0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, 0x6d, 0x7a, 0x43, 0x43,
@@ -112,5 +112,4 @@ unsigned char test_server1_cert[] = {
0x32, 0x77, 0x65, 0x2f, 0x4b, 0x44, 0x34, 0x6f, 0x6a, 0x66, 0x39, 0x73,
0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x43,
0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d,
- 0x2d, 0x2d, 0x2d, 0x0a};
-unsigned int test_server1_cert_size = 964;
+ 0x2d, 0x2d, 0x2d, 0x0a, 0x00};
diff --git a/test/core/end2end/data/server1_key.c b/test/core/end2end/data/server1_key.c
index 3540505467..992d3c032a 100644
--- a/test/core/end2end/data/server1_key.c
+++ b/test/core/end2end/data/server1_key.c
@@ -31,7 +31,7 @@
*
*/
-unsigned char test_server1_key[] = {
+const char test_server1_key[] = {
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x52,
0x53, 0x41, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b,
0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43,
@@ -105,5 +105,4 @@ unsigned char test_server1_key[] = {
0x6e, 0x68, 0x66, 0x66, 0x46, 0x79, 0x65, 0x37, 0x53, 0x42, 0x58, 0x79,
0x61, 0x67, 0x3d, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e,
0x44, 0x20, 0x52, 0x53, 0x41, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54,
- 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a};
-unsigned int test_server1_key_size = 887;
+ 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x00};
diff --git a/test/core/end2end/data/ssl_test_data.h b/test/core/end2end/data/ssl_test_data.h
index 6ac19945b2..3456ebebd4 100644
--- a/test/core/end2end/data/ssl_test_data.h
+++ b/test/core/end2end/data/ssl_test_data.h
@@ -34,14 +34,10 @@
#ifndef __GRPC_TEST_END2END_DATA_SSL_TEST_DATA_H__
#define __GRPC_TEST_END2END_DATA_SSL_TEST_DATA_H__
-extern unsigned char test_root_cert[];
-extern unsigned int test_root_cert_size;
-extern unsigned char test_server1_cert[];
-extern unsigned int test_server1_cert_size;
-extern unsigned char test_server1_key[];
-extern unsigned int test_server1_key_size;
+extern const char test_root_cert[];
+extern const char test_server1_cert[];
+extern const char test_server1_key[];
-extern unsigned char prod_roots_certs[];
-extern unsigned int prod_roots_certs_size;
+extern const char prod_roots_certs[];
#endif /* __GRPC_TEST_END2END_DATA_SSL_TEST_DATA_H__ */
diff --git a/test/core/end2end/data/test_root_cert.c b/test/core/end2end/data/test_root_cert.c
index fd01953ccb..f358b0b79a 100644
--- a/test/core/end2end/data/test_root_cert.c
+++ b/test/core/end2end/data/test_root_cert.c
@@ -31,7 +31,7 @@
*
*/
-unsigned char test_root_cert[] = {
+const char test_root_cert[] = {
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43,
0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d,
0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, 0x49, 0x7a, 0x43, 0x43,
@@ -98,5 +98,4 @@ unsigned char test_root_cert[] = {
0x31, 0x59, 0x75, 0x58, 0x32, 0x72, 0x6e, 0x65, 0x78, 0x30, 0x4a, 0x68,
0x75, 0x54, 0x51, 0x66, 0x63, 0x49, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d,
0x2d, 0x45, 0x4e, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49,
- 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a};
-unsigned int test_root_cert_size = 802;
+ 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x00};
diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c
index 7718d30b3e..e5cdec8ea7 100644
--- a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c
+++ b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c
@@ -98,8 +98,8 @@ void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) {
static void chttp2_init_client_simple_ssl_secure_fullstack(
grpc_end2end_test_fixture *f, grpc_channel_args *client_args) {
- grpc_credentials *ssl_creds = grpc_ssl_credentials_create(
- test_root_cert, test_root_cert_size, NULL, 0, NULL, 0);
+ grpc_credentials *ssl_creds =
+ grpc_ssl_credentials_create(test_root_cert, NULL);
grpc_arg ssl_name_override = {GRPC_ARG_STRING,
GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
{"foo.test.google.com"}};
@@ -111,9 +111,10 @@ static void chttp2_init_client_simple_ssl_secure_fullstack(
static void chttp2_init_server_simple_ssl_secure_fullstack(
grpc_end2end_test_fixture *f, grpc_channel_args *server_args) {
- grpc_server_credentials *ssl_creds = grpc_ssl_server_credentials_create(
- NULL, 0, test_server1_key, test_server1_key_size, test_server1_cert,
- test_server1_cert_size);
+ grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key,
+ test_server1_cert};
+ grpc_server_credentials *ssl_creds =
+ grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1);
chttp2_init_server_secure_fullstack(f, server_args, ssl_creds);
}
diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c b/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c
index bb8af88c54..8bfa465696 100644
--- a/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c
+++ b/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c
@@ -99,8 +99,7 @@ void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) {
static void chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack(
grpc_end2end_test_fixture *f, grpc_channel_args *client_args) {
- grpc_credentials *ssl_creds = grpc_ssl_credentials_create(
- test_root_cert, test_root_cert_size, NULL, 0, NULL, 0);
+ grpc_credentials *ssl_creds = grpc_ssl_credentials_create(test_root_cert, NULL);
grpc_credentials *oauth2_creds =
grpc_fake_oauth2_credentials_create("Bearer aaslkfjs424535asdf", 1);
grpc_credentials *ssl_oauth2_creds =
@@ -118,9 +117,10 @@ static void chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack(
static void chttp2_init_server_simple_ssl_secure_fullstack(
grpc_end2end_test_fixture *f, grpc_channel_args *server_args) {
- grpc_server_credentials *ssl_creds = grpc_ssl_server_credentials_create(
- NULL, 0, test_server1_key, test_server1_key_size, test_server1_cert,
- test_server1_cert_size);
+ grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {test_server1_key,
+ test_server1_cert};
+ grpc_server_credentials *ssl_creds =
+ grpc_ssl_server_credentials_create(NULL, &pem_key_cert_pair, 1);
chttp2_init_server_secure_fullstack(f, server_args, ssl_creds);
}
diff --git a/test/core/fling/server.c b/test/core/fling/server.c
index d68fbe7c3c..f811aac284 100644
--- a/test/core/fling/server.c
+++ b/test/core/fling/server.c
@@ -101,9 +101,10 @@ int main(int argc, char **argv) {
cq = grpc_completion_queue_create();
if (secure) {
- grpc_server_credentials *ssl_creds = grpc_ssl_server_credentials_create(
- NULL, 0, test_server1_key, test_server1_key_size, test_server1_cert,
- test_server1_cert_size);
+ grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {test_server1_key,
+ test_server1_cert};
+ grpc_server_credentials *ssl_creds =
+ grpc_ssl_server_credentials_create(NULL, &pem_key_cert_pair, 1);
server = grpc_secure_server_create(ssl_creds, cq, NULL);
GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr));
grpc_server_credentials_release(ssl_creds);
diff --git a/test/core/iomgr/poll_kick_test.c b/test/core/iomgr/poll_kick_test.c
index 9f0d0f38b3..c30a7b9ee0 100644
--- a/test/core/iomgr/poll_kick_test.c
+++ b/test/core/iomgr/poll_kick_test.c
@@ -33,16 +33,17 @@
#include "src/core/iomgr/pollset_kick.h"
+#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "test/core/util/test_config.h"
-static void test_allocation() {
+static void test_allocation(void) {
grpc_pollset_kick_state state;
grpc_pollset_kick_init(&state);
grpc_pollset_kick_destroy(&state);
}
-static void test_non_kick() {
+static void test_non_kick(void) {
grpc_pollset_kick_state state;
int fd;
@@ -54,7 +55,7 @@ static void test_non_kick() {
grpc_pollset_kick_destroy(&state);
}
-static void test_basic_kick() {
+static void test_basic_kick(void) {
/* Kicked during poll */
grpc_pollset_kick_state state;
int fd;
@@ -73,7 +74,7 @@ static void test_basic_kick() {
grpc_pollset_kick_destroy(&state);
}
-static void test_non_poll_kick() {
+static void test_non_poll_kick(void) {
/* Kick before entering poll */
grpc_pollset_kick_state state;
int fd;
@@ -86,6 +87,26 @@ static void test_non_poll_kick() {
grpc_pollset_kick_destroy(&state);
}
+#define GRPC_MAX_CACHED_PIPES 50
+
+static void test_over_free(void) {
+ /* Check high watermark pipe free logic */
+ int i;
+ struct grpc_pollset_kick_state *kick_state =
+ gpr_malloc(sizeof(grpc_pollset_kick_state) * GRPC_MAX_CACHED_PIPES);
+ for (i = 0; i < GRPC_MAX_CACHED_PIPES; ++i) {
+ int fd;
+ grpc_pollset_kick_init(&kick_state[i]);
+ fd = grpc_pollset_kick_pre_poll(&kick_state[i]);
+ GPR_ASSERT(fd >= 0);
+ }
+
+ for (i = 0; i < GRPC_MAX_CACHED_PIPES; ++i) {
+ grpc_pollset_kick_post_poll(&kick_state[i]);
+ grpc_pollset_kick_destroy(&kick_state[i]);
+ }
+}
+
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
@@ -95,6 +116,7 @@ int main(int argc, char **argv) {
test_basic_kick();
test_non_poll_kick();
test_non_kick();
+ test_over_free();
grpc_pollset_kick_global_destroy();
return 0;
diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c
index 619f09308e..9c60f4c233 100644
--- a/test/core/security/credentials_test.c
+++ b/test/core/security/credentials_test.c
@@ -48,7 +48,7 @@ static const char test_iam_authorization_token[] = "blahblahblhahb";
static const char test_iam_authority_selector[] = "respectmyauthoritah";
static const char test_oauth2_bearer_token[] =
"Bearer blaaslkdjfaslkdfasdsfasf";
-static const unsigned char test_root_cert[] = {0xDE, 0xAD, 0xBE, 0xEF};
+static const char test_root_cert[] = "I am the root!";
/* This JSON key was generated with the GCE console and revoked immediately.
The identifiers have been changed as well.
@@ -275,8 +275,8 @@ static void check_ssl_oauth2_composite_metadata(
}
static void test_ssl_oauth2_composite_creds(void) {
- grpc_credentials *ssl_creds = grpc_ssl_credentials_create(
- test_root_cert, sizeof(test_root_cert), NULL, 0, NULL, 0);
+ grpc_credentials *ssl_creds =
+ grpc_ssl_credentials_create(test_root_cert, NULL);
const grpc_credentials_array *creds_array;
grpc_credentials *oauth2_creds =
grpc_fake_oauth2_credentials_create(test_oauth2_bearer_token, 0);
@@ -312,8 +312,8 @@ static void check_ssl_oauth2_iam_composite_metadata(
}
static void test_ssl_oauth2_iam_composite_creds(void) {
- grpc_credentials *ssl_creds = grpc_ssl_credentials_create(
- test_root_cert, sizeof(test_root_cert), NULL, 0, NULL, 0);
+ grpc_credentials *ssl_creds =
+ grpc_ssl_credentials_create(test_root_cert, NULL);
const grpc_credentials_array *creds_array;
grpc_credentials *oauth2_creds =
grpc_fake_oauth2_credentials_create(test_oauth2_bearer_token, 0);
diff --git a/test/cpp/client/credentials_test.cc b/test/cpp/client/credentials_test.cc
index ea088b87bd..174d2187b0 100644
--- a/test/cpp/client/credentials_test.cc
+++ b/test/cpp/client/credentials_test.cc
@@ -45,15 +45,6 @@ class CredentialsTest : public ::testing::Test {
protected:
};
-TEST_F(CredentialsTest, InvalidSslCreds) {
- std::unique_ptr<Credentials> bad1 =
- CredentialsFactory::SslCredentials({"", "", ""});
- EXPECT_EQ(nullptr, bad1.get());
- std::unique_ptr<Credentials> bad2 =
- CredentialsFactory::SslCredentials({"", "bla", "bla"});
- EXPECT_EQ(nullptr, bad2.get());
-}
-
TEST_F(CredentialsTest, InvalidServiceAccountCreds) {
std::unique_ptr<Credentials> bad1 =
CredentialsFactory::ServiceAccountCredentials("", "",
diff --git a/test/cpp/interop/server.cc b/test/cpp/interop/server.cc
index 561b134c27..5b5c35416c 100644
--- a/test/cpp/interop/server.cc
+++ b/test/cpp/interop/server.cc
@@ -203,11 +203,7 @@ void RunServer() {
builder.RegisterService(service.service());
if (FLAGS_enable_ssl) {
SslServerCredentialsOptions ssl_opts = {
- "",
- {reinterpret_cast<const char*>(test_server1_key),
- test_server1_key_size},
- {reinterpret_cast<const char*>(test_server1_cert),
- test_server1_cert_size}};
+ "", {{test_server1_key, test_server1_cert}}};
std::shared_ptr<ServerCredentials> creds =
ServerCredentialsFactory::SslCredentials(ssl_opts);
builder.SetCredentials(creds);
diff --git a/test/cpp/util/create_test_channel.cc b/test/cpp/util/create_test_channel.cc
index f0d35d98c2..68f6244a53 100644
--- a/test/cpp/util/create_test_channel.cc
+++ b/test/cpp/util/create_test_channel.cc
@@ -56,11 +56,8 @@ std::shared_ptr<ChannelInterface> CreateTestChannel(
ChannelArguments channel_args;
if (enable_ssl) {
const char* roots_certs =
- use_prod_roots ? reinterpret_cast<const char*>(prod_roots_certs)
- : reinterpret_cast<const char*>(test_root_cert);
- unsigned int roots_certs_size =
- use_prod_roots ? prod_roots_certs_size : test_root_cert_size;
- SslCredentialsOptions ssl_opts = {{roots_certs, roots_certs_size}, "", ""};
+ use_prod_roots ? prod_roots_certs : test_root_cert;
+ SslCredentialsOptions ssl_opts = {roots_certs, "", ""};
std::unique_ptr<Credentials> creds =
CredentialsFactory::SslCredentials(ssl_opts);
diff --git a/tools/dockerfile/grpc_base/Dockerfile b/tools/dockerfile/grpc_base/Dockerfile
index 45be172593..be1b69b0dc 100644
--- a/tools/dockerfile/grpc_base/Dockerfile
+++ b/tools/dockerfile/grpc_base/Dockerfile
@@ -13,6 +13,7 @@ RUN apt-get update && apt-get install -y \
libc6 \
libc6-dbg \
libc6-dev \
+ libgtest-dev \
libtool \
make \
strace \
@@ -34,23 +35,13 @@ ENV CLOUD_SDK /google-cloud-sdk
RUN $CLOUD_SDK/install.sh --usage-reporting=true --path-update=true --bash-completion=true --rc-path=/.bashrc --disable-installation-options
ENV PATH $CLOUD_SDK/bin:$PATH
-# Install gcompute-tools to allow access to private git-on-borg repos
-RUN git clone https://gerrit.googlesource.com/gcompute-tools /var/local/git/gcompute-tools
-
-# Start the daemon that allows access to private git-on-borg repos
-RUN /var/local/git/gcompute-tools/git-cookie-authdaemon
-
-# Install the grpc-tools scripts dir from git
-RUN git clone https://team.googlesource.com/one-platform-grpc-team/grpc-tools /var/local/git/grpc-tools
-
-# Install the grpc-protobuf dir that has the protoc patch
-RUN git clone https://team.googlesource.com/one-platform-grpc-team/protobuf /var/local/git/protobuf
-
-# Install the patched version of protoc
-RUN cd /var/local/git/protobuf && \
- ./autogen.sh && \
- ./configure --prefix=/usr && \
- make && make check && make install && make clean
+# Install a GitHub SSH service credential that gives access to the GitHub repo while it's private
+# TODO: remove this once the repo is public
+ADD .ssh .ssh
+RUN chmod 600 .ssh/github.rsa
+RUN mkdir -p $HOME/.ssh && echo 'Host github.com' > $HOME/.ssh/config
+RUN echo " IdentityFile /.ssh/github.rsa" >> $HOME/.ssh/config
+RUN echo 'StrictHostKeyChecking no' >> $HOME/.ssh/config
# Define the default command.
CMD ["bash"]
diff --git a/tools/dockerfile/grpc_cxx/Dockerfile b/tools/dockerfile/grpc_cxx/Dockerfile
index cf38e976b1..ea3a1dba8f 100644
--- a/tools/dockerfile/grpc_cxx/Dockerfile
+++ b/tools/dockerfile/grpc_cxx/Dockerfile
@@ -1,15 +1,18 @@
# Dockerfile for gRPC C++
FROM grpc/base
-# Start the daemon that allows access to the protected git-on-borg repos
-RUN /var/local/git/gcompute-tools/git-cookie-authdaemon
-
-RUN git clone https://team.googlesource.com/one-platform-grpc-team/grpc /var/local/git/grpc
-RUN cd /var/local/git/grpc \
- && git pull --recurse-submodules \
- && git submodule update --init --recursive
+# Get the source from GitHub
+RUN git clone git@github.com:google/grpc.git /var/local/git/grpc
+RUN cd /var/local/git/grpc && \
+ git pull --recurse-submodules && \
+ git submodule update --init --recursive
+# Build the protobuf library; then the C core.
+RUN cd /var/local/git/grpc/third_party/protobuf && \
+ ./autogen.sh && \
+ ./configure --prefix=/usr && \
+ make -j12 && make check && make install && make clean
RUN make install -C /var/local/git/grpc
# Define the default command.
-CMD ["bash"] \ No newline at end of file
+CMD ["bash"]
diff --git a/tools/dockerfile/grpc_php/Dockerfile b/tools/dockerfile/grpc_php/Dockerfile
index 0e50af70a2..177587669c 100644
--- a/tools/dockerfile/grpc_php/Dockerfile
+++ b/tools/dockerfile/grpc_php/Dockerfile
@@ -1,9 +1,6 @@
# Dockerfile for gRPC PHP
FROM grpc/php_base
-# Start the daemon that allows access to the protected git-on-borg repos
-RUN /var/local/git/gcompute-tools/git-cookie-authdaemon
-
RUN cd /var/local/git/grpc \
&& git pull --recurse-submodules \
&& git submodule update --init --recursive
@@ -15,4 +12,4 @@ RUN cd /var/local/git/grpc/src/php/ext/grpc && git pull && phpize
# Build the grpc PHP extension
RUN cd /var/local/git/grpc/src/php/ext/grpc \
&& ./configure \
- && make \ No newline at end of file
+ && make
diff --git a/tools/dockerfile/grpc_php_base/Dockerfile b/tools/dockerfile/grpc_php_base/Dockerfile
index 8ec90f48b8..47266a310e 100644
--- a/tools/dockerfile/grpc_php_base/Dockerfile
+++ b/tools/dockerfile/grpc_php_base/Dockerfile
@@ -43,9 +43,10 @@ RUN cd /var/local \
&& tar -xf php-5.5.17.tar.gz \
&& cd php-5.5.17 \
&& ./configure --with-zlib=/usr --with-libxml-dir=ext/libxml \
- && make && make install
+ && make -j12 && make install
# Start the daemon that allows access to the protected git-on-borg repos
+RUN git clone https://gerrit.googlesource.com/gcompute-tools /var/local/git/gcompute-tools
RUN /var/local/git/gcompute-tools/git-cookie-authdaemon
# Download the patched PHP protobuf so that PHP gRPC clients can be generated
@@ -64,6 +65,18 @@ ENV PATH /usr/local/rvm/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/s
# rake: a ruby version of make used to build the PHP Protobuf extension
RUN rvm all do gem install ronn rake
+# Get the source from GitHub, this gets the protobuf library as well
+RUN git clone git@github.com:google/grpc.git /var/local/git/grpc
+RUN cd /var/local/git/grpc && \
+ git pull --recurse-submodules && \
+ git submodule update --init --recursive
+
+# Build and install the protobuf library
+RUN cd /var/local/git/grpc/third_party/protobuf && \
+ ./autogen.sh && \
+ ./configure --prefix=/usr && \
+ make -j12 && make check && make install && make clean
+
# Install the patched PHP protobuf so that PHP gRPC clients can be generated
# from proto3 schemas.
RUN cd /var/local/git/protobuf-php \
@@ -75,10 +88,7 @@ RUN wget https://phar.phpunit.de/phpunit.phar \
&& chmod +x phpunit.phar \
&& mv phpunit.phar /usr/local/bin/phpunit
-RUN git clone https://team.googlesource.com/one-platform-grpc-team/grpc /var/local/git/grpc
-RUN cd /var/local/git/grpc \
- && git submodule update --init --recursive
-
+# Build the C core
RUN make static_c shared_c -j12 -C /var/local/git/grpc
# Define the default command.
diff --git a/tools/dockerfile/grpc_ruby/Dockerfile b/tools/dockerfile/grpc_ruby/Dockerfile
index 9aa34bfcc9..43ec0183ca 100644
--- a/tools/dockerfile/grpc_ruby/Dockerfile
+++ b/tools/dockerfile/grpc_ruby/Dockerfile
@@ -1,19 +1,14 @@
# Dockerfile for gRPC Ruby
FROM grpc/ruby_base
-# Start the daemon that allows access to the protected git-on-borg repos
-RUN /var/local/git/gcompute-tools/git-cookie-authdaemon
-
+# Build the C libary
RUN cd /var/local/git/grpc \
&& git pull --recurse-submodules \
&& git submodule update --init --recursive
+# Build the C core.
RUN make install_c -C /var/local/git/grpc
-# Install the grpc gem locally with its dependencies and build the extension.
-RUN /bin/bash -l -c 'cd /var/local/git/beefcake && bundle && gem build beefcake.gemspec && gem install beefcake'
-RUN /bin/bash -l -c 'cd /var/local/git/grpc/src/ruby && bundle && rake compile:grpc && gem build grpc.gemspec && gem install grpc'
-
# TODO add a command to run the unittest tests when the bug below is fixed
# - the tests fail due to an error in the C threading library:
# they fail with 'ruby: __pthread_mutex_cond_lock_adjust for unknown reasons' at the end of a testcase
diff --git a/tools/dockerfile/grpc_ruby_base/Dockerfile b/tools/dockerfile/grpc_ruby_base/Dockerfile
index ad14e43ec7..b2af9d7160 100644
--- a/tools/dockerfile/grpc_ruby_base/Dockerfile
+++ b/tools/dockerfile/grpc_ruby_base/Dockerfile
@@ -31,15 +31,6 @@ RUN apt-get update && apt-get install -y \
sqlite3 \
zlib1g-dev
-
-# Start the daemon that allows access to the protected git-on-borg repos
-RUN /var/local/git/gcompute-tools/git-cookie-authdaemon
-
-# Download the patched Ruby protobuf (beefcake) so that Ruby gRPC clients can
-# be generated from proto3 schemas.
-RUN git clone https://team.googlesource.com/one-platform-grpc-team/grpc-ruby-beefcake \
- /var/local/git/beefcake
-
# Install RVM, use this to install ruby
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3 # Needed for RVM
RUN /bin/bash -l -c "curl -L get.rvm.io | bash -s stable"
@@ -52,8 +43,17 @@ RUN /bin/bash -l -c "echo 'source /home/grpc_ruby/.rvm/scripts/rvm' >> ~/.bashrc
RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.1' >> ~/.bashrc"
RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc"
-RUN git clone https://team.googlesource.com/one-platform-grpc-team/grpc /var/local/git/grpc
-RUN cd /var/local/git/grpc \
- && git submodule update --init --recursive
+# Get the source from GitHub
+RUN git clone git@github.com:google/grpc.git /var/local/git/grpc
+RUN cd /var/local/git/grpc && \
+ git pull --recurse-submodules && \
+ git submodule update --init --recursive
+
+# Build and install the protobuf library
+RUN cd /var/local/git/grpc/third_party/protobuf && \
+ ./autogen.sh && \
+ ./configure --prefix=/usr && \
+ make -j12 && make check && make install && make clean
-RUN make static_c shared_c -C /var/local/git/grpc \ No newline at end of file
+# Build the C core
+RUN make static_c shared_c -j12 -C /var/local/git/grpc
diff --git a/tools/gce_setup/shared_startup_funcs.sh b/tools/gce_setup/shared_startup_funcs.sh
index 9ea6eca461..9c747466a9 100755
--- a/tools/gce_setup/shared_startup_funcs.sh
+++ b/tools/gce_setup/shared_startup_funcs.sh
@@ -388,7 +388,7 @@ grpc_docker_pull_known() {
# grpc_dockerfile_install "grpc/image" /var/local/dockerfile/grpc_image
grpc_dockerfile_install() {
local image_label=$1
- [[ -n $image_label ]] || { echo "missing arg: image_label" >&2; return 1; }
+ [[ -n $image_label ]] || { echo "$FUNCNAME: missing arg: image_label" >&2; return 1; }
local docker_img_url=0.0.0.0:5000/$image_label
local dockerfile_dir=$2
@@ -400,19 +400,25 @@ grpc_dockerfile_install() {
[[ $cache == "cache=1" ]] && { cache_opt=''; }
[[ $cache == "cache=true" ]] && { cache_opt=''; }
- [[ -d $dockerfile_dir ]] || { echo "not a valid dir: $dockerfile_dir"; return 1; }
+ [[ -d $dockerfile_dir ]] || { echo "$FUNCNAME: not a valid dir: $dockerfile_dir"; return 1; }
+
+ # For grpc/base, sync the ssh key into the .ssh dir in the dockerfile context
+
+ [[ $image_label == "grpc/base" ]] && {
+ grpc_docker_sync_github_key $dockerfile_dir/.ssh || return 1;
+ }
# TODO(temiola): maybe make cache/no-cache a func option?
sudo docker build $cache_opt -t $image_label $dockerfile_dir || {
- echo "docker op error: build of $image_label <- $dockerfile_dir"
+ echo "$FUNCNAME:: build of $image_label <- $dockerfile_dir"
return 1
}
sudo docker tag $image_label $docker_img_url || {
- echo "docker op error: tag of $docker_img_url"
+ echo "$FUNCNAME: failed to tag $docker_img_url as $image_label"
return 1
}
sudo docker push $docker_img_url || {
- echo "docker op error: push of $docker_img_url"
+ echo "$FUNCNAME: failed to push $docker_img_url"
return 1
}
}
@@ -428,3 +434,31 @@ grpc_dockerfile_install() {
grpc_dockerfile_refresh() {
grpc_dockerfile_install "$@"
}
+
+# grpc_docker_sync_github_key.
+#
+# Copies the docker github key from GCS to the target dir
+#
+# call-seq:
+# grpc_docker_sync_github_key <target_dir>
+grpc_docker_sync_github_key() {
+ local target_dir=$1
+ [[ -n $target_dir ]] || { echo "$FUNCNAME: missing arg: target_dir" >&2; return 1; }
+
+ # determine the admin root; the parent of the dockerfile root,
+ local gs_dockerfile_root=$(load_metadata "attributes/gs_dockerfile_root")
+ [[ -n $gs_dockerfile_root ]] || {
+ echo "$FUNCNAME: missing metadata: gs_dockerfile_root" >&2
+ return 1
+ }
+ local gcs_admin_root=$(dirname $gs_dockerfile_root)
+
+ # cp the file from gsutil to a known local area
+ local gcs_key_path=$gcs_admin_root/github/ssh_key
+ local local_key_path=$target_dir/github.rsa
+ mkdir -p $target_dir || {
+ echo "$FUNCNAME: could not create dir: $target_dir" 1>&2
+ return 1
+ }
+ gsutil cp $src $gcs_key_path $local_key_path
+}