Merge github.com:grpc/grpc into epex5

pull/11095/head
Craig Tiller 8 years ago
commit 93aedbfc6a
  1. 3
      BUILD
  2. 35
      CMakeLists.txt
  3. 39
      Makefile
  4. 1
      binding.gyp
  5. 13
      build.yaml
  6. 1
      config.m4
  7. 1
      config.w32
  8. 5
      gRPC-Core.podspec
  9. 3
      grpc.gemspec
  10. 3
      package.xml
  11. 302
      src/core/ext/census/intrusive_hash_map.c
  12. 150
      src/core/ext/census/intrusive_hash_map.h
  13. 46
      src/core/ext/census/intrusive_hash_map_internal.h
  14. 2
      src/core/lib/http/httpcli.c
  15. 4
      src/core/lib/http/httpcli_security_connector.c
  16. 19
      src/core/lib/security/transport/security_connector.c
  17. 220
      src/core/lib/security/transport/security_handshaker.c
  18. 64
      src/node/README.md
  19. 138
      src/node/index.js
  20. 254
      src/node/src/client.js
  21. 64
      src/node/src/common.js
  22. 24
      src/node/src/constants.js
  23. 63
      src/node/src/credentials.js
  24. 4
      src/node/src/grpc_extension.js
  25. 15
      src/node/src/metadata.js
  26. 9
      src/node/src/protobuf_js_5_common.js
  27. 9
      src/node/src/protobuf_js_6_common.js
  28. 445
      src/node/src/server.js
  29. 8
      src/node/test/surface_test.js
  30. 1
      src/python/grpcio/grpc_core_dependencies.py
  31. 282
      test/core/census/intrusive_hash_map_test.c
  32. 3
      tools/doxygen/Doxyfile.core.internal
  33. 22
      tools/run_tests/generated/sources_and_headers.json
  34. 22
      tools/run_tests/generated/tests.json
  35. 27
      vsprojects/buildtests_c.sln
  36. 4
      vsprojects/vcxproj/grpc/grpc.vcxproj
  37. 9
      vsprojects/vcxproj/grpc/grpc.vcxproj.filters
  38. 4
      vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
  39. 9
      vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
  40. 199
      vsprojects/vcxproj/test/census_intrusive_hash_map_test/census_intrusive_hash_map_test.vcxproj
  41. 21
      vsprojects/vcxproj/test/census_intrusive_hash_map_test/census_intrusive_hash_map_test.vcxproj.filters

