Merge github.com:grpc/grpc into you-complete-me

pull/1731/head
Craig Tiller 10 years ago
commit aaa03d74ce
  1. 2
      .gitmodules
  2. 6
      BUILD
  3. 1910
      Makefile
  4. 20
      build.json
  5. 17
      composer.json
  6. 56
      include/grpc/grpc_security.h
  7. 2
      include/grpc/support/cmdline.h
  8. 7
      src/core/channel/context.h
  9. 6
      src/core/iomgr/fd_posix.c
  10. 5
      src/core/iomgr/pollset_multipoller_with_epoll.c
  11. 12
      src/core/iomgr/pollset_multipoller_with_poll_posix.c
  12. 9
      src/core/iomgr/pollset_posix.h
  13. 7
      src/core/security/auth_filters.h
  14. 26
      src/core/security/client_auth_filter.c
  15. 216
      src/core/security/credentials.c
  16. 41
      src/core/security/credentials.h
  17. 101
      src/core/security/credentials_metadata.c
  18. 71
      src/core/security/security_connector.c
  19. 1
      src/core/security/security_connector.h
  20. 150
      src/core/security/security_context.c
  21. 48
      src/core/security/security_context.h
  22. 128
      src/core/security/server_auth_filter.c
  23. 25
      src/core/security/server_secure_chttp2.c
  24. 62
      src/core/support/cmdline.c
  25. 18
      src/core/surface/call.c
  26. 4
      src/core/surface/secure_channel_create.c
  27. 6
      src/core/surface/server.c
  28. 2
      src/core/surface/server.h
  29. 3
      src/core/surface/server_chttp2.c
  30. 2
      src/core/transport/metadata.h
  31. 3
      src/core/transport/transport.h
  32. 4
      src/cpp/server/server.cc
  33. 2
      src/csharp/Grpc.Auth/Grpc.Auth.nuspec
  34. 2
      src/csharp/Grpc.Core/Grpc.Core.nuspec
  35. 22
      src/csharp/Grpc.Tools.nuspec
  36. 4
      src/csharp/Grpc.nuspec
  37. 23
      src/csharp/README.md
  38. 1
      src/csharp/build_packages.bat
  39. 16
      src/objective-c/GRPCClient/private/GRPCSecureChannel.m
  40. 6
      src/objective-c/README.md
  41. 24
      src/objective-c/tests/Info.plist
  42. 12
      src/objective-c/tests/Podfile
  43. 140
      src/objective-c/tests/RxLibraryUnitTests.m
  44. 40
      src/objective-c/tests/Tests.m
  45. 430
      src/objective-c/tests/Tests.xcodeproj/project.pbxproj
  46. 7
      src/objective-c/tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  47. 2
      src/python/interop/interop/_insecure_interop_test.py
  48. 6
      src/python/interop/interop/_interop_test_case.py
  49. 2
      src/python/interop/interop/_secure_interop_test.py
  50. 54
      src/python/interop/interop/methods.py
  51. 2
      src/python/src/grpc/_adapter/_blocking_invocation_inline_service_test.py
  52. 2
      src/python/src/grpc/_adapter/_event_invocation_synchronous_event_service_test.py
  53. 2
      src/python/src/grpc/_adapter/_future_invocation_asynchronous_event_service_test.py
  54. 2
      src/python/src/grpc/_adapter/_links_test.py
  55. 2
      src/python/src/grpc/_adapter/_lonely_rear_link_test.py
  56. 2
      src/python/src/grpc/_adapter/_low_test.py
  57. 2
      src/python/src/grpc/early_adopter/implementations_test.py
  58. 2
      src/python/src/grpc/framework/base/implementations_test.py
  59. 2
      src/python/src/grpc/framework/face/blocking_invocation_inline_service_test.py
  60. 2
      src/python/src/grpc/framework/face/event_invocation_synchronous_event_service_test.py
  61. 2
      src/python/src/grpc/framework/face/future_invocation_asynchronous_event_service_test.py
  62. 2
      src/python/src/grpc/framework/foundation/_later_test.py
  63. 2
      src/python/src/grpc/framework/foundation/_logging_pool_test.py
  64. 7
      src/ruby/bin/interop/interop_server.rb
  65. 1
      src/ruby/lib/grpc/generic/active_call.rb
  66. 28
      src/ruby/lib/grpc/generic/bidi_call.rb
  67. 1
      src/ruby/lib/grpc/generic/rpc_desc.rb
  68. 2
      templates/tools/doxygen/Doxyfile.c++.internal.template
  69. 2
      templates/tools/doxygen/Doxyfile.c++.template
  70. 2
      templates/tools/doxygen/Doxyfile.core.internal.template
  71. 2
      templates/tools/doxygen/Doxyfile.core.template
  72. 17
      templates/tools/doxygen/Doxyfile.include
  73. 2
      test/compiler/python_plugin_test.py
  74. 3
      test/core/bad_client/bad_client.c
  75. 118
      test/core/end2end/fixtures/chttp2_fullstack_with_poll.c
  76. 168
      test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_poll.c
  77. 3
      test/core/end2end/fixtures/chttp2_socket_pair.c
  78. 3
      test/core/end2end/fixtures/chttp2_socket_pair_one_byte_at_a_time.c
  79. 3
      test/core/end2end/fixtures/chttp2_socket_pair_with_grpc_trace.c
  80. 2
      test/core/end2end/gen_build_json.py
  81. 21
      test/core/end2end/tests/request_response_with_payload_and_call_creds.c
  82. 143
      test/core/security/auth_context_test.c
  83. 163
      test/core/security/credentials_test.c
  84. 23
      test/core/support/cmdline_test.c
  85. 2
      third_party/protobuf
  86. 38
      tools/buildgen/generate_build_additions.sh
  87. 9
      tools/buildgen/generate_projects.sh
  88. 2365
      tools/doxygen/Doxyfile.c++.internal
  89. 2365
      tools/doxygen/Doxyfile.core.internal
  90. 2
      tools/doxygen/run_doxygen.sh
  91. 15
      tools/run_tests/jobset.py
  92. 2
      tools/run_tests/run_sanity.sh
  93. 8
      tools/run_tests/run_tests.py
  94. 1061
      tools/run_tests/tests.json
  95. 19
      vsprojects/Grpc.mak
  96. 10
      vsprojects/grpc/grpc.vcxproj
  97. 12
      vsprojects/grpc/grpc.vcxproj.filters
  98. 2
      vsprojects/nuget_package/grpc.native.csharp_ext.nuspec

2
.gitmodules vendored

@ -8,7 +8,7 @@
[submodule "third_party/protobuf"] [submodule "third_party/protobuf"]
path = third_party/protobuf path = third_party/protobuf
url = https://github.com/google/protobuf.git url = https://github.com/google/protobuf.git
branch = v3.0.0-alpha-1 branch = v3.0.0-alpha-3
[submodule "third_party/gflags"] [submodule "third_party/gflags"]
path = third_party/gflags path = third_party/gflags
url = https://github.com/gflags/gflags.git url = https://github.com/gflags/gflags.git

@ -131,7 +131,7 @@ cc_library(
"src/core/httpcli/httpcli.h", "src/core/httpcli/httpcli.h",
"src/core/httpcli/httpcli_security_connector.h", "src/core/httpcli/httpcli_security_connector.h",
"src/core/httpcli/parser.h", "src/core/httpcli/parser.h",
"src/core/security/auth.h", "src/core/security/auth_filters.h",
"src/core/security/base64.h", "src/core/security/base64.h",
"src/core/security/credentials.h", "src/core/security/credentials.h",
"src/core/security/json_token.h", "src/core/security/json_token.h",
@ -234,9 +234,10 @@ cc_library(
"src/core/httpcli/httpcli.c", "src/core/httpcli/httpcli.c",
"src/core/httpcli/httpcli_security_connector.c", "src/core/httpcli/httpcli_security_connector.c",
"src/core/httpcli/parser.c", "src/core/httpcli/parser.c",
"src/core/security/auth.c",
"src/core/security/base64.c", "src/core/security/base64.c",
"src/core/security/client_auth_filter.c",
"src/core/security/credentials.c", "src/core/security/credentials.c",
"src/core/security/credentials_metadata.c",
"src/core/security/credentials_posix.c", "src/core/security/credentials_posix.c",
"src/core/security/credentials_win32.c", "src/core/security/credentials_win32.c",
"src/core/security/google_default_credentials.c", "src/core/security/google_default_credentials.c",
@ -245,6 +246,7 @@ cc_library(
"src/core/security/secure_transport_setup.c", "src/core/security/secure_transport_setup.c",
"src/core/security/security_connector.c", "src/core/security/security_connector.c",
"src/core/security/security_context.c", "src/core/security/security_context.c",
"src/core/security/server_auth_filter.c",
"src/core/security/server_secure_chttp2.c", "src/core/security/server_secure_chttp2.c",
"src/core/surface/init_secure.c", "src/core/surface/init_secure.c",
"src/core/surface/secure_channel_create.c", "src/core/surface/secure_channel_create.c",

1910
Makefile

File diff suppressed because one or more lines are too long

@ -405,7 +405,7 @@
"src/core/httpcli/httpcli.h", "src/core/httpcli/httpcli.h",
"src/core/httpcli/httpcli_security_connector.h", "src/core/httpcli/httpcli_security_connector.h",
"src/core/httpcli/parser.h", "src/core/httpcli/parser.h",
"src/core/security/auth.h", "src/core/security/auth_filters.h",
"src/core/security/base64.h", "src/core/security/base64.h",
"src/core/security/credentials.h", "src/core/security/credentials.h",
"src/core/security/json_token.h", "src/core/security/json_token.h",
@ -423,9 +423,10 @@
"src/core/httpcli/httpcli.c", "src/core/httpcli/httpcli.c",
"src/core/httpcli/httpcli_security_connector.c", "src/core/httpcli/httpcli_security_connector.c",
"src/core/httpcli/parser.c", "src/core/httpcli/parser.c",
"src/core/security/auth.c",
"src/core/security/base64.c", "src/core/security/base64.c",
"src/core/security/client_auth_filter.c",
"src/core/security/credentials.c", "src/core/security/credentials.c",
"src/core/security/credentials_metadata.c",
"src/core/security/credentials_posix.c", "src/core/security/credentials_posix.c",
"src/core/security/credentials_win32.c", "src/core/security/credentials_win32.c",
"src/core/security/google_default_credentials.c", "src/core/security/google_default_credentials.c",
@ -434,6 +435,7 @@
"src/core/security/secure_transport_setup.c", "src/core/security/secure_transport_setup.c",
"src/core/security/security_connector.c", "src/core/security/security_connector.c",
"src/core/security/security_context.c", "src/core/security/security_context.c",
"src/core/security/server_auth_filter.c",
"src/core/security/server_secure_chttp2.c", "src/core/security/server_secure_chttp2.c",
"src/core/surface/init_secure.c", "src/core/surface/init_secure.c",
"src/core/surface/secure_channel_create.c", "src/core/surface/secure_channel_create.c",
@ -1273,6 +1275,20 @@
"gpr" "gpr"
] ]
}, },
{
"name": "grpc_auth_context_test",
"build": "test",
"language": "c",
"src": [
"test/core/security/auth_context_test.c"
],
"deps": [
"grpc_test_util",
"grpc",
"gpr_test_util",
"gpr"
]
},
{ {
"name": "grpc_base64_test", "name": "grpc_base64_test",
"build": "test", "build": "test",

@ -0,0 +1,17 @@
{
"name": "grpc/grpc",
"type": "library",
"description": "gRPC library for PHP",
"keywords": ["rpc"],
"homepage": "http://grpc.io",
"license": "BSD-3-Clause",
"require": {
"php": ">=5.5.0",
"google/auth": "dev-master"
},
"autoload": {
"psr-4": {
"Grpc\\": "src/php/lib/Grpc/"
}
}
}

@ -191,6 +191,62 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
grpc_call_error grpc_call_set_credentials(grpc_call *call, grpc_call_error grpc_call_set_credentials(grpc_call *call,
grpc_credentials *creds); grpc_credentials *creds);
/* --- Authentication Context. --- */
/* TODO(jboeuf): Define some well-known property names. */
#define GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME \
"transport_security_type"
#define GRPC_FAKE_TRANSPORT_SECURITY_TYPE "fake"
#define GRPC_SSL_TRANSPORT_SECURITY_TYPE "ssl"
#define GRPC_X509_CN_PROPERTY_NAME "x509_common_name"
#define GRPC_X509_SAN_PROPERTY_NAME "x509_subject_alternative_name"
typedef struct grpc_auth_context grpc_auth_context;
typedef struct grpc_auth_property_iterator {
const grpc_auth_context *ctx;
size_t index;
const char *name;
} grpc_auth_property_iterator;
/* value, if not NULL, is guaranteed to be NULL terminated. */
typedef struct grpc_auth_property {
char *name;
char *value;
size_t value_length;
} grpc_auth_property;
/* Returns NULL when the iterator is at the end. */
const grpc_auth_property *grpc_auth_property_iterator_next(
grpc_auth_property_iterator *it);
/* Iterates over the auth context. */
grpc_auth_property_iterator grpc_auth_context_property_iterator(
const grpc_auth_context *ctx);
/* Gets the peer identity. Returns an empty iterator (first _next will return
NULL) if the peer is not authenticated. */
grpc_auth_property_iterator grpc_auth_context_peer_identity(
const grpc_auth_context *ctx);
/* Finds a property in the context. May return an empty iterator (first _next
will return NULL) if no property with this name was found in the context. */
grpc_auth_property_iterator grpc_auth_context_find_properties_by_name(
const grpc_auth_context *ctx, const char *name);
/* Gets the name of the property that indicates the peer identity. Will return
NULL if the peer is not authenticated. */
const char *grpc_auth_context_peer_identity_property_name(
const grpc_auth_context *ctx);
/* Returns 1 if the peer is authenticated, 0 otherwise. */
int grpc_auth_context_peer_is_authenticated(const grpc_auth_context *ctx);
/* Gets the auth context from the call. */
const grpc_auth_context *grpc_call_auth_context(grpc_call *call);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

@ -87,6 +87,8 @@ void gpr_cmdline_on_extra_arg(
void gpr_cmdline_parse(gpr_cmdline *cl, int argc, char **argv); void gpr_cmdline_parse(gpr_cmdline *cl, int argc, char **argv);
/* Destroy the parser */ /* Destroy the parser */
void gpr_cmdline_destroy(gpr_cmdline *cl); void gpr_cmdline_destroy(gpr_cmdline *cl);
/* Get a string describing usage */
char *gpr_cmdline_usage_string(gpr_cmdline *cl, const char *argv0);
#ifdef __cplusplus #ifdef __cplusplus
} }

@ -41,4 +41,9 @@ typedef enum {
GRPC_CONTEXT_COUNT GRPC_CONTEXT_COUNT
} grpc_context_index; } grpc_context_index;
#endif typedef struct {
void *value;
void (*destroy)(void *);
} grpc_call_context_element;
#endif /* GRPC_INTERNAL_CORE_CHANNEL_CONTEXT_H */

@ -165,7 +165,7 @@ static void maybe_wake_one_watcher(grpc_fd *fd) {
gpr_mu_unlock(&fd->watcher_mu); gpr_mu_unlock(&fd->watcher_mu);
} }
static void wake_all_watchers(grpc_fd *fd) { static void wake_all_watchers_locked(grpc_fd *fd) {
grpc_fd_watcher *watcher; grpc_fd_watcher *watcher;
for (watcher = fd->inactive_watcher_root.next; for (watcher = fd->inactive_watcher_root.next;
watcher != &fd->inactive_watcher_root; watcher = watcher->next) { watcher != &fd->inactive_watcher_root; watcher = watcher->next) {
@ -184,7 +184,9 @@ void grpc_fd_orphan(grpc_fd *fd, grpc_iomgr_cb_func on_done, void *user_data) {
fd->on_done_user_data = user_data; fd->on_done_user_data = user_data;
shutdown(fd->fd, SHUT_RDWR); shutdown(fd->fd, SHUT_RDWR);
ref_by(fd, 1); /* remove active status, but keep referenced */ ref_by(fd, 1); /* remove active status, but keep referenced */
wake_all_watchers(fd); gpr_mu_lock(&fd->watcher_mu);
wake_all_watchers_locked(fd);
gpr_mu_unlock(&fd->watcher_mu);
unref_by(fd, 2); /* drop the reference */ unref_by(fd, 2); /* drop the reference */
} }

@ -164,7 +164,7 @@ static const grpc_pollset_vtable multipoll_with_epoll_pollset = {
multipoll_with_epoll_pollset_maybe_work, epoll_kick, multipoll_with_epoll_pollset_maybe_work, epoll_kick,
multipoll_with_epoll_pollset_destroy}; multipoll_with_epoll_pollset_destroy};
void grpc_platform_become_multipoller(grpc_pollset *pollset, grpc_fd **fds, static void epoll_become_multipoller(grpc_pollset *pollset, grpc_fd **fds,
size_t nfds) { size_t nfds) {
size_t i; size_t i;
pollset_hdr *h = gpr_malloc(sizeof(pollset_hdr)); pollset_hdr *h = gpr_malloc(sizeof(pollset_hdr));
@ -194,4 +194,7 @@ void grpc_platform_become_multipoller(grpc_pollset *pollset, grpc_fd **fds,
} }
} }
grpc_platform_become_multipoller_type grpc_platform_become_multipoller =
epoll_become_multipoller;
#endif /* GPR_LINUX_MULTIPOLL_WITH_EPOLL */ #endif /* GPR_LINUX_MULTIPOLL_WITH_EPOLL */

@ -33,7 +33,7 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#ifdef GPR_POSIX_MULTIPOLL_WITH_POLL #ifdef GPR_POSIX_SOCKET
#include "src/core/iomgr/pollset_posix.h" #include "src/core/iomgr/pollset_posix.h"
@ -98,7 +98,8 @@ static void end_polling(grpc_pollset *pollset) {
pollset_hdr *h; pollset_hdr *h;
h = pollset->data.ptr; h = pollset->data.ptr;
for (i = 1; i < h->pfd_count; i++) { for (i = 1; i < h->pfd_count; i++) {
grpc_fd_end_poll(&h->watchers[i], h->pfds[i].revents & POLLIN, h->pfds[i].revents & POLLOUT); grpc_fd_end_poll(&h->watchers[i], h->pfds[i].revents & POLLIN,
h->pfds[i].revents & POLLOUT);
} }
} }
@ -228,7 +229,7 @@ static const grpc_pollset_vtable multipoll_with_poll_pollset = {
multipoll_with_poll_pollset_maybe_work, multipoll_with_poll_pollset_kick, multipoll_with_poll_pollset_maybe_work, multipoll_with_poll_pollset_kick,
multipoll_with_poll_pollset_destroy}; multipoll_with_poll_pollset_destroy};
void grpc_platform_become_multipoller(grpc_pollset *pollset, grpc_fd **fds, void grpc_poll_become_multipoller(grpc_pollset *pollset, grpc_fd **fds,
size_t nfds) { size_t nfds) {
size_t i; size_t i;
pollset_hdr *h = gpr_malloc(sizeof(pollset_hdr)); pollset_hdr *h = gpr_malloc(sizeof(pollset_hdr));
@ -250,4 +251,9 @@ void grpc_platform_become_multipoller(grpc_pollset *pollset, grpc_fd **fds,
} }
} }
#endif /* GPR_POSIX_SOCKET */
#ifdef GPR_POSIX_MULTIPOLL_WITH_POLL
grpc_platform_become_multipoller_type grpc_platform_become_multipoller =
grpc_poll_become_multipoller;
#endif #endif

@ -101,7 +101,12 @@ void grpc_kick_drain(grpc_pollset *p);
grpc_pollset *grpc_backup_pollset(void); grpc_pollset *grpc_backup_pollset(void);
/* turn a pollset into a multipoller: platform specific */ /* turn a pollset into a multipoller: platform specific */
void grpc_platform_become_multipoller(grpc_pollset *pollset, typedef void (*grpc_platform_become_multipoller_type)(grpc_pollset *pollset,
struct grpc_fd **fds, size_t fd_count); struct grpc_fd **fds,
size_t fd_count);
extern grpc_platform_become_multipoller_type grpc_platform_become_multipoller;
void grpc_poll_become_multipoller(grpc_pollset *pollset, struct grpc_fd **fds,
size_t fd_count);
#endif /* GRPC_INTERNAL_CORE_IOMGR_POLLSET_POSIX_H */ #endif /* GRPC_INTERNAL_CORE_IOMGR_POLLSET_POSIX_H */

@ -31,11 +31,12 @@
* *
*/ */
#ifndef GRPC_INTERNAL_CORE_SECURITY_AUTH_H #ifndef GRPC_INTERNAL_CORE_SECURITY_AUTH_FILTERS_H
#define GRPC_INTERNAL_CORE_SECURITY_AUTH_H #define GRPC_INTERNAL_CORE_SECURITY_AUTH_FILTERS_H
#include "src/core/channel/channel_stack.h" #include "src/core/channel/channel_stack.h"
extern const grpc_channel_filter grpc_client_auth_filter; extern const grpc_channel_filter grpc_client_auth_filter;
extern const grpc_channel_filter grpc_server_auth_filter;
#endif /* GRPC_INTERNAL_CORE_SECURITY_AUTH_H */ #endif /* GRPC_INTERNAL_CORE_SECURITY_AUTH_FILTERS_H */