@ -282,6 +282,7 @@ grpc_cc_library(
"src/core/ext/census/grpc_filter.c", "src/core/ext/census/grpc_filter.c",
"src/core/ext/census/grpc_plugin.c", "src/core/ext/census/grpc_plugin.c",
"src/core/ext/census/initialize.c", "src/core/ext/census/initialize.c",
"src/core/ext/census/intrusive_hash_map.c",
"src/core/ext/census/mlog.c", "src/core/ext/census/mlog.c",
"src/core/ext/census/operation.c", "src/core/ext/census/operation.c",
"src/core/ext/census/placeholders.c", "src/core/ext/census/placeholders.c",
@ -297,6 +298,8 @@ grpc_cc_library(
"src/core/ext/census/gen/census.pb.h", "src/core/ext/census/gen/census.pb.h",
"src/core/ext/census/gen/trace_context.pb.h", "src/core/ext/census/gen/trace_context.pb.h",
"src/core/ext/census/grpc_filter.h", "src/core/ext/census/grpc_filter.h",
"src/core/ext/census/intrusive_hash_map.h",
"src/core/ext/census/intrusive_hash_map_internal.h",
"src/core/ext/census/mlog.h", "src/core/ext/census/mlog.h",
"src/core/ext/census/resource.h", "src/core/ext/census/resource.h",
"src/core/ext/census/rpc_metric_id.h", "src/core/ext/census/rpc_metric_id.h",

@ -375,6 +375,7 @@ add_dependencies(buildtests_c bdp_estimator_test)
add_dependencies(buildtests_c bin_decoder_test) add_dependencies(buildtests_c bin_decoder_test)
add_dependencies(buildtests_c bin_encoder_test) add_dependencies(buildtests_c bin_encoder_test)
add_dependencies(buildtests_c census_context_test) add_dependencies(buildtests_c census_context_test)
add_dependencies(buildtests_c census_intrusive_hash_map_test)
add_dependencies(buildtests_c census_resource_test) add_dependencies(buildtests_c census_resource_test)
add_dependencies(buildtests_c census_trace_context_test) add_dependencies(buildtests_c census_trace_context_test)
add_dependencies(buildtests_c channel_create_test) add_dependencies(buildtests_c channel_create_test)
@ -1157,6 +1158,7 @@ add_library(grpc
src/core/ext/census/grpc_filter.c src/core/ext/census/grpc_filter.c
src/core/ext/census/grpc_plugin.c src/core/ext/census/grpc_plugin.c
src/core/ext/census/initialize.c src/core/ext/census/initialize.c
src/core/ext/census/intrusive_hash_map.c
src/core/ext/census/mlog.c src/core/ext/census/mlog.c
src/core/ext/census/operation.c src/core/ext/census/operation.c
src/core/ext/census/placeholders.c src/core/ext/census/placeholders.c
@ -2048,6 +2050,7 @@ add_library(grpc_unsecure
src/core/ext/census/grpc_filter.c src/core/ext/census/grpc_filter.c
src/core/ext/census/grpc_plugin.c src/core/ext/census/grpc_plugin.c
src/core/ext/census/initialize.c src/core/ext/census/initialize.c
src/core/ext/census/intrusive_hash_map.c
src/core/ext/census/mlog.c src/core/ext/census/mlog.c
src/core/ext/census/operation.c src/core/ext/census/operation.c
src/core/ext/census/placeholders.c src/core/ext/census/placeholders.c
@ -2659,6 +2662,7 @@ add_library(grpc++_cronet
src/core/ext/census/grpc_filter.c src/core/ext/census/grpc_filter.c
src/core/ext/census/grpc_plugin.c src/core/ext/census/grpc_plugin.c
src/core/ext/census/initialize.c src/core/ext/census/initialize.c
src/core/ext/census/intrusive_hash_map.c
src/core/ext/census/mlog.c src/core/ext/census/mlog.c
src/core/ext/census/operation.c src/core/ext/census/operation.c
src/core/ext/census/placeholders.c src/core/ext/census/placeholders.c
@ -4769,6 +4773,37 @@ target_link_libraries(census_context_test
endif (gRPC_BUILD_TESTS) endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS)
add_executable(census_intrusive_hash_map_test
test/core/census/intrusive_hash_map_test.c
)
target_include_directories(census_intrusive_hash_map_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src
PRIVATE ${BENCHMARK_ROOT_DIR}/include
PRIVATE ${ZLIB_ROOT_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
PRIVATE ${CARES_BUILD_INCLUDE_DIR}
PRIVATE ${CARES_INCLUDE_DIR}
PRIVATE ${CARES_PLATFORM_INCLUDE_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
)
target_link_libraries(census_intrusive_hash_map_test
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc
gpr_test_util
gpr
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(census_resource_test add_executable(census_resource_test
test/core/census/resource_test.c test/core/census/resource_test.c
) )

@ -967,6 +967,7 @@ bdp_estimator_test: $(BINDIR)/$(CONFIG)/bdp_estimator_test
bin_decoder_test: $(BINDIR)/$(CONFIG)/bin_decoder_test bin_decoder_test: $(BINDIR)/$(CONFIG)/bin_decoder_test
bin_encoder_test: $(BINDIR)/$(CONFIG)/bin_encoder_test bin_encoder_test: $(BINDIR)/$(CONFIG)/bin_encoder_test
census_context_test: $(BINDIR)/$(CONFIG)/census_context_test census_context_test: $(BINDIR)/$(CONFIG)/census_context_test
census_intrusive_hash_map_test: $(BINDIR)/$(CONFIG)/census_intrusive_hash_map_test
census_resource_test: $(BINDIR)/$(CONFIG)/census_resource_test census_resource_test: $(BINDIR)/$(CONFIG)/census_resource_test
census_trace_context_test: $(BINDIR)/$(CONFIG)/census_trace_context_test census_trace_context_test: $(BINDIR)/$(CONFIG)/census_trace_context_test
channel_create_test: $(BINDIR)/$(CONFIG)/channel_create_test channel_create_test: $(BINDIR)/$(CONFIG)/channel_create_test
@ -1360,6 +1361,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/bin_decoder_test \ $(BINDIR)/$(CONFIG)/bin_decoder_test \
$(BINDIR)/$(CONFIG)/bin_encoder_test \ $(BINDIR)/$(CONFIG)/bin_encoder_test \
$(BINDIR)/$(CONFIG)/census_context_test \ $(BINDIR)/$(CONFIG)/census_context_test \
$(BINDIR)/$(CONFIG)/census_intrusive_hash_map_test \
$(BINDIR)/$(CONFIG)/census_resource_test \ $(BINDIR)/$(CONFIG)/census_resource_test \
$(BINDIR)/$(CONFIG)/census_trace_context_test \ $(BINDIR)/$(CONFIG)/census_trace_context_test \
$(BINDIR)/$(CONFIG)/channel_create_test \ $(BINDIR)/$(CONFIG)/channel_create_test \
@ -1763,6 +1765,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/bin_encoder_test || ( echo test bin_encoder_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/bin_encoder_test || ( echo test bin_encoder_test failed ; exit 1 )
$(E) "[RUN] Testing census_context_test" $(E) "[RUN] Testing census_context_test"
$(Q) $(BINDIR)/$(CONFIG)/census_context_test || ( echo test census_context_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/census_context_test || ( echo test census_context_test failed ; exit 1 )
$(E) "[RUN] Testing census_intrusive_hash_map_test"
$(Q) $(BINDIR)/$(CONFIG)/census_intrusive_hash_map_test || ( echo test census_intrusive_hash_map_test failed ; exit 1 )
$(E) "[RUN] Testing census_resource_test" $(E) "[RUN] Testing census_resource_test"
$(Q) $(BINDIR)/$(CONFIG)/census_resource_test || ( echo test census_resource_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/census_resource_test || ( echo test census_resource_test failed ; exit 1 )
$(E) "[RUN] Testing census_trace_context_test" $(E) "[RUN] Testing census_trace_context_test"
@ -3134,6 +3138,7 @@ LIBGRPC_SRC = \
src/core/ext/census/grpc_filter.c \ src/core/ext/census/grpc_filter.c \
src/core/ext/census/grpc_plugin.c \ src/core/ext/census/grpc_plugin.c \
src/core/ext/census/initialize.c \ src/core/ext/census/initialize.c \
src/core/ext/census/intrusive_hash_map.c \
src/core/ext/census/mlog.c \ src/core/ext/census/mlog.c \
src/core/ext/census/operation.c \ src/core/ext/census/operation.c \
src/core/ext/census/placeholders.c \ src/core/ext/census/placeholders.c \
@ -3994,6 +3999,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/census/grpc_filter.c \ src/core/ext/census/grpc_filter.c \
src/core/ext/census/grpc_plugin.c \ src/core/ext/census/grpc_plugin.c \
src/core/ext/census/initialize.c \ src/core/ext/census/initialize.c \
src/core/ext/census/intrusive_hash_map.c \
src/core/ext/census/mlog.c \ src/core/ext/census/mlog.c \
src/core/ext/census/operation.c \ src/core/ext/census/operation.c \
src/core/ext/census/placeholders.c \ src/core/ext/census/placeholders.c \
@ -4591,6 +4597,7 @@ LIBGRPC++_CRONET_SRC = \
src/core/ext/census/grpc_filter.c \ src/core/ext/census/grpc_filter.c \
src/core/ext/census/grpc_plugin.c \ src/core/ext/census/grpc_plugin.c \
src/core/ext/census/initialize.c \ src/core/ext/census/initialize.c \
src/core/ext/census/intrusive_hash_map.c \
src/core/ext/census/mlog.c \ src/core/ext/census/mlog.c \
src/core/ext/census/operation.c \ src/core/ext/census/operation.c \
src/core/ext/census/placeholders.c \ src/core/ext/census/placeholders.c \
@ -8687,6 +8694,38 @@ endif
endif endif
CENSUS_INTRUSIVE_HASH_MAP_TEST_SRC = \
test/core/census/intrusive_hash_map_test.c \
CENSUS_INTRUSIVE_HASH_MAP_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_INTRUSIVE_HASH_MAP_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/census_intrusive_hash_map_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/census_intrusive_hash_map_test: $(CENSUS_INTRUSIVE_HASH_MAP_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(CENSUS_INTRUSIVE_HASH_MAP_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/census_intrusive_hash_map_test
endif
$(OBJDIR)/$(CONFIG)/test/core/census/intrusive_hash_map_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_census_intrusive_hash_map_test: $(CENSUS_INTRUSIVE_HASH_MAP_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(CENSUS_INTRUSIVE_HASH_MAP_TEST_OBJS:.o=.dep)
endif
endif
CENSUS_RESOURCE_TEST_SRC = \ CENSUS_RESOURCE_TEST_SRC = \
test/core/census/resource_test.c \ test/core/census/resource_test.c \

@ -890,6 +890,7 @@
'src/core/ext/census/grpc_filter.c', 'src/core/ext/census/grpc_filter.c',
'src/core/ext/census/grpc_plugin.c', 'src/core/ext/census/grpc_plugin.c',
'src/core/ext/census/initialize.c', 'src/core/ext/census/initialize.c',
'src/core/ext/census/intrusive_hash_map.c',
'src/core/ext/census/mlog.c', 'src/core/ext/census/mlog.c',
'src/core/ext/census/operation.c', 'src/core/ext/census/operation.c',
'src/core/ext/census/placeholders.c', 'src/core/ext/census/placeholders.c',

@ -27,6 +27,8 @@ filegroups:
- src/core/ext/census/gen/census.pb.h - src/core/ext/census/gen/census.pb.h
- src/core/ext/census/gen/trace_context.pb.h - src/core/ext/census/gen/trace_context.pb.h
- src/core/ext/census/grpc_filter.h - src/core/ext/census/grpc_filter.h
- src/core/ext/census/intrusive_hash_map.h
- src/core/ext/census/intrusive_hash_map_internal.h
- src/core/ext/census/mlog.h - src/core/ext/census/mlog.h
- src/core/ext/census/resource.h - src/core/ext/census/resource.h
- src/core/ext/census/rpc_metric_id.h - src/core/ext/census/rpc_metric_id.h
@ -45,6 +47,7 @@ filegroups:
- src/core/ext/census/grpc_filter.c - src/core/ext/census/grpc_filter.c
- src/core/ext/census/grpc_plugin.c - src/core/ext/census/grpc_plugin.c
- src/core/ext/census/initialize.c - src/core/ext/census/initialize.c
- src/core/ext/census/intrusive_hash_map.c
- src/core/ext/census/mlog.c - src/core/ext/census/mlog.c
- src/core/ext/census/operation.c - src/core/ext/census/operation.c
- src/core/ext/census/placeholders.c - src/core/ext/census/placeholders.c
@ -1676,6 +1679,16 @@ targets:
- grpc - grpc
- gpr_test_util - gpr_test_util
- gpr - gpr
- name: census_intrusive_hash_map_test
build: test
language: c
src:
- test/core/census/intrusive_hash_map_test.c
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
- name: census_resource_test - name: census_resource_test
build: test build: test
language: c language: c

@ -322,6 +322,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/census/grpc_filter.c \ src/core/ext/census/grpc_filter.c \
src/core/ext/census/grpc_plugin.c \ src/core/ext/census/grpc_plugin.c \
src/core/ext/census/initialize.c \ src/core/ext/census/initialize.c \
src/core/ext/census/intrusive_hash_map.c \
src/core/ext/census/mlog.c \ src/core/ext/census/mlog.c \
src/core/ext/census/operation.c \ src/core/ext/census/operation.c \
src/core/ext/census/placeholders.c \ src/core/ext/census/placeholders.c \

@ -299,6 +299,7 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\census\\grpc_filter.c " + "src\\core\\ext\\census\\grpc_filter.c " +
"src\\core\\ext\\census\\grpc_plugin.c " + "src\\core\\ext\\census\\grpc_plugin.c " +
"src\\core\\ext\\census\\initialize.c " + "src\\core\\ext\\census\\initialize.c " +
"src\\core\\ext\\census\\intrusive_hash_map.c " +
"src\\core\\ext\\census\\mlog.c " + "src\\core\\ext\\census\\mlog.c " +
"src\\core\\ext\\census\\operation.c " + "src\\core\\ext\\census\\operation.c " +
"src\\core\\ext\\census\\placeholders.c " + "src\\core\\ext\\census\\placeholders.c " +

@ -463,6 +463,8 @@ Pod::Spec.new do |s|
'src/core/ext/census/gen/census.pb.h', 'src/core/ext/census/gen/census.pb.h',
'src/core/ext/census/gen/trace_context.pb.h', 'src/core/ext/census/gen/trace_context.pb.h',
'src/core/ext/census/grpc_filter.h', 'src/core/ext/census/grpc_filter.h',
'src/core/ext/census/intrusive_hash_map.h',
'src/core/ext/census/intrusive_hash_map_internal.h',
'src/core/ext/census/mlog.h', 'src/core/ext/census/mlog.h',
'src/core/ext/census/resource.h', 'src/core/ext/census/resource.h',
'src/core/ext/census/rpc_metric_id.h', 'src/core/ext/census/rpc_metric_id.h',
@ -713,6 +715,7 @@ Pod::Spec.new do |s|
'src/core/ext/census/grpc_filter.c', 'src/core/ext/census/grpc_filter.c',
'src/core/ext/census/grpc_plugin.c', 'src/core/ext/census/grpc_plugin.c',
'src/core/ext/census/initialize.c', 'src/core/ext/census/initialize.c',
'src/core/ext/census/intrusive_hash_map.c',
'src/core/ext/census/mlog.c', 'src/core/ext/census/mlog.c',
'src/core/ext/census/operation.c', 'src/core/ext/census/operation.c',
'src/core/ext/census/placeholders.c', 'src/core/ext/census/placeholders.c',
@ -946,6 +949,8 @@ Pod::Spec.new do |s|
'src/core/ext/census/gen/census.pb.h', 'src/core/ext/census/gen/census.pb.h',
'src/core/ext/census/gen/trace_context.pb.h', 'src/core/ext/census/gen/trace_context.pb.h',
'src/core/ext/census/grpc_filter.h', 'src/core/ext/census/grpc_filter.h',
'src/core/ext/census/intrusive_hash_map.h',
'src/core/ext/census/intrusive_hash_map_internal.h',
'src/core/ext/census/mlog.h', 'src/core/ext/census/mlog.h',
'src/core/ext/census/resource.h', 'src/core/ext/census/resource.h',
'src/core/ext/census/rpc_metric_id.h', 'src/core/ext/census/rpc_metric_id.h',

@ -379,6 +379,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/census/gen/census.pb.h ) s.files += %w( src/core/ext/census/gen/census.pb.h )
s.files += %w( src/core/ext/census/gen/trace_context.pb.h ) s.files += %w( src/core/ext/census/gen/trace_context.pb.h )
s.files += %w( src/core/ext/census/grpc_filter.h ) s.files += %w( src/core/ext/census/grpc_filter.h )
s.files += %w( src/core/ext/census/intrusive_hash_map.h )
s.files += %w( src/core/ext/census/intrusive_hash_map_internal.h )
s.files += %w( src/core/ext/census/mlog.h ) s.files += %w( src/core/ext/census/mlog.h )
s.files += %w( src/core/ext/census/resource.h ) s.files += %w( src/core/ext/census/resource.h )
s.files += %w( src/core/ext/census/rpc_metric_id.h ) s.files += %w( src/core/ext/census/rpc_metric_id.h )
@ -629,6 +631,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/census/grpc_filter.c ) s.files += %w( src/core/ext/census/grpc_filter.c )
s.files += %w( src/core/ext/census/grpc_plugin.c ) s.files += %w( src/core/ext/census/grpc_plugin.c )
s.files += %w( src/core/ext/census/initialize.c ) s.files += %w( src/core/ext/census/initialize.c )
s.files += %w( src/core/ext/census/intrusive_hash_map.c )
s.files += %w( src/core/ext/census/mlog.c ) s.files += %w( src/core/ext/census/mlog.c )
s.files += %w( src/core/ext/census/operation.c ) s.files += %w( src/core/ext/census/operation.c )
s.files += %w( src/core/ext/census/placeholders.c ) s.files += %w( src/core/ext/census/placeholders.c )

@ -393,6 +393,8 @@
<file baseinstalldir="/" name="src/core/ext/census/gen/census.pb.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/census/gen/census.pb.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/gen/trace_context.pb.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/census/gen/trace_context.pb.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/grpc_filter.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/census/grpc_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/intrusive_hash_map.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/intrusive_hash_map_internal.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/mlog.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/census/mlog.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/resource.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/census/resource.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/rpc_metric_id.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/census/rpc_metric_id.h" role="src" />
@ -643,6 +645,7 @@
<file baseinstalldir="/" name="src/core/ext/census/grpc_filter.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/census/grpc_filter.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/grpc_plugin.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/census/grpc_plugin.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/initialize.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/census/initialize.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/intrusive_hash_map.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/mlog.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/census/mlog.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/operation.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/census/operation.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/placeholders.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/census/placeholders.c" role="src" />

@ -0,0 +1,302 @@
/*
* Copyright 2017 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "src/core/ext/census/intrusive_hash_map.h"
#include <string.h>
extern bool hm_index_compare(const hm_index *A, const hm_index *B);
/* Simple hashing function that takes lower 32 bits. */
static inline uint32_t chunked_vector_hasher(uint64_t key) {
return (uint32_t)key;
}
/* Vector chunks are 1MiB divided by pointer size. */
static const size_t VECTOR_CHUNK_SIZE = (1 << 20) / sizeof(void *);
/* Helper functions which return buckets from the chunked vector. */
static inline void **get_mutable_bucket(const chunked_vector *buckets,
uint32_t index) {
if (index < VECTOR_CHUNK_SIZE) {
return &buckets->first_[index];
}
size_t rest_index = (index - VECTOR_CHUNK_SIZE) / VECTOR_CHUNK_SIZE;
return &buckets->rest_[rest_index][index % VECTOR_CHUNK_SIZE];
}
static inline void *get_bucket(const chunked_vector *buckets, uint32_t index) {
if (index < VECTOR_CHUNK_SIZE) {
return buckets->first_[index];
}
size_t rest_index = (index - VECTOR_CHUNK_SIZE) / VECTOR_CHUNK_SIZE;
return buckets->rest_[rest_index][index % VECTOR_CHUNK_SIZE];
}
/* Helper function. */
static inline size_t RestSize(const chunked_vector *vec) {
return (vec->size_ <= VECTOR_CHUNK_SIZE)
? 0
: (vec->size_ - VECTOR_CHUNK_SIZE - 1) / VECTOR_CHUNK_SIZE + 1;
}
/* Initialize chunked vector to size of 0. */
static void chunked_vector_init(chunked_vector *vec) {
vec->size_ = 0;
vec->first_ = NULL;
vec->rest_ = NULL;
}
/* Clear chunked vector and free all memory that has been allocated then
initialize chunked vector. */
static void chunked_vector_clear(chunked_vector *vec) {
if (vec->first_ != NULL) {
gpr_free(vec->first_);
}
if (vec->rest_ != NULL) {
size_t rest_size = RestSize(vec);
for (size_t i = 0; i < rest_size; ++i) {
if (vec->rest_[i] != NULL) {
gpr_free(vec->rest_[i]);
}
}
gpr_free(vec->rest_);
}
chunked_vector_init(vec);
}
/* Clear chunked vector and then resize it to n entries. Allow the first 1MB to
be read w/o an extra cache miss. The rest of the elements are stored in an
array of arrays to avoid large mallocs. */
static void chunked_vector_reset(chunked_vector *vec, size_t n) {
chunked_vector_clear(vec);
vec->size_ = n;
if (n <= VECTOR_CHUNK_SIZE) {
vec->first_ = (void **)gpr_malloc(sizeof(void *) * n);
memset(vec->first_, 0, sizeof(void *) * n);
} else {
vec->first_ = (void **)gpr_malloc(sizeof(void *) * VECTOR_CHUNK_SIZE);
memset(vec->first_, 0, sizeof(void *) * VECTOR_CHUNK_SIZE);
size_t rest_size = RestSize(vec);
vec->rest_ = (void ***)gpr_malloc(sizeof(void **) * rest_size);
memset(vec->rest_, 0, sizeof(void **) * rest_size);
int i = 0;
n -= VECTOR_CHUNK_SIZE;
while (n > 0) {
size_t this_size = GPR_MIN(n, VECTOR_CHUNK_SIZE);
vec->rest_[i] = (void **)gpr_malloc(sizeof(void *) * this_size);
memset(vec->rest_[i], 0, sizeof(void *) * this_size);
n -= this_size;
++i;
}
}
}
void intrusive_hash_map_init(intrusive_hash_map *hash_map,
uint32_t initial_log2_table_size) {
hash_map->log2_num_buckets = initial_log2_table_size;
hash_map->num_items = 0;
uint32_t num_buckets = (uint32_t)1 << hash_map->log2_num_buckets;
hash_map->extend_threshold = num_buckets >> 1;
chunked_vector_init(&hash_map->buckets);
chunked_vector_reset(&hash_map->buckets, num_buckets);
hash_map->hash_mask = num_buckets - 1;
}
bool intrusive_hash_map_empty(const intrusive_hash_map *hash_map) {
return hash_map->num_items == 0;
}
size_t intrusive_hash_map_size(const intrusive_hash_map *hash_map) {
return hash_map->num_items;
}
void intrusive_hash_map_end(const intrusive_hash_map *hash_map, hm_index *idx) {
idx->bucket_index = (uint32_t)hash_map->buckets.size_;
GPR_ASSERT(idx->bucket_index <= UINT32_MAX);
idx->item = NULL;
}
void intrusive_hash_map_next(const intrusive_hash_map *hash_map,
hm_index *idx) {
idx->item = idx->item->hash_link;
while (idx->item == NULL) {
idx->bucket_index++;
if (idx->bucket_index >= hash_map->buckets.size_) {
/* Reached end of table. */
idx->item = NULL;
return;
}
idx->item = (hm_item *)get_bucket(&hash_map->buckets, idx->bucket_index);
}
}
void intrusive_hash_map_begin(const intrusive_hash_map *hash_map,
hm_index *idx) {
for (uint32_t i = 0; i < hash_map->buckets.size_; ++i) {
if (get_bucket(&hash_map->buckets, i) != NULL) {
idx->bucket_index = i;
idx->item = (hm_item *)get_bucket(&hash_map->buckets, i);
return;
}
}
intrusive_hash_map_end(hash_map, idx);
}
hm_item *intrusive_hash_map_find(const intrusive_hash_map *hash_map,
uint64_t key) {
uint32_t index = chunked_vector_hasher(key) & hash_map->hash_mask;
hm_item *p = (hm_item *)get_bucket(&hash_map->buckets, index);
while (p != NULL) {
if (key == p->key) {
return p;
}
p = p->hash_link;
}
return NULL;
}
hm_item *intrusive_hash_map_erase(intrusive_hash_map *hash_map, uint64_t key) {
uint32_t index = chunked_vector_hasher(key) & hash_map->hash_mask;
hm_item **slot = (hm_item **)get_mutable_bucket(&hash_map->buckets, index);
hm_item *p = *slot;
if (p == NULL) {
return NULL;
}
if (key == p->key) {
*slot = p->hash_link;
p->hash_link = NULL;
hash_map->num_items--;
return p;
}
hm_item *prev = p;
p = p->hash_link;
while (p) {
if (key == p->key) {
prev->hash_link = p->hash_link;
p->hash_link = NULL;
hash_map->num_items--;
return p;
}
prev = p;
p = p->hash_link;
}
return NULL;
}
/* Insert an hm_item* into the underlying chunked vector. hash_mask is
* array_size-1. Returns true if it is a new hm_item and false if the hm_item
* already existed.
*/
static inline bool intrusive_hash_map_internal_insert(chunked_vector *buckets,
uint32_t hash_mask,
hm_item *item) {
const uint64_t key = item->key;
uint32_t index = chunked_vector_hasher(key) & hash_mask;
hm_item **slot = (hm_item **)get_mutable_bucket(buckets, index);
hm_item *p = *slot;
item->hash_link = p;
/* Check to see if key already exists. */
while (p) {
if (p->key == key) {
return false;
}
p = p->hash_link;
}
/* Otherwise add new entry. */
*slot = item;
return true;
}
/* Extend the allocated number of elements in the hash map by a factor of 2. */
void intrusive_hash_map_extend(intrusive_hash_map *hash_map) {
uint32_t new_log2_num_buckets = 1 + hash_map->log2_num_buckets;
uint32_t new_num_buckets = (uint32_t)1 << new_log2_num_buckets;
GPR_ASSERT(new_num_buckets <= UINT32_MAX && new_num_buckets > 0);
chunked_vector new_buckets;
chunked_vector_init(&new_buckets);
chunked_vector_reset(&new_buckets, new_num_buckets);
uint32_t new_hash_mask = new_num_buckets - 1;
hm_index cur_idx;
hm_index end_idx;
intrusive_hash_map_end(hash_map, &end_idx);
intrusive_hash_map_begin(hash_map, &cur_idx);
while (!hm_index_compare(&cur_idx, &end_idx)) {
hm_item *new_item = cur_idx.item;
intrusive_hash_map_next(hash_map, &cur_idx);
intrusive_hash_map_internal_insert(&new_buckets, new_hash_mask, new_item);
}
/* Set values for new chunked_vector. extend_threshold is set to half of
* new_num_buckets. */
hash_map->log2_num_buckets = new_log2_num_buckets;
chunked_vector_clear(&hash_map->buckets);
hash_map->buckets = new_buckets;
hash_map->hash_mask = new_hash_mask;
hash_map->extend_threshold = new_num_buckets >> 1;
}
/* Insert a hm_item. The hm_item must remain live until it is removed from the
table. This object does not take the ownership of hm_item. The caller must
remove this hm_item from the table and delete it before this table is
deleted. If hm_item exists already num_items is not changed. */
bool intrusive_hash_map_insert(intrusive_hash_map *hash_map, hm_item *item) {
if (hash_map->num_items >= hash_map->extend_threshold) {
intrusive_hash_map_extend(hash_map);
}
if (intrusive_hash_map_internal_insert(&hash_map->buckets,
hash_map->hash_mask, item)) {
hash_map->num_items++;
return true;
}
return false;
}
void intrusive_hash_map_clear(intrusive_hash_map *hash_map,
void (*free_object)(void *)) {
hm_index cur;
hm_index end;
intrusive_hash_map_end(hash_map, &end);
intrusive_hash_map_begin(hash_map, &cur);
while (!hm_index_compare(&cur, &end)) {
hm_index next = cur;
intrusive_hash_map_next(hash_map, &next);
if (cur.item != NULL) {
hm_item *item = intrusive_hash_map_erase(hash_map, cur.item->key);
(*free_object)((void *)item);
gpr_free(item);
}
cur = next;
}
}
void intrusive_hash_map_free(intrusive_hash_map *hash_map,
void (*free_object)(void *)) {
intrusive_hash_map_clear(hash_map, (*free_object));
hash_map->num_items = 0;
hash_map->extend_threshold = 0;
hash_map->log2_num_buckets = 0;
hash_map->hash_mask = 0;
chunked_vector_clear(&hash_map->buckets);
}

@ -0,0 +1,150 @@
/*
* Copyright 2017 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_H
#define GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_H
#include "src/core/ext/census/intrusive_hash_map_internal.h"
/* intrusive_hash_map is a fast chained hash table. This hash map is faster than
* a dense hash map when the application calls insert and erase more often than
* find. When the workload is dominated by find() a dense hash map may be
* faster.
*
* intrusive_hash_map uses an intrusive header placed within a user defined
* struct. The header field IHM_key MUST be set to a valid value before
* insertion into the hash map or undefined behavior may occur. The header field
* IHM_hash_link MUST to be set to NULL initially.
*
* EXAMPLE USAGE:
*
* typedef struct string_item {
* INTRUSIVE_HASH_MAP_HEADER;
* // User data.
* char *str_buf;
* uint16_t len;
* } string_item;
*
* static string_item *make_string_item(uint64_t key, const char *buf,
* uint16_t len) {
* string_item *item = (string_item *)gpr_malloc(sizeof(string_item));
* item->IHM_key = key;
* item->IHM_hash_link = NULL;
* item->len = len;
* item->str_buf = (char *)malloc(len);
* memcpy(item->str_buf, buf, len);
* return item;
* }
*
* intrusive_hash_map hash_map;
* intrusive_hash_map_init(&hash_map, 4);
* string_item *new_item1 = make_string_item(10, "test1", 5);
* bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)new_item1);
*
* string_item *item1 =
* (string_item *)intrusive_hash_map_find(&hash_map, 10);
*/
/* Hash map item. Stores key and a pointer to the actual object. A user defined
* version of this can be passed in provided the first 2 entries (key and
* hash_link) are the same. These entries must be first in the user defined
* struct. Pointer to struct will need to be cast as (hm_item *) when passed to
* hash map. This allows it to be intrusive. */
typedef struct hm_item {
uint64_t key;
struct hm_item *hash_link;
/* Optional user defined data after this. */
} hm_item;
/* Macro provided for ease of use. This must be first in the user defined
* struct (i.e. uint64_t key and hm_item * must be the first two elements in
* that order). */
#define INTRUSIVE_HASH_MAP_HEADER \
uint64_t IHM_key; \
struct hm_item *IHM_hash_link
/* Index struct which acts as a pseudo-iterator within the hash map. */
typedef struct hm_index {
uint32_t bucket_index; // hash map bucket index.
hm_item *item; // Pointer to hm_item within the hash map.
} hm_index;
/* Returns true if two hm_indices point to the same object within the hash map
* and false otherwise. */
inline bool hm_index_compare(const hm_index *A, const hm_index *B) {
return (A->item == B->item && A->bucket_index == B->bucket_index);
}
/*
* Helper functions for iterating over the hash map.
*/
/* On return idx will contain an invalid index which is always equal to
* hash_map->buckets.size_ */
void intrusive_hash_map_end(const intrusive_hash_map *hash_map, hm_index *idx);
/* Iterates index to the next valid entry in the hash map and stores the
* index within idx. If end of table is reached, idx will contain the same
* values as if intrusive_hash_map_end() was called. */
void intrusive_hash_map_next(const intrusive_hash_map *hash_map, hm_index *idx);
/* On return, idx will contain the index of the first non-null entry in the hash
* map. If the hash map is empty, idx will contain the same values as if
* intrusive_hash_map_end() was called. */
void intrusive_hash_map_begin(const intrusive_hash_map *hash_map,
hm_index *idx);
/* Initialize intrusive hash map data structure. This must be called before
* the hash map can be used. The initial size of an intrusive hash map will be
* 2^initial_log2_map_size (valid range is [0, 31]). */
void intrusive_hash_map_init(intrusive_hash_map *hash_map,
uint32_t initial_log2_map_size);
/* Returns true if the hash map is empty and false otherwise. */
bool intrusive_hash_map_empty(const intrusive_hash_map *hash_map);
/* Returns the number of elements currently in the hash map. */
size_t intrusive_hash_map_size(const intrusive_hash_map *hash_map);
/* Find a hm_item within the hash map by key. Returns NULL if item was not
* found. */
hm_item *intrusive_hash_map_find(const intrusive_hash_map *hash_map,
uint64_t key);
/* Erase the hm_item that corresponds with key. If the hm_item is found, return
* the pointer to the hm_item. Else returns NULL. */
hm_item *intrusive_hash_map_erase(intrusive_hash_map *hash_map, uint64_t key);
/* Attempts to insert a new hm_item into the hash map. If an element with the
* same key already exists, it will not insert the new item and return false.
* Otherwise, it will insert the new item and return true. */
bool intrusive_hash_map_insert(intrusive_hash_map *hash_map, hm_item *item);
/* Clears entire contents of the hash map, but leaves internal data structure
* untouched. Second argument takes a function pointer to a function that will
* free the object designated by the user and pointed to by hash_map->value. */
void intrusive_hash_map_clear(intrusive_hash_map *hash_map,
void (*free_object)(void *));
/* Erase all contents of hash map and free the memory. Hash map is invalid
* after calling this function and cannot be used until it has been
* reinitialized (intrusive_hash_map_init()). This function takes a function
* pointer to a function that will free the object designated by the user and
* pointed to by hash_map->value. */
void intrusive_hash_map_free(intrusive_hash_map *hash_map,
void (*free_object)(void *));
#endif // GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_H

@ -0,0 +1,46 @@
/*
* Copyright 2017 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_INTERNAL_H
#define GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_INTERNAL_H
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/useful.h>
#include <stdbool.h>
/* The chunked vector is a data structure that allocates buckets for use in the
* hash map. ChunkedVector is logically equivalent to T*[N] (cast void* as
* T*). It's internally implemented as an array of 1MB arrays to avoid
* allocating large consecutive memory chunks. This is an internal data
* structure that should never be accessed directly. */
typedef struct chunked_vector {
size_t size_;
void **first_;
void ***rest_;
} chunked_vector;
/* Core intrusive hash map data structure. All internal elements are managed by
* functions and should not be altered manually. */
typedef struct intrusive_hash_map {
uint32_t num_items;
uint32_t extend_threshold;
uint32_t log2_num_buckets;
uint32_t hash_mask;
chunked_vector buckets;
} intrusive_hash_map;
#endif // GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_INTERNAL_H

@ -245,7 +245,7 @@ static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req,
static void on_resolved(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { static void on_resolved(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
internal_request *req = arg; internal_request *req = arg;
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
finish(exec_ctx, req, error); finish(exec_ctx, req, GRPC_ERROR_REF(error));
return; return;
} }
req->next_address = 0; req->next_address = 0;

@ -44,6 +44,7 @@
#include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
#include "src/core/tsi/ssl_transport_security.h" #include "src/core/tsi/ssl_transport_security.h"
#include "src/core/tsi/transport_security_adapter.h"
typedef struct { typedef struct {
grpc_channel_security_connector base; grpc_channel_security_connector base;
@ -78,7 +79,8 @@ static void httpcli_ssl_add_handshakers(grpc_exec_ctx *exec_ctx,
} }
grpc_handshake_manager_add( grpc_handshake_manager_add(
handshake_mgr, handshake_mgr,
grpc_security_handshaker_create(exec_ctx, handshaker, &sc->base)); grpc_security_handshaker_create(
exec_ctx, tsi_create_adapter_handshaker(handshaker), &sc->base));
} }
static void httpcli_ssl_check_peer(grpc_exec_ctx *exec_ctx, static void httpcli_ssl_check_peer(grpc_exec_ctx *exec_ctx,

@ -56,6 +56,7 @@
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
#include "src/core/tsi/fake_transport_security.h" #include "src/core/tsi/fake_transport_security.h"
#include "src/core/tsi/ssl_transport_security.h" #include "src/core/tsi/ssl_transport_security.h"
#include "src/core/tsi/transport_security_adapter.h"
/* -- Constants. -- */ /* -- Constants. -- */
@ -390,7 +391,8 @@ static void fake_channel_add_handshakers(
grpc_handshake_manager_add( grpc_handshake_manager_add(
handshake_mgr, handshake_mgr,
grpc_security_handshaker_create( grpc_security_handshaker_create(
exec_ctx, tsi_create_fake_handshaker(true /* is_client */), exec_ctx, tsi_create_adapter_handshaker(
tsi_create_fake_handshaker(true /* is_client */)),
&sc->base)); &sc->base));
} }
@ -400,7 +402,8 @@ static void fake_server_add_handshakers(grpc_exec_ctx *exec_ctx,
grpc_handshake_manager_add( grpc_handshake_manager_add(
handshake_mgr, handshake_mgr,
grpc_security_handshaker_create( grpc_security_handshaker_create(
exec_ctx, tsi_create_fake_handshaker(false /* is_client */), exec_ctx, tsi_create_adapter_handshaker(
tsi_create_fake_handshaker(false /* is_client */)),
&sc->base)); &sc->base));
} }
@ -495,8 +498,10 @@ static void ssl_channel_add_handshakers(grpc_exec_ctx *exec_ctx,
} }
// Create handshakers. // Create handshakers.
grpc_handshake_manager_add(handshake_mgr, grpc_security_handshaker_create( grpc_handshake_manager_add(
exec_ctx, tsi_hs, &sc->base)); handshake_mgr,
grpc_security_handshaker_create(
exec_ctx, tsi_create_adapter_handshaker(tsi_hs), &sc->base));
} }
static void ssl_server_add_handshakers(grpc_exec_ctx *exec_ctx, static void ssl_server_add_handshakers(grpc_exec_ctx *exec_ctx,
@ -515,8 +520,10 @@ static void ssl_server_add_handshakers(grpc_exec_ctx *exec_ctx,
} }
// Create handshakers. // Create handshakers.
grpc_handshake_manager_add(handshake_mgr, grpc_security_handshaker_create( grpc_handshake_manager_add(
exec_ctx, tsi_hs, &sc->base)); handshake_mgr,
grpc_security_handshaker_create(
exec_ctx, tsi_create_adapter_handshaker(tsi_hs), &sc->base));
} }
static int ssl_host_matches_name(const tsi_peer *peer, const char *peer_name) { static int ssl_host_matches_name(const tsi_peer *peer, const char *peer_name) {

@ -71,12 +71,12 @@ typedef struct {
unsigned char *handshake_buffer; unsigned char *handshake_buffer;
size_t handshake_buffer_size; size_t handshake_buffer_size;
grpc_slice_buffer left_overs;
grpc_slice_buffer outgoing; grpc_slice_buffer outgoing;
grpc_closure on_handshake_data_sent_to_peer; grpc_closure on_handshake_data_sent_to_peer;
grpc_closure on_handshake_data_received_from_peer; grpc_closure on_handshake_data_received_from_peer;
grpc_closure on_peer_checked; grpc_closure on_peer_checked;
grpc_auth_context *auth_context; grpc_auth_context *auth_context;
tsi_handshaker_result *handshaker_result;
} security_handshaker; } security_handshaker;
static void security_handshaker_unref(grpc_exec_ctx *exec_ctx, static void security_handshaker_unref(grpc_exec_ctx *exec_ctx,
@ -84,6 +84,7 @@ static void security_handshaker_unref(grpc_exec_ctx *exec_ctx,
if (gpr_unref(&h->refs)) { if (gpr_unref(&h->refs)) {
gpr_mu_destroy(&h->mu); gpr_mu_destroy(&h->mu);
tsi_handshaker_destroy(h->handshaker); tsi_handshaker_destroy(h->handshaker);
tsi_handshaker_result_destroy(h->handshaker_result);
if (h->endpoint_to_destroy != NULL) { if (h->endpoint_to_destroy != NULL) {
grpc_endpoint_destroy(exec_ctx, h->endpoint_to_destroy); grpc_endpoint_destroy(exec_ctx, h->endpoint_to_destroy);
} }
@ -92,7 +93,6 @@ static void security_handshaker_unref(grpc_exec_ctx *exec_ctx,
gpr_free(h->read_buffer_to_destroy); gpr_free(h->read_buffer_to_destroy);
} }
gpr_free(h->handshake_buffer); gpr_free(h->handshake_buffer);
grpc_slice_buffer_destroy_internal(exec_ctx, &h->left_overs);
grpc_slice_buffer_destroy_internal(exec_ctx, &h->outgoing); grpc_slice_buffer_destroy_internal(exec_ctx, &h->outgoing);
GRPC_AUTH_CONTEXT_UNREF(h->auth_context, "handshake"); GRPC_AUTH_CONTEXT_UNREF(h->auth_context, "handshake");
GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, h->connector, "handshake"); GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, h->connector, "handshake");
@ -150,10 +150,10 @@ static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *arg,
security_handshake_failed_locked(exec_ctx, h, GRPC_ERROR_REF(error)); security_handshake_failed_locked(exec_ctx, h, GRPC_ERROR_REF(error));
goto done; goto done;
} }
// Get frame protector. // Create frame protector.
tsi_frame_protector *protector; tsi_frame_protector *protector;
tsi_result result = tsi_result result = tsi_handshaker_result_create_frame_protector(
tsi_handshaker_create_frame_protector(h->handshaker, NULL, &protector); h->handshaker_result, NULL, &protector);
if (result != TSI_OK) { if (result != TSI_OK) {
error = grpc_set_tsi_error_result( error = grpc_set_tsi_error_result(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Frame protector creation failed"), GRPC_ERROR_CREATE_FROM_STATIC_STRING("Frame protector creation failed"),
@ -161,14 +161,25 @@ static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *arg,
security_handshake_failed_locked(exec_ctx, h, error); security_handshake_failed_locked(exec_ctx, h, error);
goto done; goto done;
} }
// Success. // Get unused bytes.
unsigned char *unused_bytes = NULL;
size_t unused_bytes_size = 0;
result = tsi_handshaker_result_get_unused_bytes(
h->handshaker_result, &unused_bytes, &unused_bytes_size);
// Create secure endpoint. // Create secure endpoint.
h->args->endpoint = grpc_secure_endpoint_create( if (unused_bytes_size > 0) {
protector, h->args->endpoint, h->left_overs.slices, h->left_overs.count); grpc_slice slice =
h->left_overs.count = 0; grpc_slice_from_copied_buffer((char *)unused_bytes, unused_bytes_size);
h->left_overs.length = 0; h->args->endpoint =
// Clear out the read buffer before it gets passed to the transport, grpc_secure_endpoint_create(protector, h->args->endpoint, &slice, 1);
// since any excess bytes were already copied to h->left_overs. grpc_slice_unref_internal(exec_ctx, slice);
} else {
h->args->endpoint =
grpc_secure_endpoint_create(protector, h->args->endpoint, NULL, 0);
}
tsi_handshaker_result_destroy(h->handshaker_result);
h->handshaker_result = NULL;
// Clear out the read buffer before it gets passed to the transport.
grpc_slice_buffer_reset_and_unref_internal(exec_ctx, h->args->read_buffer); grpc_slice_buffer_reset_and_unref_internal(exec_ctx, h->args->read_buffer);
// Add auth context to channel args. // Add auth context to channel args.
grpc_arg auth_context_arg = grpc_auth_context_to_arg(h->auth_context); grpc_arg auth_context_arg = grpc_auth_context_to_arg(h->auth_context);
@ -189,7 +200,8 @@ done:
static grpc_error *check_peer_locked(grpc_exec_ctx *exec_ctx, static grpc_error *check_peer_locked(grpc_exec_ctx *exec_ctx,
security_handshaker *h) { security_handshaker *h) {
tsi_peer peer; tsi_peer peer;
tsi_result result = tsi_handshaker_extract_peer(h->handshaker, &peer); tsi_result result =
tsi_handshaker_result_extract_peer(h->handshaker_result, &peer);
if (result != TSI_OK) { if (result != TSI_OK) {
return grpc_set_tsi_error_result( return grpc_set_tsi_error_result(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Peer extraction failed"), result); GRPC_ERROR_CREATE_FROM_STATIC_STRING("Peer extraction failed"), result);
@ -199,34 +211,87 @@ static grpc_error *check_peer_locked(grpc_exec_ctx *exec_ctx,
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
static grpc_error *send_handshake_bytes_to_peer_locked(grpc_exec_ctx *exec_ctx, static grpc_error *on_handshake_next_done_locked(
security_handshaker *h) { grpc_exec_ctx *exec_ctx, security_handshaker *h, tsi_result result,
// Get data to send. const unsigned char *bytes_to_send, size_t bytes_to_send_size,
tsi_result result = TSI_OK; tsi_handshaker_result *handshaker_result) {
size_t offset = 0; grpc_error *error = GRPC_ERROR_NONE;
do { // Read more if we need to.
size_t to_send_size = h->handshake_buffer_size - offset; if (result == TSI_INCOMPLETE_DATA) {
result = tsi_handshaker_get_bytes_to_send_to_peer( GPR_ASSERT(bytes_to_send_size == 0);
h->handshaker, h->handshake_buffer + offset, &to_send_size); grpc_endpoint_read(exec_ctx, h->args->endpoint, h->args->read_buffer,
offset += to_send_size; &h->on_handshake_data_received_from_peer);
if (result == TSI_INCOMPLETE_DATA) { return error;
h->handshake_buffer_size *= 2; }
h->handshake_buffer =
gpr_realloc(h->handshake_buffer, h->handshake_buffer_size);
}
} while (result == TSI_INCOMPLETE_DATA);
if (result != TSI_OK) { if (result != TSI_OK) {
return grpc_set_tsi_error_result( return grpc_set_tsi_error_result(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshake failed"), result); GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshake failed"), result);
} }
// Send data. // Update handshaker result.
grpc_slice to_send = if (handshaker_result != NULL) {
grpc_slice_from_copied_buffer((const char *)h->handshake_buffer, offset); GPR_ASSERT(h->handshaker_result == NULL);
grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &h->outgoing); h->handshaker_result = handshaker_result;
grpc_slice_buffer_add(&h->outgoing, to_send); }
grpc_endpoint_write(exec_ctx, h->args->endpoint, &h->outgoing, if (bytes_to_send_size > 0) {
&h->on_handshake_data_sent_to_peer); // Send data to peer, if needed.
return GRPC_ERROR_NONE; grpc_slice to_send = grpc_slice_from_copied_buffer(
(const char *)bytes_to_send, bytes_to_send_size);
grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &h->outgoing);
grpc_slice_buffer_add(&h->outgoing, to_send);
grpc_endpoint_write(exec_ctx, h->args->endpoint, &h->outgoing,
&h->on_handshake_data_sent_to_peer);
} else if (handshaker_result == NULL) {
// There is nothing to send, but need to read from peer.
grpc_endpoint_read(exec_ctx, h->args->endpoint, h->args->read_buffer,
&h->on_handshake_data_received_from_peer);
} else {
// Handshake has finished, check peer and so on.
error = check_peer_locked(exec_ctx, h);
}
return error;
}
static void on_handshake_next_done_grpc_wrapper(
tsi_result result, void *user_data, const unsigned char *bytes_to_send,
size_t bytes_to_send_size, tsi_handshaker_result *handshaker_result) {
security_handshaker *h = user_data;
// This callback will be invoked by TSI in a non-grpc thread, so it's
// safe to create our own exec_ctx here.
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
gpr_mu_lock(&h->mu);
grpc_error *error =
on_handshake_next_done_locked(&exec_ctx, h, result, bytes_to_send,
bytes_to_send_size, handshaker_result);
if (error != GRPC_ERROR_NONE) {
security_handshake_failed_locked(&exec_ctx, h, error);
gpr_mu_unlock(&h->mu);
security_handshaker_unref(&exec_ctx, h);
} else {
gpr_mu_unlock(&h->mu);
}
grpc_exec_ctx_finish(&exec_ctx);
}
static grpc_error *do_handshaker_next_locked(
grpc_exec_ctx *exec_ctx, security_handshaker *h,
const unsigned char *bytes_received, size_t bytes_received_size) {
// Invoke TSI handshaker.
unsigned char *bytes_to_send = NULL;
size_t bytes_to_send_size = 0;
tsi_handshaker_result *handshaker_result = NULL;
tsi_result result = tsi_handshaker_next(
h->handshaker, bytes_received, bytes_received_size, &bytes_to_send,
&bytes_to_send_size, &handshaker_result,
&on_handshake_next_done_grpc_wrapper, h);
if (result == TSI_ASYNC) {
// Handshaker operating asynchronously. Nothing else to do here;
// callback will be invoked in a TSI thread.
return GRPC_ERROR_NONE;
}
// Handshaker returned synchronously. Invoke callback directly in
// this thread with our existing exec_ctx.
return on_handshake_next_done_locked(exec_ctx, h, result, bytes_to_send,
bytes_to_send_size, handshaker_result);
} }
static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx, static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
@ -241,72 +306,34 @@ static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
security_handshaker_unref(exec_ctx, h); security_handshaker_unref(exec_ctx, h);
return; return;
} }
// Process received data. // Copy all slices received.
tsi_result result = TSI_OK;
size_t consumed_slice_size = 0;
size_t i; size_t i;
size_t bytes_received_size = 0;
for (i = 0; i < h->args->read_buffer->count; i++) { for (i = 0; i < h->args->read_buffer->count; i++) {
consumed_slice_size = GRPC_SLICE_LENGTH(h->args->read_buffer->slices[i]); bytes_received_size += GRPC_SLICE_LENGTH(h->args->read_buffer->slices[i]);
result = tsi_handshaker_process_bytes_from_peer(
h->handshaker, GRPC_SLICE_START_PTR(h->args->read_buffer->slices[i]),
&consumed_slice_size);
if (!tsi_handshaker_is_in_progress(h->handshaker)) break;
} }
if (tsi_handshaker_is_in_progress(h->handshaker)) { if (bytes_received_size > h->handshake_buffer_size) {
/* We may need more data. */ h->handshake_buffer = gpr_realloc(h->handshake_buffer, bytes_received_size);
if (result == TSI_INCOMPLETE_DATA) { h->handshake_buffer_size = bytes_received_size;
grpc_endpoint_read(exec_ctx, h->args->endpoint, h->args->read_buffer,
&h->on_handshake_data_received_from_peer);
goto done;
} else {
error = send_handshake_bytes_to_peer_locked(exec_ctx, h);
if (error != GRPC_ERROR_NONE) {
security_handshake_failed_locked(exec_ctx, h, error);
gpr_mu_unlock(&h->mu);
security_handshaker_unref(exec_ctx, h);
return;
}
goto done;
}
} }
if (result != TSI_OK) { size_t offset = 0;
security_handshake_failed_locked( for (i = 0; i < h->args->read_buffer->count; i++) {
exec_ctx, h, size_t slice_size = GPR_SLICE_LENGTH(h->args->read_buffer->slices[i]);
grpc_set_tsi_error_result( memcpy(h->handshake_buffer + offset,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshake failed"), result)); GRPC_SLICE_START_PTR(h->args->read_buffer->slices[i]), slice_size);
gpr_mu_unlock(&h->mu); offset += slice_size;
security_handshaker_unref(exec_ctx, h);
return;
}
/* Handshake is done and successful this point. */
bool has_left_overs_in_current_slice =
(consumed_slice_size <
GRPC_SLICE_LENGTH(h->args->read_buffer->slices[i]));
size_t num_left_overs = (has_left_overs_in_current_slice ? 1 : 0) +
h->args->read_buffer->count - i - 1;
if (num_left_overs > 0) {
/* Put the leftovers in our buffer (ownership transfered). */
if (has_left_overs_in_current_slice) {
grpc_slice tail = grpc_slice_split_tail(&h->args->read_buffer->slices[i],
consumed_slice_size);
grpc_slice_buffer_add(&h->left_overs, tail);
/* split_tail above increments refcount. */
grpc_slice_unref_internal(exec_ctx, tail);
}
grpc_slice_buffer_addn(
&h->left_overs, &h->args->read_buffer->slices[i + 1],
num_left_overs - (size_t)has_left_overs_in_current_slice);
} }
// Check peer. // Call TSI handshaker.
error = check_peer_locked(exec_ctx, h); error = do_handshaker_next_locked(exec_ctx, h, h->handshake_buffer,
bytes_received_size);
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
security_handshake_failed_locked(exec_ctx, h, error); security_handshake_failed_locked(exec_ctx, h, error);
gpr_mu_unlock(&h->mu); gpr_mu_unlock(&h->mu);
security_handshaker_unref(exec_ctx, h); security_handshaker_unref(exec_ctx, h);
return; } else {
gpr_mu_unlock(&h->mu);
} }
done:
gpr_mu_unlock(&h->mu);
} }
static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *arg, static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *arg,
@ -321,8 +348,8 @@ static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *arg,
security_handshaker_unref(exec_ctx, h); security_handshaker_unref(exec_ctx, h);
return; return;
} }
/* We may be done. */ // We may be done.
if (tsi_handshaker_is_in_progress(h->handshaker)) { if (h->handshaker_result == NULL) {
grpc_endpoint_read(exec_ctx, h->args->endpoint, h->args->read_buffer, grpc_endpoint_read(exec_ctx, h->args->endpoint, h->args->read_buffer,
&h->on_handshake_data_received_from_peer); &h->on_handshake_data_received_from_peer);
} else { } else {
@ -371,7 +398,7 @@ static void security_handshaker_do_handshake(grpc_exec_ctx *exec_ctx,
h->args = args; h->args = args;
h->on_handshake_done = on_handshake_done; h->on_handshake_done = on_handshake_done;
gpr_ref(&h->refs); gpr_ref(&h->refs);
grpc_error *error = send_handshake_bytes_to_peer_locked(exec_ctx, h); grpc_error *error = do_handshaker_next_locked(exec_ctx, h, NULL, 0);
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
security_handshake_failed_locked(exec_ctx, h, error); security_handshake_failed_locked(exec_ctx, h, error);
gpr_mu_unlock(&h->mu); gpr_mu_unlock(&h->mu);
@ -404,7 +431,6 @@ static grpc_handshaker *security_handshaker_create(
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
grpc_closure_init(&h->on_peer_checked, on_peer_checked, h, grpc_closure_init(&h->on_peer_checked, on_peer_checked, h,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
grpc_slice_buffer_init(&h->left_overs);
grpc_slice_buffer_init(&h->outgoing); grpc_slice_buffer_init(&h->outgoing);
return &h->base; return &h->base;
} }

@ -2,9 +2,9 @@
# Node.js gRPC Library # Node.js gRPC Library
## PREREQUISITES ## PREREQUISITES
- `node`: This requires `node` to be installed, version `0.12` or above. If you instead have the `nodejs` executable on Debian, you should install the [`nodejs-legacy`](https://packages.debian.org/sid/nodejs-legacy) package. - `node`: This requires `node` to be installed, version `4.0` or above. If you instead have the `nodejs` executable on Debian, you should install the [`nodejs-legacy`](https://packages.debian.org/sid/nodejs-legacy) package.
- **Note:** If you installed `node` via a package manager and the version is still less than `0.12`, try directly installing it from [nodejs.org](https://nodejs.org). - **Note:** If you installed `node` via a package manager and the version is still less than `4.0`, try directly installing it from [nodejs.org](https://nodejs.org).
## INSTALLATION ## INSTALLATION
@ -16,7 +16,7 @@ npm install grpc
## BUILD FROM SOURCE ## BUILD FROM SOURCE
1. Clone [the grpc Git Repository](https://github.com/grpc/grpc). 1. Clone [the grpc Git Repository](https://github.com/grpc/grpc).
2. Run `npm install` from the repository root. 2. Run `npm install --build-from-source` from the repository root.
- **Note:** On Windows, this might fail due to [nodejs issue #4932](https://github.com/nodejs/node/issues/4932) in which case, you will see something like the following in `npm install`'s output (towards the very beginning): - **Note:** On Windows, this might fail due to [nodejs issue #4932](https://github.com/nodejs/node/issues/4932) in which case, you will see something like the following in `npm install`'s output (towards the very beginning):
@ -34,61 +34,3 @@ npm install grpc
## TESTING ## TESTING
To run the test suite, simply run `npm test` in the install location. To run the test suite, simply run `npm test` in the install location.
## API
This library internally uses [ProtoBuf.js](https://github.com/dcodeIO/ProtoBuf.js), and some structures it exports match those exported by that library.
If you require this module, you will get an object with the following members
```javascript
function load(filename)
```
Takes a filename of a [Protocol Buffer](https://developers.google.com/protocol-buffers/) file, and returns an object representing the structure of the protocol buffer in the following way:
- Namespaces become maps from the names of their direct members to those member objects
- Service definitions become client constructors for clients for that service. They also have a `service` member that can be used for constructing servers.
- Message definitions become Message constructors like those that ProtoBuf.js would create
- Enum definitions become Enum objects like those that ProtoBuf.js would create
- Anything else becomes the relevant reflection object that ProtoBuf.js would create
```javascript
function loadObject(reflectionObject)
```
Returns the same structure that `load` returns, but takes a reflection object from `ProtoBuf.js` instead of a file name.
```javascript
function Server([serverOptions])
```
Constructs a server to which service/implementation pairs can be added.
```javascript
status
```
An object mapping status names to status code numbers.
```javascript
callError
```
An object mapping call error names to codes. This is primarily useful for tracking down certain kinds of internal errors.
```javascript
Credentials
```
An object with factory methods for creating credential objects for clients.
```javascript
ServerCredentials
```
An object with factory methods for creating credential objects for servers.

@ -1,5 +1,5 @@
/* /**
* * @license
* Copyright 2015, Google Inc. * Copyright 2015, Google Inc.
* All rights reserved. * All rights reserved.
* *
@ -31,10 +31,6 @@
* *
*/ */
/**
* @module
*/
'use strict'; 'use strict';
var path = require('path'); var path = require('path');
@ -64,24 +60,30 @@ var constants = require('./src/constants.js');
grpc.setDefaultRootsPem(fs.readFileSync(SSL_ROOTS_PATH, 'ascii')); grpc.setDefaultRootsPem(fs.readFileSync(SSL_ROOTS_PATH, 'ascii'));
/** /**
* Load a ProtoBuf.js object as a gRPC object. The options object can provide * @namespace grpc
* the following options: */
* - binaryAsBase64: deserialize bytes values as base64 strings instead of
* Buffers. Defaults to false /**
* - longsAsStrings: deserialize long values as strings instead of objects. * Load a ProtoBuf.js object as a gRPC object.
* Defaults to true * @memberof grpc
* - deprecatedArgumentOrder: Use the beta method argument order for client * @alias grpc.loadObject
* methods, with optional arguments after the callback. Defaults to false.
* This option is only a temporary stopgap measure to smooth an API breakage.
* It is deprecated, and new code should not use it.
* - protobufjsVersion: Available values are 5, 6, and 'detect'. 5 and 6
* respectively indicate that an object from the corresponding version of
* ProtoBuf.js is provided in the value argument. If the option is 'detect',
* gRPC will guess what the version is based on the structure of the value.
* Defaults to 'detect'.
* @param {Object} value The ProtoBuf.js reflection object to load * @param {Object} value The ProtoBuf.js reflection object to load
* @param {Object=} options Options to apply to the loaded file * @param {Object=} options Options to apply to the loaded file
* @return {Object<string, *>} The resulting gRPC object * @param {bool=} [options.binaryAsBase64=false] deserialize bytes values as
* base64 strings instead of Buffers
* @param {bool=} [options.longsAsStrings=true] deserialize long values as
* strings instead of objects
* @param {bool=} [options.enumsAsStrings=true] deserialize enum values as
* strings instead of numbers. Only works with Protobuf.js 6 values.
* @param {bool=} [options.deprecatedArgumentOrder=false] use the beta method
* argument order for client methods, with optional arguments after the
* callback. This option is only a temporary stopgap measure to smooth an
* API breakage. It is deprecated, and new code should not use it.
* @param {(number|string)=} [options.protobufjsVersion='detect'] 5 and 6
* respectively indicate that an object from the corresponding version of
* Protobuf.js is provided in the value argument. If the option is 'detect',
* gRPC wll guess what the version is based on the structure of the value.
* @return {Object<string, *>} The resulting gRPC object.
*/ */
exports.loadObject = function loadObject(value, options) { exports.loadObject = function loadObject(value, options) {
options = _.defaults(options, common.defaultGrpcOptions); options = _.defaults(options, common.defaultGrpcOptions);
@ -112,22 +114,23 @@ exports.loadObject = function loadObject(value, options) {
var loadObject = exports.loadObject; var loadObject = exports.loadObject;
/** /**
* Load a gRPC object from a .proto file. The options object can provide the * Load a gRPC object from a .proto file.
* following options: * @memberof grpc
* - convertFieldsToCamelCase: Load this file with field names in camel case * @alias grpc.load
* instead of their original case
* - binaryAsBase64: deserialize bytes values as base64 strings instead of
* Buffers. Defaults to false
* - longsAsStrings: deserialize long values as strings instead of objects.
* Defaults to true
* - deprecatedArgumentOrder: Use the beta method argument order for client
* methods, with optional arguments after the callback. Defaults to false.
* This option is only a temporary stopgap measure to smooth an API breakage.
* It is deprecated, and new code should not use it.
* @param {string|{root: string, file: string}} filename The file to load * @param {string|{root: string, file: string}} filename The file to load
* @param {string=} format The file format to expect. Must be either 'proto' or * @param {string=} format The file format to expect. Must be either 'proto' or
* 'json'. Defaults to 'proto' * 'json'. Defaults to 'proto'
* @param {Object=} options Options to apply to the loaded file * @param {Object=} options Options to apply to the loaded file
* @param {bool=} [options.convertFieldsToCamelCase=false] Load this file with
* field names in camel case instead of their original case
* @param {bool=} [options.binaryAsBase64=false] deserialize bytes values as
* base64 strings instead of Buffers
* @param {bool=} [options.longsAsStrings=true] deserialize long values as
* strings instead of objects
* @param {bool=} [options.deprecatedArgumentOrder=false] use the beta method
* argument order for client methods, with optional arguments after the
* callback. This option is only a temporary stopgap measure to smooth an
* API breakage. It is deprecated, and new code should not use it.
* @return {Object<string, *>} The resulting gRPC object * @return {Object<string, *>} The resulting gRPC object
*/ */
exports.load = function load(filename, format, options) { exports.load = function load(filename, format, options) {
@ -168,6 +171,8 @@ var log_template = _.template(
* called. Note: the output format here is intended to be informational, and * called. Note: the output format here is intended to be informational, and
* is not guaranteed to stay the same in the future. * is not guaranteed to stay the same in the future.
* Logs will be directed to logger.error. * Logs will be directed to logger.error.
* @memberof grpc
* @alias grpc.setLogger
* @param {Console} logger A Console-like object. * @param {Console} logger A Console-like object.
*/ */
exports.setLogger = function setLogger(logger) { exports.setLogger = function setLogger(logger) {
@ -187,6 +192,8 @@ exports.setLogger = function setLogger(logger) {
/** /**
* Sets the logger verbosity for gRPC module logging. The options are members * Sets the logger verbosity for gRPC module logging. The options are members
* of the grpc.logVerbosity map. * of the grpc.logVerbosity map.
* @memberof grpc
* @alias grpc.setLogVerbosity
* @param {Number} verbosity The minimum severity to log * @param {Number} verbosity The minimum severity to log
*/ */
exports.setLogVerbosity = function setLogVerbosity(verbosity) { exports.setLogVerbosity = function setLogVerbosity(verbosity) {
@ -194,71 +201,70 @@ exports.setLogVerbosity = function setLogVerbosity(verbosity) {
grpc.setLogVerbosity(verbosity); grpc.setLogVerbosity(verbosity);
}; };
/**
* @see module:src/server.Server
*/
exports.Server = server.Server; exports.Server = server.Server;
/**
* @see module:src/metadata
*/
exports.Metadata = Metadata; exports.Metadata = Metadata;
/**
* Status name to code number mapping
*/
exports.status = constants.status; exports.status = constants.status;
/**
* Propagate flag name to number mapping
*/
exports.propagate = constants.propagate; exports.propagate = constants.propagate;
/**
* Call error name to code number mapping
*/
exports.callError = constants.callError; exports.callError = constants.callError;
/**
* Write flag name to code number mapping
*/
exports.writeFlags = constants.writeFlags; exports.writeFlags = constants.writeFlags;
/**
* Log verbosity setting name to code number mapping
*/
exports.logVerbosity = constants.logVerbosity; exports.logVerbosity = constants.logVerbosity;
/**
* Credentials factories
*/
exports.credentials = require('./src/credentials.js'); exports.credentials = require('./src/credentials.js');
/** /**
* ServerCredentials factories * ServerCredentials factories
* @constructor ServerCredentials
* @memberof grpc
*/ */
exports.ServerCredentials = grpc.ServerCredentials; exports.ServerCredentials = grpc.ServerCredentials;
/** /**
* @see module:src/client.makeClientConstructor * Create insecure server credentials
* @name grpc.ServerCredentials.createInsecure
* @kind function
* @return grpc.ServerCredentials
*/ */
exports.makeGenericClientConstructor = client.makeClientConstructor;
/** /**
* @see module:src/client.getClientChannel * A private key and certificate pair
* @typedef {Object} grpc.ServerCredentials~keyCertPair
* @property {Buffer} privateKey The server's private key
* @property {Buffer} certChain The server's certificate chain
*/ */
exports.getClientChannel = client.getClientChannel;
/** /**
* @see module:src/client.waitForClientReady * Create SSL server credentials
* @name grpc.ServerCredentials.createInsecure
* @kind function
* @param {?Buffer} rootCerts Root CA certificates for validating client
* certificates
* @param {Array<grpc.ServerCredentials~keyCertPair>} keyCertPairs A list of
* private key and certificate chain pairs to be used for authenticating
* the server
* @param {boolean} [checkClientCertificate=false] Indicates that the server
* should request and verify the client's certificates
* @return grpc.ServerCredentials
*/ */
exports.makeGenericClientConstructor = client.makeClientConstructor;
exports.getClientChannel = client.getClientChannel;
exports.waitForClientReady = client.waitForClientReady; exports.waitForClientReady = client.waitForClientReady;
/**
* @memberof grpc
* @alias grpc.closeClient
* @param {grpc.Client} client_obj The client to close
*/
exports.closeClient = function closeClient(client_obj) { exports.closeClient = function closeClient(client_obj) {
client.Client.prototype.close.apply(client_obj); client.Client.prototype.close.apply(client_obj);
}; };
/**
* @see module:src/client.Client
*/
exports.Client = client.Client; exports.Client = client.Client;

@ -1,5 +1,5 @@
/* /**
* * @license
* Copyright 2015, Google Inc. * Copyright 2015, Google Inc.
* All rights reserved. * All rights reserved.
* *
@ -43,8 +43,6 @@
* var Client = proto_obj.package.subpackage.ServiceName; * var Client = proto_obj.package.subpackage.ServiceName;
* var client = new Client(server_address, client_credentials); * var client = new Client(server_address, client_credentials);
* var call = client.unaryMethod(arguments, callback); * var call = client.unaryMethod(arguments, callback);
*
* @module
*/ */
'use strict'; 'use strict';
@ -70,13 +68,26 @@ var Duplex = stream.Duplex;
var util = require('util'); var util = require('util');
var version = require('../../../package.json').version; var version = require('../../../package.json').version;
/**
* Initial response metadata sent by the server when it starts processing the
* call
* @event grpc~ClientUnaryCall#metadata
* @type {grpc.Metadata}
*/
/**
* Status of the call when it has completed.
* @event grpc~ClientUnaryCall#status
* @type grpc~StatusObject
*/
util.inherits(ClientUnaryCall, EventEmitter); util.inherits(ClientUnaryCall, EventEmitter);
/** /**
* An EventEmitter. Used for unary calls * An EventEmitter. Used for unary calls.
* @constructor * @constructor grpc~ClientUnaryCall
* @extends external:EventEmitter * @extends external:EventEmitter
* @param {grpc.Call} call The call object associated with the request * @param {grpc.internal~Call} call The call object associated with the request
*/ */
function ClientUnaryCall(call) { function ClientUnaryCall(call) {
EventEmitter.call(this); EventEmitter.call(this);
@ -88,14 +99,16 @@ util.inherits(ClientWritableStream, Writable);
/** /**
* A stream that the client can write to. Used for calls that are streaming from * A stream that the client can write to. Used for calls that are streaming from
* the client side. * the client side.
* @constructor * @constructor grpc~ClientWritableStream
* @extends external:Writable * @extends external:Writable
* @borrows module:src/client~ClientUnaryCall#cancel as * @borrows grpc~ClientUnaryCall#cancel as grpc~ClientWritableStream#cancel
* module:src/client~ClientWritableStream#cancel * @borrows grpc~ClientUnaryCall#getPeer as grpc~ClientWritableStream#getPeer
* @borrows module:src/client~ClientUnaryCall#getPeer as * @borrows grpc~ClientUnaryCall#event:metadata as
* module:src/client~ClientWritableStream#getPeer * grpc~ClientWritableStream#metadata
* @param {grpc.Call} call The call object to send data with * @borrows grpc~ClientUnaryCall#event:status as
* @param {module:src/common~serialize=} [serialize=identity] Serialization * grpc~ClientWritableStream#status
* @param {grpc.internal~Call} call The call object to send data with
* @param {grpc~serialize=} [serialize=identity] Serialization
* function for writes. * function for writes.
*/ */
function ClientWritableStream(call, serialize) { function ClientWritableStream(call, serialize) {
@ -109,12 +122,25 @@ function ClientWritableStream(call, serialize) {
}); });
} }
/**
* Write a message to the request stream. If serializing the argument fails,
* the call will be cancelled and the stream will end with an error.
* @name grpc~ClientWritableStream#write
* @kind function
* @override
* @param {*} message The message to write. Must be a valid argument to the
* serialize function of the corresponding method
* @param {grpc.writeFlags} flags Flags to modify how the message is written
* @param {Function} callback Callback for when this chunk of data is flushed
* @return {boolean} As defined for [Writable]{@link external:Writable}
*/
/** /**
* Attempt to write the given chunk. Calls the callback when done. This is an * Attempt to write the given chunk. Calls the callback when done. This is an
* implementation of a method needed for implementing stream.Writable. * implementation of a method needed for implementing stream.Writable.
* @access private * @private
* @param {Buffer} chunk The chunk to write * @param {*} chunk The chunk to write
* @param {string} encoding Used to pass write flags * @param {grpc.writeFlags} encoding Used to pass write flags
* @param {function(Error=)} callback Called when the write is complete * @param {function(Error=)} callback Called when the write is complete
*/ */
function _write(chunk, encoding, callback) { function _write(chunk, encoding, callback) {
@ -155,14 +181,16 @@ util.inherits(ClientReadableStream, Readable);
/** /**
* A stream that the client can read from. Used for calls that are streaming * A stream that the client can read from. Used for calls that are streaming
* from the server side. * from the server side.
* @constructor * @constructor grpc~ClientReadableStream
* @extends external:Readable * @extends external:Readable
* @borrows module:src/client~ClientUnaryCall#cancel as * @borrows grpc~ClientUnaryCall#cancel as grpc~ClientReadableStream#cancel
* module:src/client~ClientReadableStream#cancel * @borrows grpc~ClientUnaryCall#getPeer as grpc~ClientReadableStream#getPeer
* @borrows module:src/client~ClientUnaryCall#getPeer as * @borrows grpc~ClientUnaryCall#event:metadata as
* module:src/client~ClientReadableStream#getPeer * grpc~ClientReadableStream#metadata
* @param {grpc.Call} call The call object to read data with * @borrows grpc~ClientUnaryCall#event:status as
* @param {module:src/common~deserialize=} [deserialize=identity] * grpc~ClientReadableStream#status
* @param {grpc.internal~Call} call The call object to read data with
* @param {grpc~deserialize=} [deserialize=identity]
* Deserialization function for reads * Deserialization function for reads
*/ */
function ClientReadableStream(call, deserialize) { function ClientReadableStream(call, deserialize) {
@ -183,7 +211,7 @@ function ClientReadableStream(call, deserialize) {
* parameter indicates that the call should end with that status. status * parameter indicates that the call should end with that status. status
* defaults to OK if not provided. * defaults to OK if not provided.
* @param {Object!} status The status that the call should end with * @param {Object!} status The status that the call should end with
* @access private * @private
*/ */
function _readsDone(status) { function _readsDone(status) {
/* jshint validthis: true */ /* jshint validthis: true */
@ -202,7 +230,7 @@ ClientReadableStream.prototype._readsDone = _readsDone;
/** /**
* Called to indicate that we have received a status from the server. * Called to indicate that we have received a status from the server.
* @access private * @private
*/ */
function _receiveStatus(status) { function _receiveStatus(status) {
/* jshint validthis: true */ /* jshint validthis: true */
@ -215,7 +243,7 @@ ClientReadableStream.prototype._receiveStatus = _receiveStatus;
/** /**
* If we have both processed all incoming messages and received the status from * If we have both processed all incoming messages and received the status from
* the server, emit the status. Otherwise, do nothing. * the server, emit the status. Otherwise, do nothing.
* @access private * @private
*/ */
function _emitStatusIfDone() { function _emitStatusIfDone() {
/* jshint validthis: true */ /* jshint validthis: true */
@ -242,7 +270,7 @@ ClientReadableStream.prototype._emitStatusIfDone = _emitStatusIfDone;
/** /**
* Read the next object from the stream. * Read the next object from the stream.
* @access private * @private
* @param {*} size Ignored because we use objectMode=true * @param {*} size Ignored because we use objectMode=true
*/ */
function _read(size) { function _read(size) {
@ -300,16 +328,19 @@ util.inherits(ClientDuplexStream, Duplex);
/** /**
* A stream that the client can read from or write to. Used for calls with * A stream that the client can read from or write to. Used for calls with
* duplex streaming. * duplex streaming.
* @constructor * @constructor grpc~ClientDuplexStream
* @extends external:Duplex * @extends external:Duplex
* @borrows module:src/client~ClientUnaryCall#cancel as * @borrows grpc~ClientUnaryCall#cancel as grpc~ClientDuplexStream#cancel
* module:src/client~ClientDuplexStream#cancel * @borrows grpc~ClientUnaryCall#getPeer as grpc~ClientDuplexStream#getPeer
* @borrows module:src/client~ClientUnaryCall#getPeer as * @borrows grpc~ClientWritableStream#write as grpc~ClientDuplexStream#write
* module:src/client~ClientDuplexStream#getPeer * @borrows grpc~ClientUnaryCall#event:metadata as
* @param {grpc.Call} call Call object to proxy * grpc~ClientDuplexStream#metadata
* @param {module:src/common~serialize=} [serialize=identity] Serialization * @borrows grpc~ClientUnaryCall#event:status as
* grpc~ClientDuplexStream#status
* @param {grpc.internal~Call} call Call object to proxy
* @param {grpc~serialize=} [serialize=identity] Serialization
* function for requests * function for requests
* @param {module:src/common~deserialize=} [deserialize=identity] * @param {grpc~deserialize=} [deserialize=identity]
* Deserialization function for responses * Deserialization function for responses
*/ */
function ClientDuplexStream(call, serialize, deserialize) { function ClientDuplexStream(call, serialize, deserialize) {
@ -336,8 +367,9 @@ ClientDuplexStream.prototype._read = _read;
ClientDuplexStream.prototype._write = _write; ClientDuplexStream.prototype._write = _write;
/** /**
* Cancel the ongoing call * Cancel the ongoing call. Results in the call ending with a CANCELLED status,
* @alias module:src/client~ClientUnaryCall#cancel * unless it has already ended with some other status.
* @alias grpc~ClientUnaryCall#cancel
*/ */
function cancel() { function cancel() {
/* jshint validthis: true */ /* jshint validthis: true */
@ -352,7 +384,7 @@ ClientDuplexStream.prototype.cancel = cancel;
/** /**
* Get the endpoint this call/stream is connected to. * Get the endpoint this call/stream is connected to.
* @return {string} The URI of the endpoint * @return {string} The URI of the endpoint
* @alias module:src/client~ClientUnaryCall#getPeer * @alias grpc~ClientUnaryCall#getPeer
*/ */
function getPeer() { function getPeer() {
/* jshint validthis: true */ /* jshint validthis: true */
@ -368,33 +400,31 @@ ClientDuplexStream.prototype.getPeer = getPeer;
* Any client call type * Any client call type
* @typedef {(ClientUnaryCall|ClientReadableStream| * @typedef {(ClientUnaryCall|ClientReadableStream|
* ClientWritableStream|ClientDuplexStream)} * ClientWritableStream|ClientDuplexStream)}
* module:src/client~Call * grpc.Client~Call
*/ */
/** /**
* Options that can be set on a call. * Options that can be set on a call.
* @typedef {Object} module:src/client~CallOptions * @typedef {Object} grpc.Client~CallOptions
* @property {(date|number)} deadline The deadline for the entire call to * @property {grpc~Deadline} deadline The deadline for the entire call to
* complete. A value of Infinity indicates that no deadline should be set. * complete.
* @property {(string)} host Server hostname to set on the call. Only meaningful * @property {string} host Server hostname to set on the call. Only meaningful
* if different from the server address used to construct the client. * if different from the server address used to construct the client.
* @property {module:src/client~Call} parent Parent call. Used in servers when * @property {grpc.Client~Call} parent Parent call. Used in servers when
* making a call as part of the process of handling a call. Used to * making a call as part of the process of handling a call. Used to
* propagate some information automatically, as specified by * propagate some information automatically, as specified by
* propagate_flags. * propagate_flags.
* @property {number} propagate_flags Indicates which properties of a parent * @property {number} propagate_flags Indicates which properties of a parent
* call should propagate to this call. Bitwise combination of flags in * call should propagate to this call. Bitwise combination of flags in
* [grpc.propagate]{@link module:index.propagate}. * {@link grpc.propagate}.
* @property {module:src/credentials~CallCredentials} credentials The * @property {grpc.credentials~CallCredentials} credentials The credentials that
* credentials that should be used to make this particular call. * should be used to make this particular call.
*/ */
/** /**
* Get a call object built with the provided options. Keys for options are * Get a call object built with the provided options.
* 'deadline', which takes a date or number, and 'host', which takes a string
* and overrides the hostname to connect to.
* @access private * @access private
* @param {module:src/client~CallOptions=} options Options object. * @param {grpc.Client~CallOptions=} options Options object.
*/ */
function getCall(channel, method, options) { function getCall(channel, method, options) {
var deadline; var deadline;
@ -422,14 +452,14 @@ function getCall(channel, method, options) {
/** /**
* A generic gRPC client. Primarily useful as a base class for generated clients * A generic gRPC client. Primarily useful as a base class for generated clients
* @alias module:src/client.Client * @memberof grpc
* @constructor * @constructor
* @param {string} address Server address to connect to * @param {string} address Server address to connect to
* @param {module:src/credentials~ChannelCredentials} credentials Credentials to * @param {grpc~ChannelCredentials} credentials Credentials to use to connect to
* use to connect to the server * the server
* @param {Object} options Options to apply to channel creation * @param {Object} options Options to apply to channel creation
*/ */
var Client = exports.Client = function Client(address, credentials, options) { function Client(address, credentials, options) {
if (!options) { if (!options) {
options = {}; options = {};
} }
@ -445,19 +475,13 @@ var Client = exports.Client = function Client(address, credentials, options) {
/* Private fields use $ as a prefix instead of _ because it is an invalid /* Private fields use $ as a prefix instead of _ because it is an invalid
* prefix of a method name */ * prefix of a method name */
this.$channel = new grpc.Channel(address, credentials, options); this.$channel = new grpc.Channel(address, credentials, options);
}; }
/** exports.Client = Client;
* @typedef {Error} module:src/client.Client~ServiceError
* @property {number} code The error code, a key of
* [grpc.status]{@link module:src/client.status}
* @property {module:metadata.Metadata} metadata Metadata sent with the status
* by the server, if any
*/
/** /**
* @callback module:src/client.Client~requestCallback * @callback grpc.Client~requestCallback
* @param {?module:src/client.Client~ServiceError} error The error, if the call * @param {?grpc~ServiceError} error The error, if the call
* failed * failed
* @param {*} value The response value, if the call succeeded * @param {*} value The response value, if the call succeeded
*/ */
@ -466,17 +490,17 @@ var Client = exports.Client = function Client(address, credentials, options) {
* Make a unary request to the given method, using the given serialize * Make a unary request to the given method, using the given serialize
* and deserialize functions, with the given argument. * and deserialize functions, with the given argument.
* @param {string} method The name of the method to request * @param {string} method The name of the method to request
* @param {module:src/common~serialize} serialize The serialization function for * @param {grpc~serialize} serialize The serialization function for
* inputs * inputs
* @param {module:src/common~deserialize} deserialize The deserialization * @param {grpc~deserialize} deserialize The deserialization
* function for outputs * function for outputs
* @param {*} argument The argument to the call. Should be serializable with * @param {*} argument The argument to the call. Should be serializable with
* serialize * serialize
* @param {module:src/metadata.Metadata=} metadata Metadata to add to the call * @param {grpc.Metadata=} metadata Metadata to add to the call
* @param {module:src/client~CallOptions=} options Options map * @param {grpc.Client~CallOptions=} options Options map
* @param {module:src/client.Client~requestCallback} callback The callback to * @param {grpc.Client~requestCallback} callback The callback to
* for when the response is received * for when the response is received
* @return {EventEmitter} An event emitter for stream related events * @return {grpc~ClientUnaryCall} An event emitter for stream related events
*/ */
Client.prototype.makeUnaryRequest = function(method, serialize, deserialize, Client.prototype.makeUnaryRequest = function(method, serialize, deserialize,
argument, metadata, options, argument, metadata, options,
@ -548,17 +572,17 @@ Client.prototype.makeUnaryRequest = function(method, serialize, deserialize,
* Make a client stream request to the given method, using the given serialize * Make a client stream request to the given method, using the given serialize
* and deserialize functions, with the given argument. * and deserialize functions, with the given argument.
* @param {string} method The name of the method to request * @param {string} method The name of the method to request
* @param {module:src/common~serialize} serialize The serialization function for * @param {grpc~serialize} serialize The serialization function for
* inputs * inputs
* @param {module:src/common~deserialize} deserialize The deserialization * @param {grpc~deserialize} deserialize The deserialization
* function for outputs * function for outputs
* @param {module:src/metadata.Metadata=} metadata Array of metadata key/value * @param {grpc.Metadata=} metadata Array of metadata key/value pairs to add to
* pairs to add to the call * the call
* @param {module:src/client~CallOptions=} options Options map * @param {grpc.Client~CallOptions=} options Options map
* @param {Client~requestCallback} callback The callback to for when the * @param {grpc.Client~requestCallback} callback The callback to for when the
* response is received * response is received
* @return {module:src/client~ClientWritableStream} An event emitter for stream * @return {grpc~ClientWritableStream} An event emitter for stream related
* related events * events
*/ */
Client.prototype.makeClientStreamRequest = function(method, serialize, Client.prototype.makeClientStreamRequest = function(method, serialize,
deserialize, metadata, deserialize, metadata,
@ -631,17 +655,16 @@ Client.prototype.makeClientStreamRequest = function(method, serialize,
* Make a server stream request to the given method, with the given serialize * Make a server stream request to the given method, with the given serialize
* and deserialize function, using the given argument * and deserialize function, using the given argument
* @param {string} method The name of the method to request * @param {string} method The name of the method to request
* @param {module:src/common~serialize} serialize The serialization function for * @param {grpc~serialize} serialize The serialization function for inputs
* inputs * @param {grpc~deserialize} deserialize The deserialization
* @param {module:src/common~deserialize} deserialize The deserialization
* function for outputs * function for outputs
* @param {*} argument The argument to the call. Should be serializable with * @param {*} argument The argument to the call. Should be serializable with
* serialize * serialize
* @param {module:src/metadata.Metadata=} metadata Array of metadata key/value * @param {grpc.Metadata=} metadata Array of metadata key/value pairs to add to
* pairs to add to the call * the call
* @param {module:src/client~CallOptions=} options Options map * @param {grpc.Client~CallOptions=} options Options map
* @return {module:src/client~ClientReadableStream} An event emitter for stream * @return {grpc~ClientReadableStream} An event emitter for stream related
* related events * events
*/ */
Client.prototype.makeServerStreamRequest = function(method, serialize, Client.prototype.makeServerStreamRequest = function(method, serialize,
deserialize, argument, deserialize, argument,
@ -693,15 +716,13 @@ Client.prototype.makeServerStreamRequest = function(method, serialize,
/** /**
* Make a bidirectional stream request with this method on the given channel. * Make a bidirectional stream request with this method on the given channel.
* @param {string} method The name of the method to request * @param {string} method The name of the method to request
* @param {module:src/common~serialize} serialize The serialization function for * @param {grpc~serialize} serialize The serialization function for inputs
* inputs * @param {grpc~deserialize} deserialize The deserialization
* @param {module:src/common~deserialize} deserialize The deserialization
* function for outputs * function for outputs
* @param {module:src/metadata.Metadata=} metadata Array of metadata key/value * @param {grpc.Metadata=} metadata Array of metadata key/value
* pairs to add to the call * pairs to add to the call
* @param {module:src/client~CallOptions=} options Options map * @param {grpc.Client~CallOptions=} options Options map
* @return {module:src/client~ClientDuplexStream} An event emitter for stream * @return {grpc~ClientDuplexStream} An event emitter for stream related events
* related events
*/ */
Client.prototype.makeBidiStreamRequest = function(method, serialize, Client.prototype.makeBidiStreamRequest = function(method, serialize,
deserialize, metadata, deserialize, metadata,
@ -743,6 +764,9 @@ Client.prototype.makeBidiStreamRequest = function(method, serialize,
return stream; return stream;
}; };
/**
* Close this client.
*/
Client.prototype.close = function() { Client.prototype.close = function() {
this.$channel.close(); this.$channel.close();
}; };
@ -761,8 +785,7 @@ Client.prototype.getChannel = function() {
* with an error if the attempt to connect to the server has unrecoverablly * with an error if the attempt to connect to the server has unrecoverablly
* failed or if the deadline expires. This function will make the channel * failed or if the deadline expires. This function will make the channel
* start connecting if it has not already done so. * start connecting if it has not already done so.
* @param {(Date|Number)} deadline When to stop waiting for a connection. Pass * @param {grpc~Deadline} deadline When to stop waiting for a connection.
* Infinity to wait forever.
* @param {function(Error)} callback The callback to call when done attempting * @param {function(Error)} callback The callback to call when done attempting
* to connect. * to connect.
*/ */
@ -788,7 +811,7 @@ Client.prototype.waitForReady = function(deadline, callback) {
/** /**
* Map with short names for each of the requester maker functions. Used in * Map with short names for each of the requester maker functions. Used in
* makeClientConstructor * makeClientConstructor
* @access private * @private
*/ */
var requester_funcs = { var requester_funcs = {
unary: Client.prototype.makeUnaryRequest, unary: Client.prototype.makeUnaryRequest,
@ -834,9 +857,15 @@ var deprecated_request_wrap = {
/** /**
* Creates a constructor for a client with the given methods, as specified in * Creates a constructor for a client with the given methods, as specified in
* the methods argument. * the methods argument. The resulting class will have an instance method for
* @param {module:src/common~ServiceDefinition} methods An object mapping * each method in the service, which is a partial application of one of the
* method names to method attributes * [Client]{@link grpc.Client} request methods, depending on `requestSerialize`
* and `responseSerialize`, with the `method`, `serialize`, and `deserialize`
* arguments predefined.
* @memberof grpc
* @alias grpc~makeGenericClientConstructor
* @param {grpc~ServiceDefinition} methods An object mapping method names to
* method attributes
* @param {string} serviceName The fully qualified name of the service * @param {string} serviceName The fully qualified name of the service
* @param {Object} class_options An options object. * @param {Object} class_options An options object.
* @param {boolean=} [class_options.deprecatedArgumentOrder=false] Indicates * @param {boolean=} [class_options.deprecatedArgumentOrder=false] Indicates
@ -844,9 +873,8 @@ var deprecated_request_wrap = {
* arguments at the end instead of the callback at the end. This option * arguments at the end instead of the callback at the end. This option
* is only a temporary stopgap measure to smooth an API breakage. * is only a temporary stopgap measure to smooth an API breakage.
* It is deprecated, and new code should not use it. * It is deprecated, and new code should not use it.
* @return {function(string, Object)} New client constructor, which is a * @return {function} New client constructor, which is a subclass of
* subclass of [grpc.Client]{@link module:src/client.Client}, and has the * {@link grpc.Client}, and has the same arguments as that constructor.
* same arguments as that constructor.
*/ */
exports.makeClientConstructor = function(methods, serviceName, exports.makeClientConstructor = function(methods, serviceName,
class_options) { class_options) {
@ -898,8 +926,11 @@ exports.makeClientConstructor = function(methods, serviceName,
/** /**
* Return the underlying channel object for the specified client * Return the underlying channel object for the specified client
* @memberof grpc
* @alias grpc~getClientChannel
* @param {Client} client * @param {Client} client
* @return {Channel} The channel * @return {Channel} The channel
* @see grpc.Client#getChannel
*/ */
exports.getClientChannel = function(client) { exports.getClientChannel = function(client) {
return Client.prototype.getChannel.call(client); return Client.prototype.getChannel.call(client);
@ -911,22 +942,15 @@ exports.getClientChannel = function(client) {
* with an error if the attempt to connect to the server has unrecoverablly * with an error if the attempt to connect to the server has unrecoverablly
* failed or if the deadline expires. This function will make the channel * failed or if the deadline expires. This function will make the channel
* start connecting if it has not already done so. * start connecting if it has not already done so.
* @memberof grpc
* @alias grpc~waitForClientReady
* @param {Client} client The client to wait on * @param {Client} client The client to wait on
* @param {(Date|Number)} deadline When to stop waiting for a connection. Pass * @param {grpc~Deadline} deadline When to stop waiting for a connection. Pass
* Infinity to wait forever. * Infinity to wait forever.
* @param {function(Error)} callback The callback to call when done attempting * @param {function(Error)} callback The callback to call when done attempting
* to connect. * to connect.
* @see grpc.Client#waitForReady
*/ */
exports.waitForClientReady = function(client, deadline, callback) { exports.waitForClientReady = function(client, deadline, callback) {
Client.prototype.waitForReady.call(client, deadline, callback); Client.prototype.waitForReady.call(client, deadline, callback);
}; };
/**
* Map of status code names to status codes
*/
exports.status = constants.status;
/**
* See docs for client.callError
*/
exports.callError = grpc.callError;

@ -1,5 +1,5 @@
/* /**
* * @license
* Copyright 2015, Google Inc. * Copyright 2015, Google Inc.
* All rights reserved. * All rights reserved.
* *
@ -31,12 +31,6 @@
* *
*/ */
/**
* This module contains functions that are common to client and server
* code. None of them should be used directly by gRPC users.
* @module
*/
'use strict'; 'use strict';
var _ = require('lodash'); var _ = require('lodash');
@ -62,16 +56,19 @@ exports.wrapIgnoreNull = function wrapIgnoreNull(func) {
/** /**
* The logger object for the gRPC module. Defaults to console. * The logger object for the gRPC module. Defaults to console.
* @private
*/ */
exports.logger = console; exports.logger = console;
/** /**
* The current logging verbosity. 0 corresponds to logging everything * The current logging verbosity. 0 corresponds to logging everything
* @private
*/ */
exports.logVerbosity = 0; exports.logVerbosity = 0;
/** /**
* Log a message if the severity is at least as high as the current verbosity * Log a message if the severity is at least as high as the current verbosity
* @private
* @param {Number} severity A value of the grpc.logVerbosity map * @param {Number} severity A value of the grpc.logVerbosity map
* @param {String} message The message to log * @param {String} message The message to log
*/ */
@ -83,6 +80,7 @@ exports.log = function log(severity, message) {
/** /**
* Default options for loading proto files into gRPC * Default options for loading proto files into gRPC
* @alias grpc~defaultLoadOptions
*/ */
exports.defaultGrpcOptions = { exports.defaultGrpcOptions = {
convertFieldsToCamelCase: false, convertFieldsToCamelCase: false,
@ -94,6 +92,30 @@ exports.defaultGrpcOptions = {
// JSDoc definitions that are used in multiple other modules // JSDoc definitions that are used in multiple other modules
/**
* Represents the status of a completed request. If `code` is
* {@link grpc.status}.OK, then the request has completed successfully.
* Otherwise, the request has failed, `details` will contain a description of
* the error. Either way, `metadata` contains the trailing response metadata
* sent by the server when it finishes processing the call.
* @typedef {object} grpc~StatusObject
* @property {number} code The error code, a key of {@link grpc.status}
* @property {string} details Human-readable description of the status
* @property {grpc.Metadata} metadata Trailing metadata sent with the status,
* if applicable
*/
/**
* Describes how a request has failed. The member `message` will be the same as
* `details` in {@link grpc~StatusObject}, and `code` and `metadata` are the
* same as in that object.
* @typedef {Error} grpc~ServiceError
* @property {number} code The error code, a key of {@link grpc.status} that is
* not `grpc.status.OK`
* @property {grpc.Metadata} metadata Trailing metadata sent with the status,
* if applicable
*/
/** /**
* The EventEmitter class in the event standard module * The EventEmitter class in the event standard module
* @external EventEmitter * @external EventEmitter
@ -120,38 +142,46 @@ exports.defaultGrpcOptions = {
/** /**
* A serialization function * A serialization function
* @callback module:src/common~serialize * @callback grpc~serialize
* @param {*} value The value to serialize * @param {*} value The value to serialize
* @return {Buffer} The value serialized as a byte sequence * @return {Buffer} The value serialized as a byte sequence
*/ */
/** /**
* A deserialization function * A deserialization function
* @callback module:src/common~deserialize * @callback grpc~deserialize
* @param {Buffer} data The byte sequence to deserialize * @param {Buffer} data The byte sequence to deserialize
* @return {*} The data deserialized as a value * @return {*} The data deserialized as a value
*/ */
/**
* The deadline of an operation. If it is a date, the deadline is reached at
* the date and time specified. If it is a finite number, it is treated as
* a number of milliseconds since the Unix Epoch. If it is Infinity, the
* deadline will never be reached. If it is -Infinity, the deadline has already
* passed.
* @typedef {(number|date)} grpc~Deadline
*/
/** /**
* An object that completely defines a service method signature. * An object that completely defines a service method signature.
* @typedef {Object} module:src/common~MethodDefinition * @typedef {Object} grpc~MethodDefinition
* @property {string} path The method's URL path * @property {string} path The method's URL path
* @property {boolean} requestStream Indicates whether the method accepts * @property {boolean} requestStream Indicates whether the method accepts
* a stream of requests * a stream of requests
* @property {boolean} responseStream Indicates whether the method returns * @property {boolean} responseStream Indicates whether the method returns
* a stream of responses * a stream of responses
* @property {module:src/common~serialize} requestSerialize Serialization * @property {grpc~serialize} requestSerialize Serialization
* function for request values * function for request values
* @property {module:src/common~serialize} responseSerialize Serialization * @property {grpc~serialize} responseSerialize Serialization
* function for response values * function for response values
* @property {module:src/common~deserialize} requestDeserialize Deserialization * @property {grpc~deserialize} requestDeserialize Deserialization
* function for request data * function for request data
* @property {module:src/common~deserialize} responseDeserialize Deserialization * @property {grpc~deserialize} responseDeserialize Deserialization
* function for repsonse data * function for repsonse data
*/ */
/** /**
* An object that completely defines a service. * An object that completely defines a service.
* @typedef {Object.<string, module:src/common~MethodDefinition>} * @typedef {Object.<string, grpc~MethodDefinition>} grpc~ServiceDefinition
* module:src/common~ServiceDefinition
*/ */

@ -1,5 +1,5 @@
/* /**
* * @license
* Copyright 2017, Google Inc. * Copyright 2017, Google Inc.
* All rights reserved. * All rights reserved.
* *
@ -31,16 +31,14 @@
* *
*/ */
/**
* @module
*/
/* The comments about status codes are copied verbatim (with some formatting /* The comments about status codes are copied verbatim (with some formatting
* modifications) from include/grpc/impl/codegen/status.h, for the purpose of * modifications) from include/grpc/impl/codegen/status.h, for the purpose of
* including them in generated documentation. * including them in generated documentation.
*/ */
/** /**
* Enum of status codes that gRPC can return * Enum of status codes that gRPC can return
* @memberof grpc
* @alias grpc.status
* @readonly * @readonly
* @enum {number} * @enum {number}
*/ */
@ -178,6 +176,8 @@ exports.status = {
* Users are encouraged to write propagation masks as deltas from the default. * Users are encouraged to write propagation masks as deltas from the default.
* i.e. write `grpc.propagate.DEFAULTS & ~grpc.propagate.DEADLINE` to disable * i.e. write `grpc.propagate.DEFAULTS & ~grpc.propagate.DEADLINE` to disable
* deadline propagation. * deadline propagation.
* @memberof grpc
* @alias grpc.propagate
* @enum {number} * @enum {number}
*/ */
exports.propagate = { exports.propagate = {
@ -194,9 +194,11 @@ exports.propagate = {
/** /**
* Call error constants. Call errors almost always indicate bugs in the gRPC * Call error constants. Call errors almost always indicate bugs in the gRPC
* library, and these error codes are mainly useful for finding those bugs. * library, and these error codes are mainly useful for finding those bugs.
* @memberof grpc
* @readonly
* @enum {number} * @enum {number}
*/ */
exports.callError = { const callError = {
OK: 0, OK: 0,
ERROR: 1, ERROR: 1,
NOT_ON_SERVER: 2, NOT_ON_SERVER: 2,
@ -213,9 +215,14 @@ exports.callError = {
PAYLOAD_TYPE_MISMATCH: 14 PAYLOAD_TYPE_MISMATCH: 14
}; };
exports.callError = callError;
/** /**
* Write flags: these can be bitwise or-ed to form write options that modify * Write flags: these can be bitwise or-ed to form write options that modify
* how data is written. * how data is written.
* @memberof grpc
* @alias grpc.writeFlags
* @readonly
* @enum {number} * @enum {number}
*/ */
exports.writeFlags = { exports.writeFlags = {
@ -232,6 +239,9 @@ exports.writeFlags = {
}; };
/** /**
* @memberof grpc
* @alias grpc.logVerbosity
* @readonly
* @enum {number} * @enum {number}
*/ */
exports.logVerbosity = { exports.logVerbosity = {

@ -1,5 +1,5 @@
/* /**
* * @license
* Copyright 2015, Google Inc. * Copyright 2015, Google Inc.
* All rights reserved. * All rights reserved.
* *
@ -48,6 +48,7 @@
* For example, to create a client secured with SSL that uses Google * For example, to create a client secured with SSL that uses Google
* default application credentials to authenticate: * default application credentials to authenticate:
* *
* @example
* var channel_creds = credentials.createSsl(root_certs); * var channel_creds = credentials.createSsl(root_certs);
* (new GoogleAuth()).getApplicationDefault(function(err, credential) { * (new GoogleAuth()).getApplicationDefault(function(err, credential) {
* var call_creds = credentials.createFromGoogleCredential(credential); * var call_creds = credentials.createFromGoogleCredential(credential);
@ -56,15 +57,25 @@
* var client = new Client(address, combined_creds); * var client = new Client(address, combined_creds);
* }); * });
* *
* @module * @namespace grpc.credentials
*/ */
'use strict'; 'use strict';
var grpc = require('./grpc_extension'); var grpc = require('./grpc_extension');
/**
* This cannot be constructed directly. Instead, instances of this class should
* be created using the factory functions in {@link grpc.credentials}
* @constructor grpc.credentials~CallCredentials
*/
var CallCredentials = grpc.CallCredentials; var CallCredentials = grpc.CallCredentials;
/**
* This cannot be constructed directly. Instead, instances of this class should
* be created using the factory functions in {@link grpc.credentials}
* @constructor grpc.credentials~ChannelCredentials
*/
var ChannelCredentials = grpc.ChannelCredentials; var ChannelCredentials = grpc.ChannelCredentials;
var Metadata = require('./metadata.js'); var Metadata = require('./metadata.js');
@ -75,25 +86,49 @@ var constants = require('./constants');
var _ = require('lodash'); var _ = require('lodash');
/**
* @external GoogleCredential
* @see https://github.com/google/google-auth-library-nodejs
*/
/** /**
* Create an SSL Credentials object. If using a client-side certificate, both * Create an SSL Credentials object. If using a client-side certificate, both
* the second and third arguments must be passed. * the second and third arguments must be passed.
* @memberof grpc.credentials
* @alias grpc.credentials.createSsl
* @kind function
* @param {Buffer} root_certs The root certificate data * @param {Buffer} root_certs The root certificate data
* @param {Buffer=} private_key The client certificate private key, if * @param {Buffer=} private_key The client certificate private key, if
* applicable * applicable
* @param {Buffer=} cert_chain The client certificate cert chain, if applicable * @param {Buffer=} cert_chain The client certificate cert chain, if applicable
* @return {ChannelCredentials} The SSL Credentials object * @return {grpc.credentials.ChannelCredentials} The SSL Credentials object
*/ */
exports.createSsl = ChannelCredentials.createSsl; exports.createSsl = ChannelCredentials.createSsl;
/**
* @callback grpc.credentials~metadataCallback
* @param {Error} error The error, if getting metadata failed
* @param {grpc.Metadata} metadata The metadata
*/
/**
* @callback grpc.credentials~generateMetadata
* @param {Object} params Parameters that can modify metadata generation
* @param {string} params.service_url The URL of the service that the call is
* going to
* @param {grpc.credentials~metadataCallback} callback
*/
/** /**
* Create a gRPC credentials object from a metadata generation function. This * Create a gRPC credentials object from a metadata generation function. This
* function gets the service URL and a callback as parameters. The error * function gets the service URL and a callback as parameters. The error
* passed to the callback can optionally have a 'code' value attached to it, * passed to the callback can optionally have a 'code' value attached to it,
* which corresponds to a status code that this library uses. * which corresponds to a status code that this library uses.
* @param {function(String, function(Error, Metadata))} metadata_generator The * @memberof grpc.credentials
* function that generates metadata * @alias grpc.credentials.createFromMetadataGenerator
* @return {CallCredentials} The credentials object * @param {grpc.credentials~generateMetadata} metadata_generator The function
* that generates metadata
* @return {grpc.credentials.CallCredentials} The credentials object
*/ */
exports.createFromMetadataGenerator = function(metadata_generator) { exports.createFromMetadataGenerator = function(metadata_generator) {
return CallCredentials.createFromPlugin(function(service_url, cb_data, return CallCredentials.createFromPlugin(function(service_url, cb_data,
@ -119,8 +154,11 @@ exports.createFromMetadataGenerator = function(metadata_generator) {
/** /**
* Create a gRPC credential from a Google credential object. * Create a gRPC credential from a Google credential object.
* @param {Object} google_credential The Google credential object to use * @memberof grpc.credentials
* @return {CallCredentials} The resulting credentials object * @alias grpc.credentials.createFromGoogleCredential
* @param {external:GoogleCredential} google_credential The Google credential
* object to use
* @return {grpc.credentials.CallCredentials} The resulting credentials object
*/ */
exports.createFromGoogleCredential = function(google_credential) { exports.createFromGoogleCredential = function(google_credential) {
return exports.createFromMetadataGenerator(function(auth_context, callback) { return exports.createFromMetadataGenerator(function(auth_context, callback) {
@ -141,6 +179,8 @@ exports.createFromGoogleCredential = function(google_credential) {
/** /**
* Combine a ChannelCredentials with any number of CallCredentials into a single * Combine a ChannelCredentials with any number of CallCredentials into a single
* ChannelCredentials object. * ChannelCredentials object.
* @memberof grpc.credentials
* @alias grpc.credentials.combineChannelCredentials
* @param {ChannelCredentials} channel_credential The ChannelCredentials to * @param {ChannelCredentials} channel_credential The ChannelCredentials to
* start with * start with
* @param {...CallCredentials} credentials The CallCredentials to compose * @param {...CallCredentials} credentials The CallCredentials to compose
@ -157,6 +197,8 @@ exports.combineChannelCredentials = function(channel_credential) {
/** /**
* Combine any number of CallCredentials into a single CallCredentials object * Combine any number of CallCredentials into a single CallCredentials object
* @memberof grpc.credentials
* @alias grpc.credentials.combineCallCredentials
* @param {...CallCredentials} credentials the CallCredentials to compose * @param {...CallCredentials} credentials the CallCredentials to compose
* @return CallCredentials A credentials object that combines all of the input * @return CallCredentials A credentials object that combines all of the input
* credentials * credentials
@ -172,6 +214,9 @@ exports.combineCallCredentials = function() {
/** /**
* Create an insecure credentials object. This is used to create a channel that * Create an insecure credentials object. This is used to create a channel that
* does not use SSL. This cannot be composed with anything. * does not use SSL. This cannot be composed with anything.
* @memberof grpc.credentials
* @alias grpc.credentials.createInsecure
* @kind function
* @return {ChannelCredentials} The insecure credentials object * @return {ChannelCredentials} The insecure credentials object
*/ */
exports.createInsecure = ChannelCredentials.createInsecure; exports.createInsecure = ChannelCredentials.createInsecure;

@ -1,5 +1,5 @@
/* /**
* * @license
* Copyright 2016, Google Inc. * Copyright 2016, Google Inc.
* All rights reserved. * All rights reserved.
* *

@ -1,5 +1,5 @@
/* /**
* * @license
* Copyright 2015, Google Inc. * Copyright 2015, Google Inc.
* All rights reserved. * All rights reserved.
* *
@ -31,15 +31,6 @@
* *
*/ */
/**
* Metadata module
*
* This module defines the Metadata class, which represents header and trailer
* metadata for gRPC calls.
*
* @module
*/
'use strict'; 'use strict';
var _ = require('lodash'); var _ = require('lodash');
@ -48,8 +39,8 @@ var grpc = require('./grpc_extension');
/** /**
* Class for storing metadata. Keys are normalized to lowercase ASCII. * Class for storing metadata. Keys are normalized to lowercase ASCII.
* @memberof grpc
* @constructor * @constructor
* @alias module:src/metadata.Metadata
* @example * @example
* var metadata = new metadata_module.Metadata(); * var metadata = new metadata_module.Metadata();
* metadata.set('key1', 'value1'); * metadata.set('key1', 'value1');

@ -1,5 +1,5 @@
/* /**
* * @license
* Copyright 2017, Google Inc. * Copyright 2017, Google Inc.
* All rights reserved. * All rights reserved.
* *
@ -31,6 +31,11 @@
* *
*/ */
/**
* @module
* @private
*/
'use strict'; 'use strict';
var _ = require('lodash'); var _ = require('lodash');

@ -1,5 +1,5 @@
/* /**
* * @license
* Copyright 2017, Google Inc. * Copyright 2017, Google Inc.
* All rights reserved. * All rights reserved.
* *
@ -31,6 +31,11 @@
* *
*/ */
/**
* @module
* @private
*/
'use strict'; 'use strict';
var _ = require('lodash'); var _ = require('lodash');

@ -1,5 +1,5 @@
/* /**
* * @license
* Copyright 2015, Google Inc. * Copyright 2015, Google Inc.
* All rights reserved. * All rights reserved.
* *
@ -31,22 +31,6 @@
* *
*/ */
/**
* Server module
*
* This module contains all the server code for Node gRPC: both the Server
* class itself and the method handler code for all types of methods.
*
* For example, to create a Server, add a service, and start it:
*
* var server = new server_module.Server();
* server.addProtoService(protobuf_service_descriptor, service_implementation);
* server.bind('address:port', server_credential);
* server.start();
*
* @module
*/
'use strict'; 'use strict';
var _ = require('lodash'); var _ = require('lodash');
@ -70,9 +54,9 @@ var EventEmitter = require('events').EventEmitter;
/** /**
* Handle an error on a call by sending it as a status * Handle an error on a call by sending it as a status
* @access private * @private
* @param {grpc.Call} call The call to send the error on * @param {grpc.internal~Call} call The call to send the error on
* @param {Object} error The error object * @param {(Object|Error)} error The error object
*/ */
function handleError(call, error) { function handleError(call, error) {
var statusMetadata = new Metadata(); var statusMetadata = new Metadata();
@ -104,14 +88,14 @@ function handleError(call, error) {
/** /**
* Send a response to a unary or client streaming call. * Send a response to a unary or client streaming call.
* @access private * @private
* @param {grpc.Call} call The call to respond on * @param {grpc.Call} call The call to respond on
* @param {*} value The value to respond with * @param {*} value The value to respond with
* @param {function(*):Buffer=} serialize Serialization function for the * @param {grpc~serialize} serialize Serialization function for the
* response * response
* @param {Metadata=} metadata Optional trailing metadata to send with status * @param {grpc.Metadata=} metadata Optional trailing metadata to send with
* @param {number=} flags Flags for modifying how the message is sent. * status
* Defaults to 0. * @param {number=} [flags=0] Flags for modifying how the message is sent.
*/ */
function sendUnaryResponse(call, value, serialize, metadata, flags) { function sendUnaryResponse(call, value, serialize, metadata, flags) {
var end_batch = {}; var end_batch = {};
@ -146,7 +130,7 @@ function sendUnaryResponse(call, value, serialize, metadata, flags) {
/** /**
* Initialize a writable stream. This is used for both the writable and duplex * Initialize a writable stream. This is used for both the writable and duplex
* stream constructors. * stream constructors.
* @access private * @private
* @param {Writable} stream The stream to set up * @param {Writable} stream The stream to set up
* @param {function(*):Buffer=} Serialization function for responses * @param {function(*):Buffer=} Serialization function for responses
*/ */
@ -225,9 +209,9 @@ function setUpWritable(stream, serialize) {
/** /**
* Initialize a readable stream. This is used for both the readable and duplex * Initialize a readable stream. This is used for both the readable and duplex
* stream constructors. * stream constructors.
* @access private * @private
* @param {Readable} stream The stream to initialize * @param {Readable} stream The stream to initialize
* @param {function(Buffer):*=} deserialize Deserialization function for * @param {grpc~deserialize} deserialize Deserialization function for
* incoming data. * incoming data.
*/ */
function setUpReadable(stream, deserialize) { function setUpReadable(stream, deserialize) {
@ -245,34 +229,88 @@ function setUpReadable(stream, deserialize) {
}); });
} }
/**
* Emitted when the call has been cancelled. After this has been emitted, the
* call's `cancelled` property will be set to `true`.
* @event grpc~ServerUnaryCall~cancelled
*/
util.inherits(ServerUnaryCall, EventEmitter); util.inherits(ServerUnaryCall, EventEmitter);
function ServerUnaryCall(call) { /**
* An EventEmitter. Used for unary calls.
* @constructor grpc~ServerUnaryCall
* @extends external:EventEmitter
* @param {grpc.internal~Call} call The call object associated with the request
* @param {grpc.Metadata} metadata The request metadata from the client
*/
function ServerUnaryCall(call, metadata) {
EventEmitter.call(this); EventEmitter.call(this);
this.call = call; this.call = call;
/**
* Indicates if the call has been cancelled
* @member {boolean} grpc~ServerUnaryCall#cancelled
*/
this.cancelled = false;
/**
* The request metadata from the client
* @member {grpc.Metadata} grpc~ServerUnaryCall#metadata
*/
this.metadata = metadata;
/**
* The request message from the client
* @member {*} grpc~ServerUnaryCall#request
*/
this.request = undefined;
} }
/**
* Emitted when the call has been cancelled. After this has been emitted, the
* call's `cancelled` property will be set to `true`.
* @event grpc~ServerWritableStream~cancelled
*/
util.inherits(ServerWritableStream, Writable); util.inherits(ServerWritableStream, Writable);
/** /**
* A stream that the server can write to. Used for calls that are streaming from * A stream that the server can write to. Used for calls that are streaming from
* the server side. * the server side.
* @constructor * @constructor grpc~ServerWritableStream
* @param {grpc.Call} call The call object to send data with * @extends external:Writable
* @param {function(*):Buffer=} serialize Serialization function for writes * @borrows grpc~ServerUnaryCall#sendMetadata as
* grpc~ServerWritableStream#sendMetadata
* @borrows grpc~ServerUnaryCall#getPeer as grpc~ServerWritableStream#getPeer
* @param {grpc.internal~Call} call The call object to send data with
* @param {grpc.Metadata} metadata The request metadata from the client
* @param {grpc~serialize} serialize Serialization function for writes
*/ */
function ServerWritableStream(call, serialize) { function ServerWritableStream(call, metadata, serialize) {
Writable.call(this, {objectMode: true}); Writable.call(this, {objectMode: true});
this.call = call; this.call = call;
this.finished = false; this.finished = false;
setUpWritable(this, serialize); setUpWritable(this, serialize);
/**
* Indicates if the call has been cancelled
* @member {boolean} grpc~ServerWritableStream#cancelled
*/
this.cancelled = false;
/**
* The request metadata from the client
* @member {grpc.Metadata} grpc~ServerWritableStream#metadata
*/
this.metadata = metadata;
/**
* The request message from the client
* @member {*} grpc~ServerWritableStream#request
*/
this.request = undefined;
} }
/** /**
* Start writing a chunk of data. This is an implementation of a method required * Start writing a chunk of data. This is an implementation of a method required
* for implementing stream.Writable. * for implementing stream.Writable.
* @access private * @private
* @param {Buffer} chunk The chunk of data to write * @param {Buffer} chunk The chunk of data to write
* @param {string} encoding Used to pass write flags * @param {string} encoding Used to pass write flags
* @param {function(Error=)} callback Callback to indicate that the write is * @param {function(Error=)} callback Callback to indicate that the write is
@ -312,19 +350,40 @@ function _write(chunk, encoding, callback) {
ServerWritableStream.prototype._write = _write; ServerWritableStream.prototype._write = _write;
/**
* Emitted when the call has been cancelled. After this has been emitted, the
* call's `cancelled` property will be set to `true`.
* @event grpc~ServerReadableStream~cancelled
*/
util.inherits(ServerReadableStream, Readable); util.inherits(ServerReadableStream, Readable);
/** /**
* A stream that the server can read from. Used for calls that are streaming * A stream that the server can read from. Used for calls that are streaming
* from the client side. * from the client side.
* @constructor * @constructor grpc~ServerReadableStream
* @param {grpc.Call} call The call object to read data with * @extends external:Readable
* @param {function(Buffer):*=} deserialize Deserialization function for reads * @borrows grpc~ServerUnaryCall#sendMetadata as
* grpc~ServerReadableStream#sendMetadata
* @borrows grpc~ServerUnaryCall#getPeer as grpc~ServerReadableStream#getPeer
* @param {grpc.internal~Call} call The call object to read data with
* @param {grpc.Metadata} metadata The request metadata from the client
* @param {grpc~deserialize} deserialize Deserialization function for reads
*/ */
function ServerReadableStream(call, deserialize) { function ServerReadableStream(call, metadata, deserialize) {
Readable.call(this, {objectMode: true}); Readable.call(this, {objectMode: true});
this.call = call; this.call = call;
setUpReadable(this, deserialize); setUpReadable(this, deserialize);
/**
* Indicates if the call has been cancelled
* @member {boolean} grpc~ServerReadableStream#cancelled
*/
this.cancelled = false;
/**
* The request metadata from the client
* @member {grpc.Metadata} grpc~ServerReadableStream#metadata
*/
this.metadata = metadata;
} }
/** /**
@ -381,22 +440,43 @@ function _read(size) {
ServerReadableStream.prototype._read = _read; ServerReadableStream.prototype._read = _read;
/**
* Emitted when the call has been cancelled. After this has been emitted, the
* call's `cancelled` property will be set to `true`.
* @event grpc~ServerDuplexStream~cancelled
*/
util.inherits(ServerDuplexStream, Duplex); util.inherits(ServerDuplexStream, Duplex);
/** /**
* A stream that the server can read from or write to. Used for calls with * A stream that the server can read from or write to. Used for calls with
* duplex streaming. * duplex streaming.
* @constructor * @constructor grpc~ServerDuplexStream
* @param {grpc.Call} call Call object to proxy * @extends external:Duplex
* @param {function(*):Buffer=} serialize Serialization function for requests * @borrows grpc~ServerUnaryCall#sendMetadata as
* @param {function(Buffer):*=} deserialize Deserialization function for * grpc~ServerDuplexStream#sendMetadata
* @borrows grpc~ServerUnaryCall#getPeer as grpc~ServerDuplexStream#getPeer
* @param {grpc.internal~Call} call Call object to proxy
* @param {grpc.Metadata} metadata The request metadata from the client
* @param {grpc~serialize} serialize Serialization function for requests
* @param {grpc~deserialize} deserialize Deserialization function for
* responses * responses
*/ */
function ServerDuplexStream(call, serialize, deserialize) { function ServerDuplexStream(call, metadata, serialize, deserialize) {
Duplex.call(this, {objectMode: true}); Duplex.call(this, {objectMode: true});
this.call = call; this.call = call;
setUpWritable(this, serialize); setUpWritable(this, serialize);
setUpReadable(this, deserialize); setUpReadable(this, deserialize);
/**
* Indicates if the call has been cancelled
* @member {boolean} grpc~ServerReadableStream#cancelled
*/
this.cancelled = false;
/**
* The request metadata from the client
* @member {grpc.Metadata} grpc~ServerReadableStream#metadata
*/
this.metadata = metadata;
} }
ServerDuplexStream.prototype._read = _read; ServerDuplexStream.prototype._read = _read;
@ -404,6 +484,7 @@ ServerDuplexStream.prototype._write = _write;
/** /**
* Send the initial metadata for a writable stream. * Send the initial metadata for a writable stream.
* @alias grpc~ServerUnaryCall#sendMetadata
* @param {Metadata} responseMetadata Metadata to send * @param {Metadata} responseMetadata Metadata to send
*/ */
function sendMetadata(responseMetadata) { function sendMetadata(responseMetadata) {
@ -430,6 +511,7 @@ ServerDuplexStream.prototype.sendMetadata = sendMetadata;
/** /**
* Get the endpoint this call/stream is connected to. * Get the endpoint this call/stream is connected to.
* @alias grpc~ServerUnaryCall#getPeer
* @return {string} The URI of the endpoint * @return {string} The URI of the endpoint
*/ */
function getPeer() { function getPeer() {
@ -445,6 +527,7 @@ ServerDuplexStream.prototype.getPeer = getPeer;
/** /**
* Wait for the client to close, then emit a cancelled event if the client * Wait for the client to close, then emit a cancelled event if the client
* cancelled. * cancelled.
* @private
*/ */
function waitForCancel() { function waitForCancel() {
/* jshint validthis: true */ /* jshint validthis: true */
@ -467,19 +550,42 @@ ServerReadableStream.prototype.waitForCancel = waitForCancel;
ServerWritableStream.prototype.waitForCancel = waitForCancel; ServerWritableStream.prototype.waitForCancel = waitForCancel;
ServerDuplexStream.prototype.waitForCancel = waitForCancel; ServerDuplexStream.prototype.waitForCancel = waitForCancel;
/**
* Callback function passed to server handlers that handle methods with unary
* responses.
* @callback grpc.Server~sendUnaryData
* @param {grpc~ServiceError} error An error, if the call failed
* @param {*} value The response value. Must be a valid argument to the
* `responseSerialize` method of the method that is being handled
* @param {grpc.Metadata=} trailer Trailing metadata to send, if applicable
* @param {grpc.writeFlags=} flags Flags to modify writing the response
*/
/**
* User-provided method to handle unary requests on a server
* @callback grpc.Server~handleUnaryCall
* @param {grpc~ServerUnaryCall} call The call object
* @param {grpc.Server~sendUnaryData} callback The callback to call to respond
* to the request
*/
/** /**
* Fully handle a unary call * Fully handle a unary call
* @access private * @private
* @param {grpc.Call} call The call to handle * @param {grpc.internal~Call} call The call to handle
* @param {Object} handler Request handler object for the method that was called * @param {Object} handler Request handler object for the method that was called
* @param {Metadata} metadata Metadata from the client * @param {grpc~Server.handleUnaryCall} handler.func The handler function
* @param {grpc~deserialize} handler.deserialize The deserialization function
* for request data
* @param {grpc~serialize} handler.serialize The serialization function for
* response data
* @param {grpc.Metadata} metadata Metadata from the client
*/ */
function handleUnary(call, handler, metadata) { function handleUnary(call, handler, metadata) {
var emitter = new ServerUnaryCall(call); var emitter = new ServerUnaryCall(call, metadata);
emitter.on('error', function(error) { emitter.on('error', function(error) {
handleError(call, error); handleError(call, error);
}); });
emitter.metadata = metadata;
emitter.waitForCancel(); emitter.waitForCancel();
var batch = {}; var batch = {};
batch[grpc.opType.RECV_MESSAGE] = true; batch[grpc.opType.RECV_MESSAGE] = true;
@ -511,17 +617,28 @@ function handleUnary(call, handler, metadata) {
}); });
} }
/**
* User provided method to handle server streaming methods on the server.
* @callback grpc.Server~handleServerStreamingCall
* @param {grpc~ServerWritableStream} call The call object
*/
/** /**
* Fully handle a server streaming call * Fully handle a server streaming call
* @access private * @private
* @param {grpc.Call} call The call to handle * @param {grpc.internal~Call} call The call to handle
* @param {Object} handler Request handler object for the method that was called * @param {Object} handler Request handler object for the method that was called
* @param {Metadata} metadata Metadata from the client * @param {grpc~Server.handleServerStreamingCall} handler.func The handler
* function
* @param {grpc~deserialize} handler.deserialize The deserialization function
* for request data
* @param {grpc~serialize} handler.serialize The serialization function for
* response data
* @param {grpc.Metadata} metadata Metadata from the client
*/ */
function handleServerStreaming(call, handler, metadata) { function handleServerStreaming(call, handler, metadata) {
var stream = new ServerWritableStream(call, handler.serialize); var stream = new ServerWritableStream(call, metadata, handler.serialize);
stream.waitForCancel(); stream.waitForCancel();
stream.metadata = metadata;
var batch = {}; var batch = {};
batch[grpc.opType.RECV_MESSAGE] = true; batch[grpc.opType.RECV_MESSAGE] = true;
call.startBatch(batch, function(err, result) { call.startBatch(batch, function(err, result) {
@ -540,20 +657,33 @@ function handleServerStreaming(call, handler, metadata) {
}); });
} }
/**
* User provided method to handle client streaming methods on the server.
* @callback grpc.Server~handleClientStreamingCall
* @param {grpc~ServerReadableStream} call The call object
* @param {grpc.Server~sendUnaryData} callback The callback to call to respond
* to the request
*/
/** /**
* Fully handle a client streaming call * Fully handle a client streaming call
* @access private * @access private
* @param {grpc.Call} call The call to handle * @param {grpc.internal~Call} call The call to handle
* @param {Object} handler Request handler object for the method that was called * @param {Object} handler Request handler object for the method that was called
* @param {Metadata} metadata Metadata from the client * @param {grpc~Server.handleClientStreamingCall} handler.func The handler
* function
* @param {grpc~deserialize} handler.deserialize The deserialization function
* for request data
* @param {grpc~serialize} handler.serialize The serialization function for
* response data
* @param {grpc.Metadata} metadata Metadata from the client
*/ */
function handleClientStreaming(call, handler, metadata) { function handleClientStreaming(call, handler, metadata) {
var stream = new ServerReadableStream(call, handler.deserialize); var stream = new ServerReadableStream(call, metadata, handler.deserialize);
stream.on('error', function(error) { stream.on('error', function(error) {
handleError(call, error); handleError(call, error);
}); });
stream.waitForCancel(); stream.waitForCancel();
stream.metadata = metadata;
handler.func(stream, function(err, value, trailer, flags) { handler.func(stream, function(err, value, trailer, flags) {
stream.terminate(); stream.terminate();
if (err) { if (err) {
@ -567,18 +697,29 @@ function handleClientStreaming(call, handler, metadata) {
}); });
} }
/**
* User provided method to handle bidirectional streaming calls on the server.
* @callback grpc.Server~handleBidiStreamingCall
* @param {grpc~ServerDuplexStream} call The call object
*/
/** /**
* Fully handle a bidirectional streaming call * Fully handle a bidirectional streaming call
* @access private * @private
* @param {grpc.Call} call The call to handle * @param {grpc.internal~Call} call The call to handle
* @param {Object} handler Request handler object for the method that was called * @param {Object} handler Request handler object for the method that was called
* @param {grpc~Server.handleBidiStreamingCall} handler.func The handler
* function
* @param {grpc~deserialize} handler.deserialize The deserialization function
* for request data
* @param {grpc~serialize} handler.serialize The serialization function for
* response data
* @param {Metadata} metadata Metadata from the client * @param {Metadata} metadata Metadata from the client
*/ */
function handleBidiStreaming(call, handler, metadata) { function handleBidiStreaming(call, handler, metadata) {
var stream = new ServerDuplexStream(call, handler.serialize, var stream = new ServerDuplexStream(call, metadata, handler.serialize,
handler.deserialize); handler.deserialize);
stream.waitForCancel(); stream.waitForCancel();
stream.metadata = metadata;
handler.func(stream); handler.func(stream);
} }
@ -592,96 +733,90 @@ var streamHandlers = {
/** /**
* Constructs a server object that stores request handlers and delegates * Constructs a server object that stores request handlers and delegates
* incoming requests to those handlers * incoming requests to those handlers
* @memberof grpc
* @constructor * @constructor
* @param {Object=} options Options that should be passed to the internal server * @param {Object=} options Options that should be passed to the internal server
* implementation * implementation
* @example
* var server = new grpc.Server();
* server.addProtoService(protobuf_service_descriptor, service_implementation);
* server.bind('address:port', server_credential);
* server.start();
*/ */
function Server(options) { function Server(options) {
this.handlers = {}; this.handlers = {};
var handlers = this.handlers;
var server = new grpc.Server(options); var server = new grpc.Server(options);
this._server = server; this._server = server;
this.started = false; this.started = false;
}
/**
* Start the server and begin handling requests
*/
Server.prototype.start = function() {
if (this.started) {
throw new Error('Server is already running');
}
var self = this;
this.started = true;
this._server.start();
/** /**
* Start the server and begin handling requests * Handles the SERVER_RPC_NEW event. If there is a handler associated with
* @this Server * the requested method, use that handler to respond to the request. Then
* wait for the next request
* @param {grpc.internal~Event} event The event to handle with tag
* SERVER_RPC_NEW
*/ */
this.start = function() { function handleNewCall(err, event) {
if (this.started) { if (err) {
throw new Error('Server is already running'); return;
} }
this.started = true; var details = event.new_call;
server.start(); var call = details.call;
/** var method = details.method;
* Handles the SERVER_RPC_NEW event. If there is a handler associated with var metadata = Metadata._fromCoreRepresentation(details.metadata);
* the requested method, use that handler to respond to the request. Then if (method === null) {
* wait for the next request return;
* @param {grpc.Event} event The event to handle with tag SERVER_RPC_NEW
*/
function handleNewCall(err, event) {
if (err) {
return;
}
var details = event.new_call;
var call = details.call;
var method = details.method;
var metadata = Metadata._fromCoreRepresentation(details.metadata);
if (method === null) {
return;
}
server.requestCall(handleNewCall);
var handler;
if (handlers.hasOwnProperty(method)) {
handler = handlers[method];
} else {
var batch = {};
batch[grpc.opType.SEND_INITIAL_METADATA] =
(new Metadata())._getCoreRepresentation();
batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
code: constants.status.UNIMPLEMENTED,
details: '',
metadata: {}
};
batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true;
call.startBatch(batch, function() {});
return;
}
streamHandlers[handler.type](call, handler, metadata);
} }
server.requestCall(handleNewCall); self._server.requestCall(handleNewCall);
}; var handler;
if (self.handlers.hasOwnProperty(method)) {
/** handler = self.handlers[method];
* Gracefully shuts down the server. The server will stop receiving new calls, } else {
* and any pending calls will complete. The callback will be called when all var batch = {};
* pending calls have completed and the server is fully shut down. This method batch[grpc.opType.SEND_INITIAL_METADATA] =
* is idempotent with itself and forceShutdown. (new Metadata())._getCoreRepresentation();
* @param {function()} callback The shutdown complete callback batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
*/ code: constants.status.UNIMPLEMENTED,
this.tryShutdown = function(callback) { details: '',
server.tryShutdown(callback); metadata: {}
}; };
batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true;
call.startBatch(batch, function() {});
return;
}
streamHandlers[handler.type](call, handler, metadata);
}
this._server.requestCall(handleNewCall);
};
/** /**
* Forcibly shuts down the server. The server will stop receiving new calls * Unified type for application handlers for all types of calls
* and cancel all pending calls. When it returns, the server has shut down. * @typedef {(grpc.Server~handleUnaryCall
* This method is idempotent with itself and tryShutdown, and it will trigger * |grpc.Server~handleClientStreamingCall
* any outstanding tryShutdown callbacks. * |grpc.Server~handleServerStreamingCall
*/ * |grpc.Server~handleBidiStreamingCall)} grpc.Server~handleCall
this.forceShutdown = function() { */
server.forceShutdown();
};
}
/** /**
* Registers a handler to handle the named method. Fails if there already is * Registers a handler to handle the named method. Fails if there already is
* a handler for the given method. Returns true on success * a handler for the given method. Returns true on success
* @param {string} name The name of the method that the provided function should * @param {string} name The name of the method that the provided function should
* handle/respond to. * handle/respond to.
* @param {function} handler Function that takes a stream of request values and * @param {grpc.Server~handleCall} handler Function that takes a stream of
* returns a stream of response values * request values and returns a stream of response values
* @param {function(*):Buffer} serialize Serialization function for responses * @param {grpc~serialize} serialize Serialization function for responses
* @param {function(Buffer):*} deserialize Deserialization function for requests * @param {grpc~deserialize} deserialize Deserialization function for requests
* @param {string} type The streaming type of method that this handles * @param {string} type The streaming type of method that this handles
* @return {boolean} True if the handler was set. False if a handler was already * @return {boolean} True if the handler was set. False if a handler was already
* set for that name. * set for that name.
@ -700,6 +835,27 @@ Server.prototype.register = function(name, handler, serialize, deserialize,
return true; return true;
}; };
/**
* Gracefully shuts down the server. The server will stop receiving new calls,
* and any pending calls will complete. The callback will be called when all
* pending calls have completed and the server is fully shut down. This method
* is idempotent with itself and forceShutdown.
* @param {function()} callback The shutdown complete callback
*/
Server.prototype.tryShutdown = function(callback) {
this._server.tryShutdown(callback);
};
/**
* Forcibly shuts down the server. The server will stop receiving new calls
* and cancel all pending calls. When it returns, the server has shut down.
* This method is idempotent with itself and tryShutdown, and it will trigger
* any outstanding tryShutdown callbacks.
*/
Server.prototype.forceShutdown = function() {
this._server.forceShutdown();
};
var unimplementedStatusResponse = { var unimplementedStatusResponse = {
code: constants.status.UNIMPLEMENTED, code: constants.status.UNIMPLEMENTED,
details: 'The server does not implement this method' details: 'The server does not implement this method'
@ -721,13 +877,10 @@ var defaultHandler = {
}; };
/** /**
* Add a service to the server, with a corresponding implementation. If you are * Add a service to the server, with a corresponding implementation.
* generating this from a proto file, you should instead use * @param {grpc~ServiceDefinition} service The service descriptor
* addProtoService. * @param {Object<String, grpc.Server~handleCall>} implementation Map of method
* @param {Object<String, *>} service The service descriptor, as * names to method implementation for the provided service.
* {@link module:src/common.getProtobufServiceAttrs} returns
* @param {Object<String, function>} implementation Map of method names to
* method implementation for the provided service.
*/ */
Server.prototype.addService = function(service, implementation) { Server.prototype.addService = function(service, implementation) {
if (!_.isObject(service) || !_.isObject(implementation)) { if (!_.isObject(service) || !_.isObject(implementation)) {
@ -788,10 +941,10 @@ var logAddProtoServiceDeprecationOnce = _.once(function() {
/** /**
* Add a proto service to the server, with a corresponding implementation * Add a proto service to the server, with a corresponding implementation
* @deprecated Use grpc.load and Server#addService instead * @deprecated Use {@link grpc.Server#addService} instead
* @param {Protobuf.Reflect.Service} service The proto service descriptor * @param {Protobuf.Reflect.Service} service The proto service descriptor
* @param {Object<String, function>} implementation Map of method names to * @param {Object<String, grpc.Server~handleCall>} implementation Map of method
* method implementation for the provided service. * names to method implementation for the provided service.
*/ */
Server.prototype.addProtoService = function(service, implementation) { Server.prototype.addProtoService = function(service, implementation) {
var options; var options;
@ -815,10 +968,11 @@ Server.prototype.addProtoService = function(service, implementation) {
}; };
/** /**
* Binds the server to the given port, with SSL enabled if creds is given * Binds the server to the given port, with SSL disabled if creds is an
* insecure credentials object
* @param {string} port The port that the server should bind on, in the format * @param {string} port The port that the server should bind on, in the format
* "address:port" * "address:port"
* @param {ServerCredentials=} creds Server credential object to be used for * @param {grpc.ServerCredentials} creds Server credential object to be used for
* SSL. Pass an insecure credentials object for an insecure port. * SSL. Pass an insecure credentials object for an insecure port.
*/ */
Server.prototype.bind = function(port, creds) { Server.prototype.bind = function(port, creds) {
@ -828,7 +982,4 @@ Server.prototype.bind = function(port, creds) {
return this._server.addHttp2Port(port, creds); return this._server.addHttp2Port(port, creds);
}; };
/**
* @see module:src/server~Server
*/
exports.Server = Server; exports.Server = Server;

@ -1322,14 +1322,14 @@ describe('Cancelling surface client', function() {
}); });
it('Should correctly cancel a unary call', function(done) { it('Should correctly cancel a unary call', function(done) {
var call = client.div({'divisor': 0, 'dividend': 0}, function(err, resp) { var call = client.div({'divisor': 0, 'dividend': 0}, function(err, resp) {
assert.strictEqual(err.code, surface_client.status.CANCELLED); assert.strictEqual(err.code, grpc.status.CANCELLED);
done(); done();
}); });
call.cancel(); call.cancel();
}); });
it('Should correctly cancel a client stream call', function(done) { it('Should correctly cancel a client stream call', function(done) {
var call = client.sum(function(err, resp) { var call = client.sum(function(err, resp) {
assert.strictEqual(err.code, surface_client.status.CANCELLED); assert.strictEqual(err.code, grpc.status.CANCELLED);
done(); done();
}); });
call.cancel(); call.cancel();
@ -1338,7 +1338,7 @@ describe('Cancelling surface client', function() {
var call = client.fib({'limit': 5}); var call = client.fib({'limit': 5});
call.on('data', function() {}); call.on('data', function() {});
call.on('error', function(error) { call.on('error', function(error) {
assert.strictEqual(error.code, surface_client.status.CANCELLED); assert.strictEqual(error.code, grpc.status.CANCELLED);
done(); done();
}); });
call.cancel(); call.cancel();
@ -1347,7 +1347,7 @@ describe('Cancelling surface client', function() {
var call = client.divMany(); var call = client.divMany();
call.on('data', function() {}); call.on('data', function() {});
call.on('error', function(error) { call.on('error', function(error) {
assert.strictEqual(error.code, surface_client.status.CANCELLED); assert.strictEqual(error.code, grpc.status.CANCELLED);
done(); done();
}); });
call.cancel(); call.cancel();

@ -313,6 +313,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/census/grpc_filter.c', 'src/core/ext/census/grpc_filter.c',
'src/core/ext/census/grpc_plugin.c', 'src/core/ext/census/grpc_plugin.c',
'src/core/ext/census/initialize.c', 'src/core/ext/census/initialize.c',
'src/core/ext/census/intrusive_hash_map.c',
'src/core/ext/census/mlog.c', 'src/core/ext/census/mlog.c',
'src/core/ext/census/operation.c', 'src/core/ext/census/operation.c',
'src/core/ext/census/placeholders.c', 'src/core/ext/census/placeholders.c',

@ -0,0 +1,282 @@
/*
* Copyright 2017 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "src/core/ext/census/intrusive_hash_map.h"
#include <grpc/support/log.h>
#include <grpc/support/useful.h>
#include "test/core/util/test_config.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* The initial size of an intrusive hash map will be 2 to this power. */
static const uint32_t kInitialLog2Size = 4;
/* Simple object used for testing intrusive_hash_map. */
typedef struct object { uint64_t val; } object;
/* Helper function to allocate and initialize object. */
static inline object *make_new_object(uint64_t val) {
object *obj = (object *)gpr_malloc(sizeof(object));
obj->val = val;
return obj;
}
/* Wrapper struct for object. */
typedef struct ptr_item {
INTRUSIVE_HASH_MAP_HEADER;
object *obj;
} ptr_item;
/* Helper function that creates a new hash map item. It is up to the user to
* free the item that was allocated. */
static inline ptr_item *make_ptr_item(uint64_t key, uint64_t value) {
ptr_item *new_item = (ptr_item *)gpr_malloc(sizeof(ptr_item));
new_item->IHM_key = key;
new_item->IHM_hash_link = NULL;
new_item->obj = make_new_object(value);
return new_item;
}
/* Helper function to deallocate ptr_item. */
static void free_ptr_item(void *ptr) { gpr_free(((ptr_item *)ptr)->obj); }
/* Simple string object used for testing intrusive_hash_map. */
typedef struct string_item {
INTRUSIVE_HASH_MAP_HEADER;
// User data.
char buf[32];
uint16_t len;
} string_item;
/* Helper function to allocate and initialize string object. */
static string_item *make_string_item(uint64_t key, const char *buf,
uint16_t len) {
string_item *item = (string_item *)gpr_malloc(sizeof(string_item));
item->IHM_key = key;
item->IHM_hash_link = NULL;
item->len = len;
memcpy(item->buf, buf, sizeof(char) * len);
return item;
}
/* Helper function for comparing two string objects. */
static bool compare_string_item(const string_item *A, const string_item *B) {
if (A->IHM_key != B->IHM_key || A->len != B->len)
return false;
else {
for (int i = 0; i < A->len; ++i) {
if (A->buf[i] != B->buf[i]) return false;
}
}
return true;
}
void test_empty() {
intrusive_hash_map hash_map;
intrusive_hash_map_init(&hash_map, kInitialLog2Size);
GPR_ASSERT(0 == intrusive_hash_map_size(&hash_map));
GPR_ASSERT(intrusive_hash_map_empty(&hash_map));
intrusive_hash_map_free(&hash_map, NULL);
}
void test_single_item() {
intrusive_hash_map hash_map;
intrusive_hash_map_init(&hash_map, kInitialLog2Size);
ptr_item *new_item = make_ptr_item(10, 20);
bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)new_item);
GPR_ASSERT(ok);
ptr_item *item1 =
(ptr_item *)intrusive_hash_map_find(&hash_map, (uint64_t)10);
GPR_ASSERT(item1->obj->val == 20);
GPR_ASSERT(item1 == new_item);
ptr_item *item2 =
(ptr_item *)intrusive_hash_map_erase(&hash_map, (uint64_t)10);
GPR_ASSERT(item2 == new_item);
gpr_free(new_item->obj);
gpr_free(new_item);
GPR_ASSERT(0 == intrusive_hash_map_size(&hash_map));
intrusive_hash_map_free(&hash_map, &free_ptr_item);
}
void test_two_items() {
intrusive_hash_map hash_map;
intrusive_hash_map_init(&hash_map, kInitialLog2Size);
string_item *new_item1 = make_string_item(10, "test1", 5);
bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)new_item1);
GPR_ASSERT(ok);
string_item *new_item2 = make_string_item(20, "test2", 5);
ok = intrusive_hash_map_insert(&hash_map, (hm_item *)new_item2);
GPR_ASSERT(ok);
string_item *item1 =
(string_item *)intrusive_hash_map_find(&hash_map, (uint64_t)10);
GPR_ASSERT(compare_string_item(new_item1, item1));
GPR_ASSERT(item1 == new_item1);
string_item *item2 =
(string_item *)intrusive_hash_map_find(&hash_map, (uint64_t)20);
GPR_ASSERT(compare_string_item(new_item2, item2));
GPR_ASSERT(item2 == new_item2);
item1 = (string_item *)intrusive_hash_map_erase(&hash_map, (uint64_t)10);
GPR_ASSERT(item1 == new_item1);
item2 = (string_item *)intrusive_hash_map_erase(&hash_map, (uint64_t)20);
GPR_ASSERT(item2 == new_item2);
gpr_free(new_item1);
gpr_free(new_item2);
GPR_ASSERT(0 == intrusive_hash_map_size(&hash_map));
intrusive_hash_map_free(&hash_map, NULL);
}
// Test resetting and clearing the hash map.
void test_reset_clear() {
intrusive_hash_map hash_map;
intrusive_hash_map_init(&hash_map, kInitialLog2Size);
// Add some data to the hash_map.
for (uint64_t i = 0; i < 3; ++i) {
intrusive_hash_map_insert(&hash_map, (hm_item *)make_ptr_item(i, i));
}
GPR_ASSERT(3 == intrusive_hash_map_size(&hash_map));
// Test find.
for (uint64_t i = 0; i < 3; ++i) {
ptr_item *item = (ptr_item *)intrusive_hash_map_find(&hash_map, i);
GPR_ASSERT(item != NULL);
GPR_ASSERT(item->IHM_key == i && item->obj->val == i);
}
intrusive_hash_map_clear(&hash_map, &free_ptr_item);
GPR_ASSERT(intrusive_hash_map_empty(&hash_map));
intrusive_hash_map_free(&hash_map, &free_ptr_item);
}
// Check that the hash_map contains every key between [min_value, max_value]
// (inclusive).
void check_hash_map_values(intrusive_hash_map *hash_map, uint64_t min_value,
uint64_t max_value) {
GPR_ASSERT(intrusive_hash_map_size(hash_map) == max_value - min_value + 1);
for (uint64_t i = min_value; i <= max_value; ++i) {
ptr_item *item = (ptr_item *)intrusive_hash_map_find(hash_map, i);
GPR_ASSERT(item != NULL);
GPR_ASSERT(item->obj->val == i);
}
}
// Add many items and cause the hash_map to extend.
void test_extend() {
intrusive_hash_map hash_map;
intrusive_hash_map_init(&hash_map, kInitialLog2Size);
const uint64_t kNumValues = (1 << 16);
for (uint64_t i = 0; i < kNumValues; ++i) {
ptr_item *item = make_ptr_item(i, i);
bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)item);
GPR_ASSERT(ok);
if (i % 1000 == 0) {
check_hash_map_values(&hash_map, 0, i);
}
}
for (uint64_t i = 0; i < kNumValues; ++i) {
ptr_item *item = (ptr_item *)intrusive_hash_map_find(&hash_map, i);
GPR_ASSERT(item != NULL);
GPR_ASSERT(item->IHM_key == i && item->obj->val == i);
ptr_item *item2 = (ptr_item *)intrusive_hash_map_erase(&hash_map, i);
GPR_ASSERT(item == item2);
gpr_free(item->obj);
gpr_free(item);
}
GPR_ASSERT(intrusive_hash_map_empty(&hash_map));
intrusive_hash_map_free(&hash_map, &free_ptr_item);
}
void test_stress() {
intrusive_hash_map hash_map;
intrusive_hash_map_init(&hash_map, kInitialLog2Size);
size_t n = 0;
// Randomly add and insert entries 1000000 times.
for (uint64_t i = 0; i < 1000000; ++i) {
int op = rand() & 0x1;
switch (op) {
// Case 0 is insertion of entry.
case 0: {
uint64_t key = (uint64_t)(rand() % 10000);
ptr_item *item = make_ptr_item(key, key);
bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)item);
if (ok) {
n++;
} else {
gpr_free(item->obj);
gpr_free(item);
}
break;
}
// Case 1 is removal of entry.
case 1: {
uint64_t key = (uint64_t)(rand() % 10000);
ptr_item *item = (ptr_item *)intrusive_hash_map_find(&hash_map, key);
if (item != NULL) {
n--;
GPR_ASSERT(key == item->obj->val);
ptr_item *item2 =
(ptr_item *)intrusive_hash_map_erase(&hash_map, key);
GPR_ASSERT(item == item2);
gpr_free(item->obj);
gpr_free(item);
}
break;
}
}
}
// Check size
GPR_ASSERT(n == intrusive_hash_map_size(&hash_map));
// Clean the hash_map up.
intrusive_hash_map_clear(&hash_map, &free_ptr_item);
GPR_ASSERT(intrusive_hash_map_empty(&hash_map));
intrusive_hash_map_free(&hash_map, &free_ptr_item);
}
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
gpr_time_init();
srand((unsigned)gpr_now(GPR_CLOCK_REALTIME).tv_nsec);
test_empty();
test_single_item();
test_two_items();
test_reset_clear();
test_extend();
test_stress();
return 0;
}

@ -883,6 +883,9 @@ src/core/ext/census/grpc_filter.c \
src/core/ext/census/grpc_filter.h \ src/core/ext/census/grpc_filter.h \
src/core/ext/census/grpc_plugin.c \ src/core/ext/census/grpc_plugin.c \
src/core/ext/census/initialize.c \ src/core/ext/census/initialize.c \
src/core/ext/census/intrusive_hash_map.c \
src/core/ext/census/intrusive_hash_map.h \
src/core/ext/census/intrusive_hash_map_internal.h \
src/core/ext/census/mlog.c \ src/core/ext/census/mlog.c \
src/core/ext/census/mlog.h \ src/core/ext/census/mlog.h \
src/core/ext/census/operation.c \ src/core/ext/census/operation.c \

@ -181,6 +181,23 @@
"third_party": false, "third_party": false,
"type": "target" "type": "target"
}, },
{
"deps": [
"gpr",
"gpr_test_util",
"grpc",
"grpc_test_util"
],
"headers": [],
"is_filegroup": false,
"language": "c",
"name": "census_intrusive_hash_map_test",
"src": [
"test/core/census/intrusive_hash_map_test.c"
],
"third_party": false,
"type": "target"
},
{ {
"deps": [ "deps": [
"gpr", "gpr",
@ -7541,6 +7558,8 @@
"src/core/ext/census/gen/census.pb.h", "src/core/ext/census/gen/census.pb.h",
"src/core/ext/census/gen/trace_context.pb.h", "src/core/ext/census/gen/trace_context.pb.h",
"src/core/ext/census/grpc_filter.h", "src/core/ext/census/grpc_filter.h",
"src/core/ext/census/intrusive_hash_map.h",
"src/core/ext/census/intrusive_hash_map_internal.h",
"src/core/ext/census/mlog.h", "src/core/ext/census/mlog.h",
"src/core/ext/census/resource.h", "src/core/ext/census/resource.h",
"src/core/ext/census/rpc_metric_id.h", "src/core/ext/census/rpc_metric_id.h",
@ -7571,6 +7590,9 @@
"src/core/ext/census/grpc_filter.h", "src/core/ext/census/grpc_filter.h",
"src/core/ext/census/grpc_plugin.c", "src/core/ext/census/grpc_plugin.c",
"src/core/ext/census/initialize.c", "src/core/ext/census/initialize.c",
"src/core/ext/census/intrusive_hash_map.c",
"src/core/ext/census/intrusive_hash_map.h",
"src/core/ext/census/intrusive_hash_map_internal.h",
"src/core/ext/census/mlog.c", "src/core/ext/census/mlog.c",
"src/core/ext/census/mlog.h", "src/core/ext/census/mlog.h",
"src/core/ext/census/operation.c", "src/core/ext/census/operation.c",

@ -223,6 +223,28 @@
"windows" "windows"
] ]
}, },
{
"args": [],
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": false,
"language": "c",
"name": "census_intrusive_hash_map_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
]
},
{ {
"args": [], "args": [],
"ci_platforms": [ "ci_platforms": [

@ -129,6 +129,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "census_context_test", "vcxp
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
EndProjectSection EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "census_intrusive_hash_map_test", "vcxproj\test\census_intrusive_hash_map_test\census_intrusive_hash_map_test.vcxproj", "{BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}"
ProjectSection(myProperties) = preProject
lib = "False"
EndProjectSection
ProjectSection(ProjectDependencies) = postProject
{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "census_resource_test", "vcxproj\test\census_resource_test\census_resource_test.vcxproj", "{18CF99B5-3C61-EC3D-9509-3C95334C3B88}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "census_resource_test", "vcxproj\test\census_resource_test\census_resource_test.vcxproj", "{18CF99B5-3C61-EC3D-9509-3C95334C3B88}"
ProjectSection(myProperties) = preProject ProjectSection(myProperties) = preProject
lib = "False" lib = "False"
@ -1899,6 +1910,22 @@ Global
{5C1CFC2D-AF3C-D7CB-BA74-D267E91CBC73}.Release-DLL|Win32.Build.0 = Release|Win32 {5C1CFC2D-AF3C-D7CB-BA74-D267E91CBC73}.Release-DLL|Win32.Build.0 = Release|Win32
{5C1CFC2D-AF3C-D7CB-BA74-D267E91CBC73}.Release-DLL|x64.ActiveCfg = Release|x64 {5C1CFC2D-AF3C-D7CB-BA74-D267E91CBC73}.Release-DLL|x64.ActiveCfg = Release|x64
{5C1CFC2D-AF3C-D7CB-BA74-D267E91CBC73}.Release-DLL|x64.Build.0 = Release|x64 {5C1CFC2D-AF3C-D7CB-BA74-D267E91CBC73}.Release-DLL|x64.Build.0 = Release|x64
{BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Debug|Win32.ActiveCfg = Debug|Win32
{BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Debug|x64.ActiveCfg = Debug|x64
{BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Release|Win32.ActiveCfg = Release|Win32
{BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Release|x64.ActiveCfg = Release|x64
{BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Debug|Win32.Build.0 = Debug|Win32
{BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Debug|x64.Build.0 = Debug|x64
{BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Release|Win32.Build.0 = Release|Win32
{BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Release|x64.Build.0 = Release|x64
{BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
{BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Debug-DLL|Win32.Build.0 = Debug|Win32
{BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Debug-DLL|x64.ActiveCfg = Debug|x64
{BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Debug-DLL|x64.Build.0 = Debug|x64
{BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Release-DLL|Win32.ActiveCfg = Release|Win32
{BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Release-DLL|Win32.Build.0 = Release|Win32
{BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Release-DLL|x64.ActiveCfg = Release|x64
{BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Release-DLL|x64.Build.0 = Release|x64
{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Debug|Win32.ActiveCfg = Debug|Win32 {18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Debug|Win32.ActiveCfg = Debug|Win32
{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Debug|x64.ActiveCfg = Debug|x64 {18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Debug|x64.ActiveCfg = Debug|x64
{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Release|Win32.ActiveCfg = Release|Win32 {18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Release|Win32.ActiveCfg = Release|Win32

@ -504,6 +504,8 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\gen\census.pb.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\gen\census.pb.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\gen\trace_context.pb.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\gen\trace_context.pb.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\grpc_filter.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\grpc_filter.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map_internal.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\resource.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\resource.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\rpc_metric_id.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\rpc_metric_id.h" />
@ -993,6 +995,8 @@
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\initialize.c"> <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\initialize.c">
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\mlog.c"> <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\mlog.c">
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\operation.c"> <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\operation.c">

@ -712,6 +712,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\initialize.c"> <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\initialize.c">
<Filter>src\core\ext\census</Filter> <Filter>src\core\ext\census</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map.c">
<Filter>src\core\ext\census</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\mlog.c"> <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\mlog.c">
<Filter>src\core\ext\census</Filter> <Filter>src\core\ext\census</Filter>
</ClCompile> </ClCompile>
@ -1454,6 +1457,12 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\grpc_filter.h"> <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\grpc_filter.h">
<Filter>src\core\ext\census</Filter> <Filter>src\core\ext\census</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map.h">
<Filter>src\core\ext\census</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map_internal.h">
<Filter>src\core\ext\census</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h"> <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h">
<Filter>src\core\ext\census</Filter> <Filter>src\core\ext\census</Filter>
</ClInclude> </ClInclude>

@ -469,6 +469,8 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\gen\census.pb.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\gen\census.pb.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\gen\trace_context.pb.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\gen\trace_context.pb.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\grpc_filter.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\grpc_filter.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map_internal.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\resource.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\resource.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\rpc_metric_id.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\rpc_metric_id.h" />
@ -900,6 +902,8 @@
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\initialize.c"> <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\initialize.c">
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\mlog.c"> <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\mlog.c">
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\operation.c"> <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\operation.c">

@ -625,6 +625,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\initialize.c"> <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\initialize.c">
<Filter>src\core\ext\census</Filter> <Filter>src\core\ext\census</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map.c">
<Filter>src\core\ext\census</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\mlog.c"> <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\mlog.c">
<Filter>src\core\ext\census</Filter> <Filter>src\core\ext\census</Filter>
</ClCompile> </ClCompile>
@ -1289,6 +1292,12 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\grpc_filter.h"> <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\grpc_filter.h">
<Filter>src\core\ext\census</Filter> <Filter>src\core\ext\census</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map.h">
<Filter>src\core\ext\census</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map_internal.h">
<Filter>src\core\ext\census</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h"> <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h">
<Filter>src\core\ext\census</Filter> <Filter>src\core\ext\census</Filter>
</ClInclude> </ClInclude>

@ -0,0 +1,199 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}</ProjectGuid>
<IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
<IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
<PlatformToolset>v100</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(SolutionDir)\..\vsprojects\global.props" />
<Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
<Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
<Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<TargetName>census_intrusive_hash_map_test</TargetName>
<Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
<Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
<Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
<Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<TargetName>census_intrusive_hash_map_test</TargetName>
<Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
<Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
<Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
<Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="$(SolutionDir)\..\test\core\census\intrusive_hash_map_test.c">
</ClCompile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
<Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
<Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
<Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
<Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
</Target>
</Project>

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="$(SolutionDir)\..\test\core\census\intrusive_hash_map_test.c">
<Filter>test\core\census</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="test">
<UniqueIdentifier>{24bfacc6-bd89-4cdf-4183-3ff53180fa48}</UniqueIdentifier>
</Filter>
<Filter Include="test\core">
<UniqueIdentifier>{71b1debf-71c7-c1e9-9e01-21330ede0d7f}</UniqueIdentifier>
</Filter>
<Filter Include="test\core\census">
<UniqueIdentifier>{0228063a-a601-967e-27ed-9f6197cb3629}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
Loading…
Cancel
Save