@ -31,7 +31,7 @@
* *
*/ */
#include "src/core/security/auth.h" #include "src/core/security/auth_filters.h"
#include <string.h> #include <string.h>
@ -77,11 +77,13 @@ static void bubble_up_error(grpc_call_element *elem, const char *error_msg) {
grpc_call_next_op(elem, &calld->op); grpc_call_next_op(elem, &calld->op);
} }
static void on_credentials_metadata(void *user_data, grpc_mdelem **md_elems, static void on_credentials_metadata(void *user_data,
grpc_credentials_md *md_elems,
size_t num_md, size_t num_md,
grpc_credentials_status status) { grpc_credentials_status status) {
grpc_call_element *elem = (grpc_call_element *)user_data; grpc_call_element *elem = (grpc_call_element *)user_data;
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
grpc_transport_op *op = &calld->op; grpc_transport_op *op = &calld->op;
grpc_metadata_batch *mdb; grpc_metadata_batch *mdb;
size_t i; size_t i;
@ -94,8 +96,10 @@ static void on_credentials_metadata(void *user_data, grpc_mdelem **md_elems,
op->send_ops->ops[calld->op_md_idx].type == GRPC_OP_METADATA); op->send_ops->ops[calld->op_md_idx].type == GRPC_OP_METADATA);
mdb = &op->send_ops->ops[calld->op_md_idx].data.metadata; mdb = &op->send_ops->ops[calld->op_md_idx].data.metadata;
for (i = 0; i < num_md; i++) { for (i = 0; i < num_md; i++) {
grpc_metadata_batch_add_tail(mdb, &calld->md_links[i], grpc_metadata_batch_add_tail(
grpc_mdelem_ref(md_elems[i])); mdb, &calld->md_links[i],
grpc_mdelem_from_slices(chand->md_ctx, gpr_slice_ref(md_elems[i].key),
gpr_slice_ref(md_elems[i].value)));
} }
grpc_call_next_op(elem, op); grpc_call_next_op(elem, op);
} }
@ -125,7 +129,7 @@ static void send_security_metadata(grpc_call_element *elem,
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
grpc_client_security_context *ctx = grpc_client_security_context *ctx =
(grpc_client_security_context *)op->context[GRPC_CONTEXT_SECURITY]; (grpc_client_security_context *)op->context[GRPC_CONTEXT_SECURITY].value;
char *service_url = NULL; char *service_url = NULL;
grpc_credentials *channel_creds = grpc_credentials *channel_creds =
chand->security_connector->request_metadata_creds; chand->security_connector->request_metadata_creds;
@ -189,6 +193,8 @@ static void auth_start_transport_op(grpc_call_element *elem,
grpc_linked_mdelem *l; grpc_linked_mdelem *l;
size_t i; size_t i;
/* TODO(jboeuf): write the call auth context. */
if (op->send_ops && !calld->sent_initial_metadata) { if (op->send_ops && !calld->sent_initial_metadata) {
size_t nops = op->send_ops->nops; size_t nops = op->send_ops->nops;
grpc_stream_op *ops = op->send_ops->ops; grpc_stream_op *ops = op->send_ops->ops;
@ -273,7 +279,7 @@ static void init_channel_elem(grpc_channel_element *elem,
const grpc_channel_args *args, const grpc_channel_args *args,
grpc_mdctx *metadata_context, int is_first, grpc_mdctx *metadata_context, int is_first,
int is_last) { int is_last) {
grpc_security_connector *ctx = grpc_find_security_connector_in_args(args); grpc_security_connector *sc = grpc_find_security_connector_in_args(args);
/* grab pointers to our data from the channel element */ /* grab pointers to our data from the channel element */
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
@ -282,12 +288,12 @@ static void init_channel_elem(grpc_channel_element *elem,
path */ path */
GPR_ASSERT(!is_first); GPR_ASSERT(!is_first);
GPR_ASSERT(!is_last); GPR_ASSERT(!is_last);
GPR_ASSERT(ctx != NULL); GPR_ASSERT(sc != NULL);
/* initialize members */ /* initialize members */
GPR_ASSERT(ctx->is_client_side); GPR_ASSERT(sc->is_client_side);
chand->security_connector = chand->security_connector =
(grpc_channel_security_connector *)grpc_security_connector_ref(ctx); (grpc_channel_security_connector *)grpc_security_connector_ref(sc);
chand->md_ctx = metadata_context; chand->md_ctx = metadata_context;
chand->authority_string = chand->authority_string =
grpc_mdstr_from_string(chand->md_ctx, ":authority"); grpc_mdstr_from_string(chand->md_ctx, ":authority");
@ -321,4 +327,4 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
const grpc_channel_filter grpc_client_auth_filter = { const grpc_channel_filter grpc_client_auth_filter = {
auth_start_transport_op, channel_op, sizeof(call_data), init_call_elem, auth_start_transport_op, channel_op, sizeof(call_data), init_call_elem,
destroy_call_elem, sizeof(channel_data), init_channel_elem, destroy_call_elem, sizeof(channel_data), init_channel_elem,
destroy_channel_elem, "auth"}; destroy_channel_elem, "client-auth"};

@ -114,20 +114,6 @@ void grpc_credentials_get_request_metadata(grpc_credentials *creds,
creds->vtable->get_request_metadata(creds, service_url, cb, user_data); creds->vtable->get_request_metadata(creds, service_url, cb, user_data);
} }
grpc_mdctx *grpc_credentials_get_or_create_metadata_context(
grpc_credentials *creds) {
grpc_mdctx *mdctx = NULL;
if (creds != NULL && creds->vtable->get_metadata_context != NULL) {
mdctx = creds->vtable->get_metadata_context(creds);
}
if (mdctx == NULL) {
return grpc_mdctx_create();
} else {
grpc_mdctx_ref(mdctx);
return mdctx;
}
}
grpc_security_status grpc_credentials_create_security_connector( grpc_security_status grpc_credentials_create_security_connector(
grpc_credentials *creds, const char *target, const grpc_channel_args *args, grpc_credentials *creds, const char *target, const grpc_channel_args *args,
grpc_credentials *request_metadata_creds, grpc_credentials *request_metadata_creds,
@ -208,10 +194,6 @@ static int ssl_has_request_metadata_only(const grpc_credentials *creds) {
return 0; return 0;
} }
static grpc_mdctx *ssl_get_metadata_context(grpc_credentials *creds) {
return NULL;
}
static grpc_security_status ssl_create_security_connector( static grpc_security_status ssl_create_security_connector(
grpc_credentials *creds, const char *target, const grpc_channel_args *args, grpc_credentials *creds, const char *target, const grpc_channel_args *args,
grpc_credentials *request_metadata_creds, grpc_credentials *request_metadata_creds,
@ -249,8 +231,8 @@ static grpc_security_status ssl_server_create_security_connector(
} }
static grpc_credentials_vtable ssl_vtable = { static grpc_credentials_vtable ssl_vtable = {
ssl_destroy, ssl_has_request_metadata, ssl_has_request_metadata_only, ssl_destroy, ssl_has_request_metadata, ssl_has_request_metadata_only, NULL,
ssl_get_metadata_context, NULL, ssl_create_security_connector}; ssl_create_security_connector};
static grpc_server_credentials_vtable ssl_server_vtable = { static grpc_server_credentials_vtable ssl_server_vtable = {
ssl_server_destroy, ssl_server_create_security_connector}; ssl_server_destroy, ssl_server_create_security_connector};
@ -341,13 +323,12 @@ grpc_server_credentials *grpc_ssl_server_credentials_create(
typedef struct { typedef struct {
grpc_credentials base; grpc_credentials base;
grpc_mdctx *md_ctx;
/* Have a simple cache for now with just 1 entry. We could have a map based on /* Have a simple cache for now with just 1 entry. We could have a map based on
the service_url for a more sophisticated one. */ the service_url for a more sophisticated one. */
gpr_mu cache_mu; gpr_mu cache_mu;
struct { struct {
grpc_mdelem *jwt_md; grpc_credentials_md_store *jwt_md;
char *service_url; char *service_url;
gpr_timespec jwt_expiration; gpr_timespec jwt_expiration;
} cached; } cached;
@ -358,7 +339,7 @@ typedef struct {
static void jwt_reset_cache(grpc_jwt_credentials *c) { static void jwt_reset_cache(grpc_jwt_credentials *c) {
if (c->cached.jwt_md != NULL) { if (c->cached.jwt_md != NULL) {
grpc_mdelem_unref(c->cached.jwt_md); grpc_credentials_md_store_unref(c->cached.jwt_md);
c->cached.jwt_md = NULL; c->cached.jwt_md = NULL;
} }
if (c->cached.service_url != NULL) { if (c->cached.service_url != NULL) {
@ -373,7 +354,6 @@ static void jwt_destroy(grpc_credentials *creds) {
grpc_auth_json_key_destruct(&c->key); grpc_auth_json_key_destruct(&c->key);
jwt_reset_cache(c); jwt_reset_cache(c);
gpr_mu_destroy(&c->cache_mu); gpr_mu_destroy(&c->cache_mu);
grpc_mdctx_unref(c->md_ctx);
gpr_free(c); gpr_free(c);
} }
@ -393,7 +373,7 @@ static void jwt_get_request_metadata(grpc_credentials *creds,
0}; 0};
/* See if we can return a cached jwt. */ /* See if we can return a cached jwt. */
grpc_mdelem *jwt_md = NULL; grpc_credentials_md_store *jwt_md = NULL;
{ {
gpr_mu_lock(&c->cache_mu); gpr_mu_lock(&c->cache_mu);
if (c->cached.service_url != NULL && if (c->cached.service_url != NULL &&
@ -401,7 +381,7 @@ static void jwt_get_request_metadata(grpc_credentials *creds,
c->cached.jwt_md != NULL && c->cached.jwt_md != NULL &&
(gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration, gpr_now()), (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration, gpr_now()),
refresh_threshold) > 0)) { refresh_threshold) > 0)) {
jwt_md = grpc_mdelem_ref(c->cached.jwt_md); jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md);
} }
gpr_mu_unlock(&c->cache_mu); gpr_mu_unlock(&c->cache_mu);
} }
@ -418,30 +398,26 @@ static void jwt_get_request_metadata(grpc_credentials *creds,
gpr_free(jwt); gpr_free(jwt);
c->cached.jwt_expiration = gpr_time_add(gpr_now(), c->jwt_lifetime); c->cached.jwt_expiration = gpr_time_add(gpr_now(), c->jwt_lifetime);
c->cached.service_url = gpr_strdup(service_url); c->cached.service_url = gpr_strdup(service_url);
c->cached.jwt_md = grpc_mdelem_from_strings( c->cached.jwt_md = grpc_credentials_md_store_create(1);
c->md_ctx, GRPC_AUTHORIZATION_METADATA_KEY, md_value); grpc_credentials_md_store_add_cstrings(
c->cached.jwt_md, GRPC_AUTHORIZATION_METADATA_KEY, md_value);
gpr_free(md_value); gpr_free(md_value);
jwt_md = grpc_mdelem_ref(c->cached.jwt_md); jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md);
} }
gpr_mu_unlock(&c->cache_mu); gpr_mu_unlock(&c->cache_mu);
} }
if (jwt_md != NULL) { if (jwt_md != NULL) {
cb(user_data, &jwt_md, 1, GRPC_CREDENTIALS_OK); cb(user_data, jwt_md->entries, jwt_md->num_entries, GRPC_CREDENTIALS_OK);
grpc_mdelem_unref(jwt_md); grpc_credentials_md_store_unref(jwt_md);
} else { } else {
cb(user_data, NULL, 0, GRPC_CREDENTIALS_ERROR); cb(user_data, NULL, 0, GRPC_CREDENTIALS_ERROR);
} }
} }
static grpc_mdctx *jwt_get_metadata_context(grpc_credentials *creds) {
grpc_jwt_credentials *c = (grpc_jwt_credentials *)creds;
return c->md_ctx;
}
static grpc_credentials_vtable jwt_vtable = { static grpc_credentials_vtable jwt_vtable = {
jwt_destroy, jwt_has_request_metadata, jwt_has_request_metadata_only, jwt_destroy, jwt_has_request_metadata, jwt_has_request_metadata_only,
jwt_get_metadata_context, jwt_get_request_metadata, NULL}; jwt_get_request_metadata, NULL};
grpc_credentials *grpc_jwt_credentials_create(const char *json_key, grpc_credentials *grpc_jwt_credentials_create(const char *json_key,
gpr_timespec token_lifetime) { gpr_timespec token_lifetime) {
@ -456,7 +432,6 @@ grpc_credentials *grpc_jwt_credentials_create(const char *json_key,
c->base.type = GRPC_CREDENTIALS_TYPE_JWT; c->base.type = GRPC_CREDENTIALS_TYPE_JWT;
gpr_ref_init(&c->base.refcount, 1); gpr_ref_init(&c->base.refcount, 1);
c->base.vtable = &jwt_vtable; c->base.vtable = &jwt_vtable;
c->md_ctx = grpc_mdctx_create();
c->key = key; c->key = key;
c->jwt_lifetime = token_lifetime; c->jwt_lifetime = token_lifetime;
gpr_mu_init(&c->cache_mu); gpr_mu_init(&c->cache_mu);
@ -476,8 +451,7 @@ typedef void (*grpc_fetch_oauth2_func)(grpc_credentials_metadata_request *req,
typedef struct { typedef struct {
grpc_credentials base; grpc_credentials base;
gpr_mu mu; gpr_mu mu;
grpc_mdctx *md_ctx; grpc_credentials_md_store *access_token_md;
grpc_mdelem *access_token_md;
gpr_timespec token_expiration; gpr_timespec token_expiration;
grpc_fetch_oauth2_func fetch_func; grpc_fetch_oauth2_func fetch_func;
} grpc_oauth2_token_fetcher_credentials; } grpc_oauth2_token_fetcher_credentials;
@ -485,11 +459,8 @@ typedef struct {
static void oauth2_token_fetcher_destroy(grpc_credentials *creds) { static void oauth2_token_fetcher_destroy(grpc_credentials *creds) {
grpc_oauth2_token_fetcher_credentials *c = grpc_oauth2_token_fetcher_credentials *c =
(grpc_oauth2_token_fetcher_credentials *)creds; (grpc_oauth2_token_fetcher_credentials *)creds;
if (c->access_token_md != NULL) { grpc_credentials_md_store_unref(c->access_token_md);
grpc_mdelem_unref(c->access_token_md);
}
gpr_mu_destroy(&c->mu); gpr_mu_destroy(&c->mu);
grpc_mdctx_unref(c->md_ctx);
gpr_free(c); gpr_free(c);
} }
@ -505,8 +476,8 @@ static int oauth2_token_fetcher_has_request_metadata_only(
grpc_credentials_status grpc_credentials_status
grpc_oauth2_token_fetcher_credentials_parse_server_response( grpc_oauth2_token_fetcher_credentials_parse_server_response(
const grpc_httpcli_response *response, grpc_mdctx *ctx, const grpc_httpcli_response *response,
grpc_mdelem **token_elem, gpr_timespec *token_lifetime) { grpc_credentials_md_store **token_md, gpr_timespec *token_lifetime) {
char *null_terminated_body = NULL; char *null_terminated_body = NULL;
char *new_access_token = NULL; char *new_access_token = NULL;
grpc_credentials_status status = GRPC_CREDENTIALS_OK; grpc_credentials_status status = GRPC_CREDENTIALS_OK;
@ -574,16 +545,17 @@ grpc_oauth2_token_fetcher_credentials_parse_server_response(
access_token->value); access_token->value);
token_lifetime->tv_sec = strtol(expires_in->value, NULL, 10); token_lifetime->tv_sec = strtol(expires_in->value, NULL, 10);
token_lifetime->tv_nsec = 0; token_lifetime->tv_nsec = 0;
if (*token_elem != NULL) grpc_mdelem_unref(*token_elem); if (*token_md != NULL) grpc_credentials_md_store_unref(*token_md);
*token_elem = grpc_mdelem_from_strings(ctx, GRPC_AUTHORIZATION_METADATA_KEY, *token_md = grpc_credentials_md_store_create(1);
new_access_token); grpc_credentials_md_store_add_cstrings(
*token_md, GRPC_AUTHORIZATION_METADATA_KEY, new_access_token);
status = GRPC_CREDENTIALS_OK; status = GRPC_CREDENTIALS_OK;
} }
end: end:
if (status != GRPC_CREDENTIALS_OK && (*token_elem != NULL)) { if (status != GRPC_CREDENTIALS_OK && (*token_md != NULL)) {
grpc_mdelem_unref(*token_elem); grpc_credentials_md_store_unref(*token_md);
*token_elem = NULL; *token_md = NULL;
} }
if (null_terminated_body != NULL) gpr_free(null_terminated_body); if (null_terminated_body != NULL) gpr_free(null_terminated_body);
if (new_access_token != NULL) gpr_free(new_access_token); if (new_access_token != NULL) gpr_free(new_access_token);
@ -602,10 +574,11 @@ static void on_oauth2_token_fetcher_http_response(
gpr_mu_lock(&c->mu); gpr_mu_lock(&c->mu);
status = grpc_oauth2_token_fetcher_credentials_parse_server_response( status = grpc_oauth2_token_fetcher_credentials_parse_server_response(
response, c->md_ctx, &c->access_token_md, &token_lifetime); response, &c->access_token_md, &token_lifetime);
if (status == GRPC_CREDENTIALS_OK) { if (status == GRPC_CREDENTIALS_OK) {
c->token_expiration = gpr_time_add(gpr_now(), token_lifetime); c->token_expiration = gpr_time_add(gpr_now(), token_lifetime);
r->cb(r->user_data, &c->access_token_md, 1, status); r->cb(r->user_data, c->access_token_md->entries,
c->access_token_md->num_entries, status);
} else { } else {
c->token_expiration = gpr_inf_past; c->token_expiration = gpr_inf_past;
r->cb(r->user_data, NULL, 0, status); r->cb(r->user_data, NULL, 0, status);
@ -621,19 +594,20 @@ static void oauth2_token_fetcher_get_request_metadata(
(grpc_oauth2_token_fetcher_credentials *)creds; (grpc_oauth2_token_fetcher_credentials *)creds;
gpr_timespec refresh_threshold = {GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, gpr_timespec refresh_threshold = {GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS,
0}; 0};
grpc_mdelem *cached_access_token_md = NULL; grpc_credentials_md_store *cached_access_token_md = NULL;
{ {
gpr_mu_lock(&c->mu); gpr_mu_lock(&c->mu);
if (c->access_token_md != NULL && if (c->access_token_md != NULL &&
(gpr_time_cmp(gpr_time_sub(c->token_expiration, gpr_now()), (gpr_time_cmp(gpr_time_sub(c->token_expiration, gpr_now()),
refresh_threshold) > 0)) { refresh_threshold) > 0)) {
cached_access_token_md = grpc_mdelem_ref(c->access_token_md); cached_access_token_md = grpc_credentials_md_store_ref(c->access_token_md);
} }
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
} }
if (cached_access_token_md != NULL) { if (cached_access_token_md != NULL) {
cb(user_data, &cached_access_token_md, 1, GRPC_CREDENTIALS_OK); cb(user_data, cached_access_token_md->entries,
grpc_mdelem_unref(cached_access_token_md); cached_access_token_md->num_entries, GRPC_CREDENTIALS_OK);
grpc_credentials_md_store_unref(cached_access_token_md);
} else { } else {
c->fetch_func( c->fetch_func(
grpc_credentials_metadata_request_create(creds, cb, user_data), grpc_credentials_metadata_request_create(creds, cb, user_data),
@ -648,24 +622,15 @@ static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c,
c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2; c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2;
gpr_ref_init(&c->base.refcount, 1); gpr_ref_init(&c->base.refcount, 1);
gpr_mu_init(&c->mu); gpr_mu_init(&c->mu);
c->md_ctx = grpc_mdctx_create();
c->token_expiration = gpr_inf_past; c->token_expiration = gpr_inf_past;
c->fetch_func = fetch_func; c->fetch_func = fetch_func;
} }
static grpc_mdctx *oauth2_token_fetcher_get_metadata_context(
grpc_credentials *creds) {
grpc_oauth2_token_fetcher_credentials *c =
(grpc_oauth2_token_fetcher_credentials *)creds;
return c->md_ctx;
}
/* -- ComputeEngine credentials. -- */ /* -- ComputeEngine credentials. -- */
static grpc_credentials_vtable compute_engine_vtable = { static grpc_credentials_vtable compute_engine_vtable = {
oauth2_token_fetcher_destroy, oauth2_token_fetcher_has_request_metadata, oauth2_token_fetcher_destroy, oauth2_token_fetcher_has_request_metadata,
oauth2_token_fetcher_has_request_metadata_only, oauth2_token_fetcher_has_request_metadata_only,
oauth2_token_fetcher_get_metadata_context,
oauth2_token_fetcher_get_request_metadata, NULL}; oauth2_token_fetcher_get_request_metadata, NULL};
static void compute_engine_fetch_oauth2( static void compute_engine_fetch_oauth2(
@ -709,7 +674,6 @@ static void service_account_destroy(grpc_credentials *creds) {
static grpc_credentials_vtable service_account_vtable = { static grpc_credentials_vtable service_account_vtable = {
service_account_destroy, oauth2_token_fetcher_has_request_metadata, service_account_destroy, oauth2_token_fetcher_has_request_metadata,
oauth2_token_fetcher_has_request_metadata_only, oauth2_token_fetcher_has_request_metadata_only,
oauth2_token_fetcher_get_metadata_context,
oauth2_token_fetcher_get_request_metadata, NULL}; oauth2_token_fetcher_get_request_metadata, NULL};
static void service_account_fetch_oauth2( static void service_account_fetch_oauth2(
@ -783,7 +747,6 @@ static void refresh_token_destroy(grpc_credentials *creds) {
static grpc_credentials_vtable refresh_token_vtable = { static grpc_credentials_vtable refresh_token_vtable = {
refresh_token_destroy, oauth2_token_fetcher_has_request_metadata, refresh_token_destroy, oauth2_token_fetcher_has_request_metadata,
oauth2_token_fetcher_has_request_metadata_only, oauth2_token_fetcher_has_request_metadata_only,
oauth2_token_fetcher_get_metadata_context,
oauth2_token_fetcher_get_request_metadata, NULL}; oauth2_token_fetcher_get_request_metadata, NULL};
static void refresh_token_fetch_oauth2( static void refresh_token_fetch_oauth2(
@ -832,17 +795,13 @@ grpc_credentials *grpc_refresh_token_credentials_create(
typedef struct { typedef struct {
grpc_credentials base; grpc_credentials base;
grpc_mdctx *md_ctx; grpc_credentials_md_store *access_token_md;
grpc_mdelem *access_token_md;
int is_async; int is_async;
} grpc_fake_oauth2_credentials; } grpc_fake_oauth2_credentials;
static void fake_oauth2_destroy(grpc_credentials *creds) { static void fake_oauth2_destroy(grpc_credentials *creds) {
grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)creds; grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)creds;
if (c->access_token_md != NULL) { grpc_credentials_md_store_unref(c->access_token_md);
grpc_mdelem_unref(c->access_token_md);
}
grpc_mdctx_unref(c->md_ctx);
gpr_free(c); gpr_free(c);
} }
@ -860,7 +819,8 @@ void on_simulated_token_fetch_done(void *user_data, int success) {
(grpc_credentials_metadata_request *)user_data; (grpc_credentials_metadata_request *)user_data;
grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)r->creds; grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)r->creds;
GPR_ASSERT(success); GPR_ASSERT(success);
r->cb(r->user_data, &c->access_token_md, 1, GRPC_CREDENTIALS_OK); r->cb(r->user_data, c->access_token_md->entries,
c->access_token_md->num_entries, GRPC_CREDENTIALS_OK);
grpc_credentials_metadata_request_destroy(r); grpc_credentials_metadata_request_destroy(r);
} }
@ -875,19 +835,14 @@ static void fake_oauth2_get_request_metadata(grpc_credentials *creds,
on_simulated_token_fetch_done, on_simulated_token_fetch_done,
grpc_credentials_metadata_request_create(creds, cb, user_data)); grpc_credentials_metadata_request_create(creds, cb, user_data));
} else { } else {
cb(user_data, &c->access_token_md, 1, GRPC_CREDENTIALS_OK); cb(user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK);
} }
} }
static grpc_mdctx *fake_oauth2_get_metadata_context(grpc_credentials *creds) {
grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)creds;
return c->md_ctx;
}
static grpc_credentials_vtable fake_oauth2_vtable = { static grpc_credentials_vtable fake_oauth2_vtable = {
fake_oauth2_destroy, fake_oauth2_has_request_metadata, fake_oauth2_destroy, fake_oauth2_has_request_metadata,
fake_oauth2_has_request_metadata_only, fake_oauth2_get_metadata_context, fake_oauth2_has_request_metadata_only, fake_oauth2_get_request_metadata,
fake_oauth2_get_request_metadata, NULL}; NULL};
grpc_credentials *grpc_fake_oauth2_credentials_create( grpc_credentials *grpc_fake_oauth2_credentials_create(
const char *token_md_value, int is_async) { const char *token_md_value, int is_async) {
@ -897,9 +852,9 @@ grpc_credentials *grpc_fake_oauth2_credentials_create(
c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2; c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2;
c->base.vtable = &fake_oauth2_vtable; c->base.vtable = &fake_oauth2_vtable;
gpr_ref_init(&c->base.refcount, 1); gpr_ref_init(&c->base.refcount, 1);
c->md_ctx = grpc_mdctx_create(); c->access_token_md = grpc_credentials_md_store_create(1);
c->access_token_md = grpc_mdelem_from_strings( grpc_credentials_md_store_add_cstrings(
c->md_ctx, GRPC_AUTHORIZATION_METADATA_KEY, token_md_value); c->access_token_md, GRPC_AUTHORIZATION_METADATA_KEY, token_md_value);
c->is_async = is_async; c->is_async = is_async;
return &c->base; return &c->base;
} }
@ -926,11 +881,6 @@ static int fake_transport_security_has_request_metadata_only(
return 0; return 0;
} }
static grpc_mdctx *fake_transport_security_get_metadata_context(
grpc_credentials *c) {
return NULL;
}
static grpc_security_status static grpc_security_status
fake_transport_security_create_security_connector( fake_transport_security_create_security_connector(
grpc_credentials *c, const char *target, const grpc_channel_args *args, grpc_credentials *c, const char *target, const grpc_channel_args *args,
@ -950,8 +900,7 @@ fake_transport_security_server_create_security_connector(
static grpc_credentials_vtable fake_transport_security_credentials_vtable = { static grpc_credentials_vtable fake_transport_security_credentials_vtable = {
fake_transport_security_credentials_destroy, fake_transport_security_credentials_destroy,
fake_transport_security_has_request_metadata, fake_transport_security_has_request_metadata,
fake_transport_security_has_request_metadata_only, fake_transport_security_has_request_metadata_only, NULL,
fake_transport_security_get_metadata_context, NULL,
fake_transport_security_create_security_connector}; fake_transport_security_create_security_connector};
static grpc_server_credentials_vtable static grpc_server_credentials_vtable
@ -988,8 +937,7 @@ typedef struct {
typedef struct { typedef struct {
grpc_composite_credentials *composite_creds; grpc_composite_credentials *composite_creds;
size_t creds_index; size_t creds_index;
grpc_mdelem **md_elems; grpc_credentials_md_store *md_elems;
size_t num_md;
char *service_url; char *service_url;
void *user_data; void *user_data;
grpc_credentials_metadata_cb cb; grpc_credentials_metadata_cb cb;
@ -1031,21 +979,16 @@ static int composite_has_request_metadata_only(const grpc_credentials *creds) {
static void composite_md_context_destroy( static void composite_md_context_destroy(
grpc_composite_credentials_metadata_context *ctx) { grpc_composite_credentials_metadata_context *ctx) {
size_t i; grpc_credentials_md_store_unref(ctx->md_elems);
for (i = 0; i < ctx->num_md; i++) {
grpc_mdelem_unref(ctx->md_elems[i]);
}
gpr_free(ctx->md_elems);
if (ctx->service_url != NULL) gpr_free(ctx->service_url); if (ctx->service_url != NULL) gpr_free(ctx->service_url);
gpr_free(ctx); gpr_free(ctx);
} }
static void composite_metadata_cb(void *user_data, grpc_mdelem **md_elems, static void composite_metadata_cb(void *user_data,
size_t num_md, grpc_credentials_md *md_elems, size_t num_md,
grpc_credentials_status status) { grpc_credentials_status status) {
grpc_composite_credentials_metadata_context *ctx = grpc_composite_credentials_metadata_context *ctx =
(grpc_composite_credentials_metadata_context *)user_data; (grpc_composite_credentials_metadata_context *)user_data;
size_t i;
if (status != GRPC_CREDENTIALS_OK) { if (status != GRPC_CREDENTIALS_OK) {
ctx->cb(ctx->user_data, NULL, 0, status); ctx->cb(ctx->user_data, NULL, 0, status);
return; return;
@ -1053,12 +996,11 @@ static void composite_metadata_cb(void *user_data, grpc_mdelem **md_elems,
/* Copy the metadata in the context. */ /* Copy the metadata in the context. */
if (num_md > 0) { if (num_md > 0) {
ctx->md_elems = gpr_realloc(ctx->md_elems, size_t i;
(ctx->num_md + num_md) * sizeof(grpc_mdelem *));
for (i = 0; i < num_md; i++) { for (i = 0; i < num_md; i++) {
ctx->md_elems[i + ctx->num_md] = grpc_mdelem_ref(md_elems[i]); grpc_credentials_md_store_add(ctx->md_elems, md_elems[i].key,
md_elems[i].value);
} }
ctx->num_md += num_md;
} }
/* See if we need to get some more metadata. */ /* See if we need to get some more metadata. */
@ -1073,7 +1015,8 @@ static void composite_metadata_cb(void *user_data, grpc_mdelem **md_elems,
} }
/* We're done!. */ /* We're done!. */
ctx->cb(ctx->user_data, ctx->md_elems, ctx->num_md, GRPC_CREDENTIALS_OK); ctx->cb(ctx->user_data, ctx->md_elems->entries, ctx->md_elems->num_entries,
GRPC_CREDENTIALS_OK);
composite_md_context_destroy(ctx); composite_md_context_destroy(ctx);
} }
@ -1093,6 +1036,7 @@ static void composite_get_request_metadata(grpc_credentials *creds,
ctx->user_data = user_data; ctx->user_data = user_data;
ctx->cb = cb; ctx->cb = cb;
ctx->composite_creds = c; ctx->composite_creds = c;
ctx->md_elems = grpc_credentials_md_store_create(c->inner.num_creds);
while (ctx->creds_index < c->inner.num_creds) { while (ctx->creds_index < c->inner.num_creds) {
grpc_credentials *inner_creds = c->inner.creds_array[ctx->creds_index++]; grpc_credentials *inner_creds = c->inner.creds_array[ctx->creds_index++];
if (grpc_credentials_has_request_metadata(inner_creds)) { if (grpc_credentials_has_request_metadata(inner_creds)) {
@ -1104,25 +1048,6 @@ static void composite_get_request_metadata(grpc_credentials *creds,
GPR_ASSERT(0); /* Should have exited before. */ GPR_ASSERT(0); /* Should have exited before. */
} }
static grpc_mdctx *composite_get_metadata_context(grpc_credentials *creds) {
grpc_composite_credentials *c = (grpc_composite_credentials *)creds;
grpc_mdctx *ctx = NULL;
size_t i;
for (i = 0; i < c->inner.num_creds; i++) {
grpc_credentials *inner_creds = c->inner.creds_array[i];
grpc_mdctx *inner_ctx = NULL;
if (inner_creds->vtable->get_metadata_context != NULL) {
inner_ctx = inner_creds->vtable->get_metadata_context(inner_creds);
}
if (inner_ctx) {
GPR_ASSERT(ctx == NULL &&
"can only have one metadata context per composite credential");
ctx = inner_ctx;
}
}
return ctx;
}
static grpc_security_status composite_create_security_connector( static grpc_security_status composite_create_security_connector(
grpc_credentials *creds, const char *target, const grpc_channel_args *args, grpc_credentials *creds, const char *target, const grpc_channel_args *args,
grpc_credentials *request_metadata_creds, grpc_credentials *request_metadata_creds,
@ -1139,8 +1064,8 @@ static grpc_security_status composite_create_security_connector(
static grpc_credentials_vtable composite_credentials_vtable = { static grpc_credentials_vtable composite_credentials_vtable = {
composite_destroy, composite_has_request_metadata, composite_destroy, composite_has_request_metadata,
composite_has_request_metadata_only, composite_get_metadata_context, composite_has_request_metadata_only, composite_get_request_metadata,
composite_get_request_metadata, composite_create_security_connector}; composite_create_security_connector};
static grpc_credentials_array get_creds_array(grpc_credentials **creds_addr) { static grpc_credentials_array get_creds_array(grpc_credentials **creds_addr) {
grpc_credentials_array result; grpc_credentials_array result;
@ -1237,16 +1162,12 @@ grpc_credentials *grpc_credentials_contains_type(
typedef struct { typedef struct {
grpc_credentials base; grpc_credentials base;
grpc_mdctx *md_ctx; grpc_credentials_md_store *iam_md;
grpc_mdelem *token_md;
grpc_mdelem *authority_selector_md;
} grpc_iam_credentials; } grpc_iam_credentials;
static void iam_destroy(grpc_credentials *creds) { static void iam_destroy(grpc_credentials *creds) {
grpc_iam_credentials *c = (grpc_iam_credentials *)creds; grpc_iam_credentials *c = (grpc_iam_credentials *)creds;
grpc_mdelem_unref(c->token_md); grpc_credentials_md_store_unref(c->iam_md);
grpc_mdelem_unref(c->authority_selector_md);
grpc_mdctx_unref(c->md_ctx);
gpr_free(c); gpr_free(c);
} }
@ -1263,20 +1184,13 @@ static void iam_get_request_metadata(grpc_credentials *creds,
grpc_credentials_metadata_cb cb, grpc_credentials_metadata_cb cb,
void *user_data) { void *user_data) {
grpc_iam_credentials *c = (grpc_iam_credentials *)creds; grpc_iam_credentials *c = (grpc_iam_credentials *)creds;
grpc_mdelem *md_array[2]; cb(user_data, c->iam_md->entries, c->iam_md->num_entries,
md_array[0] = c->token_md; GRPC_CREDENTIALS_OK);
md_array[1] = c->authority_selector_md;
cb(user_data, md_array, 2, GRPC_CREDENTIALS_OK);
}
static grpc_mdctx *iam_get_metadata_context(grpc_credentials *creds) {
grpc_iam_credentials *c = (grpc_iam_credentials *)creds;
return c->md_ctx;
} }
static grpc_credentials_vtable iam_vtable = { static grpc_credentials_vtable iam_vtable = {
iam_destroy, iam_has_request_metadata, iam_has_request_metadata_only, iam_destroy, iam_has_request_metadata, iam_has_request_metadata_only,
iam_get_metadata_context, iam_get_request_metadata, NULL}; iam_get_request_metadata, NULL};
grpc_credentials *grpc_iam_credentials_create(const char *token, grpc_credentials *grpc_iam_credentials_create(const char *token,
const char *authority_selector) { const char *authority_selector) {
@ -1288,10 +1202,10 @@ grpc_credentials *grpc_iam_credentials_create(const char *token,
c->base.type = GRPC_CREDENTIALS_TYPE_IAM; c->base.type = GRPC_CREDENTIALS_TYPE_IAM;
c->base.vtable = &iam_vtable; c->base.vtable = &iam_vtable;
gpr_ref_init(&c->base.refcount, 1); gpr_ref_init(&c->base.refcount, 1);
c->md_ctx = grpc_mdctx_create(); c->iam_md = grpc_credentials_md_store_create(2);
c->token_md = grpc_mdelem_from_strings( grpc_credentials_md_store_add_cstrings(
c->md_ctx, GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, token); c->iam_md, GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, token);
c->authority_selector_md = grpc_mdelem_from_strings( grpc_credentials_md_store_add_cstrings(
c->md_ctx, GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, authority_selector); c->iam_md, GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, authority_selector);
return &c->base; return &c->base;
} }

@ -82,13 +82,40 @@ typedef enum {
#define GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING \ #define GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING \
"client_id=%s&client_secret=%s&refresh_token=%s&grant_type=refresh_token" "client_id=%s&client_secret=%s&refresh_token=%s&grant_type=refresh_token"
/* --- grpc_credentials_md. --- */
typedef struct {
gpr_slice key;
gpr_slice value;
} grpc_credentials_md;
typedef struct {
grpc_credentials_md *entries;
size_t num_entries;
size_t allocated;
gpr_refcount refcount;
} grpc_credentials_md_store;
grpc_credentials_md_store *grpc_credentials_md_store_create(
size_t initial_capacity);
/* Will ref key and value. */
void grpc_credentials_md_store_add(grpc_credentials_md_store *store,
gpr_slice key, gpr_slice value);
void grpc_credentials_md_store_add_cstrings(grpc_credentials_md_store *store,
const char *key, const char *value);
grpc_credentials_md_store *grpc_credentials_md_store_ref(
grpc_credentials_md_store *store);
void grpc_credentials_md_store_unref(grpc_credentials_md_store *store);
/* --- grpc_credentials. --- */ /* --- grpc_credentials. --- */
/* It is the caller's responsibility to gpr_free the result if not NULL. */ /* It is the caller's responsibility to gpr_free the result if not NULL. */
char *grpc_get_well_known_google_credentials_file_path(void); char *grpc_get_well_known_google_credentials_file_path(void);
typedef void (*grpc_credentials_metadata_cb)(void *user_data, typedef void (*grpc_credentials_metadata_cb)(void *user_data,
grpc_mdelem **md_elems, grpc_credentials_md *md_elems,
size_t num_md, size_t num_md,
grpc_credentials_status status); grpc_credentials_status status);
@ -96,7 +123,6 @@ typedef struct {
void (*destroy)(grpc_credentials *c); void (*destroy)(grpc_credentials *c);
int (*has_request_metadata)(const grpc_credentials *c); int (*has_request_metadata)(const grpc_credentials *c);
int (*has_request_metadata_only)(const grpc_credentials *c); int (*has_request_metadata_only)(const grpc_credentials *c);
grpc_mdctx *(*get_metadata_context)(grpc_credentials *c);
void (*get_request_metadata)(grpc_credentials *c, void (*get_request_metadata)(grpc_credentials *c,
const char *service_url, const char *service_url,
grpc_credentials_metadata_cb cb, grpc_credentials_metadata_cb cb,
@ -123,11 +149,6 @@ void grpc_credentials_get_request_metadata(grpc_credentials *creds,
grpc_credentials_metadata_cb cb, grpc_credentials_metadata_cb cb,
void *user_data); void *user_data);
/* Gets the mdctx from the credentials and increase the refcount if it exists,
otherwise, create a new one. */
grpc_mdctx *grpc_credentials_get_or_create_metadata_context(
grpc_credentials *creds);
/* Creates a security connector for the channel. May also create new channel /* Creates a security connector for the channel. May also create new channel
args for the channel to be used in place of the passed in const args if args for the channel to be used in place of the passed in const args if
returned non NULL. In that case the caller is responsible for destroying returned non NULL. In that case the caller is responsible for destroying
@ -155,9 +176,9 @@ grpc_credentials *grpc_credentials_contains_type(
/* Exposed for testing only. */ /* Exposed for testing only. */
grpc_credentials_status grpc_credentials_status
grpc_oauth2_token_fetcher_credentials_parse_server_response( grpc_oauth2_token_fetcher_credentials_parse_server_response(
const struct grpc_httpcli_response *response, grpc_mdctx *ctx, const struct grpc_httpcli_response *response, grpc_credentials_md_store **token_md,
grpc_mdelem **token_elem, gpr_timespec *token_lifetime); gpr_timespec *token_lifetime);
/* Simulates an oauth2 token fetch with the specified value for testing. */ /* Simulates an oauth2 token fetch with the specified value for testing. */
grpc_credentials *grpc_fake_oauth2_credentials_create( grpc_credentials *grpc_fake_oauth2_credentials_create(

@ -0,0 +1,101 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/core/security/credentials.h"
#include <grpc/support/alloc.h>
#include <string.h>
static void store_ensure_capacity(grpc_credentials_md_store *store) {
if (store->num_entries == store->allocated) {
store->allocated = (store->allocated == 0) ? 1 : store->allocated * 2;
store->entries = gpr_realloc(
store->entries, store->allocated * sizeof(grpc_credentials_md));
}
}
grpc_credentials_md_store *grpc_credentials_md_store_create(
size_t initial_capacity) {
grpc_credentials_md_store *store = gpr_malloc(sizeof(grpc_credentials_md_store));
memset(store, 0, sizeof(grpc_credentials_md_store));
if (initial_capacity > 0) {
store->entries = gpr_malloc(initial_capacity * sizeof(grpc_credentials_md));
store->allocated = initial_capacity;
}
gpr_ref_init(&store->refcount, 1);
return store;
}
void grpc_credentials_md_store_add(grpc_credentials_md_store *store,
gpr_slice key, gpr_slice value) {
if (store == NULL) return;
store_ensure_capacity(store);
store->entries[store->num_entries].key = gpr_slice_ref(key);
store->entries[store->num_entries].value = gpr_slice_ref(value);
store->num_entries++;
}
void grpc_credentials_md_store_add_cstrings(grpc_credentials_md_store *store,
const char *key,
const char *value) {
if (store == NULL) return;
store_ensure_capacity(store);
store->entries[store->num_entries].key = gpr_slice_from_copied_string(key);
store->entries[store->num_entries].value =
gpr_slice_from_copied_string(value);
store->num_entries++;
}
grpc_credentials_md_store *grpc_credentials_md_store_ref(
grpc_credentials_md_store *store) {
if (store == NULL) return NULL;
gpr_ref(&store->refcount);
return store;
}
void grpc_credentials_md_store_unref(grpc_credentials_md_store *store) {
if (store == NULL) return;
if (gpr_unref(&store->refcount)) {
if (store->entries != NULL) {
size_t i;
for (i = 0; i < store->num_entries; i++) {
gpr_slice_unref(store->entries[i].key);
gpr_slice_unref(store->entries[i].value);
}
gpr_free(store->entries);
}
gpr_free(store);
}
}

@ -37,6 +37,7 @@
#include "src/core/security/credentials.h" #include "src/core/security/credentials.h"
#include "src/core/security/secure_endpoint.h" #include "src/core/security/secure_endpoint.h"
#include "src/core/security/security_context.h"
#include "src/core/support/env.h" #include "src/core/support/env.h"
#include "src/core/support/file.h" #include "src/core/support/file.h"
#include "src/core/support/string.h" #include "src/core/support/string.h"
@ -194,10 +195,14 @@ typedef struct {
static void fake_channel_destroy(grpc_security_connector *sc) { static void fake_channel_destroy(grpc_security_connector *sc) {
grpc_channel_security_connector *c = (grpc_channel_security_connector *)sc; grpc_channel_security_connector *c = (grpc_channel_security_connector *)sc;
grpc_credentials_unref(c->request_metadata_creds); grpc_credentials_unref(c->request_metadata_creds);
grpc_auth_context_unref(sc->auth_context);
gpr_free(sc); gpr_free(sc);
} }
static void fake_server_destroy(grpc_security_connector *sc) { gpr_free(sc); } static void fake_server_destroy(grpc_security_connector *sc) {
grpc_auth_context_unref(sc->auth_context);
gpr_free(sc);
}
static grpc_security_status fake_channel_create_handshaker( static grpc_security_status fake_channel_create_handshaker(
grpc_security_connector *sc, tsi_handshaker **handshaker) { grpc_security_connector *sc, tsi_handshaker **handshaker) {
@ -236,6 +241,12 @@ static grpc_security_status fake_check_peer(grpc_security_connector *sc,
status = GRPC_SECURITY_ERROR; status = GRPC_SECURITY_ERROR;
goto end; goto end;
} }
grpc_auth_context_unref(sc->auth_context);
sc->auth_context = grpc_auth_context_create(NULL, 1);
sc->auth_context->properties[0] = grpc_auth_property_init_from_cstring(
GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
GRPC_FAKE_TRANSPORT_SECURITY_TYPE);
end: end:
tsi_peer_destruct(&peer); tsi_peer_destruct(&peer);
return status; return status;
@ -264,6 +275,7 @@ grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
grpc_credentials *request_metadata_creds, int call_host_check_is_async) { grpc_credentials *request_metadata_creds, int call_host_check_is_async) {
grpc_fake_channel_security_connector *c = grpc_fake_channel_security_connector *c =
gpr_malloc(sizeof(grpc_fake_channel_security_connector)); gpr_malloc(sizeof(grpc_fake_channel_security_connector));
memset(c, 0, sizeof(grpc_fake_channel_security_connector));
gpr_ref_init(&c->base.base.refcount, 1); gpr_ref_init(&c->base.base.refcount, 1);
c->base.base.is_client_side = 1; c->base.base.is_client_side = 1;
c->base.base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME; c->base.base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
@ -277,7 +289,9 @@ grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
grpc_security_connector *grpc_fake_server_security_connector_create(void) { grpc_security_connector *grpc_fake_server_security_connector_create(void) {
grpc_security_connector *c = gpr_malloc(sizeof(grpc_security_connector)); grpc_security_connector *c = gpr_malloc(sizeof(grpc_security_connector));
memset(c, 0, sizeof(grpc_security_connector));
gpr_ref_init(&c->refcount, 1); gpr_ref_init(&c->refcount, 1);
c->is_client_side = 0;
c->vtable = &fake_server_vtable; c->vtable = &fake_server_vtable;
c->url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME; c->url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
return c; return c;
@ -308,6 +322,7 @@ static void ssl_channel_destroy(grpc_security_connector *sc) {
if (c->target_name != NULL) gpr_free(c->target_name); if (c->target_name != NULL) gpr_free(c->target_name);
if (c->overridden_target_name != NULL) gpr_free(c->overridden_target_name); if (c->overridden_target_name != NULL) gpr_free(c->overridden_target_name);
tsi_peer_destruct(&c->peer); tsi_peer_destruct(&c->peer);
grpc_auth_context_unref(sc->auth_context);
gpr_free(sc); gpr_free(sc);
} }
@ -317,6 +332,7 @@ static void ssl_server_destroy(grpc_security_connector *sc) {
if (c->handshaker_factory != NULL) { if (c->handshaker_factory != NULL) {
tsi_ssl_handshaker_factory_destroy(c->handshaker_factory); tsi_ssl_handshaker_factory_destroy(c->handshaker_factory);
} }
grpc_auth_context_unref(sc->auth_context);
gpr_free(sc); gpr_free(sc);
} }
@ -369,7 +385,51 @@ static int ssl_host_matches_name(const tsi_peer *peer, const char *peer_name) {
return r; return r;
} }
static grpc_security_status ssl_check_peer(const char *peer_name, static grpc_auth_context *tsi_ssl_peer_to_auth_context(const tsi_peer *peer) {
/* We bet that iterating over a handful of properties twice will be faster
than having to realloc on average . */
size_t auth_prop_count = 1; /* for transport_security_type. */
size_t i;
const char *peer_identity_property_name = NULL;
grpc_auth_context *ctx = NULL;
for (i = 0; i < peer->property_count; i++) {
const tsi_peer_property *prop = &peer->properties[i];
if (prop->name == NULL) continue;
if (strcmp(prop->name, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) {
auth_prop_count++;
/* If there is no subject alt name, have the CN as the identity. */
if (peer_identity_property_name == NULL) {
peer_identity_property_name = prop->name;
}
} else if (strcmp(prop->name,
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) {
auth_prop_count++;
peer_identity_property_name = prop->name;
}
}
ctx = grpc_auth_context_create(NULL, auth_prop_count);
ctx->properties[0] = grpc_auth_property_init_from_cstring(
GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
GRPC_SSL_TRANSPORT_SECURITY_TYPE);
ctx->property_count = 1;
for (i = 0; i < peer->property_count; i++) {
const tsi_peer_property *prop = &peer->properties[i];
if (prop->name == NULL) continue;
if (strcmp(prop->name, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) {
ctx->properties[ctx->property_count++] = grpc_auth_property_init(
GRPC_X509_CN_PROPERTY_NAME, prop->value.data, prop->value.length);
} else if (strcmp(prop->name,
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) {
ctx->properties[ctx->property_count++] = grpc_auth_property_init(
GRPC_X509_SAN_PROPERTY_NAME, prop->value.data, prop->value.length);
}
}
GPR_ASSERT(auth_prop_count == ctx->property_count);
return ctx;
}
static grpc_security_status ssl_check_peer(grpc_security_connector *sc,
const char *peer_name,
const tsi_peer *peer) { const tsi_peer *peer) {
/* Check the ALPN. */ /* Check the ALPN. */
const tsi_peer_property *p = const tsi_peer_property *p =
@ -388,7 +448,7 @@ static grpc_security_status ssl_check_peer(const char *peer_name,
gpr_log(GPR_ERROR, "Peer name %s is not in peer certificate", peer_name); gpr_log(GPR_ERROR, "Peer name %s is not in peer certificate", peer_name);
return GRPC_SECURITY_ERROR; return GRPC_SECURITY_ERROR;
} }
sc->auth_context = tsi_ssl_peer_to_auth_context(peer);
return GRPC_SECURITY_OK; return GRPC_SECURITY_OK;
} }
@ -401,7 +461,7 @@ static grpc_security_status ssl_channel_check_peer(grpc_security_connector *sc,
grpc_security_status status; grpc_security_status status;
tsi_peer_destruct(&c->peer); tsi_peer_destruct(&c->peer);
c->peer = peer; c->peer = peer;
status = ssl_check_peer(c->overridden_target_name != NULL status = ssl_check_peer(sc, c->overridden_target_name != NULL
? c->overridden_target_name ? c->overridden_target_name
: c->target_name, : c->target_name,
&peer); &peer);
@ -412,8 +472,7 @@ static grpc_security_status ssl_server_check_peer(grpc_security_connector *sc,
tsi_peer peer, tsi_peer peer,
grpc_security_check_cb cb, grpc_security_check_cb cb,
void *user_data) { void *user_data) {
/* TODO(jboeuf): Find a way to expose the peer to the authorization layer. */ grpc_security_status status = ssl_check_peer(sc, NULL, &peer);
grpc_security_status status = ssl_check_peer(NULL, &peer);
tsi_peer_destruct(&peer); tsi_peer_destruct(&peer);
return status; return status;
} }

@ -77,6 +77,7 @@ struct grpc_security_connector {
gpr_refcount refcount; gpr_refcount refcount;
int is_client_side; int is_client_side;
const char *url_scheme; const char *url_scheme;
grpc_auth_context *auth_context; /* Populated after the peer is checked. */
}; };
/* Increments the refcount. */ /* Increments the refcount. */

@ -35,11 +35,14 @@
#include "src/core/security/security_context.h" #include "src/core/security/security_context.h"
#include "src/core/surface/call.h" #include "src/core/surface/call.h"
#include "src/core/support/string.h"
#include <grpc/grpc_security.h> #include <grpc/grpc_security.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
/* --- grpc_call --- */
grpc_call_error grpc_call_set_credentials(grpc_call *call, grpc_call_error grpc_call_set_credentials(grpc_call *call,
grpc_credentials *creds) { grpc_credentials *creds) {
grpc_client_security_context *ctx = NULL; grpc_client_security_context *ctx = NULL;
@ -65,6 +68,16 @@ grpc_call_error grpc_call_set_credentials(grpc_call *call,
return GRPC_CALL_OK; return GRPC_CALL_OK;
} }
const grpc_auth_context *grpc_call_auth_context(grpc_call *call) {
void *sec_ctx = grpc_call_context_get(call, GRPC_CONTEXT_SECURITY);
if (sec_ctx == NULL) return NULL;
return grpc_call_is_client(call)
? ((grpc_client_security_context *)sec_ctx)->auth_context
: ((grpc_server_security_context *)sec_ctx)->auth_context;
}
/* --- grpc_client_security_context --- */
grpc_client_security_context *grpc_client_security_context_create(void) { grpc_client_security_context *grpc_client_security_context_create(void) {
grpc_client_security_context *ctx = grpc_client_security_context *ctx =
gpr_malloc(sizeof(grpc_client_security_context)); gpr_malloc(sizeof(grpc_client_security_context));
@ -75,5 +88,142 @@ grpc_client_security_context *grpc_client_security_context_create(void) {
void grpc_client_security_context_destroy(void *ctx) { void grpc_client_security_context_destroy(void *ctx) {
grpc_client_security_context *c = (grpc_client_security_context *)ctx; grpc_client_security_context *c = (grpc_client_security_context *)ctx;
grpc_credentials_unref(c->creds); grpc_credentials_unref(c->creds);
grpc_auth_context_unref(c->auth_context);
gpr_free(ctx); gpr_free(ctx);
} }
/* --- grpc_server_security_context --- */
grpc_server_security_context *grpc_server_security_context_create(void) {
grpc_server_security_context *ctx =
gpr_malloc(sizeof(grpc_server_security_context));
memset(ctx, 0, sizeof(grpc_server_security_context));
return ctx;
}
void grpc_server_security_context_destroy(void *ctx) {
grpc_server_security_context *c = (grpc_server_security_context *)ctx;
grpc_auth_context_unref(c->auth_context);
gpr_free(ctx);
}
/* --- grpc_auth_context --- */
static grpc_auth_property_iterator empty_iterator = {NULL, 0, NULL};
grpc_auth_context *grpc_auth_context_create(grpc_auth_context *chained,
size_t property_count) {
grpc_auth_context *ctx = gpr_malloc(sizeof(grpc_auth_context));
memset(ctx, 0, sizeof(grpc_auth_context));
ctx->properties = gpr_malloc(property_count * sizeof(grpc_auth_property));
memset(ctx->properties, 0, property_count * sizeof(grpc_auth_property));
ctx->property_count = property_count;
gpr_ref_init(&ctx->refcount, 1);
if (chained != NULL) ctx->chained = grpc_auth_context_ref(chained);
return ctx;
}
grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *ctx) {
if (ctx == NULL) return NULL;
gpr_ref(&ctx->refcount);
return ctx;
}
void grpc_auth_context_unref(grpc_auth_context *ctx) {
if (ctx == NULL) return;
if (gpr_unref(&ctx->refcount)) {
size_t i;
grpc_auth_context_unref(ctx->chained);
if (ctx->properties != NULL) {
for (i = 0; i < ctx->property_count; i++) {
grpc_auth_property_reset(&ctx->properties[i]);
}
gpr_free(ctx->properties);
}
gpr_free(ctx);
}
}
const char *grpc_auth_context_peer_identity_property_name(
const grpc_auth_context *ctx) {
return ctx->peer_identity_property_name;
}
int grpc_auth_context_peer_is_authenticated(
const grpc_auth_context *ctx) {
return ctx->peer_identity_property_name == NULL ? 0 : 1;
}
grpc_auth_property_iterator grpc_auth_context_property_iterator(
const grpc_auth_context *ctx) {
grpc_auth_property_iterator it = empty_iterator;
if (ctx == NULL) return it;
it.ctx = ctx;
return it;
}
const grpc_auth_property *grpc_auth_property_iterator_next(
grpc_auth_property_iterator *it) {
if (it == NULL || it->ctx == NULL) return NULL;
while (it->index == it->ctx->property_count) {
if (it->ctx->chained == NULL) return NULL;
it->ctx = it->ctx->chained;
it->index = 0;
}
if (it->name == NULL) {
return &it->ctx->properties[it->index++];
} else {
while (it->index < it->ctx->property_count) {
const grpc_auth_property *prop = &it->ctx->properties[it->index++];
GPR_ASSERT(prop->name != NULL);
if (strcmp(it->name, prop->name) == 0) {
return prop;
}
}
/* We could not find the name, try another round. */
return grpc_auth_property_iterator_next(it);
}
}
grpc_auth_property_iterator grpc_auth_context_find_properties_by_name(
const grpc_auth_context *ctx, const char *name) {
grpc_auth_property_iterator it = empty_iterator;
if (ctx == NULL || name == NULL) return empty_iterator;
it.ctx = ctx;
it.name = name;
return it;
}
grpc_auth_property_iterator grpc_auth_context_peer_identity(
const grpc_auth_context *ctx) {
if (ctx == NULL) return empty_iterator;
return grpc_auth_context_find_properties_by_name(
ctx, ctx->peer_identity_property_name);
}
grpc_auth_property grpc_auth_property_init_from_cstring(const char *name,
const char *value) {
grpc_auth_property prop;
prop.name = gpr_strdup(name);
prop.value = gpr_strdup(value);
prop.value_length = strlen(value);
return prop;
}
grpc_auth_property grpc_auth_property_init(const char *name, const char *value,
size_t value_length) {
grpc_auth_property prop;
prop.name = gpr_strdup(name);
prop.value = gpr_malloc(value_length + 1);
memcpy(prop.value, value, value_length);
prop.value[value_length] = '\0';
prop.value_length = value_length;
return prop;
}
void grpc_auth_property_reset(grpc_auth_property *property) {
if (property->name != NULL) gpr_free(property->name);
if (property->value != NULL) gpr_free(property->value);
memset(property, 0, sizeof(grpc_auth_property));
}

@ -36,13 +36,59 @@
#include "src/core/security/credentials.h" #include "src/core/security/credentials.h"
/* Security context attached to a client-side call. */ /* --- grpc_auth_context ---
High level authentication context object. Can optionally be chained. */
/* Property names are always NULL terminated. */
struct grpc_auth_context {
struct grpc_auth_context *chained;
grpc_auth_property *properties;
size_t property_count;
gpr_refcount refcount;
const char *peer_identity_property_name;
};
/* Constructor. */
grpc_auth_context *grpc_auth_context_create(grpc_auth_context *chained,
size_t property_count);
/* Refcounting. */
grpc_auth_context *grpc_auth_context_ref(
grpc_auth_context *ctx);
void grpc_auth_context_unref(grpc_auth_context *ctx);
grpc_auth_property grpc_auth_property_init_from_cstring(const char *name,
const char *value);
grpc_auth_property grpc_auth_property_init(const char *name, const char *value,
size_t value_length);
void grpc_auth_property_reset(grpc_auth_property *property);
/* --- grpc_client_security_context ---
Internal client-side security context. */
typedef struct { typedef struct {
grpc_credentials *creds; grpc_credentials *creds;
grpc_auth_context *auth_context;
} grpc_client_security_context; } grpc_client_security_context;
grpc_client_security_context *grpc_client_security_context_create(void); grpc_client_security_context *grpc_client_security_context_create(void);
void grpc_client_security_context_destroy(void *ctx); void grpc_client_security_context_destroy(void *ctx);
/* --- grpc_server_security_context ---
Internal server-side security context. */
typedef struct {
grpc_auth_context *auth_context;
} grpc_server_security_context;
grpc_server_security_context *grpc_server_security_context_create(void);
void grpc_server_security_context_destroy(void *ctx);
#endif /* GRPC_INTERNAL_CORE_SECURITY_SECURITY_CONTEXT_H */ #endif /* GRPC_INTERNAL_CORE_SECURITY_SECURITY_CONTEXT_H */

@ -0,0 +1,128 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/core/security/auth_filters.h"
#include "src/core/security/security_connector.h"
#include "src/core/security/security_context.h"
#include <grpc/support/log.h>
typedef struct call_data {
int unused; /* C89 requires at least one struct element */
} call_data;
typedef struct channel_data {
grpc_security_connector *security_connector;
} channel_data;
/* Called either:
- in response to an API call (or similar) from above, to send something
- a network event (or similar) from below, to receive something
op contains type and call direction information, in addition to the data
that is being sent or received. */
static void auth_start_transport_op(grpc_call_element *elem,
grpc_transport_op *op) {
/* TODO(jboeuf): Get the metadata and get a new context from it. */
/* pass control down the stack */
grpc_call_next_op(elem, op);
}
/* Called on special channel events, such as disconnection or new incoming
calls on the server */
static void channel_op(grpc_channel_element *elem,
grpc_channel_element *from_elem, grpc_channel_op *op) {
grpc_channel_next_op(elem, op);
}
/* Constructor for call_data */
static void init_call_elem(grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_op *initial_op) {
/* grab pointers to our data from the call element */
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
grpc_server_security_context *server_ctx = NULL;
/* initialize members */
calld->unused = 0;
GPR_ASSERT(initial_op && initial_op->context != NULL &&
chand->security_connector->auth_context != NULL &&
initial_op->context[GRPC_CONTEXT_SECURITY].value == NULL);
/* Create a security context for the call and reference the auth context from
the channel. */
server_ctx = grpc_server_security_context_create();
server_ctx->auth_context =
grpc_auth_context_ref(chand->security_connector->auth_context);
initial_op->context[GRPC_CONTEXT_SECURITY].value = server_ctx;
initial_op->context[GRPC_CONTEXT_SECURITY].destroy =
grpc_server_security_context_destroy;
}
/* Destructor for call_data */
static void destroy_call_elem(grpc_call_element *elem) {
}
/* Constructor for channel_data */
static void init_channel_elem(grpc_channel_element *elem,
const grpc_channel_args *args, grpc_mdctx *mdctx,
int is_first, int is_last) {
grpc_security_connector *sc = grpc_find_security_connector_in_args(args);
/* grab pointers to our data from the channel element */
channel_data *chand = elem->channel_data;
/* The first and the last filters tend to be implemented differently to
handle the case that there's no 'next' filter to call on the up or down
path */
GPR_ASSERT(!is_first);
GPR_ASSERT(!is_last);
GPR_ASSERT(sc != NULL);
/* initialize members */
GPR_ASSERT(!sc->is_client_side);
chand->security_connector = grpc_security_connector_ref(sc);
}
/* Destructor for channel data */
static void destroy_channel_elem(grpc_channel_element *elem) {
/* grab pointers to our data from the channel element */
channel_data *chand = elem->channel_data;
grpc_security_connector_unref(chand->security_connector);
}
const grpc_channel_filter grpc_server_auth_filter = {
auth_start_transport_op, channel_op, sizeof(call_data), init_call_elem,
destroy_call_elem, sizeof(channel_data), init_channel_elem,
destroy_channel_elem, "server-auth"};

@ -35,10 +35,12 @@
#include <string.h> #include <string.h>
#include "src/core/channel/channel_args.h"
#include "src/core/channel/http_server_filter.h" #include "src/core/channel/http_server_filter.h"
#include "src/core/iomgr/endpoint.h" #include "src/core/iomgr/endpoint.h"
#include "src/core/iomgr/resolve_address.h" #include "src/core/iomgr/resolve_address.h"
#include "src/core/iomgr/tcp_server.h" #include "src/core/iomgr/tcp_server.h"
#include "src/core/security/auth_filters.h"
#include "src/core/security/credentials.h" #include "src/core/security/credentials.h"
#include "src/core/security/security_connector.h" #include "src/core/security/security_connector.h"
#include "src/core/security/secure_transport_setup.h" #include "src/core/security/secure_transport_setup.h"
@ -69,13 +71,21 @@ static void state_unref(grpc_server_secure_state *state) {
} }
} }
static grpc_transport_setup_result setup_transport(void *server, static grpc_transport_setup_result setup_transport(void *statep,
grpc_transport *transport, grpc_transport *transport,
grpc_mdctx *mdctx) { grpc_mdctx *mdctx) {
static grpc_channel_filter const *extra_filters[] = { static grpc_channel_filter const *extra_filters[] = {
&grpc_http_server_filter}; &grpc_server_auth_filter, &grpc_http_server_filter};
return grpc_server_setup_transport(server, transport, extra_filters, grpc_server_secure_state *state = statep;
GPR_ARRAY_SIZE(extra_filters), mdctx); grpc_transport_setup_result result;
grpc_arg connector_arg = grpc_security_connector_to_arg(state->sc);
grpc_channel_args *args_copy = grpc_channel_args_copy_and_add(
grpc_server_get_channel_args(state->server), &connector_arg);
result = grpc_server_setup_transport(state->server, transport, extra_filters,
GPR_ARRAY_SIZE(extra_filters), mdctx,
args_copy);
grpc_channel_args_destroy(args_copy);
return result;
} }
static void on_secure_transport_setup_done(void *statep, static void on_secure_transport_setup_done(void *statep,
@ -85,10 +95,9 @@ static void on_secure_transport_setup_done(void *statep,
if (status == GRPC_SECURITY_OK) { if (status == GRPC_SECURITY_OK) {
gpr_mu_lock(&state->mu); gpr_mu_lock(&state->mu);
if (!state->is_shutdown) { if (!state->is_shutdown) {
grpc_create_chttp2_transport(setup_transport, state->server, grpc_create_chttp2_transport(
grpc_server_get_channel_args(state->server), setup_transport, state, grpc_server_get_channel_args(state->server),
secure_endpoint, NULL, 0, secure_endpoint, NULL, 0, grpc_mdctx_create(), 0);
grpc_mdctx_create(), 0);
} else { } else {
/* We need to consume this here, because the server may already have gone /* We need to consume this here, because the server may already have gone
* away. */ * away. */

@ -131,33 +131,63 @@ void gpr_cmdline_on_extra_arg(
cl->extra_arg_help = help; cl->extra_arg_help = help;
} }
static void print_usage_and_die(gpr_cmdline *cl) { /* recursively descend argument list, adding the last element
/* TODO(ctiller): make this prettier */ to s first - so that arguments are added in the order they were
arg *a; added to the list by api calls */
const char *name = strrchr(cl->argv0, '/'); static void add_args_to_usage(gpr_strvec *s, arg *a) {
if (name) { char *tmp;
name++;
} else { if (!a) return;
name = cl->argv0; add_args_to_usage(s, a->next);
}
fprintf(stderr, "Usage: %s", name);
for (a = cl->args; a; a = a->next) {
switch (a->type) { switch (a->type) {
case ARGTYPE_BOOL: case ARGTYPE_BOOL:
fprintf(stderr, " [--%s|--no-%s]", a->name, a->name); gpr_asprintf(&tmp, " [--%s|--no-%s]", a->name, a->name);
gpr_strvec_add(s, tmp);
break; break;
case ARGTYPE_STRING: case ARGTYPE_STRING:
fprintf(stderr, " [--%s=string]", a->name); gpr_asprintf(&tmp, " [--%s=string]", a->name);
gpr_strvec_add(s, tmp);
break; break;
case ARGTYPE_INT: case ARGTYPE_INT:
fprintf(stderr, " [--%s=int]", a->name); gpr_asprintf(&tmp, " [--%s=int]", a->name);
gpr_strvec_add(s, tmp);
break; break;
} }
}
char *gpr_cmdline_usage_string(gpr_cmdline *cl, const char *argv0) {
/* TODO(ctiller): make this prettier */
gpr_strvec s;
char *tmp;
const char *name = strrchr(argv0, '/');
if (name) {
name++;
} else {
name = argv0;
} }
gpr_strvec_init(&s);
gpr_asprintf(&tmp, "Usage: %s", name);
gpr_strvec_add(&s, tmp);
add_args_to_usage(&s, cl->args);
if (cl->extra_arg) { if (cl->extra_arg) {
fprintf(stderr, " [%s...]", cl->extra_arg_name); gpr_asprintf(&tmp, " [%s...]", cl->extra_arg_name);
gpr_strvec_add(&s, tmp);
} }
fprintf(stderr, "\n"); gpr_strvec_add(&s, gpr_strdup("\n"));
tmp = gpr_strvec_flatten(&s, NULL);
gpr_strvec_destroy(&s);
return tmp;
}
static void print_usage_and_die(gpr_cmdline *cl) {
char *usage = gpr_cmdline_usage_string(cl, cl->argv0);
fprintf(stderr, "%s", usage);
gpr_free(usage);
exit(1); exit(1);
} }

@ -205,8 +205,8 @@ struct grpc_call {
/* Received call statuses from various sources */ /* Received call statuses from various sources */
received_status status[STATUS_SOURCE_COUNT]; received_status status[STATUS_SOURCE_COUNT];
void *context[GRPC_CONTEXT_COUNT]; /* Contexts for various subsystems (security, tracing, ...). */
void (*destroy_context[GRPC_CONTEXT_COUNT])(void *); grpc_call_context_element context[GRPC_CONTEXT_COUNT];
/* Deadline alarm - if have_alarm is non-zero */ /* Deadline alarm - if have_alarm is non-zero */
grpc_alarm alarm; grpc_alarm alarm;
@ -344,8 +344,8 @@ static void destroy_call(void *call, int ignored_success) {
grpc_mdelem_unref(c->send_initial_metadata[i].md); grpc_mdelem_unref(c->send_initial_metadata[i].md);
} }
for (i = 0; i < GRPC_CONTEXT_COUNT; i++) { for (i = 0; i < GRPC_CONTEXT_COUNT; i++) {
if (c->destroy_context[i]) { if (c->context[i].destroy) {
c->destroy_context[i](c->context[i]); c->context[i].destroy(c->context[i].value);
} }
} }
grpc_sopb_destroy(&c->send_ops); grpc_sopb_destroy(&c->send_ops);
@ -1300,15 +1300,15 @@ grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
void grpc_call_context_set(grpc_call *call, grpc_context_index elem, void *value, void grpc_call_context_set(grpc_call *call, grpc_context_index elem, void *value,
void (*destroy)(void *value)) { void (*destroy)(void *value)) {
if (call->destroy_context[elem]) { if (call->context[elem].destroy) {
call->destroy_context[elem](value); call->context[elem].destroy(call->context[elem].value);
} }
call->context[elem] = value; call->context[elem].value = value;
call->destroy_context[elem] = destroy; call->context[elem].destroy = destroy;
} }
void *grpc_call_context_get(grpc_call *call, grpc_context_index elem) { void *grpc_call_context_get(grpc_call *call, grpc_context_index elem) {
return call->context[elem]; return call->context[elem].value;
} }
gpr_uint8 grpc_call_is_client(grpc_call *call) { return call->is_client; } gpr_uint8 grpc_call_is_client(grpc_call *call) { return call->is_client; }

@ -46,7 +46,7 @@
#include "src/core/channel/http_client_filter.h" #include "src/core/channel/http_client_filter.h"
#include "src/core/iomgr/resolve_address.h" #include "src/core/iomgr/resolve_address.h"
#include "src/core/iomgr/tcp_client.h" #include "src/core/iomgr/tcp_client.h"
#include "src/core/security/auth.h" #include "src/core/security/auth_filters.h"
#include "src/core/security/credentials.h" #include "src/core/security/credentials.h"
#include "src/core/security/secure_transport_setup.h" #include "src/core/security/secure_transport_setup.h"
#include "src/core/support/string.h" #include "src/core/support/string.h"
@ -226,7 +226,7 @@ grpc_channel *grpc_secure_channel_create(grpc_credentials *creds,
GRPC_SECURITY_OK) { GRPC_SECURITY_OK) {
return grpc_lame_client_channel_create(); return grpc_lame_client_channel_create();
} }
mdctx = grpc_credentials_get_or_create_metadata_context(creds); mdctx = grpc_mdctx_create();
s = gpr_malloc(sizeof(setup)); s = gpr_malloc(sizeof(setup));
connector_arg = grpc_security_connector_to_arg(&connector->base); connector_arg = grpc_security_connector_to_arg(&connector->base);

@ -727,7 +727,7 @@ void grpc_server_start(grpc_server *server) {
grpc_transport_setup_result grpc_server_setup_transport( grpc_transport_setup_result grpc_server_setup_transport(
grpc_server *s, grpc_transport *transport, grpc_server *s, grpc_transport *transport,
grpc_channel_filter const **extra_filters, size_t num_extra_filters, grpc_channel_filter const **extra_filters, size_t num_extra_filters,
grpc_mdctx *mdctx) { grpc_mdctx *mdctx, const grpc_channel_args *args) {
size_t num_filters = s->channel_filter_count + num_extra_filters + 1; size_t num_filters = s->channel_filter_count + num_extra_filters + 1;
grpc_channel_filter const **filters = grpc_channel_filter const **filters =
gpr_malloc(sizeof(grpc_channel_filter *) * num_filters); gpr_malloc(sizeof(grpc_channel_filter *) * num_filters);
@ -758,8 +758,8 @@ grpc_transport_setup_result grpc_server_setup_transport(
grpc_transport_add_to_pollset(transport, grpc_cq_pollset(s->cqs[i])); grpc_transport_add_to_pollset(transport, grpc_cq_pollset(s->cqs[i]));
} }
channel = grpc_channel_create_from_filters(filters, num_filters, channel =
s->channel_args, mdctx, 0); grpc_channel_create_from_filters(filters, num_filters, args, mdctx, 0);
chand = (channel_data *)grpc_channel_stack_element( chand = (channel_data *)grpc_channel_stack_element(
grpc_channel_get_channel_stack(channel), 0) grpc_channel_get_channel_stack(channel), 0)
->channel_data; ->channel_data;

@ -58,7 +58,7 @@ void grpc_server_listener_destroy_done(void *server);
grpc_transport_setup_result grpc_server_setup_transport( grpc_transport_setup_result grpc_server_setup_transport(
grpc_server *server, grpc_transport *transport, grpc_server *server, grpc_transport *transport,
grpc_channel_filter const **extra_filters, size_t num_extra_filters, grpc_channel_filter const **extra_filters, size_t num_extra_filters,
grpc_mdctx *mdctx); grpc_mdctx *mdctx, const grpc_channel_args *args);
const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server); const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server);

@ -48,7 +48,8 @@ static grpc_transport_setup_result setup_transport(void *server,
static grpc_channel_filter const *extra_filters[] = { static grpc_channel_filter const *extra_filters[] = {
&grpc_http_server_filter}; &grpc_http_server_filter};
return grpc_server_setup_transport(server, transport, extra_filters, return grpc_server_setup_transport(server, transport, extra_filters,
GPR_ARRAY_SIZE(extra_filters), mdctx); GPR_ARRAY_SIZE(extra_filters), mdctx,
grpc_server_get_channel_args(server));
} }
static void new_transport(void *server, grpc_endpoint *tcp) { static void new_transport(void *server, grpc_endpoint *tcp) {

@ -96,6 +96,7 @@ size_t grpc_mdctx_get_mdtab_free_test_only(grpc_mdctx *mdctx);
/* Constructors for grpc_mdstr instances; take a variety of data types that /* Constructors for grpc_mdstr instances; take a variety of data types that
clients may have handy */ clients may have handy */
grpc_mdstr *grpc_mdstr_from_string(grpc_mdctx *ctx, const char *str); grpc_mdstr *grpc_mdstr_from_string(grpc_mdctx *ctx, const char *str);
/* Unrefs the slice. */
grpc_mdstr *grpc_mdstr_from_slice(grpc_mdctx *ctx, gpr_slice slice); grpc_mdstr *grpc_mdstr_from_slice(grpc_mdctx *ctx, gpr_slice slice);
grpc_mdstr *grpc_mdstr_from_buffer(grpc_mdctx *ctx, const gpr_uint8 *str, grpc_mdstr *grpc_mdstr_from_buffer(grpc_mdctx *ctx, const gpr_uint8 *str,
size_t length); size_t length);
@ -110,6 +111,7 @@ grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_mdctx *ctx, grpc_mdstr *key,
grpc_mdstr *value); grpc_mdstr *value);
grpc_mdelem *grpc_mdelem_from_strings(grpc_mdctx *ctx, const char *key, grpc_mdelem *grpc_mdelem_from_strings(grpc_mdctx *ctx, const char *key,
const char *value); const char *value);
/* Unrefs the slices. */
grpc_mdelem *grpc_mdelem_from_slices(grpc_mdctx *ctx, gpr_slice key, grpc_mdelem *grpc_mdelem_from_slices(grpc_mdctx *ctx, gpr_slice key,
gpr_slice value); gpr_slice value);
grpc_mdelem *grpc_mdelem_from_string_and_buffer(grpc_mdctx *ctx, grpc_mdelem *grpc_mdelem_from_string_and_buffer(grpc_mdctx *ctx,

@ -38,6 +38,7 @@
#include "src/core/iomgr/pollset.h" #include "src/core/iomgr/pollset.h"
#include "src/core/transport/stream_op.h" #include "src/core/transport/stream_op.h"
#include "src/core/channel/context.h"
/* forward declarations */ /* forward declarations */
typedef struct grpc_transport grpc_transport; typedef struct grpc_transport grpc_transport;
@ -78,7 +79,7 @@ typedef struct grpc_transport_op {
grpc_mdstr *cancel_message; grpc_mdstr *cancel_message;
/* Indexes correspond to grpc_context_index enum values */ /* Indexes correspond to grpc_context_index enum values */
void *const *context; grpc_call_context_element *context;
} grpc_transport_op; } grpc_transport_op;
/* Callbacks made from the transport to the upper layers of grpc. */ /* Callbacks made from the transport to the upper layers of grpc. */

@ -75,6 +75,10 @@ class Server::SyncRequest GRPC_FINAL : public CompletionQueueTag {
grpc_metadata_array_init(&request_metadata_); grpc_metadata_array_init(&request_metadata_);
} }
~SyncRequest() {
grpc_metadata_array_destroy(&request_metadata_);
}
static SyncRequest* Wait(CompletionQueue* cq, bool* ok) { static SyncRequest* Wait(CompletionQueue* cq, bool* ok) {
void* tag = nullptr; void* tag = nullptr;
*ok = false; *ok = false;

@ -7,7 +7,7 @@
<description>Auth library for C# implementation of gRPC - an RPC library and framework. See project site for more info.</description> <description>Auth library for C# implementation of gRPC - an RPC library and framework. See project site for more info.</description>
<version>0.5.0</version> <version>0.5.0</version>
<authors>Google Inc.</authors> <authors>Google Inc.</authors>
<owners>jtattermusch</owners> <owners>grpc-packages</owners>
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl> <licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/grpc/grpc</projectUrl> <projectUrl>https://github.com/grpc/grpc</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance> <requireLicenseAcceptance>false</requireLicenseAcceptance>

@ -7,7 +7,7 @@
<description>Core C# implementation of gRPC - an RPC library and framework. See project site for more info.</description> <description>Core C# implementation of gRPC - an RPC library and framework. See project site for more info.</description>
<version>0.5.0</version> <version>0.5.0</version>
<authors>Google Inc.</authors> <authors>Google Inc.</authors>
<owners>jtattermusch</owners> <owners>grpc-packages</owners>
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl> <licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/grpc/grpc</projectUrl> <projectUrl>https://github.com/grpc/grpc</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance> <requireLicenseAcceptance>false</requireLicenseAcceptance>

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<package>
<metadata>
<id>Grpc.Tools</id>
<title>gRPC C# Tools</title>
<summary>Tools for C# implementation of gRPC - an RPC library and framework</summary>
<description>Precompiled Windows binaries for generating protocol buffer messages and gRPC client/server code</description>
<version>0.5.0</version>
<authors>Google Inc.</authors>
<owners>grpc-packages</owners>
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/grpc/grpc</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<releaseNotes>protoc.exe - protocol buffer compiler v3.0.0-alpha-3; grpc_csharp_plugin.exe - gRPC C# protoc plugin version 0.5.0</releaseNotes>
<copyright>Copyright 2015, Google Inc.</copyright>
<tags>gRPC RPC Protocol HTTP/2</tags>
</metadata>
<files>
<file src="protoc.exe" target="tools" />
<file src="grpc_csharp_plugin.exe" target="tools" />
</files>
</package>

@ -5,9 +5,9 @@
<title>gRPC C#</title> <title>gRPC C#</title>
<summary>C# implementation of gRPC - an RPC library and framework</summary> <summary>C# implementation of gRPC - an RPC library and framework</summary>
<description>C# implementation of gRPC - an RPC library and framework. See project site for more info.</description> <description>C# implementation of gRPC - an RPC library and framework. See project site for more info.</description>
<version>0.5.0</version> <version>0.5.0.1</version>
<authors>Google Inc.</authors> <authors>Google Inc.</authors>
<owners>jtattermusch</owners> <owners>grpc-packages</owners>
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl> <licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/grpc/grpc</projectUrl> <projectUrl>https://github.com/grpc/grpc</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance> <requireLicenseAcceptance>false</requireLicenseAcceptance>

@ -35,15 +35,16 @@ Usage: Linux (Mono)
- (preferred approach) add `libgrpc_csharp_ext.so` to `/etc/ld.so.cache` by running: - (preferred approach) add `libgrpc_csharp_ext.so` to `/etc/ld.so.cache` by running:
```sh ```sh
echo "$HOME/.linuxbrew/lib" | sudo tee /etc/ld.so.conf.d/zzz_brew_lib.conf $ echo "$HOME/.linuxbrew/lib" | sudo tee /etc/ld.so.conf.d/zzz_brew_lib.conf
sudo ldconfig $ sudo ldconfig
``` ```
- (adhoc approach) set `LD_LIBRARY_PATH` environment variable to point to directory containing `libgrpc_csharp_ext.so`: - (adhoc approach) set `LD_LIBRARY_PATH` environment variable to point to directory containing `libgrpc_csharp_ext.so`:
```sh ```sh
export LD_LIBRARY_PATH=$HOME/.linuxbrew/lib:${LD_LIBRARY_PATH} $ export LD_LIBRARY_PATH=$HOME/.linuxbrew/lib:${LD_LIBRARY_PATH}
``` ```
- (if you are contributor) installing gRPC from sources using `sudo make install_grpc_csharp_ext` also works.
- Open MonoDevelop and start a new project/solution. - Open MonoDevelop and start a new project/solution.
@ -87,14 +88,14 @@ If you are a user of gRPC C#, go to Usage section above.
a convenience batch script that builds everything for you. a convenience batch script that builds everything for you.
``` ```
buildall.bat > buildall.bat
``` ```
- Open Grpc.sln using Visual Studio 2013. NuGet dependencies will be restored - Open Grpc.sln using Visual Studio 2013. NuGet dependencies will be restored
upon build (you need to have NuGet add-in installed). upon build (you need to have NuGet add-in installed).
Building: Linux & Mono Building: Linux (Mono)
---------------------- ----------------------
You only need to go through these steps if you are planning to develop gRPC C#. You only need to go through these steps if you are planning to develop gRPC C#.
@ -103,8 +104,8 @@ If you are a user of gRPC C#, go to Usage section above.
- Prerequisites for development: Mono 3.2.8+, MonoDevelop 5.9 with NuGet and NUnit add-ins installed. - Prerequisites for development: Mono 3.2.8+, MonoDevelop 5.9 with NuGet and NUnit add-ins installed.
```sh ```sh
sudo apt-get install mono-devel $ sudo apt-get install mono-devel
sudo apt-get install nunit nunit-console $ sudo apt-get install nunit nunit-console
``` ```
You can use older versions of MonoDevelop, but then you might need to restore You can use older versions of MonoDevelop, but then you might need to restore
@ -114,8 +115,8 @@ don't support NuGet add-in.
- Compile and install the gRPC C# extension library (that will be used via - Compile and install the gRPC C# extension library (that will be used via
P/Invoke from C#). P/Invoke from C#).
```sh ```sh
make grpc_csharp_ext $ make grpc_csharp_ext
sudo make install_grpc_csharp_ext $ sudo make install_grpc_csharp_ext
``` ```
- Use MonoDevelop to open the solution Grpc.sln - Use MonoDevelop to open the solution Grpc.sln
@ -135,9 +136,9 @@ Then you should be able to run all the test from the Test View.
After building the solution, you can also run the tests from command line After building the solution, you can also run the tests from command line
using nunit-console tool. using nunit-console tool.
``` ```sh
# from Grpc.Core.Test/bin/Debug directory # from Grpc.Core.Test/bin/Debug directory
nunit-console Grpc.Core.Tests.dll $ nunit-console Grpc.Core.Tests.dll
``` ```
Contents Contents

@ -13,6 +13,7 @@ endlocal
%NUGET% pack ..\..\vsprojects\nuget_package\grpc.native.csharp_ext.nuspec || goto :error %NUGET% pack ..\..\vsprojects\nuget_package\grpc.native.csharp_ext.nuspec || goto :error
%NUGET% pack Grpc.Core\Grpc.Core.nuspec -Symbols || goto :error %NUGET% pack Grpc.Core\Grpc.Core.nuspec -Symbols || goto :error
%NUGET% pack Grpc.Auth\Grpc.Auth.nuspec -Symbols || goto :error %NUGET% pack Grpc.Auth\Grpc.Auth.nuspec -Symbols || goto :error
%NUGET% pack Grpc.Tools.nuspec || goto :error
%NUGET% pack Grpc.nuspec || goto :error %NUGET% pack Grpc.nuspec || goto :error
goto :EOF goto :EOF

@ -38,13 +38,17 @@
@implementation GRPCSecureChannel @implementation GRPCSecureChannel
- (instancetype)initWithHost:(NSString *)host { - (instancetype)initWithHost:(NSString *)host {
// TODO(jcanizales): Load certs only once. static const grpc_credentials *kCredentials;
NSURL *certsURL = [[NSBundle mainBundle] URLForResource:@"gRPC.bundle/roots" withExtension:@"pem"]; static dispatch_once_t loading;
NSData *certsData = [NSData dataWithContentsOfURL:certsURL]; dispatch_once(&loading, ^{
// Do not use NSBundle.mainBundle, as it's nil for tests of library projects.
NSBundle *bundle = [NSBundle bundleForClass:self.class];
NSString *certsPath = [bundle pathForResource:@"gRPC.bundle/roots" ofType:@"pem"];
NSData *certsData = [NSData dataWithContentsOfFile:certsPath];
NSString *certsString = [[NSString alloc] initWithData:certsData encoding:NSUTF8StringEncoding]; NSString *certsString = [[NSString alloc] initWithData:certsData encoding:NSUTF8StringEncoding];
kCredentials = grpc_ssl_credentials_create(certsString.UTF8String, NULL);
grpc_credentials *credentials = grpc_ssl_credentials_create(certsString.UTF8String, NULL); });
return (self = [super initWithChannel:grpc_secure_channel_create(credentials, return (self = [super initWithChannel:grpc_secure_channel_create(kCredentials,
host.UTF8String, host.UTF8String,
NULL)]); NULL)]);
} }

@ -50,13 +50,15 @@ Pod::Spec.new do |s|
s.osx.deployment_target = '10.8' s.osx.deployment_target = '10.8'
s.subspec 'Messages' do |ms| s.subspec 'Messages' do |ms|
ms.source_files = '*.pbobjc.{h,m}' ms.source_files = '*.pbobjc.{h,m}', '**/*.pbobjc.{h,m}'
ms.header_mappings_dir = '.'
ms.requires_arc = false ms.requires_arc = false
ms.dependency 'Protobuf', '~> 3.0' ms.dependency 'Protobuf', '~> 3.0'
end end
s.subspec 'Services' do |ss| s.subspec 'Services' do |ss|
ss.source_files = '*.pbrpc.{h,m}' ss.source_files = '*.pbrpc.{h,m}', '**/*.pbrpc.{h,m}'
ss.header_mappings_dir = '.'
ss.requires_arc = true ss.requires_arc = true
ss.dependency 'gRPC', '~> 0.0' ss.dependency 'gRPC', '~> 0.0'
ss.dependency '<Podspec file name>/Messages' ss.dependency '<Podspec file name>/Messages'

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>gRPC.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>

@ -0,0 +1,12 @@
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
pod 'gRPC/RxLibrary', :path => "../../.."
link_with 'AllTests'
target 'Tests' do
end
target 'AllTests' do
end

@ -0,0 +1,140 @@
/*
*
* Copyright 2015, 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.
*
*/
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import <gRPC/GRXBufferedPipe.h>
#import <gRPC/GRXWriter.h>
#import <gRPC/GRXWriteable.h>
// A mock of a GRXSingleValueHandler block that can be queried for how many times it was called and
// what were the last values passed to it.
//
// TODO(jcanizales): Move this to a test util library, and add tests for it.
@interface CapturingSingleValueHandler : NSObject
@property (nonatomic, readonly) void (^block)(id value, NSError *errorOrNil);
@property (nonatomic, readonly) NSUInteger timesCalled;
@property (nonatomic, readonly) id value;
@property (nonatomic, readonly) NSError *errorOrNil;
+ (instancetype)handler;
@end
@implementation CapturingSingleValueHandler
+ (instancetype)handler {
return [[self alloc] init];
}
- (GRXSingleValueHandler)block {
return ^(id value, NSError *errorOrNil) {
++_timesCalled;
_value = value;
_errorOrNil = errorOrNil;
};
}
@end
@interface RxLibraryUnitTests : XCTestCase
@end
@implementation RxLibraryUnitTests
#pragma mark Writeable
- (void)testWriteableSingleValueHandlerIsCalledForValue {
// Given:
CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
id anyValue = @7;
// If:
id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleValueHandler:handler.block];
[writeable writeValue:anyValue];
// Then:
XCTAssertEqual(handler.timesCalled, 1);
XCTAssertEqualObjects(handler.value, anyValue);
XCTAssertEqualObjects(handler.errorOrNil, nil);
}
- (void)testWriteableSingleValueHandlerIsCalledForError {
// Given:
CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
NSError *anyError = [NSError errorWithDomain:@"domain" code:7 userInfo:nil];
// If:
id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleValueHandler:handler.block];
[writeable writesFinishedWithError:anyError];
// Then:
XCTAssertEqual(handler.timesCalled, 1);
XCTAssertEqualObjects(handler.value, nil);
XCTAssertEqualObjects(handler.errorOrNil, anyError);
}
#pragma mark BufferedPipe
- (void)testBufferedPipePropagatesValue {
// Given:
CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleValueHandler:handler.block];
id anyValue = @7;
// If:
GRXBufferedPipe *pipe = [GRXBufferedPipe pipe];
[pipe startWithWriteable:writeable];
[pipe writeValue:anyValue];
// Then:
XCTAssertEqual(handler.timesCalled, 1);
XCTAssertEqualObjects(handler.value, anyValue);
XCTAssertEqualObjects(handler.errorOrNil, nil);
}
- (void)testBufferedPipePropagatesError {
// Given:
CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleValueHandler:handler.block];
NSError *anyError = [NSError errorWithDomain:@"domain" code:7 userInfo:nil];
// If:
GRXBufferedPipe *pipe = [GRXBufferedPipe pipe];
[pipe startWithWriteable:writeable];
[pipe writesFinishedWithError:anyError];
// Then:
XCTAssertEqual(handler.timesCalled, 1);
XCTAssertEqualObjects(handler.value, nil);
XCTAssertEqualObjects(handler.errorOrNil, anyError);
}
@end

@ -0,0 +1,40 @@
/*
*
* Copyright 2015, 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.
*
*/
#import <Foundation/Foundation.h>
@interface Tests : NSObject
@end
@implementation Tests
@end

@ -0,0 +1,430 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
63423F4A1B150A5F006CF63C /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; };
63423F511B151B77006CF63C /* RxLibraryUnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 63423F501B151B77006CF63C /* RxLibraryUnitTests.m */; };
635697CD1B14FC11007A7283 /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 635697CC1B14FC11007A7283 /* Tests.m */; };
7D8A186224D39101F90230F6 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 35F2B6BF3BAE8F0DC4AFD76E /* libPods.a */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
63423F4B1B150A5F006CF63C /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 635697BF1B14FC11007A7283 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 635697C61B14FC11007A7283;
remoteInfo = Tests;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
635697C51B14FC11007A7283 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "include/$(PRODUCT_NAME)";
dstSubfolderSpec = 16;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
0A4F89D9C90E9C30990218F0 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
35F2B6BF3BAE8F0DC4AFD76E /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
63423F441B150A5F006CF63C /* AllTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AllTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
63423F501B151B77006CF63C /* RxLibraryUnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RxLibraryUnitTests.m; sourceTree = "<group>"; };
635697C71B14FC11007A7283 /* libTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libTests.a; sourceTree = BUILT_PRODUCTS_DIR; };
635697CC1B14FC11007A7283 /* Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = "<group>"; };
635697D81B14FC11007A7283 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
FF7B5489BCFE40111D768DD0 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
63423F411B150A5F006CF63C /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
63423F4A1B150A5F006CF63C /* libTests.a in Frameworks */,
7D8A186224D39101F90230F6 /* libPods.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
635697C41B14FC11007A7283 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
136D535E19727099B941D7B1 /* Frameworks */ = {
isa = PBXGroup;
children = (
35F2B6BF3BAE8F0DC4AFD76E /* libPods.a */,
);
name = Frameworks;
sourceTree = "<group>";
};
51E4650F34F854F41FF053B3 /* Pods */ = {
isa = PBXGroup;
children = (
FF7B5489BCFE40111D768DD0 /* Pods.debug.xcconfig */,
0A4F89D9C90E9C30990218F0 /* Pods.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
635697BE1B14FC11007A7283 = {
isa = PBXGroup;
children = (
635697C91B14FC11007A7283 /* Tests */,
635697C81B14FC11007A7283 /* Products */,
51E4650F34F854F41FF053B3 /* Pods */,
136D535E19727099B941D7B1 /* Frameworks */,
);
sourceTree = "<group>";
};
635697C81B14FC11007A7283 /* Products */ = {
isa = PBXGroup;
children = (
635697C71B14FC11007A7283 /* libTests.a */,
63423F441B150A5F006CF63C /* AllTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
635697C91B14FC11007A7283 /* Tests */ = {
isa = PBXGroup;
children = (
63423F501B151B77006CF63C /* RxLibraryUnitTests.m */,
635697CC1B14FC11007A7283 /* Tests.m */,
635697D71B14FC11007A7283 /* Supporting Files */,
);
name = Tests;
sourceTree = SOURCE_ROOT;
};
635697D71B14FC11007A7283 /* Supporting Files */ = {
isa = PBXGroup;
children = (
635697D81B14FC11007A7283 /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
63423F431B150A5F006CF63C /* AllTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 63423F4D1B150A5F006CF63C /* Build configuration list for PBXNativeTarget "AllTests" */;
buildPhases = (
914ADDD7106BA9BB8A7E569F /* Check Pods Manifest.lock */,
63423F401B150A5F006CF63C /* Sources */,
63423F411B150A5F006CF63C /* Frameworks */,
63423F421B150A5F006CF63C /* Resources */,
A441F71824DCB9D0CA297748 /* Copy Pods Resources */,
);
buildRules = (
);
dependencies = (
63423F4C1B150A5F006CF63C /* PBXTargetDependency */,
);
name = AllTests;
productName = AllTests;
productReference = 63423F441B150A5F006CF63C /* AllTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
635697C61B14FC11007A7283 /* Tests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 635697DB1B14FC11007A7283 /* Build configuration list for PBXNativeTarget "Tests" */;
buildPhases = (
635697C31B14FC11007A7283 /* Sources */,
635697C41B14FC11007A7283 /* Frameworks */,
635697C51B14FC11007A7283 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = Tests;
productName = Tests;
productReference = 635697C71B14FC11007A7283 /* libTests.a */;
productType = "com.apple.product-type.library.static";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
635697BF1B14FC11007A7283 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0630;
ORGANIZATIONNAME = gRPC;
TargetAttributes = {
63423F431B150A5F006CF63C = {
CreatedOnToolsVersion = 6.3.1;
};
635697C61B14FC11007A7283 = {
CreatedOnToolsVersion = 6.3.1;
};
};
};
buildConfigurationList = 635697C21B14FC11007A7283 /* Build configuration list for PBXProject "Tests" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 635697BE1B14FC11007A7283;
productRefGroup = 635697C81B14FC11007A7283 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
635697C61B14FC11007A7283 /* Tests */,
63423F431B150A5F006CF63C /* AllTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
63423F421B150A5F006CF63C /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
914ADDD7106BA9BB8A7E569F /* Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
A441F71824DCB9D0CA297748 /* Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
63423F401B150A5F006CF63C /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
63423F511B151B77006CF63C /* RxLibraryUnitTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
635697C31B14FC11007A7283 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
635697CD1B14FC11007A7283 /* Tests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
63423F4C1B150A5F006CF63C /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 635697C61B14FC11007A7283 /* Tests */;
targetProxy = 63423F4B1B150A5F006CF63C /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
63423F4E1B150A5F006CF63C /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = FF7B5489BCFE40111D768DD0 /* Pods.debug.xcconfig */;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
63423F4F1B150A5F006CF63C /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 0A4F89D9C90E9C30990218F0 /* Pods.release.xcconfig */;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
INFOPLIST_FILE = Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
635697D91B14FC11007A7283 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
name = Debug;
};
635697DA1B14FC11007A7283 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
635697DC1B14FC11007A7283 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
};
name = Debug;
};
635697DD1B14FC11007A7283 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
63423F4D1B150A5F006CF63C /* Build configuration list for PBXNativeTarget "AllTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
63423F4E1B150A5F006CF63C /* Debug */,
63423F4F1B150A5F006CF63C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
635697C21B14FC11007A7283 /* Build configuration list for PBXProject "Tests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
635697D91B14FC11007A7283 /* Debug */,
635697DA1B14FC11007A7283 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
635697DB1B14FC11007A7283 /* Build configuration list for PBXNativeTarget "Tests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
635697DC1B14FC11007A7283 /* Debug */,
635697DD1B14FC11007A7283 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 635697BF1B14FC11007A7283 /* Project object */;
}

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:Tests.xcodeproj">
</FileRef>
</Workspace>

@ -54,4 +54,4 @@ class InsecureInteropTest(
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main(verbosity=2)

@ -53,3 +53,9 @@ class InteropTestCase(object):
def testPingPong(self): def testPingPong(self):
methods.TestCase.PING_PONG.test_interoperability(self.stub, None) methods.TestCase.PING_PONG.test_interoperability(self.stub, None)
def testCancelAfterBegin(self):
methods.TestCase.CANCEL_AFTER_BEGIN.test_interoperability(self.stub, None)
def testCancelAfterFirstResponse(self):
methods.TestCase.CANCEL_AFTER_FIRST_RESPONSE.test_interoperability(self.stub, None)

@ -61,4 +61,4 @@ class SecureInteropTest(
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main(verbosity=2)

@ -219,6 +219,17 @@ def _server_streaming(stub):
raise ValueError( raise ValueError(
'response body of invalid size %d!' % len(response.payload.body)) 'response body of invalid size %d!' % len(response.payload.body))
def _cancel_after_begin(stub):
with stub:
sizes = (27182, 8, 1828, 45904)
payloads = [messages_pb2.Payload(body=b'\x00' * size) for size in sizes]
requests = [messages_pb2.StreamingInputCallRequest(payload=payload)
for payload in payloads]
responses = stub.StreamingInputCall.async(requests, _TIMEOUT)
responses.cancel()
if not responses.cancelled():
raise ValueError('expected call to be cancelled')
class _Pipe(object): class _Pipe(object):
@ -249,13 +260,18 @@ class _Pipe(object):
self._open = False self._open = False
self._condition.notify() self._condition.notify()
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
self.close()
def _ping_pong(stub): def _ping_pong(stub):
request_response_sizes = (31415, 9, 2653, 58979) request_response_sizes = (31415, 9, 2653, 58979)
request_payload_sizes = (27182, 8, 1828, 45904) request_payload_sizes = (27182, 8, 1828, 45904)
with stub: with stub, _Pipe() as pipe:
pipe = _Pipe()
response_iterator = stub.FullDuplexCall(pipe, _TIMEOUT) response_iterator = stub.FullDuplexCall(pipe, _TIMEOUT)
print 'Starting ping-pong with response iterator %s' % response_iterator print 'Starting ping-pong with response iterator %s' % response_iterator
for response_size, payload_size in zip( for response_size, payload_size in zip(
@ -273,7 +289,33 @@ def _ping_pong(stub):
if len(response.payload.body) != response_size: if len(response.payload.body) != response_size:
raise ValueError( raise ValueError(
'response body of invalid size %d!' % len(response.payload.body)) 'response body of invalid size %d!' % len(response.payload.body))
pipe.close()
def _cancel_after_first_response(stub):
request_response_sizes = (31415, 9, 2653, 58979)
request_payload_sizes = (27182, 8, 1828, 45904)
with stub, _Pipe() as pipe:
response_iterator = stub.FullDuplexCall(pipe, _TIMEOUT)
response_size = request_response_sizes[0]
payload_size = request_payload_sizes[0]
request = messages_pb2.StreamingOutputCallRequest(
response_type=messages_pb2.COMPRESSABLE,
response_parameters=(messages_pb2.ResponseParameters(
size=response_size),),
payload=messages_pb2.Payload(body=b'\x00' * payload_size))
pipe.add(request)
response = next(response_iterator)
# We test the contents of `response` in the Ping Pong test - don't check
# them here.
response_iterator.cancel()
try:
next(response_iterator)
except Exception:
pass
else:
raise ValueError('expected call to be cancelled')
def _compute_engine_creds(stub, args): def _compute_engine_creds(stub, args):
@ -305,6 +347,8 @@ class TestCase(enum.Enum):
SERVER_STREAMING = 'server_streaming' SERVER_STREAMING = 'server_streaming'
CLIENT_STREAMING = 'client_streaming' CLIENT_STREAMING = 'client_streaming'
PING_PONG = 'ping_pong' PING_PONG = 'ping_pong'
CANCEL_AFTER_BEGIN = 'cancel_after_begin'
CANCEL_AFTER_FIRST_RESPONSE = 'cancel_after_first_response'
COMPUTE_ENGINE_CREDS = 'compute_engine_creds' COMPUTE_ENGINE_CREDS = 'compute_engine_creds'
SERVICE_ACCOUNT_CREDS = 'service_account_creds' SERVICE_ACCOUNT_CREDS = 'service_account_creds'
@ -319,6 +363,10 @@ class TestCase(enum.Enum):
_client_streaming(stub) _client_streaming(stub)
elif self is TestCase.PING_PONG: elif self is TestCase.PING_PONG:
_ping_pong(stub) _ping_pong(stub)
elif self is TestCase.CANCEL_AFTER_BEGIN:
_cancel_after_begin(stub)
elif self is TestCase.CANCEL_AFTER_FIRST_RESPONSE:
_cancel_after_first_response(stub)
elif self is TestCase.COMPUTE_ENGINE_CREDS: elif self is TestCase.COMPUTE_ENGINE_CREDS:
_compute_engine_creds(stub, args) _compute_engine_creds(stub, args)
elif self is TestCase.SERVICE_ACCOUNT_CREDS: elif self is TestCase.SERVICE_ACCOUNT_CREDS:

@ -43,4 +43,4 @@ class BlockingInvocationInlineServiceTest(
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main(verbosity=2)

@ -43,4 +43,4 @@ class EventInvocationSynchronousEventServiceTest(
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main(verbosity=2)

@ -43,4 +43,4 @@ class FutureInvocationAsynchronousEventServiceTest(
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main(verbosity=2)

@ -274,4 +274,4 @@ class RoundTripTest(unittest.TestCase):
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main(verbosity=2)

@ -97,4 +97,4 @@ class LonelyRearLinkTest(unittest.TestCase):
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main(verbosity=2)

@ -412,4 +412,4 @@ class ExpirationTest(unittest.TestCase):
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main(verbosity=2)

@ -177,4 +177,4 @@ class EarlyAdopterImplementationsTest(unittest.TestCase):
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main(verbosity=2)

@ -77,4 +77,4 @@ class ImplementationsTest(
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main(verbosity=2)

@ -43,4 +43,4 @@ class BlockingInvocationInlineServiceTest(
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main(verbosity=2)

@ -43,4 +43,4 @@ class EventInvocationSynchronousEventServiceTest(
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main(verbosity=2)

@ -43,4 +43,4 @@ class FutureInvocationAsynchronousEventServiceTest(
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main(verbosity=2)

@ -148,4 +148,4 @@ class LaterTest(unittest.TestCase):
self.assertEqual(return_value, future_passed_to_callback_cell[0].result()) self.assertEqual(return_value, future_passed_to_callback_cell[0].result())
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main(verbosity=2)

@ -61,4 +61,4 @@ class LoggingPoolTest(unittest.TestCase):
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main(verbosity=2)

@ -128,16 +128,19 @@ class TestTarget < Grpc::Testing::TestService::Service
cls = StreamingOutputCallResponse cls = StreamingOutputCallResponse
Thread.new do Thread.new do
begin begin
GRPC.logger.info('interop-server: started receiving')
reqs.each do |req| reqs.each do |req|
GRPC.logger.info("read #{req.inspect}")
resp_size = req.response_parameters[0].size resp_size = req.response_parameters[0].size
GRPC.logger.info("read a req, response size is #{resp_size}")
resp = cls.new(payload: Payload.new(type: req.response_type, resp = cls.new(payload: Payload.new(type: req.response_type,
body: nulls(resp_size))) body: nulls(resp_size)))
q.push(resp) q.push(resp)
end end
GRPC.logger.info('finished reads') GRPC.logger.info('interop-server: finished receiving')
q.push(self) q.push(self)
rescue StandardError => e rescue StandardError => e
GRPC.logger.info('interop-server: failed')
GRPC.logger.warn(e)
q.push(e) # share the exception with the enumerator q.push(e) # share the exception with the enumerator
end end
end end

@ -39,6 +39,7 @@ class Struct
return nil if status.nil? return nil if status.nil?
fail GRPC::Cancelled if status.code == GRPC::Core::StatusCodes::CANCELLED fail GRPC::Cancelled if status.code == GRPC::Core::StatusCodes::CANCELLED
if status.code != GRPC::Core::StatusCodes::OK if status.code != GRPC::Core::StatusCodes::OK
GRPC.logger.debug("Failing with status #{status}")
# raise BadStatus, propagating the metadata if present. # raise BadStatus, propagating the metadata if present.
md = status.metadata md = status.metadata
with_sym_keys = Hash[md.each_pair.collect { |x, y| [x.to_sym, y] }] with_sym_keys = Hash[md.each_pair.collect { |x, y| [x.to_sym, y] }]

@ -100,6 +100,7 @@ module GRPC
replys = gen_each_reply.call(each_queued_msg) replys = gen_each_reply.call(each_queued_msg)
@enq_th = start_write_loop(replys, is_client: false) @enq_th = start_write_loop(replys, is_client: false)
@loop_th = start_read_loop @loop_th = start_read_loop
@enq_th.join if @enq_th.alive?
end end
private private
@ -115,7 +116,7 @@ module GRPC
return enum_for(:each_queued_msg) unless block_given? return enum_for(:each_queued_msg) unless block_given?
count = 0 count = 0
loop do loop do
GRPC.logger.debug("each_queued_msg: msg##{count}") GRPC.logger.debug("each_queued_msg: waiting##{count}")
count += 1 count += 1
req = @readq.pop req = @readq.pop
GRPC.logger.debug("each_queued_msg: req = #{req}") GRPC.logger.debug("each_queued_msg: req = #{req}")
@ -123,70 +124,73 @@ module GRPC
break if req.equal?(END_OF_READS) break if req.equal?(END_OF_READS)
yield req yield req
end end
@enq_th.join if @enq_th.alive?
end end
# during bidi-streaming, read the requests to send from a separate thread # during bidi-streaming, read the requests to send from a separate thread
# read so that read_loop does not block waiting for requests to read. # read so that read_loop does not block waiting for requests to read.
def start_write_loop(requests, is_client: true) def start_write_loop(requests, is_client: true)
Thread.new do # TODO: run on a thread pool Thread.new do # TODO: run on a thread pool
write_tag = Object.new GRPC.logger.debug('bidi-write-loop: starting')
begin begin
write_tag = Object.new
count = 0 count = 0
requests.each do |req| requests.each do |req|
GRPC.logger.debug("bidi-write_loop: #{count}") GRPC.logger.debug("bidi-write-loop: #{count}")
count += 1 count += 1
payload = @marshal.call(req) payload = @marshal.call(req)
@call.run_batch(@cq, write_tag, INFINITE_FUTURE, @call.run_batch(@cq, write_tag, INFINITE_FUTURE,
SEND_MESSAGE => payload) SEND_MESSAGE => payload)
end end
GRPC.logger.debug("bidi-write-loop: #{count} writes done")
if is_client if is_client
GRPC.logger.debug("bidi-write-loop: sent #{count}, waiting") GRPC.logger.debug("bidi-write-loop: client sent #{count}, waiting")
@call.run_batch(@cq, write_tag, INFINITE_FUTURE,
SEND_CLOSE_FROM_CLIENT => nil)
batch_result = @call.run_batch(@cq, write_tag, INFINITE_FUTURE, batch_result = @call.run_batch(@cq, write_tag, INFINITE_FUTURE,
SEND_CLOSE_FROM_CLIENT => nil,
RECV_STATUS_ON_CLIENT => nil) RECV_STATUS_ON_CLIENT => nil)
batch_result.check_status batch_result.check_status
end end
rescue StandardError => e rescue StandardError => e
GRPC.logger.warn('bidi-write_loop: failed') GRPC.logger.warn('bidi-write-loop: failed')
GRPC.logger.warn(e) GRPC.logger.warn(e)
raise e raise e
end end
GRPC.logger.debug('bidi-write-loop: finished')
end end
end end
# starts the read loop # starts the read loop
def start_read_loop def start_read_loop
Thread.new do Thread.new do
GRPC.logger.debug('bidi-read-loop: starting')
begin begin
read_tag = Object.new read_tag = Object.new
count = 0 count = 0
# queue the initial read before beginning the loop # queue the initial read before beginning the loop
loop do loop do
GRPC.logger.debug("bidi-read_loop: #{count}") GRPC.logger.debug("bidi-read-loop: #{count}")
count += 1 count += 1
# TODO: ensure metadata is read if available, currently it's not # TODO: ensure metadata is read if available, currently it's not
batch_result = @call.run_batch(@cq, read_tag, INFINITE_FUTURE, batch_result = @call.run_batch(@cq, read_tag, INFINITE_FUTURE,
RECV_MESSAGE => nil) RECV_MESSAGE => nil)
# handle the next message # handle the next message
if batch_result.message.nil? if batch_result.message.nil?
GRPC.logger.debug("bidi-read-loop: null batch #{batch_result}")
@readq.push(END_OF_READS) @readq.push(END_OF_READS)
GRPC.logger.debug('bidi-read-loop: done reading!') GRPC.logger.debug('bidi-read-loop: done reading!')
break break
end end
# push the latest read onto the queue and continue reading # push the latest read onto the queue and continue reading
GRPC.logger.debug("received req: #{batch_result.message}")
res = @unmarshal.call(batch_result.message) res = @unmarshal.call(batch_result.message)
@readq.push(res) @readq.push(res)
end end
rescue StandardError => e rescue StandardError => e
GRPC.logger.warn('bidi: read_loop failed') GRPC.logger.warn('bidi: read-loop failed')
GRPC.logger.warn(e) GRPC.logger.warn(e)
@readq.push(e) # let each_queued_msg terminate with this error @readq.push(e) # let each_queued_msg terminate with this error
end end
GRPC.logger.debug('bidi-read-loop: finished')
end end
end end
end end

@ -137,6 +137,7 @@ module GRPC
def send_status(active_client, code, details, **kw) def send_status(active_client, code, details, **kw)
details = 'Not sure why' if details.nil? details = 'Not sure why' if details.nil?
GRPC.logger.debug("Sending status #{code}:#{details}")
active_client.send_status(code, details, code == OK, **kw) active_client.send_status(code, details, code == OK, **kw)
rescue StandardError => e rescue StandardError => e
GRPC.logger.warn("Could not send status #{code}:#{details}") GRPC.logger.warn("Could not send status #{code}:#{details}")

@ -0,0 +1,2 @@
<%namespace file="Doxyfile.include" import="gen_doxyfile"/>\
${gen_doxyfile(['grpc++'], 'C++', libs, True)}

@ -1,2 +1,2 @@
<%namespace file="Doxyfile.include" import="gen_doxyfile"/>\ <%namespace file="Doxyfile.include" import="gen_doxyfile"/>\
${gen_doxyfile(['grpc++'], 'C++', libs)} ${gen_doxyfile(['grpc++'], 'C++', libs, False)}

@ -0,0 +1,2 @@
<%namespace file="Doxyfile.include" import="gen_doxyfile"/>\
${gen_doxyfile(['grpc', 'gpr'], 'Core', libs, True)}

@ -1,2 +1,2 @@
<%namespace file="Doxyfile.include" import="gen_doxyfile"/>\ <%namespace file="Doxyfile.include" import="gen_doxyfile"/>\
${gen_doxyfile(['grpc', 'gpr'], 'Core', libs)} ${gen_doxyfile(['grpc', 'gpr'], 'Core', libs, False)}

@ -1,4 +1,11 @@
<%def name="gen_doxyfile(libnames, packagename, collection)"> ## Populates "targets" for all names in the collection "libnames" that are
## part of "collection".
##
## Note that "packagename" and "internal" while not used
## in the function itself are referenced in the template.
## When "internal" is true, documentation for non-public headers
## and sources is also taken as input to Doxygen (see INPUT).
<%def name="gen_doxyfile(libnames, packagename, collection, internal)">
<% <%
import itertools import itertools
targets = [] targets = []
@ -770,7 +777,13 @@ WARN_LOGFILE =
# spaces. # spaces.
# Note: If this tag is empty the current directory is searched. # Note: If this tag is empty the current directory is searched.
INPUT = ${' '.join(itertools.chain.from_iterable(target.public_headers for target in targets))} INPUT = ${' '.join(
itertools.chain.from_iterable(
target.public_headers +
([]
if not internal
else target.headers + target.src)
for target in targets))}
# This tag can be used to specify the character encoding of the source files # This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses

@ -520,4 +520,4 @@ class PythonPluginTest(unittest.TestCase):
if __name__ == '__main__': if __name__ == '__main__':
os.chdir(os.path.dirname(sys.argv[0])) os.chdir(os.path.dirname(sys.argv[0]))
unittest.main() unittest.main(verbosity=2)

@ -68,7 +68,8 @@ static grpc_transport_setup_result server_setup_transport(
static grpc_channel_filter const *extra_filters[] = { static grpc_channel_filter const *extra_filters[] = {
&grpc_http_server_filter}; &grpc_http_server_filter};
return grpc_server_setup_transport(a->server, transport, extra_filters, return grpc_server_setup_transport(a->server, transport, extra_filters,
GPR_ARRAY_SIZE(extra_filters), mdctx); GPR_ARRAY_SIZE(extra_filters), mdctx,
grpc_server_get_channel_args(a->server));
} }
void grpc_run_bad_client_test(const char *name, const char *client_payload, void grpc_run_bad_client_test(const char *name, const char *client_payload,

@ -0,0 +1,118 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <string.h>
#include "src/core/channel/client_channel.h"
#include "src/core/channel/connected_channel.h"
#include "src/core/channel/http_server_filter.h"
#include "src/core/surface/channel.h"
#include "src/core/surface/client.h"
#include "src/core/surface/server.h"
#include "src/core/transport/chttp2_transport.h"
#include <grpc/support/alloc.h>
#include <grpc/support/host_port.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
#include <grpc/support/thd.h>
#include <grpc/support/useful.h>
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
typedef struct fullstack_fixture_data {
char *localaddr;
} fullstack_fixture_data;
static grpc_end2end_test_fixture chttp2_create_fixture_fullstack(
grpc_channel_args *client_args, grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
int port = grpc_pick_unused_port_or_die();
fullstack_fixture_data *ffd = gpr_malloc(sizeof(fullstack_fixture_data));
memset(&f, 0, sizeof(f));
gpr_join_host_port(&ffd->localaddr, "localhost", port);
f.fixture_data = ffd;
f.client_cq = grpc_completion_queue_create();
f.server_cq = grpc_completion_queue_create();
return f;
}
void chttp2_init_client_fullstack(grpc_end2end_test_fixture *f,
grpc_channel_args *client_args) {
fullstack_fixture_data *ffd = f->fixture_data;
f->client = grpc_channel_create(ffd->localaddr, client_args);
}
void chttp2_init_server_fullstack(grpc_end2end_test_fixture *f,
grpc_channel_args *server_args) {
fullstack_fixture_data *ffd = f->fixture_data;
if (f->server) {
grpc_server_destroy(f->server);
}
f->server = grpc_server_create(server_args);
grpc_server_register_completion_queue(f->server, f->server_cq);
GPR_ASSERT(grpc_server_add_http2_port(f->server, ffd->localaddr));
grpc_server_start(f->server);
}
void chttp2_tear_down_fullstack(grpc_end2end_test_fixture *f) {
fullstack_fixture_data *ffd = f->fixture_data;
gpr_free(ffd->localaddr);
gpr_free(ffd);
}
/* All test configurations */
static grpc_end2end_test_config configs[] = {
{"chttp2/fullstack", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION,
chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
};
int main(int argc, char **argv) {
size_t i;
grpc_test_init(argc, argv);
grpc_init();
for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
grpc_end2end_tests(configs[i]);
}
grpc_shutdown();
return 0;
}

@ -0,0 +1,168 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include "src/core/channel/channel_args.h"
#include "src/core/security/credentials.h"
#include "src/core/support/env.h"
#include "src/core/support/file.h"
#include "src/core/support/string.h"
#include <grpc/support/alloc.h>
#include <grpc/support/host_port.h>
#include <grpc/support/log.h>
#include "test/core/util/test_config.h"
#include "test/core/util/port.h"
#include "test/core/end2end/data/ssl_test_data.h"
typedef struct fullstack_secure_fixture_data {
char *localaddr;
} fullstack_secure_fixture_data;
static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack(
grpc_channel_args *client_args, grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
int port = grpc_pick_unused_port_or_die();
fullstack_secure_fixture_data *ffd =
gpr_malloc(sizeof(fullstack_secure_fixture_data));
memset(&f, 0, sizeof(f));
gpr_join_host_port(&ffd->localaddr, "localhost", port);
f.fixture_data = ffd;
f.client_cq = grpc_completion_queue_create();
f.server_cq = grpc_completion_queue_create();
return f;
}
static void chttp2_init_client_secure_fullstack(grpc_end2end_test_fixture *f,
grpc_channel_args *client_args,
grpc_credentials *creds) {
fullstack_secure_fixture_data *ffd = f->fixture_data;
f->client = grpc_secure_channel_create(creds, ffd->localaddr, client_args);
GPR_ASSERT(f->client != NULL);
grpc_credentials_release(creds);
}
static void chttp2_init_server_secure_fullstack(
grpc_end2end_test_fixture *f, grpc_channel_args *server_args,
grpc_server_credentials *server_creds) {
fullstack_secure_fixture_data *ffd = f->fixture_data;
if (f->server) {
grpc_server_destroy(f->server);
}
f->server = grpc_server_create(server_args);
grpc_server_register_completion_queue(f->server, f->server_cq);
GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr,
server_creds));
grpc_server_credentials_release(server_creds);
grpc_server_start(f->server);
}
void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) {
fullstack_secure_fixture_data *ffd = f->fixture_data;
gpr_free(ffd->localaddr);
gpr_free(ffd);
}
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(NULL, NULL);
grpc_arg ssl_name_override = {GRPC_ARG_STRING,
GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
{"foo.test.google.fr"}};
grpc_channel_args *new_client_args =
grpc_channel_args_copy_and_add(client_args, &ssl_name_override);
chttp2_init_client_secure_fullstack(f, new_client_args, ssl_creds);
grpc_channel_args_destroy(new_client_args);
}
static void chttp2_init_server_simple_ssl_secure_fullstack(
grpc_end2end_test_fixture *f, grpc_channel_args *server_args) {
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);
}
/* All test configurations */
static grpc_end2end_test_config configs[] = {
{"chttp2/simple_ssl_fullstack",
FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION |
FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS,
chttp2_create_fixture_secure_fullstack,
chttp2_init_client_simple_ssl_secure_fullstack,
chttp2_init_server_simple_ssl_secure_fullstack,
chttp2_tear_down_secure_fullstack},
};
int main(int argc, char **argv) {
size_t i;
FILE *roots_file;
size_t roots_size = strlen(test_root_cert);
char *roots_filename;
grpc_platform_become_multipoller = grpc_poll_become_multipoller;
grpc_test_init(argc, argv);
/* Set the SSL roots env var. */
roots_file = gpr_tmpfile("chttp2_simple_ssl_with_poll_fullstack_test",
&roots_filename);
GPR_ASSERT(roots_filename != NULL);
GPR_ASSERT(roots_file != NULL);
GPR_ASSERT(fwrite(test_root_cert, 1, roots_size, roots_file) == roots_size);
fclose(roots_file);
gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_filename);
grpc_init();
for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
grpc_end2end_tests(configs[i]);
}
grpc_shutdown();
/* Cleanup. */
remove(roots_filename);
gpr_free(roots_filename);
return 0;
}

@ -62,7 +62,8 @@ static grpc_transport_setup_result server_setup_transport(
static grpc_channel_filter const *extra_filters[] = { static grpc_channel_filter const *extra_filters[] = {
&grpc_http_server_filter}; &grpc_http_server_filter};
return grpc_server_setup_transport(f->server, transport, extra_filters, return grpc_server_setup_transport(f->server, transport, extra_filters,
GPR_ARRAY_SIZE(extra_filters), mdctx); GPR_ARRAY_SIZE(extra_filters), mdctx,
grpc_server_get_channel_args(f->server));
} }
typedef struct { typedef struct {

@ -62,7 +62,8 @@ static grpc_transport_setup_result server_setup_transport(
static grpc_channel_filter const *extra_filters[] = { static grpc_channel_filter const *extra_filters[] = {
&grpc_http_server_filter}; &grpc_http_server_filter};
return grpc_server_setup_transport(f->server, transport, extra_filters, return grpc_server_setup_transport(f->server, transport, extra_filters,
GPR_ARRAY_SIZE(extra_filters), mdctx); GPR_ARRAY_SIZE(extra_filters), mdctx,
grpc_server_get_channel_args(f->server));
} }
typedef struct { typedef struct {

@ -63,7 +63,8 @@ static grpc_transport_setup_result server_setup_transport(
static grpc_channel_filter const *extra_filters[] = { static grpc_channel_filter const *extra_filters[] = {
&grpc_http_server_filter}; &grpc_http_server_filter};
return grpc_server_setup_transport(f->server, transport, extra_filters, return grpc_server_setup_transport(f->server, transport, extra_filters,
GPR_ARRAY_SIZE(extra_filters), mdctx); GPR_ARRAY_SIZE(extra_filters), mdctx,
grpc_server_get_channel_args(f->server));
} }
typedef struct { typedef struct {

@ -44,8 +44,10 @@ default_secure_fixture_options = FixtureOptions(True, ['windows', 'posix'])
END2END_FIXTURES = { END2END_FIXTURES = {
'chttp2_fake_security': default_secure_fixture_options, 'chttp2_fake_security': default_secure_fixture_options,
'chttp2_fullstack': default_unsecure_fixture_options, 'chttp2_fullstack': default_unsecure_fixture_options,
'chttp2_fullstack_with_poll': FixtureOptions(False, ['posix']),
'chttp2_fullstack_uds_posix': FixtureOptions(False, ['posix']), 'chttp2_fullstack_uds_posix': FixtureOptions(False, ['posix']),
'chttp2_simple_ssl_fullstack': default_secure_fixture_options, 'chttp2_simple_ssl_fullstack': default_secure_fixture_options,
'chttp2_simple_ssl_fullstack_with_poll': FixtureOptions(True, ['posix']),
'chttp2_simple_ssl_with_oauth2_fullstack': default_secure_fixture_options, 'chttp2_simple_ssl_with_oauth2_fullstack': default_secure_fixture_options,
'chttp2_socket_pair': default_unsecure_fixture_options, 'chttp2_socket_pair': default_unsecure_fixture_options,
'chttp2_socket_pair_one_byte_at_a_time': default_unsecure_fixture_options, 'chttp2_socket_pair_one_byte_at_a_time': default_unsecure_fixture_options,

@ -112,6 +112,23 @@ static void end_test(grpc_end2end_test_fixture *f) {
grpc_completion_queue_destroy(f->client_cq); grpc_completion_queue_destroy(f->client_cq);
} }
static void print_auth_context(int is_client, const grpc_auth_context *ctx) {
const grpc_auth_property *p;
grpc_auth_property_iterator it;
gpr_log(GPR_INFO, "%s peer:", is_client ? "client" : "server");
gpr_log(GPR_INFO, "\tauthenticated: %s",
grpc_auth_context_peer_is_authenticated(ctx) ? "YES" : "NO");
it = grpc_auth_context_peer_identity(ctx);
while ((p = grpc_auth_property_iterator_next(&it)) != NULL) {
gpr_log(GPR_INFO, "\t\t%s: %s", p->name, p->value);
}
gpr_log(GPR_INFO, "\tall properties:");
it = grpc_auth_context_property_iterator(ctx);
while ((p = grpc_auth_property_iterator_next(&it)) != NULL) {
gpr_log(GPR_INFO, "\t\t%s: %s", p->name, p->value);
}
}
static void test_call_creds_failure(grpc_end2end_test_config config) { static void test_call_creds_failure(grpc_end2end_test_config config) {
grpc_call *c; grpc_call *c;
grpc_credentials *creds = NULL; grpc_credentials *creds = NULL;
@ -161,6 +178,7 @@ static void request_response_with_payload_and_call_creds(
size_t details_capacity = 0; size_t details_capacity = 0;
int was_cancelled = 2; int was_cancelled = 2;
grpc_credentials *creds = NULL; grpc_credentials *creds = NULL;
const grpc_auth_context *s_auth_context = NULL;
c = grpc_channel_create_call(f.client, f.client_cq, "/foo", c = grpc_channel_create_call(f.client, f.client_cq, "/foo",
"foo.test.google.fr", deadline); "foo.test.google.fr", deadline);
@ -219,6 +237,9 @@ static void request_response_with_payload_and_call_creds(
tag(101))); tag(101)));
cq_expect_completion(v_server, tag(101), 1); cq_expect_completion(v_server, tag(101), 1);
cq_verify(v_server); cq_verify(v_server);
s_auth_context = grpc_call_auth_context(s);
GPR_ASSERT(s_auth_context != NULL);
print_auth_context(0, s_auth_context);
/* Cannot set creds on the server call object. */ /* Cannot set creds on the server call object. */
GPR_ASSERT(grpc_call_set_credentials(s, NULL) != GRPC_CALL_OK); GPR_ASSERT(grpc_call_set_credentials(s, NULL) != GRPC_CALL_OK);

@ -0,0 +1,143 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include<string.h>
#include "src/core/security/security_context.h"
#include "src/core/support/string.h"
#include "test/core/util/test_config.h"
#include <grpc/support/log.h>
static void test_empty_context(void) {
grpc_auth_context *ctx = grpc_auth_context_create(NULL, 0);
grpc_auth_property_iterator it;
gpr_log(GPR_INFO, "test_empty_context");
GPR_ASSERT(ctx != NULL);
GPR_ASSERT(grpc_auth_context_peer_identity_property_name(ctx) == NULL);
it = grpc_auth_context_peer_identity(ctx);
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL);
it = grpc_auth_context_property_iterator(ctx);
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL);
it = grpc_auth_context_find_properties_by_name(ctx, "foo");
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL);
grpc_auth_context_unref(ctx);
}
static void test_simple_context(void) {
grpc_auth_context *ctx = grpc_auth_context_create(NULL, 3);
grpc_auth_property_iterator it;
size_t i;
gpr_log(GPR_INFO, "test_simple_context");
GPR_ASSERT(ctx != NULL);
GPR_ASSERT(ctx->property_count == 3);
ctx->properties[0] = grpc_auth_property_init_from_cstring("name", "chapi");
ctx->properties[1] = grpc_auth_property_init_from_cstring("name", "chapo");
ctx->properties[2] = grpc_auth_property_init_from_cstring("foo", "bar");
ctx->peer_identity_property_name = ctx->properties[0].name;
GPR_ASSERT(
strcmp(grpc_auth_context_peer_identity_property_name(ctx), "name") == 0);
it = grpc_auth_context_property_iterator(ctx);
for (i = 0; i < ctx->property_count; i++) {
const grpc_auth_property *p = grpc_auth_property_iterator_next(&it);
GPR_ASSERT(p == &ctx->properties[i]);
}
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL);
it = grpc_auth_context_find_properties_by_name(ctx, "foo");
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == &ctx->properties[2]);
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL);
it = grpc_auth_context_peer_identity(ctx);
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == &ctx->properties[0]);
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == &ctx->properties[1]);
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL);
grpc_auth_context_unref(ctx);
}
static void test_chained_context(void) {
grpc_auth_context *chained = grpc_auth_context_create(NULL, 2);
grpc_auth_context *ctx = grpc_auth_context_create(chained, 3);
grpc_auth_property_iterator it;
size_t i;
gpr_log(GPR_INFO, "test_chained_context");
grpc_auth_context_unref(chained);
chained->properties[0] =
grpc_auth_property_init_from_cstring("name", "padapo");
chained->properties[1] = grpc_auth_property_init_from_cstring("foo", "baz");
ctx->properties[0] = grpc_auth_property_init_from_cstring("name", "chapi");
ctx->properties[1] = grpc_auth_property_init_from_cstring("name", "chapo");
ctx->properties[2] = grpc_auth_property_init_from_cstring("foo", "bar");
ctx->peer_identity_property_name = ctx->properties[0].name;
GPR_ASSERT(
strcmp(grpc_auth_context_peer_identity_property_name(ctx), "name") == 0);
it = grpc_auth_context_property_iterator(ctx);
for (i = 0; i < ctx->property_count; i++) {
const grpc_auth_property *p = grpc_auth_property_iterator_next(&it);
GPR_ASSERT(p == &ctx->properties[i]);
}
for (i = 0; i < chained->property_count; i++) {
const grpc_auth_property *p = grpc_auth_property_iterator_next(&it);
GPR_ASSERT(p == &chained->properties[i]);
}
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL);
it = grpc_auth_context_find_properties_by_name(ctx, "foo");
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == &ctx->properties[2]);
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == &chained->properties[1]);
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL);
it = grpc_auth_context_peer_identity(ctx);
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == &ctx->properties[0]);
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == &ctx->properties[1]);
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == &chained->properties[0]);
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL);
grpc_auth_context_unref(ctx);
}
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
test_empty_context();
test_simple_context();
test_chained_context();
return 0;
}

@ -135,51 +135,113 @@ static grpc_httpcli_response http_response(int status, const char *body) {
return response; return response;
} }
static void test_empty_md_store(void) {
grpc_credentials_md_store *store = grpc_credentials_md_store_create(0);
GPR_ASSERT(store->num_entries == 0);
GPR_ASSERT(store->allocated == 0);
grpc_credentials_md_store_unref(store);
}
static void test_ref_unref_empty_md_store(void) {
grpc_credentials_md_store *store = grpc_credentials_md_store_create(0);
grpc_credentials_md_store_ref(store);
grpc_credentials_md_store_ref(store);
GPR_ASSERT(store->num_entries == 0);
GPR_ASSERT(store->allocated == 0);
grpc_credentials_md_store_unref(store);
grpc_credentials_md_store_unref(store);
grpc_credentials_md_store_unref(store);
}
static void test_add_to_empty_md_store(void) {
grpc_credentials_md_store *store = grpc_credentials_md_store_create(0);
const char *key_str = "hello";
const char *value_str = "there blah blah blah blah blah blah blah";
gpr_slice key = gpr_slice_from_copied_string(key_str);
gpr_slice value = gpr_slice_from_copied_string(value_str);
grpc_credentials_md_store_add(store, key, value);
GPR_ASSERT(store->num_entries == 1);
GPR_ASSERT(gpr_slice_cmp(key, store->entries[0].key) == 0);
GPR_ASSERT(gpr_slice_cmp(value, store->entries[0].value) == 0);
gpr_slice_unref(key);
gpr_slice_unref(value);
grpc_credentials_md_store_unref(store);
}
static void test_add_cstrings_to_empty_md_store(void) {
grpc_credentials_md_store *store = grpc_credentials_md_store_create(0);
const char *key_str = "hello";
const char *value_str = "there blah blah blah blah blah blah blah";
grpc_credentials_md_store_add_cstrings(store, key_str, value_str);
GPR_ASSERT(store->num_entries == 1);
GPR_ASSERT(gpr_slice_str_cmp(store->entries[0].key, key_str) == 0);
GPR_ASSERT(gpr_slice_str_cmp(store->entries[0].value, value_str) == 0);
grpc_credentials_md_store_unref(store);
}
static void test_empty_preallocated_md_store(void) {
grpc_credentials_md_store *store = grpc_credentials_md_store_create(4);
GPR_ASSERT(store->num_entries == 0);
GPR_ASSERT(store->allocated == 4);
GPR_ASSERT(store->entries != NULL);
grpc_credentials_md_store_unref(store);
}
static void test_add_abunch_to_md_store(void) {
grpc_credentials_md_store *store = grpc_credentials_md_store_create(4);
size_t num_entries = 1000;
const char *key_str = "hello";
const char *value_str = "there blah blah blah blah blah blah blah";
size_t i;
for (i = 0; i < num_entries; i++) {
grpc_credentials_md_store_add_cstrings(store, key_str, value_str);
}
for (i = 0; i < num_entries; i++) {
GPR_ASSERT(gpr_slice_str_cmp(store->entries[i].key, key_str) == 0);
GPR_ASSERT(gpr_slice_str_cmp(store->entries[i].value, value_str) == 0);
}
grpc_credentials_md_store_unref(store);
}
static void test_oauth2_token_fetcher_creds_parsing_ok(void) { static void test_oauth2_token_fetcher_creds_parsing_ok(void) {
grpc_mdctx *ctx = grpc_mdctx_create(); grpc_credentials_md_store *token_md = NULL;
grpc_mdelem *token_elem = NULL;
gpr_timespec token_lifetime; gpr_timespec token_lifetime;
grpc_httpcli_response response = grpc_httpcli_response response =
http_response(200, valid_oauth2_json_response); http_response(200, valid_oauth2_json_response);
GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
&response, ctx, &token_elem, &token_lifetime) == &response, &token_md, &token_lifetime) ==
GRPC_CREDENTIALS_OK); GRPC_CREDENTIALS_OK);
GPR_ASSERT(token_lifetime.tv_sec == 3599); GPR_ASSERT(token_lifetime.tv_sec == 3599);
GPR_ASSERT(token_lifetime.tv_nsec == 0); GPR_ASSERT(token_lifetime.tv_nsec == 0);
GPR_ASSERT(strcmp(grpc_mdstr_as_c_string(token_elem->key), GPR_ASSERT(token_md->num_entries == 1);
"Authorization") == 0); GPR_ASSERT(gpr_slice_str_cmp(token_md->entries[0].key, "Authorization") == 0);
GPR_ASSERT(strcmp(grpc_mdstr_as_c_string(token_elem->value), GPR_ASSERT(gpr_slice_str_cmp(token_md->entries[0].value,
"Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_") == 0); "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_") ==
grpc_mdelem_unref(token_elem); 0);
grpc_mdctx_unref(ctx); grpc_credentials_md_store_unref(token_md);
} }
static void test_oauth2_token_fetcher_creds_parsing_bad_http_status(void) { static void test_oauth2_token_fetcher_creds_parsing_bad_http_status(void) {
grpc_mdctx *ctx = grpc_mdctx_create(); grpc_credentials_md_store *token_md = NULL;
grpc_mdelem *token_elem = NULL;
gpr_timespec token_lifetime; gpr_timespec token_lifetime;
grpc_httpcli_response response = grpc_httpcli_response response =
http_response(401, valid_oauth2_json_response); http_response(401, valid_oauth2_json_response);
GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
&response, ctx, &token_elem, &token_lifetime) == &response, &token_md, &token_lifetime) ==
GRPC_CREDENTIALS_ERROR); GRPC_CREDENTIALS_ERROR);
grpc_mdctx_unref(ctx);
} }
static void test_oauth2_token_fetcher_creds_parsing_empty_http_body(void) { static void test_oauth2_token_fetcher_creds_parsing_empty_http_body(void) {
grpc_mdctx *ctx = grpc_mdctx_create(); grpc_credentials_md_store *token_md = NULL;
grpc_mdelem *token_elem = NULL;
gpr_timespec token_lifetime; gpr_timespec token_lifetime;
grpc_httpcli_response response = http_response(200, ""); grpc_httpcli_response response = http_response(200, "");
GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
&response, ctx, &token_elem, &token_lifetime) == &response, &token_md, &token_lifetime) ==
GRPC_CREDENTIALS_ERROR); GRPC_CREDENTIALS_ERROR);
grpc_mdctx_unref(ctx);
} }
static void test_oauth2_token_fetcher_creds_parsing_invalid_json(void) { static void test_oauth2_token_fetcher_creds_parsing_invalid_json(void) {
grpc_mdctx *ctx = grpc_mdctx_create(); grpc_credentials_md_store *token_md = NULL;
grpc_mdelem *token_elem = NULL;
gpr_timespec token_lifetime; gpr_timespec token_lifetime;
grpc_httpcli_response response = grpc_httpcli_response response =
http_response(200, http_response(200,
@ -187,28 +249,24 @@ static void test_oauth2_token_fetcher_creds_parsing_invalid_json(void) {
" \"expires_in\":3599, " " \"expires_in\":3599, "
" \"token_type\":\"Bearer\""); " \"token_type\":\"Bearer\"");
GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
&response, ctx, &token_elem, &token_lifetime) == &response, &token_md, &token_lifetime) ==
GRPC_CREDENTIALS_ERROR); GRPC_CREDENTIALS_ERROR);
grpc_mdctx_unref(ctx);
} }
static void test_oauth2_token_fetcher_creds_parsing_missing_token(void) { static void test_oauth2_token_fetcher_creds_parsing_missing_token(void) {
grpc_mdctx *ctx = grpc_mdctx_create(); grpc_credentials_md_store *token_md = NULL;
grpc_mdelem *token_elem = NULL;
gpr_timespec token_lifetime; gpr_timespec token_lifetime;
grpc_httpcli_response response = http_response(200, grpc_httpcli_response response = http_response(200,
"{" "{"
" \"expires_in\":3599, " " \"expires_in\":3599, "
" \"token_type\":\"Bearer\"}"); " \"token_type\":\"Bearer\"}");
GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
&response, ctx, &token_elem, &token_lifetime) == &response, &token_md, &token_lifetime) ==
GRPC_CREDENTIALS_ERROR); GRPC_CREDENTIALS_ERROR);
grpc_mdctx_unref(ctx);
} }
static void test_oauth2_token_fetcher_creds_parsing_missing_token_type(void) { static void test_oauth2_token_fetcher_creds_parsing_missing_token_type(void) {
grpc_mdctx *ctx = grpc_mdctx_create(); grpc_credentials_md_store *token_md = NULL;
grpc_mdelem *token_elem = NULL;
gpr_timespec token_lifetime; gpr_timespec token_lifetime;
grpc_httpcli_response response = grpc_httpcli_response response =
http_response(200, http_response(200,
@ -216,35 +274,32 @@ static void test_oauth2_token_fetcher_creds_parsing_missing_token_type(void) {
" \"expires_in\":3599, " " \"expires_in\":3599, "
"}"); "}");
GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
&response, ctx, &token_elem, &token_lifetime) == &response, &token_md, &token_lifetime) ==
GRPC_CREDENTIALS_ERROR); GRPC_CREDENTIALS_ERROR);
grpc_mdctx_unref(ctx);
} }
static void test_oauth2_token_fetcher_creds_parsing_missing_token_lifetime( static void test_oauth2_token_fetcher_creds_parsing_missing_token_lifetime(
void) { void) {
grpc_mdctx *ctx = grpc_mdctx_create(); grpc_credentials_md_store *token_md = NULL;
grpc_mdelem *token_elem = NULL;
gpr_timespec token_lifetime; gpr_timespec token_lifetime;
grpc_httpcli_response response = grpc_httpcli_response response =
http_response(200, http_response(200,
"{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\"," "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\","
" \"token_type\":\"Bearer\"}"); " \"token_type\":\"Bearer\"}");
GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
&response, ctx, &token_elem, &token_lifetime) == &response, &token_md, &token_lifetime) ==
GRPC_CREDENTIALS_ERROR); GRPC_CREDENTIALS_ERROR);
grpc_mdctx_unref(ctx);
} }
static void check_metadata(expected_md *expected, grpc_mdelem **md_elems, static void check_metadata(expected_md *expected, grpc_credentials_md *md_elems,
size_t num_md) { size_t num_md) {
size_t i; size_t i;
for (i = 0; i < num_md; i++) { for (i = 0; i < num_md; i++) {
size_t j; size_t j;
for (j = 0; j < num_md; j++) { for (j = 0; j < num_md; j++) {
if (0 == gpr_slice_str_cmp(md_elems[j]->key->slice, expected[i].key)) { if (0 == gpr_slice_str_cmp(md_elems[j].key, expected[i].key)) {
GPR_ASSERT(0 == gpr_slice_str_cmp(md_elems[j]->value->slice, GPR_ASSERT(gpr_slice_str_cmp(md_elems[j].value, expected[i].value) ==
expected[i].value)); 0);
break; break;
} }
} }
@ -255,7 +310,7 @@ static void check_metadata(expected_md *expected, grpc_mdelem **md_elems,
} }
} }
static void check_iam_metadata(void *user_data, grpc_mdelem **md_elems, static void check_iam_metadata(void *user_data, grpc_credentials_md *md_elems,
size_t num_md, grpc_credentials_status status) { size_t num_md, grpc_credentials_status status) {
grpc_credentials *c = (grpc_credentials *)user_data; grpc_credentials *c = (grpc_credentials *)user_data;
expected_md emd[] = { expected_md emd[] = {
@ -277,7 +332,7 @@ static void test_iam_creds(void) {
} }
static void check_ssl_oauth2_composite_metadata( static void check_ssl_oauth2_composite_metadata(
void *user_data, grpc_mdelem **md_elems, size_t num_md, void *user_data, grpc_credentials_md *md_elems, size_t num_md,
grpc_credentials_status status) { grpc_credentials_status status) {
grpc_credentials *c = (grpc_credentials *)user_data; grpc_credentials *c = (grpc_credentials *)user_data;
expected_md emd[] = { expected_md emd[] = {
@ -327,7 +382,7 @@ void test_ssl_fake_transport_security_composite_creds_failure(void) {
} }
static void check_ssl_oauth2_iam_composite_metadata( static void check_ssl_oauth2_iam_composite_metadata(
void *user_data, grpc_mdelem **md_elems, size_t num_md, void *user_data, grpc_credentials_md *md_elems, size_t num_md,
grpc_credentials_status status) { grpc_credentials_status status) {
grpc_credentials *c = (grpc_credentials *)user_data; grpc_credentials *c = (grpc_credentials *)user_data;
expected_md emd[] = { expected_md emd[] = {
@ -374,20 +429,20 @@ static void test_ssl_oauth2_iam_composite_creds(void) {
} }
static void on_oauth2_creds_get_metadata_success( static void on_oauth2_creds_get_metadata_success(
void *user_data, grpc_mdelem **md_elems, size_t num_md, void *user_data, grpc_credentials_md *md_elems, size_t num_md,
grpc_credentials_status status) { grpc_credentials_status status) {
GPR_ASSERT(status == GRPC_CREDENTIALS_OK); GPR_ASSERT(status == GRPC_CREDENTIALS_OK);
GPR_ASSERT(num_md == 1); GPR_ASSERT(num_md == 1);
GPR_ASSERT(strcmp(grpc_mdstr_as_c_string(md_elems[0]->key), GPR_ASSERT(gpr_slice_str_cmp(md_elems[0].key, "Authorization") == 0);
"Authorization") == 0); GPR_ASSERT(gpr_slice_str_cmp(md_elems[0].value,
GPR_ASSERT(strcmp(grpc_mdstr_as_c_string(md_elems[0]->value), "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_") ==
"Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_") == 0); 0);
GPR_ASSERT(user_data != NULL); GPR_ASSERT(user_data != NULL);
GPR_ASSERT(strcmp((const char *)user_data, test_user_data) == 0); GPR_ASSERT(strcmp((const char *)user_data, test_user_data) == 0);
} }
static void on_oauth2_creds_get_metadata_failure( static void on_oauth2_creds_get_metadata_failure(
void *user_data, grpc_mdelem **md_elems, size_t num_md, void *user_data, grpc_credentials_md *md_elems, size_t num_md,
grpc_credentials_status status) { grpc_credentials_status status) {
GPR_ASSERT(status == GRPC_CREDENTIALS_ERROR); GPR_ASSERT(status == GRPC_CREDENTIALS_ERROR);
GPR_ASSERT(num_md == 0); GPR_ASSERT(num_md == 0);
@ -719,24 +774,22 @@ static void test_service_account_creds_signing_failure(void) {
} }
static void on_jwt_creds_get_metadata_success(void *user_data, static void on_jwt_creds_get_metadata_success(void *user_data,
grpc_mdelem **md_elems, grpc_credentials_md *md_elems,
size_t num_md, size_t num_md,
grpc_credentials_status status) { grpc_credentials_status status) {
char *expected_md_value; char *expected_md_value;
gpr_asprintf(&expected_md_value, "Bearer %s", test_signed_jwt); gpr_asprintf(&expected_md_value, "Bearer %s", test_signed_jwt);
GPR_ASSERT(status == GRPC_CREDENTIALS_OK); GPR_ASSERT(status == GRPC_CREDENTIALS_OK);
GPR_ASSERT(num_md == 1); GPR_ASSERT(num_md == 1);
GPR_ASSERT(strcmp(grpc_mdstr_as_c_string(md_elems[0]->key), GPR_ASSERT(gpr_slice_str_cmp(md_elems[0].key, "Authorization") == 0);
"Authorization") == 0); GPR_ASSERT(gpr_slice_str_cmp(md_elems[0].value, expected_md_value) == 0);
GPR_ASSERT(strcmp(grpc_mdstr_as_c_string(md_elems[0]->value),
expected_md_value) == 0);
GPR_ASSERT(user_data != NULL); GPR_ASSERT(user_data != NULL);
GPR_ASSERT(strcmp((const char *)user_data, test_user_data) == 0); GPR_ASSERT(strcmp((const char *)user_data, test_user_data) == 0);
gpr_free(expected_md_value); gpr_free(expected_md_value);
} }
static void on_jwt_creds_get_metadata_failure(void *user_data, static void on_jwt_creds_get_metadata_failure(void *user_data,
grpc_mdelem **md_elems, grpc_credentials_md *md_elems,
size_t num_md, size_t num_md,
grpc_credentials_status status) { grpc_credentials_status status) {
GPR_ASSERT(status == GRPC_CREDENTIALS_ERROR); GPR_ASSERT(status == GRPC_CREDENTIALS_ERROR);
@ -796,6 +849,12 @@ static void test_jwt_creds_signing_failure(void) {
int main(int argc, char **argv) { int main(int argc, char **argv) {
grpc_test_init(argc, argv); grpc_test_init(argc, argv);
test_empty_md_store();
test_ref_unref_empty_md_store();
test_add_to_empty_md_store();
test_add_cstrings_to_empty_md_store();
test_empty_preallocated_md_store();
test_add_abunch_to_md_store();
test_oauth2_token_fetcher_creds_parsing_ok(); test_oauth2_token_fetcher_creds_parsing_ok();
test_oauth2_token_fetcher_creds_parsing_bad_http_status(); test_oauth2_token_fetcher_creds_parsing_bad_http_status();
test_oauth2_token_fetcher_creds_parsing_empty_http_body(); test_oauth2_token_fetcher_creds_parsing_empty_http_body();

@ -35,6 +35,7 @@
#include <string.h> #include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/useful.h> #include <grpc/support/useful.h>
#include "test/core/util/test_config.h" #include "test/core/util/test_config.h"
@ -272,6 +273,27 @@ static void test_many(void) {
gpr_cmdline_destroy(cl); gpr_cmdline_destroy(cl);
} }
static void test_usage(void) {
gpr_cmdline *cl;
char *usage;
char *str = NULL;
int x = 0;
int flag = 2;
cl = gpr_cmdline_create(NULL);
gpr_cmdline_add_string(cl, "str", NULL, &str);
gpr_cmdline_add_int(cl, "x", NULL, &x);
gpr_cmdline_add_flag(cl, "flag", NULL, &flag);
usage = gpr_cmdline_usage_string(cl, "test");
GPR_ASSERT(0 == strcmp(usage,
"Usage: test [--str=string] [--x=int] [--flag|--no-flag]\n"));
gpr_free(usage);
gpr_cmdline_destroy(cl);
}
int main(int argc, char **argv) { int main(int argc, char **argv) {
grpc_test_init(argc, argv); grpc_test_init(argc, argv);
test_simple_int(); test_simple_int();
@ -289,5 +311,6 @@ int main(int argc, char **argv) {
test_flag_val_true(); test_flag_val_true();
test_flag_val_false(); test_flag_val_false();
test_many(); test_many();
test_usage();
return 0; return 0;
} }

@ -1 +1 @@
Subproject commit 8908cf16fe81f42c766fdf067b1da4554f54ed87 Subproject commit 3e2c8a5dd79481e1d36572cdf65be93514ba6581

@ -0,0 +1,38 @@
#!/bin/sh
# Copyright 2015, 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.
gen_build_json_dirs="test/core/end2end test/core/bad_client"
gen_build_files=""
for gen_build_json in $gen_build_json_dirs
do
output_file=`mktemp /tmp/genXXXXXX`
$gen_build_json/gen_build_json.py > $output_file
gen_build_files="$gen_build_files $output_file"
done

@ -38,19 +38,12 @@ fi
cd `dirname $0`/../.. cd `dirname $0`/../..
mako_renderer=tools/buildgen/mako_renderer.py mako_renderer=tools/buildgen/mako_renderer.py
gen_build_json_dirs="test/core/end2end test/core/bad_client"
if [ "x$TEST" != "x" ] ; then if [ "x$TEST" != "x" ] ; then
tools/buildgen/build-cleaner.py build.json tools/buildgen/build-cleaner.py build.json
fi fi
gen_build_files="" . tools/buildgen/generate_build_additions.sh
for gen_build_json in $gen_build_json_dirs
do
output_file=`mktemp /tmp/genXXXXXX`
$gen_build_json/gen_build_json.py > $output_file
gen_build_files="$gen_build_files $output_file"
done
global_plugins=`find ./tools/buildgen/plugins -name '*.py' | global_plugins=`find ./tools/buildgen/plugins -name '*.py' |
sort | grep -v __init__ | awk ' { printf "-p %s ", $0 } '` sort | grep -v __init__ | awk ' { printf "-p %s ", $0 } '`

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -34,7 +34,7 @@ set -ex
# change to grpc repo root # change to grpc repo root
cd $(dirname $0)/../.. cd $(dirname $0)/../..
for i in core c++ for i in core c++ core.internal c++.internal
do do
mkdir -p doc/ref/$i mkdir -p doc/ref/$i
doxygen tools/doxygen/Doxyfile.$i doxygen tools/doxygen/Doxyfile.$i

@ -234,7 +234,8 @@ class Job(object):
class Jobset(object): class Jobset(object):
"""Manages one run of jobs.""" """Manages one run of jobs."""
def __init__(self, check_cancelled, maxjobs, newline_on_success, travis, cache): def __init__(self, check_cancelled, maxjobs, newline_on_success, travis,
stop_on_failure, cache):
self._running = set() self._running = set()
self._check_cancelled = check_cancelled self._check_cancelled = check_cancelled
self._cancelled = False self._cancelled = False
@ -244,6 +245,7 @@ class Jobset(object):
self._newline_on_success = newline_on_success self._newline_on_success = newline_on_success
self._travis = travis self._travis = travis
self._cache = cache self._cache = cache
self._stop_on_failure = stop_on_failure
def start(self, spec): def start(self, spec):
"""Start a job. Return True on success, False on failure.""" """Start a job. Return True on success, False on failure."""
@ -280,8 +282,12 @@ class Jobset(object):
for job in self._running: for job in self._running:
st = job.state(self._cache) st = job.state(self._cache)
if st == _RUNNING: continue if st == _RUNNING: continue
if st == _FAILURE: self._failures += 1 if st == _FAILURE or st == _KILLED:
if st == _KILLED: self._failures += 1 self._failures += 1
if self._stop_on_failure:
self._cancelled = True
for job in self._running:
job.kill()
dead.add(job) dead.add(job)
for job in dead: for job in dead:
self._completed += 1 self._completed += 1
@ -333,10 +339,11 @@ def run(cmdlines,
maxjobs=None, maxjobs=None,
newline_on_success=False, newline_on_success=False,
travis=False, travis=False,
stop_on_failure=False,
cache=None): cache=None):
js = Jobset(check_cancelled, js = Jobset(check_cancelled,
maxjobs if maxjobs is not None else _DEFAULT_MAX_JOBS, maxjobs if maxjobs is not None else _DEFAULT_MAX_JOBS,
newline_on_success, travis, newline_on_success, travis, stop_on_failure,
cache if cache is not None else NoCache()) cache if cache is not None else NoCache())
if not travis: if not travis:
cmdlines = shuffle_iteratable(cmdlines) cmdlines = shuffle_iteratable(cmdlines)

@ -45,6 +45,6 @@ git submodule > $submodules
diff -u $submodules - << EOF diff -u $submodules - << EOF
05b155ff59114735ec8cd089f669c4c3d8f59029 third_party/gflags (v2.1.0-45-g05b155f) 05b155ff59114735ec8cd089f669c4c3d8f59029 third_party/gflags (v2.1.0-45-g05b155f)
3df69d3aefde7671053d4e3c242b228e5d79c83f third_party/openssl (OpenSSL_1_0_2a) 3df69d3aefde7671053d4e3c242b228e5d79c83f third_party/openssl (OpenSSL_1_0_2a)
8908cf16fe81f42c766fdf067b1da4554f54ed87 third_party/protobuf (v3.0.0-alpha-1-1044-g8908cf1) 3e2c8a5dd79481e1d36572cdf65be93514ba6581 third_party/protobuf (v3.0.0-alpha-1-1048-g3e2c8a5)
50893291621658f355bc5b4d450a8d06a563053d third_party/zlib (v1.2.8) 50893291621658f355bc5b4d450a8d06a563053d third_party/zlib (v1.2.8)
EOF EOF

@ -301,7 +301,8 @@ _CONFIGS = {
'msan': SimpleConfig('msan'), 'msan': SimpleConfig('msan'),
'ubsan': SimpleConfig('ubsan'), 'ubsan': SimpleConfig('ubsan'),
'asan': SimpleConfig('asan', environ={ 'asan': SimpleConfig('asan', environ={
'ASAN_OPTIONS': 'detect_leaks=1:color=always:suppressions=tools/tsan_suppressions.txt'}), 'ASAN_OPTIONS': 'detect_leaks=1:color=always:suppressions=tools/tsan_suppressions.txt',
'LSAN_OPTIONS': 'report_objects=1'}),
'asan-noleaks': SimpleConfig('asan', environ={ 'asan-noleaks': SimpleConfig('asan', environ={
'ASAN_OPTIONS': 'detect_leaks=0:color=always:suppressions=tools/tsan_suppressions.txt'}), 'ASAN_OPTIONS': 'detect_leaks=0:color=always:suppressions=tools/tsan_suppressions.txt'}),
'gcov': SimpleConfig('gcov'), 'gcov': SimpleConfig('gcov'),
@ -349,6 +350,10 @@ argp.add_argument('-l', '--language',
choices=sorted(_LANGUAGES.keys()), choices=sorted(_LANGUAGES.keys()),
nargs='+', nargs='+',
default=sorted(_LANGUAGES.keys())) default=sorted(_LANGUAGES.keys()))
argp.add_argument('-S', '--stop_on_failure',
default=False,
action='store_const',
const=True)
argp.add_argument('-a', '--antagonists', default=0, type=int) argp.add_argument('-a', '--antagonists', default=0, type=int)
args = argp.parse_args() args = argp.parse_args()
@ -454,6 +459,7 @@ def _build_and_run(check_cancelled, newline_on_success, travis, cache):
if not jobset.run(all_runs, check_cancelled, if not jobset.run(all_runs, check_cancelled,
newline_on_success=newline_on_success, travis=travis, newline_on_success=newline_on_success, travis=travis,
maxjobs=args.jobs, maxjobs=args.jobs,
stop_on_failure=args.stop_on_failure,
cache=cache): cache=cache):
return 2 return 2
finally: finally:

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -158,7 +158,7 @@
<ClInclude Include="..\..\src\core\httpcli\httpcli.h" /> <ClInclude Include="..\..\src\core\httpcli\httpcli.h" />
<ClInclude Include="..\..\src\core\httpcli\httpcli_security_connector.h" /> <ClInclude Include="..\..\src\core\httpcli\httpcli_security_connector.h" />
<ClInclude Include="..\..\src\core\httpcli\parser.h" /> <ClInclude Include="..\..\src\core\httpcli\parser.h" />
<ClInclude Include="..\..\src\core\security\auth.h" /> <ClInclude Include="..\..\src\core\security\auth_filters.h" />
<ClInclude Include="..\..\src\core\security\base64.h" /> <ClInclude Include="..\..\src\core\security\base64.h" />
<ClInclude Include="..\..\src\core\security\credentials.h" /> <ClInclude Include="..\..\src\core\security\credentials.h" />
<ClInclude Include="..\..\src\core\security\json_token.h" /> <ClInclude Include="..\..\src\core\security\json_token.h" />
@ -267,12 +267,14 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\core\httpcli\parser.c"> <ClCompile Include="..\..\src\core\httpcli\parser.c">
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\core\security\auth.c">
</ClCompile>
<ClCompile Include="..\..\src\core\security\base64.c"> <ClCompile Include="..\..\src\core\security\base64.c">
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\core\security\client_auth_filter.c">
</ClCompile>
<ClCompile Include="..\..\src\core\security\credentials.c"> <ClCompile Include="..\..\src\core\security\credentials.c">
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\core\security\credentials_metadata.c">
</ClCompile>
<ClCompile Include="..\..\src\core\security\credentials_posix.c"> <ClCompile Include="..\..\src\core\security\credentials_posix.c">
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\core\security\credentials_win32.c"> <ClCompile Include="..\..\src\core\security\credentials_win32.c">
@ -289,6 +291,8 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\core\security\security_context.c"> <ClCompile Include="..\..\src\core\security\security_context.c">
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\core\security\server_auth_filter.c">
</ClCompile>
<ClCompile Include="..\..\src\core\security\server_secure_chttp2.c"> <ClCompile Include="..\..\src\core\security\server_secure_chttp2.c">
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\core\surface\init_secure.c"> <ClCompile Include="..\..\src\core\surface\init_secure.c">

@ -13,15 +13,18 @@
<ClCompile Include="..\..\src\core\httpcli\parser.c"> <ClCompile Include="..\..\src\core\httpcli\parser.c">
<Filter>src\core\httpcli</Filter> <Filter>src\core\httpcli</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\core\security\auth.c"> <ClCompile Include="..\..\src\core\security\base64.c">
<Filter>src\core\security</Filter> <Filter>src\core\security</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\core\security\base64.c"> <ClCompile Include="..\..\src\core\security\client_auth_filter.c">
<Filter>src\core\security</Filter> <Filter>src\core\security</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\core\security\credentials.c"> <ClCompile Include="..\..\src\core\security\credentials.c">
<Filter>src\core\security</Filter> <Filter>src\core\security</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\core\security\credentials_metadata.c">
<Filter>src\core\security</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\security\credentials_posix.c"> <ClCompile Include="..\..\src\core\security\credentials_posix.c">
<Filter>src\core\security</Filter> <Filter>src\core\security</Filter>
</ClCompile> </ClCompile>
@ -46,6 +49,9 @@
<ClCompile Include="..\..\src\core\security\security_context.c"> <ClCompile Include="..\..\src\core\security\security_context.c">
<Filter>src\core\security</Filter> <Filter>src\core\security</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\core\security\server_auth_filter.c">
<Filter>src\core\security</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\security\server_secure_chttp2.c"> <ClCompile Include="..\..\src\core\security\server_secure_chttp2.c">
<Filter>src\core\security</Filter> <Filter>src\core\security</Filter>
</ClCompile> </ClCompile>
@ -386,7 +392,7 @@
<ClInclude Include="..\..\src\core\httpcli\parser.h"> <ClInclude Include="..\..\src\core\httpcli\parser.h">
<Filter>src\core\httpcli</Filter> <Filter>src\core\httpcli</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\core\security\auth.h"> <ClInclude Include="..\..\src\core\security\auth_filters.h">
<Filter>src\core\security</Filter> <Filter>src\core\security</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\core\security\base64.h"> <ClInclude Include="..\..\src\core\security\base64.h">

@ -4,7 +4,7 @@
<id>grpc.native.csharp_ext</id> <id>grpc.native.csharp_ext</id>
<version>0.9.0.0</version> <version>0.9.0.0</version>
<authors>Google Inc.</authors> <authors>Google Inc.</authors>
<owners>Jan Tattermusch</owners> <owners>grpc-packages</owners>
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl> <licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
<projectUrl>http://github.com/grpc/grpc</projectUrl> <projectUrl>http://github.com/grpc/grpc</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance> <requireLicenseAcceptance>false</requireLicenseAcceptance>

Loading…
Cancel
Save